xref: /AOO41X/main/sfx2/source/dialog/filedlghelper.cxx (revision b2937f997bda0a05141a2d862a64f7be893955b7)
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_sfx2.hxx"
26 #include <sfx2/filedlghelper.hxx>
27 #include <sal/types.h>
28 #include <com/sun/star/lang/XInitialization.hpp>
29 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
30 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
31 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
32 #include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
33 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
34 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
35 #include <com/sun/star/ui/dialogs/XControlInformation.hpp>
36 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
37 #include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp>
38 #include <com/sun/star/ui/dialogs/XFilePreview.hpp>
39 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
40 #include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp>
41 #include <com/sun/star/ui/dialogs/XFolderPicker.hpp>
42 #include <com/sun/star/ui/dialogs/XFilePicker2.hpp>
43 #include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
44 #include <com/sun/star/lang/XServiceInfo.hpp>
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/beans/NamedValue.hpp>
47 #include <com/sun/star/embed/ElementModes.hpp>
48 #include <com/sun/star/container/XEnumeration.hpp>
49 #include <com/sun/star/container/XContainerQuery.hpp>
50 #include <com/sun/star/task/XInteractionRequest.hpp>
51 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
52 
53 #include <comphelper/processfactory.hxx>
54 #include <comphelper/types.hxx>
55 #include <comphelper/sequenceashashmap.hxx>
56 #include <comphelper/stillreadwriteinteraction.hxx>
57 #include <tools/urlobj.hxx>
58 #include <vcl/help.hxx>
59 #include <unotools/ucbstreamhelper.hxx>
60 #include <unotools/ucbhelper.hxx>
61 #include <unotools/localfilehelper.hxx>
62 #include <vos/thread.hxx>
63 #include <vos/mutex.hxx>
64 #include <vos/security.hxx>
65 #include <vcl/cvtgrf.hxx>
66 #include <vcl/msgbox.hxx>
67 #include <vcl/mnemonic.hxx>
68 #include <unotools/pathoptions.hxx>
69 #include <unotools/securityoptions.hxx>
70 #include <svl/itemset.hxx>
71 #include <svl/eitem.hxx>
72 #include <svl/intitem.hxx>
73 #include <svl/stritem.hxx>
74 #include <svtools/filter.hxx>
75 #include <unotools/viewoptions.hxx>
76 #include <unotools/moduleoptions.hxx>
77 #include <svtools/helpid.hrc>
78 #include <comphelper/docpasswordrequest.hxx>
79 #include <comphelper/docpasswordhelper.hxx>
80 #include <ucbhelper/content.hxx>
81 #include <ucbhelper/commandenvironment.hxx>
82 #include <comphelper/storagehelper.hxx>
83 #include <toolkit/helper/vclunohelper.hxx>
84 #include <sfx2/app.hxx>
85 #include <sfx2/frame.hxx>
86 #include <sfx2/docfile.hxx>
87 #include <sfx2/docfac.hxx>
88 #include "openflag.hxx"
89 #include <sfx2/passwd.hxx>
90 #include "sfx2/sfxresid.hxx"
91 #include <sfx2/sfxsids.hrc>
92 #include "filedlghelper.hrc"
93 #include "filtergrouping.hxx"
94 #include <sfx2/request.hxx>
95 #include "filedlgimpl.hxx"
96 #include <helpid.hrc>
97 #include <sfxlocal.hrc>
98 
99 //-----------------------------------------------------------------------------
100 
101 using namespace ::com::sun::star;
102 using namespace ::com::sun::star::container;
103 using namespace ::com::sun::star::lang;
104 using namespace ::com::sun::star::ui::dialogs;
105 using namespace ::com::sun::star::ui::dialogs::TemplateDescription;
106 using namespace ::com::sun::star::uno;
107 using namespace ::com::sun::star::beans;
108 using namespace ::rtl;
109 using namespace ::cppu;
110 
111 //-----------------------------------------------------------------------------
112 
113 #define IODLG_CONFIGNAME        String(DEFINE_CONST_UNICODE("FilePicker_Save"))
114 #define IMPGRF_CONFIGNAME       String(DEFINE_CONST_UNICODE("FilePicker_Graph"))
115 #define USERITEM_NAME           ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "UserItem" ))
116 
117 //-----------------------------------------------------------------------------
118 
119 namespace sfx2
120 {
121 
122 const OUString* GetLastFilterConfigId( FileDialogHelper::Context _eContext )
123 {
124     static const OUString aSD_EXPORT_IDENTIFIER( RTL_CONSTASCII_USTRINGPARAM( "SdExportLastFilter" ) );
125     static const OUString aSI_EXPORT_IDENTIFIER( RTL_CONSTASCII_USTRINGPARAM( "SiExportLastFilter" ) );
126     static const OUString aSW_EXPORT_IDENTIFIER( RTL_CONSTASCII_USTRINGPARAM( "SwExportLastFilter" ) );
127 
128     const OUString* pRet = NULL;
129 
130     switch( _eContext )
131     {
132         case FileDialogHelper::SD_EXPORT: pRet = &aSD_EXPORT_IDENTIFIER; break;
133         case FileDialogHelper::SI_EXPORT: pRet = &aSI_EXPORT_IDENTIFIER; break;
134         case FileDialogHelper::SW_EXPORT: pRet = &aSW_EXPORT_IDENTIFIER; break;
135         default: break;
136     }
137 
138     return pRet;
139 }
140 
141 String EncodeSpaces_Impl( const String& rSource );
142 String DecodeSpaces_Impl( const String& rSource );
143 
144 // ------------------------------------------------------------------------
145 // -----------      FileDialogHelper_Impl       ---------------------------
146 // ------------------------------------------------------------------------
147 
148 // ------------------------------------------------------------------------
149 // XFilePickerListener Methods
150 // ------------------------------------------------------------------------
151 void SAL_CALL FileDialogHelper_Impl::fileSelectionChanged( const FilePickerEvent& aEvent ) throw ( RuntimeException )
152 {
153     ::vos::OGuard aGuard( Application::GetSolarMutex() );
154     mpAntiImpl->FileSelectionChanged( aEvent );
155 }
156 
157 // ------------------------------------------------------------------------
158 void SAL_CALL FileDialogHelper_Impl::directoryChanged( const FilePickerEvent& aEvent ) throw ( RuntimeException )
159 {
160     ::vos::OGuard aGuard( Application::GetSolarMutex() );
161     mpAntiImpl->DirectoryChanged( aEvent );
162 }
163 
164 // ------------------------------------------------------------------------
165 OUString SAL_CALL FileDialogHelper_Impl::helpRequested( const FilePickerEvent& aEvent ) throw ( RuntimeException )
166 {
167     ::vos::OGuard aGuard( Application::GetSolarMutex() );
168     return mpAntiImpl->HelpRequested( aEvent );
169 }
170 
171 // ------------------------------------------------------------------------
172 void SAL_CALL FileDialogHelper_Impl::controlStateChanged( const FilePickerEvent& aEvent ) throw ( RuntimeException )
173 {
174     ::vos::OGuard aGuard( Application::GetSolarMutex() );
175     mpAntiImpl->ControlStateChanged( aEvent );
176 }
177 
178 // ------------------------------------------------------------------------
179 void SAL_CALL FileDialogHelper_Impl::dialogSizeChanged() throw ( RuntimeException )
180 {
181     ::vos::OGuard aGuard( Application::GetSolarMutex() );
182     mpAntiImpl->DialogSizeChanged();
183 }
184 
185 // ------------------------------------------------------------------------
186 // XDialogClosedListener Methods
187 // ------------------------------------------------------------------------
188 void SAL_CALL FileDialogHelper_Impl::dialogClosed( const DialogClosedEvent& _rEvent ) throw ( RuntimeException )
189 {
190     ::vos::OGuard aGuard( Application::GetSolarMutex() );
191     mpAntiImpl->DialogClosed( _rEvent );
192     postExecute( _rEvent.DialogResult );
193 }
194 
195 // ------------------------------------------------------------------------
196 // handle XFilePickerListener events
197 // ------------------------------------------------------------------------
198 void FileDialogHelper_Impl::handleFileSelectionChanged( const FilePickerEvent& )
199 {
200     if ( mbHasVersions )
201         updateVersions();
202 
203     if ( mbShowPreview )
204         maPreViewTimer.Start();
205 }
206 
207 // ------------------------------------------------------------------------
208 void FileDialogHelper_Impl::handleDirectoryChanged( const FilePickerEvent& )
209 {
210     if ( mbShowPreview )
211         TimeOutHdl_Impl( NULL );
212 }
213 
214 // ------------------------------------------------------------------------
215 OUString FileDialogHelper_Impl::handleHelpRequested( const FilePickerEvent& aEvent )
216 {
217     //!!! todo: cache the help strings (here or TRA)
218 
219     rtl::OString sHelpId;
220     // mapping from element id -> help id
221     switch ( aEvent.ElementId )
222     {
223         case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION :
224             sHelpId = HID_FILESAVE_AUTOEXTENSION;
225             break;
226 
227         case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
228             sHelpId = HID_FILESAVE_SAVEWITHPASSWORD;
229             break;
230 
231         case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
232             sHelpId = HID_FILESAVE_CUSTOMIZEFILTER;
233             break;
234 
235         case ExtendedFilePickerElementIds::CHECKBOX_READONLY :
236             sHelpId = HID_FILEOPEN_READONLY;
237             break;
238 
239         case ExtendedFilePickerElementIds::CHECKBOX_LINK :
240             sHelpId = HID_FILEDLG_LINK_CB;
241             break;
242 
243         case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW :
244             sHelpId = HID_FILEDLG_PREVIEW_CB;
245             break;
246 
247         case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY :
248             sHelpId = HID_FILESAVE_DOPLAY;
249             break;
250 
251         case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL :
252         case ExtendedFilePickerElementIds::LISTBOX_VERSION :
253             sHelpId = HID_FILEOPEN_VERSION;
254             break;
255 
256         case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL :
257         case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE :
258             sHelpId = HID_FILESAVE_TEMPLATE;
259             break;
260 
261         case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL :
262         case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE :
263             sHelpId = HID_FILEOPEN_IMAGE_TEMPLATE;
264             break;
265 
266         case ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
267             sHelpId = HID_FILESAVE_SELECTION;
268             break;
269 
270         default:
271             DBG_ERRORFILE( "invalid element id" );
272     }
273 
274     OUString aHelpText;
275     Help* pHelp = Application::GetHelp();
276     if ( pHelp )
277         aHelpText = String( pHelp->GetHelpText( String( ByteString(sHelpId), RTL_TEXTENCODING_UTF8), NULL ) );
278     return aHelpText;
279 }
280 
281 // ------------------------------------------------------------------------
282 void FileDialogHelper_Impl::handleControlStateChanged( const FilePickerEvent& aEvent )
283 {
284     switch ( aEvent.ElementId )
285     {
286         case CommonFilePickerElementIds::LISTBOX_FILTER:
287             updateFilterOptionsBox();
288             enablePasswordBox( sal_False );
289             updateSelectionBox();
290             // only use it for export and with our own dialog
291             if ( mbExport && !mbSystemPicker )
292                 updateExportButton();
293             break;
294 
295         case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW:
296             updatePreviewState();
297             break;
298     }
299 }
300 
301 // ------------------------------------------------------------------------
302 void FileDialogHelper_Impl::handleDialogSizeChanged()
303 {
304     if ( mbShowPreview )
305         TimeOutHdl_Impl( NULL );
306 }
307 
308 // ------------------------------------------------------------------------
309 // XEventListener Methods
310 // ------------------------------------------------------------------------
311 void SAL_CALL FileDialogHelper_Impl::disposing( const EventObject& ) throw ( RuntimeException )
312 {
313     ::vos::OGuard aGuard( Application::GetSolarMutex() );
314     dispose();
315 }
316 
317 // ------------------------------------------------------------------------
318 // ------------------------------------------------------------------------
319 // ------------------------------------------------------------------------
320 void FileDialogHelper_Impl::dispose()
321 {
322     if ( mxFileDlg.is() )
323     {
324         // remove the event listener
325         uno::Reference< XFilePickerNotifier > xNotifier( mxFileDlg, UNO_QUERY );
326         if ( xNotifier.is() )
327             xNotifier->removeFilePickerListener( this );
328 
329         ::comphelper::disposeComponent( mxFileDlg );
330         mxFileDlg.clear();
331     }
332 }
333 
334 // ------------------------------------------------------------------------
335 String FileDialogHelper_Impl::getCurrentFilterUIName() const
336 {
337     String aFilterName;
338     uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY );
339 
340     if( xFltMgr.is() )
341     {
342         aFilterName = xFltMgr->getCurrentFilter();
343 
344         if ( aFilterName.Len() && isShowFilterExtensionEnabled() )
345             aFilterName = getFilterName( aFilterName );
346     }
347 
348     return aFilterName;
349 }
350 
351 // ------------------------------------------------------------------------
352 void FileDialogHelper_Impl::LoadLastUsedFilter( const OUString& _rContextIdentifier )
353 {
354     SvtViewOptions aDlgOpt( E_DIALOG, IODLG_CONFIGNAME );
355 
356     if( aDlgOpt.Exists() )
357     {
358         OUString    aLastFilter;
359         if( aDlgOpt.GetUserItem( _rContextIdentifier ) >>= aLastFilter )
360             setFilter( aLastFilter );
361     }
362 }
363 
364 // ------------------------------------------------------------------------
365 void FileDialogHelper_Impl::SaveLastUsedFilter( const OUString& _rContextIdentifier )
366 {
367     SvtViewOptions( E_DIALOG, IODLG_CONFIGNAME ).SetUserItem( _rContextIdentifier,
368                         makeAny( getFilterWithExtension( getFilter() ) ) );
369 }
370 
371 // ------------------------------------------------------------------------
372 void FileDialogHelper_Impl::SaveLastUsedFilter( void )
373 {
374     const OUString* pConfigId = GetLastFilterConfigId( meContext );
375     if( pConfigId )
376         SaveLastUsedFilter( *pConfigId );
377 }
378 
379 // ------------------------------------------------------------------------
380 const SfxFilter* FileDialogHelper_Impl::getCurentSfxFilter()
381 {
382     String aFilterName = getCurrentFilterUIName();
383 
384     const SfxFilter* pFilter = NULL;
385     if ( mpMatcher && aFilterName.Len() )
386         pFilter = mpMatcher->GetFilter4UIName( aFilterName, m_nMustFlags, m_nDontFlags );
387 
388     return pFilter;
389 }
390 
391 // ------------------------------------------------------------------------
392 sal_Bool FileDialogHelper_Impl::updateExtendedControl( sal_Int16 _nExtendedControlId, sal_Bool _bEnable )
393 {
394     sal_Bool bIsEnabled = sal_False;
395 
396     uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
397     if ( xCtrlAccess.is() )
398     {
399         try
400         {
401             xCtrlAccess->enableControl( _nExtendedControlId, _bEnable );
402             bIsEnabled = _bEnable;
403         }
404         catch( const IllegalArgumentException& )
405         {
406             DBG_ERROR( "FileDialogHelper_Impl::updateExtendedControl: caught an exception!" );
407         }
408     }
409     return bIsEnabled;
410 }
411 
412 // ------------------------------------------------------------------------
413 sal_Bool FileDialogHelper_Impl::CheckFilterOptionsCapability( const SfxFilter* _pFilter )
414 {
415     sal_Bool bResult = sal_False;
416 
417     if( mxFilterCFG.is() && _pFilter )
418     {
419         try {
420             Sequence < PropertyValue > aProps;
421             Any aAny = mxFilterCFG->getByName( _pFilter->GetName() );
422             if ( aAny >>= aProps )
423             {
424                 ::rtl::OUString aServiceName;
425                 sal_Int32 nPropertyCount = aProps.getLength();
426                 for( sal_Int32 nProperty=0; nProperty < nPropertyCount; ++nProperty )
427                 {
428                     if( aProps[nProperty].Name.equals( DEFINE_CONST_OUSTRING( "UIComponent") ) )
429                     {
430                         aProps[nProperty].Value >>= aServiceName;
431                         if( aServiceName.getLength() )
432                             bResult = sal_True;
433                     }
434                 }
435             }
436         }
437         catch( Exception& )
438         {
439         }
440     }
441 
442     return bResult;
443 }
444 
445 // ------------------------------------------------------------------------
446 sal_Bool FileDialogHelper_Impl::isInOpenMode() const
447 {
448     sal_Bool bRet = sal_False;
449 
450     switch ( m_nDialogType )
451     {
452         case FILEOPEN_SIMPLE:
453         case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
454         case FILEOPEN_PLAY:
455         case FILEOPEN_READONLY_VERSION:
456         case FILEOPEN_LINK_PREVIEW:
457             bRet = sal_True;
458     }
459 
460     return bRet;
461 }
462 
463 // ------------------------------------------------------------------------
464 
465 void FileDialogHelper_Impl::updateFilterOptionsBox()
466 {
467     if ( !m_bHaveFilterOptions )
468         return;
469 
470     updateExtendedControl(
471         ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS,
472         CheckFilterOptionsCapability( getCurentSfxFilter() )
473     );
474 }
475 
476 // ------------------------------------------------------------------------
477 
478 void FileDialogHelper_Impl::updateExportButton()
479 {
480     uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
481     if ( xCtrlAccess.is() )
482     {
483         OUString sEllipses( RTL_CONSTASCII_USTRINGPARAM( "..." ) );
484         OUString sOldLabel( xCtrlAccess->getLabel( CommonFilePickerElementIds::PUSHBUTTON_OK ) );
485 
486         // initialize button label; we need the label with the mnemonic char
487         if ( !maButtonLabel.getLength() || maButtonLabel.indexOf( MNEMONIC_CHAR ) == -1 )
488         {
489             // cut the ellipses, if necessary
490             sal_Int32 nIndex = sOldLabel.indexOf( sEllipses );
491             if ( -1 == nIndex )
492                 nIndex = sOldLabel.getLength();
493             maButtonLabel = sOldLabel.copy( 0, nIndex );
494         }
495 
496         OUString sLabel = maButtonLabel;
497         // filter with options -> append ellipses on export button label
498         if ( CheckFilterOptionsCapability( getCurentSfxFilter() ) )
499             sLabel += OUString( RTL_CONSTASCII_USTRINGPARAM( "..." ) );
500 
501         if ( sOldLabel != sLabel )
502         {
503             try
504             {
505                 xCtrlAccess->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK, sLabel );
506             }
507             catch( const IllegalArgumentException& )
508             {
509                 DBG_ERRORFILE( "FileDialogHelper_Impl::updateExportButton: caught an exception!" );
510             }
511         }
512     }
513 }
514 
515 // ------------------------------------------------------------------------
516 void FileDialogHelper_Impl::updateSelectionBox()
517 {
518     if ( !mbHasSelectionBox )
519         return;
520 
521     // Does the selection box exist?
522     sal_Bool bSelectionBoxFound = sal_False;
523     uno::Reference< XControlInformation > xCtrlInfo( mxFileDlg, UNO_QUERY );
524     if ( xCtrlInfo.is() )
525     {
526         Sequence< ::rtl::OUString > aCtrlList = xCtrlInfo->getSupportedControls();
527         sal_uInt32 nCount = aCtrlList.getLength();
528         for ( sal_uInt32 nCtrl = 0; nCtrl < nCount; ++nCtrl )
529             if ( aCtrlList[ nCtrl ].equalsAscii("SelectionBox") )
530             {
531                 bSelectionBoxFound = sal_False;
532                 break;
533             }
534     }
535 
536     if ( bSelectionBoxFound )
537     {
538         const SfxFilter* pFilter = getCurentSfxFilter();
539         mbSelectionFltrEnabled = updateExtendedControl(
540             ExtendedFilePickerElementIds::CHECKBOX_SELECTION,
541             ( mbSelectionEnabled && pFilter && ( pFilter->GetFilterFlags() & SFX_FILTER_SUPPORTSSELECTION ) != 0 ) );
542         uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
543         xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0, makeAny( (sal_Bool)mbSelection ) );
544     }
545 }
546 
547 // ------------------------------------------------------------------------
548 void FileDialogHelper_Impl::enablePasswordBox( sal_Bool bInit )
549 {
550     if ( ! mbHasPassword )
551         return;
552 
553     sal_Bool bWasEnabled = mbIsPwdEnabled;
554 
555     const SfxFilter* pCurrentFilter = getCurentSfxFilter();
556     mbIsPwdEnabled = updateExtendedControl(
557         ExtendedFilePickerElementIds::CHECKBOX_PASSWORD,
558         pCurrentFilter && ( pCurrentFilter->GetFilterFlags() & SFX_FILTER_ENCRYPTION )
559     );
560 
561     if( bInit )
562     {
563         // in case of inintialization previous state is not interesting
564         if( mbIsPwdEnabled )
565         {
566             uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
567             if( mbPwdCheckBoxState )
568                 xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0, makeAny( sal_True ) );
569         }
570     }
571     else if( !bWasEnabled && mbIsPwdEnabled )
572     {
573         uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
574         if( mbPwdCheckBoxState )
575             xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0, makeAny( sal_True ) );
576     }
577     else if( bWasEnabled && !mbIsPwdEnabled )
578     {
579         // remember user settings until checkbox is enabled
580         uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
581         Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0 );
582         sal_Bool bPassWord = sal_False;
583         mbPwdCheckBoxState = ( aValue >>= bPassWord ) && bPassWord;
584         xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0, makeAny( sal_False ) );
585     }
586 }
587 
588 // ------------------------------------------------------------------------
589 void FileDialogHelper_Impl::updatePreviewState( sal_Bool _bUpdatePreviewWindow )
590 {
591     if ( mbHasPreview )
592     {
593         uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
594 
595         // check, wether or not we have to display a preview
596         if ( xCtrlAccess.is() )
597         {
598             try
599             {
600                 Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0 );
601                 sal_Bool bShowPreview = sal_False;
602 
603                 if ( aValue >>= bShowPreview )
604                 {
605                     mbShowPreview = bShowPreview;
606 
607                     // #97633
608                     // setShowState has currently no effect for the
609                     // OpenOffice FilePicker (see svtools/source/filepicker/iodlg.cxx)
610                     uno::Reference< XFilePreview > xFilePreview( mxFileDlg, UNO_QUERY );
611                     if ( xFilePreview.is() )
612                         xFilePreview->setShowState( mbShowPreview );
613 
614                     if ( _bUpdatePreviewWindow )
615                         TimeOutHdl_Impl( NULL );
616                 }
617             }
618             catch( Exception )
619             {
620                 DBG_ERRORFILE( "FileDialogHelper_Impl::updatePreviewState: caught an exception!" );
621             }
622         }
623     }
624 }
625 
626 // ------------------------------------------------------------------------
627 void FileDialogHelper_Impl::updateVersions()
628 {
629     Sequence < OUString > aEntries;
630     Sequence < OUString > aPathSeq = mxFileDlg->getFiles();
631 
632     if ( aPathSeq.getLength() == 1 )
633     {
634         INetURLObject aObj( aPathSeq[0] );
635 
636         if ( ( aObj.GetProtocol() == INET_PROT_FILE ) &&
637             ( utl::UCBContentHelper::IsDocument( aObj.GetMainURL( INetURLObject::NO_DECODE ) ) ) )
638         {
639             try
640             {
641                 uno::Reference< embed::XStorage > xStorage = ::comphelper::OStorageHelper::GetStorageFromURL(
642                                                                 aObj.GetMainURL( INetURLObject::NO_DECODE ),
643                                                                 embed::ElementModes::READ );
644 
645                 DBG_ASSERT( xStorage.is(), "The method must return the storage or throw an exception!" );
646                 if ( !xStorage.is() )
647                     throw uno::RuntimeException();
648 
649                 uno::Sequence < util::RevisionTag > xVersions = SfxMedium::GetVersionList( xStorage );
650 
651                 aEntries.realloc( xVersions.getLength() + 1 );
652                 aEntries[0] = OUString( String ( SfxResId( STR_SFX_FILEDLG_ACTUALVERSION ) ) );
653 
654                 for ( sal_Int32 i=0; i<xVersions.getLength(); i++ )
655                     aEntries[ i + 1 ] = xVersions[i].Identifier;
656 
657                 // TODO/LATER: not sure that this information must be shown in future ( binfilter? )
658 //REMOVE                    else
659 //REMOVE                    {
660 //REMOVE                        SfxFilterFlags nMust = SFX_FILTER_IMPORT | SFX_FILTER_OWN;
661 //REMOVE                        SfxFilterFlags nDont = SFX_FILTER_NOTINSTALLED | SFX_FILTER_STARONEFILTER;
662 //REMOVE                        if ( SFX_APP()->GetFilterMatcher().GetFilter4ClipBoardId( pStor->GetFormat(), nMust, nDont ) )
663 //REMOVE                        {
664 //REMOVE                            aEntries.realloc( 1 );
665 //REMOVE                            aEntries[0] = OUString( String ( SfxResId( STR_SFX_FILEDLG_ACTUALVERSION ) ) );
666 //REMOVE                        }
667 //REMOVE                    }
668             }
669             catch( uno::Exception& )
670             {
671             }
672         }
673     }
674 
675     uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY );
676     Any aValue;
677 
678     try
679     {
680         xDlg->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
681                         ControlActions::DELETE_ITEMS, aValue );
682     }
683     catch( IllegalArgumentException ){}
684 
685     sal_Int32 nCount = aEntries.getLength();
686 
687     if ( nCount )
688     {
689         try
690         {
691             aValue <<= aEntries;
692             xDlg->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
693                             ControlActions::ADD_ITEMS, aValue );
694 
695             Any aPos;
696             aPos <<= (sal_Int32) 0;
697             xDlg->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
698                             ControlActions::SET_SELECT_ITEM, aPos );
699         }
700         catch( IllegalArgumentException ){}
701     }
702 }
703 
704 // -----------------------------------------------------------------------
705 class OReleaseSolarMutex
706 {
707 private:
708     const sal_Int32 m_nAquireCount;
709 public:
710     OReleaseSolarMutex( )
711         :m_nAquireCount( Application::ReleaseSolarMutex() )
712     {
713     }
714     ~OReleaseSolarMutex( )
715     {
716         Application::AcquireSolarMutex( m_nAquireCount );
717     }
718 };
719 
720 // -----------------------------------------------------------------------
721 IMPL_LINK( FileDialogHelper_Impl, TimeOutHdl_Impl, Timer*, EMPTYARG )
722 {
723     if ( !mbHasPreview )
724         return 0;
725 
726     maGraphic.Clear();
727 
728     Any aAny;
729     uno::Reference < XFilePreview > xFilePicker( mxFileDlg, UNO_QUERY );
730 
731     if ( ! xFilePicker.is() )
732         return 0;
733 
734     Sequence < OUString > aPathSeq = mxFileDlg->getFiles();
735 
736     if ( mbShowPreview && ( aPathSeq.getLength() == 1 ) )
737     {
738         OUString    aURL = aPathSeq[0];
739 
740         if ( ERRCODE_NONE == getGraphic( aURL, maGraphic ) )
741         {
742             // #89491
743             // changed the code slightly;
744             // before: the bitmap was scaled and
745             // surrounded a white frame
746             // now: the bitmap will only be scaled
747             // and the filepicker implementation
748             // is responsible for placing it at its
749             // proper position and painting a frame
750 
751             Bitmap aBmp = maGraphic.GetBitmap();
752 
753             // scale the bitmap to the correct size
754             sal_Int32 nOutWidth  = xFilePicker->getAvailableWidth();
755             sal_Int32 nOutHeight = xFilePicker->getAvailableHeight();
756             sal_Int32 nBmpWidth  = aBmp.GetSizePixel().Width();
757             sal_Int32 nBmpHeight = aBmp.GetSizePixel().Height();
758 
759             double nXRatio = (double) nOutWidth / nBmpWidth;
760             double nYRatio = (double) nOutHeight / nBmpHeight;
761 
762             if ( nXRatio < nYRatio )
763                 aBmp.Scale( nXRatio, nXRatio );
764             else
765                 aBmp.Scale( nYRatio, nYRatio );
766 
767             // #94505# Convert to true color, to allow CopyPixel
768             aBmp.Convert( BMP_CONVERSION_24BIT );
769 
770             // and copy it into the Any
771             SvMemoryStream aData;
772 
773             aData << aBmp;
774 
775             const Sequence < sal_Int8 > aBuffer(
776                 static_cast< const sal_Int8* >(aData.GetData()),
777                 aData.GetEndOfData() );
778 
779             aAny <<= aBuffer;
780         }
781     }
782 
783     try
784     {
785         OReleaseSolarMutex aReleaseForCallback;
786         // clear the preview window
787         xFilePicker->setImage( FilePreviewImageFormats::BITMAP, aAny );
788     }
789     catch( IllegalArgumentException )
790     {
791     }
792 
793     return 0;
794 }
795 
796 // ------------------------------------------------------------------------
797 ErrCode FileDialogHelper_Impl::getGraphic( const OUString& rURL,
798                                            Graphic& rGraphic ) const
799 {
800     if ( utl::UCBContentHelper::IsFolder( rURL ) )
801         return ERRCODE_IO_NOTAFILE;
802 
803     if ( !mpGraphicFilter )
804         return ERRCODE_IO_NOTSUPPORTED;
805 
806     // select graphic filter from dialog filter selection
807     OUString aCurFilter( getFilter() );
808 
809     sal_uInt16 nFilter = aCurFilter.getLength() && mpGraphicFilter->GetImportFormatCount()
810                     ? mpGraphicFilter->GetImportFormatNumber( aCurFilter )
811                     : GRFILTER_FORMAT_DONTKNOW;
812 
813     INetURLObject aURLObj( rURL );
814 
815     if ( aURLObj.HasError() || INET_PROT_NOT_VALID == aURLObj.GetProtocol() )
816     {
817         aURLObj.SetSmartProtocol( INET_PROT_FILE );
818         aURLObj.SetSmartURL( rURL );
819     }
820 
821     ErrCode nRet = ERRCODE_NONE;
822 
823     sal_uInt32 nFilterImportFlags = GRFILTER_I_FLAGS_SET_LOGSIZE_FOR_JPEG;
824     // non-local?
825     if ( INET_PROT_FILE != aURLObj.GetProtocol() )
826     {
827         SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( rURL, STREAM_READ );
828 
829         if( pStream )
830             nRet = mpGraphicFilter->ImportGraphic( rGraphic, rURL, *pStream, nFilter, NULL, nFilterImportFlags );
831         else
832             nRet = mpGraphicFilter->ImportGraphic( rGraphic, aURLObj, nFilter, NULL, nFilterImportFlags );
833         delete pStream;
834     }
835     else
836     {
837         nRet = mpGraphicFilter->ImportGraphic( rGraphic, aURLObj, nFilter, NULL, nFilterImportFlags );
838     }
839 
840     return nRet;
841 }
842 
843 // ------------------------------------------------------------------------
844 ErrCode FileDialogHelper_Impl::getGraphic( Graphic& rGraphic ) const
845 {
846     ErrCode nRet = ERRCODE_NONE;
847 
848     if ( ! maGraphic )
849     {
850         OUString aPath;;
851         Sequence < OUString > aPathSeq = mxFileDlg->getFiles();
852 
853         if ( aPathSeq.getLength() == 1 )
854         {
855             aPath = aPathSeq[0];
856         }
857 
858         if ( aPath.getLength() )
859             nRet = getGraphic( aPath, rGraphic );
860         else
861             nRet = ERRCODE_IO_GENERAL;
862     }
863     else
864         rGraphic = maGraphic;
865 
866     return nRet;
867 }
868 
869 // ------------------------------------------------------------------------
870 sal_Bool lcl_isSystemFilePicker( const uno::Reference< XFilePicker >& _rxFP )
871 {
872     try
873     {
874         uno::Reference< XServiceInfo > xSI( _rxFP, UNO_QUERY );
875         if ( xSI.is() && xSI->supportsService( DEFINE_CONST_OUSTRING( "com.sun.star.ui.dialogs.SystemFilePicker" ) ) )
876             return sal_True;
877     }
878     catch( const Exception& )
879     {
880     }
881     return sal_False;
882 }
883 
884 
885 // ------------------------------------------------------------------------
886 // -----------      FileDialogHelper_Impl       ---------------------------
887 // ------------------------------------------------------------------------
888 
889 FileDialogHelper_Impl::FileDialogHelper_Impl(
890     FileDialogHelper* _pAntiImpl,
891     sal_Int16 nDialogType,
892     sal_Int64 nFlags,
893     sal_Int16 nDialog,
894     Window* _pPreferredParentWindow,
895     const String& sStandardDir,
896     const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList
897     )
898     :m_nDialogType          ( nDialogType )
899     ,meContext              ( FileDialogHelper::UNKNOWN_CONTEXT )
900 {
901     const char* pServiceName=0;
902     if ( nDialog == SFX2_IMPL_DIALOG_SYSTEM )
903         pServiceName = FILE_OPEN_SERVICE_NAME_OOO;
904     else if ( nDialog == SFX2_IMPL_DIALOG_OOO )
905         pServiceName = FILE_OPEN_SERVICE_NAME_OOO;
906     else
907         pServiceName = FILE_OPEN_SERVICE_NAME;
908     OUString aService = ::rtl::OUString::createFromAscii( pServiceName );
909 
910     uno::Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
911 
912     // create the file open dialog
913     // the flags can be SFXWB_INSERT or SFXWB_MULTISELECTION
914 
915     mpPreferredParentWindow = _pPreferredParentWindow;
916     mpAntiImpl              = _pAntiImpl;
917     mnError                 = ERRCODE_NONE;
918     mbHasAutoExt            = sal_False;
919     mbHasPassword           = sal_False;
920     m_bHaveFilterOptions    = sal_False;
921     mbIsPwdEnabled          = sal_True;
922     mbHasVersions           = sal_False;
923     mbHasPreview            = sal_False;
924     mbShowPreview           = sal_False;
925     mbHasLink               = sal_False;
926     mbDeleteMatcher         = sal_False;
927     mbInsert                = SFXWB_INSERT == ( nFlags & SFXWB_INSERT );
928     mbExport                = SFXWB_EXPORT == ( nFlags & SFXWB_EXPORT );
929     mbIsSaveDlg             = sal_False;
930     mbPwdCheckBoxState      = sal_False;
931     mbSelection             = sal_False;
932     mbSelectionEnabled      = sal_True;
933     mbHasSelectionBox       = sal_False;
934     mbSelectionFltrEnabled  = sal_False;
935 
936     // default settings
937     m_nDontFlags = SFX_FILTER_INTERNAL | SFX_FILTER_NOTINFILEDLG | SFX_FILTER_NOTINSTALLED;
938     if( WB_OPEN == ( nFlags & WB_OPEN ) )
939         m_nMustFlags = SFX_FILTER_IMPORT;
940     else
941         m_nMustFlags = SFX_FILTER_EXPORT;
942 
943 
944     mpMatcher = NULL;
945     mpGraphicFilter = NULL;
946     mnPostUserEventId = 0;
947 
948     // create the picker component
949     mxFileDlg = mxFileDlg.query( xFactory->createInstance( aService ) );
950     mbSystemPicker = lcl_isSystemFilePicker( mxFileDlg );
951 
952     uno::Reference< XFilePickerNotifier > xNotifier( mxFileDlg, UNO_QUERY );
953     uno::Reference< XInitialization > xInit( mxFileDlg, UNO_QUERY );
954 
955     if ( ! mxFileDlg.is() || ! xNotifier.is() )
956     {
957         mnError = ERRCODE_ABORT;
958         return;
959     }
960 
961 
962     if ( xInit.is() )
963     {
964         sal_Int16 nTemplateDescription = TemplateDescription::FILEOPEN_SIMPLE;
965 
966         switch ( m_nDialogType )
967         {
968             case FILEOPEN_SIMPLE:
969                 nTemplateDescription = TemplateDescription::FILEOPEN_SIMPLE;
970                 break;
971 
972             case FILESAVE_SIMPLE:
973                 nTemplateDescription = TemplateDescription::FILESAVE_SIMPLE;
974                 mbIsSaveDlg = sal_True;
975                 break;
976 
977             case FILESAVE_AUTOEXTENSION_PASSWORD:
978                 nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD;
979                 mbHasPassword = sal_True;
980                 mbHasAutoExt = sal_True;
981                 mbIsSaveDlg = sal_True;
982                 break;
983 
984             case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
985                 nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS;
986                 mbHasPassword = sal_True;
987 
988                 m_bHaveFilterOptions = sal_True;
989                 if( xFactory.is() )
990                 {
991                     mxFilterCFG = uno::Reference< XNameAccess >(
992                         xFactory->createInstance( DEFINE_CONST_OUSTRING( "com.sun.star.document.FilterFactory" ) ),
993                         UNO_QUERY );
994                 }
995 
996                 mbHasAutoExt = sal_True;
997                 mbIsSaveDlg = sal_True;
998                 break;
999 
1000             case FILESAVE_AUTOEXTENSION_SELECTION:
1001                 nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION;
1002                 mbHasAutoExt = sal_True;
1003                 mbIsSaveDlg = sal_True;
1004                 mbHasSelectionBox = sal_True;
1005                 if ( mbExport && !mxFilterCFG.is() && xFactory.is() )
1006                 {
1007                     mxFilterCFG = uno::Reference< XNameAccess >(
1008                         xFactory->createInstance( DEFINE_CONST_OUSTRING( "com.sun.star.document.FilterFactory" ) ),
1009                         UNO_QUERY );
1010                 }
1011                 break;
1012 
1013             case FILESAVE_AUTOEXTENSION_TEMPLATE:
1014                 nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE;
1015                 mbHasAutoExt = sal_True;
1016                 mbIsSaveDlg = sal_True;
1017                 break;
1018 
1019             case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
1020                 nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE;
1021                 mbHasPreview = sal_True;
1022                 mbHasLink = sal_True;
1023 
1024                 // aPreviewTimer
1025                 maPreViewTimer.SetTimeout( 500 );
1026                 maPreViewTimer.SetTimeoutHdl( LINK( this, FileDialogHelper_Impl, TimeOutHdl_Impl ) );
1027                 break;
1028 
1029             case FILEOPEN_PLAY:
1030                 nTemplateDescription = TemplateDescription::FILEOPEN_PLAY;
1031                 break;
1032 
1033             case FILEOPEN_READONLY_VERSION:
1034                 nTemplateDescription = TemplateDescription::FILEOPEN_READONLY_VERSION;
1035                 mbHasVersions = sal_True;
1036                 break;
1037 
1038             case FILEOPEN_LINK_PREVIEW:
1039                 nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PREVIEW;
1040                 mbHasPreview = sal_True;
1041                 mbHasLink = sal_True;
1042                 // aPreviewTimer
1043                 maPreViewTimer.SetTimeout( 500 );
1044                 maPreViewTimer.SetTimeoutHdl( LINK( this, FileDialogHelper_Impl, TimeOutHdl_Impl ) );
1045                 break;
1046 
1047             case FILESAVE_AUTOEXTENSION:
1048                 nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION;
1049                 mbHasAutoExt = sal_True;
1050                 mbIsSaveDlg = sal_True;
1051                 break;
1052 
1053             default:
1054                 DBG_ERRORFILE( "FileDialogHelper::ctor with unknown type" );
1055                 break;
1056         }
1057 
1058 
1059 
1060         //Sequence < Any > aInitArguments( mbSystemPicker || !mpPreferredParentWindow ? 1 : 3 );
1061         Sequence < Any > aInitArguments( !mpPreferredParentWindow ? 3 : 4 );
1062 
1063         // This is a hack. We currently know that the internal file picker implementation
1064         // supports the extended arguments as specified below.
1065         // TODO:
1066         // a) adjust the service description so that it includes the TemplateDescription and ParentWindow args
1067         // b) adjust the implementation of the system file picker to that it recognizes it
1068         if ( mbSystemPicker )
1069         {
1070             aInitArguments[0] <<= nTemplateDescription;
1071         }
1072         else
1073         {
1074             aInitArguments[0] <<= NamedValue(
1075                                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TemplateDescription" ) ),
1076                                     makeAny( nTemplateDescription )
1077                                 );
1078 
1079             ::rtl::OUString sStandardDirTemp = ::rtl::OUString( sStandardDir );
1080 
1081             aInitArguments[1] <<= NamedValue(
1082                                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StandardDir" ) ),
1083                                     makeAny( sStandardDirTemp )
1084                                 );
1085 
1086             aInitArguments[2] <<= NamedValue(
1087                                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BlackList" ) ),
1088                                     makeAny( rBlackList )
1089                                 );
1090 
1091 
1092             if ( mpPreferredParentWindow )
1093                 aInitArguments[3] <<= NamedValue(
1094                                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" ) ),
1095                                         makeAny( VCLUnoHelper::GetInterface( mpPreferredParentWindow ) )
1096                                     );
1097 
1098 
1099         }
1100 
1101         try
1102         {
1103             xInit->initialize( aInitArguments );
1104         }
1105         catch( const Exception& )
1106         {
1107             DBG_ERROR( "FileDialogHelper_Impl::FileDialogHelper_Impl: could not initialize the picker!" );
1108         }
1109     }
1110 
1111 
1112     // set multiselection mode
1113     if ( nFlags & SFXWB_MULTISELECTION )
1114         mxFileDlg->setMultiSelectionMode( sal_True );
1115 
1116     if ( mbHasLink )        // generate graphic filter only on demand
1117         addGraphicFilter();
1118 
1119     // Export dialog
1120     if ( mbExport )
1121     {
1122         mxFileDlg->setTitle( OUString( String( SfxResId( STR_SFX_EXPLORERFILE_EXPORT ) ) ) );
1123         try {
1124                 com::sun::star::uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY_THROW );
1125                 xCtrlAccess->enableControl( ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR, sal_True );
1126         }
1127         catch( const Exception & ) { }
1128     }
1129 
1130     // the "insert file" dialog needs another title
1131     if ( mbInsert )
1132     {
1133         mxFileDlg->setTitle( OUString( String( SfxResId( STR_SFX_EXPLORERFILE_INSERT ) ) ) );
1134         uno::Reference < XFilePickerControlAccess > xExtDlg( mxFileDlg, UNO_QUERY );
1135         if ( xExtDlg.is() )
1136         {
1137             try
1138             {
1139                 xExtDlg->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK,
1140                                    OUString( String( SfxResId( STR_SFX_EXPLORERFILE_BUTTONINSERT ) ) ) );
1141             }
1142             catch( IllegalArgumentException ){}
1143         }
1144     }
1145 
1146     // add the event listener
1147     xNotifier->addFilePickerListener( this );
1148 }
1149 
1150 // ------------------------------------------------------------------------
1151 FileDialogHelper_Impl::~FileDialogHelper_Impl()
1152 {
1153     // Remove user event if we haven't received it yet
1154     if ( mnPostUserEventId )
1155         Application::RemoveUserEvent( mnPostUserEventId );
1156     mnPostUserEventId = 0;
1157 
1158     delete mpGraphicFilter;
1159 
1160     if ( mbDeleteMatcher )
1161         delete mpMatcher;
1162 
1163     maPreViewTimer.SetTimeoutHdl( Link() );
1164 
1165     ::comphelper::disposeComponent( mxFileDlg );
1166 }
1167 
1168 #define nMagic -1
1169 
1170 class PickerThread_Impl : public ::vos::OThread
1171 {
1172     uno::Reference < XFilePicker > mxPicker;
1173     ::vos::OMutex           maMutex;
1174     virtual void SAL_CALL   run();
1175     sal_Int16               mnRet;
1176 public:
1177                             PickerThread_Impl( const uno::Reference < XFilePicker >& rPicker )
1178                             : mxPicker( rPicker ), mnRet(nMagic) {}
1179 
1180     sal_Int16               GetReturnValue()
1181                             { ::vos::OGuard aGuard( maMutex ); return mnRet; }
1182 
1183     void                    SetReturnValue( sal_Int16 aRetValue )
1184                             { ::vos::OGuard aGuard( maMutex ); mnRet = aRetValue; }
1185 };
1186 
1187 void SAL_CALL PickerThread_Impl::run()
1188 {
1189     try
1190     {
1191         sal_Int16 n = mxPicker->execute();
1192         SetReturnValue( n );
1193     }
1194     catch( RuntimeException& )
1195     {
1196         SetReturnValue( ExecutableDialogResults::CANCEL );
1197         DBG_ERRORFILE( "RuntimeException caught" );
1198     }
1199 }
1200 
1201 // ------------------------------------------------------------------------
1202 void FileDialogHelper_Impl::setControlHelpIds( const sal_Int16* _pControlId, const char** _pHelpId )
1203 {
1204     DBG_ASSERT( _pControlId && _pHelpId, "FileDialogHelper_Impl::setControlHelpIds: invalid array pointers!" );
1205     if ( !_pControlId || !_pHelpId )
1206         return;
1207 
1208     // forward these ids to the file picker
1209     try
1210     {
1211         const ::rtl::OUString sHelpIdPrefix( RTL_CONSTASCII_USTRINGPARAM( INET_HID_SCHEME ) );
1212         // the ids for the single controls
1213         uno::Reference< XFilePickerControlAccess > xControlAccess( mxFileDlg, UNO_QUERY );
1214         if ( xControlAccess.is() )
1215         {
1216             while ( *_pControlId )
1217             {
1218                 DBG_ASSERT( INetURLObject( rtl::OStringToOUString( *_pHelpId, RTL_TEXTENCODING_UTF8 ) ).GetProtocol() == INET_PROT_NOT_VALID, "Wrong HelpId!" );
1219                 ::rtl::OUString sId( sHelpIdPrefix );
1220                 sId += ::rtl::OUString( *_pHelpId, strlen( *_pHelpId ), RTL_TEXTENCODING_UTF8 );
1221                 xControlAccess->setValue( *_pControlId, ControlActions::SET_HELP_URL, makeAny( sId ) );
1222 
1223                 ++_pControlId; ++_pHelpId;
1224             }
1225         }
1226     }
1227     catch( const Exception& )
1228     {
1229         DBG_ERROR( "FileDialogHelper_Impl::setControlHelpIds: caught an exception while setting the help ids!" );
1230     }
1231 }
1232 
1233 // ------------------------------------------------------------------------
1234 IMPL_LINK( FileDialogHelper_Impl, InitControls, void*, NOTINTERESTEDIN )
1235 {
1236     (void)NOTINTERESTEDIN;
1237     mnPostUserEventId = 0;
1238     enablePasswordBox( sal_True );
1239     updateFilterOptionsBox( );
1240     updateSelectionBox( );
1241 
1242     return 0L;
1243 }
1244 
1245 // ------------------------------------------------------------------------
1246 void FileDialogHelper_Impl::preExecute()
1247 {
1248     loadConfig( );
1249     setDefaultValues( );
1250     updatePreviewState( sal_False );
1251 
1252     implInitializeFileName( );
1253     // #106079# / 2002-12-09 / fs@openoffice.org
1254 
1255 #if !(defined(MACOSX) && defined(QUARTZ)) && !defined(WNT)
1256     // allow for dialog implementations which need to be executed before they return valid values for
1257     // current filter and such
1258 
1259     // On Vista (at least SP1) it's the same as on MacOSX, the modal dialog won't let message pass
1260     // through before it returns from execution
1261     mnPostUserEventId = Application::PostUserEvent( LINK( this, FileDialogHelper_Impl, InitControls ) );
1262 #else
1263     // However, the Mac OS X implementation's pickers run modally in execute and so the event doesn't
1264     // get through in time... so we call the methods directly
1265     enablePasswordBox( sal_True );
1266     updateFilterOptionsBox( );
1267     updateSelectionBox( );
1268 #endif
1269 }
1270 
1271 // ------------------------------------------------------------------------
1272 void FileDialogHelper_Impl::postExecute( sal_Int16 _nResult )
1273 {
1274     if ( ExecutableDialogResults::CANCEL != _nResult )
1275         saveConfig();
1276 }
1277 
1278 // ------------------------------------------------------------------------
1279 void FileDialogHelper_Impl::implInitializeFileName( )
1280 {
1281     if ( maFileName.getLength() )
1282     {
1283         INetURLObject aObj( maPath );
1284         aObj.Append( maFileName );
1285 
1286         // in case we're operating as save dialog, and "auto extension" is checked,
1287         // cut the extension from the name
1288         // #106079# / 2002-12-09 / fs@openoffice.org
1289         if ( mbIsSaveDlg && mbHasAutoExt )
1290         {
1291             try
1292             {
1293                 sal_Bool bAutoExtChecked = sal_False;
1294 
1295                 uno::Reference < XFilePickerControlAccess > xControlAccess( mxFileDlg, UNO_QUERY );
1296                 if  (   xControlAccess.is()
1297                     &&  (   xControlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0 )
1298                         >>= bAutoExtChecked
1299                         )
1300                     )
1301                 {
1302                     if ( bAutoExtChecked )
1303                     {   // cut the extension
1304                         aObj.removeExtension( );
1305                         mxFileDlg->setDefaultName( aObj.GetName( INetURLObject::DECODE_WITH_CHARSET ) );
1306                     }
1307                 }
1308             }
1309             catch( const Exception& )
1310             {
1311                 DBG_ERROR( "FileDialogHelper_Impl::implInitializeFileName: could not ask for the auto-extension current-value!" );
1312             }
1313         }
1314     }
1315 }
1316 
1317 // ------------------------------------------------------------------------
1318 sal_Int16 FileDialogHelper_Impl::implDoExecute()
1319 {
1320     preExecute();
1321 
1322     sal_Int16 nRet = ExecutableDialogResults::CANCEL;
1323 
1324 //On MacOSX the native file picker has to run in the primordial thread because of drawing issues
1325 //On Linux the native gtk file picker, when backed by gnome-vfs2, needs to be run in the same
1326 //primordial thread as the ucb gnome-vfs2 provider was initialized in.
1327 /*
1328 #ifdef WNT
1329     if ( mbSystemPicker )
1330     {
1331         PickerThread_Impl* pThread = new PickerThread_Impl( mxFileDlg );
1332         pThread->create();
1333         while ( pThread->GetReturnValue() == nMagic )
1334             Application::Yield();
1335         pThread->join();
1336         nRet = pThread->GetReturnValue();
1337         delete pThread;
1338     }
1339     else
1340 #endif
1341 */
1342     {
1343         try
1344         {
1345 #ifdef WNT
1346             if ( mbSystemPicker )
1347             {
1348                 OReleaseSolarMutex aSolarMutex;
1349                 nRet = mxFileDlg->execute();
1350             }
1351             else
1352 #endif
1353             nRet = mxFileDlg->execute();
1354         }
1355         catch( const Exception& )
1356         {
1357             DBG_ERRORFILE( "FileDialogHelper_Impl::implDoExecute: caught an exception!" );
1358         }
1359     }
1360 
1361     postExecute( nRet );
1362 
1363     return nRet;
1364 }
1365 
1366 // ------------------------------------------------------------------------
1367 void FileDialogHelper_Impl::implStartExecute()
1368 {
1369     DBG_ASSERT( mxFileDlg.is(), "invalid file dialog" );
1370 
1371     preExecute();
1372 
1373     if ( mbSystemPicker )
1374     {
1375     }
1376     else
1377     {
1378         try
1379         {
1380             uno::Reference< XAsynchronousExecutableDialog > xAsyncDlg( mxFileDlg, UNO_QUERY );
1381             if ( xAsyncDlg.is() )
1382                 xAsyncDlg->startExecuteModal( this );
1383         }
1384         catch( const Exception& )
1385         {
1386             DBG_ERRORFILE( "FileDialogHelper_Impl::implDoExecute: caught an exception!" );
1387         }
1388     }
1389 }
1390 
1391 // ------------------------------------------------------------------------
1392 String FileDialogHelper_Impl::implEnsureURLExtension(const String& sURL,
1393                                                      const String& /*sExtension*/)
1394 {
1395     return sURL;
1396     /*
1397     // This feature must be active for file save/export only !
1398     if (
1399         (! mbIsSaveDlg) &&
1400         (! mbExport   )
1401         )
1402         return sURL;
1403 
1404     // no extension available (because "ALL *.*" was selected) ?
1405     // Nod idea what else should happen here .-)
1406     if (sExtension.Len() < 1)
1407         return sURL;
1408 
1409     // Some FilePicker implementations already add the right extension ...
1410     // or might be the user used the right one already ...
1411     // Dont create duplicate extension.
1412     INetURLObject aURL(sURL);
1413     if (aURL.getExtension().equals(sExtension))
1414         return sURL;
1415 
1416     // Ignore any other extension set by the user.
1417     // Make sure suitable extension is used always.
1418     // e.g. "test.bla.odt" for "ODT"
1419     ::rtl::OUStringBuffer sNewURL(256);
1420     sNewURL.append     (sURL      );
1421     sNewURL.appendAscii("."       );
1422     sNewURL.append     (sExtension);
1423     return sNewURL.makeStringAndClear();
1424     */
1425 }
1426 
1427 // ------------------------------------------------------------------------
1428 void lcl_saveLastURLs(SvStringsDtor*&                                    rpURLList ,
1429                       ::comphelper::SequenceAsVector< ::rtl::OUString >& lLastURLs )
1430 {
1431     lLastURLs.clear();
1432     sal_uInt16 c = rpURLList->Count();
1433     sal_uInt16 i = 0;
1434     for (i=0; i<c; ++i)
1435         lLastURLs.push_back(*(rpURLList->GetObject(i)));
1436 }
1437 
1438 // ------------------------------------------------------------------------
1439 void FileDialogHelper_Impl::implGetAndCacheFiles(const uno::Reference< XInterface >& xPicker  ,
1440                                                        SvStringsDtor*&               rpURLList,
1441                                                  const SfxFilter*                    pFilter  )
1442 {
1443     rpURLList = NULL;
1444 
1445     String sExtension;
1446     if (pFilter)
1447     {
1448         sExtension = pFilter->GetDefaultExtension ();
1449         sExtension.EraseAllChars( '*' );
1450         sExtension.EraseAllChars( '.' );
1451     }
1452 
1453     // a) the new way (optional!)
1454     uno::Reference< XFilePicker2 > xPickNew(xPicker, UNO_QUERY);
1455     if (xPickNew.is())
1456     {
1457                              rpURLList = new SvStringsDtor;
1458         Sequence< OUString > lFiles    = xPickNew->getSelectedFiles();
1459         ::sal_Int32          nFiles    = lFiles.getLength();
1460         for (::sal_Int32 i = 0; i < nFiles; i++)
1461         {
1462             String* pURL = new String(implEnsureURLExtension(lFiles[i], sExtension));
1463             rpURLList->Insert( pURL, rpURLList->Count() );
1464         }
1465     }
1466 
1467     // b) the olde way ... non optional.
1468     else
1469     {
1470         uno::Reference< XFilePicker > xPickOld(xPicker, UNO_QUERY_THROW);
1471         Sequence< OUString > lFiles = xPickOld->getFiles();
1472         ::sal_Int32          nFiles = lFiles.getLength();
1473         if ( nFiles == 1 )
1474         {
1475                     rpURLList = new SvStringsDtor;
1476             String* pURL      = new String(implEnsureURLExtension(lFiles[0], sExtension));
1477             rpURLList->Insert( pURL, 0 );
1478         }
1479         else
1480         if ( nFiles > 1 )
1481         {
1482             rpURLList = new SvStringsDtor;
1483 
1484             INetURLObject aPath( lFiles[0] );
1485             aPath.setFinalSlash();
1486 
1487             for (::sal_Int32 i = 1; i < nFiles; i++)
1488             {
1489                 if (i == 1)
1490                     aPath.Append( lFiles[i] );
1491                 else
1492                     aPath.setName( lFiles[i] );
1493 
1494                 String* pURL = new String(implEnsureURLExtension(aPath.GetMainURL( INetURLObject::NO_DECODE ), sExtension) );
1495                 rpURLList->Insert( pURL, rpURLList->Count() );
1496             }
1497         }
1498     }
1499 
1500     lcl_saveLastURLs(rpURLList, mlLastURLs);
1501 }
1502 
1503 // ------------------------------------------------------------------------
1504 ErrCode FileDialogHelper_Impl::execute( SvStringsDtor*& rpURLList,
1505                                         SfxItemSet *&   rpSet,
1506                                         String&         rFilter )
1507 {
1508     // rFilter is a pure output parameter, it shouldn't be used for anything else
1509     // changing this would surely break code
1510     // rpSet is in/out parameter, usually just a media-descriptor that can be changed by dialog
1511 
1512     uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
1513 
1514     // retrieves parameters from rpSet
1515     // for now only Password is used
1516     if ( rpSet )
1517     {
1518         // check password checkbox if the document had password before
1519         if( mbHasPassword )
1520         {
1521             SFX_ITEMSET_ARG( rpSet, pPassItem, SfxBoolItem, SID_PASSWORDINTERACTION, sal_False );
1522             mbPwdCheckBoxState = ( pPassItem != NULL && pPassItem->GetValue() );
1523 
1524             // in case the document has password to modify, the dialog should be shown
1525             SFX_ITEMSET_ARG( rpSet, pPassToModifyItem, SfxUnoAnyItem, SID_MODIFYPASSWORDINFO, sal_False );
1526             mbPwdCheckBoxState |= ( pPassToModifyItem && pPassToModifyItem->GetValue().hasValue() );
1527         }
1528 
1529         SFX_ITEMSET_ARG( rpSet, pSelectItem, SfxBoolItem, SID_SELECTION, sal_False );
1530         if ( pSelectItem )
1531             mbSelection = pSelectItem->GetValue();
1532         else
1533             mbSelectionEnabled = sal_False;
1534 
1535         // the password will be set in case user decide so
1536         rpSet->ClearItem( SID_PASSWORDINTERACTION );
1537         rpSet->ClearItem( SID_PASSWORD );
1538         rpSet->ClearItem( SID_ENCRYPTIONDATA );
1539         rpSet->ClearItem( SID_RECOMMENDREADONLY );
1540         rpSet->ClearItem( SID_MODIFYPASSWORDINFO );
1541 
1542     }
1543 
1544     if ( mbHasPassword && !mbPwdCheckBoxState )
1545     {
1546         SvtSecurityOptions aSecOpt;
1547         mbPwdCheckBoxState = (
1548             aSecOpt.IsOptionSet( SvtSecurityOptions::E_DOCWARN_RECOMMENDPASSWORD ) );
1549     }
1550 
1551     rpURLList = NULL;
1552 
1553     if ( ! mxFileDlg.is() )
1554         return ERRCODE_ABORT;
1555 
1556     if ( ExecutableDialogResults::CANCEL != implDoExecute() )
1557     {
1558         // create an itemset if there is no
1559         if( !rpSet )
1560             rpSet = new SfxAllItemSet( SFX_APP()->GetPool() );
1561 
1562         // the item should remain only if it was set by the dialog
1563         rpSet->ClearItem( SID_SELECTION );
1564 
1565         if( mbExport && mbHasSelectionBox )
1566         {
1567             try
1568             {
1569                 Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0 );
1570                 sal_Bool bSelection = sal_False;
1571                 if ( aValue >>= bSelection )
1572                     rpSet->Put( SfxBoolItem( SID_SELECTION, bSelection ) );
1573             }
1574             catch( IllegalArgumentException )
1575             {
1576                 DBG_ERROR( "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
1577             }
1578         }
1579 
1580 
1581         // set the read-only flag. When inserting a file, this flag is always set
1582         if ( mbInsert )
1583             rpSet->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
1584         else
1585         {
1586             if ( ( FILEOPEN_READONLY_VERSION == m_nDialogType ) && xCtrlAccess.is() )
1587             {
1588                 try
1589                 {
1590                     Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 );
1591                     sal_Bool bReadOnly = sal_False;
1592                     if ( ( aValue >>= bReadOnly ) && bReadOnly )
1593                         rpSet->Put( SfxBoolItem( SID_DOC_READONLY, bReadOnly ) );
1594                 }
1595                 catch( IllegalArgumentException )
1596                 {
1597                     DBG_ERROR( "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
1598                 }
1599             }
1600         }
1601         if ( mbHasVersions && xCtrlAccess.is() )
1602         {
1603             try
1604             {
1605                 Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
1606                                                     ControlActions::GET_SELECTED_ITEM_INDEX );
1607                 sal_Int32 nVersion = 0;
1608                 if ( ( aValue >>= nVersion ) && nVersion > 0 )
1609                     // open a special version; 0 == current version
1610                     rpSet->Put( SfxInt16Item( SID_VERSION, (short)nVersion ) );
1611             }
1612             catch( IllegalArgumentException ){}
1613         }
1614 
1615         // set the filter
1616         getRealFilter( rFilter );
1617 
1618         const SfxFilter* pCurrentFilter = getCurentSfxFilter();
1619 
1620         // fill the rpURLList
1621         implGetAndCacheFiles( mxFileDlg, rpURLList, pCurrentFilter );
1622         if ( rpURLList == NULL || rpURLList->GetObject(0) == NULL )
1623             return ERRCODE_ABORT;
1624 
1625         // check, wether or not we have to display a password box
1626         if ( pCurrentFilter && mbHasPassword && mbIsPwdEnabled && xCtrlAccess.is() )
1627         {
1628             try
1629             {
1630                 Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0 );
1631                 sal_Bool bPassWord = sal_False;
1632                 if ( ( aValue >>= bPassWord ) && bPassWord )
1633                 {
1634                     // ask for a password
1635                     uno::Reference < ::com::sun::star::task::XInteractionHandler > xInteractionHandler( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.comp.uui.UUIInteractionHandler")), UNO_QUERY );
1636 
1637                     if( xInteractionHandler.is() )
1638                     {
1639                         // TODO: need a save way to distinguish MS filters from other filters
1640                         // for now MS-filters are the only alien filters that support encryption
1641                         sal_Bool bMSType = !pCurrentFilter->IsOwnFormat();
1642                         ::comphelper::DocPasswordRequestType eType = bMSType ?
1643                             ::comphelper::DocPasswordRequestType_MS :
1644                             ::comphelper::DocPasswordRequestType_STANDARD;
1645 
1646                         ::rtl::Reference< ::comphelper::DocPasswordRequest > pPasswordRequest( new ::comphelper::DocPasswordRequest( eType, ::com::sun::star::task::PasswordRequestMode_PASSWORD_CREATE, *(rpURLList->GetObject(0)), ( pCurrentFilter->GetFilterFlags() & SFX_FILTER_PASSWORDTOMODIFY ) != 0 ) );
1647 
1648                         uno::Reference< com::sun::star::task::XInteractionRequest > rRequest( pPasswordRequest.get() );
1649                         xInteractionHandler->handle( rRequest );
1650                         if ( pPasswordRequest->isPassword() )
1651                         {
1652                             if ( pPasswordRequest->getPassword().getLength() )
1653                             {
1654                                 // TODO/LATER: The filters should show the password dialog themself in future
1655                                 if ( bMSType )
1656                                 {
1657                                     // all the current MS-filters use MSCodec_Std97 implementation
1658                                     uno::Sequence< sal_Int8 > aUniqueID = ::comphelper::DocPasswordHelper::GenerateRandomByteSequence( 16 );
1659                                     uno::Sequence< sal_Int8 > aEncryptionKey = ::comphelper::DocPasswordHelper::GenerateStd97Key( pPasswordRequest->getPassword(), aUniqueID );
1660 
1661                                     if ( aEncryptionKey.getLength() )
1662                                     {
1663                                         ::comphelper::SequenceAsHashMap aHashData;
1664                                         aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97EncryptionKey" ) ) ] <<= aEncryptionKey;
1665                                         aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97UniqueID" ) ) ] <<= aUniqueID;
1666 
1667                                         rpSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aHashData.getAsConstNamedValueList() ) ) );
1668                                     }
1669                                     else
1670                                         return ERRCODE_IO_NOTSUPPORTED;
1671                                 }
1672                                 else
1673                                 {
1674                                     rpSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( ::comphelper::OStorageHelper::CreatePackageEncryptionData( pPasswordRequest->getPassword() ) ) ) );
1675                                 }
1676                             }
1677 
1678                             if ( pPasswordRequest->getRecommendReadOnly() )
1679                                 rpSet->Put( SfxBoolItem( SID_RECOMMENDREADONLY, sal_True ) );
1680 
1681                             if ( bMSType )
1682                             {
1683                                 // the empty password has 0 as Hash
1684                                 sal_Int32 nHash = SfxMedium::CreatePasswordToModifyHash( pPasswordRequest->getPasswordToModify(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" ) ).equals( pCurrentFilter->GetServiceName() ) );
1685                                 if ( nHash )
1686                                     rpSet->Put( SfxUnoAnyItem( SID_MODIFYPASSWORDINFO, uno::makeAny( nHash ) ) );
1687                             }
1688                             else
1689                             {
1690                                 uno::Sequence< beans::PropertyValue > aModifyPasswordInfo = ::comphelper::DocPasswordHelper::GenerateNewModifyPasswordInfo( pPasswordRequest->getPasswordToModify() );
1691                                 if ( aModifyPasswordInfo.getLength() )
1692                                     rpSet->Put( SfxUnoAnyItem( SID_MODIFYPASSWORDINFO, uno::makeAny( aModifyPasswordInfo ) ) );
1693                             }
1694                         }
1695                         else
1696                             return ERRCODE_ABORT;
1697                     }
1698                 }
1699             }
1700             catch( IllegalArgumentException ){}
1701         }
1702 
1703         SaveLastUsedFilter();
1704         return ERRCODE_NONE;
1705     }
1706     else
1707         return ERRCODE_ABORT;
1708 }
1709 
1710 // ------------------------------------------------------------------------
1711 ErrCode FileDialogHelper_Impl::execute()
1712 {
1713     if ( ! mxFileDlg.is() )
1714         return ERRCODE_ABORT;
1715 
1716     sal_Int16 nRet = implDoExecute();
1717 
1718     maPath = mxFileDlg->getDisplayDirectory();
1719 
1720     if ( ExecutableDialogResults::CANCEL == nRet )
1721         return ERRCODE_ABORT;
1722     else
1723     {
1724         return ERRCODE_NONE;
1725     }
1726 }
1727 
1728 // ------------------------------------------------------------------------
1729 OUString FileDialogHelper_Impl::getPath() const
1730 {
1731     OUString aPath;
1732 
1733     if ( mxFileDlg.is() )
1734         aPath = mxFileDlg->getDisplayDirectory();
1735 
1736     if ( !aPath.getLength() )
1737         aPath = maPath;
1738 
1739     return aPath;
1740 }
1741 
1742 // ------------------------------------------------------------------------
1743 OUString FileDialogHelper_Impl::getFilter() const
1744 {
1745     String aFilter = getCurrentFilterUIName();
1746 
1747     if( !aFilter.Len() )
1748         aFilter = maCurFilter;
1749 
1750     return aFilter;
1751 }
1752 
1753 // ------------------------------------------------------------------------
1754 void FileDialogHelper_Impl::getRealFilter( String& _rFilter ) const
1755 {
1756     _rFilter = getCurrentFilterUIName();
1757 
1758     if ( !_rFilter.Len() )
1759         _rFilter = maCurFilter;
1760 
1761     if ( _rFilter.Len() && mpMatcher )
1762     {
1763         const SfxFilter* pFilter =
1764             mpMatcher->GetFilter4UIName( _rFilter, m_nMustFlags, m_nDontFlags );
1765         _rFilter = pFilter ? pFilter->GetFilterName() : _rFilter.Erase();
1766     }
1767 }
1768 
1769 // ------------------------------------------------------------------------
1770 void FileDialogHelper_Impl::displayFolder( const ::rtl::OUString& _rPath )
1771 {
1772     if ( ! _rPath.getLength() )
1773         // nothing to do
1774         return;
1775 
1776     /*
1777     if ( !::utl::UCBContentHelper::IsFolder( _rPath ) )
1778         // only valid folders accepted here
1779         return;
1780     */
1781 
1782     maPath = _rPath;
1783     if ( mxFileDlg.is() )
1784     {
1785         try
1786         {
1787             mxFileDlg->setDisplayDirectory( maPath );
1788         }
1789         catch( const IllegalArgumentException& )
1790         {
1791             DBG_ERROR( "FileDialogHelper_Impl::displayFolder: caught an exception!" );
1792         }
1793     }
1794 }
1795 
1796 // ------------------------------------------------------------------------
1797 void FileDialogHelper_Impl::setFileName( const ::rtl::OUString& _rFile )
1798 {
1799     maFileName = _rFile;
1800     if ( mxFileDlg.is() )
1801     {
1802         try
1803         {
1804             mxFileDlg->setDefaultName( maFileName );
1805         }
1806         catch( const IllegalArgumentException& )
1807         {
1808             DBG_ERROR( "FileDialogHelper_Impl::setFileName: caught an exception!" );
1809         }
1810     }
1811 }
1812 
1813 // ------------------------------------------------------------------------
1814 void FileDialogHelper_Impl::setFilter( const OUString& rFilter )
1815 {
1816     DBG_ASSERT( rFilter.indexOf(':') == -1, "Old filter name used!");
1817 
1818     maCurFilter = rFilter;
1819 
1820     if ( rFilter.getLength() && mpMatcher )
1821     {
1822         const SfxFilter* pFilter = mpMatcher->GetFilter4FilterName(
1823                                         rFilter, m_nMustFlags, m_nDontFlags );
1824         if ( pFilter )
1825             maCurFilter = pFilter->GetUIName();
1826     }
1827 
1828     uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY );
1829 
1830     if ( maCurFilter.getLength() && xFltMgr.is() )
1831     {
1832         try
1833         {
1834             xFltMgr->setCurrentFilter( maCurFilter );
1835         }
1836         catch( IllegalArgumentException ){}
1837     }
1838 }
1839 
1840 // ------------------------------------------------------------------------
1841 void FileDialogHelper_Impl::createMatcher( const String& rFactory )
1842 {
1843     mpMatcher = new SfxFilterMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory) );
1844     mbDeleteMatcher = sal_True;
1845 }
1846 
1847 // ------------------------------------------------------------------------
1848 void FileDialogHelper_Impl::addFilters( sal_Int64 nFlags,
1849                                         const String& rFactory,
1850                                         SfxFilterFlags nMust,
1851                                         SfxFilterFlags nDont )
1852 {
1853     uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY );
1854 
1855     if ( ! xFltMgr.is() )
1856         return;
1857 
1858     // we still need a matcher to convert UI names to filter names
1859     if ( !rFactory.Len() )
1860     {
1861         SfxApplication *pSfxApp = SFX_APP();
1862         mpMatcher = &pSfxApp->GetFilterMatcher();
1863         mbDeleteMatcher = sal_False;
1864     }
1865     else
1866     {
1867         mpMatcher = new SfxFilterMatcher( rFactory );
1868         mbDeleteMatcher = sal_True;
1869     }
1870 
1871     uno::Reference< XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
1872     uno::Reference< XContainerQuery > xFilterCont(
1873         xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.document.FilterFactory")),
1874         UNO_QUERY);
1875     if ( ! xFilterCont.is() )
1876         return;
1877 
1878     m_nMustFlags |= nMust;
1879     m_nDontFlags |= nDont;
1880 
1881     // create the list of filters
1882     ::rtl::OUStringBuffer sQuery(256);
1883     sQuery.appendAscii("getSortedFilterList()");
1884     sQuery.appendAscii(":module="                                       );
1885     sQuery.append     (rFactory                                         ); // use long name here !
1886     sQuery.appendAscii(":iflags="                                       );
1887     sQuery.append     (::rtl::OUString::valueOf((sal_Int32)m_nMustFlags));
1888     sQuery.appendAscii(":eflags="                                       );
1889     sQuery.append     (::rtl::OUString::valueOf((sal_Int32)m_nDontFlags));
1890 
1891     uno::Reference< XEnumeration > xResult;
1892     try
1893     {
1894         xResult = xFilterCont->createSubSetEnumerationByQuery(sQuery.makeStringAndClear());
1895     }
1896     catch( uno::Exception& )
1897     {
1898         DBG_ERRORFILE( "Could not get filters from the configuration!" );
1899     }
1900 
1901     TSortedFilterList         aIter   (xResult);
1902 
1903     // no matcher any longer used ...
1904     mbDeleteMatcher = sal_False;
1905 
1906     // append the filters
1907     ::rtl::OUString sFirstFilter;
1908     if ( WB_OPEN == ( nFlags & WB_OPEN ) )
1909         ::sfx2::appendFiltersForOpen( aIter, xFltMgr, sFirstFilter, *this );
1910     else if ( mbExport )
1911         ::sfx2::appendExportFilters( aIter, xFltMgr, sFirstFilter, *this );
1912     else
1913         ::sfx2::appendFiltersForSave( aIter, xFltMgr, sFirstFilter, *this, rFactory );
1914 
1915     // set our initial selected filter (if we do not already have one)
1916     if ( !maSelectFilter.getLength() )
1917         maSelectFilter = sFirstFilter;
1918 }
1919 
1920 // ------------------------------------------------------------------------
1921 void FileDialogHelper_Impl::addFilter( const OUString& rFilterName,
1922                                        const OUString& rExtension )
1923 {
1924     uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY );
1925 
1926     if ( ! xFltMgr.is() )
1927         return;
1928 
1929     try
1930     {
1931         xFltMgr->appendFilter( rFilterName, rExtension );
1932 
1933         if ( !maSelectFilter.getLength() )
1934             maSelectFilter = rFilterName;
1935     }
1936     catch( IllegalArgumentException )
1937     {
1938 #ifdef DBG_UTIL
1939         ByteString aMsg( "Could not append Filter" );
1940         aMsg += ByteString( String( rFilterName ), RTL_TEXTENCODING_UTF8 );
1941         DBG_ERRORFILE( aMsg.GetBuffer() );
1942 #endif
1943     }
1944 }
1945 
1946 // ------------------------------------------------------------------------
1947 void FileDialogHelper_Impl::addGraphicFilter()
1948 {
1949     uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY );
1950 
1951     if ( ! xFltMgr.is() )
1952         return;
1953 
1954     // create the list of filters
1955     mpGraphicFilter = new GraphicFilter;
1956     sal_uInt16 i, j, nCount = mpGraphicFilter->GetImportFormatCount();
1957 
1958     // compute the extension string for all known import filters
1959     String aExtensions;
1960 
1961     for ( i = 0; i < nCount; i++ )
1962     {
1963         j = 0;
1964         String sWildcard;
1965         while( sal_True )
1966         {
1967             sWildcard = mpGraphicFilter->GetImportWildcard( i, j++ );
1968             if ( !sWildcard.Len() )
1969                 break;
1970             if ( aExtensions.Search( sWildcard ) == STRING_NOTFOUND )
1971             {
1972                 if ( aExtensions.Len() )
1973                     aExtensions += sal_Unicode(';');
1974                 aExtensions += sWildcard;
1975             }
1976         }
1977     }
1978 
1979 #if defined(WNT)
1980     if ( aExtensions.Len() > 240 )
1981         aExtensions = DEFINE_CONST_UNICODE( FILEDIALOG_FILTER_ALL );
1982 #endif
1983     sal_Bool bIsInOpenMode = isInOpenMode();
1984 
1985     try
1986     {
1987         OUString aAllFilterName = String( SfxResId( STR_SFX_IMPORT_ALL ) );
1988         aAllFilterName = ::sfx2::addExtension( aAllFilterName, aExtensions, bIsInOpenMode, *this );
1989 
1990         xFltMgr->appendFilter( aAllFilterName, aExtensions );
1991         maSelectFilter = aAllFilterName;
1992     }
1993     catch( IllegalArgumentException )
1994     {
1995         DBG_ERRORFILE( "Could not append Filter" );
1996     }
1997 
1998     // Now add the filter
1999     for ( i = 0; i < nCount; i++ )
2000     {
2001         String aName = mpGraphicFilter->GetImportFormatName( i );
2002         String aExt;
2003         j = 0;
2004         String sWildcard;
2005         while( sal_True )
2006         {
2007             sWildcard = mpGraphicFilter->GetImportWildcard( i, j++ );
2008             if ( !sWildcard.Len() )
2009                 break;
2010             if ( aExt.Search( sWildcard ) == STRING_NOTFOUND )
2011             {
2012                 if ( aExt.Len() )
2013                     aExt += sal_Unicode(';');
2014                 aExt += sWildcard;
2015             }
2016         }
2017         aName = ::sfx2::addExtension( aName, aExt, bIsInOpenMode, *this );
2018         try
2019         {
2020             xFltMgr->appendFilter( aName, aExt );
2021         }
2022         catch( IllegalArgumentException )
2023         {
2024             DBG_ERRORFILE( "Could not append Filter" );
2025         }
2026     }
2027 }
2028 
2029 // ------------------------------------------------------------------------
2030 #define GRF_CONFIG_STR      "   "
2031 #define STD_CONFIG_STR      "1 "
2032 
2033 void FileDialogHelper_Impl::saveConfig()
2034 {
2035     uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY );
2036     Any aValue;
2037 
2038     if ( ! xDlg.is() )
2039         return;
2040 
2041     if ( mbHasPreview )
2042     {
2043         SvtViewOptions aDlgOpt( E_DIALOG, IMPGRF_CONFIGNAME );
2044         String aUserData = DEFINE_CONST_UNICODE( GRF_CONFIG_STR );
2045 
2046         try
2047         {
2048             aValue = xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0 );
2049             sal_Bool bValue = sal_False;
2050             aValue >>= bValue;
2051             aUserData.SetToken( 0, ' ', String::CreateFromInt32( (sal_Int32) bValue ) );
2052 
2053             aValue = xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0 );
2054             bValue = sal_False;
2055             aValue >>= bValue;
2056             aUserData.SetToken( 1, ' ', String::CreateFromInt32( (sal_Int32) bValue ) );
2057 
2058             INetURLObject aObj( getPath() );
2059 
2060             if ( aObj.GetProtocol() == INET_PROT_FILE )
2061                 aUserData.SetToken( 2, ' ', aObj.GetMainURL( INetURLObject::NO_DECODE ) );
2062 
2063             String aFilter = getFilter();
2064             aFilter = EncodeSpaces_Impl( aFilter );
2065             aUserData.SetToken( 3, ' ', aFilter );
2066 
2067             aDlgOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aUserData ) ) );
2068         }
2069         catch( IllegalArgumentException ){}
2070     }
2071     else
2072     {
2073         sal_Bool bWriteConfig = sal_False;
2074         SvtViewOptions aDlgOpt( E_DIALOG, IODLG_CONFIGNAME );
2075         String aUserData = DEFINE_CONST_UNICODE( STD_CONFIG_STR );
2076 
2077         if ( aDlgOpt.Exists() )
2078         {
2079             Any aUserItem = aDlgOpt.GetUserItem( USERITEM_NAME );
2080             OUString aTemp;
2081             if ( aUserItem >>= aTemp )
2082                 aUserData = String( aTemp );
2083         }
2084 
2085         if ( mbHasAutoExt )
2086         {
2087             try
2088             {
2089                 aValue = xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0 );
2090                 sal_Bool bAutoExt = sal_True;
2091                 aValue >>= bAutoExt;
2092                 aUserData.SetToken( 0, ' ', String::CreateFromInt32( (sal_Int32) bAutoExt ) );
2093                 bWriteConfig = sal_True;
2094             }
2095             catch( IllegalArgumentException ){}
2096         }
2097 
2098         if ( ! mbIsSaveDlg )
2099         {
2100             OUString aPath = getPath();
2101             if ( aPath.getLength() &&
2102                  utl::LocalFileHelper::IsLocalFile( aPath ) )
2103             {
2104                 aUserData.SetToken( 1, ' ', aPath );
2105                 bWriteConfig = sal_True;
2106             }
2107         }
2108 
2109         if( mbHasSelectionBox && mbSelectionFltrEnabled )
2110         {
2111             try
2112             {
2113                 aValue = xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0 );
2114                 sal_Bool bSelection = sal_True;
2115                 aValue >>= bSelection;
2116                 if ( aUserData.GetTokenCount(' ') < 3 )
2117                     aUserData.Append(' ');
2118                 aUserData.SetToken( 2, ' ', String::CreateFromInt32( (sal_Int32) bSelection ) );
2119                 bWriteConfig = sal_True;
2120             }
2121             catch( IllegalArgumentException ){}
2122         }
2123 
2124         if ( bWriteConfig )
2125             aDlgOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aUserData ) ) );
2126     }
2127 
2128     SfxApplication *pSfxApp = SFX_APP();
2129     pSfxApp->SetLastDir_Impl( getPath() );
2130 }
2131 
2132 // ------------------------------------------------------------------------
2133 namespace
2134 {
2135     static ::rtl::OUString getInitPath( const String& _rFallback, const xub_StrLen _nFallbackToken )
2136     {
2137         SfxApplication *pSfxApp = SFX_APP();
2138         String sPath = pSfxApp->GetLastDir_Impl();
2139 
2140         if ( !sPath.Len() )
2141             sPath = _rFallback.GetToken( _nFallbackToken, ' ' );
2142 
2143         // check if the path points to a valid (accessible) directory
2144         sal_Bool bValid = sal_False;
2145         if ( sPath.Len() )
2146         {
2147             String sPathCheck( sPath );
2148             if ( sPathCheck.GetBuffer()[ sPathCheck.Len() - 1 ] != '/' )
2149                 sPathCheck += '/';
2150             sPathCheck += '.';
2151             try
2152             {
2153                 ::ucbhelper::Content aContent( sPathCheck, uno::Reference< ucb::XCommandEnvironment >() );
2154                 bValid = aContent.isFolder();
2155             }
2156             catch( Exception& ) {}
2157         }
2158 
2159         if ( !bValid )
2160             sPath.Erase();
2161 
2162         return sPath;
2163     }
2164 }
2165 
2166 // ------------------------------------------------------------------------
2167 void FileDialogHelper_Impl::loadConfig()
2168 {
2169     uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY );
2170     Any aValue;
2171 
2172     if ( ! xDlg.is() )
2173         return;
2174 
2175     if ( mbHasPreview )
2176     {
2177         SvtViewOptions aViewOpt( E_DIALOG, IMPGRF_CONFIGNAME );
2178         String aUserData;
2179 
2180         if ( aViewOpt.Exists() )
2181         {
2182             Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME );
2183             OUString aTemp;
2184             if ( aUserItem >>= aTemp )
2185                 aUserData = String( aTemp );
2186         }
2187 
2188         if ( aUserData.Len() > 0 )
2189         {
2190             try
2191             {
2192                 // respect the last "insert as link" state
2193                 sal_Bool bLink = (sal_Bool) aUserData.GetToken( 0, ' ' ).ToInt32();
2194                 aValue <<= bLink;
2195                 xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, aValue );
2196 
2197                 // respect the last "show preview" state
2198                 sal_Bool bShowPreview = (sal_Bool) aUserData.GetToken( 1, ' ' ).ToInt32();
2199                 aValue <<= bShowPreview;
2200                 xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0, aValue );
2201 
2202                 if ( !maPath.getLength() )
2203                     displayFolder( getInitPath( aUserData, 2 ) );
2204 
2205                 if ( ! maCurFilter.getLength() )
2206                 {
2207                     String aFilter = aUserData.GetToken( 3, ' ' );
2208                     aFilter = DecodeSpaces_Impl( aFilter );
2209                     setFilter( aFilter );
2210                 }
2211 
2212                 // set the member so we know that we have to show the preview
2213                 mbShowPreview = bShowPreview;
2214             }
2215             catch( IllegalArgumentException ){}
2216         }
2217 
2218         if ( !maPath.getLength() )
2219             displayFolder( SvtPathOptions().GetGraphicPath() );
2220     }
2221     else
2222     {
2223         SvtViewOptions aViewOpt( E_DIALOG, IODLG_CONFIGNAME );
2224         String aUserData;
2225 
2226         if ( aViewOpt.Exists() )
2227         {
2228             Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME );
2229             OUString aTemp;
2230             if ( aUserItem >>= aTemp )
2231                 aUserData = String( aTemp );
2232         }
2233 
2234         if ( ! aUserData.Len() )
2235             aUserData = DEFINE_CONST_UNICODE( STD_CONFIG_STR );
2236 
2237         if ( ! maPath.getLength() )
2238             displayFolder( getInitPath( aUserData, 1 ) );
2239 
2240         if ( mbHasAutoExt )
2241         {
2242             sal_Int32 nFlag = aUserData.GetToken( 0, ' ' ).ToInt32();
2243             aValue <<= (sal_Bool) nFlag;
2244             try
2245             {
2246                 xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, aValue );
2247             }
2248             catch( IllegalArgumentException ){}
2249         }
2250 
2251         if( mbHasSelectionBox )
2252         {
2253             sal_Int32 nFlag = aUserData.GetToken( 2, ' ' ).ToInt32();
2254             aValue <<= (sal_Bool) nFlag;
2255             try
2256             {
2257                 xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0, aValue );
2258             }
2259             catch( IllegalArgumentException ){}
2260         }
2261 
2262         if ( !maPath.getLength() )
2263             displayFolder( SvtPathOptions().GetWorkPath() );
2264     }
2265 }
2266 
2267 // ------------------------------------------------------------------------
2268 void FileDialogHelper_Impl::setDefaultValues()
2269 {
2270     // when no filter is set, we set the curentFilter to <all>
2271     if ( !maCurFilter.getLength() && maSelectFilter.getLength() )
2272     {
2273         uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY );
2274         try
2275         {
2276             xFltMgr->setCurrentFilter( maSelectFilter );
2277         }
2278         catch( IllegalArgumentException )
2279         {}
2280     }
2281 
2282     // when no path is set, we use the standard 'work' folder
2283     if ( ! maPath.getLength() )
2284     {
2285         OUString aWorkFolder = SvtPathOptions().GetWorkPath();
2286         try
2287         {
2288             mxFileDlg->setDisplayDirectory( aWorkFolder );
2289         }
2290         catch( const Exception& )
2291         {
2292             DBG_ERROR( "FileDialogHelper_Impl::setDefaultValues: caught an exception while setting the display directory!" );
2293         }
2294 
2295         // INetURLObject aStdDirObj( SvtPathOptions().GetWorkPath() );
2296         //SetStandardDir( aStdDirObj.GetMainURL( INetURLObject::NO_DECODE ) );
2297     }
2298 }
2299 
2300 sal_Bool FileDialogHelper_Impl::isShowFilterExtensionEnabled() const
2301 {
2302     return !maFilters.empty();
2303 }
2304 
2305 void FileDialogHelper_Impl::addFilterPair( const OUString& rFilter,
2306                                            const OUString& rFilterWithExtension )
2307 {
2308     maFilters.push_back( FilterPair( rFilter, rFilterWithExtension ) );
2309 
2310 }
2311 
2312 OUString FileDialogHelper_Impl::getFilterName( const OUString& rFilterWithExtension ) const
2313 {
2314     OUString sRet;
2315     for( ::std::vector< FilterPair >::const_iterator pIter = maFilters.begin(); pIter != maFilters.end(); ++pIter )
2316     {
2317         if ( (*pIter).Second == rFilterWithExtension )
2318         {
2319             sRet = (*pIter).First;
2320             break;
2321         }
2322     }
2323     return sRet;
2324 }
2325 
2326 OUString FileDialogHelper_Impl::getFilterWithExtension( const OUString& rFilter ) const
2327 {
2328     OUString sRet;
2329     for( ::std::vector< FilterPair >::const_iterator pIter = maFilters.begin(); pIter != maFilters.end(); ++pIter )
2330     {
2331         if ( (*pIter).First == rFilter )
2332         {
2333             sRet = (*pIter).Second;
2334             break;
2335         }
2336     }
2337     return sRet;
2338 }
2339 
2340 void FileDialogHelper_Impl::SetContext( FileDialogHelper::Context _eNewContext )
2341 {
2342     meContext = _eNewContext;
2343 
2344     sal_Int32       nNewHelpId = 0;
2345     OUString        aConfigId;
2346 
2347     switch( _eNewContext )
2348     {
2349 // #104952# dependency to SVX not allowed! When used again, another solution has to be found
2350 //      case FileDialogHelper::SW_INSERT_GRAPHIC:
2351 //      case FileDialogHelper::SC_INSERT_GRAPHIC:
2352 //      case FileDialogHelper::SD_INSERT_GRAPHIC:       nNewHelpId = SID_INSERT_GRAPHIC;        break;
2353         case FileDialogHelper::SW_INSERT_SOUND:
2354         case FileDialogHelper::SC_INSERT_SOUND:
2355         case FileDialogHelper::SD_INSERT_SOUND:         nNewHelpId = SID_INSERT_SOUND;          break;
2356         case FileDialogHelper::SW_INSERT_VIDEO:
2357         case FileDialogHelper::SC_INSERT_VIDEO:
2358         case FileDialogHelper::SD_INSERT_VIDEO:         nNewHelpId = SID_INSERT_VIDEO;          break;
2359               default: break;
2360     }
2361 
2362     const OUString* pConfigId = GetLastFilterConfigId( _eNewContext );
2363     if( pConfigId )
2364         LoadLastUsedFilter( *pConfigId );
2365 }
2366 
2367 // ------------------------------------------------------------------------
2368 // -----------          FileDialogHelper        ---------------------------
2369 // ------------------------------------------------------------------------
2370 
2371 FileDialogHelper::FileDialogHelper(
2372     sal_Int64 nFlags,
2373     const String& rFact,
2374     SfxFilterFlags nMust,
2375     SfxFilterFlags nDont )
2376 {
2377     mpImp = new FileDialogHelper_Impl( this, getDialogType( nFlags ), nFlags );
2378     mxImp = mpImp;
2379 
2380     // create the list of filters
2381     mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont );
2382 }
2383 
2384 FileDialogHelper::FileDialogHelper(
2385     sal_Int64 nFlags,
2386     const String& rFact,
2387     sal_Int16 nDialog,
2388     SfxFilterFlags nMust,
2389     SfxFilterFlags nDont,
2390     const String& rStandardDir,
2391     const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList)
2392 {
2393     mpImp = new FileDialogHelper_Impl( this, getDialogType( nFlags ), nFlags, nDialog, NULL , rStandardDir, rBlackList );
2394     mxImp = mpImp;
2395 
2396     // create the list of filters
2397     mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont );
2398 }
2399 
2400 FileDialogHelper::FileDialogHelper(
2401     sal_Int64 nFlags,
2402     const String& rFact,
2403     sal_Int16 nDialog,
2404     SfxFilterFlags nMust,
2405     SfxFilterFlags nDont )
2406 {
2407     mpImp = new FileDialogHelper_Impl( this, getDialogType( nFlags ), nFlags, nDialog );
2408     mxImp = mpImp;
2409 
2410     // create the list of filters
2411     mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont );
2412 }
2413 
2414 // ------------------------------------------------------------------------
2415 FileDialogHelper::FileDialogHelper( sal_Int64 nFlags )
2416 {
2417     sal_Int16 nDialogType = getDialogType( nFlags );
2418 
2419     mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags );
2420     mxImp = mpImp;
2421 }
2422 
2423 // ------------------------------------------------------------------------
2424 FileDialogHelper::FileDialogHelper(
2425     sal_Int16 nDialogType,
2426     sal_Int64 nFlags,
2427     const String& rFact,
2428     SfxFilterFlags nMust,
2429     SfxFilterFlags nDont )
2430 {
2431     mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags );
2432     mxImp = mpImp;
2433 
2434     // create the list of filters
2435     mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont );
2436 }
2437 
2438 // ------------------------------------------------------------------------
2439 FileDialogHelper::FileDialogHelper(
2440     sal_Int16 nDialogType,
2441     sal_Int64 nFlags,
2442     const String& rFact,
2443     sal_Int16 nDialog,
2444     SfxFilterFlags nMust,
2445     SfxFilterFlags nDont,
2446     const String& rStandardDir,
2447     const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList)
2448 {
2449     mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags, nDialog, NULL, rStandardDir, rBlackList );
2450     mxImp = mpImp;
2451 
2452     // create the list of filters
2453     mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont );
2454 }
2455 
2456 // ------------------------------------------------------------------------
2457 FileDialogHelper::FileDialogHelper(
2458     sal_Int16 nDialogType,
2459     sal_Int64 nFlags,
2460     Window* _pPreferredParent )
2461 {
2462     mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags, SFX2_IMPL_DIALOG_CONFIG, _pPreferredParent );
2463     mxImp = mpImp;
2464 }
2465 
2466 // ------------------------------------------------------------------------
2467 FileDialogHelper::FileDialogHelper(
2468     sal_Int16 nDialogType,
2469     sal_Int64 nFlags,
2470     const ::rtl::OUString& aFilterUIName,
2471     const ::rtl::OUString& aExtName,
2472     const ::rtl::OUString& rStandardDir,
2473     const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList,
2474     Window* _pPreferredParent )
2475 {
2476     mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags, SFX2_IMPL_DIALOG_CONFIG, _pPreferredParent,rStandardDir, rBlackList );
2477     mxImp = mpImp;
2478 
2479     // the wildcard here is expected in form "*.extension"
2480     ::rtl::OUString aWildcard;
2481     if ( aExtName.indexOf( (sal_Unicode)'*' ) != 0 )
2482     {
2483         if ( aExtName.getLength() && aExtName.indexOf( (sal_Unicode)'.' ) != 0 )
2484             aWildcard = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*." ) );
2485         else
2486             aWildcard = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*" ) );
2487     }
2488 
2489     aWildcard += aExtName;
2490 
2491     ::rtl::OUString aUIString =
2492         ::sfx2::addExtension( aFilterUIName, aWildcard, ( WB_OPEN == ( nFlags & WB_OPEN ) ), *mpImp );
2493     AddFilter( aUIString, aWildcard );
2494 }
2495 
2496 // ------------------------------------------------------------------------
2497 FileDialogHelper::~FileDialogHelper()
2498 {
2499     mpImp->dispose();
2500     mxImp.clear();
2501 }
2502 
2503 // ------------------------------------------------------------------------
2504 void FileDialogHelper::CreateMatcher( const String& rFactory )
2505 {
2506     mpImp->createMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory) );
2507 }
2508 
2509 // ------------------------------------------------------------------------
2510 void FileDialogHelper::SetControlHelpIds( const sal_Int16* _pControlId, const char** _pHelpId )
2511 {
2512     mpImp->setControlHelpIds( _pControlId, _pHelpId );
2513 }
2514 
2515 void FileDialogHelper::SetContext( Context _eNewContext )
2516 {
2517     mpImp->SetContext( _eNewContext );
2518 }
2519 
2520 // ------------------------------------------------------------------------
2521 IMPL_LINK( FileDialogHelper, ExecuteSystemFilePicker, void*, EMPTYARG )
2522 {
2523     m_nError = mpImp->execute();
2524     if ( m_aDialogClosedLink.IsSet() )
2525         m_aDialogClosedLink.Call( this );
2526 
2527     return 0L;
2528 }
2529 
2530 // ------------------------------------------------------------------------
2531 // rDirPath has to be a directory
2532 ErrCode FileDialogHelper::Execute( SvStringsDtor*& rpURLList,
2533                                    SfxItemSet *&   rpSet,
2534                                    String&         rFilter,
2535                                    const String&   rDirPath )
2536 {
2537     SetDisplayFolder( rDirPath );
2538     return mpImp->execute( rpURLList, rpSet, rFilter );
2539 }
2540 
2541 
2542 // ------------------------------------------------------------------------
2543 ErrCode FileDialogHelper::Execute()
2544 {
2545     return mpImp->execute();
2546 }
2547 
2548 // ------------------------------------------------------------------------
2549 ErrCode FileDialogHelper::Execute( SfxItemSet *&   rpSet,
2550                                    String&         rFilter )
2551 {
2552     ErrCode nRet;
2553     SvStringsDtor* pURLList;
2554 
2555     nRet = mpImp->execute( pURLList, rpSet, rFilter );
2556 
2557     delete pURLList;
2558 
2559     return nRet;
2560 }
2561 
2562 void FileDialogHelper::StartExecuteModal( const Link& rEndDialogHdl )
2563 {
2564     m_aDialogClosedLink = rEndDialogHdl;
2565     m_nError = ERRCODE_NONE;
2566     if ( mpImp->isSystemFilePicker() )
2567         Application::PostUserEvent( LINK( this, FileDialogHelper, ExecuteSystemFilePicker ) );
2568     else
2569         mpImp->implStartExecute();
2570 }
2571 
2572 // ------------------------------------------------------------------------
2573 
2574 short FileDialogHelper::GetDialogType() const
2575 {
2576     return mpImp ? mpImp->m_nDialogType : 0;
2577 }
2578 
2579 // ------------------------------------------------------------------------
2580 
2581 sal_Bool FileDialogHelper::IsPasswordEnabled() const
2582 {
2583     return mpImp ? mpImp->isPasswordEnabled() : sal_False;
2584 }
2585 
2586 // ------------------------------------------------------------------------
2587 
2588 String FileDialogHelper::GetRealFilter() const
2589 {
2590     String sFilter;
2591     if ( mpImp )
2592         mpImp->getRealFilter( sFilter );
2593     return sFilter;
2594 }
2595 
2596 // ------------------------------------------------------------------------
2597 void FileDialogHelper::SetTitle( const String& rNewTitle )
2598 {
2599     if ( mpImp->mxFileDlg.is() )
2600         mpImp->mxFileDlg->setTitle( rNewTitle );
2601 }
2602 
2603 // ------------------------------------------------------------------------
2604 String FileDialogHelper::GetPath() const
2605 {
2606     OUString aPath;
2607 
2608     if ( mpImp->mlLastURLs.size() > 0)
2609         return mpImp->mlLastURLs[0];
2610 
2611     if ( mpImp->mxFileDlg.is() )
2612     {
2613         Sequence < OUString > aPathSeq = mpImp->mxFileDlg->getFiles();
2614 
2615         if ( aPathSeq.getLength() == 1 )
2616         {
2617             aPath = aPathSeq[0];
2618         }
2619     }
2620 
2621     return aPath;
2622 }
2623 
2624 // ------------------------------------------------------------------------
2625 Sequence < OUString > FileDialogHelper::GetMPath() const
2626 {
2627     if ( mpImp->mlLastURLs.size() > 0)
2628         return mpImp->mlLastURLs.getAsConstList();
2629 
2630     if ( mpImp->mxFileDlg.is() )
2631         return mpImp->mxFileDlg->getFiles();
2632     else
2633     {
2634         Sequence < OUString > aEmpty;
2635         return aEmpty;
2636     }
2637 }
2638 
2639 // ------------------------------------------------------------------------
2640 Sequence< ::rtl::OUString > FileDialogHelper::GetSelectedFiles() const
2641 {
2642     // a) the new way (optional!)
2643     uno::Sequence< ::rtl::OUString > aResultSeq;
2644     uno::Reference< XFilePicker2 > xPickNew(mpImp->mxFileDlg, UNO_QUERY);
2645     if (xPickNew.is())
2646     {
2647         aResultSeq = xPickNew->getSelectedFiles();
2648     }
2649     // b) the olde way ... non optional.
2650     else
2651     {
2652         uno::Reference< XFilePicker > xPickOld(mpImp->mxFileDlg, UNO_QUERY_THROW);
2653         Sequence< OUString > lFiles = xPickOld->getFiles();
2654         ::sal_Int32          nFiles = lFiles.getLength();
2655         if ( nFiles > 1 )
2656         {
2657             aResultSeq = Sequence< ::rtl::OUString >( nFiles-1 );
2658 
2659             INetURLObject aPath( lFiles[0] );
2660             aPath.setFinalSlash();
2661 
2662             for (::sal_Int32 i = 1; i < nFiles; i++)
2663             {
2664                 if (i == 1)
2665                     aPath.Append( lFiles[i] );
2666                 else
2667                     aPath.setName( lFiles[i] );
2668 
2669                 aResultSeq[i-1] = ::rtl::OUString(aPath.GetMainURL( INetURLObject::NO_DECODE ));
2670             }
2671         }
2672         else
2673             aResultSeq = lFiles;
2674     }
2675 
2676     return aResultSeq;
2677 }
2678 
2679 // ------------------------------------------------------------------------
2680 String FileDialogHelper::GetDisplayDirectory() const
2681 {
2682     return mpImp->getPath();
2683 }
2684 
2685 // ------------------------------------------------------------------------
2686 String FileDialogHelper::GetCurrentFilter() const
2687 {
2688     return mpImp->getFilter();
2689 }
2690 
2691 // ------------------------------------------------------------------------
2692 ErrCode FileDialogHelper::GetGraphic( Graphic& rGraphic ) const
2693 {
2694     return mpImp->getGraphic( rGraphic );
2695 }
2696 
2697 // ------------------------------------------------------------------------
2698 static int impl_isFolder( const OUString& rPath )
2699 {
2700     uno::Reference< task::XInteractionHandler > xHandler;
2701     try
2702     {
2703         uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
2704         xHandler.set( xFactory->createInstance( DEFINE_CONST_OUSTRING( "com.sun.star.task.InteractionHandler" ) ),
2705                       uno::UNO_QUERY_THROW );
2706     }
2707     catch ( Exception const & )
2708     {
2709     }
2710 
2711     ::rtl::Reference< ::comphelper::StillReadWriteInteraction > aHandler = new ::comphelper::StillReadWriteInteraction( xHandler );
2712 
2713     try
2714     {
2715         ::ucbhelper::Content aContent(
2716             rPath, new ::ucbhelper::CommandEnvironment( static_cast< task::XInteractionHandler* > ( aHandler.get() ), uno::Reference< ucb::XProgressHandler >() ) );
2717         if ( aContent.isFolder() )
2718             return 1;
2719 
2720         return 0;
2721     }
2722     catch ( Exception const & )
2723     {
2724     }
2725 
2726     return -1;
2727 }
2728 
2729 void FileDialogHelper::SetDisplayDirectory( const String& _rPath )
2730 {
2731     if ( !_rPath.Len() )
2732         return;
2733 
2734     // if the given path isn't a folder, we cut off the last part
2735     // and take it as filename and the rest of the path should be
2736     // the folder
2737 
2738     INetURLObject aObj( _rPath );
2739 
2740     ::rtl::OUString sFileName = aObj.GetName( INetURLObject::DECODE_WITH_CHARSET );
2741     aObj.removeSegment();
2742     ::rtl::OUString sPath = aObj.GetMainURL( INetURLObject::NO_DECODE );
2743 
2744     int nIsFolder = impl_isFolder( _rPath );
2745     if ( nIsFolder == 0 ||
2746          ( nIsFolder == -1 && impl_isFolder( sPath ) == 1 ) )
2747     {
2748         mpImp->setFileName( sFileName );
2749         mpImp->displayFolder( sPath );
2750     }
2751     else
2752     {
2753         INetURLObject aObjPathName( _rPath );
2754         ::rtl::OUString sFolder( aObjPathName.GetMainURL( INetURLObject::NO_DECODE ) );
2755         if ( sFolder.getLength() == 0 )
2756         {
2757             // _rPath is not a valid path -> fallback to home directory
2758             vos:: OSecurity  aSecurity;
2759             aSecurity.getHomeDir( sFolder );
2760         }
2761         mpImp->displayFolder( sFolder );
2762     }
2763 }
2764 
2765 // ------------------------------------------------------------------------
2766 void FileDialogHelper::SetDisplayFolder( const String& _rURL )
2767 {
2768     mpImp->displayFolder( _rURL );
2769 }
2770 
2771 // ------------------------------------------------------------------------
2772 void FileDialogHelper::SetFileName( const String& _rFileName )
2773 {
2774     mpImp->setFileName( _rFileName );
2775 }
2776 
2777 // ------------------------------------------------------------------------
2778 void FileDialogHelper::AddFilter( const String& rFilterName,
2779                                   const String& rExtension )
2780 {
2781     mpImp->addFilter( rFilterName, rExtension );
2782 }
2783 
2784 // ------------------------------------------------------------------------
2785 void FileDialogHelper::SetCurrentFilter( const String& rFilter )
2786 {
2787     String sFilter( rFilter );
2788     if ( mpImp->isShowFilterExtensionEnabled() )
2789         sFilter = mpImp->getFilterWithExtension( rFilter );
2790     mpImp->setFilter( sFilter );
2791 }
2792 
2793 // ------------------------------------------------------------------------
2794 uno::Reference < XFilePicker > FileDialogHelper::GetFilePicker() const
2795 {
2796     return mpImp->mxFileDlg;
2797 }
2798 
2799 // ------------------------------------------------------------------------
2800 sal_Int16 FileDialogHelper::getDialogType( sal_Int64 nFlags ) const
2801 {
2802     sal_Int16 nDialogType = FILEOPEN_SIMPLE;
2803 
2804     if ( nFlags & WB_SAVEAS )
2805     {
2806         if ( nFlags & SFXWB_PASSWORD )
2807             nDialogType = FILESAVE_AUTOEXTENSION_PASSWORD;
2808         else
2809             nDialogType = FILESAVE_SIMPLE;
2810     }
2811     else if ( nFlags & SFXWB_GRAPHIC )
2812     {
2813         if ( nFlags & SFXWB_SHOWSTYLES )
2814             nDialogType = FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE;
2815         else
2816             nDialogType = FILEOPEN_LINK_PREVIEW;
2817     }
2818     else if ( SFXWB_INSERT != ( nFlags & SFXWB_INSERT ) )
2819         nDialogType = FILEOPEN_READONLY_VERSION;
2820 
2821     return nDialogType;
2822 }
2823 
2824 // ------------------------------------------------------------------------
2825 // XFilePickerListener Methods
2826 // ------------------------------------------------------------------------
2827 void SAL_CALL FileDialogHelper::FileSelectionChanged( const FilePickerEvent& aEvent )
2828 {
2829     mpImp->handleFileSelectionChanged( aEvent );
2830 }
2831 
2832 // ------------------------------------------------------------------------
2833 void SAL_CALL FileDialogHelper::DirectoryChanged( const FilePickerEvent& aEvent )
2834 {
2835     mpImp->handleDirectoryChanged( aEvent );
2836 }
2837 
2838 // ------------------------------------------------------------------------
2839 OUString SAL_CALL FileDialogHelper::HelpRequested( const FilePickerEvent& aEvent )
2840 {
2841     return mpImp->handleHelpRequested( aEvent );
2842 }
2843 
2844 // ------------------------------------------------------------------------
2845 void SAL_CALL FileDialogHelper::ControlStateChanged( const FilePickerEvent& aEvent )
2846 {
2847     mpImp->handleControlStateChanged( aEvent );
2848 }
2849 
2850 // ------------------------------------------------------------------------
2851 void SAL_CALL FileDialogHelper::DialogSizeChanged()
2852 {
2853     mpImp->handleDialogSizeChanged();
2854 }
2855 
2856 // ------------------------------------------------------------------------
2857 void SAL_CALL FileDialogHelper::DialogClosed( const DialogClosedEvent& _rEvent )
2858 {
2859     m_nError = ( RET_OK == _rEvent.DialogResult ) ? ERRCODE_NONE : ERRCODE_ABORT;
2860     if ( m_aDialogClosedLink.IsSet() )
2861         m_aDialogClosedLink.Call( this );
2862 }
2863 
2864 // ------------------------------------------------------------------------
2865 // ------------------------------------------------------------------------
2866 // ------------------------------------------------------------------------
2867 
2868 ErrCode FileOpenDialog_Impl( sal_Int64 nFlags,
2869                              const String& rFact,
2870                              SvStringsDtor *& rpURLList,
2871                              String& rFilter,
2872                              SfxItemSet *& rpSet,
2873                              const String* pPath,
2874                              sal_Int16 nDialog,
2875                              const String& rStandardDir,
2876                              const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList )
2877 {
2878     ErrCode nRet;
2879     FileDialogHelper aDialog( nFlags, rFact, nDialog, 0, 0, rStandardDir, rBlackList );
2880 
2881     String aPath;
2882     if ( pPath )
2883         aPath = *pPath;
2884 
2885     nRet = aDialog.Execute( rpURLList, rpSet, rFilter, aPath );
2886     DBG_ASSERT( rFilter.SearchAscii(": ") == STRING_NOTFOUND, "Old filter name used!");
2887 
2888     return nRet;
2889 }
2890 
2891 
2892 // ------------------------------------------------------------------------
2893 String EncodeSpaces_Impl( const String& rSource )
2894 {
2895     String sRet( rSource );
2896     sRet.SearchAndReplaceAll( DEFINE_CONST_UNICODE( " " ), DEFINE_CONST_UNICODE( "%20" ) );
2897     return sRet;
2898 }
2899 
2900 // ------------------------------------------------------------------------
2901 String DecodeSpaces_Impl( const String& rSource )
2902 {
2903     String sRet( rSource );
2904     sRet.SearchAndReplaceAll( DEFINE_CONST_UNICODE( "%20" ), DEFINE_CONST_UNICODE( " " ) );
2905     return sRet;
2906 }
2907 
2908 // ------------------------------------------------------------------------
2909 
2910 }   // end of namespace sfx2
2911 
2912