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