1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <sfx2/filedlghelper.hxx>
30 #include <sal/types.h>
31 #include <com/sun/star/lang/XInitialization.hpp>
32 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
33 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
34 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
35 #include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
36 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
37 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
38 #include <com/sun/star/ui/dialogs/XControlInformation.hpp>
39 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
40 #include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp>
41 #include <com/sun/star/ui/dialogs/XFilePreview.hpp>
42 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
43 #include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp>
44 #include <com/sun/star/ui/dialogs/XFolderPicker.hpp>
45 #include <com/sun/star/ui/dialogs/XFilePicker2.hpp>
46 #include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
47 #include <com/sun/star/lang/XServiceInfo.hpp>
48 #include <com/sun/star/beans/XPropertySet.hpp>
49 #include <com/sun/star/beans/NamedValue.hpp>
50 #include <com/sun/star/embed/ElementModes.hpp>
51 #include <com/sun/star/container/XEnumeration.hpp>
52 #include <com/sun/star/container/XContainerQuery.hpp>
53 #include <com/sun/star/task/XInteractionRequest.hpp>
54 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
56 #include <comphelper/processfactory.hxx>
57 #include <comphelper/sequenceashashmap.hxx>
58 #include <comphelper/stillreadwriteinteraction.hxx>
59 #include <comphelper/string.hxx>
60 #include <comphelper/types.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 <osl/file.hxx>
67 #include <osl/mutex.hxx>
68 #include <osl/security.hxx>
69 #include <osl/thread.hxx>
70 #include <vcl/cvtgrf.hxx>
71 #include <vcl/msgbox.hxx>
72 #include <vcl/mnemonic.hxx>
73 #include <unotools/pathoptions.hxx>
74 #include <unotools/securityoptions.hxx>
75 #include <svl/itemset.hxx>
76 #include <svl/eitem.hxx>
77 #include <svl/intitem.hxx>
78 #include <svl/stritem.hxx>
79 #include <svtools/filter.hxx>
80 #include <unotools/viewoptions.hxx>
81 #include <unotools/moduleoptions.hxx>
82 #include <svtools/helpid.hrc>
83 #include <comphelper/docpasswordrequest.hxx>
84 #include <comphelper/docpasswordhelper.hxx>
85 #include <ucbhelper/content.hxx>
86 #include <ucbhelper/commandenvironment.hxx>
87 #include <comphelper/storagehelper.hxx>
88 #include <toolkit/helper/vclunohelper.hxx>
89 #include <sfx2/app.hxx>
90 #include <sfx2/frame.hxx>
91 #include <sfx2/docfile.hxx>
92 #include <sfx2/docfac.hxx>
93 #include "openflag.hxx"
94 #include <sfx2/passwd.hxx>
95 #include "sfx2/sfxresid.hxx"
96 #include <sfx2/sfxsids.hrc>
97 #include "filedlghelper.hrc"
98 #include "filtergrouping.hxx"
99 #include <sfx2/request.hxx>
100 #include "filedlgimpl.hxx"
101 #include <helpid.hrc>
102 #include <sfxlocal.hrc>
103 #include <rtl/oustringostreaminserter.hxx>
104 #include <rtl/strbuf.hxx>
108 #include <sys/stat.h>
111 //-----------------------------------------------------------------------------
113 using namespace ::com::sun::star
;
114 using namespace ::com::sun::star::container
;
115 using namespace ::com::sun::star::lang
;
116 using namespace ::com::sun::star::ui::dialogs
;
117 using namespace ::com::sun::star::ui::dialogs::TemplateDescription
;
118 using namespace ::com::sun::star::uno
;
119 using namespace ::com::sun::star::beans
;
120 using namespace ::rtl
;
121 using namespace ::cppu
;
123 //-----------------------------------------------------------------------------
125 #define IODLG_CONFIGNAME String(DEFINE_CONST_UNICODE("FilePicker_Save"))
126 #define IMPGRF_CONFIGNAME String(DEFINE_CONST_UNICODE("FilePicker_Graph"))
127 #define USERITEM_NAME ::rtl::OUString("UserItem" )
129 //-----------------------------------------------------------------------------
134 const OUString
* GetLastFilterConfigId( FileDialogHelper::Context _eContext
)
136 static const OUString
aSD_EXPORT_IDENTIFIER( "SdExportLastFilter" );
137 static const OUString
aSI_EXPORT_IDENTIFIER( "SiExportLastFilter" );
138 static const OUString
aSW_EXPORT_IDENTIFIER( "SwExportLastFilter" );
140 const OUString
* pRet
= NULL
;
144 case FileDialogHelper::SD_EXPORT
: pRet
= &aSD_EXPORT_IDENTIFIER
; break;
145 case FileDialogHelper::SI_EXPORT
: pRet
= &aSI_EXPORT_IDENTIFIER
; break;
146 case FileDialogHelper::SW_EXPORT
: pRet
= &aSW_EXPORT_IDENTIFIER
; break;
153 String
EncodeSpaces_Impl( const String
& rSource
);
154 String
DecodeSpaces_Impl( const String
& rSource
);
156 // ------------------------------------------------------------------------
157 // ----------- FileDialogHelper_Impl ---------------------------
158 // ------------------------------------------------------------------------
160 // ------------------------------------------------------------------------
161 // XFilePickerListener Methods
162 // ------------------------------------------------------------------------
163 void SAL_CALL
FileDialogHelper_Impl::fileSelectionChanged( const FilePickerEvent
& aEvent
) throw ( RuntimeException
)
165 SolarMutexGuard aGuard
;
166 mpAntiImpl
->FileSelectionChanged( aEvent
);
169 // ------------------------------------------------------------------------
170 void SAL_CALL
FileDialogHelper_Impl::directoryChanged( const FilePickerEvent
& aEvent
) throw ( RuntimeException
)
172 SolarMutexGuard aGuard
;
173 mpAntiImpl
->DirectoryChanged( aEvent
);
176 // ------------------------------------------------------------------------
177 OUString SAL_CALL
FileDialogHelper_Impl::helpRequested( const FilePickerEvent
& aEvent
) throw ( RuntimeException
)
179 SolarMutexGuard aGuard
;
180 return mpAntiImpl
->HelpRequested( aEvent
);
183 // ------------------------------------------------------------------------
184 void SAL_CALL
FileDialogHelper_Impl::controlStateChanged( const FilePickerEvent
& aEvent
) throw ( RuntimeException
)
186 SolarMutexGuard aGuard
;
187 mpAntiImpl
->ControlStateChanged( aEvent
);
190 // ------------------------------------------------------------------------
191 void SAL_CALL
FileDialogHelper_Impl::dialogSizeChanged() throw ( RuntimeException
)
193 SolarMutexGuard aGuard
;
194 mpAntiImpl
->DialogSizeChanged();
197 // ------------------------------------------------------------------------
198 // XDialogClosedListener Methods
199 // ------------------------------------------------------------------------
200 void SAL_CALL
FileDialogHelper_Impl::dialogClosed( const DialogClosedEvent
& _rEvent
) throw ( RuntimeException
)
202 SolarMutexGuard aGuard
;
203 mpAntiImpl
->DialogClosed( _rEvent
);
204 postExecute( _rEvent
.DialogResult
);
207 // ------------------------------------------------------------------------
208 // handle XFilePickerListener events
209 // ------------------------------------------------------------------------
210 void FileDialogHelper_Impl::handleFileSelectionChanged( const FilePickerEvent
& )
216 maPreViewTimer
.Start();
219 // ------------------------------------------------------------------------
220 void FileDialogHelper_Impl::handleDirectoryChanged( const FilePickerEvent
& )
223 TimeOutHdl_Impl( NULL
);
226 // ------------------------------------------------------------------------
227 OUString
FileDialogHelper_Impl::handleHelpRequested( const FilePickerEvent
& aEvent
)
229 //!!! todo: cache the help strings (here or TRA)
231 rtl::OString sHelpId
;
232 // mapping from element id -> help id
233 switch ( aEvent
.ElementId
)
235 case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
:
236 sHelpId
= HID_FILESAVE_AUTOEXTENSION
;
239 case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
:
240 sHelpId
= HID_FILESAVE_SAVEWITHPASSWORD
;
243 case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
:
244 sHelpId
= HID_FILESAVE_CUSTOMIZEFILTER
;
247 case ExtendedFilePickerElementIds::CHECKBOX_READONLY
:
248 sHelpId
= HID_FILEOPEN_READONLY
;
251 case ExtendedFilePickerElementIds::CHECKBOX_LINK
:
252 sHelpId
= HID_FILEDLG_LINK_CB
;
255 case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
:
256 sHelpId
= HID_FILEDLG_PREVIEW_CB
;
259 case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY
:
260 sHelpId
= HID_FILESAVE_DOPLAY
;
263 case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL
:
264 case ExtendedFilePickerElementIds::LISTBOX_VERSION
:
265 sHelpId
= HID_FILEOPEN_VERSION
;
268 case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL
:
269 case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE
:
270 sHelpId
= HID_FILESAVE_TEMPLATE
;
273 case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL
:
274 case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE
:
275 sHelpId
= HID_FILEOPEN_IMAGE_TEMPLATE
;
278 case ExtendedFilePickerElementIds::CHECKBOX_SELECTION
:
279 sHelpId
= HID_FILESAVE_SELECTION
;
283 SAL_WARN( "sfx2.dialog", "invalid element id" );
287 Help
* pHelp
= Application::GetHelp();
289 aHelpText
= String( pHelp
->GetHelpText( rtl::OStringToOUString(sHelpId
, RTL_TEXTENCODING_UTF8
), NULL
) );
293 // ------------------------------------------------------------------------
294 void FileDialogHelper_Impl::handleControlStateChanged( const FilePickerEvent
& aEvent
)
296 switch ( aEvent
.ElementId
)
298 case CommonFilePickerElementIds::LISTBOX_FILTER
:
299 updateFilterOptionsBox();
300 enablePasswordBox( sal_False
);
301 updateSelectionBox();
302 // only use it for export and with our own dialog
303 if ( mbExport
&& !mbSystemPicker
)
304 updateExportButton();
307 case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
:
308 updatePreviewState();
313 // ------------------------------------------------------------------------
314 void FileDialogHelper_Impl::handleDialogSizeChanged()
317 TimeOutHdl_Impl( NULL
);
320 // ------------------------------------------------------------------------
321 // XEventListener Methods
322 // ------------------------------------------------------------------------
323 void SAL_CALL
FileDialogHelper_Impl::disposing( const EventObject
& ) throw ( RuntimeException
)
325 SolarMutexGuard aGuard
;
329 // ------------------------------------------------------------------------
331 void FileDialogHelper_Impl::dispose()
333 if ( mxFileDlg
.is() )
335 // remove the event listener
336 uno::Reference
< XFilePickerNotifier
> xNotifier( mxFileDlg
, UNO_QUERY
);
337 if ( xNotifier
.is() )
338 xNotifier
->removeFilePickerListener( this );
340 ::comphelper::disposeComponent( mxFileDlg
);
345 // ------------------------------------------------------------------------
346 String
FileDialogHelper_Impl::getCurrentFilterUIName() const
349 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
353 aFilterName
= xFltMgr
->getCurrentFilter();
355 if ( aFilterName
.Len() && isShowFilterExtensionEnabled() )
356 aFilterName
= getFilterName( aFilterName
);
362 // ------------------------------------------------------------------------
363 void FileDialogHelper_Impl::LoadLastUsedFilter( const OUString
& _rContextIdentifier
)
365 SvtViewOptions
aDlgOpt( E_DIALOG
, IODLG_CONFIGNAME
);
367 if( aDlgOpt
.Exists() )
369 OUString aLastFilter
;
370 if( aDlgOpt
.GetUserItem( _rContextIdentifier
) >>= aLastFilter
)
371 setFilter( aLastFilter
);
375 // ------------------------------------------------------------------------
376 void FileDialogHelper_Impl::SaveLastUsedFilter( const OUString
& _rContextIdentifier
)
378 SvtViewOptions( E_DIALOG
, IODLG_CONFIGNAME
).SetUserItem( _rContextIdentifier
,
379 makeAny( getFilterWithExtension( getFilter() ) ) );
382 // ------------------------------------------------------------------------
383 void FileDialogHelper_Impl::SaveLastUsedFilter( void )
385 const OUString
* pConfigId
= GetLastFilterConfigId( meContext
);
387 SaveLastUsedFilter( *pConfigId
);
390 // ------------------------------------------------------------------------
391 const SfxFilter
* FileDialogHelper_Impl::getCurentSfxFilter()
393 String aFilterName
= getCurrentFilterUIName();
395 const SfxFilter
* pFilter
= NULL
;
396 if ( mpMatcher
&& aFilterName
.Len() )
397 pFilter
= mpMatcher
->GetFilter4UIName( aFilterName
, m_nMustFlags
, m_nDontFlags
);
402 // ------------------------------------------------------------------------
403 sal_Bool
FileDialogHelper_Impl::updateExtendedControl( sal_Int16 _nExtendedControlId
, sal_Bool _bEnable
)
405 sal_Bool bIsEnabled
= sal_False
;
407 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
408 if ( xCtrlAccess
.is() )
412 xCtrlAccess
->enableControl( _nExtendedControlId
, _bEnable
);
413 bIsEnabled
= _bEnable
;
415 catch( const IllegalArgumentException
& )
417 OSL_FAIL( "FileDialogHelper_Impl::updateExtendedControl: caught an exception!" );
423 // ------------------------------------------------------------------------
424 sal_Bool
FileDialogHelper_Impl::CheckFilterOptionsCapability( const SfxFilter
* _pFilter
)
426 sal_Bool bResult
= sal_False
;
428 if( mxFilterCFG
.is() && _pFilter
)
431 Sequence
< PropertyValue
> aProps
;
432 Any aAny
= mxFilterCFG
->getByName( _pFilter
->GetName() );
433 if ( aAny
>>= aProps
)
435 ::rtl::OUString aServiceName
;
436 sal_Int32 nPropertyCount
= aProps
.getLength();
437 for( sal_Int32 nProperty
=0; nProperty
< nPropertyCount
; ++nProperty
)
439 if( aProps
[nProperty
].Name
.equals( DEFINE_CONST_OUSTRING( "UIComponent") ) )
441 aProps
[nProperty
].Value
>>= aServiceName
;
442 if( !aServiceName
.isEmpty() )
448 catch( const Exception
& )
456 // ------------------------------------------------------------------------
457 sal_Bool
FileDialogHelper_Impl::isInOpenMode() const
459 sal_Bool bRet
= sal_False
;
461 switch ( m_nDialogType
)
463 case FILEOPEN_SIMPLE
:
464 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
466 case FILEOPEN_READONLY_VERSION
:
467 case FILEOPEN_LINK_PREVIEW
:
474 // ------------------------------------------------------------------------
476 void FileDialogHelper_Impl::updateFilterOptionsBox()
478 if ( !m_bHaveFilterOptions
)
481 updateExtendedControl(
482 ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
,
483 CheckFilterOptionsCapability( getCurentSfxFilter() )
487 // ------------------------------------------------------------------------
489 void FileDialogHelper_Impl::updateExportButton()
491 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
492 if ( xCtrlAccess
.is() )
494 OUString
sEllipses( "..." );
495 OUString
sOldLabel( xCtrlAccess
->getLabel( CommonFilePickerElementIds::PUSHBUTTON_OK
) );
497 // initialize button label; we need the label with the mnemonic char
498 if ( maButtonLabel
.isEmpty() || maButtonLabel
.indexOf( MNEMONIC_CHAR
) == -1 )
500 // cut the ellipses, if necessary
501 sal_Int32 nIndex
= sOldLabel
.indexOf( sEllipses
);
503 nIndex
= sOldLabel
.getLength();
504 maButtonLabel
= sOldLabel
.copy( 0, nIndex
);
507 OUString sLabel
= maButtonLabel
;
508 // filter with options -> append ellipses on export button label
509 if ( CheckFilterOptionsCapability( getCurentSfxFilter() ) )
510 sLabel
+= OUString( "..." );
512 if ( sOldLabel
!= sLabel
)
516 xCtrlAccess
->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK
, sLabel
);
518 catch( const IllegalArgumentException
& )
520 SAL_WARN( "sfx2.dialog", "FileDialogHelper_Impl::updateExportButton: caught an exception!" );
526 // ------------------------------------------------------------------------
527 void FileDialogHelper_Impl::updateSelectionBox()
529 if ( !mbHasSelectionBox
)
532 // Does the selection box exist?
533 sal_Bool bSelectionBoxFound
= sal_False
;
534 uno::Reference
< XControlInformation
> xCtrlInfo( mxFileDlg
, UNO_QUERY
);
535 if ( xCtrlInfo
.is() )
537 Sequence
< ::rtl::OUString
> aCtrlList
= xCtrlInfo
->getSupportedControls();
538 sal_uInt32 nCount
= aCtrlList
.getLength();
539 for ( sal_uInt32 nCtrl
= 0; nCtrl
< nCount
; ++nCtrl
)
540 if ( aCtrlList
[ nCtrl
] == "SelectionBox" )
542 bSelectionBoxFound
= sal_False
;
547 if ( bSelectionBoxFound
)
549 const SfxFilter
* pFilter
= getCurentSfxFilter();
550 mbSelectionFltrEnabled
= updateExtendedControl(
551 ExtendedFilePickerElementIds::CHECKBOX_SELECTION
,
552 ( mbSelectionEnabled
&& pFilter
&& ( pFilter
->GetFilterFlags() & SFX_FILTER_SUPPORTSSELECTION
) != 0 ) );
553 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
554 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0, makeAny( (sal_Bool
)mbSelection
) );
558 // ------------------------------------------------------------------------
559 void FileDialogHelper_Impl::enablePasswordBox( sal_Bool bInit
)
561 if ( ! mbHasPassword
)
564 sal_Bool bWasEnabled
= mbIsPwdEnabled
;
566 const SfxFilter
* pCurrentFilter
= getCurentSfxFilter();
567 mbIsPwdEnabled
= updateExtendedControl(
568 ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
,
569 pCurrentFilter
&& ( pCurrentFilter
->GetFilterFlags() & SFX_FILTER_ENCRYPTION
)
574 // in case of inintialization previous state is not interesting
577 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
578 if( mbPwdCheckBoxState
)
579 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0, makeAny( sal_True
) );
582 else if( !bWasEnabled
&& mbIsPwdEnabled
)
584 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
585 if( mbPwdCheckBoxState
)
586 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0, makeAny( sal_True
) );
588 else if( bWasEnabled
&& !mbIsPwdEnabled
)
590 // remember user settings until checkbox is enabled
591 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
592 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0 );
593 sal_Bool bPassWord
= sal_False
;
594 mbPwdCheckBoxState
= ( aValue
>>= bPassWord
) && bPassWord
;
595 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0, makeAny( sal_False
) );
599 // ------------------------------------------------------------------------
600 void FileDialogHelper_Impl::updatePreviewState( sal_Bool _bUpdatePreviewWindow
)
604 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
606 // check, whether or not we have to display a preview
607 if ( xCtrlAccess
.is() )
611 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0 );
612 sal_Bool bShowPreview
= sal_False
;
614 if ( aValue
>>= bShowPreview
)
616 mbShowPreview
= bShowPreview
;
618 // setShowState has currently no effect for the
619 // OpenOffice FilePicker (see svtools/source/filepicker/iodlg.cxx)
620 uno::Reference
< XFilePreview
> xFilePreview( mxFileDlg
, UNO_QUERY
);
621 if ( xFilePreview
.is() )
622 xFilePreview
->setShowState( mbShowPreview
);
624 if ( _bUpdatePreviewWindow
)
625 TimeOutHdl_Impl( NULL
);
628 catch( const Exception
& )
630 SAL_WARN( "sfx2.dialog", "FileDialogHelper_Impl::updatePreviewState: caught an exception!" );
636 // ------------------------------------------------------------------------
637 void FileDialogHelper_Impl::updateVersions()
639 Sequence
< OUString
> aEntries
;
640 Sequence
< OUString
> aPathSeq
= mxFileDlg
->getFiles();
642 if ( aPathSeq
.getLength() == 1 )
644 INetURLObject
aObj( aPathSeq
[0] );
646 if ( ( aObj
.GetProtocol() == INET_PROT_FILE
) &&
647 ( utl::UCBContentHelper::IsDocument( aObj
.GetMainURL( INetURLObject::NO_DECODE
) ) ) )
651 uno::Reference
< embed::XStorage
> xStorage
= ::comphelper::OStorageHelper::GetStorageFromURL(
652 aObj
.GetMainURL( INetURLObject::NO_DECODE
),
653 embed::ElementModes::READ
);
655 DBG_ASSERT( xStorage
.is(), "The method must return the storage or throw an exception!" );
656 if ( !xStorage
.is() )
657 throw uno::RuntimeException();
659 uno::Sequence
< util::RevisionTag
> xVersions
= SfxMedium::GetVersionList( xStorage
);
661 aEntries
.realloc( xVersions
.getLength() + 1 );
662 aEntries
[0] = OUString( String ( SfxResId( STR_SFX_FILEDLG_ACTUALVERSION
) ) );
664 for ( sal_Int32 i
=0; i
<xVersions
.getLength(); i
++ )
665 aEntries
[ i
+ 1 ] = xVersions
[i
].Identifier
;
667 catch( const uno::Exception
& )
673 uno::Reference
< XFilePickerControlAccess
> xDlg( mxFileDlg
, UNO_QUERY
);
678 xDlg
->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
679 ControlActions::DELETE_ITEMS
, aValue
);
681 catch( const IllegalArgumentException
& ){}
683 sal_Int32 nCount
= aEntries
.getLength();
690 xDlg
->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
691 ControlActions::ADD_ITEMS
, aValue
);
694 aPos
<<= (sal_Int32
) 0;
695 xDlg
->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
696 ControlActions::SET_SELECT_ITEM
, aPos
);
698 catch( const IllegalArgumentException
& ){}
702 // -----------------------------------------------------------------------
703 IMPL_LINK_NOARG(FileDialogHelper_Impl
, TimeOutHdl_Impl
)
711 uno::Reference
< XFilePreview
> xFilePicker( mxFileDlg
, UNO_QUERY
);
713 if ( ! xFilePicker
.is() )
716 Sequence
< OUString
> aPathSeq
= mxFileDlg
->getFiles();
718 if ( mbShowPreview
&& ( aPathSeq
.getLength() == 1 ) )
720 OUString aURL
= aPathSeq
[0];
722 if ( ERRCODE_NONE
== getGraphic( aURL
, maGraphic
) )
724 // changed the code slightly;
725 // before: the bitmap was scaled and
726 // surrounded a white frame
727 // now: the bitmap will only be scaled
728 // and the filepicker implementation
729 // is responsible for placing it at its
730 // proper position and painting a frame
732 Bitmap aBmp
= maGraphic
.GetBitmap();
734 // scale the bitmap to the correct size
735 sal_Int32 nOutWidth
= xFilePicker
->getAvailableWidth();
736 sal_Int32 nOutHeight
= xFilePicker
->getAvailableHeight();
737 sal_Int32 nBmpWidth
= aBmp
.GetSizePixel().Width();
738 sal_Int32 nBmpHeight
= aBmp
.GetSizePixel().Height();
740 double nXRatio
= (double) nOutWidth
/ nBmpWidth
;
741 double nYRatio
= (double) nOutHeight
/ nBmpHeight
;
743 if ( nXRatio
< nYRatio
)
744 aBmp
.Scale( nXRatio
, nXRatio
);
746 aBmp
.Scale( nYRatio
, nYRatio
);
748 // Convert to true color, to allow CopyPixel
749 aBmp
.Convert( BMP_CONVERSION_24BIT
);
751 // and copy it into the Any
752 SvMemoryStream aData
;
756 const Sequence
< sal_Int8
> aBuffer(
757 static_cast< const sal_Int8
* >(aData
.GetData()),
758 aData
.GetEndOfData() );
766 SolarMutexReleaser aReleaseForCallback
;
767 // clear the preview window
768 xFilePicker
->setImage( FilePreviewImageFormats::BITMAP
, aAny
);
770 catch( const IllegalArgumentException
& )
777 // ------------------------------------------------------------------------
778 ErrCode
FileDialogHelper_Impl::getGraphic( const OUString
& rURL
,
779 Graphic
& rGraphic
) const
781 if ( utl::UCBContentHelper::IsFolder( rURL
) )
782 return ERRCODE_IO_NOTAFILE
;
784 if ( !mpGraphicFilter
)
785 return ERRCODE_IO_NOTSUPPORTED
;
787 // select graphic filter from dialog filter selection
788 OUString
aCurFilter( getFilter() );
790 sal_uInt16 nFilter
= !aCurFilter
.isEmpty() && mpGraphicFilter
->GetImportFormatCount()
791 ? mpGraphicFilter
->GetImportFormatNumber( aCurFilter
)
792 : GRFILTER_FORMAT_DONTKNOW
;
794 INetURLObject
aURLObj( rURL
);
796 if ( aURLObj
.HasError() || INET_PROT_NOT_VALID
== aURLObj
.GetProtocol() )
798 aURLObj
.SetSmartProtocol( INET_PROT_FILE
);
799 aURLObj
.SetSmartURL( rURL
);
802 ErrCode nRet
= ERRCODE_NONE
;
804 sal_uInt32 nFilterImportFlags
= GRFILTER_I_FLAGS_SET_LOGSIZE_FOR_JPEG
;
806 if ( INET_PROT_FILE
!= aURLObj
.GetProtocol() )
808 SvStream
* pStream
= ::utl::UcbStreamHelper::CreateStream( rURL
, STREAM_READ
);
811 nRet
= mpGraphicFilter
->ImportGraphic( rGraphic
, rURL
, *pStream
, nFilter
, NULL
, nFilterImportFlags
);
813 nRet
= mpGraphicFilter
->ImportGraphic( rGraphic
, aURLObj
, nFilter
, NULL
, nFilterImportFlags
);
818 nRet
= mpGraphicFilter
->ImportGraphic( rGraphic
, aURLObj
, nFilter
, NULL
, nFilterImportFlags
);
824 // ------------------------------------------------------------------------
825 ErrCode
FileDialogHelper_Impl::getGraphic( Graphic
& rGraphic
) const
827 ErrCode nRet
= ERRCODE_NONE
;
832 Sequence
< OUString
> aPathSeq
= mxFileDlg
->getFiles();
834 if ( aPathSeq
.getLength() == 1 )
839 if ( !aPath
.isEmpty() )
840 nRet
= getGraphic( aPath
, rGraphic
);
842 nRet
= ERRCODE_IO_GENERAL
;
845 rGraphic
= maGraphic
;
850 // ------------------------------------------------------------------------
851 static bool lcl_isSystemFilePicker( const uno::Reference
< XFilePicker
>& _rxFP
)
855 uno::Reference
< XServiceInfo
> xSI( _rxFP
, UNO_QUERY
);
858 return xSI
->supportsService( DEFINE_CONST_OUSTRING( "com.sun.star.ui.dialogs.SystemFilePicker" ) );
860 catch( const Exception
& )
866 enum open_or_save_t
{OPEN
, SAVE
, UNDEFINED
};
867 static open_or_save_t
lcl_OpenOrSave(sal_Int16
const nDialogType
)
871 case FILEOPEN_SIMPLE
:
872 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
874 case FILEOPEN_READONLY_VERSION
:
875 case FILEOPEN_LINK_PREVIEW
:
877 case FILESAVE_SIMPLE
:
878 case FILESAVE_AUTOEXTENSION_PASSWORD
:
879 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
880 case FILESAVE_AUTOEXTENSION_SELECTION
:
881 case FILESAVE_AUTOEXTENSION_TEMPLATE
:
882 case FILESAVE_AUTOEXTENSION
:
885 assert(false); // invalid dialog type
890 // ------------------------------------------------------------------------
891 // ----------- FileDialogHelper_Impl ---------------------------
892 // ------------------------------------------------------------------------
894 FileDialogHelper_Impl::FileDialogHelper_Impl(
895 FileDialogHelper
* _pAntiImpl
,
896 sal_Int16 nDialogType
,
899 Window
* _pPreferredParentWindow
,
900 const String
& sStandardDir
,
901 const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& rBlackList
903 :m_nDialogType ( nDialogType
)
904 ,meContext ( FileDialogHelper::UNKNOWN_CONTEXT
)
906 const char* pServiceName
=0;
907 if ( nDialog
== SFX2_IMPL_DIALOG_SYSTEM
)
908 pServiceName
= FILE_OPEN_SERVICE_NAME_OOO
;
909 else if ( nDialog
== SFX2_IMPL_DIALOG_OOO
)
910 pServiceName
= FILE_OPEN_SERVICE_NAME_OOO
;
912 pServiceName
= FILE_OPEN_SERVICE_NAME
;
913 OUString aService
= ::rtl::OUString::createFromAscii( pServiceName
);
915 uno::Reference
< XMultiServiceFactory
> xFactory( ::comphelper::getProcessServiceFactory() );
917 // create the file open dialog
918 // the flags can be SFXWB_INSERT or SFXWB_MULTISELECTION
920 mpPreferredParentWindow
= _pPreferredParentWindow
;
921 mpAntiImpl
= _pAntiImpl
;
922 mnError
= ERRCODE_NONE
;
923 mbHasAutoExt
= sal_False
;
924 mbHasPassword
= sal_False
;
925 m_bHaveFilterOptions
= sal_False
;
926 mbIsPwdEnabled
= sal_True
;
927 mbHasVersions
= sal_False
;
928 mbHasPreview
= sal_False
;
929 mbShowPreview
= sal_False
;
930 mbAddGraphicFilter
= SFXWB_GRAPHIC
== (nFlags
& SFXWB_GRAPHIC
);
931 mbDeleteMatcher
= sal_False
;
932 mbInsert
= SFXWB_INSERT
== ( nFlags
& SFXWB_INSERT
);
933 mbExport
= SFXWB_EXPORT
== ( nFlags
& SFXWB_EXPORT
);
934 mbIsSaveDlg
= sal_False
;
935 mbPwdCheckBoxState
= sal_False
;
936 mbSelection
= sal_False
;
937 mbSelectionEnabled
= sal_True
;
938 mbHasSelectionBox
= sal_False
;
939 mbSelectionFltrEnabled
= sal_False
;
942 m_nDontFlags
= SFX_FILTER_INTERNAL
| SFX_FILTER_NOTINFILEDLG
| SFX_FILTER_NOTINSTALLED
;
943 if (OPEN
== lcl_OpenOrSave(m_nDialogType
))
944 m_nMustFlags
= SFX_FILTER_IMPORT
;
946 m_nMustFlags
= SFX_FILTER_EXPORT
;
950 mpGraphicFilter
= NULL
;
951 mnPostUserEventId
= 0;
953 // create the picker component
954 mxFileDlg
= mxFileDlg
.query( xFactory
->createInstance( aService
) );
955 mbSystemPicker
= lcl_isSystemFilePicker( mxFileDlg
);
957 uno::Reference
< XFilePickerNotifier
> xNotifier( mxFileDlg
, UNO_QUERY
);
958 uno::Reference
< XInitialization
> xInit( mxFileDlg
, UNO_QUERY
);
960 if ( ! mxFileDlg
.is() || ! xNotifier
.is() )
962 mnError
= ERRCODE_ABORT
;
969 sal_Int16 nTemplateDescription
= TemplateDescription::FILEOPEN_SIMPLE
;
971 switch ( m_nDialogType
)
973 case FILEOPEN_SIMPLE
:
974 nTemplateDescription
= TemplateDescription::FILEOPEN_SIMPLE
;
977 case FILESAVE_SIMPLE
:
978 nTemplateDescription
= TemplateDescription::FILESAVE_SIMPLE
;
979 mbIsSaveDlg
= sal_True
;
982 case FILESAVE_AUTOEXTENSION_PASSWORD
:
983 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD
;
984 mbHasPassword
= sal_True
;
985 mbHasAutoExt
= sal_True
;
986 mbIsSaveDlg
= sal_True
;
989 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
990 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
;
991 mbHasPassword
= sal_True
;
993 m_bHaveFilterOptions
= sal_True
;
996 mxFilterCFG
= uno::Reference
< XNameAccess
>(
997 xFactory
->createInstance( DEFINE_CONST_OUSTRING( "com.sun.star.document.FilterFactory" ) ),
1001 mbHasAutoExt
= sal_True
;
1002 mbIsSaveDlg
= sal_True
;
1005 case FILESAVE_AUTOEXTENSION_SELECTION
:
1006 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION
;
1007 mbHasAutoExt
= sal_True
;
1008 mbIsSaveDlg
= sal_True
;
1009 mbHasSelectionBox
= sal_True
;
1010 if ( mbExport
&& !mxFilterCFG
.is() && xFactory
.is() )
1012 mxFilterCFG
= uno::Reference
< XNameAccess
>(
1013 xFactory
->createInstance( DEFINE_CONST_OUSTRING( "com.sun.star.document.FilterFactory" ) ),
1018 case FILESAVE_AUTOEXTENSION_TEMPLATE
:
1019 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE
;
1020 mbHasAutoExt
= sal_True
;
1021 mbIsSaveDlg
= sal_True
;
1024 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
1025 nTemplateDescription
= TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
;
1026 mbHasPreview
= sal_True
;
1029 maPreViewTimer
.SetTimeout( 500 );
1030 maPreViewTimer
.SetTimeoutHdl( LINK( this, FileDialogHelper_Impl
, TimeOutHdl_Impl
) );
1034 nTemplateDescription
= TemplateDescription::FILEOPEN_PLAY
;
1037 case FILEOPEN_READONLY_VERSION
:
1038 nTemplateDescription
= TemplateDescription::FILEOPEN_READONLY_VERSION
;
1039 mbHasVersions
= sal_True
;
1042 case FILEOPEN_LINK_PREVIEW
:
1043 nTemplateDescription
= TemplateDescription::FILEOPEN_LINK_PREVIEW
;
1044 mbHasPreview
= sal_True
;
1046 maPreViewTimer
.SetTimeout( 500 );
1047 maPreViewTimer
.SetTimeoutHdl( LINK( this, FileDialogHelper_Impl
, TimeOutHdl_Impl
) );
1050 case FILESAVE_AUTOEXTENSION
:
1051 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION
;
1052 mbHasAutoExt
= sal_True
;
1053 mbIsSaveDlg
= sal_True
;
1057 SAL_WARN( "sfx2.dialog", "FileDialogHelper::ctor with unknown type" );
1061 Sequence
< Any
> aInitArguments( !mpPreferredParentWindow
? 3 : 4 );
1063 // This is a hack. We currently know that the internal file picker implementation
1064 // supports the extended arguments as specified below.
1066 // a) adjust the service description so that it includes the TemplateDescription and ParentWindow args
1067 // b) adjust the implementation of the system file picker to that it recognizes it
1068 if ( mbSystemPicker
)
1070 aInitArguments
[0] <<= nTemplateDescription
;
1074 aInitArguments
[0] <<= NamedValue(
1075 ::rtl::OUString( "TemplateDescription" ),
1076 makeAny( nTemplateDescription
)
1079 ::rtl::OUString sStandardDirTemp
= ::rtl::OUString( sStandardDir
);
1081 aInitArguments
[1] <<= NamedValue(
1082 ::rtl::OUString( "StandardDir" ),
1083 makeAny( sStandardDirTemp
)
1086 aInitArguments
[2] <<= NamedValue(
1087 ::rtl::OUString( "BlackList" ),
1088 makeAny( rBlackList
)
1092 if ( mpPreferredParentWindow
)
1093 aInitArguments
[3] <<= NamedValue(
1094 ::rtl::OUString( "ParentWindow" ),
1095 makeAny( VCLUnoHelper::GetInterface( mpPreferredParentWindow
) )
1101 xInit
->initialize( aInitArguments
);
1103 catch( const Exception
& )
1105 OSL_FAIL( "FileDialogHelper_Impl::FileDialogHelper_Impl: could not initialize the picker!" );
1110 // set multiselection mode
1111 if ( nFlags
& SFXWB_MULTISELECTION
)
1112 mxFileDlg
->setMultiSelectionMode( sal_True
);
1114 if (mbAddGraphicFilter
) // generate graphic filter only on demand
1122 mxFileDlg
->setTitle( OUString( String( SfxResId( STR_SFX_EXPLORERFILE_EXPORT
) ) ) );
1124 com::sun::star::uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY_THROW
);
1125 xCtrlAccess
->enableControl( ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR
, sal_True
);
1127 catch( const Exception
& ) { }
1130 // the "insert file" dialog needs another title
1133 mxFileDlg
->setTitle( OUString( String( SfxResId( STR_SFX_EXPLORERFILE_INSERT
) ) ) );
1134 uno::Reference
< XFilePickerControlAccess
> xExtDlg( mxFileDlg
, UNO_QUERY
);
1139 xExtDlg
->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK
,
1140 OUString( String( SfxResId( STR_SFX_EXPLORERFILE_BUTTONINSERT
) ) ) );
1142 catch( const IllegalArgumentException
& ){}
1146 // add the event listener
1147 xNotifier
->addFilePickerListener( this );
1150 // ------------------------------------------------------------------------
1151 FileDialogHelper_Impl::~FileDialogHelper_Impl()
1153 // Remove user event if we haven't received it yet
1154 if ( mnPostUserEventId
)
1155 Application::RemoveUserEvent( mnPostUserEventId
);
1156 mnPostUserEventId
= 0;
1158 delete mpGraphicFilter
;
1160 if ( mbDeleteMatcher
)
1163 maPreViewTimer
.SetTimeoutHdl( Link() );
1165 ::comphelper::disposeComponent( mxFileDlg
);
1170 class PickerThread_Impl
: public ::osl::Thread
1172 uno::Reference
< XFilePicker
> mxPicker
;
1173 ::osl::Mutex maMutex
;
1174 virtual void SAL_CALL
run();
1177 PickerThread_Impl( const uno::Reference
< XFilePicker
>& rPicker
)
1178 : mxPicker( rPicker
), mnRet(nMagic
) {}
1180 sal_Int16
GetReturnValue()
1181 { ::osl::MutexGuard
aGuard( maMutex
); return mnRet
; }
1183 void SetReturnValue( sal_Int16 aRetValue
)
1184 { ::osl::MutexGuard
aGuard( maMutex
); mnRet
= aRetValue
; }
1187 void SAL_CALL
PickerThread_Impl::run()
1191 sal_Int16 n
= mxPicker
->execute();
1192 SetReturnValue( n
);
1194 catch( const RuntimeException
& )
1196 SetReturnValue( ExecutableDialogResults::CANCEL
);
1197 SAL_WARN( "sfx2.dialog", "RuntimeException caught" );
1201 // ------------------------------------------------------------------------
1202 void FileDialogHelper_Impl::setControlHelpIds( const sal_Int16
* _pControlId
, const char** _pHelpId
)
1204 DBG_ASSERT( _pControlId
&& _pHelpId
, "FileDialogHelper_Impl::setControlHelpIds: invalid array pointers!" );
1205 if ( !_pControlId
|| !_pHelpId
)
1208 // forward these ids to the file picker
1211 const ::rtl::OUString
sHelpIdPrefix( INET_HID_SCHEME
);
1212 // the ids for the single controls
1213 uno::Reference
< XFilePickerControlAccess
> xControlAccess( mxFileDlg
, UNO_QUERY
);
1214 if ( xControlAccess
.is() )
1216 while ( *_pControlId
)
1218 DBG_ASSERT( INetURLObject( rtl::OStringToOUString( *_pHelpId
, RTL_TEXTENCODING_UTF8
) ).GetProtocol() == INET_PROT_NOT_VALID
, "Wrong HelpId!" );
1219 ::rtl::OUString
sId( sHelpIdPrefix
);
1220 sId
+= ::rtl::OUString( *_pHelpId
, strlen( *_pHelpId
), RTL_TEXTENCODING_UTF8
);
1221 xControlAccess
->setValue( *_pControlId
, ControlActions::SET_HELP_URL
, makeAny( sId
) );
1223 ++_pControlId
; ++_pHelpId
;
1227 catch( const Exception
& )
1229 OSL_FAIL( "FileDialogHelper_Impl::setControlHelpIds: caught an exception while setting the help ids!" );
1233 // ------------------------------------------------------------------------
1234 IMPL_LINK( FileDialogHelper_Impl
, InitControls
, void*, NOTINTERESTEDIN
)
1236 (void)NOTINTERESTEDIN
;
1237 mnPostUserEventId
= 0;
1238 enablePasswordBox( sal_True
);
1239 updateFilterOptionsBox( );
1240 updateSelectionBox( );
1245 // ------------------------------------------------------------------------
1246 void FileDialogHelper_Impl::preExecute()
1249 setDefaultValues( );
1250 updatePreviewState( sal_False
);
1252 implInitializeFileName( );
1254 #if !(defined(MACOSX) && defined(QUARTZ)) && !defined(WNT)
1255 // allow for dialog implementations which need to be executed before they return valid values for
1256 // current filter and such
1258 // On Vista (at least SP1) it's the same as on MacOSX, the modal dialog won't let message pass
1259 // through before it returns from execution
1260 mnPostUserEventId
= Application::PostUserEvent( LINK( this, FileDialogHelper_Impl
, InitControls
) );
1262 // However, the Mac OS X implementation's pickers run modally in execute and so the event doesn't
1263 // get through in time... so we call the methods directly
1264 enablePasswordBox( sal_True
);
1265 updateFilterOptionsBox( );
1266 updateSelectionBox( );
1270 // ------------------------------------------------------------------------
1271 void FileDialogHelper_Impl::postExecute( sal_Int16 _nResult
)
1273 if ( ExecutableDialogResults::CANCEL
!= _nResult
)
1277 // ------------------------------------------------------------------------
1278 void FileDialogHelper_Impl::implInitializeFileName( )
1280 if ( !maFileName
.isEmpty() )
1282 INetURLObject
aObj( maPath
);
1283 aObj
.Append( maFileName
);
1285 // in case we're operating as save dialog, and "auto extension" is checked,
1286 // cut the extension from the name
1287 if ( mbIsSaveDlg
&& mbHasAutoExt
)
1291 sal_Bool bAutoExtChecked
= sal_False
;
1293 uno::Reference
< XFilePickerControlAccess
> xControlAccess( mxFileDlg
, UNO_QUERY
);
1294 if ( xControlAccess
.is()
1295 && ( xControlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0 )
1300 if ( bAutoExtChecked
)
1301 { // cut the extension
1302 aObj
.removeExtension( );
1303 mxFileDlg
->setDefaultName( aObj
.GetName( INetURLObject::DECODE_WITH_CHARSET
) );
1307 catch( const Exception
& )
1309 OSL_FAIL( "FileDialogHelper_Impl::implInitializeFileName: could not ask for the auto-extension current-value!" );
1315 // ------------------------------------------------------------------------
1316 sal_Int16
FileDialogHelper_Impl::implDoExecute()
1320 sal_Int16 nRet
= ExecutableDialogResults::CANCEL
;
1322 //On MacOSX the native file picker has to run in the primordial thread because of drawing issues
1323 //On Linux the native gtk file picker, when backed by gnome-vfs2, needs to be run in the same
1324 //primordial thread as the ucb gnome-vfs2 provider was initialized in.
1330 if ( mbSystemPicker
)
1332 SolarMutexReleaser aSolarMutex
;
1333 nRet
= mxFileDlg
->execute();
1337 nRet
= mxFileDlg
->execute();
1339 catch( const Exception
& )
1341 SAL_WARN( "sfx2.dialog", "FileDialogHelper_Impl::implDoExecute: caught an exception!" );
1345 postExecute( nRet
);
1350 // ------------------------------------------------------------------------
1351 void FileDialogHelper_Impl::implStartExecute()
1353 DBG_ASSERT( mxFileDlg
.is(), "invalid file dialog" );
1357 if ( mbSystemPicker
)
1364 uno::Reference
< XAsynchronousExecutableDialog
> xAsyncDlg( mxFileDlg
, UNO_QUERY
);
1365 if ( xAsyncDlg
.is() )
1366 xAsyncDlg
->startExecuteModal( this );
1368 catch( const Exception
& )
1370 SAL_WARN( "sfx2.dialog", "FileDialogHelper_Impl::implDoExecute: caught an exception!" );
1375 // ------------------------------------------------------------------------
1376 void lcl_saveLastURLs(std::vector
<rtl::OUString
>& rpURLList
,
1377 ::comphelper::SequenceAsVector
< ::rtl::OUString
>& lLastURLs
)
1380 for(std::vector
<rtl::OUString
>::iterator i
= rpURLList
.begin(); i
!= rpURLList
.end(); ++i
)
1381 lLastURLs
.push_back(*i
);
1384 // ------------------------------------------------------------------------
1385 void FileDialogHelper_Impl::implGetAndCacheFiles(const uno::Reference
< XInterface
>& xPicker
, std::vector
<rtl::OUString
>& rpURLList
, const SfxFilter
* pFilter
)
1389 rtl::OUString sExtension
;
1392 sExtension
= pFilter
->GetDefaultExtension ();
1393 sExtension
= comphelper::string::remove(sExtension
, '*');
1394 sExtension
= comphelper::string::remove(sExtension
, '.');
1397 // a) the new way (optional!)
1398 uno::Reference
< XFilePicker2
> xPickNew(xPicker
, UNO_QUERY
);
1401 Sequence
< OUString
> lFiles
= xPickNew
->getSelectedFiles();
1402 ::sal_Int32 nFiles
= lFiles
.getLength();
1403 for(sal_Int32 i
= 0; i
< nFiles
; ++i
)
1404 rpURLList
.push_back(lFiles
[i
]);
1407 // b) the olde way ... non optional.
1410 uno::Reference
< XFilePicker
> xPickOld(xPicker
, UNO_QUERY_THROW
);
1411 Sequence
< OUString
> lFiles
= xPickOld
->getFiles();
1412 ::sal_Int32 nFiles
= lFiles
.getLength();
1415 rpURLList
.push_back(lFiles
[0]);
1417 else if ( nFiles
> 1 )
1419 INetURLObject
aPath( lFiles
[0] );
1420 aPath
.setFinalSlash();
1422 for (::sal_Int32 i
= 1; i
< nFiles
; i
++)
1425 aPath
.Append( lFiles
[i
] );
1427 aPath
.setName( lFiles
[i
] );
1429 rpURLList
.push_back(aPath
.GetMainURL(INetURLObject::NO_DECODE
));
1434 lcl_saveLastURLs(rpURLList
, mlLastURLs
);
1437 // ------------------------------------------------------------------------
1438 ErrCode
FileDialogHelper_Impl::execute( std::vector
<rtl::OUString
>& rpURLList
,
1439 SfxItemSet
*& rpSet
,
1442 // rFilter is a pure output parameter, it shouldn't be used for anything else
1443 // changing this would surely break code
1444 // rpSet is in/out parameter, usually just a media-descriptor that can be changed by dialog
1446 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
1448 // retrieves parameters from rpSet
1449 // for now only Password is used
1452 // check password checkbox if the document had password before
1455 SFX_ITEMSET_ARG( rpSet
, pPassItem
, SfxBoolItem
, SID_PASSWORDINTERACTION
, sal_False
);
1456 mbPwdCheckBoxState
= ( pPassItem
!= NULL
&& pPassItem
->GetValue() );
1458 // in case the document has password to modify, the dialog should be shown
1459 SFX_ITEMSET_ARG( rpSet
, pPassToModifyItem
, SfxUnoAnyItem
, SID_MODIFYPASSWORDINFO
, sal_False
);
1460 mbPwdCheckBoxState
|= ( pPassToModifyItem
&& pPassToModifyItem
->GetValue().hasValue() );
1463 SFX_ITEMSET_ARG( rpSet
, pSelectItem
, SfxBoolItem
, SID_SELECTION
, sal_False
);
1465 mbSelection
= pSelectItem
->GetValue();
1467 mbSelectionEnabled
= sal_False
;
1469 // the password will be set in case user decide so
1470 rpSet
->ClearItem( SID_PASSWORDINTERACTION
);
1471 rpSet
->ClearItem( SID_PASSWORD
);
1472 rpSet
->ClearItem( SID_ENCRYPTIONDATA
);
1473 rpSet
->ClearItem( SID_RECOMMENDREADONLY
);
1474 rpSet
->ClearItem( SID_MODIFYPASSWORDINFO
);
1478 if ( mbHasPassword
&& !mbPwdCheckBoxState
)
1480 SvtSecurityOptions aSecOpt
;
1481 mbPwdCheckBoxState
= (
1482 aSecOpt
.IsOptionSet( SvtSecurityOptions::E_DOCWARN_RECOMMENDPASSWORD
) );
1487 if ( ! mxFileDlg
.is() )
1488 return ERRCODE_ABORT
;
1490 if ( ExecutableDialogResults::CANCEL
!= implDoExecute() )
1492 // create an itemset if there is no
1494 rpSet
= new SfxAllItemSet( SFX_APP()->GetPool() );
1496 // the item should remain only if it was set by the dialog
1497 rpSet
->ClearItem( SID_SELECTION
);
1499 if( mbExport
&& mbHasSelectionBox
)
1503 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0 );
1504 sal_Bool bSelection
= sal_False
;
1505 if ( aValue
>>= bSelection
)
1506 rpSet
->Put( SfxBoolItem( SID_SELECTION
, bSelection
) );
1508 catch( const IllegalArgumentException
& )
1510 OSL_FAIL( "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
1515 // set the read-only flag. When inserting a file, this flag is always set
1517 rpSet
->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
1520 if ( ( FILEOPEN_READONLY_VERSION
== m_nDialogType
) && xCtrlAccess
.is() )
1524 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY
, 0 );
1525 sal_Bool bReadOnly
= sal_False
;
1526 if ( ( aValue
>>= bReadOnly
) && bReadOnly
)
1527 rpSet
->Put( SfxBoolItem( SID_DOC_READONLY
, bReadOnly
) );
1529 catch( const IllegalArgumentException
& )
1531 OSL_FAIL( "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
1535 if ( mbHasVersions
&& xCtrlAccess
.is() )
1539 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
1540 ControlActions::GET_SELECTED_ITEM_INDEX
);
1541 sal_Int32 nVersion
= 0;
1542 if ( ( aValue
>>= nVersion
) && nVersion
> 0 )
1543 // open a special version; 0 == current version
1544 rpSet
->Put( SfxInt16Item( SID_VERSION
, (short)nVersion
) );
1546 catch( const IllegalArgumentException
& ){}
1550 getRealFilter( rFilter
);
1552 const SfxFilter
* pCurrentFilter
= getCurentSfxFilter();
1554 // fill the rpURLList
1555 implGetAndCacheFiles( mxFileDlg
, rpURLList
, pCurrentFilter
);
1556 if ( rpURLList
.empty() )
1557 return ERRCODE_ABORT
;
1559 // check, whether or not we have to display a password box
1560 if ( pCurrentFilter
&& mbHasPassword
&& mbIsPwdEnabled
&& xCtrlAccess
.is() )
1564 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0 );
1565 sal_Bool bPassWord
= sal_False
;
1566 if ( ( aValue
>>= bPassWord
) && bPassWord
)
1568 // ask for a password
1569 rtl::OUString
aDocName(rpURLList
[0]);
1570 ErrCode errCode
= RequestPassword(pCurrentFilter
, aDocName
, rpSet
);
1571 if (errCode
!= ERRCODE_NONE
)
1575 catch( const IllegalArgumentException
& ){}
1578 SaveLastUsedFilter();
1579 return ERRCODE_NONE
;
1582 return ERRCODE_ABORT
;
1585 // ------------------------------------------------------------------------
1586 ErrCode
FileDialogHelper_Impl::execute()
1588 if ( ! mxFileDlg
.is() )
1589 return ERRCODE_ABORT
;
1591 sal_Int16 nRet
= implDoExecute();
1593 maPath
= mxFileDlg
->getDisplayDirectory();
1595 if ( ExecutableDialogResults::CANCEL
== nRet
)
1596 return ERRCODE_ABORT
;
1599 return ERRCODE_NONE
;
1603 // ------------------------------------------------------------------------
1604 OUString
FileDialogHelper_Impl::getPath() const
1608 if ( mxFileDlg
.is() )
1609 aPath
= mxFileDlg
->getDisplayDirectory();
1611 if ( aPath
.isEmpty() )
1617 // ------------------------------------------------------------------------
1618 OUString
FileDialogHelper_Impl::getFilter() const
1620 String aFilter
= getCurrentFilterUIName();
1622 if( !aFilter
.Len() )
1623 aFilter
= maCurFilter
;
1628 // ------------------------------------------------------------------------
1629 void FileDialogHelper_Impl::getRealFilter( String
& _rFilter
) const
1631 _rFilter
= getCurrentFilterUIName();
1633 if ( !_rFilter
.Len() )
1634 _rFilter
= maCurFilter
;
1636 if ( _rFilter
.Len() && mpMatcher
)
1638 const SfxFilter
* pFilter
=
1639 mpMatcher
->GetFilter4UIName( _rFilter
, m_nMustFlags
, m_nDontFlags
);
1640 _rFilter
= pFilter
? pFilter
->GetFilterName() : _rFilter
.Erase();
1644 void FileDialogHelper_Impl::verifyPath()
1647 // lp#905355, fdo#43895
1648 // Check that the file has read only permission and is in /tmp -- this is
1649 // the case if we have opened the file from the web with firefox only.
1650 if (maFileName
.isEmpty()) {
1653 INetURLObject
url(maPath
);
1654 if (url
.GetProtocol() != INET_PROT_FILE
1655 || url
.getName(0, true, INetURLObject::DECODE_WITH_CHARSET
) != "tmp")
1659 if (maFileName
.indexOf('/') != -1) {
1660 SAL_WARN("sfx2", maFileName
<< " contains /");
1664 maFileName
, false, INetURLObject::LAST_SEGMENT
, true,
1665 INetURLObject::ENCODE_ALL
);
1666 rtl::OUString sysPathU
;
1667 osl::FileBase::RC e
= osl::FileBase::getSystemPathFromFileURL(
1668 url
.GetMainURL(INetURLObject::NO_DECODE
), sysPathU
);
1669 if (e
!= osl::FileBase::E_None
) {
1672 "getSystemPathFromFileURL("
1673 << url
.GetMainURL(INetURLObject::NO_DECODE
) << ") failed with "
1677 rtl::OString sysPathC
;
1678 if (!sysPathU
.convertToString(
1679 &sysPathC
, osl_getThreadTextEncoding(),
1680 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
1681 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
1685 "convertToString(" << sysPathU
<< ") failed for encoding "
1686 << +osl_getThreadTextEncoding());
1689 struct stat aFileStat
;
1690 if (stat(sysPathC
.getStr(), &aFileStat
) == -1) {
1693 "stat(" << sysPathC
.getStr() << ") failed with errno " << errno
);
1696 if ((aFileStat
.st_mode
& (S_IRWXO
| S_IRWXG
| S_IRWXU
)) == S_IRUSR
) {
1697 maPath
= SvtPathOptions().GetWorkPath();
1698 mxFileDlg
->setDisplayDirectory( maPath
);
1703 // ------------------------------------------------------------------------
1704 void FileDialogHelper_Impl::displayFolder( const ::rtl::OUString
& _rPath
)
1706 if ( _rPath
.isEmpty() )
1711 if ( mxFileDlg
.is() )
1715 mxFileDlg
->setDisplayDirectory( maPath
);
1718 catch( const IllegalArgumentException
& )
1720 OSL_FAIL( "FileDialogHelper_Impl::displayFolder: caught an exception!" );
1725 // ------------------------------------------------------------------------
1726 void FileDialogHelper_Impl::setFileName( const ::rtl::OUString
& _rFile
)
1728 maFileName
= _rFile
;
1729 if ( mxFileDlg
.is() )
1733 mxFileDlg
->setDefaultName( maFileName
);
1736 catch( const IllegalArgumentException
& )
1738 OSL_FAIL( "FileDialogHelper_Impl::setFileName: caught an exception!" );
1743 // ------------------------------------------------------------------------
1744 void FileDialogHelper_Impl::setFilter( const OUString
& rFilter
)
1746 DBG_ASSERT( rFilter
.indexOf(':') == -1, "Old filter name used!");
1748 maCurFilter
= rFilter
;
1750 if ( !rFilter
.isEmpty() && mpMatcher
)
1752 const SfxFilter
* pFilter
= mpMatcher
->GetFilter4FilterName(
1753 rFilter
, m_nMustFlags
, m_nDontFlags
);
1755 maCurFilter
= pFilter
->GetUIName();
1758 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
1760 if ( !maCurFilter
.isEmpty() && xFltMgr
.is() )
1764 xFltMgr
->setCurrentFilter( maCurFilter
);
1766 catch( const IllegalArgumentException
& ){}
1770 // ------------------------------------------------------------------------
1771 void FileDialogHelper_Impl::createMatcher( const String
& rFactory
)
1773 mpMatcher
= new SfxFilterMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory
) );
1774 mbDeleteMatcher
= sal_True
;
1777 // ------------------------------------------------------------------------
1778 void FileDialogHelper_Impl::addFilters( const String
& rFactory
,
1779 SfxFilterFlags nMust
,
1780 SfxFilterFlags nDont
)
1782 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
1784 if ( ! xFltMgr
.is() )
1787 // we still need a matcher to convert UI names to filter names
1788 if ( !rFactory
.Len() )
1790 SfxApplication
*pSfxApp
= SFX_APP();
1791 mpMatcher
= &pSfxApp
->GetFilterMatcher();
1792 mbDeleteMatcher
= sal_False
;
1796 mpMatcher
= new SfxFilterMatcher( rFactory
);
1797 mbDeleteMatcher
= sal_True
;
1800 uno::Reference
< XMultiServiceFactory
> xSMGR
= ::comphelper::getProcessServiceFactory();
1801 uno::Reference
< XContainerQuery
> xFilterCont(
1802 xSMGR
->createInstance(::rtl::OUString("com.sun.star.document.FilterFactory")),
1804 if ( ! xFilterCont
.is() )
1807 m_nMustFlags
|= nMust
;
1808 m_nDontFlags
|= nDont
;
1810 // create the list of filters
1811 ::rtl::OUStringBuffer
sQuery(256);
1812 sQuery
.appendAscii(RTL_CONSTASCII_STRINGPARAM("getSortedFilterList()"));
1813 sQuery
.appendAscii(RTL_CONSTASCII_STRINGPARAM(":module="));
1814 sQuery
.append(rFactory
); // use long name here !
1815 sQuery
.appendAscii(RTL_CONSTASCII_STRINGPARAM(":iflags="));
1816 sQuery
.append(::rtl::OUString::valueOf((sal_Int32
)m_nMustFlags
));
1817 sQuery
.appendAscii(RTL_CONSTASCII_STRINGPARAM(":eflags="));
1818 sQuery
.append(::rtl::OUString::valueOf((sal_Int32
)m_nDontFlags
));
1820 uno::Reference
< XEnumeration
> xResult
;
1823 xResult
= xFilterCont
->createSubSetEnumerationByQuery(sQuery
.makeStringAndClear());
1825 catch( const uno::Exception
& )
1827 SAL_WARN( "sfx2.dialog", "Could not get filters from the configuration!" );
1830 TSortedFilterList
aIter (xResult
);
1832 // no matcher any longer used ...
1833 mbDeleteMatcher
= sal_False
;
1835 // append the filters
1836 ::rtl::OUString sFirstFilter
;
1837 if (OPEN
== lcl_OpenOrSave(m_nDialogType
))
1838 ::sfx2::appendFiltersForOpen( aIter
, xFltMgr
, sFirstFilter
, *this );
1839 else if ( mbExport
)
1840 ::sfx2::appendExportFilters( aIter
, xFltMgr
, sFirstFilter
, *this );
1842 ::sfx2::appendFiltersForSave( aIter
, xFltMgr
, sFirstFilter
, *this, rFactory
);
1844 // set our initial selected filter (if we do not already have one)
1845 if ( maSelectFilter
.isEmpty() )
1846 maSelectFilter
= sFirstFilter
;
1849 // ------------------------------------------------------------------------
1850 void FileDialogHelper_Impl::addFilter( const OUString
& rFilterName
,
1851 const OUString
& rExtension
)
1853 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
1855 if ( ! xFltMgr
.is() )
1860 xFltMgr
->appendFilter( rFilterName
, rExtension
);
1862 if ( maSelectFilter
.isEmpty() )
1863 maSelectFilter
= rFilterName
;
1865 catch( const IllegalArgumentException
& )
1867 SAL_WARN( "sfx2.dialog", "Could not append Filter" << rFilterName
);
1871 // ------------------------------------------------------------------------
1872 void FileDialogHelper_Impl::addGraphicFilter()
1874 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
1876 if ( ! xFltMgr
.is() )
1879 // create the list of filters
1880 mpGraphicFilter
= new GraphicFilter
;
1881 sal_uInt16 i
, j
, nCount
= mpGraphicFilter
->GetImportFormatCount();
1883 // compute the extension string for all known import filters
1886 for ( i
= 0; i
< nCount
; i
++ )
1892 sWildcard
= mpGraphicFilter
->GetImportWildcard( i
, j
++ );
1893 if ( !sWildcard
.Len() )
1895 if ( aExtensions
.Search( sWildcard
) == STRING_NOTFOUND
)
1897 if ( aExtensions
.Len() )
1898 aExtensions
+= sal_Unicode(';');
1899 aExtensions
+= sWildcard
;
1905 if ( aExtensions
.Len() > 240 )
1906 aExtensions
= DEFINE_CONST_UNICODE( FILEDIALOG_FILTER_ALL
);
1908 sal_Bool bIsInOpenMode
= isInOpenMode();
1912 OUString aAllFilterName
= String( SfxResId( STR_SFX_IMPORT_ALL
) );
1913 aAllFilterName
= ::sfx2::addExtension( aAllFilterName
, aExtensions
, bIsInOpenMode
, *this );
1915 xFltMgr
->appendFilter( aAllFilterName
, aExtensions
);
1916 maSelectFilter
= aAllFilterName
;
1918 catch( const IllegalArgumentException
& )
1920 SAL_WARN( "sfx2.dialog", "Could not append Filter" );
1923 // Now add the filter
1924 for ( i
= 0; i
< nCount
; i
++ )
1926 String aName
= mpGraphicFilter
->GetImportFormatName( i
);
1932 sWildcard
= mpGraphicFilter
->GetImportWildcard( i
, j
++ );
1933 if ( !sWildcard
.Len() )
1935 if ( aExt
.Search( sWildcard
) == STRING_NOTFOUND
)
1938 aExt
+= sal_Unicode(';');
1942 aName
= ::sfx2::addExtension( aName
, aExt
, bIsInOpenMode
, *this );
1945 xFltMgr
->appendFilter( aName
, aExt
);
1947 catch( const IllegalArgumentException
& )
1949 SAL_WARN( "sfx2.dialog", "Could not append Filter" );
1954 // ------------------------------------------------------------------------
1955 #define GRF_CONFIG_STR " "
1956 #define STD_CONFIG_STR "1 "
1958 void FileDialogHelper_Impl::saveConfig()
1960 uno::Reference
< XFilePickerControlAccess
> xDlg( mxFileDlg
, UNO_QUERY
);
1968 SvtViewOptions
aDlgOpt( E_DIALOG
, IMPGRF_CONFIGNAME
);
1969 String aUserData
= DEFINE_CONST_UNICODE( GRF_CONFIG_STR
);
1973 sal_Bool bValue
= sal_False
;
1974 aValue
= xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0 );
1977 aUserData
.SetToken( 1, ' ', String::CreateFromInt32( (sal_Int32
) bValue
) );
1979 INetURLObject
aObj( getPath() );
1981 if ( aObj
.GetProtocol() == INET_PROT_FILE
)
1982 aUserData
.SetToken( 2, ' ', aObj
.GetMainURL( INetURLObject::NO_DECODE
) );
1984 String aFilter
= getFilter();
1985 aFilter
= EncodeSpaces_Impl( aFilter
);
1986 aUserData
.SetToken( 3, ' ', aFilter
);
1988 aDlgOpt
.SetUserItem( USERITEM_NAME
, makeAny( OUString( aUserData
) ) );
1990 catch( const IllegalArgumentException
& ){}
1994 sal_Bool bWriteConfig
= sal_False
;
1995 SvtViewOptions
aDlgOpt( E_DIALOG
, IODLG_CONFIGNAME
);
1996 String aUserData
= DEFINE_CONST_UNICODE( STD_CONFIG_STR
);
1998 if ( aDlgOpt
.Exists() )
2000 Any aUserItem
= aDlgOpt
.GetUserItem( USERITEM_NAME
);
2002 if ( aUserItem
>>= aTemp
)
2003 aUserData
= String( aTemp
);
2010 aValue
= xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0 );
2011 sal_Bool bAutoExt
= sal_True
;
2012 aValue
>>= bAutoExt
;
2013 aUserData
.SetToken( 0, ' ', String::CreateFromInt32( (sal_Int32
) bAutoExt
) );
2014 bWriteConfig
= sal_True
;
2016 catch( const IllegalArgumentException
& ){}
2019 if ( ! mbIsSaveDlg
)
2021 OUString aPath
= getPath();
2022 if ( !aPath
.isEmpty() &&
2023 utl::LocalFileHelper::IsLocalFile( aPath
) )
2025 aUserData
.SetToken( 1, ' ', aPath
);
2026 bWriteConfig
= sal_True
;
2030 if( mbHasSelectionBox
&& mbSelectionFltrEnabled
)
2034 aValue
= xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0 );
2035 sal_Bool bSelection
= sal_True
;
2036 aValue
>>= bSelection
;
2037 if ( comphelper::string::getTokenCount(aUserData
, ' ') < 3 )
2038 aUserData
.Append(' ');
2039 aUserData
.SetToken( 2, ' ', String::CreateFromInt32( (sal_Int32
) bSelection
) );
2040 bWriteConfig
= sal_True
;
2042 catch( const IllegalArgumentException
& ){}
2046 aDlgOpt
.SetUserItem( USERITEM_NAME
, makeAny( OUString( aUserData
) ) );
2049 SfxApplication
*pSfxApp
= SFX_APP();
2050 pSfxApp
->SetLastDir_Impl( getPath() );
2053 // ------------------------------------------------------------------------
2056 static ::rtl::OUString
getInitPath( const String
& _rFallback
, const xub_StrLen _nFallbackToken
)
2058 SfxApplication
*pSfxApp
= SFX_APP();
2059 String sPath
= pSfxApp
->GetLastDir_Impl();
2062 sPath
= _rFallback
.GetToken( _nFallbackToken
, ' ' );
2064 // check if the path points to a valid (accessible) directory
2065 sal_Bool bValid
= sal_False
;
2068 String
sPathCheck( sPath
);
2069 if ( sPathCheck
.GetBuffer()[ sPathCheck
.Len() - 1 ] != '/' )
2074 ::ucbhelper::Content
aContent( sPathCheck
, uno::Reference
< ucb::XCommandEnvironment
>() );
2075 bValid
= aContent
.isFolder();
2077 catch( const Exception
& ) {}
2087 // ------------------------------------------------------------------------
2088 void FileDialogHelper_Impl::loadConfig()
2090 uno::Reference
< XFilePickerControlAccess
> xDlg( mxFileDlg
, UNO_QUERY
);
2098 SvtViewOptions
aViewOpt( E_DIALOG
, IMPGRF_CONFIGNAME
);
2101 if ( aViewOpt
.Exists() )
2103 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
2105 if ( aUserItem
>>= aTemp
)
2106 aUserData
= String( aTemp
);
2109 if ( aUserData
.Len() > 0 )
2113 // respect the last "show preview" state
2114 sal_Bool bShowPreview
= (sal_Bool
) aUserData
.GetToken( 1, ' ' ).ToInt32();
2115 if ( !xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0 ).hasValue() )
2117 aValue
<<= bShowPreview
;
2118 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0, aValue
);
2121 if ( maPath
.isEmpty() )
2122 displayFolder( getInitPath( aUserData
, 2 ) );
2124 if ( maCurFilter
.isEmpty() )
2126 String aFilter
= aUserData
.GetToken( 3, ' ' );
2127 aFilter
= DecodeSpaces_Impl( aFilter
);
2128 setFilter( aFilter
);
2131 // set the member so we know that we have to show the preview
2132 mbShowPreview
= bShowPreview
;
2134 catch( const IllegalArgumentException
& ){}
2137 if ( maPath
.isEmpty() )
2138 displayFolder( SvtPathOptions().GetGraphicPath() );
2142 SvtViewOptions
aViewOpt( E_DIALOG
, IODLG_CONFIGNAME
);
2145 if ( aViewOpt
.Exists() )
2147 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
2149 if ( aUserItem
>>= aTemp
)
2150 aUserData
= String( aTemp
);
2153 if ( ! aUserData
.Len() )
2154 aUserData
= DEFINE_CONST_UNICODE( STD_CONFIG_STR
);
2156 if ( maPath
.isEmpty() )
2157 displayFolder( getInitPath( aUserData
, 1 ) );
2161 sal_Int32 nFlag
= aUserData
.GetToken( 0, ' ' ).ToInt32();
2162 aValue
<<= (sal_Bool
) nFlag
;
2165 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0, aValue
);
2167 catch( const IllegalArgumentException
& ){}
2170 if( mbHasSelectionBox
)
2172 sal_Int32 nFlag
= aUserData
.GetToken( 2, ' ' ).ToInt32();
2173 aValue
<<= (sal_Bool
) nFlag
;
2176 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0, aValue
);
2178 catch( const IllegalArgumentException
& ){}
2181 if ( maPath
.isEmpty() )
2182 displayFolder( SvtPathOptions().GetWorkPath() );
2186 // ------------------------------------------------------------------------
2187 void FileDialogHelper_Impl::setDefaultValues()
2189 // when no filter is set, we set the curentFilter to <all>
2190 if ( maCurFilter
.isEmpty() && !maSelectFilter
.isEmpty() )
2192 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
2195 xFltMgr
->setCurrentFilter( maSelectFilter
);
2197 catch( const IllegalArgumentException
& )
2201 // when no path is set, we use the standard 'work' folder
2202 if ( maPath
.isEmpty() )
2204 OUString aWorkFolder
= SvtPathOptions().GetWorkPath();
2207 mxFileDlg
->setDisplayDirectory( aWorkFolder
);
2209 catch( const Exception
& )
2211 OSL_FAIL( "FileDialogHelper_Impl::setDefaultValues: caught an exception while setting the display directory!" );
2216 sal_Bool
FileDialogHelper_Impl::isShowFilterExtensionEnabled() const
2218 return !maFilters
.empty();
2221 void FileDialogHelper_Impl::addFilterPair( const OUString
& rFilter
,
2222 const OUString
& rFilterWithExtension
)
2224 maFilters
.push_back( FilterPair( rFilter
, rFilterWithExtension
) );
2228 OUString
FileDialogHelper_Impl::getFilterName( const OUString
& rFilterWithExtension
) const
2231 for( ::std::vector
< FilterPair
>::const_iterator pIter
= maFilters
.begin(); pIter
!= maFilters
.end(); ++pIter
)
2233 if ( (*pIter
).Second
== rFilterWithExtension
)
2235 sRet
= (*pIter
).First
;
2242 OUString
FileDialogHelper_Impl::getFilterWithExtension( const OUString
& rFilter
) const
2245 for( ::std::vector
< FilterPair
>::const_iterator pIter
= maFilters
.begin(); pIter
!= maFilters
.end(); ++pIter
)
2247 if ( (*pIter
).First
== rFilter
)
2249 sRet
= (*pIter
).Second
;
2256 void FileDialogHelper_Impl::SetContext( FileDialogHelper::Context _eNewContext
)
2258 meContext
= _eNewContext
;
2260 const OUString
* pConfigId
= GetLastFilterConfigId( _eNewContext
);
2262 LoadLastUsedFilter( *pConfigId
);
2265 // ------------------------------------------------------------------------
2266 // ----------- FileDialogHelper ---------------------------
2267 // ------------------------------------------------------------------------
2269 FileDialogHelper::FileDialogHelper(
2270 sal_Int16 nDialogType
,
2272 const String
& rFact
,
2273 SfxFilterFlags nMust
,
2274 SfxFilterFlags nDont
)
2276 mpImp
= new FileDialogHelper_Impl( this, nDialogType
, nFlags
);
2279 // create the list of filters
2281 SfxObjectShell::GetServiceNameFromFactory(rFact
), nMust
, nDont
);
2284 // ------------------------------------------------------------------------
2285 FileDialogHelper::FileDialogHelper(
2286 sal_Int16 nDialogType
,
2288 const String
& rFact
,
2290 SfxFilterFlags nMust
,
2291 SfxFilterFlags nDont
,
2292 const String
& rStandardDir
,
2293 const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& rBlackList
)
2295 mpImp
= new FileDialogHelper_Impl( this, nDialogType
, nFlags
, nDialog
, NULL
, rStandardDir
, rBlackList
);
2298 // create the list of filters
2300 SfxObjectShell::GetServiceNameFromFactory(rFact
), nMust
, nDont
);
2303 // ------------------------------------------------------------------------
2304 FileDialogHelper::FileDialogHelper(
2305 sal_Int16 nDialogType
,
2307 Window
* _pPreferredParent
)
2309 mpImp
= new FileDialogHelper_Impl( this, nDialogType
, nFlags
, SFX2_IMPL_DIALOG_CONFIG
, _pPreferredParent
);
2313 // ------------------------------------------------------------------------
2314 FileDialogHelper::FileDialogHelper(
2315 sal_Int16 nDialogType
,
2317 const ::rtl::OUString
& aFilterUIName
,
2318 const ::rtl::OUString
& aExtName
,
2319 const ::rtl::OUString
& rStandardDir
,
2320 const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& rBlackList
,
2321 Window
* _pPreferredParent
)
2323 mpImp
= new FileDialogHelper_Impl( this, nDialogType
, nFlags
, SFX2_IMPL_DIALOG_CONFIG
, _pPreferredParent
,rStandardDir
, rBlackList
);
2326 // the wildcard here is expected in form "*.extension"
2327 ::rtl::OUString aWildcard
;
2328 if ( aExtName
.indexOf( (sal_Unicode
)'*' ) != 0 )
2330 if ( !aExtName
.isEmpty() && aExtName
.indexOf( (sal_Unicode
)'.' ) != 0 )
2331 aWildcard
= ::rtl::OUString( "*." );
2333 aWildcard
= ::rtl::OUString( "*" );
2336 aWildcard
+= aExtName
;
2338 ::rtl::OUString
const aUIString
= ::sfx2::addExtension( aFilterUIName
,
2339 aWildcard
, (OPEN
== lcl_OpenOrSave(mpImp
->m_nDialogType
)), *mpImp
);
2340 AddFilter( aUIString
, aWildcard
);
2343 // ------------------------------------------------------------------------
2344 FileDialogHelper::~FileDialogHelper()
2350 // ------------------------------------------------------------------------
2351 void FileDialogHelper::CreateMatcher( const String
& rFactory
)
2353 mpImp
->createMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory
) );
2356 // ------------------------------------------------------------------------
2357 void FileDialogHelper::SetControlHelpIds( const sal_Int16
* _pControlId
, const char** _pHelpId
)
2359 mpImp
->setControlHelpIds( _pControlId
, _pHelpId
);
2362 void FileDialogHelper::SetContext( Context _eNewContext
)
2364 mpImp
->SetContext( _eNewContext
);
2367 // ------------------------------------------------------------------------
2368 IMPL_LINK_NOARG(FileDialogHelper
, ExecuteSystemFilePicker
)
2370 m_nError
= mpImp
->execute();
2371 if ( m_aDialogClosedLink
.IsSet() )
2372 m_aDialogClosedLink
.Call( this );
2377 // ------------------------------------------------------------------------
2378 // rDirPath has to be a directory
2379 ErrCode
FileDialogHelper::Execute( std::vector
<rtl::OUString
>& rpURLList
,
2380 SfxItemSet
*& rpSet
,
2382 const String
& rDirPath
)
2384 SetDisplayFolder( rDirPath
);
2385 return mpImp
->execute( rpURLList
, rpSet
, rFilter
);
2389 // ------------------------------------------------------------------------
2390 ErrCode
FileDialogHelper::Execute()
2392 return mpImp
->execute();
2395 // ------------------------------------------------------------------------
2396 ErrCode
FileDialogHelper::Execute( SfxItemSet
*& rpSet
,
2400 std::vector
<rtl::OUString
> rURLList
;
2401 nRet
= mpImp
->execute(rURLList
, rpSet
, rFilter
);
2405 void FileDialogHelper::StartExecuteModal( const Link
& rEndDialogHdl
)
2407 m_aDialogClosedLink
= rEndDialogHdl
;
2408 m_nError
= ERRCODE_NONE
;
2409 if ( mpImp
->isSystemFilePicker() )
2410 Application::PostUserEvent( LINK( this, FileDialogHelper
, ExecuteSystemFilePicker
) );
2412 mpImp
->implStartExecute();
2415 // ------------------------------------------------------------------------
2417 short FileDialogHelper::GetDialogType() const
2419 return mpImp
? mpImp
->m_nDialogType
: 0;
2422 // ------------------------------------------------------------------------
2424 sal_Bool
FileDialogHelper::IsPasswordEnabled() const
2426 return mpImp
? mpImp
->isPasswordEnabled() : sal_False
;
2429 // ------------------------------------------------------------------------
2431 String
FileDialogHelper::GetRealFilter() const
2435 mpImp
->getRealFilter( sFilter
);
2439 // ------------------------------------------------------------------------
2440 void FileDialogHelper::SetTitle( const String
& rNewTitle
)
2442 if ( mpImp
->mxFileDlg
.is() )
2443 mpImp
->mxFileDlg
->setTitle( rNewTitle
);
2446 // ------------------------------------------------------------------------
2447 String
FileDialogHelper::GetPath() const
2451 if ( mpImp
->mlLastURLs
.size() > 0)
2452 return mpImp
->mlLastURLs
[0];
2454 if ( mpImp
->mxFileDlg
.is() )
2456 Sequence
< OUString
> aPathSeq
= mpImp
->mxFileDlg
->getFiles();
2458 if ( aPathSeq
.getLength() == 1 )
2460 aPath
= aPathSeq
[0];
2467 // ------------------------------------------------------------------------
2468 Sequence
< OUString
> FileDialogHelper::GetMPath() const
2470 if ( mpImp
->mlLastURLs
.size() > 0)
2471 return mpImp
->mlLastURLs
.getAsConstList();
2473 if ( mpImp
->mxFileDlg
.is() )
2474 return mpImp
->mxFileDlg
->getFiles();
2477 Sequence
< OUString
> aEmpty
;
2482 // ------------------------------------------------------------------------
2483 Sequence
< ::rtl::OUString
> FileDialogHelper::GetSelectedFiles() const
2485 // a) the new way (optional!)
2486 uno::Sequence
< ::rtl::OUString
> aResultSeq
;
2487 uno::Reference
< XFilePicker2
> xPickNew(mpImp
->mxFileDlg
, UNO_QUERY
);
2490 aResultSeq
= xPickNew
->getSelectedFiles();
2492 // b) the olde way ... non optional.
2495 uno::Reference
< XFilePicker
> xPickOld(mpImp
->mxFileDlg
, UNO_QUERY_THROW
);
2496 Sequence
< OUString
> lFiles
= xPickOld
->getFiles();
2497 ::sal_Int32 nFiles
= lFiles
.getLength();
2500 aResultSeq
= Sequence
< ::rtl::OUString
>( nFiles
-1 );
2502 INetURLObject
aPath( lFiles
[0] );
2503 aPath
.setFinalSlash();
2505 for (::sal_Int32 i
= 1; i
< nFiles
; i
++)
2508 aPath
.Append( lFiles
[i
] );
2510 aPath
.setName( lFiles
[i
] );
2512 aResultSeq
[i
-1] = ::rtl::OUString(aPath
.GetMainURL( INetURLObject::NO_DECODE
));
2516 aResultSeq
= lFiles
;
2522 // ------------------------------------------------------------------------
2523 String
FileDialogHelper::GetDisplayDirectory() const
2525 return mpImp
->getPath();
2528 // ------------------------------------------------------------------------
2529 String
FileDialogHelper::GetCurrentFilter() const
2531 return mpImp
->getFilter();
2534 // ------------------------------------------------------------------------
2535 ErrCode
FileDialogHelper::GetGraphic( Graphic
& rGraphic
) const
2537 return mpImp
->getGraphic( rGraphic
);
2540 // ------------------------------------------------------------------------
2541 static int impl_isFolder( const OUString
& rPath
)
2545 ::ucbhelper::Content
aContent(
2546 rPath
, uno::Reference
< ucb::XCommandEnvironment
> () );
2547 if ( aContent
.isFolder() )
2552 catch ( const Exception
& )
2559 void FileDialogHelper::SetDisplayDirectory( const String
& _rPath
)
2561 if ( !_rPath
.Len() )
2564 // if the given path isn't a folder, we cut off the last part
2565 // and take it as filename and the rest of the path should be
2568 INetURLObject
aObj( _rPath
);
2570 ::rtl::OUString sFileName
= aObj
.GetName( INetURLObject::DECODE_WITH_CHARSET
);
2571 aObj
.removeSegment();
2572 ::rtl::OUString sPath
= aObj
.GetMainURL( INetURLObject::NO_DECODE
);
2574 int nIsFolder
= impl_isFolder( _rPath
);
2575 if ( nIsFolder
== 0 ||
2576 ( nIsFolder
== -1 && impl_isFolder( sPath
) == 1 ) )
2578 mpImp
->setFileName( sFileName
);
2579 mpImp
->displayFolder( sPath
);
2583 INetURLObject
aObjPathName( _rPath
);
2584 ::rtl::OUString
sFolder( aObjPathName
.GetMainURL( INetURLObject::NO_DECODE
) );
2585 if ( sFolder
.isEmpty() )
2587 // _rPath is not a valid path -> fallback to home directory
2588 osl::Security aSecurity
;
2589 aSecurity
.getHomeDir( sFolder
);
2591 mpImp
->displayFolder( sFolder
);
2595 // ------------------------------------------------------------------------
2596 void FileDialogHelper::SetDisplayFolder( const String
& _rURL
)
2598 mpImp
->displayFolder( _rURL
);
2601 // ------------------------------------------------------------------------
2602 void FileDialogHelper::SetFileName( const String
& _rFileName
)
2604 mpImp
->setFileName( _rFileName
);
2607 // ------------------------------------------------------------------------
2608 void FileDialogHelper::AddFilter( const String
& rFilterName
,
2609 const String
& rExtension
)
2611 mpImp
->addFilter( rFilterName
, rExtension
);
2614 // ------------------------------------------------------------------------
2615 void FileDialogHelper::SetCurrentFilter( const String
& rFilter
)
2617 String
sFilter( rFilter
);
2618 if ( mpImp
->isShowFilterExtensionEnabled() )
2619 sFilter
= mpImp
->getFilterWithExtension( rFilter
);
2620 mpImp
->setFilter( sFilter
);
2623 // ------------------------------------------------------------------------
2624 uno::Reference
< XFilePicker
> FileDialogHelper::GetFilePicker() const
2626 return mpImp
->mxFileDlg
;
2629 // ------------------------------------------------------------------------
2630 // XFilePickerListener Methods
2631 // ------------------------------------------------------------------------
2632 void SAL_CALL
FileDialogHelper::FileSelectionChanged( const FilePickerEvent
& aEvent
)
2634 mpImp
->handleFileSelectionChanged( aEvent
);
2637 // ------------------------------------------------------------------------
2638 void SAL_CALL
FileDialogHelper::DirectoryChanged( const FilePickerEvent
& aEvent
)
2640 mpImp
->handleDirectoryChanged( aEvent
);
2643 // ------------------------------------------------------------------------
2644 OUString SAL_CALL
FileDialogHelper::HelpRequested( const FilePickerEvent
& aEvent
)
2646 return mpImp
->handleHelpRequested( aEvent
);
2649 // ------------------------------------------------------------------------
2650 void SAL_CALL
FileDialogHelper::ControlStateChanged( const FilePickerEvent
& aEvent
)
2652 mpImp
->handleControlStateChanged( aEvent
);
2655 // ------------------------------------------------------------------------
2656 void SAL_CALL
FileDialogHelper::DialogSizeChanged()
2658 mpImp
->handleDialogSizeChanged();
2661 // ------------------------------------------------------------------------
2662 void SAL_CALL
FileDialogHelper::DialogClosed( const DialogClosedEvent
& _rEvent
)
2664 m_nError
= ( RET_OK
== _rEvent
.DialogResult
) ? ERRCODE_NONE
: ERRCODE_ABORT
;
2665 if ( m_aDialogClosedLink
.IsSet() )
2666 m_aDialogClosedLink
.Call( this );
2669 // ------------------------------------------------------------------------
2671 ErrCode
FileOpenDialog_Impl( sal_Int16 nDialogType
,
2673 const String
& rFact
,
2674 std::vector
<rtl::OUString
>& rpURLList
,
2676 SfxItemSet
*& rpSet
,
2677 const String
* pPath
,
2679 const String
& rStandardDir
,
2680 const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& rBlackList
)
2683 FileDialogHelper
aDialog( nDialogType
, nFlags
,
2684 rFact
, nDialog
, 0, 0, rStandardDir
, rBlackList
);
2690 nRet
= aDialog
.Execute( rpURLList
, rpSet
, rFilter
, aPath
);
2691 DBG_ASSERT( rFilter
.SearchAscii(": ") == STRING_NOTFOUND
, "Old filter name used!");
2696 ErrCode
RequestPassword(const SfxFilter
* pCurrentFilter
, rtl::OUString
& aURL
, SfxItemSet
* pSet
)
2698 uno::Reference
< ::com::sun::star::task::XInteractionHandler
> xInteractionHandler( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString("com.sun.star.comp.uui.UUIInteractionHandler")), UNO_QUERY
);
2699 if( xInteractionHandler
.is() )
2701 // TODO: need a save way to distinguish MS filters from other filters
2702 // for now MS-filters are the only alien filters that support encryption
2703 sal_Bool bMSType
= !pCurrentFilter
->IsOwnFormat();
2704 ::comphelper::DocPasswordRequestType eType
= bMSType
?
2705 ::comphelper::DocPasswordRequestType_MS
:
2706 ::comphelper::DocPasswordRequestType_STANDARD
;
2708 ::rtl::Reference
< ::comphelper::DocPasswordRequest
> pPasswordRequest( new ::comphelper::DocPasswordRequest( eType
, ::com::sun::star::task::PasswordRequestMode_PASSWORD_CREATE
, aURL
, ( pCurrentFilter
->GetFilterFlags() & SFX_FILTER_PASSWORDTOMODIFY
) != 0 ) );
2710 uno::Reference
< com::sun::star::task::XInteractionRequest
> rRequest( pPasswordRequest
.get() );
2711 xInteractionHandler
->handle( rRequest
);
2712 if ( pPasswordRequest
->isPassword() )
2714 if ( pPasswordRequest
->getPassword().getLength() )
2716 // TODO/LATER: The filters should show the password dialog themself in future
2719 // all the current MS-filters use MSCodec_Std97 implementation
2720 uno::Sequence
< sal_Int8
> aUniqueID
= ::comphelper::DocPasswordHelper::GenerateRandomByteSequence( 16 );
2721 uno::Sequence
< sal_Int8
> aEncryptionKey
= ::comphelper::DocPasswordHelper::GenerateStd97Key( pPasswordRequest
->getPassword(), aUniqueID
);
2723 if ( aEncryptionKey
.getLength() )
2725 ::comphelper::SequenceAsHashMap aHashData
;
2726 aHashData
[ ::rtl::OUString( "STD97EncryptionKey" ) ] <<= aEncryptionKey
;
2727 aHashData
[ ::rtl::OUString( "STD97UniqueID" ) ] <<= aUniqueID
;
2729 pSet
->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aHashData
.getAsConstNamedValueList() ) ) );
2732 return ERRCODE_IO_NOTSUPPORTED
;
2736 pSet
->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( ::comphelper::OStorageHelper::CreatePackageEncryptionData( pPasswordRequest
->getPassword() ) ) ) );
2740 if ( pPasswordRequest
->getRecommendReadOnly() )
2741 pSet
->Put( SfxBoolItem( SID_RECOMMENDREADONLY
, sal_True
) );
2745 // the empty password has 0 as Hash
2746 sal_Int32 nHash
= SfxMedium::CreatePasswordToModifyHash( pPasswordRequest
->getPasswordToModify(), ::rtl::OUString( "com.sun.star.text.TextDocument" ).equals( pCurrentFilter
->GetServiceName() ) );
2748 pSet
->Put( SfxUnoAnyItem( SID_MODIFYPASSWORDINFO
, uno::makeAny( nHash
) ) );
2752 uno::Sequence
< beans::PropertyValue
> aModifyPasswordInfo
= ::comphelper::DocPasswordHelper::GenerateNewModifyPasswordInfo( pPasswordRequest
->getPasswordToModify() );
2753 if ( aModifyPasswordInfo
.getLength() )
2754 pSet
->Put( SfxUnoAnyItem( SID_MODIFYPASSWORDINFO
, uno::makeAny( aModifyPasswordInfo
) ) );
2758 return ERRCODE_ABORT
;
2760 return ERRCODE_NONE
;
2763 // ------------------------------------------------------------------------
2764 String
EncodeSpaces_Impl( const String
& rSource
)
2766 String
sRet( rSource
);
2767 sRet
.SearchAndReplaceAll( DEFINE_CONST_UNICODE( " " ), DEFINE_CONST_UNICODE( "%20" ) );
2771 // ------------------------------------------------------------------------
2772 String
DecodeSpaces_Impl( const String
& rSource
)
2774 String
sRet( rSource
);
2775 sRet
.SearchAndReplaceAll( DEFINE_CONST_UNICODE( "%20" ), DEFINE_CONST_UNICODE( " " ) );
2779 // ------------------------------------------------------------------------
2781 } // end of namespace sfx2
2783 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */