xref: /trunk/main/fpicker/source/office/OfficeFilePicker.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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