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