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