1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sfx2/filedlghelper.hxx>
21 #include <sal/types.h>
22 #include <com/sun/star/lang/XInitialization.hpp>
23 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
24 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
25 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
26 #include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
27 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
28 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
29 #include <com/sun/star/ui/dialogs/XControlInformation.hpp>
30 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
31 #include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp>
32 #include <com/sun/star/ui/dialogs/XFilePreview.hpp>
33 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
34 #include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp>
35 #include <com/sun/star/ui/dialogs/XFilePicker2.hpp>
36 #include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
37 #include <com/sun/star/lang/XServiceInfo.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/beans/NamedValue.hpp>
40 #include <com/sun/star/embed/ElementModes.hpp>
41 #include <com/sun/star/container/XEnumeration.hpp>
42 #include <com/sun/star/container/XContainerQuery.hpp>
43 #include <com/sun/star/task/InteractionHandler.hpp>
44 #include <com/sun/star/task/XInteractionRequest.hpp>
45 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
47 #include <comphelper/processfactory.hxx>
48 #include <comphelper/sequenceashashmap.hxx>
49 #include <comphelper/stillreadwriteinteraction.hxx>
50 #include <comphelper/string.hxx>
51 #include <comphelper/types.hxx>
52 #include <tools/urlobj.hxx>
53 #include <vcl/help.hxx>
54 #include <unotools/ucbstreamhelper.hxx>
55 #include <unotools/ucbhelper.hxx>
56 #include <unotools/localfilehelper.hxx>
57 #include <osl/file.hxx>
58 #include <osl/mutex.hxx>
59 #include <osl/security.hxx>
60 #include <osl/thread.hxx>
61 #include <vcl/cvtgrf.hxx>
62 #include <vcl/msgbox.hxx>
63 #include <vcl/mnemonic.hxx>
64 #include <unotools/pathoptions.hxx>
65 #include <unotools/securityoptions.hxx>
66 #include <svl/itemset.hxx>
67 #include <svl/eitem.hxx>
68 #include <svl/intitem.hxx>
69 #include <svl/stritem.hxx>
70 #include <vcl/graphicfilter.hxx>
71 #include <unotools/viewoptions.hxx>
72 #include <unotools/moduleoptions.hxx>
73 #include <svtools/helpid.hrc>
74 #include <comphelper/docpasswordrequest.hxx>
75 #include <comphelper/docpasswordhelper.hxx>
76 #include <ucbhelper/content.hxx>
77 #include <ucbhelper/commandenvironment.hxx>
78 #include <comphelper/storagehelper.hxx>
79 #include <toolkit/helper/vclunohelper.hxx>
80 #include <sfx2/app.hxx>
81 #include <sfx2/frame.hxx>
82 #include <sfx2/docfile.hxx>
83 #include <sfx2/docfac.hxx>
84 #include "openflag.hxx"
85 #include <sfx2/passwd.hxx>
86 #include "sfx2/sfxresid.hxx"
87 #include <sfx2/sfxsids.hrc>
88 #include "filedlghelper.hrc"
89 #include "filtergrouping.hxx"
90 #include <sfx2/request.hxx>
91 #include "filedlgimpl.hxx"
93 #include <sfxlocal.hrc>
94 #include <rtl/strbuf.hxx>
101 //-----------------------------------------------------------------------------
103 using namespace ::com::sun::star
;
104 using namespace ::com::sun::star::container
;
105 using namespace ::com::sun::star::lang
;
106 using namespace ::com::sun::star::ui::dialogs
;
107 using namespace ::com::sun::star::ui::dialogs::TemplateDescription
;
108 using namespace ::com::sun::star::uno
;
109 using namespace ::com::sun::star::beans
;
110 using namespace ::rtl
;
111 using namespace ::cppu
;
113 //-----------------------------------------------------------------------------
115 #define IODLG_CONFIGNAME OUString("FilePicker_Save")
116 #define IMPGRF_CONFIGNAME OUString("FilePicker_Graph")
117 #define USERITEM_NAME OUString("UserItem")
119 //-----------------------------------------------------------------------------
124 const OUString
* GetLastFilterConfigId( FileDialogHelper::Context _eContext
)
126 static const OUString
aSD_EXPORT_IDENTIFIER( "SdExportLastFilter" );
127 static const OUString
aSI_EXPORT_IDENTIFIER( "SiExportLastFilter" );
128 static const OUString
aSW_EXPORT_IDENTIFIER( "SwExportLastFilter" );
130 const OUString
* pRet
= NULL
;
134 case FileDialogHelper::SD_EXPORT
: pRet
= &aSD_EXPORT_IDENTIFIER
; break;
135 case FileDialogHelper::SI_EXPORT
: pRet
= &aSI_EXPORT_IDENTIFIER
; break;
136 case FileDialogHelper::SW_EXPORT
: pRet
= &aSW_EXPORT_IDENTIFIER
; break;
143 String
EncodeSpaces_Impl( const String
& rSource
);
144 String
DecodeSpaces_Impl( const String
& rSource
);
146 // ------------------------------------------------------------------------
147 // ----------- FileDialogHelper_Impl ---------------------------
148 // ------------------------------------------------------------------------
150 // ------------------------------------------------------------------------
151 // XFilePickerListener Methods
152 // ------------------------------------------------------------------------
153 void SAL_CALL
FileDialogHelper_Impl::fileSelectionChanged( const FilePickerEvent
& aEvent
) throw ( RuntimeException
)
155 SolarMutexGuard aGuard
;
156 mpAntiImpl
->FileSelectionChanged( aEvent
);
159 // ------------------------------------------------------------------------
160 void SAL_CALL
FileDialogHelper_Impl::directoryChanged( const FilePickerEvent
& aEvent
) throw ( RuntimeException
)
162 SolarMutexGuard aGuard
;
163 mpAntiImpl
->DirectoryChanged( aEvent
);
166 // ------------------------------------------------------------------------
167 OUString SAL_CALL
FileDialogHelper_Impl::helpRequested( const FilePickerEvent
& aEvent
) throw ( RuntimeException
)
169 SolarMutexGuard aGuard
;
170 return mpAntiImpl
->HelpRequested( aEvent
);
173 // ------------------------------------------------------------------------
174 void SAL_CALL
FileDialogHelper_Impl::controlStateChanged( const FilePickerEvent
& aEvent
) throw ( RuntimeException
)
176 SolarMutexGuard aGuard
;
177 mpAntiImpl
->ControlStateChanged( aEvent
);
180 // ------------------------------------------------------------------------
181 void SAL_CALL
FileDialogHelper_Impl::dialogSizeChanged() throw ( RuntimeException
)
183 SolarMutexGuard aGuard
;
184 mpAntiImpl
->DialogSizeChanged();
187 // ------------------------------------------------------------------------
188 // XDialogClosedListener Methods
189 // ------------------------------------------------------------------------
190 void SAL_CALL
FileDialogHelper_Impl::dialogClosed( const DialogClosedEvent
& _rEvent
) throw ( RuntimeException
)
192 SolarMutexGuard aGuard
;
193 mpAntiImpl
->DialogClosed( _rEvent
);
194 postExecute( _rEvent
.DialogResult
);
197 // ------------------------------------------------------------------------
198 // handle XFilePickerListener events
199 // ------------------------------------------------------------------------
200 void FileDialogHelper_Impl::handleFileSelectionChanged( const FilePickerEvent
& )
206 maPreViewTimer
.Start();
209 // ------------------------------------------------------------------------
210 void FileDialogHelper_Impl::handleDirectoryChanged( const FilePickerEvent
& )
213 TimeOutHdl_Impl( NULL
);
216 // ------------------------------------------------------------------------
217 OUString
FileDialogHelper_Impl::handleHelpRequested( const FilePickerEvent
& aEvent
)
219 //!!! todo: cache the help strings (here or TRA)
222 // mapping from element id -> help id
223 switch ( aEvent
.ElementId
)
225 case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
:
226 sHelpId
= HID_FILESAVE_AUTOEXTENSION
;
229 case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
:
230 sHelpId
= HID_FILESAVE_SAVEWITHPASSWORD
;
233 case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
:
234 sHelpId
= HID_FILESAVE_CUSTOMIZEFILTER
;
237 case ExtendedFilePickerElementIds::CHECKBOX_READONLY
:
238 sHelpId
= HID_FILEOPEN_READONLY
;
241 case ExtendedFilePickerElementIds::CHECKBOX_LINK
:
242 sHelpId
= HID_FILEDLG_LINK_CB
;
245 case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
:
246 sHelpId
= HID_FILEDLG_PREVIEW_CB
;
249 case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY
:
250 sHelpId
= HID_FILESAVE_DOPLAY
;
253 case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL
:
254 case ExtendedFilePickerElementIds::LISTBOX_VERSION
:
255 sHelpId
= HID_FILEOPEN_VERSION
;
258 case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL
:
259 case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE
:
260 sHelpId
= HID_FILESAVE_TEMPLATE
;
263 case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL
:
264 case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE
:
265 sHelpId
= HID_FILEOPEN_IMAGE_TEMPLATE
;
268 case ExtendedFilePickerElementIds::CHECKBOX_SELECTION
:
269 sHelpId
= HID_FILESAVE_SELECTION
;
273 SAL_WARN( "sfx2.dialog", "invalid element id" );
277 Help
* pHelp
= Application::GetHelp();
279 aHelpText
= String( pHelp
->GetHelpText( OStringToOUString(sHelpId
, RTL_TEXTENCODING_UTF8
), NULL
) );
283 // ------------------------------------------------------------------------
284 void FileDialogHelper_Impl::handleControlStateChanged( const FilePickerEvent
& aEvent
)
286 switch ( aEvent
.ElementId
)
288 case CommonFilePickerElementIds::LISTBOX_FILTER
:
289 updateFilterOptionsBox();
290 enablePasswordBox( sal_False
);
291 updateSelectionBox();
292 // only use it for export and with our own dialog
293 if ( mbExport
&& !mbSystemPicker
)
294 updateExportButton();
297 case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
:
298 updatePreviewState();
303 // ------------------------------------------------------------------------
304 void FileDialogHelper_Impl::handleDialogSizeChanged()
307 TimeOutHdl_Impl( NULL
);
310 // ------------------------------------------------------------------------
311 // XEventListener Methods
312 // ------------------------------------------------------------------------
313 void SAL_CALL
FileDialogHelper_Impl::disposing( const EventObject
& ) throw ( RuntimeException
)
315 SolarMutexGuard aGuard
;
319 // ------------------------------------------------------------------------
321 void FileDialogHelper_Impl::dispose()
323 if ( mxFileDlg
.is() )
325 // remove the event listener
326 uno::Reference
< XFilePickerNotifier
> xNotifier( mxFileDlg
, UNO_QUERY
);
327 if ( xNotifier
.is() )
328 xNotifier
->removeFilePickerListener( this );
330 ::comphelper::disposeComponent( mxFileDlg
);
335 // ------------------------------------------------------------------------
336 String
FileDialogHelper_Impl::getCurrentFilterUIName() const
339 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
343 aFilterName
= xFltMgr
->getCurrentFilter();
345 if ( aFilterName
.Len() && isShowFilterExtensionEnabled() )
346 aFilterName
= getFilterName( aFilterName
);
352 // ------------------------------------------------------------------------
353 void FileDialogHelper_Impl::LoadLastUsedFilter( const OUString
& _rContextIdentifier
)
355 SvtViewOptions
aDlgOpt( E_DIALOG
, IODLG_CONFIGNAME
);
357 if( aDlgOpt
.Exists() )
359 OUString aLastFilter
;
360 if( aDlgOpt
.GetUserItem( _rContextIdentifier
) >>= aLastFilter
)
361 setFilter( aLastFilter
);
365 // ------------------------------------------------------------------------
366 void FileDialogHelper_Impl::SaveLastUsedFilter( const OUString
& _rContextIdentifier
)
368 SvtViewOptions( E_DIALOG
, IODLG_CONFIGNAME
).SetUserItem( _rContextIdentifier
,
369 makeAny( getFilterWithExtension( getFilter() ) ) );
372 // ------------------------------------------------------------------------
373 void FileDialogHelper_Impl::SaveLastUsedFilter( void )
375 const OUString
* pConfigId
= GetLastFilterConfigId( meContext
);
377 SaveLastUsedFilter( *pConfigId
);
380 // ------------------------------------------------------------------------
381 const SfxFilter
* FileDialogHelper_Impl::getCurentSfxFilter()
383 String aFilterName
= getCurrentFilterUIName();
385 const SfxFilter
* pFilter
= NULL
;
386 if ( mpMatcher
&& aFilterName
.Len() )
387 pFilter
= mpMatcher
->GetFilter4UIName( aFilterName
, m_nMustFlags
, m_nDontFlags
);
392 // ------------------------------------------------------------------------
393 sal_Bool
FileDialogHelper_Impl::updateExtendedControl( sal_Int16 _nExtendedControlId
, sal_Bool _bEnable
)
395 sal_Bool bIsEnabled
= sal_False
;
397 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
398 if ( xCtrlAccess
.is() )
402 xCtrlAccess
->enableControl( _nExtendedControlId
, _bEnable
);
403 bIsEnabled
= _bEnable
;
405 catch( const IllegalArgumentException
& )
407 OSL_FAIL( "FileDialogHelper_Impl::updateExtendedControl: caught an exception!" );
413 // ------------------------------------------------------------------------
414 sal_Bool
FileDialogHelper_Impl::CheckFilterOptionsCapability( const SfxFilter
* _pFilter
)
416 sal_Bool bResult
= sal_False
;
418 if( mxFilterCFG
.is() && _pFilter
)
421 Sequence
< PropertyValue
> aProps
;
422 Any aAny
= mxFilterCFG
->getByName( _pFilter
->GetName() );
423 if ( aAny
>>= aProps
)
425 OUString aServiceName
;
426 sal_Int32 nPropertyCount
= aProps
.getLength();
427 for( sal_Int32 nProperty
=0; nProperty
< nPropertyCount
; ++nProperty
)
429 if( aProps
[nProperty
].Name
== "UIComponent" )
431 aProps
[nProperty
].Value
>>= aServiceName
;
432 if( !aServiceName
.isEmpty() )
438 catch( const Exception
& )
446 // ------------------------------------------------------------------------
447 sal_Bool
FileDialogHelper_Impl::isInOpenMode() const
449 sal_Bool bRet
= sal_False
;
451 switch ( m_nDialogType
)
453 case FILEOPEN_SIMPLE
:
454 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
456 case FILEOPEN_READONLY_VERSION
:
457 case FILEOPEN_LINK_PREVIEW
:
464 // ------------------------------------------------------------------------
466 void FileDialogHelper_Impl::updateFilterOptionsBox()
468 if ( !m_bHaveFilterOptions
)
471 updateExtendedControl(
472 ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
,
473 CheckFilterOptionsCapability( getCurentSfxFilter() )
477 // ------------------------------------------------------------------------
479 void FileDialogHelper_Impl::updateExportButton()
481 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
482 if ( xCtrlAccess
.is() )
484 OUString
sEllipses( "..." );
485 OUString
sOldLabel( xCtrlAccess
->getLabel( CommonFilePickerElementIds::PUSHBUTTON_OK
) );
487 // initialize button label; we need the label with the mnemonic char
488 if ( maButtonLabel
.isEmpty() || maButtonLabel
.indexOf( MNEMONIC_CHAR
) == -1 )
490 // cut the ellipses, if necessary
491 sal_Int32 nIndex
= sOldLabel
.indexOf( sEllipses
);
493 nIndex
= sOldLabel
.getLength();
494 maButtonLabel
= sOldLabel
.copy( 0, nIndex
);
497 OUString sLabel
= maButtonLabel
;
498 // filter with options -> append ellipses on export button label
499 if ( CheckFilterOptionsCapability( getCurentSfxFilter() ) )
502 if ( sOldLabel
!= sLabel
)
506 xCtrlAccess
->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK
, sLabel
);
508 catch( const IllegalArgumentException
& )
510 SAL_WARN( "sfx2.dialog", "FileDialogHelper_Impl::updateExportButton: caught an exception!" );
516 // ------------------------------------------------------------------------
517 void FileDialogHelper_Impl::updateSelectionBox()
519 if ( !mbHasSelectionBox
)
522 // Does the selection box exist?
523 sal_Bool bSelectionBoxFound
= sal_False
;
524 uno::Reference
< XControlInformation
> xCtrlInfo( mxFileDlg
, UNO_QUERY
);
525 if ( xCtrlInfo
.is() )
527 Sequence
< OUString
> aCtrlList
= xCtrlInfo
->getSupportedControls();
528 sal_uInt32 nCount
= aCtrlList
.getLength();
529 for ( sal_uInt32 nCtrl
= 0; nCtrl
< nCount
; ++nCtrl
)
530 if ( aCtrlList
[ nCtrl
] == "SelectionBox" )
532 bSelectionBoxFound
= sal_True
;
537 if ( bSelectionBoxFound
)
539 const SfxFilter
* pFilter
= getCurentSfxFilter();
540 mbSelectionFltrEnabled
= updateExtendedControl(
541 ExtendedFilePickerElementIds::CHECKBOX_SELECTION
,
542 ( mbSelectionEnabled
&& pFilter
&& ( pFilter
->GetFilterFlags() & SFX_FILTER_SUPPORTSSELECTION
) != 0 ) );
543 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
544 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0, makeAny( (sal_Bool
)mbSelection
) );
548 // ------------------------------------------------------------------------
549 void FileDialogHelper_Impl::enablePasswordBox( sal_Bool bInit
)
551 if ( ! mbHasPassword
)
554 sal_Bool bWasEnabled
= mbIsPwdEnabled
;
556 const SfxFilter
* pCurrentFilter
= getCurentSfxFilter();
557 mbIsPwdEnabled
= updateExtendedControl(
558 ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
,
559 pCurrentFilter
&& ( pCurrentFilter
->GetFilterFlags() & SFX_FILTER_ENCRYPTION
)
564 // in case of inintialization previous state is not interesting
567 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
568 if( mbPwdCheckBoxState
)
569 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0, makeAny( sal_True
) );
572 else if( !bWasEnabled
&& mbIsPwdEnabled
)
574 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
575 if( mbPwdCheckBoxState
)
576 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0, makeAny( sal_True
) );
578 else if( bWasEnabled
&& !mbIsPwdEnabled
)
580 // remember user settings until checkbox is enabled
581 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
582 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0 );
583 sal_Bool bPassWord
= sal_False
;
584 mbPwdCheckBoxState
= ( aValue
>>= bPassWord
) && bPassWord
;
585 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0, makeAny( sal_False
) );
589 // ------------------------------------------------------------------------
590 void FileDialogHelper_Impl::updatePreviewState( sal_Bool _bUpdatePreviewWindow
)
594 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
596 // check, whether or not we have to display a preview
597 if ( xCtrlAccess
.is() )
601 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0 );
602 sal_Bool bShowPreview
= sal_False
;
604 if ( aValue
>>= bShowPreview
)
606 mbShowPreview
= bShowPreview
;
608 // setShowState has currently no effect for the
609 // OpenOffice FilePicker (see svtools/source/filepicker/iodlg.cxx)
610 uno::Reference
< XFilePreview
> xFilePreview( mxFileDlg
, UNO_QUERY
);
611 if ( xFilePreview
.is() )
612 xFilePreview
->setShowState( mbShowPreview
);
614 if ( _bUpdatePreviewWindow
)
615 TimeOutHdl_Impl( NULL
);
618 catch( const Exception
& )
620 SAL_WARN( "sfx2.dialog", "FileDialogHelper_Impl::updatePreviewState: caught an exception!" );
626 // ------------------------------------------------------------------------
627 void FileDialogHelper_Impl::updateVersions()
629 Sequence
< OUString
> aEntries
;
630 Sequence
< OUString
> aPathSeq
= mxFileDlg
->getFiles();
632 if ( aPathSeq
.getLength() == 1 )
634 INetURLObject
aObj( aPathSeq
[0] );
636 if ( ( aObj
.GetProtocol() == INET_PROT_FILE
) &&
637 ( utl::UCBContentHelper::IsDocument( aObj
.GetMainURL( INetURLObject::NO_DECODE
) ) ) )
641 uno::Reference
< embed::XStorage
> xStorage
= ::comphelper::OStorageHelper::GetStorageFromURL(
642 aObj
.GetMainURL( INetURLObject::NO_DECODE
),
643 embed::ElementModes::READ
);
645 DBG_ASSERT( xStorage
.is(), "The method must return the storage or throw an exception!" );
646 if ( !xStorage
.is() )
647 throw uno::RuntimeException();
649 uno::Sequence
< util::RevisionTag
> xVersions
= SfxMedium::GetVersionList( xStorage
);
651 aEntries
.realloc( xVersions
.getLength() + 1 );
652 aEntries
[0] = SfxResId( STR_SFX_FILEDLG_ACTUALVERSION
).toString();
654 for ( sal_Int32 i
=0; i
<xVersions
.getLength(); i
++ )
655 aEntries
[ i
+ 1 ] = xVersions
[i
].Identifier
;
657 catch( const uno::Exception
& )
663 uno::Reference
< XFilePickerControlAccess
> xDlg( mxFileDlg
, UNO_QUERY
);
668 xDlg
->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
669 ControlActions::DELETE_ITEMS
, aValue
);
671 catch( const IllegalArgumentException
& ){}
673 sal_Int32 nCount
= aEntries
.getLength();
680 xDlg
->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
681 ControlActions::ADD_ITEMS
, aValue
);
684 aPos
<<= (sal_Int32
) 0;
685 xDlg
->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
686 ControlActions::SET_SELECT_ITEM
, aPos
);
688 catch( const IllegalArgumentException
& ){}
692 // -----------------------------------------------------------------------
693 IMPL_LINK_NOARG(FileDialogHelper_Impl
, TimeOutHdl_Impl
)
701 uno::Reference
< XFilePreview
> xFilePicker( mxFileDlg
, UNO_QUERY
);
703 if ( ! xFilePicker
.is() )
706 Sequence
< OUString
> aPathSeq
= mxFileDlg
->getFiles();
708 if ( mbShowPreview
&& ( aPathSeq
.getLength() == 1 ) )
710 OUString aURL
= aPathSeq
[0];
712 if ( ERRCODE_NONE
== getGraphic( aURL
, maGraphic
) )
714 // changed the code slightly;
715 // before: the bitmap was scaled and
716 // surrounded a white frame
717 // now: the bitmap will only be scaled
718 // and the filepicker implementation
719 // is responsible for placing it at its
720 // proper position and painting a frame
722 Bitmap aBmp
= maGraphic
.GetBitmap();
723 if ( !aBmp
.IsEmpty() )
725 // scale the bitmap to the correct size
726 sal_Int32 nOutWidth
= xFilePicker
->getAvailableWidth();
727 sal_Int32 nOutHeight
= xFilePicker
->getAvailableHeight();
728 sal_Int32 nBmpWidth
= aBmp
.GetSizePixel().Width();
729 sal_Int32 nBmpHeight
= aBmp
.GetSizePixel().Height();
731 double nXRatio
= (double) nOutWidth
/ nBmpWidth
;
732 double nYRatio
= (double) nOutHeight
/ nBmpHeight
;
734 if ( nXRatio
< nYRatio
)
735 aBmp
.Scale( nXRatio
, nXRatio
);
737 aBmp
.Scale( nYRatio
, nYRatio
);
739 // Convert to true color, to allow CopyPixel
740 aBmp
.Convert( BMP_CONVERSION_24BIT
);
742 // and copy it into the Any
743 SvMemoryStream aData
;
747 const Sequence
< sal_Int8
> aBuffer(
748 static_cast< const sal_Int8
* >(aData
.GetData()),
749 aData
.GetEndOfData() );
758 SolarMutexReleaser aReleaseForCallback
;
759 // clear the preview window
760 xFilePicker
->setImage( FilePreviewImageFormats::BITMAP
, aAny
);
762 catch( const IllegalArgumentException
& )
769 // ------------------------------------------------------------------------
770 ErrCode
FileDialogHelper_Impl::getGraphic( const OUString
& rURL
,
771 Graphic
& rGraphic
) const
773 if ( utl::UCBContentHelper::IsFolder( rURL
) )
774 return ERRCODE_IO_NOTAFILE
;
776 if ( !mpGraphicFilter
)
777 return ERRCODE_IO_NOTSUPPORTED
;
779 // select graphic filter from dialog filter selection
780 OUString
aCurFilter( getFilter() );
782 sal_uInt16 nFilter
= !aCurFilter
.isEmpty() && mpGraphicFilter
->GetImportFormatCount()
783 ? mpGraphicFilter
->GetImportFormatNumber( aCurFilter
)
784 : GRFILTER_FORMAT_DONTKNOW
;
786 INetURLObject
aURLObj( rURL
);
788 if ( aURLObj
.HasError() || INET_PROT_NOT_VALID
== aURLObj
.GetProtocol() )
790 aURLObj
.SetSmartProtocol( INET_PROT_FILE
);
791 aURLObj
.SetSmartURL( rURL
);
794 ErrCode nRet
= ERRCODE_NONE
;
796 sal_uInt32 nFilterImportFlags
= GRFILTER_I_FLAGS_SET_LOGSIZE_FOR_JPEG
;
798 if ( INET_PROT_FILE
!= aURLObj
.GetProtocol() )
800 SvStream
* pStream
= ::utl::UcbStreamHelper::CreateStream( rURL
, STREAM_READ
);
803 nRet
= mpGraphicFilter
->ImportGraphic( rGraphic
, rURL
, *pStream
, nFilter
, NULL
, nFilterImportFlags
);
805 nRet
= mpGraphicFilter
->ImportGraphic( rGraphic
, aURLObj
, nFilter
, NULL
, nFilterImportFlags
);
810 nRet
= mpGraphicFilter
->ImportGraphic( rGraphic
, aURLObj
, nFilter
, NULL
, nFilterImportFlags
);
816 // ------------------------------------------------------------------------
817 ErrCode
FileDialogHelper_Impl::getGraphic( Graphic
& rGraphic
) const
819 ErrCode nRet
= ERRCODE_NONE
;
824 Sequence
< OUString
> aPathSeq
= mxFileDlg
->getFiles();
826 if ( aPathSeq
.getLength() == 1 )
831 if ( !aPath
.isEmpty() )
832 nRet
= getGraphic( aPath
, rGraphic
);
834 nRet
= ERRCODE_IO_GENERAL
;
837 rGraphic
= maGraphic
;
842 // ------------------------------------------------------------------------
843 static bool lcl_isSystemFilePicker( const uno::Reference
< XFilePicker
>& _rxFP
)
847 uno::Reference
< XServiceInfo
> xSI( _rxFP
, UNO_QUERY
);
850 return xSI
->supportsService( "com.sun.star.ui.dialogs.SystemFilePicker" );
852 catch( const Exception
& )
858 enum open_or_save_t
{OPEN
, SAVE
, UNDEFINED
};
859 static open_or_save_t
lcl_OpenOrSave(sal_Int16
const nDialogType
)
863 case FILEOPEN_SIMPLE
:
864 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
866 case FILEOPEN_READONLY_VERSION
:
867 case FILEOPEN_LINK_PREVIEW
:
869 case FILESAVE_SIMPLE
:
870 case FILESAVE_AUTOEXTENSION_PASSWORD
:
871 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
872 case FILESAVE_AUTOEXTENSION_SELECTION
:
873 case FILESAVE_AUTOEXTENSION_TEMPLATE
:
874 case FILESAVE_AUTOEXTENSION
:
877 assert(false); // invalid dialog type
882 // ------------------------------------------------------------------------
883 // ----------- FileDialogHelper_Impl ---------------------------
884 // ------------------------------------------------------------------------
886 FileDialogHelper_Impl::FileDialogHelper_Impl(
887 FileDialogHelper
* _pAntiImpl
,
888 sal_Int16 nDialogType
,
891 Window
* _pPreferredParentWindow
,
892 const String
& sStandardDir
,
893 const ::com::sun::star::uno::Sequence
< OUString
>& rBlackList
895 :m_nDialogType ( nDialogType
)
896 ,meContext ( FileDialogHelper::UNKNOWN_CONTEXT
)
898 const char* pServiceName
=0;
899 if ( nDialog
== SFX2_IMPL_DIALOG_SYSTEM
)
900 pServiceName
= FILE_OPEN_SERVICE_NAME_OOO
;
901 else if ( nDialog
== SFX2_IMPL_DIALOG_OOO
)
902 pServiceName
= FILE_OPEN_SERVICE_NAME_OOO
;
904 pServiceName
= "com.sun.star.ui.dialogs.FilePicker";
905 OUString aService
= OUString::createFromAscii( pServiceName
);
907 uno::Reference
< XMultiServiceFactory
> xFactory( ::comphelper::getProcessServiceFactory() );
909 // create the file open dialog
910 // the flags can be SFXWB_INSERT or SFXWB_MULTISELECTION
912 mpPreferredParentWindow
= _pPreferredParentWindow
;
913 mpAntiImpl
= _pAntiImpl
;
914 mnError
= ERRCODE_NONE
;
915 mbHasAutoExt
= sal_False
;
916 mbHasPassword
= sal_False
;
917 m_bHaveFilterOptions
= sal_False
;
918 mbIsPwdEnabled
= sal_True
;
919 mbHasVersions
= sal_False
;
920 mbHasPreview
= sal_False
;
921 mbShowPreview
= sal_False
;
922 mbAddGraphicFilter
= SFXWB_GRAPHIC
== (nFlags
& SFXWB_GRAPHIC
);
923 mbDeleteMatcher
= sal_False
;
924 mbInsert
= SFXWB_INSERT
== ( nFlags
& SFXWB_INSERT
);
925 mbExport
= SFXWB_EXPORT
== ( nFlags
& SFXWB_EXPORT
);
926 mbIsSaveDlg
= sal_False
;
927 mbIsSaveACopyDlg
= SFXWB_SAVEACOPY
== ( nFlags
& SFXWB_SAVEACOPY
);
928 mbPwdCheckBoxState
= sal_False
;
929 mbSelection
= sal_False
;
930 mbSelectionEnabled
= sal_True
;
931 mbHasSelectionBox
= sal_False
;
932 mbSelectionFltrEnabled
= sal_False
;
935 m_nDontFlags
= SFX_FILTER_INTERNAL
| SFX_FILTER_NOTINFILEDLG
| SFX_FILTER_NOTINSTALLED
;
936 if (OPEN
== lcl_OpenOrSave(m_nDialogType
))
937 m_nMustFlags
= SFX_FILTER_IMPORT
;
939 m_nMustFlags
= SFX_FILTER_EXPORT
;
943 mpGraphicFilter
= NULL
;
944 mnPostUserEventId
= 0;
946 // create the picker component
947 mxFileDlg
= mxFileDlg
.query( xFactory
->createInstance( aService
) );
948 mbSystemPicker
= lcl_isSystemFilePicker( mxFileDlg
);
950 uno::Reference
< XFilePickerNotifier
> xNotifier( mxFileDlg
, UNO_QUERY
);
951 uno::Reference
< XInitialization
> xInit( mxFileDlg
, UNO_QUERY
);
953 if ( ! mxFileDlg
.is() || ! xNotifier
.is() )
955 mnError
= ERRCODE_ABORT
;
962 sal_Int16 nTemplateDescription
= TemplateDescription::FILEOPEN_SIMPLE
;
964 switch ( m_nDialogType
)
966 case FILEOPEN_SIMPLE
:
967 nTemplateDescription
= TemplateDescription::FILEOPEN_SIMPLE
;
970 case FILESAVE_SIMPLE
:
971 nTemplateDescription
= TemplateDescription::FILESAVE_SIMPLE
;
972 mbIsSaveDlg
= sal_True
;
975 case FILESAVE_AUTOEXTENSION_PASSWORD
:
976 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD
;
977 mbHasPassword
= sal_True
;
978 mbHasAutoExt
= sal_True
;
979 mbIsSaveDlg
= sal_True
;
982 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
983 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
;
984 mbHasPassword
= sal_True
;
986 m_bHaveFilterOptions
= sal_True
;
989 mxFilterCFG
= uno::Reference
< XNameAccess
>(
990 xFactory
->createInstance( "com.sun.star.document.FilterFactory" ),
994 mbHasAutoExt
= sal_True
;
995 mbIsSaveDlg
= sal_True
;
998 case FILESAVE_AUTOEXTENSION_SELECTION
:
999 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION
;
1000 mbHasAutoExt
= sal_True
;
1001 mbIsSaveDlg
= sal_True
;
1002 mbHasSelectionBox
= sal_True
;
1003 if ( mbExport
&& !mxFilterCFG
.is() && xFactory
.is() )
1005 mxFilterCFG
= uno::Reference
< XNameAccess
>(
1006 xFactory
->createInstance( "com.sun.star.document.FilterFactory" ),
1011 case FILESAVE_AUTOEXTENSION_TEMPLATE
:
1012 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE
;
1013 mbHasAutoExt
= sal_True
;
1014 mbIsSaveDlg
= sal_True
;
1017 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
1018 nTemplateDescription
= TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
;
1019 mbHasPreview
= sal_True
;
1022 maPreViewTimer
.SetTimeout( 500 );
1023 maPreViewTimer
.SetTimeoutHdl( LINK( this, FileDialogHelper_Impl
, TimeOutHdl_Impl
) );
1027 nTemplateDescription
= TemplateDescription::FILEOPEN_PLAY
;
1030 case FILEOPEN_READONLY_VERSION
:
1031 nTemplateDescription
= TemplateDescription::FILEOPEN_READONLY_VERSION
;
1032 mbHasVersions
= sal_True
;
1035 case FILEOPEN_LINK_PREVIEW
:
1036 nTemplateDescription
= TemplateDescription::FILEOPEN_LINK_PREVIEW
;
1037 mbHasPreview
= sal_True
;
1039 maPreViewTimer
.SetTimeout( 500 );
1040 maPreViewTimer
.SetTimeoutHdl( LINK( this, FileDialogHelper_Impl
, TimeOutHdl_Impl
) );
1043 case FILESAVE_AUTOEXTENSION
:
1044 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION
;
1045 mbHasAutoExt
= sal_True
;
1046 mbIsSaveDlg
= sal_True
;
1050 SAL_WARN( "sfx2.dialog", "FileDialogHelper::ctor with unknown type" );
1054 Sequence
< Any
> aInitArguments( !mpPreferredParentWindow
? 3 : 4 );
1056 // This is a hack. We currently know that the internal file picker implementation
1057 // supports the extended arguments as specified below.
1059 // a) adjust the service description so that it includes the TemplateDescription and ParentWindow args
1060 // b) adjust the implementation of the system file picker to that it recognizes it
1061 if ( mbSystemPicker
)
1063 aInitArguments
[0] <<= nTemplateDescription
;
1067 aInitArguments
[0] <<= NamedValue(
1068 OUString( "TemplateDescription" ),
1069 makeAny( nTemplateDescription
)
1072 OUString sStandardDirTemp
= OUString( sStandardDir
);
1074 aInitArguments
[1] <<= NamedValue(
1075 OUString( "StandardDir" ),
1076 makeAny( sStandardDirTemp
)
1079 aInitArguments
[2] <<= NamedValue(
1080 OUString( "BlackList" ),
1081 makeAny( rBlackList
)
1085 if ( mpPreferredParentWindow
)
1086 aInitArguments
[3] <<= NamedValue(
1087 OUString( "ParentWindow" ),
1088 makeAny( VCLUnoHelper::GetInterface( mpPreferredParentWindow
) )
1094 xInit
->initialize( aInitArguments
);
1096 catch( const Exception
& )
1098 OSL_FAIL( "FileDialogHelper_Impl::FileDialogHelper_Impl: could not initialize the picker!" );
1103 // set multiselection mode
1104 if ( nFlags
& SFXWB_MULTISELECTION
)
1105 mxFileDlg
->setMultiSelectionMode( sal_True
);
1107 if (mbAddGraphicFilter
) // generate graphic filter only on demand
1115 mxFileDlg
->setTitle( SfxResId( STR_SFX_EXPLORERFILE_EXPORT
).toString() );
1117 com::sun::star::uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY_THROW
);
1118 xCtrlAccess
->enableControl( ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR
, sal_True
);
1120 catch( const Exception
& ) { }
1123 // Save a copy dialog
1124 if ( mbIsSaveACopyDlg
)
1126 mxFileDlg
->setTitle( SfxResId( STR_PB_SAVEACOPY
).toString() );
1129 // the "insert file" dialog needs another title
1132 mxFileDlg
->setTitle( SfxResId( STR_SFX_EXPLORERFILE_INSERT
).toString() );
1133 uno::Reference
< XFilePickerControlAccess
> xExtDlg( mxFileDlg
, UNO_QUERY
);
1138 xExtDlg
->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK
,
1139 SfxResId( STR_SFX_EXPLORERFILE_BUTTONINSERT
).toString() );
1141 catch( const IllegalArgumentException
& ){}
1145 // add the event listener
1146 xNotifier
->addFilePickerListener( this );
1149 // ------------------------------------------------------------------------
1150 FileDialogHelper_Impl::~FileDialogHelper_Impl()
1152 // Remove user event if we haven't received it yet
1153 if ( mnPostUserEventId
)
1154 Application::RemoveUserEvent( mnPostUserEventId
);
1155 mnPostUserEventId
= 0;
1157 delete mpGraphicFilter
;
1159 if ( mbDeleteMatcher
)
1162 maPreViewTimer
.SetTimeoutHdl( Link() );
1164 ::comphelper::disposeComponent( mxFileDlg
);
1169 class PickerThread_Impl
: public ::osl::Thread
1171 uno::Reference
< XFilePicker
> mxPicker
;
1172 ::osl::Mutex maMutex
;
1173 virtual void SAL_CALL
run();
1176 PickerThread_Impl( const uno::Reference
< XFilePicker
>& rPicker
)
1177 : mxPicker( rPicker
), mnRet(nMagic
) {}
1179 sal_Int16
GetReturnValue()
1180 { ::osl::MutexGuard
aGuard( maMutex
); return mnRet
; }
1182 void SetReturnValue( sal_Int16 aRetValue
)
1183 { ::osl::MutexGuard
aGuard( maMutex
); mnRet
= aRetValue
; }
1186 void SAL_CALL
PickerThread_Impl::run()
1190 sal_Int16 n
= mxPicker
->execute();
1191 SetReturnValue( n
);
1193 catch( const RuntimeException
& )
1195 SetReturnValue( ExecutableDialogResults::CANCEL
);
1196 SAL_WARN( "sfx2.dialog", "RuntimeException caught" );
1200 // ------------------------------------------------------------------------
1201 void FileDialogHelper_Impl::setControlHelpIds( const sal_Int16
* _pControlId
, const char** _pHelpId
)
1203 DBG_ASSERT( _pControlId
&& _pHelpId
, "FileDialogHelper_Impl::setControlHelpIds: invalid array pointers!" );
1204 if ( !_pControlId
|| !_pHelpId
)
1207 // forward these ids to the file picker
1210 const OUString
sHelpIdPrefix( INET_HID_SCHEME
);
1211 // the ids for the single controls
1212 uno::Reference
< XFilePickerControlAccess
> xControlAccess( mxFileDlg
, UNO_QUERY
);
1213 if ( xControlAccess
.is() )
1215 while ( *_pControlId
)
1217 DBG_ASSERT( INetURLObject( OStringToOUString( *_pHelpId
, RTL_TEXTENCODING_UTF8
) ).GetProtocol() == INET_PROT_NOT_VALID
, "Wrong HelpId!" );
1218 OUString
sId( sHelpIdPrefix
);
1219 sId
+= OUString( *_pHelpId
, strlen( *_pHelpId
), RTL_TEXTENCODING_UTF8
);
1220 xControlAccess
->setValue( *_pControlId
, ControlActions::SET_HELP_URL
, makeAny( sId
) );
1222 ++_pControlId
; ++_pHelpId
;
1226 catch( const Exception
& )
1228 OSL_FAIL( "FileDialogHelper_Impl::setControlHelpIds: caught an exception while setting the help ids!" );
1232 // ------------------------------------------------------------------------
1233 IMPL_LINK( FileDialogHelper_Impl
, InitControls
, void*, NOTINTERESTEDIN
)
1235 (void)NOTINTERESTEDIN
;
1236 mnPostUserEventId
= 0;
1237 enablePasswordBox( sal_True
);
1238 updateFilterOptionsBox( );
1239 updateSelectionBox( );
1244 // ------------------------------------------------------------------------
1245 void FileDialogHelper_Impl::preExecute()
1248 setDefaultValues( );
1249 updatePreviewState( sal_False
);
1251 implInitializeFileName( );
1253 #if !(defined(MACOSX) && defined(MACOSX)) && !defined(WNT)
1254 // allow for dialog implementations which need to be executed before they return valid values for
1255 // current filter and such
1257 // On Vista (at least SP1) it's the same as on MacOSX, the modal dialog won't let message pass
1258 // through before it returns from execution
1259 mnPostUserEventId
= Application::PostUserEvent( LINK( this, FileDialogHelper_Impl
, InitControls
) );
1261 // However, the Mac OS X implementation's pickers run modally in execute and so the event doesn't
1262 // get through in time... so we call the methods directly
1263 enablePasswordBox( sal_True
);
1264 updateFilterOptionsBox( );
1265 updateSelectionBox( );
1269 // ------------------------------------------------------------------------
1270 void FileDialogHelper_Impl::postExecute( sal_Int16 _nResult
)
1272 if ( ExecutableDialogResults::CANCEL
!= _nResult
)
1276 // ------------------------------------------------------------------------
1277 void FileDialogHelper_Impl::implInitializeFileName( )
1279 if ( !maFileName
.isEmpty() )
1281 INetURLObject
aObj( maPath
);
1282 aObj
.Append( maFileName
);
1284 // in case we're operating as save dialog, and "auto extension" is checked,
1285 // cut the extension from the name
1286 if ( mbIsSaveDlg
&& mbHasAutoExt
)
1290 sal_Bool bAutoExtChecked
= sal_False
;
1292 uno::Reference
< XFilePickerControlAccess
> xControlAccess( mxFileDlg
, UNO_QUERY
);
1293 if ( xControlAccess
.is()
1294 && ( xControlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0 )
1299 if ( bAutoExtChecked
)
1300 { // cut the extension
1301 aObj
.removeExtension( );
1302 mxFileDlg
->setDefaultName( aObj
.GetName( INetURLObject::DECODE_WITH_CHARSET
) );
1306 catch( const Exception
& )
1308 OSL_FAIL( "FileDialogHelper_Impl::implInitializeFileName: could not ask for the auto-extension current-value!" );
1314 // ------------------------------------------------------------------------
1315 sal_Int16
FileDialogHelper_Impl::implDoExecute()
1319 sal_Int16 nRet
= ExecutableDialogResults::CANCEL
;
1321 //On MacOSX the native file picker has to run in the primordial thread because of drawing issues
1322 //On Linux the native gtk file picker, when backed by gnome-vfs2, needs to be run in the same
1323 //primordial thread as the ucb gnome-vfs2 provider was initialized in.
1329 if ( mbSystemPicker
)
1331 SolarMutexReleaser aSolarMutex
;
1332 nRet
= mxFileDlg
->execute();
1336 nRet
= mxFileDlg
->execute();
1338 catch( const Exception
& )
1340 SAL_WARN( "sfx2.dialog", "FileDialogHelper_Impl::implDoExecute: caught an exception!" );
1344 postExecute( nRet
);
1349 // ------------------------------------------------------------------------
1350 void FileDialogHelper_Impl::implStartExecute()
1352 DBG_ASSERT( mxFileDlg
.is(), "invalid file dialog" );
1356 if ( mbSystemPicker
)
1363 uno::Reference
< XAsynchronousExecutableDialog
> xAsyncDlg( mxFileDlg
, UNO_QUERY
);
1364 if ( xAsyncDlg
.is() )
1365 xAsyncDlg
->startExecuteModal( this );
1367 catch( const Exception
& )
1369 SAL_WARN( "sfx2.dialog", "FileDialogHelper_Impl::implDoExecute: caught an exception!" );
1374 // ------------------------------------------------------------------------
1375 void lcl_saveLastURLs(std::vector
<OUString
>& rpURLList
,
1376 ::comphelper::SequenceAsVector
< OUString
>& lLastURLs
)
1379 for(std::vector
<OUString
>::iterator i
= rpURLList
.begin(); i
!= rpURLList
.end(); ++i
)
1380 lLastURLs
.push_back(*i
);
1383 // ------------------------------------------------------------------------
1384 void FileDialogHelper_Impl::implGetAndCacheFiles(const uno::Reference
< XInterface
>& xPicker
, std::vector
<OUString
>& rpURLList
, const SfxFilter
* pFilter
)
1388 OUString sExtension
;
1391 sExtension
= pFilter
->GetDefaultExtension ();
1392 sExtension
= comphelper::string::remove(sExtension
, '*');
1393 sExtension
= comphelper::string::remove(sExtension
, '.');
1396 // a) the new way (optional!)
1397 uno::Reference
< XFilePicker2
> xPickNew(xPicker
, UNO_QUERY
);
1400 Sequence
< OUString
> lFiles
= xPickNew
->getSelectedFiles();
1401 ::sal_Int32 nFiles
= lFiles
.getLength();
1402 for(sal_Int32 i
= 0; i
< nFiles
; ++i
)
1403 rpURLList
.push_back(lFiles
[i
]);
1406 // b) the olde way ... non optional.
1409 uno::Reference
< XFilePicker
> xPickOld(xPicker
, UNO_QUERY_THROW
);
1410 Sequence
< OUString
> lFiles
= xPickOld
->getFiles();
1411 ::sal_Int32 nFiles
= lFiles
.getLength();
1414 rpURLList
.push_back(lFiles
[0]);
1416 else if ( nFiles
> 1 )
1418 INetURLObject
aPath( lFiles
[0] );
1419 aPath
.setFinalSlash();
1421 for (::sal_Int32 i
= 1; i
< nFiles
; i
++)
1424 aPath
.Append( lFiles
[i
] );
1426 aPath
.setName( lFiles
[i
] );
1428 rpURLList
.push_back(aPath
.GetMainURL(INetURLObject::NO_DECODE
));
1433 lcl_saveLastURLs(rpURLList
, mlLastURLs
);
1436 // ------------------------------------------------------------------------
1437 ErrCode
FileDialogHelper_Impl::execute( std::vector
<OUString
>& rpURLList
,
1438 SfxItemSet
*& rpSet
,
1441 // rFilter is a pure output parameter, it shouldn't be used for anything else
1442 // changing this would surely break code
1443 // rpSet is in/out parameter, usually just a media-descriptor that can be changed by dialog
1445 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
1447 // retrieves parameters from rpSet
1448 // for now only Password is used
1451 // check password checkbox if the document had password before
1454 SFX_ITEMSET_ARG( rpSet
, pPassItem
, SfxBoolItem
, SID_PASSWORDINTERACTION
, sal_False
);
1455 mbPwdCheckBoxState
= ( pPassItem
!= NULL
&& pPassItem
->GetValue() );
1457 // in case the document has password to modify, the dialog should be shown
1458 SFX_ITEMSET_ARG( rpSet
, pPassToModifyItem
, SfxUnoAnyItem
, SID_MODIFYPASSWORDINFO
, sal_False
);
1459 mbPwdCheckBoxState
|= ( pPassToModifyItem
&& pPassToModifyItem
->GetValue().hasValue() );
1462 SFX_ITEMSET_ARG( rpSet
, pSelectItem
, SfxBoolItem
, SID_SELECTION
, sal_False
);
1464 mbSelection
= pSelectItem
->GetValue();
1466 mbSelectionEnabled
= sal_False
;
1468 // the password will be set in case user decide so
1469 rpSet
->ClearItem( SID_PASSWORDINTERACTION
);
1470 rpSet
->ClearItem( SID_PASSWORD
);
1471 rpSet
->ClearItem( SID_ENCRYPTIONDATA
);
1472 rpSet
->ClearItem( SID_RECOMMENDREADONLY
);
1473 rpSet
->ClearItem( SID_MODIFYPASSWORDINFO
);
1477 if ( mbHasPassword
&& !mbPwdCheckBoxState
)
1479 SvtSecurityOptions aSecOpt
;
1480 mbPwdCheckBoxState
= (
1481 aSecOpt
.IsOptionSet( SvtSecurityOptions::E_DOCWARN_RECOMMENDPASSWORD
) );
1486 if ( ! mxFileDlg
.is() )
1487 return ERRCODE_ABORT
;
1489 if ( ExecutableDialogResults::CANCEL
!= implDoExecute() )
1491 // create an itemset if there is no
1493 rpSet
= new SfxAllItemSet( SFX_APP()->GetPool() );
1495 // the item should remain only if it was set by the dialog
1496 rpSet
->ClearItem( SID_SELECTION
);
1498 if( mbExport
&& mbHasSelectionBox
)
1502 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0 );
1503 sal_Bool bSelection
= sal_False
;
1504 if ( aValue
>>= bSelection
)
1505 rpSet
->Put( SfxBoolItem( SID_SELECTION
, bSelection
) );
1507 catch( const IllegalArgumentException
& )
1509 OSL_FAIL( "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
1514 // set the read-only flag. When inserting a file, this flag is always set
1516 rpSet
->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
1519 if ( ( FILEOPEN_READONLY_VERSION
== m_nDialogType
) && xCtrlAccess
.is() )
1523 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY
, 0 );
1524 sal_Bool bReadOnly
= sal_False
;
1525 if ( ( aValue
>>= bReadOnly
) && bReadOnly
)
1526 rpSet
->Put( SfxBoolItem( SID_DOC_READONLY
, bReadOnly
) );
1528 catch( const IllegalArgumentException
& )
1530 OSL_FAIL( "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
1534 if ( mbHasVersions
&& xCtrlAccess
.is() )
1538 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
1539 ControlActions::GET_SELECTED_ITEM_INDEX
);
1540 sal_Int32 nVersion
= 0;
1541 if ( ( aValue
>>= nVersion
) && nVersion
> 0 )
1542 // open a special version; 0 == current version
1543 rpSet
->Put( SfxInt16Item( SID_VERSION
, (short)nVersion
) );
1545 catch( const IllegalArgumentException
& ){}
1549 getRealFilter( rFilter
);
1551 const SfxFilter
* pCurrentFilter
= getCurentSfxFilter();
1553 // fill the rpURLList
1554 implGetAndCacheFiles( mxFileDlg
, rpURLList
, pCurrentFilter
);
1555 if ( rpURLList
.empty() )
1556 return ERRCODE_ABORT
;
1558 // check, whether or not we have to display a password box
1559 if ( pCurrentFilter
&& mbHasPassword
&& mbIsPwdEnabled
&& xCtrlAccess
.is() )
1563 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0 );
1564 sal_Bool bPassWord
= sal_False
;
1565 if ( ( aValue
>>= bPassWord
) && bPassWord
)
1567 // ask for a password
1568 OUString
aDocName(rpURLList
[0]);
1569 ErrCode errCode
= RequestPassword(pCurrentFilter
, aDocName
, rpSet
);
1570 if (errCode
!= ERRCODE_NONE
)
1574 catch( const IllegalArgumentException
& ){}
1577 SaveLastUsedFilter();
1578 return ERRCODE_NONE
;
1581 return ERRCODE_ABORT
;
1584 // ------------------------------------------------------------------------
1585 ErrCode
FileDialogHelper_Impl::execute()
1587 if ( ! mxFileDlg
.is() )
1588 return ERRCODE_ABORT
;
1590 sal_Int16 nRet
= implDoExecute();
1592 maPath
= mxFileDlg
->getDisplayDirectory();
1594 if ( ExecutableDialogResults::CANCEL
== nRet
)
1595 return ERRCODE_ABORT
;
1598 return ERRCODE_NONE
;
1602 // ------------------------------------------------------------------------
1603 OUString
FileDialogHelper_Impl::getPath() const
1607 if ( mxFileDlg
.is() )
1608 aPath
= mxFileDlg
->getDisplayDirectory();
1610 if ( aPath
.isEmpty() )
1616 // ------------------------------------------------------------------------
1617 OUString
FileDialogHelper_Impl::getFilter() const
1619 String aFilter
= getCurrentFilterUIName();
1621 if( !aFilter
.Len() )
1622 aFilter
= maCurFilter
;
1627 // ------------------------------------------------------------------------
1628 void FileDialogHelper_Impl::getRealFilter( String
& _rFilter
) const
1630 _rFilter
= getCurrentFilterUIName();
1632 if ( !_rFilter
.Len() )
1633 _rFilter
= maCurFilter
;
1635 if ( _rFilter
.Len() && mpMatcher
)
1637 const SfxFilter
* pFilter
=
1638 mpMatcher
->GetFilter4UIName( _rFilter
, m_nMustFlags
, m_nDontFlags
);
1639 _rFilter
= pFilter
? String(pFilter
->GetFilterName()) : _rFilter
.Erase();
1643 void FileDialogHelper_Impl::verifyPath()
1646 // lp#905355, fdo#43895
1647 // Check that the file has read only permission and is in /tmp -- this is
1648 // the case if we have opened the file from the web with firefox only.
1649 if (maFileName
.isEmpty()) {
1652 INetURLObject
url(maPath
);
1653 if (url
.GetProtocol() != INET_PROT_FILE
1654 || url
.getName(0, true, INetURLObject::DECODE_WITH_CHARSET
) != "tmp")
1658 if (maFileName
.indexOf('/') != -1) {
1659 SAL_WARN("sfx2.dialog", maFileName
<< " contains /");
1663 maFileName
, false, INetURLObject::LAST_SEGMENT
, true,
1664 INetURLObject::ENCODE_ALL
);
1666 osl::FileBase::RC e
= osl::FileBase::getSystemPathFromFileURL(
1667 url
.GetMainURL(INetURLObject::NO_DECODE
), sysPathU
);
1668 if (e
!= osl::FileBase::E_None
) {
1671 "getSystemPathFromFileURL("
1672 << url
.GetMainURL(INetURLObject::NO_DECODE
) << ") failed with "
1677 if (!sysPathU
.convertToString(
1678 &sysPathC
, osl_getThreadTextEncoding(),
1679 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
1680 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
1684 "convertToString(" << sysPathU
<< ") failed for encoding "
1685 << +osl_getThreadTextEncoding());
1688 struct stat aFileStat
;
1689 if (stat(sysPathC
.getStr(), &aFileStat
) == -1) {
1692 "stat(" << sysPathC
.getStr() << ") failed with errno " << errno
);
1695 if ((aFileStat
.st_mode
& (S_IRWXO
| S_IRWXG
| S_IRWXU
)) == S_IRUSR
) {
1696 maPath
= SvtPathOptions().GetWorkPath();
1697 mxFileDlg
->setDisplayDirectory( maPath
);
1702 // ------------------------------------------------------------------------
1703 void FileDialogHelper_Impl::displayFolder( const OUString
& _rPath
)
1705 if ( _rPath
.isEmpty() )
1710 if ( mxFileDlg
.is() )
1714 mxFileDlg
->setDisplayDirectory( maPath
);
1717 catch( const IllegalArgumentException
& )
1719 OSL_FAIL( "FileDialogHelper_Impl::displayFolder: caught an exception!" );
1724 // ------------------------------------------------------------------------
1725 void FileDialogHelper_Impl::setFileName( const OUString
& _rFile
)
1727 maFileName
= _rFile
;
1728 if ( mxFileDlg
.is() )
1732 mxFileDlg
->setDefaultName( maFileName
);
1735 catch( const IllegalArgumentException
& )
1737 OSL_FAIL( "FileDialogHelper_Impl::setFileName: caught an exception!" );
1742 // ------------------------------------------------------------------------
1743 void FileDialogHelper_Impl::setFilter( const OUString
& rFilter
)
1745 DBG_ASSERT( rFilter
.indexOf(':') == -1, "Old filter name used!");
1747 maCurFilter
= rFilter
;
1749 if ( !rFilter
.isEmpty() && mpMatcher
)
1751 const SfxFilter
* pFilter
= mpMatcher
->GetFilter4FilterName(
1752 rFilter
, m_nMustFlags
, m_nDontFlags
);
1754 maCurFilter
= pFilter
->GetUIName();
1757 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
1759 if ( !maCurFilter
.isEmpty() && xFltMgr
.is() )
1763 xFltMgr
->setCurrentFilter( maCurFilter
);
1765 catch( const IllegalArgumentException
& ){}
1769 // ------------------------------------------------------------------------
1770 void FileDialogHelper_Impl::createMatcher( const String
& rFactory
)
1772 mpMatcher
= new SfxFilterMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory
) );
1773 mbDeleteMatcher
= sal_True
;
1776 // ------------------------------------------------------------------------
1777 void FileDialogHelper_Impl::addFilters( const String
& rFactory
,
1778 SfxFilterFlags nMust
,
1779 SfxFilterFlags nDont
)
1781 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
1783 if ( ! xFltMgr
.is() )
1786 // we still need a matcher to convert UI names to filter names
1787 if ( !rFactory
.Len() )
1789 SfxApplication
*pSfxApp
= SFX_APP();
1790 mpMatcher
= &pSfxApp
->GetFilterMatcher();
1791 mbDeleteMatcher
= sal_False
;
1795 mpMatcher
= new SfxFilterMatcher( rFactory
);
1796 mbDeleteMatcher
= sal_True
;
1799 uno::Reference
< XMultiServiceFactory
> xSMGR
= ::comphelper::getProcessServiceFactory();
1800 uno::Reference
< XContainerQuery
> xFilterCont(
1801 xSMGR
->createInstance(OUString("com.sun.star.document.FilterFactory")),
1803 if ( ! xFilterCont
.is() )
1806 m_nMustFlags
|= nMust
;
1807 m_nDontFlags
|= nDont
;
1809 // create the list of filters
1810 OUStringBuffer
sQuery(256);
1811 sQuery
.appendAscii(RTL_CONSTASCII_STRINGPARAM("getSortedFilterList()"));
1812 sQuery
.appendAscii(RTL_CONSTASCII_STRINGPARAM(":module="));
1813 sQuery
.append(rFactory
); // use long name here !
1814 sQuery
.appendAscii(RTL_CONSTASCII_STRINGPARAM(":iflags="));
1815 sQuery
.append(OUString::valueOf((sal_Int32
)m_nMustFlags
));
1816 sQuery
.appendAscii(RTL_CONSTASCII_STRINGPARAM(":eflags="));
1817 sQuery
.append(OUString::valueOf((sal_Int32
)m_nDontFlags
));
1819 uno::Reference
< XEnumeration
> xResult
;
1822 xResult
= xFilterCont
->createSubSetEnumerationByQuery(sQuery
.makeStringAndClear());
1824 catch( const uno::Exception
& )
1826 SAL_WARN( "sfx2.dialog", "Could not get filters from the configuration!" );
1829 TSortedFilterList
aIter (xResult
);
1831 // no matcher any longer used ...
1832 mbDeleteMatcher
= sal_False
;
1834 // append the filters
1835 OUString sFirstFilter
;
1836 if (OPEN
== lcl_OpenOrSave(m_nDialogType
))
1837 ::sfx2::appendFiltersForOpen( aIter
, xFltMgr
, sFirstFilter
, *this );
1838 else if ( mbExport
)
1839 ::sfx2::appendExportFilters( aIter
, xFltMgr
, sFirstFilter
, *this );
1841 ::sfx2::appendFiltersForSave( aIter
, xFltMgr
, sFirstFilter
, *this, rFactory
);
1843 // set our initial selected filter (if we do not already have one)
1844 if ( maSelectFilter
.isEmpty() )
1845 maSelectFilter
= sFirstFilter
;
1848 // ------------------------------------------------------------------------
1849 void FileDialogHelper_Impl::addFilter( const OUString
& rFilterName
,
1850 const OUString
& rExtension
)
1852 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
1854 if ( ! xFltMgr
.is() )
1859 xFltMgr
->appendFilter( rFilterName
, rExtension
);
1861 if ( maSelectFilter
.isEmpty() )
1862 maSelectFilter
= rFilterName
;
1864 catch( const IllegalArgumentException
& )
1866 SAL_WARN( "sfx2.dialog", "Could not append Filter" << rFilterName
);
1870 // ------------------------------------------------------------------------
1871 void FileDialogHelper_Impl::addGraphicFilter()
1873 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
1875 if ( ! xFltMgr
.is() )
1878 // create the list of filters
1879 mpGraphicFilter
= new GraphicFilter
;
1880 sal_uInt16 i
, j
, nCount
= mpGraphicFilter
->GetImportFormatCount();
1882 // compute the extension string for all known import filters
1885 for ( i
= 0; i
< nCount
; i
++ )
1891 sWildcard
= mpGraphicFilter
->GetImportWildcard( i
, j
++ );
1892 if ( !sWildcard
.Len() )
1894 if ( aExtensions
.Search( sWildcard
) == STRING_NOTFOUND
)
1896 if ( aExtensions
.Len() )
1897 aExtensions
+= sal_Unicode(';');
1898 aExtensions
+= sWildcard
;
1904 if ( aExtensions
.Len() > 240 )
1905 aExtensions
= FILEDIALOG_FILTER_ALL
;
1907 sal_Bool bIsInOpenMode
= isInOpenMode();
1911 OUString aAllFilterName
= SfxResId( STR_SFX_IMPORT_ALL
).toString();
1912 aAllFilterName
= ::sfx2::addExtension( aAllFilterName
, aExtensions
, bIsInOpenMode
, *this );
1914 xFltMgr
->appendFilter( aAllFilterName
, aExtensions
);
1915 maSelectFilter
= aAllFilterName
;
1917 catch( const IllegalArgumentException
& )
1919 SAL_WARN( "sfx2.dialog", "Could not append Filter" );
1922 // Now add the filter
1923 for ( i
= 0; i
< nCount
; i
++ )
1925 String aName
= mpGraphicFilter
->GetImportFormatName( i
);
1931 sWildcard
= mpGraphicFilter
->GetImportWildcard( i
, j
++ );
1932 if ( !sWildcard
.Len() )
1934 if ( aExt
.Search( sWildcard
) == STRING_NOTFOUND
)
1937 aExt
+= sal_Unicode(';');
1941 aName
= ::sfx2::addExtension( aName
, aExt
, bIsInOpenMode
, *this );
1944 xFltMgr
->appendFilter( aName
, aExt
);
1946 catch( const IllegalArgumentException
& )
1948 SAL_WARN( "sfx2.dialog", "Could not append Filter" );
1953 // ------------------------------------------------------------------------
1954 #define GRF_CONFIG_STR " "
1955 #define STD_CONFIG_STR "1 "
1957 void FileDialogHelper_Impl::saveConfig()
1959 uno::Reference
< XFilePickerControlAccess
> xDlg( mxFileDlg
, UNO_QUERY
);
1967 SvtViewOptions
aDlgOpt( E_DIALOG
, IMPGRF_CONFIGNAME
);
1968 String aUserData
= OUString(GRF_CONFIG_STR
);
1972 sal_Bool bValue
= sal_False
;
1973 aValue
= xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0 );
1976 aUserData
.SetToken( 1, ' ', OUString::number( (sal_Int32
) bValue
) );
1978 INetURLObject
aObj( getPath() );
1980 if ( aObj
.GetProtocol() == INET_PROT_FILE
)
1981 aUserData
.SetToken( 2, ' ', aObj
.GetMainURL( INetURLObject::NO_DECODE
) );
1983 String aFilter
= getFilter();
1984 aFilter
= EncodeSpaces_Impl( aFilter
);
1985 aUserData
.SetToken( 3, ' ', aFilter
);
1987 aDlgOpt
.SetUserItem( USERITEM_NAME
, makeAny( OUString( aUserData
) ) );
1989 catch( const IllegalArgumentException
& ){}
1993 sal_Bool bWriteConfig
= sal_False
;
1994 SvtViewOptions
aDlgOpt( E_DIALOG
, IODLG_CONFIGNAME
);
1995 String aUserData
= OUString(STD_CONFIG_STR
);
1997 if ( aDlgOpt
.Exists() )
1999 Any aUserItem
= aDlgOpt
.GetUserItem( USERITEM_NAME
);
2001 if ( aUserItem
>>= aTemp
)
2002 aUserData
= String( aTemp
);
2009 aValue
= xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0 );
2010 sal_Bool bAutoExt
= sal_True
;
2011 aValue
>>= bAutoExt
;
2012 aUserData
.SetToken( 0, ' ', OUString::number( (sal_Int32
) bAutoExt
) );
2013 bWriteConfig
= sal_True
;
2015 catch( const IllegalArgumentException
& ){}
2018 if ( ! mbIsSaveDlg
)
2020 OUString aPath
= getPath();
2021 if ( !aPath
.isEmpty() &&
2022 utl::LocalFileHelper::IsLocalFile( aPath
) )
2024 aUserData
.SetToken( 1, ' ', aPath
);
2025 bWriteConfig
= sal_True
;
2029 if( mbHasSelectionBox
&& mbSelectionFltrEnabled
)
2033 aValue
= xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0 );
2034 sal_Bool bSelection
= sal_True
;
2035 aValue
>>= bSelection
;
2036 if ( comphelper::string::getTokenCount(aUserData
, ' ') < 3 )
2037 aUserData
.Append(' ');
2038 aUserData
.SetToken( 2, ' ', OUString::number( (sal_Int32
) bSelection
) );
2039 bWriteConfig
= sal_True
;
2041 catch( const IllegalArgumentException
& ){}
2045 aDlgOpt
.SetUserItem( USERITEM_NAME
, makeAny( OUString( aUserData
) ) );
2048 SfxApplication
*pSfxApp
= SFX_APP();
2049 pSfxApp
->SetLastDir_Impl( getPath() );
2052 // ------------------------------------------------------------------------
2055 static OUString
getInitPath( const String
& _rFallback
, const xub_StrLen _nFallbackToken
)
2057 SfxApplication
*pSfxApp
= SFX_APP();
2058 String sPath
= pSfxApp
->GetLastDir_Impl();
2061 sPath
= _rFallback
.GetToken( _nFallbackToken
, ' ' );
2063 // check if the path points to a valid (accessible) directory
2064 sal_Bool bValid
= sal_False
;
2067 String
sPathCheck( sPath
);
2068 if ( sPathCheck
.GetBuffer()[ sPathCheck
.Len() - 1 ] != '/' )
2073 ::ucbhelper::Content
aContent( sPathCheck
, uno::Reference
< ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
2074 bValid
= aContent
.isFolder();
2076 catch( const Exception
& ) {}
2086 // ------------------------------------------------------------------------
2087 void FileDialogHelper_Impl::loadConfig()
2089 uno::Reference
< XFilePickerControlAccess
> xDlg( mxFileDlg
, UNO_QUERY
);
2097 SvtViewOptions
aViewOpt( E_DIALOG
, IMPGRF_CONFIGNAME
);
2100 if ( aViewOpt
.Exists() )
2102 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
2104 if ( aUserItem
>>= aTemp
)
2105 aUserData
= String( aTemp
);
2108 if ( aUserData
.Len() > 0 )
2112 // respect the last "insert as link" state
2113 sal_Bool bLink
= (sal_Bool
) aUserData
.GetToken( 0, ' ' ).ToInt32();
2115 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_LINK
, 0, aValue
);
2117 // respect the last "show preview" state
2118 sal_Bool bShowPreview
= (sal_Bool
) aUserData
.GetToken( 1, ' ' ).ToInt32();
2119 aValue
<<= bShowPreview
;
2120 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0, aValue
);
2122 if ( maPath
.isEmpty() )
2123 displayFolder( getInitPath( aUserData
, 2 ) );
2125 if ( maCurFilter
.isEmpty() )
2127 String aFilter
= aUserData
.GetToken( 3, ' ' );
2128 aFilter
= DecodeSpaces_Impl( aFilter
);
2129 setFilter( aFilter
);
2132 // set the member so we know that we have to show the preview
2133 mbShowPreview
= bShowPreview
;
2135 catch( const IllegalArgumentException
& ){}
2138 if ( maPath
.isEmpty() )
2139 displayFolder( SvtPathOptions().GetGraphicPath() );
2143 SvtViewOptions
aViewOpt( E_DIALOG
, IODLG_CONFIGNAME
);
2146 if ( aViewOpt
.Exists() )
2148 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
2150 if ( aUserItem
>>= aTemp
)
2151 aUserData
= String( aTemp
);
2154 if ( ! aUserData
.Len() )
2155 aUserData
= STD_CONFIG_STR
;
2157 if ( maPath
.isEmpty() )
2158 displayFolder( getInitPath( aUserData
, 1 ) );
2162 sal_Int32 nFlag
= aUserData
.GetToken( 0, ' ' ).ToInt32();
2163 aValue
<<= (sal_Bool
) nFlag
;
2166 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0, aValue
);
2168 catch( const IllegalArgumentException
& ){}
2171 if( mbHasSelectionBox
)
2173 sal_Int32 nFlag
= aUserData
.GetToken( 2, ' ' ).ToInt32();
2174 aValue
<<= (sal_Bool
) nFlag
;
2177 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0, aValue
);
2179 catch( const IllegalArgumentException
& ){}
2182 if ( maPath
.isEmpty() )
2183 displayFolder( SvtPathOptions().GetWorkPath() );
2187 // ------------------------------------------------------------------------
2188 void FileDialogHelper_Impl::setDefaultValues()
2190 // when no filter is set, we set the curentFilter to <all>
2191 if ( maCurFilter
.isEmpty() && !maSelectFilter
.isEmpty() )
2193 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
2196 xFltMgr
->setCurrentFilter( maSelectFilter
);
2198 catch( const IllegalArgumentException
& )
2202 // when no path is set, we use the standard 'work' folder
2203 if ( maPath
.isEmpty() )
2205 OUString aWorkFolder
= SvtPathOptions().GetWorkPath();
2208 mxFileDlg
->setDisplayDirectory( aWorkFolder
);
2210 catch( const Exception
& )
2212 OSL_FAIL( "FileDialogHelper_Impl::setDefaultValues: caught an exception while setting the display directory!" );
2217 sal_Bool
FileDialogHelper_Impl::isShowFilterExtensionEnabled() const
2219 return !maFilters
.empty();
2222 void FileDialogHelper_Impl::addFilterPair( const OUString
& rFilter
,
2223 const OUString
& rFilterWithExtension
)
2225 maFilters
.push_back( FilterPair( rFilter
, rFilterWithExtension
) );
2229 OUString
FileDialogHelper_Impl::getFilterName( const OUString
& rFilterWithExtension
) const
2232 for( ::std::vector
< FilterPair
>::const_iterator pIter
= maFilters
.begin(); pIter
!= maFilters
.end(); ++pIter
)
2234 if ( (*pIter
).Second
== rFilterWithExtension
)
2236 sRet
= (*pIter
).First
;
2243 OUString
FileDialogHelper_Impl::getFilterWithExtension( const OUString
& rFilter
) const
2246 for( ::std::vector
< FilterPair
>::const_iterator pIter
= maFilters
.begin(); pIter
!= maFilters
.end(); ++pIter
)
2248 if ( (*pIter
).First
== rFilter
)
2250 sRet
= (*pIter
).Second
;
2257 void FileDialogHelper_Impl::SetContext( FileDialogHelper::Context _eNewContext
)
2259 meContext
= _eNewContext
;
2261 const OUString
* pConfigId
= GetLastFilterConfigId( _eNewContext
);
2263 LoadLastUsedFilter( *pConfigId
);
2266 // ------------------------------------------------------------------------
2267 // ----------- FileDialogHelper ---------------------------
2268 // ------------------------------------------------------------------------
2270 FileDialogHelper::FileDialogHelper(
2271 sal_Int16 nDialogType
,
2273 const String
& rFact
,
2274 SfxFilterFlags nMust
,
2275 SfxFilterFlags nDont
)
2277 mpImp
= new FileDialogHelper_Impl( this, nDialogType
, nFlags
);
2280 // create the list of filters
2282 SfxObjectShell::GetServiceNameFromFactory(rFact
), nMust
, nDont
);
2285 // ------------------------------------------------------------------------
2286 FileDialogHelper::FileDialogHelper(
2287 sal_Int16 nDialogType
,
2289 const String
& rFact
,
2291 SfxFilterFlags nMust
,
2292 SfxFilterFlags nDont
,
2293 const String
& rStandardDir
,
2294 const ::com::sun::star::uno::Sequence
< OUString
>& rBlackList
)
2296 mpImp
= new FileDialogHelper_Impl( this, nDialogType
, nFlags
, nDialog
, NULL
, rStandardDir
, rBlackList
);
2299 // create the list of filters
2301 SfxObjectShell::GetServiceNameFromFactory(rFact
), nMust
, nDont
);
2304 // ------------------------------------------------------------------------
2305 FileDialogHelper::FileDialogHelper(
2306 sal_Int16 nDialogType
,
2308 Window
* _pPreferredParent
)
2310 mpImp
= new FileDialogHelper_Impl( this, nDialogType
, nFlags
, SFX2_IMPL_DIALOG_CONFIG
, _pPreferredParent
);
2314 // ------------------------------------------------------------------------
2315 FileDialogHelper::FileDialogHelper(
2316 sal_Int16 nDialogType
,
2318 const OUString
& aFilterUIName
,
2319 const OUString
& aExtName
,
2320 const OUString
& rStandardDir
,
2321 const ::com::sun::star::uno::Sequence
< OUString
>& rBlackList
,
2322 Window
* _pPreferredParent
)
2324 mpImp
= new FileDialogHelper_Impl( this, nDialogType
, nFlags
, SFX2_IMPL_DIALOG_CONFIG
, _pPreferredParent
,rStandardDir
, rBlackList
);
2327 // the wildcard here is expected in form "*.extension"
2329 if ( aExtName
.indexOf( (sal_Unicode
)'*' ) != 0 )
2331 if ( !aExtName
.isEmpty() && aExtName
.indexOf( (sal_Unicode
)'.' ) != 0 )
2332 aWildcard
= OUString( "*." );
2334 aWildcard
= OUString( "*" );
2337 aWildcard
+= aExtName
;
2339 OUString
const aUIString
= ::sfx2::addExtension( aFilterUIName
,
2340 aWildcard
, (OPEN
== lcl_OpenOrSave(mpImp
->m_nDialogType
)), *mpImp
);
2341 AddFilter( aUIString
, aWildcard
);
2344 // ------------------------------------------------------------------------
2345 FileDialogHelper::~FileDialogHelper()
2351 // ------------------------------------------------------------------------
2352 void FileDialogHelper::CreateMatcher( const String
& rFactory
)
2354 mpImp
->createMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory
) );
2357 // ------------------------------------------------------------------------
2358 void FileDialogHelper::SetControlHelpIds( const sal_Int16
* _pControlId
, const char** _pHelpId
)
2360 mpImp
->setControlHelpIds( _pControlId
, _pHelpId
);
2363 void FileDialogHelper::SetContext( Context _eNewContext
)
2365 mpImp
->SetContext( _eNewContext
);
2368 // ------------------------------------------------------------------------
2369 IMPL_LINK_NOARG(FileDialogHelper
, ExecuteSystemFilePicker
)
2371 m_nError
= mpImp
->execute();
2372 if ( m_aDialogClosedLink
.IsSet() )
2373 m_aDialogClosedLink
.Call( this );
2378 // ------------------------------------------------------------------------
2379 // rDirPath has to be a directory
2380 ErrCode
FileDialogHelper::Execute( std::vector
<OUString
>& rpURLList
,
2381 SfxItemSet
*& rpSet
,
2383 const String
& rDirPath
)
2385 SetDisplayFolder( rDirPath
);
2386 return mpImp
->execute( rpURLList
, rpSet
, rFilter
);
2390 // ------------------------------------------------------------------------
2391 ErrCode
FileDialogHelper::Execute()
2393 return mpImp
->execute();
2396 // ------------------------------------------------------------------------
2397 ErrCode
FileDialogHelper::Execute( SfxItemSet
*& rpSet
,
2401 std::vector
<OUString
> rURLList
;
2402 nRet
= mpImp
->execute(rURLList
, rpSet
, rFilter
);
2406 void FileDialogHelper::StartExecuteModal( const Link
& rEndDialogHdl
)
2408 m_aDialogClosedLink
= rEndDialogHdl
;
2409 m_nError
= ERRCODE_NONE
;
2410 if ( mpImp
->isSystemFilePicker() )
2411 Application::PostUserEvent( LINK( this, FileDialogHelper
, ExecuteSystemFilePicker
) );
2413 mpImp
->implStartExecute();
2416 // ------------------------------------------------------------------------
2418 short FileDialogHelper::GetDialogType() const
2420 return mpImp
? mpImp
->m_nDialogType
: 0;
2423 // ------------------------------------------------------------------------
2425 sal_Bool
FileDialogHelper::IsPasswordEnabled() const
2427 return mpImp
? mpImp
->isPasswordEnabled() : sal_False
;
2430 // ------------------------------------------------------------------------
2432 String
FileDialogHelper::GetRealFilter() const
2436 mpImp
->getRealFilter( sFilter
);
2440 // ------------------------------------------------------------------------
2441 void FileDialogHelper::SetTitle( const String
& rNewTitle
)
2443 if ( mpImp
->mxFileDlg
.is() )
2444 mpImp
->mxFileDlg
->setTitle( rNewTitle
);
2447 // ------------------------------------------------------------------------
2448 String
FileDialogHelper::GetPath() const
2452 if ( mpImp
->mlLastURLs
.size() > 0)
2453 return mpImp
->mlLastURLs
[0];
2455 if ( mpImp
->mxFileDlg
.is() )
2457 Sequence
< OUString
> aPathSeq
= mpImp
->mxFileDlg
->getFiles();
2459 if ( aPathSeq
.getLength() == 1 )
2461 aPath
= aPathSeq
[0];
2468 // ------------------------------------------------------------------------
2469 Sequence
< OUString
> FileDialogHelper::GetMPath() const
2471 if ( mpImp
->mlLastURLs
.size() > 0)
2472 return mpImp
->mlLastURLs
.getAsConstList();
2474 if ( mpImp
->mxFileDlg
.is() )
2475 return mpImp
->mxFileDlg
->getFiles();
2478 Sequence
< OUString
> aEmpty
;
2483 // ------------------------------------------------------------------------
2484 Sequence
< OUString
> FileDialogHelper::GetSelectedFiles() const
2486 // a) the new way (optional!)
2487 uno::Sequence
< OUString
> aResultSeq
;
2488 uno::Reference
< XFilePicker2
> xPickNew(mpImp
->mxFileDlg
, UNO_QUERY
);
2491 aResultSeq
= xPickNew
->getSelectedFiles();
2493 // b) the olde way ... non optional.
2496 uno::Reference
< XFilePicker
> xPickOld(mpImp
->mxFileDlg
, UNO_QUERY_THROW
);
2497 Sequence
< OUString
> lFiles
= xPickOld
->getFiles();
2498 ::sal_Int32 nFiles
= lFiles
.getLength();
2501 aResultSeq
= Sequence
< OUString
>( nFiles
-1 );
2503 INetURLObject
aPath( lFiles
[0] );
2504 aPath
.setFinalSlash();
2506 for (::sal_Int32 i
= 1; i
< nFiles
; i
++)
2509 aPath
.Append( lFiles
[i
] );
2511 aPath
.setName( lFiles
[i
] );
2513 aResultSeq
[i
-1] = OUString(aPath
.GetMainURL( INetURLObject::NO_DECODE
));
2517 aResultSeq
= lFiles
;
2523 // ------------------------------------------------------------------------
2524 String
FileDialogHelper::GetDisplayDirectory() const
2526 return mpImp
->getPath();
2529 // ------------------------------------------------------------------------
2530 String
FileDialogHelper::GetCurrentFilter() const
2532 return mpImp
->getFilter();
2535 // ------------------------------------------------------------------------
2536 ErrCode
FileDialogHelper::GetGraphic( Graphic
& rGraphic
) const
2538 return mpImp
->getGraphic( rGraphic
);
2541 // ------------------------------------------------------------------------
2542 static int impl_isFolder( const OUString
& rPath
)
2546 ::ucbhelper::Content
aContent(
2547 rPath
, uno::Reference
< ucb::XCommandEnvironment
> (),
2548 comphelper::getProcessComponentContext() );
2549 if ( aContent
.isFolder() )
2554 catch ( const Exception
& )
2561 void FileDialogHelper::SetDisplayDirectory( const String
& _rPath
)
2563 if ( !_rPath
.Len() )
2566 // if the given path isn't a folder, we cut off the last part
2567 // and take it as filename and the rest of the path should be
2570 INetURLObject
aObj( _rPath
);
2572 OUString sFileName
= aObj
.GetName( INetURLObject::DECODE_WITH_CHARSET
);
2573 aObj
.removeSegment();
2574 OUString sPath
= aObj
.GetMainURL( INetURLObject::NO_DECODE
);
2576 int nIsFolder
= impl_isFolder( _rPath
);
2577 if ( nIsFolder
== 0 ||
2578 ( nIsFolder
== -1 && impl_isFolder( sPath
) == 1 ) )
2580 mpImp
->setFileName( sFileName
);
2581 mpImp
->displayFolder( sPath
);
2585 INetURLObject
aObjPathName( _rPath
);
2586 OUString
sFolder( aObjPathName
.GetMainURL( INetURLObject::NO_DECODE
) );
2587 if ( sFolder
.isEmpty() )
2589 // _rPath is not a valid path -> fallback to home directory
2590 osl::Security aSecurity
;
2591 aSecurity
.getHomeDir( sFolder
);
2593 mpImp
->displayFolder( sFolder
);
2597 // ------------------------------------------------------------------------
2598 void FileDialogHelper::SetDisplayFolder( const String
& _rURL
)
2600 mpImp
->displayFolder( _rURL
);
2603 // ------------------------------------------------------------------------
2604 void FileDialogHelper::SetFileName( const String
& _rFileName
)
2606 mpImp
->setFileName( _rFileName
);
2609 // ------------------------------------------------------------------------
2610 void FileDialogHelper::AddFilter( const String
& rFilterName
,
2611 const String
& rExtension
)
2613 mpImp
->addFilter( rFilterName
, rExtension
);
2616 // ------------------------------------------------------------------------
2617 void FileDialogHelper::SetCurrentFilter( const String
& rFilter
)
2619 String
sFilter( rFilter
);
2620 if ( mpImp
->isShowFilterExtensionEnabled() )
2621 sFilter
= mpImp
->getFilterWithExtension( rFilter
);
2622 mpImp
->setFilter( sFilter
);
2625 // ------------------------------------------------------------------------
2626 uno::Reference
< XFilePicker
> FileDialogHelper::GetFilePicker() const
2628 return mpImp
->mxFileDlg
;
2631 // ------------------------------------------------------------------------
2632 // XFilePickerListener Methods
2633 // ------------------------------------------------------------------------
2634 void SAL_CALL
FileDialogHelper::FileSelectionChanged( const FilePickerEvent
& aEvent
)
2636 mpImp
->handleFileSelectionChanged( aEvent
);
2639 // ------------------------------------------------------------------------
2640 void SAL_CALL
FileDialogHelper::DirectoryChanged( const FilePickerEvent
& aEvent
)
2642 mpImp
->handleDirectoryChanged( aEvent
);
2645 // ------------------------------------------------------------------------
2646 OUString SAL_CALL
FileDialogHelper::HelpRequested( const FilePickerEvent
& aEvent
)
2648 return mpImp
->handleHelpRequested( aEvent
);
2651 // ------------------------------------------------------------------------
2652 void SAL_CALL
FileDialogHelper::ControlStateChanged( const FilePickerEvent
& aEvent
)
2654 mpImp
->handleControlStateChanged( aEvent
);
2657 // ------------------------------------------------------------------------
2658 void SAL_CALL
FileDialogHelper::DialogSizeChanged()
2660 mpImp
->handleDialogSizeChanged();
2663 // ------------------------------------------------------------------------
2664 void SAL_CALL
FileDialogHelper::DialogClosed( const DialogClosedEvent
& _rEvent
)
2666 m_nError
= ( RET_OK
== _rEvent
.DialogResult
) ? ERRCODE_NONE
: ERRCODE_ABORT
;
2667 if ( m_aDialogClosedLink
.IsSet() )
2668 m_aDialogClosedLink
.Call( this );
2671 // ------------------------------------------------------------------------
2673 ErrCode
FileOpenDialog_Impl( sal_Int16 nDialogType
,
2675 const String
& rFact
,
2676 std::vector
<OUString
>& rpURLList
,
2678 SfxItemSet
*& rpSet
,
2679 const String
* pPath
,
2681 const String
& rStandardDir
,
2682 const ::com::sun::star::uno::Sequence
< OUString
>& rBlackList
)
2685 FileDialogHelper
aDialog( nDialogType
, nFlags
,
2686 rFact
, nDialog
, 0, 0, rStandardDir
, rBlackList
);
2692 nRet
= aDialog
.Execute( rpURLList
, rpSet
, rFilter
, aPath
);
2693 DBG_ASSERT( rFilter
.SearchAscii(": ") == STRING_NOTFOUND
, "Old filter name used!");
2698 ErrCode
RequestPassword(const SfxFilter
* pCurrentFilter
, OUString
& aURL
, SfxItemSet
* pSet
)
2700 uno::Reference
< task::XInteractionHandler2
> xInteractionHandler
= task::InteractionHandler::createWithParent( ::comphelper::getProcessComponentContext(), 0 );
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
[ OUString( "STD97EncryptionKey" ) ] <<= aEncryptionKey
;
2727 aHashData
[ 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(), 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
;
2759 return ERRCODE_NONE
;
2762 // ------------------------------------------------------------------------
2763 String
EncodeSpaces_Impl( const String
& rSource
)
2765 OUString
sRet( rSource
);
2766 sRet
= sRet
.replaceAll( " ", "%20" );
2770 // ------------------------------------------------------------------------
2771 String
DecodeSpaces_Impl( const String
& rSource
)
2773 OUString
sRet( rSource
);
2774 sRet
= sRet
.replaceAll( "%20", " " );
2778 // ------------------------------------------------------------------------
2780 } // end of namespace sfx2
2782 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */