1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_fpicker.hxx"
26 
27 #include "OfficeFilePicker.hxx"
28 #include "iodlg.hxx"
29 
30 #ifndef _LIST_
31 #include <list>
32 #endif
33 #ifndef _FUNCTIONAL_
34 #include <functional>
35 #endif
36 #ifndef _ALGORITHM_
37 #include <algorithm>
38 #endif
39 #include <tools/urlobj.hxx>
40 #include <tools/debug.hxx>
41 #define _SVSTDARR_STRINGSDTOR
42 #include "svl/svstdarr.hxx"
43 #include <com/sun/star/uno/Any.hxx>
44 #include <com/sun/star/ui/dialogs/FilePickerEvent.hpp>
45 #include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
46 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
47 #include <com/sun/star/beans/PropertyValue.hpp>
48 #include <com/sun/star/beans/XPropertySet.hpp>
49 #include <com/sun/star/awt/XWindow.hpp>
50 #include <com/sun/star/beans/StringPair.hpp>
51 #include <com/sun/star/uno/Sequence.hxx>
52 #include <com/sun/star/beans/NamedValue.hpp>
53 #include <unotools/ucbhelper.hxx>
54 #include <unotools/pathoptions.hxx>
55 #include <comphelper/sequence.hxx>
56 #include <cppuhelper/typeprovider.hxx>
57 #include "vos/mutex.hxx"
58 #ifndef _SV_APP_HXX
59 #include "vcl/svapp.hxx"
60 #endif
61 
62 // define ----------------------------------------------------------------
63 
64 #define MAKE_ANY    ::com::sun::star::uno::makeAny
65 
66 // using ----------------------------------------------------------------
67 
68 using namespace     ::com::sun::star::container;
69 using namespace     ::com::sun::star::lang;
70 using namespace     ::com::sun::star::ui::dialogs;
71 using namespace     ::com::sun::star::uno;
72 using namespace     ::com::sun::star::beans;
73 using namespace     ::com::sun::star::awt;
74 using namespace     ::utl;
75 
76 //=====================================================================
77 
78 //=====================================================================
79 
80 struct FilterEntry
81 {
82 protected:
83 	::rtl::OUString		m_sTitle;
84 	::rtl::OUString		m_sFilter;
85 
86 	UnoFilterList		m_aSubFilters;
87 
88 public:
89 	FilterEntry( const ::rtl::OUString& _rTitle, const ::rtl::OUString& _rFilter )
90 		:m_sTitle( _rTitle )
91 		,m_sFilter( _rFilter )
92 	{
93 	}
94 
95 	FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters );
96 
97 	::rtl::OUString		getTitle() const { return m_sTitle; }
98 	::rtl::OUString		getFilter() const { return m_sFilter; }
99 
100 	/// determines if the filter has sub filter (i.e., the filter is a filter group in real)
101 	sal_Bool			hasSubFilters( ) const;
102 
103 	/** retrieves the filters belonging to the entry
104 	@return
105 		the number of sub filters
106 	*/
107 	sal_Int32			getSubFilters( UnoFilterList& _rSubFilterList );
108 
109 	// helpers for iterating the sub filters
110 	const UnoFilterEntry*	beginSubFilters() const { return m_aSubFilters.getConstArray(); }
111 	const UnoFilterEntry*	endSubFilters() const { return m_aSubFilters.getConstArray() + m_aSubFilters.getLength(); }
112 };
113 
114 //=====================================================================
115 
116 //---------------------------------------------------------------------
117 FilterEntry::FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters )
118 	:m_sTitle( _rTitle )
119 	,m_aSubFilters( _rSubFilters )
120 {
121 }
122 
123 //---------------------------------------------------------------------
124 sal_Bool FilterEntry::hasSubFilters( ) const
125 {
126 	return ( 0 < m_aSubFilters.getLength() );
127 }
128 
129 //---------------------------------------------------------------------
130 sal_Int32 FilterEntry::getSubFilters( UnoFilterList& _rSubFilterList )
131 {
132 	_rSubFilterList = m_aSubFilters;
133 	return m_aSubFilters.getLength();
134 }
135 
136 // struct ElementEntry_Impl ----------------------------------------------
137 
138 struct ElementEntry_Impl
139 {
140 	sal_Int16		m_nElementID;
141 	sal_Int16		m_nControlAction;
142 	Any			m_aValue;
143 	rtl::OUString		m_aLabel;
144     sal_Bool        m_bEnabled      : 1;
145 
146     sal_Bool        m_bHasValue     : 1;
147     sal_Bool        m_bHasLabel     : 1;
148     sal_Bool        m_bHasEnabled   : 1;
149 
150                     ElementEntry_Impl( sal_Int16 nId );
151 
152     void            setValue( const Any& rVal ) { m_aValue = rVal; m_bHasValue = sal_True; }
153     void            setAction( sal_Int16 nAction ) { m_nControlAction = nAction; }
154     void            setLabel( const rtl::OUString& rVal ) { m_aLabel = rVal; m_bHasLabel = sal_True; }
155     void            setEnabled( sal_Bool bEnabled ) { m_bEnabled = bEnabled; m_bHasEnabled = sal_True; }
156 };
157 
158 ElementEntry_Impl::ElementEntry_Impl( sal_Int16 nId )
159     : m_nElementID( nId )
160     , m_nControlAction( 0 )
161     , m_bEnabled( sal_False )
162     , m_bHasValue( sal_False )
163     , m_bHasLabel( sal_False )
164     , m_bHasEnabled( sal_False )
165 {}
166 
167 //------------------------------------------------------------------------------------
168 void SvtFilePicker::prepareExecute()
169 {
170 	// set the default directory
171 	// --**-- doesn't match the spec yet
172 	if ( m_aDisplayDirectory.getLength() > 0 || m_aDefaultName.getLength() > 0 )
173 	{
174 		if ( m_aDisplayDirectory.getLength() > 0 )
175 		{
176 
177 			INetURLObject aPath( m_aDisplayDirectory );
178 			if ( m_aDefaultName.getLength() > 0 )
179 			{
180 				aPath.insertName( m_aDefaultName );
181 				getDialog()->SetHasFilename( true );
182 			}
183 			String sPath = aPath.GetMainURL( INetURLObject::NO_DECODE );
184 			getDialog()->SetPath( aPath.GetMainURL( INetURLObject::NO_DECODE ) );
185 		}
186 		else if ( m_aDefaultName.getLength() > 0 )
187 		{
188 			getDialog()->SetPath( m_aDefaultName );
189 			getDialog()->SetHasFilename( true );
190 		}
191 	}
192 	else
193 	{
194 		// Default-Standard-Dir setzen
195 		INetURLObject aStdDirObj( SvtPathOptions().GetWorkPath() );
196 		getDialog()->SetPath( aStdDirObj.GetMainURL( INetURLObject::NO_DECODE ) );
197 	}
198 
199 	// set the control values and set the control labels, too
200     if ( m_pElemList && !m_pElemList->empty() )
201     {
202 		::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() );
203 
204         ElementList::iterator aListIter;
205 		for ( aListIter = m_pElemList->begin();
206 			  aListIter != m_pElemList->end(); ++aListIter )
207 		{
208 			ElementEntry_Impl& rEntry = *aListIter;
209             if ( rEntry.m_bHasValue )
210 				aAccess.setValue( rEntry.m_nElementID, rEntry.m_nControlAction, rEntry.m_aValue );
211             if ( rEntry.m_bHasLabel )
212 				aAccess.setLabel( rEntry.m_nElementID, rEntry.m_aLabel );
213             if ( rEntry.m_bHasEnabled )
214 				aAccess.enableControl( rEntry.m_nElementID, rEntry.m_bEnabled );
215 		}
216 
217         getDialog()->updateListboxLabelSizes();
218     }
219 
220     if ( m_pFilterList && !m_pFilterList->empty() )
221     {
222         for (   FilterList::iterator aListIter = m_pFilterList->begin();
223                 aListIter != m_pFilterList->end();
224                 ++aListIter
225             )
226         {
227             if ( aListIter->hasSubFilters() )
228             {   // it's a filter group
229                 UnoFilterList aSubFilters;
230                 aListIter->getSubFilters( aSubFilters );
231 
232                 getDialog()->AddFilterGroup( aListIter->getTitle(), aSubFilters );
233              }
234             else
235                 // it's a single filter
236                 getDialog()->AddFilter( aListIter->getTitle(), aListIter->getFilter() );
237         }
238     }
239 
240     // set the default filter
241     if ( m_aCurrentFilter.getLength() > 0 )
242         getDialog()->SetCurFilter( m_aCurrentFilter );
243 
244 }
245 
246 //-----------------------------------------------------------------------------
247 IMPL_LINK( SvtFilePicker, DialogClosedHdl, Dialog*, pDlg )
248 {
249     if ( m_xDlgClosedListener.is() )
250     {
251         sal_Int16 nRet = static_cast< sal_Int16 >( pDlg->GetResult() );
252         ::com::sun::star::ui::dialogs::DialogClosedEvent aEvent( *this, nRet );
253         m_xDlgClosedListener->dialogClosed( aEvent );
254         m_xDlgClosedListener.clear();
255     }
256     return 0;
257 }
258 
259 //------------------------------------------------------------------------------------
260 // SvtFilePicker
261 //------------------------------------------------------------------------------------
262 
263 //------------------------------------------------------------------------------------
264 WinBits SvtFilePicker::getWinBits( WinBits& rExtraBits )
265 {
266 	// set the winbits for creating the filedialog
267 	WinBits nBits = 0L;
268     rExtraBits = 0L;
269 
270 	// set the standard bits acording to the service name
271     if ( m_nServiceType == TemplateDescription::FILEOPEN_SIMPLE )
272 	{
273 		nBits = WB_OPEN;
274 	}
275 	else if ( m_nServiceType == TemplateDescription::FILESAVE_SIMPLE )
276 	{
277 		nBits = WB_SAVEAS;
278 	}
279 	else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION )
280 	{
281 		nBits = WB_SAVEAS;
282         rExtraBits = SFX_EXTRA_AUTOEXTENSION;
283 	}
284 	else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD )
285 	{
286 		nBits = WB_SAVEAS | SFXWB_PASSWORD;
287         rExtraBits = SFX_EXTRA_AUTOEXTENSION;
288 	}
289     else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS )
290 	{
291 		nBits = WB_SAVEAS | SFXWB_PASSWORD;
292         rExtraBits = SFX_EXTRA_AUTOEXTENSION | SFX_EXTRA_FILTEROPTIONS;
293 	}
294     else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE )
295 	{
296 		nBits = WB_SAVEAS;
297         rExtraBits = SFX_EXTRA_AUTOEXTENSION | SFX_EXTRA_TEMPLATES;
298 	}
299     else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION )
300 	{
301 		nBits = WB_SAVEAS;
302         rExtraBits = SFX_EXTRA_AUTOEXTENSION | SFX_EXTRA_SELECTION;
303     }
304 
305     else if ( m_nServiceType == TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE )
306 	{
307 		nBits = WB_OPEN;
308         rExtraBits = SFX_EXTRA_INSERTASLINK | SFX_EXTRA_SHOWPREVIEW | SFX_EXTRA_IMAGE_TEMPLATE;
309 	}
310     else if ( m_nServiceType == TemplateDescription::FILEOPEN_PLAY )
311 	{
312 		nBits = WB_OPEN;
313         rExtraBits = SFX_EXTRA_PLAYBUTTON;
314     }
315     else if ( m_nServiceType == TemplateDescription::FILEOPEN_READONLY_VERSION )
316 	{
317 		nBits = WB_OPEN | SFXWB_READONLY;
318         rExtraBits = SFX_EXTRA_SHOWVERSIONS;
319 	}
320     else if ( m_nServiceType == TemplateDescription::FILEOPEN_LINK_PREVIEW )
321 	{
322 		nBits = WB_OPEN;
323         rExtraBits = SFX_EXTRA_INSERTASLINK | SFX_EXTRA_SHOWPREVIEW;
324 	}
325 	if ( m_bMultiSelection && ( ( nBits & WB_OPEN ) == WB_OPEN ) )
326 		nBits |= SFXWB_MULTISELECTION;
327 
328 	return nBits;
329 }
330 
331 //------------------------------------------------------------------------------------
332 void SvtFilePicker::notify( sal_Int16 _nEventId, sal_Int16 _nControlId )
333 {
334 	if ( !m_xListener.is() )
335 		return;
336 
337     FilePickerEvent aEvent( *this, _nControlId );
338 
339 	switch ( _nEventId )
340 	{
341 		case FILE_SELECTION_CHANGED:
342 			m_xListener->fileSelectionChanged( aEvent );
343 			break;
344 		case DIRECTORY_CHANGED:
345 			m_xListener->directoryChanged( aEvent );
346 			break;
347 		case HELP_REQUESTED:
348 			m_xListener->helpRequested( aEvent );
349 			break;
350 		case CTRL_STATE_CHANGED:
351 			m_xListener->controlStateChanged( aEvent );
352 			break;
353 		case DIALOG_SIZE_CHANGED:
354 			m_xListener->dialogSizeChanged();
355 			break;
356 		default:
357 			DBG_ERRORFILE( "SvtFilePicker::notify(): Unknown event id!" );
358 			break;
359 	}
360 }
361 
362 //------------------------------------------------------------------------------------
363 namespace {
364 	//................................................................................
365 	struct FilterTitleMatch : public ::std::unary_function< FilterEntry, bool >
366 	{
367 	protected:
368 		const ::rtl::OUString& rTitle;
369 
370 	public:
371 		FilterTitleMatch( const ::rtl::OUString& _rTitle ) : rTitle( _rTitle ) { }
372 
373 		//............................................................................
374 		bool operator () ( const FilterEntry& _rEntry )
375 		{
376 			sal_Bool bMatch;
377 			if ( !_rEntry.hasSubFilters() )
378 				// a real filter
379 				bMatch = ( _rEntry.getTitle() == rTitle );
380 			else
381 				// a filter group -> search the sub filters
382 				bMatch =
383 					_rEntry.endSubFilters() != ::std::find_if(
384 						_rEntry.beginSubFilters(),
385 						_rEntry.endSubFilters(),
386 						*this
387 					);
388 
389 			return bMatch ? true : false;
390 		}
391 		bool operator () ( const UnoFilterEntry& _rEntry )
392 		{
393 			return _rEntry.First == rTitle ? true : false;
394 		}
395 	};
396 }
397 
398 //------------------------------------------------------------------------------------
399 sal_Bool SvtFilePicker::FilterNameExists( const ::rtl::OUString& rTitle )
400 {
401     sal_Bool bRet = sal_False;
402 
403     if ( m_pFilterList )
404 		bRet =
405 			m_pFilterList->end() != ::std::find_if(
406 				m_pFilterList->begin(),
407 				m_pFilterList->end(),
408 				FilterTitleMatch( rTitle )
409 			);
410 
411     return bRet;
412 }
413 
414 //------------------------------------------------------------------------------------
415 sal_Bool SvtFilePicker::FilterNameExists( const UnoFilterList& _rGroupedFilters )
416 {
417     sal_Bool bRet = sal_False;
418 
419 	if ( m_pFilterList )
420 	{
421 		const UnoFilterEntry* pStart = _rGroupedFilters.getConstArray();
422 		const UnoFilterEntry* pEnd = pStart + _rGroupedFilters.getLength();
423 		for ( ; pStart != pEnd; ++pStart )
424 			if ( m_pFilterList->end() != ::std::find_if( m_pFilterList->begin(), m_pFilterList->end(), FilterTitleMatch( pStart->First ) ) )
425 				break;
426 
427 		bRet = pStart != pEnd;
428 	}
429 
430 	return bRet;
431 }
432 
433 //------------------------------------------------------------------------------------
434 void SvtFilePicker::ensureFilterList( const ::rtl::OUString& _rInitialCurrentFilter )
435 {
436 	if ( !m_pFilterList )
437     {
438 		m_pFilterList = new FilterList;
439 
440         // set the first filter to the current filter
441         if ( ! m_aCurrentFilter.getLength() )
442             m_aCurrentFilter = _rInitialCurrentFilter;
443     }
444 }
445 
446 //------------------------------------------------------------------------------------
447 // class SvtFilePicker
448 //------------------------------------------------------------------------------------
449 SvtFilePicker::SvtFilePicker( const Reference < XMultiServiceFactory >& xFactory )
450 	:OCommonPicker( xFactory )
451 	,m_pFilterList		( NULL )
452 	,m_pElemList		( NULL )
453 	,m_bMultiSelection	( sal_False )
454 	,m_nServiceType		( TemplateDescription::FILEOPEN_SIMPLE )
455 {
456 }
457 
458 SvtFilePicker::~SvtFilePicker()
459 {
460 	if ( m_pFilterList && !m_pFilterList->empty() )
461 		m_pFilterList->erase( m_pFilterList->begin(), m_pFilterList->end() );
462 	delete m_pFilterList;
463 
464 	if ( m_pElemList && !m_pElemList->empty() )
465 		m_pElemList->erase( m_pElemList->begin(), m_pElemList->end() );
466 	delete m_pElemList;
467 }
468 
469 //------------------------------------------------------------------------------------
470 sal_Int16 SvtFilePicker::implExecutePicker( )
471 {
472 	getDialog()->SetFileCallback( this );
473 
474     prepareExecute();
475 
476     getDialog()->EnableAutocompletion( sal_True );
477     // now we are ready to execute the dialog
478     sal_Int16 nRet = getDialog()->Execute();
479 
480 	// the execution of the dialog yields, so it is possible the at this point the window or the dialog is closed
481 	if ( getDialog() )
482 		getDialog()->SetFileCallback( NULL );
483 
484 	return nRet;
485 }
486 
487 //------------------------------------------------------------------------------------
488 SvtFileDialog* SvtFilePicker::implCreateDialog( Window* _pParent )
489 {
490 	WinBits	nExtraBits;
491 	WinBits	nBits = getWinBits( nExtraBits );
492 
493 	SvtFileDialog* dialog = new SvtFileDialog( _pParent, nBits, nExtraBits );
494 
495 	// Set StandardDir if present
496 	if ( m_aStandardDir.getLength() > 0)
497 	{
498 		String sStandardDir = String( m_aStandardDir );
499 		dialog->SetStandardDir( sStandardDir );
500 		dialog->SetBlackList( m_aBlackList );
501 	}
502 
503 	return dialog;
504 }
505 
506 //------------------------------------------------------------------------------------
507 // disambiguate XInterface
508 //------------------------------------------------------------------------------------
509 IMPLEMENT_FORWARD_XINTERFACE2( SvtFilePicker, OCommonPicker, SvtFilePicker_Base )
510 
511 //------------------------------------------------------------------------------------
512 // disambiguate XTypeProvider
513 //------------------------------------------------------------------------------------
514 IMPLEMENT_FORWARD_XTYPEPROVIDER2( SvtFilePicker, OCommonPicker, SvtFilePicker_Base )
515 
516 //------------------------------------------------------------------------------------
517 // XExecutableDialog functions
518 //------------------------------------------------------------------------------------
519 
520 //------------------------------------------------------------------------------------
521 void SAL_CALL SvtFilePicker::setTitle( const ::rtl::OUString& _rTitle ) throw (RuntimeException)
522 {
523 	OCommonPicker::setTitle( _rTitle );
524 }
525 
526 //------------------------------------------------------------------------------------
527 sal_Int16 SAL_CALL SvtFilePicker::execute(  ) throw (RuntimeException)
528 {
529 	return OCommonPicker::execute();
530 }
531 
532 //------------------------------------------------------------------------------------
533 // XAsynchronousExecutableDialog functions
534 //------------------------------------------------------------------------------------
535 
536 //------------------------------------------------------------------------------------
537 void SAL_CALL SvtFilePicker::setDialogTitle( const ::rtl::OUString& _rTitle ) throw (RuntimeException)
538 {
539     setTitle( _rTitle );
540 }
541 
542 //------------------------------------------------------------------------------------
543 void SAL_CALL SvtFilePicker::startExecuteModal( const Reference< ::com::sun::star::ui::dialogs::XDialogClosedListener >& xListener ) throw (RuntimeException)
544 {
545     m_xDlgClosedListener = xListener;
546     prepareDialog();
547     prepareExecute();
548     getDialog()->EnableAutocompletion( sal_True );
549     getDialog()->StartExecuteModal( LINK( this, SvtFilePicker, DialogClosedHdl ) );
550 }
551 
552 //------------------------------------------------------------------------------------
553 // XFilePicker functions
554 //------------------------------------------------------------------------------------
555 
556 void SAL_CALL SvtFilePicker::setMultiSelectionMode( sal_Bool bMode ) throw( RuntimeException )
557 {
558 	checkAlive();
559 
560     ::vos::OGuard aGuard( Application::GetSolarMutex() );
561 	m_bMultiSelection = bMode;
562 }
563 
564 void SAL_CALL SvtFilePicker::setDefaultName( const rtl::OUString& aName ) throw( RuntimeException )
565 {
566 	checkAlive();
567 
568     ::vos::OGuard aGuard( Application::GetSolarMutex() );
569 	m_aDefaultName = aName;
570 }
571 
572 void SAL_CALL SvtFilePicker::setDisplayDirectory( const rtl::OUString& aDirectory )
573     throw( IllegalArgumentException, RuntimeException )
574 {
575 	checkAlive();
576 
577     ::vos::OGuard aGuard( Application::GetSolarMutex() );
578 	m_aDisplayDirectory = aDirectory;
579 }
580 
581 rtl::OUString SAL_CALL SvtFilePicker::getDisplayDirectory() throw( RuntimeException )
582 {
583 	checkAlive();
584 
585     ::vos::OGuard aGuard( Application::GetSolarMutex() );
586 	if ( getDialog() )
587     {
588         rtl::OUString aPath = getDialog()->GetPath();
589 
590 		// #97148# ----
591 		if( m_aOldHideDirectory == aPath )
592 			return m_aOldDisplayDirectory;
593 		m_aOldHideDirectory = aPath;
594 
595 		// #102204# -----
596 		if( !getDialog()->ContentIsFolder( aPath ) )
597         {
598             INetURLObject aFolder( aPath );
599             aFolder.CutLastName();
600             aPath = aFolder.GetMainURL( INetURLObject::NO_DECODE );
601         }
602 		m_aOldDisplayDirectory = aPath;
603         return aPath;
604     }
605     else
606         return m_aDisplayDirectory;
607 }
608 
609 Sequence< rtl::OUString > SAL_CALL SvtFilePicker::getFiles() throw( RuntimeException )
610 {
611 	checkAlive();
612 
613     ::vos::OGuard aGuard( Application::GetSolarMutex() );
614 	if ( ! getDialog() )
615 	{
616 		Sequence< rtl::OUString > aEmpty;
617 		return aEmpty;
618 	}
619 
620 	// if there is more than one path we have to return the path to the
621 	// files first and then the list of the selected entries
622 
623 	SvStringsDtor* pPathList = getDialog()->GetPathList();
624 	sal_uInt16 i, nCount = pPathList->Count();
625 	sal_uInt16 nTotal = nCount > 1 ? nCount+1: nCount;
626 
627 	Sequence< rtl::OUString > aPath( nTotal );
628 
629 	if ( nCount == 1 )
630 		aPath[0] = rtl::OUString( *pPathList->GetObject( 0 ) );
631 	else if ( nCount > 1 )
632 	{
633 		INetURLObject aObj( *pPathList->GetObject( 0 ) );
634 		aObj.removeSegment();
635 		aPath[0] = aObj.GetMainURL( INetURLObject::NO_DECODE );
636 
637 		for ( i = 0; i < nCount; /* i++ is done below */ )
638 		{
639 			aObj.SetURL( *pPathList->GetObject(i++) );
640 			aPath[i] = aObj.getName();
641 		}
642 	}
643 
644 	delete pPathList;
645 	return aPath;
646 }
647 
648 //------------------------------------------------------------------------------------
649 // XFilePickerControlAccess functions
650 //------------------------------------------------------------------------------------
651 
652 void SAL_CALL SvtFilePicker::setValue( sal_Int16 nElementID,
653                                        sal_Int16 nControlAction,
654                                        const Any& rValue )
655     throw( RuntimeException )
656 {
657 	checkAlive();
658 
659     ::vos::OGuard aGuard( Application::GetSolarMutex() );
660 	if ( getDialog() )
661 	{
662 		::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() );
663 		aAccess.setValue( nElementID, nControlAction, rValue );
664 	}
665 	else
666 	{
667 		if ( !m_pElemList )
668 			m_pElemList = new ElementList;
669 
670         sal_Bool bFound = sal_False;
671 		ElementList::iterator aListIter;
672 
673         for ( aListIter = m_pElemList->begin();
674 			  aListIter != m_pElemList->end(); ++aListIter )
675 		{
676 			ElementEntry_Impl& rEntry = *aListIter;
677             if ( ( rEntry.m_nElementID == nElementID ) &&
678                  ( !rEntry.m_bHasValue || ( rEntry.m_nControlAction == nControlAction ) ) )
679             {
680                 rEntry.setAction( nControlAction );
681                 rEntry.setValue( rValue );
682                 bFound = sal_True;
683             }
684 		}
685 
686         if ( !bFound )
687         {
688             ElementEntry_Impl aNew( nElementID );
689             aNew.setAction( nControlAction );
690             aNew.setValue( rValue );
691             m_pElemList->insert( m_pElemList->end(), aNew );
692         }
693 	}
694 }
695 
696 //------------------------------------------------------------------------------------
697 
698 Any SAL_CALL SvtFilePicker::getValue( sal_Int16 nElementID, sal_Int16 nControlAction )
699     throw( RuntimeException )
700 {
701 	checkAlive();
702 
703     ::vos::OGuard aGuard( Application::GetSolarMutex() );
704 	Any      aAny;
705 
706 	// execute() called?
707 	if ( getDialog() )
708 	{
709 		::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() );
710 		aAny = aAccess.getValue( nElementID, nControlAction );
711 	}
712     else if ( m_pElemList && !m_pElemList->empty() )
713     {
714 		ElementList::iterator aListIter;
715 		for ( aListIter = m_pElemList->begin();
716 			  aListIter != m_pElemList->end(); ++aListIter )
717 		{
718 			ElementEntry_Impl& rEntry = *aListIter;
719             if ( ( rEntry.m_nElementID == nElementID ) &&
720                  ( rEntry.m_bHasValue ) &&
721                  ( rEntry.m_nControlAction == nControlAction ) )
722             {
723                 aAny = rEntry.m_aValue;
724                 break;
725             }
726 		}
727     }
728 
729     return aAny;
730 }
731 
732 
733 //------------------------------------------------------------------------------------
734 void SAL_CALL SvtFilePicker::setLabel( sal_Int16 nLabelID, const rtl::OUString& rValue )
735     throw ( RuntimeException )
736 {
737 	checkAlive();
738 
739     ::vos::OGuard aGuard( Application::GetSolarMutex() );
740 	if ( getDialog() )
741 	{
742 		::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() );
743 		aAccess.setLabel( nLabelID, rValue );
744 	}
745 	else
746 	{
747 		if ( !m_pElemList )
748 			m_pElemList = new ElementList;
749 
750         sal_Bool bFound = sal_False;
751 		ElementList::iterator aListIter;
752 
753         for ( aListIter = m_pElemList->begin();
754 			  aListIter != m_pElemList->end(); ++aListIter )
755 		{
756 			ElementEntry_Impl& rEntry = *aListIter;
757             if ( rEntry.m_nElementID == nLabelID )
758             {
759                 rEntry.setLabel( rValue );
760                 bFound = sal_True;
761             }
762 		}
763 
764         if ( !bFound )
765         {
766             ElementEntry_Impl aNew( nLabelID );
767             aNew.setLabel( rValue );
768             m_pElemList->insert( m_pElemList->end(), aNew );
769         }
770 	}
771 }
772 
773 //------------------------------------------------------------------------------------
774 rtl::OUString SAL_CALL SvtFilePicker::getLabel( sal_Int16 nLabelID )
775     throw ( RuntimeException )
776 {
777 	checkAlive();
778 
779     ::vos::OGuard aGuard( Application::GetSolarMutex() );
780 	rtl::OUString aLabel;
781 
782     if ( getDialog() )
783 	{
784 		::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() );
785 		aLabel = aAccess.getLabel( nLabelID );
786 	}
787     else if ( m_pElemList && !m_pElemList->empty() )
788     {
789 		ElementList::iterator aListIter;
790 		for ( aListIter = m_pElemList->begin();
791 			  aListIter != m_pElemList->end(); ++aListIter )
792 		{
793 			ElementEntry_Impl& rEntry = *aListIter;
794             if ( rEntry.m_nElementID == nLabelID )
795             {
796                 if ( rEntry.m_bHasLabel )
797                     aLabel = rEntry.m_aLabel;
798                 break;
799             }
800 		}
801     }
802 
803 	return aLabel;
804 }
805 
806 //------------------------------------------------------------------------------------
807 void SAL_CALL SvtFilePicker::enableControl( sal_Int16 nElementID, sal_Bool bEnable )
808     throw( RuntimeException )
809 {
810 	checkAlive();
811 
812     ::vos::OGuard aGuard( Application::GetSolarMutex() );
813     if ( getDialog() )
814 	{
815 		::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() );
816 		aAccess.enableControl( nElementID, bEnable );
817 	}
818     else
819     {
820 		if ( !m_pElemList )
821 			m_pElemList = new ElementList;
822 
823         sal_Bool bFound = sal_False;
824 		ElementList::iterator aListIter;
825 
826         for ( aListIter = m_pElemList->begin();
827 			  aListIter != m_pElemList->end(); ++aListIter )
828 		{
829 			ElementEntry_Impl& rEntry = *aListIter;
830             if ( rEntry.m_nElementID == nElementID )
831             {
832                 rEntry.setEnabled( bEnable );
833                 bFound = sal_True;
834             }
835 		}
836 
837         if ( !bFound )
838         {
839             ElementEntry_Impl aNew( nElementID );
840             aNew.setEnabled( bEnable );
841             m_pElemList->insert( m_pElemList->end(), aNew );
842         }
843     }
844 }
845 
846 //------------------------------------------------------------------------------------
847 // XFilePickerNotifier functions
848 //------------------------------------------------------------------------------------
849 
850 void SAL_CALL SvtFilePicker::addFilePickerListener( const Reference< XFilePickerListener >& xListener ) throw ( RuntimeException )
851 {
852 	checkAlive();
853 
854     ::vos::OGuard aGuard( Application::GetSolarMutex() );
855 	m_xListener = xListener;
856 }
857 
858 //------------------------------------------------------------------------------------
859 void SAL_CALL SvtFilePicker::removeFilePickerListener( const Reference< XFilePickerListener >& ) throw ( RuntimeException )
860 {
861 	checkAlive();
862 
863     ::vos::OGuard aGuard( Application::GetSolarMutex() );
864 	m_xListener.clear();
865 }
866 
867 //------------------------------------------------------------------------------------
868 // XFilePreview functions
869 //------------------------------------------------------------------------------------
870 
871 Sequence< sal_Int16 > SAL_CALL SvtFilePicker::getSupportedImageFormats()
872     throw ( RuntimeException )
873 {
874 	checkAlive();
875 
876     ::vos::OGuard aGuard( Application::GetSolarMutex() );
877     Sequence< sal_Int16 > aFormats( 1 );
878 
879     aFormats[0] = FilePreviewImageFormats::BITMAP;
880 
881     return aFormats;
882 }
883 
884 //------------------------------------------------------------------------------------
885 sal_Int32 SAL_CALL SvtFilePicker::getTargetColorDepth() throw ( RuntimeException )
886 {
887 	checkAlive();
888 
889     ::vos::OGuard aGuard( Application::GetSolarMutex() );
890     sal_Int32 nDepth = 0;
891 
892     if ( getDialog() )
893         nDepth = getDialog()->getTargetColorDepth();
894 
895     return nDepth;
896 }
897 
898 //------------------------------------------------------------------------------------
899 sal_Int32 SAL_CALL SvtFilePicker::getAvailableWidth() throw ( RuntimeException )
900 {
901 	checkAlive();
902 
903     ::vos::OGuard aGuard( Application::GetSolarMutex() );
904     sal_Int32 nWidth = 0;
905 
906     if ( getDialog() )
907         nWidth = getDialog()->getAvailableWidth();
908 
909     return nWidth;
910 }
911 
912 //------------------------------------------------------------------------------------
913 sal_Int32 SAL_CALL SvtFilePicker::getAvailableHeight() throw ( RuntimeException )
914 {
915 	checkAlive();
916 
917     ::vos::OGuard aGuard( Application::GetSolarMutex() );
918     sal_Int32 nHeigth = 0;
919 
920     if ( getDialog() )
921         nHeigth = getDialog()->getAvailableHeight();
922 
923     return nHeigth;
924 }
925 
926 //------------------------------------------------------------------------------------
927 void SAL_CALL SvtFilePicker::setImage( sal_Int16 aImageFormat, const Any& rImage )
928     throw ( IllegalArgumentException, RuntimeException )
929 {
930 	checkAlive();
931 
932     ::vos::OGuard aGuard( Application::GetSolarMutex() );
933     if ( getDialog() )
934         getDialog()->setImage( aImageFormat, rImage );
935 }
936 
937 //------------------------------------------------------------------------------------
938 sal_Bool SAL_CALL SvtFilePicker::setShowState( sal_Bool bShowState )
939     throw ( RuntimeException )
940 {
941 	checkAlive();
942 
943     ::vos::OGuard aGuard( Application::GetSolarMutex() );
944     sal_Bool bRet = sal_False;
945 
946     if ( getDialog() )
947         bRet = getDialog()->setShowState( bShowState );
948 
949     return bRet;
950 }
951 
952 //------------------------------------------------------------------------------------
953 sal_Bool SAL_CALL SvtFilePicker::getShowState() throw ( RuntimeException )
954 {
955 	checkAlive();
956 
957     ::vos::OGuard aGuard( Application::GetSolarMutex() );
958     sal_Bool bRet = sal_False;
959 
960     if ( getDialog() )
961         bRet = getDialog()->getShowState();
962 
963     return bRet;
964 }
965 
966 //------------------------------------------------------------------------------------
967 // XFilterGroupManager functions
968 //------------------------------------------------------------------------------------
969 
970 void SAL_CALL SvtFilePicker::appendFilterGroup(	const ::rtl::OUString& sGroupTitle,
971 												const Sequence< StringPair >& aFilters )
972 	throw ( IllegalArgumentException, RuntimeException )
973 {
974 	checkAlive();
975 
976     ::vos::OGuard aGuard( Application::GetSolarMutex() );
977 
978 	// check the names
979 	if ( FilterNameExists( aFilters ) )
980         throw IllegalArgumentException(
981             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("filter name exists")),
982             static_cast< OWeakObject * >(this), 1);
983 
984 	// ensure that we have a filter list
985 	::rtl::OUString sInitialCurrentFilter;
986 	if ( aFilters.getLength() )
987 		sInitialCurrentFilter = aFilters[0].First;
988 	ensureFilterList( sInitialCurrentFilter );
989 
990 	// append the filter
991 	m_pFilterList->insert( m_pFilterList->end(), FilterEntry( sGroupTitle, aFilters ) );
992 }
993 
994 //------------------------------------------------------------------------------------
995 // XFilterManager functions
996 //------------------------------------------------------------------------------------
997 
998 void SAL_CALL SvtFilePicker::appendFilter( const rtl::OUString& aTitle,
999                                            const rtl::OUString& aFilter )
1000     throw( IllegalArgumentException, RuntimeException )
1001 {
1002 	checkAlive();
1003 
1004     ::vos::OGuard aGuard( Application::GetSolarMutex() );
1005 	// check the name
1006 	if ( FilterNameExists( aTitle ) )
1007 		// TODO: a more precise exception message
1008         throw IllegalArgumentException();
1009 
1010 	// ensure that we have a filter list
1011 	ensureFilterList( aTitle );
1012 
1013 	// append the filter
1014 	m_pFilterList->insert( m_pFilterList->end(), FilterEntry( aTitle, aFilter ) );
1015 }
1016 
1017 //------------------------------------------------------------------------------------
1018 void SAL_CALL SvtFilePicker::setCurrentFilter( const rtl::OUString& aTitle )
1019     throw( IllegalArgumentException, RuntimeException )
1020 {
1021 	checkAlive();
1022 
1023     ::vos::OGuard aGuard( Application::GetSolarMutex() );
1024     if ( ! FilterNameExists( aTitle ) )
1025         throw IllegalArgumentException();
1026 
1027 	m_aCurrentFilter = aTitle;
1028 
1029     if ( getDialog() )
1030         getDialog()->SetCurFilter( aTitle );
1031 }
1032 
1033 //------------------------------------------------------------------------------------
1034 rtl::OUString SAL_CALL SvtFilePicker::getCurrentFilter()
1035     throw( RuntimeException )
1036 {
1037 	checkAlive();
1038 
1039     ::vos::OGuard aGuard( Application::GetSolarMutex() );
1040 	rtl::OUString aFilter = getDialog() ? rtl::OUString( getDialog()->GetCurFilter() ) :
1041                                             rtl::OUString( m_aCurrentFilter );
1042 	return aFilter;
1043 }
1044 
1045 
1046 //------------------------------------------------------------------------------------
1047 // XInitialization functions
1048 //------------------------------------------------------------------------------------
1049 
1050 void SAL_CALL SvtFilePicker::initialize( const Sequence< Any >& _rArguments )
1051 	throw ( Exception, RuntimeException )
1052 {
1053 	checkAlive();
1054 
1055 	Sequence< Any > aArguments( _rArguments.getLength());
1056 
1057 	m_nServiceType = TemplateDescription::FILEOPEN_SIMPLE;
1058 
1059 	if ( _rArguments.getLength() >= 1 )
1060 	{
1061 		// compatibility: one argument, type sal_Int16 , specifies the service type
1062 		int index = 0;
1063 
1064 		if (_rArguments[0] >>= m_nServiceType)
1065 		{
1066 			// skip the first entry if it was the ServiceType, because it's not needed in OCommonPicker::initialize and it's not a NamedValue
1067 			NamedValue emptyNamedValue;
1068 			aArguments[0] <<= emptyNamedValue;
1069 			index = 1;
1070 
1071 		}
1072 		for ( int i = index; i < _rArguments.getLength(); i++)
1073 		{
1074 			NamedValue namedValue;
1075 			aArguments[i] <<= _rArguments[i];
1076 
1077 			if (aArguments[i] >>= namedValue )
1078 			{
1079 
1080 				if ( namedValue.Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StandardDir" ) ) ) )
1081 				{
1082 					::rtl::OUString sStandardDir;
1083 
1084 					namedValue.Value >>= sStandardDir;
1085 
1086 					// Set the directory for the "back to the default dir" button
1087 						if ( sStandardDir.getLength() > 0 )
1088 					{
1089 						m_aStandardDir = sStandardDir;
1090 					}
1091 				}
1092 				else if ( namedValue.Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BlackList" ) ) ) )
1093 				{
1094 					namedValue.Value >>= m_aBlackList;
1095 				}
1096 			}
1097 		}
1098 	}
1099 
1100 	// let the base class analyze the sequence (will call into implHandleInitializationArgument)
1101 	OCommonPicker::initialize( aArguments );
1102 }
1103 
1104 //-------------------------------------------------------------------------
1105 sal_Bool SvtFilePicker::implHandleInitializationArgument( const ::rtl::OUString& _rName, const Any& _rValue ) SAL_THROW( ( Exception, RuntimeException ) )
1106 {
1107 	if ( _rName.equalsAscii( "TemplateDescription" ) )
1108 	{
1109 		m_nServiceType = TemplateDescription::FILEOPEN_SIMPLE;
1110 		OSL_VERIFY( _rValue >>= m_nServiceType );
1111 		return sal_True;
1112 	}
1113 	if ( _rName.equalsAscii( "StandardDir" ) )
1114 	{
1115 		OSL_VERIFY( _rValue >>= m_aStandardDir );
1116 		return sal_True;
1117 	}
1118 
1119 	if ( _rName.equalsAscii( "BlackList" ) )
1120 	{
1121 		OSL_VERIFY( _rValue >>= m_aBlackList );
1122 		return sal_True;
1123 	}
1124 
1125 
1126 
1127 	return OCommonPicker::implHandleInitializationArgument( _rName, _rValue );
1128 }
1129 
1130 //------------------------------------------------------------------------------------
1131 // XServiceInfo
1132 //------------------------------------------------------------------------------------
1133 
1134 /* XServiceInfo */
1135 rtl::OUString SAL_CALL SvtFilePicker::getImplementationName() throw( RuntimeException )
1136 {
1137 	return impl_getStaticImplementationName();
1138 }
1139 
1140 /* XServiceInfo */
1141 sal_Bool SAL_CALL SvtFilePicker::supportsService( const rtl::OUString& sServiceName ) throw( RuntimeException )
1142 {
1143     Sequence< rtl::OUString > seqServiceNames = getSupportedServiceNames();
1144     const rtl::OUString* pArray = seqServiceNames.getConstArray();
1145     for ( sal_Int32 i = 0; i < seqServiceNames.getLength(); i++ )
1146 	{
1147         if ( sServiceName == pArray[i] )
1148 		{
1149             return sal_True ;
1150 		}
1151 	}
1152     return sal_False ;
1153 }
1154 
1155 /* XServiceInfo */
1156 Sequence< rtl::OUString > SAL_CALL SvtFilePicker::getSupportedServiceNames() throw( RuntimeException )
1157 {
1158 	return impl_getStaticSupportedServiceNames();
1159 }
1160 
1161 /* Helper for XServiceInfo */
1162 Sequence< rtl::OUString > SvtFilePicker::impl_getStaticSupportedServiceNames()
1163 {
1164     Sequence< rtl::OUString > seqServiceNames( 1 );
1165     rtl::OUString* pArray = seqServiceNames.getArray();
1166     pArray[0] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.OfficeFilePicker" );
1167     return seqServiceNames ;
1168 }
1169 
1170 /* Helper for XServiceInfo */
1171 rtl::OUString SvtFilePicker::impl_getStaticImplementationName()
1172 {
1173     return rtl::OUString::createFromAscii( "com.sun.star.svtools.OfficeFilePicker" );
1174 }
1175 
1176 /* Helper for registry */
1177 Reference< XInterface > SAL_CALL SvtFilePicker::impl_createInstance(
1178 	const Reference< XComponentContext >& rxContext) throw( Exception )
1179 {
1180 	Reference< XMultiServiceFactory > xServiceManager (rxContext->getServiceManager(), UNO_QUERY_THROW);
1181 	return Reference< XInterface >( *new SvtFilePicker( xServiceManager ) );
1182 }
1183