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/dibtools.hxx>
71 #include <vcl/graphicfilter.hxx>
72 #include <unotools/viewoptions.hxx>
73 #include <unotools/moduleoptions.hxx>
74 #include <svtools/helpid.hrc>
75 #include <comphelper/docpasswordrequest.hxx>
76 #include <comphelper/docpasswordhelper.hxx>
77 #include <ucbhelper/content.hxx>
78 #include <ucbhelper/commandenvironment.hxx>
79 #include <comphelper/storagehelper.hxx>
80 #include <toolkit/helper/vclunohelper.hxx>
81 #include <sfx2/app.hxx>
82 #include <sfx2/frame.hxx>
83 #include <sfx2/docfile.hxx>
84 #include <sfx2/docfac.hxx>
85 #include "openflag.hxx"
86 #include <sfx2/passwd.hxx>
87 #include <sfx2/sfxresid.hxx>
88 #include <sfx2/sfxsids.hrc>
89 #include "filedlghelper.hrc"
90 #include "filtergrouping.hxx"
91 #include <sfx2/request.hxx>
92 #include "filedlgimpl.hxx"
94 #include <sfxlocal.hrc>
95 #include <rtl/strbuf.hxx>
96 #include <comphelper/sequence.hxx>
100 #include <sys/stat.h>
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 ::cppu
;
112 #define IODLG_CONFIGNAME OUString("FilePicker_Save")
113 #define IMPGRF_CONFIGNAME OUString("FilePicker_Graph")
114 #define USERITEM_NAME OUString("UserItem")
121 bool lclSupportsOOXMLEncryption(const OUString
& aFilterName
)
123 return aFilterName
== "Calc MS Excel 2007 XML"
124 || aFilterName
== "MS Word 2007 XML"
125 || aFilterName
== "Impress MS PowerPoint 2007 XML"
126 || aFilterName
== "Impress MS PowerPoint 2007 XML AutoPlay"
127 || aFilterName
== "Calc Office Open XML"
128 || aFilterName
== "Impress Office Open XML"
129 || aFilterName
== "Impress Office Open XML AutoPlay"
130 || aFilterName
== "Office Open XML Text";
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 OUString
EncodeSpaces_Impl( const OUString
& rSource
);
154 OUString
DecodeSpaces_Impl( const OUString
& rSource
);
156 // FileDialogHelper_Impl
158 // XFilePickerListener Methods
159 void SAL_CALL
FileDialogHelper_Impl::fileSelectionChanged( const FilePickerEvent
& aEvent
) throw ( RuntimeException
, std::exception
)
161 SolarMutexGuard aGuard
;
162 mpAntiImpl
->FileSelectionChanged( aEvent
);
165 void SAL_CALL
FileDialogHelper_Impl::directoryChanged( const FilePickerEvent
& aEvent
) throw ( RuntimeException
, std::exception
)
167 SolarMutexGuard aGuard
;
168 mpAntiImpl
->DirectoryChanged( aEvent
);
171 OUString SAL_CALL
FileDialogHelper_Impl::helpRequested( const FilePickerEvent
& aEvent
) throw ( RuntimeException
, std::exception
)
173 SolarMutexGuard aGuard
;
174 return sfx2::FileDialogHelper::HelpRequested( aEvent
);
177 void SAL_CALL
FileDialogHelper_Impl::controlStateChanged( const FilePickerEvent
& aEvent
) throw ( RuntimeException
, std::exception
)
179 SolarMutexGuard aGuard
;
180 mpAntiImpl
->ControlStateChanged( aEvent
);
183 void SAL_CALL
FileDialogHelper_Impl::dialogSizeChanged() throw ( RuntimeException
, std::exception
)
185 SolarMutexGuard aGuard
;
186 mpAntiImpl
->DialogSizeChanged();
189 // XDialogClosedListener Methods
190 void SAL_CALL
FileDialogHelper_Impl::dialogClosed( const DialogClosedEvent
& _rEvent
) throw ( RuntimeException
, std::exception
)
192 SolarMutexGuard aGuard
;
193 mpAntiImpl
->DialogClosed( _rEvent
);
194 postExecute( _rEvent
.DialogResult
);
197 // handle XFilePickerListener events
198 void FileDialogHelper_Impl::handleFileSelectionChanged( const FilePickerEvent
& )
204 maPreviewIdle
.Start();
207 void FileDialogHelper_Impl::handleDirectoryChanged( const FilePickerEvent
& )
210 TimeOutHdl_Impl( NULL
);
213 OUString
FileDialogHelper_Impl::handleHelpRequested( const FilePickerEvent
& aEvent
)
215 //!!! todo: cache the help strings (here or TRA)
218 // mapping from element id -> help id
219 switch ( aEvent
.ElementId
)
221 case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
:
222 sHelpId
= HID_FILESAVE_AUTOEXTENSION
;
225 case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
:
226 sHelpId
= HID_FILESAVE_SAVEWITHPASSWORD
;
229 case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
:
230 sHelpId
= HID_FILESAVE_CUSTOMIZEFILTER
;
233 case ExtendedFilePickerElementIds::CHECKBOX_READONLY
:
234 sHelpId
= HID_FILEOPEN_READONLY
;
237 case ExtendedFilePickerElementIds::CHECKBOX_LINK
:
238 sHelpId
= HID_FILEDLG_LINK_CB
;
241 case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
:
242 sHelpId
= HID_FILEDLG_PREVIEW_CB
;
245 case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY
:
246 sHelpId
= HID_FILESAVE_DOPLAY
;
249 case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL
:
250 case ExtendedFilePickerElementIds::LISTBOX_VERSION
:
251 sHelpId
= HID_FILEOPEN_VERSION
;
254 case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL
:
255 case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE
:
256 sHelpId
= HID_FILESAVE_TEMPLATE
;
259 case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL
:
260 case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE
:
261 sHelpId
= HID_FILEOPEN_IMAGE_TEMPLATE
;
264 case ExtendedFilePickerElementIds::CHECKBOX_SELECTION
:
265 sHelpId
= HID_FILESAVE_SELECTION
;
269 SAL_WARN( "sfx.dialog", "invalid element id" );
273 Help
* pHelp
= Application::GetHelp();
275 aHelpText
= pHelp
->GetHelpText( OStringToOUString(sHelpId
, RTL_TEXTENCODING_UTF8
), NULL
);
279 void FileDialogHelper_Impl::handleControlStateChanged( const FilePickerEvent
& aEvent
)
281 switch ( aEvent
.ElementId
)
283 case CommonFilePickerElementIds::LISTBOX_FILTER
:
284 updateFilterOptionsBox();
285 enablePasswordBox( false );
286 updateSelectionBox();
287 // only use it for export and with our own dialog
288 if ( mbExport
&& !mbSystemPicker
)
289 updateExportButton();
292 case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
:
293 updatePreviewState();
298 void FileDialogHelper_Impl::handleDialogSizeChanged()
301 TimeOutHdl_Impl( NULL
);
304 // XEventListener Methods
305 void SAL_CALL
FileDialogHelper_Impl::disposing( const EventObject
& ) throw ( RuntimeException
, std::exception
)
307 SolarMutexGuard aGuard
;
311 void FileDialogHelper_Impl::dispose()
313 if ( mxFileDlg
.is() )
315 // remove the event listener
316 uno::Reference
< XFilePickerNotifier
> xNotifier( mxFileDlg
, UNO_QUERY
);
317 if ( xNotifier
.is() )
318 xNotifier
->removeFilePickerListener( this );
320 ::comphelper::disposeComponent( mxFileDlg
);
325 OUString
FileDialogHelper_Impl::getCurrentFilterUIName() const
327 OUString aFilterName
;
328 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
332 aFilterName
= xFltMgr
->getCurrentFilter();
334 if ( !aFilterName
.isEmpty() && isShowFilterExtensionEnabled() )
335 aFilterName
= getFilterName( aFilterName
);
341 void FileDialogHelper_Impl::LoadLastUsedFilter( const OUString
& _rContextIdentifier
)
343 SvtViewOptions
aDlgOpt( E_DIALOG
, IODLG_CONFIGNAME
);
345 if( aDlgOpt
.Exists() )
347 OUString aLastFilter
;
348 if( aDlgOpt
.GetUserItem( _rContextIdentifier
) >>= aLastFilter
)
349 setFilter( aLastFilter
);
353 void FileDialogHelper_Impl::SaveLastUsedFilter( const OUString
& _rContextIdentifier
)
355 SvtViewOptions( E_DIALOG
, IODLG_CONFIGNAME
).SetUserItem( _rContextIdentifier
,
356 makeAny( getFilterWithExtension( getFilter() ) ) );
359 void FileDialogHelper_Impl::SaveLastUsedFilter()
361 const OUString
* pConfigId
= GetLastFilterConfigId( meContext
);
363 SaveLastUsedFilter( *pConfigId
);
366 const SfxFilter
* FileDialogHelper_Impl::getCurentSfxFilter()
368 OUString aFilterName
= getCurrentFilterUIName();
370 const SfxFilter
* pFilter
= NULL
;
371 if ( mpMatcher
&& !aFilterName
.isEmpty() )
372 pFilter
= mpMatcher
->GetFilter4UIName( aFilterName
, m_nMustFlags
, m_nDontFlags
);
377 bool FileDialogHelper_Impl::updateExtendedControl( sal_Int16 _nExtendedControlId
, bool _bEnable
)
379 bool bIsEnabled
= false;
381 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
382 if ( xCtrlAccess
.is() )
386 xCtrlAccess
->enableControl( _nExtendedControlId
, _bEnable
);
387 bIsEnabled
= _bEnable
;
389 catch( const IllegalArgumentException
& )
391 OSL_FAIL( "FileDialogHelper_Impl::updateExtendedControl: caught an exception!" );
397 bool FileDialogHelper_Impl::CheckFilterOptionsCapability( const SfxFilter
* _pFilter
)
399 bool bResult
= false;
401 if( mxFilterCFG
.is() && _pFilter
)
404 Sequence
< PropertyValue
> aProps
;
405 Any aAny
= mxFilterCFG
->getByName( _pFilter
->GetName() );
406 if ( aAny
>>= aProps
)
408 OUString aServiceName
;
409 sal_Int32 nPropertyCount
= aProps
.getLength();
410 for( sal_Int32 nProperty
=0; nProperty
< nPropertyCount
; ++nProperty
)
412 if( aProps
[nProperty
].Name
== "UIComponent" )
414 aProps
[nProperty
].Value
>>= aServiceName
;
415 if( !aServiceName
.isEmpty() )
421 catch( const Exception
& )
429 bool FileDialogHelper_Impl::isInOpenMode() const
433 switch ( m_nDialogType
)
435 case FILEOPEN_SIMPLE
:
436 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
438 case FILEOPEN_READONLY_VERSION
:
439 case FILEOPEN_LINK_PREVIEW
:
446 void FileDialogHelper_Impl::updateFilterOptionsBox()
448 if ( !m_bHaveFilterOptions
)
451 updateExtendedControl(
452 ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
,
453 CheckFilterOptionsCapability( getCurentSfxFilter() )
457 void FileDialogHelper_Impl::updateExportButton()
459 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
460 if ( xCtrlAccess
.is() )
462 OUString
sEllipses( "..." );
463 OUString
sOldLabel( xCtrlAccess
->getLabel( CommonFilePickerElementIds::PUSHBUTTON_OK
) );
465 // initialize button label; we need the label with the mnemonic char
466 if ( maButtonLabel
.isEmpty() || maButtonLabel
.indexOf( MNEMONIC_CHAR
) == -1 )
468 // cut the ellipses, if necessary
469 sal_Int32 nIndex
= sOldLabel
.indexOf( sEllipses
);
471 nIndex
= sOldLabel
.getLength();
472 maButtonLabel
= sOldLabel
.copy( 0, nIndex
);
475 OUString sLabel
= maButtonLabel
;
476 // filter with options -> append ellipses on export button label
477 if ( CheckFilterOptionsCapability( getCurentSfxFilter() ) )
480 if ( sOldLabel
!= sLabel
)
484 xCtrlAccess
->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK
, sLabel
);
486 catch( const IllegalArgumentException
& )
488 SAL_WARN( "sfx.dialog", "FileDialogHelper_Impl::updateExportButton: caught an exception!" );
494 void FileDialogHelper_Impl::updateSelectionBox()
496 if ( !mbHasSelectionBox
)
499 // Does the selection box exist?
500 bool bSelectionBoxFound
= false;
501 uno::Reference
< XControlInformation
> xCtrlInfo( mxFileDlg
, UNO_QUERY
);
502 if ( xCtrlInfo
.is() )
504 Sequence
< OUString
> aCtrlList
= xCtrlInfo
->getSupportedControls();
505 sal_uInt32 nCount
= aCtrlList
.getLength();
506 for ( sal_uInt32 nCtrl
= 0; nCtrl
< nCount
; ++nCtrl
)
507 if ( aCtrlList
[ nCtrl
] == "SelectionBox" )
509 bSelectionBoxFound
= true;
514 if ( bSelectionBoxFound
)
516 const SfxFilter
* pFilter
= getCurentSfxFilter();
517 mbSelectionFltrEnabled
= updateExtendedControl(
518 ExtendedFilePickerElementIds::CHECKBOX_SELECTION
,
519 ( mbSelectionEnabled
&& pFilter
&& ( pFilter
->GetFilterFlags() & SfxFilterFlags::SUPPORTSSELECTION
) ) );
520 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
521 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0, makeAny( mbSelection
) );
525 void FileDialogHelper_Impl::enablePasswordBox( bool bInit
)
527 if ( ! mbHasPassword
)
530 bool bWasEnabled
= mbIsPwdEnabled
;
532 const SfxFilter
* pCurrentFilter
= getCurentSfxFilter();
533 mbIsPwdEnabled
= updateExtendedControl(
534 ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
,
535 pCurrentFilter
&& ( pCurrentFilter
->GetFilterFlags() & SfxFilterFlags::ENCRYPTION
)
540 // in case of inintialization previous state is not interesting
543 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
544 if( mbPwdCheckBoxState
)
545 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0, makeAny( sal_True
) );
548 else if( !bWasEnabled
&& mbIsPwdEnabled
)
550 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
551 if( mbPwdCheckBoxState
)
552 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0, makeAny( sal_True
) );
554 else if( bWasEnabled
&& !mbIsPwdEnabled
)
556 // remember user settings until checkbox is enabled
557 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
558 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0 );
559 bool bPassWord
= false;
560 mbPwdCheckBoxState
= ( aValue
>>= bPassWord
) && bPassWord
;
561 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0, makeAny( sal_False
) );
565 void FileDialogHelper_Impl::updatePreviewState( bool _bUpdatePreviewWindow
)
569 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
571 // check, whether or not we have to display a preview
572 if ( xCtrlAccess
.is() )
576 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0 );
577 bool bShowPreview
= false;
579 if ( aValue
>>= bShowPreview
)
581 mbShowPreview
= bShowPreview
;
583 // setShowState has currently no effect for the
584 // OpenOffice FilePicker (see svtools/source/filepicker/iodlg.cxx)
585 uno::Reference
< XFilePreview
> xFilePreview( mxFileDlg
, UNO_QUERY
);
586 if ( xFilePreview
.is() )
587 xFilePreview
->setShowState( mbShowPreview
);
589 if ( _bUpdatePreviewWindow
)
590 TimeOutHdl_Impl( NULL
);
593 catch( const Exception
& )
595 SAL_WARN( "sfx.dialog", "FileDialogHelper_Impl::updatePreviewState: caught an exception!" );
601 void FileDialogHelper_Impl::updateVersions()
603 Sequence
< OUString
> aEntries
;
604 Sequence
< OUString
> aPathSeq
= mxFileDlg
->getFiles();
606 if ( aPathSeq
.getLength() == 1 )
608 INetURLObject
aObj( aPathSeq
[0] );
610 if ( ( aObj
.GetProtocol() == INetProtocol::File
) &&
611 ( utl::UCBContentHelper::IsDocument( aObj
.GetMainURL( INetURLObject::NO_DECODE
) ) ) )
615 uno::Reference
< embed::XStorage
> xStorage
= ::comphelper::OStorageHelper::GetStorageFromURL(
616 aObj
.GetMainURL( INetURLObject::NO_DECODE
),
617 embed::ElementModes::READ
);
619 DBG_ASSERT( xStorage
.is(), "The method must return the storage or throw an exception!" );
620 if ( !xStorage
.is() )
621 throw uno::RuntimeException();
623 uno::Sequence
< util::RevisionTag
> xVersions
= SfxMedium::GetVersionList( xStorage
);
625 aEntries
.realloc( xVersions
.getLength() + 1 );
626 aEntries
[0] = SfxResId( STR_SFX_FILEDLG_ACTUALVERSION
).toString();
628 for ( sal_Int32 i
=0; i
<xVersions
.getLength(); i
++ )
629 aEntries
[ i
+ 1 ] = xVersions
[i
].Identifier
;
631 catch( const uno::Exception
& )
637 uno::Reference
< XFilePickerControlAccess
> xDlg( mxFileDlg
, UNO_QUERY
);
642 xDlg
->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
643 ControlActions::DELETE_ITEMS
, aValue
);
645 catch( const IllegalArgumentException
& ){}
647 sal_Int32 nCount
= aEntries
.getLength();
654 xDlg
->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
655 ControlActions::ADD_ITEMS
, aValue
);
658 aPos
<<= (sal_Int32
) 0;
659 xDlg
->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
660 ControlActions::SET_SELECT_ITEM
, aPos
);
662 catch( const IllegalArgumentException
& ){}
666 IMPL_LINK_NOARG_TYPED(FileDialogHelper_Impl
, TimeOutHdl_Impl
, Idle
*, void)
674 uno::Reference
< XFilePreview
> xFilePicker( mxFileDlg
, UNO_QUERY
);
676 if ( ! xFilePicker
.is() )
679 Sequence
< OUString
> aPathSeq
= mxFileDlg
->getFiles();
681 if ( mbShowPreview
&& ( aPathSeq
.getLength() == 1 ) )
683 OUString aURL
= aPathSeq
[0];
685 if ( ERRCODE_NONE
== getGraphic( aURL
, maGraphic
) )
687 // changed the code slightly;
688 // before: the bitmap was scaled and
689 // surrounded a white frame
690 // now: the bitmap will only be scaled
691 // and the filepicker implementation
692 // is responsible for placing it at its
693 // proper position and painting a frame
695 Bitmap aBmp
= maGraphic
.GetBitmap();
696 if ( !aBmp
.IsEmpty() )
698 // scale the bitmap to the correct size
699 sal_Int32 nOutWidth
= xFilePicker
->getAvailableWidth();
700 sal_Int32 nOutHeight
= xFilePicker
->getAvailableHeight();
701 sal_Int32 nBmpWidth
= aBmp
.GetSizePixel().Width();
702 sal_Int32 nBmpHeight
= aBmp
.GetSizePixel().Height();
704 double nXRatio
= (double) nOutWidth
/ nBmpWidth
;
705 double nYRatio
= (double) nOutHeight
/ nBmpHeight
;
707 if ( nXRatio
< nYRatio
)
708 aBmp
.Scale( nXRatio
, nXRatio
);
710 aBmp
.Scale( nYRatio
, nYRatio
);
712 // Convert to true color, to allow CopyPixel
713 aBmp
.Convert( BMP_CONVERSION_24BIT
);
715 // and copy it into the Any
716 SvMemoryStream aData
;
718 WriteDIB(aBmp
, aData
, false, true);
720 const Sequence
< sal_Int8
> aBuffer(
721 static_cast< const sal_Int8
* >(aData
.GetData()),
722 aData
.GetEndOfData() );
731 SolarMutexReleaser aReleaseForCallback
;
732 // clear the preview window
733 xFilePicker
->setImage( FilePreviewImageFormats::BITMAP
, aAny
);
735 catch( const IllegalArgumentException
& )
740 ErrCode
FileDialogHelper_Impl::getGraphic( const OUString
& rURL
,
741 Graphic
& rGraphic
) const
743 if ( utl::UCBContentHelper::IsFolder( rURL
) )
744 return ERRCODE_IO_NOTAFILE
;
746 if ( !mpGraphicFilter
)
747 return ERRCODE_IO_NOTSUPPORTED
;
749 // select graphic filter from dialog filter selection
750 OUString
aCurFilter( getFilter() );
752 sal_uInt16 nFilter
= !aCurFilter
.isEmpty() && mpGraphicFilter
->GetImportFormatCount()
753 ? mpGraphicFilter
->GetImportFormatNumber( aCurFilter
)
754 : GRFILTER_FORMAT_DONTKNOW
;
756 INetURLObject
aURLObj( rURL
);
758 if ( aURLObj
.HasError() || INetProtocol::NotValid
== aURLObj
.GetProtocol() )
760 aURLObj
.SetSmartProtocol( INetProtocol::File
);
761 aURLObj
.SetSmartURL( rURL
);
764 ErrCode nRet
= ERRCODE_NONE
;
766 GraphicFilterImportFlags nFilterImportFlags
= GraphicFilterImportFlags::SetLogsizeForJpeg
;
768 if ( INetProtocol::File
!= aURLObj
.GetProtocol() )
770 SvStream
* pStream
= ::utl::UcbStreamHelper::CreateStream( rURL
, StreamMode::READ
);
773 nRet
= mpGraphicFilter
->ImportGraphic( rGraphic
, rURL
, *pStream
, nFilter
, NULL
, nFilterImportFlags
);
775 nRet
= mpGraphicFilter
->ImportGraphic( rGraphic
, aURLObj
, nFilter
, NULL
, nFilterImportFlags
);
780 nRet
= mpGraphicFilter
->ImportGraphic( rGraphic
, aURLObj
, nFilter
, NULL
, nFilterImportFlags
);
786 ErrCode
FileDialogHelper_Impl::getGraphic( Graphic
& rGraphic
) const
788 ErrCode nRet
= ERRCODE_NONE
;
790 // rhbz#1079672 do not return maGraphic, it need not be the selected file
793 Sequence
<OUString
> aPathSeq
= mxFileDlg
->getFiles();
795 if (aPathSeq
.getLength() == 1)
800 if (!aPath
.isEmpty())
801 nRet
= getGraphic(aPath
, rGraphic
);
803 nRet
= ERRCODE_IO_GENERAL
;
808 static bool lcl_isSystemFilePicker( const uno::Reference
< XFilePicker
>& _rxFP
)
812 uno::Reference
< XServiceInfo
> xSI( _rxFP
, UNO_QUERY
);
815 return xSI
->supportsService( "com.sun.star.ui.dialogs.SystemFilePicker" );
817 catch( const Exception
& )
823 enum open_or_save_t
{OPEN
, SAVE
, UNDEFINED
};
824 static open_or_save_t
lcl_OpenOrSave(sal_Int16
const nDialogType
)
828 case FILEOPEN_SIMPLE
:
829 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
831 case FILEOPEN_READONLY_VERSION
:
832 case FILEOPEN_LINK_PREVIEW
:
834 case FILESAVE_SIMPLE
:
835 case FILESAVE_AUTOEXTENSION_PASSWORD
:
836 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
837 case FILESAVE_AUTOEXTENSION_SELECTION
:
838 case FILESAVE_AUTOEXTENSION_TEMPLATE
:
839 case FILESAVE_AUTOEXTENSION
:
842 assert(false); // invalid dialog type
847 // FileDialogHelper_Impl
849 FileDialogHelper_Impl::FileDialogHelper_Impl(
850 FileDialogHelper
* _pAntiImpl
,
851 sal_Int16 nDialogType
,
854 vcl::Window
* _pPreferredParentWindow
,
855 const OUString
& sStandardDir
,
856 const ::com::sun::star::uno::Sequence
< OUString
>& rBlackList
858 :m_nDialogType ( nDialogType
)
859 ,meContext ( FileDialogHelper::UNKNOWN_CONTEXT
)
861 const char* pServiceName
=0;
862 if ( nDialog
== SFX2_IMPL_DIALOG_SYSTEM
)
863 pServiceName
= FILE_OPEN_SERVICE_NAME_OOO
;
864 else if ( nDialog
== SFX2_IMPL_DIALOG_OOO
)
865 pServiceName
= FILE_OPEN_SERVICE_NAME_OOO
;
867 pServiceName
= "com.sun.star.ui.dialogs.FilePicker";
868 OUString aService
= OUString::createFromAscii( pServiceName
);
870 uno::Reference
< XMultiServiceFactory
> xFactory( ::comphelper::getProcessServiceFactory() );
872 // create the file open dialog
873 // the flags can be SFXWB_INSERT or SFXWB_MULTISELECTION
875 mpPreferredParentWindow
= _pPreferredParentWindow
;
876 mpAntiImpl
= _pAntiImpl
;
877 mnError
= ERRCODE_NONE
;
878 mbHasAutoExt
= false;
879 mbHasPassword
= false;
880 m_bHaveFilterOptions
= false;
881 mbIsPwdEnabled
= true;
882 mbHasVersions
= false;
883 mbHasPreview
= false;
884 mbShowPreview
= false;
885 mbAddGraphicFilter
= SFXWB_GRAPHIC
== (nFlags
& SFXWB_GRAPHIC
);
886 mbDeleteMatcher
= false;
887 mbInsert
= SFXWB_INSERT
== ( nFlags
& SFXWB_INSERT
);
888 mbExport
= SFXWB_EXPORT
== ( nFlags
& SFXWB_EXPORT
);
890 mbIsSaveACopyDlg
= SFXWB_SAVEACOPY
== ( nFlags
& SFXWB_SAVEACOPY
);
891 mbPwdCheckBoxState
= false;
893 mbSelectionEnabled
= true;
894 mbHasSelectionBox
= false;
895 mbSelectionFltrEnabled
= false;
898 m_nDontFlags
= SFX_FILTER_NOTINSTALLED
| SfxFilterFlags::INTERNAL
| SfxFilterFlags::NOTINFILEDLG
;
899 if (OPEN
== lcl_OpenOrSave(m_nDialogType
))
900 m_nMustFlags
= SfxFilterFlags::IMPORT
;
902 m_nMustFlags
= SfxFilterFlags::EXPORT
;
906 mpGraphicFilter
= NULL
;
907 mnPostUserEventId
= 0;
909 // create the picker component
910 mxFileDlg
.set(xFactory
->createInstance( aService
), css::uno::UNO_QUERY
);
911 mbSystemPicker
= lcl_isSystemFilePicker( mxFileDlg
);
913 uno::Reference
< XFilePickerNotifier
> xNotifier( mxFileDlg
, UNO_QUERY
);
914 uno::Reference
< XInitialization
> xInit( mxFileDlg
, UNO_QUERY
);
916 if ( ! mxFileDlg
.is() || ! xNotifier
.is() )
918 mnError
= ERRCODE_ABORT
;
925 sal_Int16 nTemplateDescription
= TemplateDescription::FILEOPEN_SIMPLE
;
927 switch ( m_nDialogType
)
929 case FILEOPEN_SIMPLE
:
930 nTemplateDescription
= TemplateDescription::FILEOPEN_SIMPLE
;
933 case FILESAVE_SIMPLE
:
934 nTemplateDescription
= TemplateDescription::FILESAVE_SIMPLE
;
938 case FILESAVE_AUTOEXTENSION_PASSWORD
:
939 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD
;
940 mbHasPassword
= true;
945 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
946 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
;
947 mbHasPassword
= true;
949 m_bHaveFilterOptions
= true;
952 mxFilterCFG
= uno::Reference
< XNameAccess
>(
953 xFactory
->createInstance( "com.sun.star.document.FilterFactory" ),
961 case FILESAVE_AUTOEXTENSION_SELECTION
:
962 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION
;
965 mbHasSelectionBox
= true;
966 if ( mbExport
&& !mxFilterCFG
.is() && xFactory
.is() )
968 mxFilterCFG
= uno::Reference
< XNameAccess
>(
969 xFactory
->createInstance( "com.sun.star.document.FilterFactory" ),
974 case FILESAVE_AUTOEXTENSION_TEMPLATE
:
975 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE
;
980 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
981 nTemplateDescription
= TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
;
985 maPreviewIdle
.SetPriority( SchedulerPriority::LOWEST
);
986 maPreviewIdle
.SetIdleHdl( LINK( this, FileDialogHelper_Impl
, TimeOutHdl_Impl
) );
990 nTemplateDescription
= TemplateDescription::FILEOPEN_PLAY
;
993 case FILEOPEN_READONLY_VERSION
:
994 nTemplateDescription
= TemplateDescription::FILEOPEN_READONLY_VERSION
;
995 mbHasVersions
= true;
998 case FILEOPEN_LINK_PREVIEW
:
999 nTemplateDescription
= TemplateDescription::FILEOPEN_LINK_PREVIEW
;
1000 mbHasPreview
= true;
1002 maPreviewIdle
.SetPriority( SchedulerPriority::LOWEST
);
1003 maPreviewIdle
.SetIdleHdl( LINK( this, FileDialogHelper_Impl
, TimeOutHdl_Impl
) );
1006 case FILESAVE_AUTOEXTENSION
:
1007 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION
;
1008 mbHasAutoExt
= true;
1013 SAL_WARN( "sfx.dialog", "FileDialogHelper::ctor with unknown type" );
1017 Sequence
< Any
> aInitArguments( !mpPreferredParentWindow
? 3 : 4 );
1019 // This is a hack. We currently know that the internal file picker implementation
1020 // supports the extended arguments as specified below.
1022 // a) adjust the service description so that it includes the TemplateDescription and ParentWindow args
1023 // b) adjust the implementation of the system file picker to that it recognizes it
1024 if ( mbSystemPicker
)
1026 aInitArguments
[0] <<= nTemplateDescription
;
1030 aInitArguments
[0] <<= NamedValue(
1031 OUString( "TemplateDescription" ),
1032 makeAny( nTemplateDescription
)
1035 OUString sStandardDirTemp
= sStandardDir
;
1037 aInitArguments
[1] <<= NamedValue(
1038 OUString( "StandardDir" ),
1039 makeAny( sStandardDirTemp
)
1042 aInitArguments
[2] <<= NamedValue(
1043 OUString( "BlackList" ),
1044 makeAny( rBlackList
)
1048 if ( mpPreferredParentWindow
)
1049 aInitArguments
[3] <<= NamedValue(
1050 OUString( "ParentWindow" ),
1051 makeAny( VCLUnoHelper::GetInterface( mpPreferredParentWindow
) )
1057 xInit
->initialize( aInitArguments
);
1059 catch( const Exception
& )
1061 OSL_FAIL( "FileDialogHelper_Impl::FileDialogHelper_Impl: could not initialize the picker!" );
1066 // set multiselection mode
1067 if ( nFlags
& SFXWB_MULTISELECTION
)
1068 mxFileDlg
->setMultiSelectionMode( sal_True
);
1070 if (mbAddGraphicFilter
) // generate graphic filter only on demand
1078 mxFileDlg
->setTitle( SfxResId( STR_SFX_EXPLORERFILE_EXPORT
).toString() );
1080 com::sun::star::uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY_THROW
);
1081 xCtrlAccess
->enableControl( ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR
, sal_True
);
1083 catch( const Exception
& ) { }
1086 // Save a copy dialog
1087 if ( mbIsSaveACopyDlg
)
1089 mxFileDlg
->setTitle( SfxResId( STR_PB_SAVEACOPY
).toString() );
1092 // the "insert file" dialog needs another title
1095 mxFileDlg
->setTitle( SfxResId( STR_SFX_EXPLORERFILE_INSERT
).toString() );
1096 uno::Reference
< XFilePickerControlAccess
> xExtDlg( mxFileDlg
, UNO_QUERY
);
1101 xExtDlg
->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK
,
1102 SfxResId( STR_SFX_EXPLORERFILE_BUTTONINSERT
).toString() );
1104 catch( const IllegalArgumentException
& ){}
1108 // add the event listener
1109 xNotifier
->addFilePickerListener( this );
1112 FileDialogHelper_Impl::~FileDialogHelper_Impl()
1114 // Remove user event if we haven't received it yet
1115 if ( mnPostUserEventId
)
1116 Application::RemoveUserEvent( mnPostUserEventId
);
1117 mnPostUserEventId
= 0;
1119 delete mpGraphicFilter
;
1121 if ( mbDeleteMatcher
)
1124 maPreviewIdle
.SetIdleHdl( Link
<Idle
*, void>() );
1126 ::comphelper::disposeComponent( mxFileDlg
);
1129 void FileDialogHelper_Impl::setControlHelpIds( const sal_Int16
* _pControlId
, const char** _pHelpId
)
1131 DBG_ASSERT( _pControlId
&& _pHelpId
, "FileDialogHelper_Impl::setControlHelpIds: invalid array pointers!" );
1132 if ( !_pControlId
|| !_pHelpId
)
1135 // forward these ids to the file picker
1138 const OUString
sHelpIdPrefix( INET_HID_SCHEME
);
1139 // the ids for the single controls
1140 uno::Reference
< XFilePickerControlAccess
> xControlAccess( mxFileDlg
, UNO_QUERY
);
1141 if ( xControlAccess
.is() )
1143 while ( *_pControlId
)
1145 DBG_ASSERT( INetURLObject( OStringToOUString( *_pHelpId
, RTL_TEXTENCODING_UTF8
) ).GetProtocol() == INetProtocol::NotValid
, "Wrong HelpId!" );
1146 OUString
sId( sHelpIdPrefix
);
1147 sId
+= OUString( *_pHelpId
, strlen( *_pHelpId
), RTL_TEXTENCODING_UTF8
);
1148 xControlAccess
->setValue( *_pControlId
, ControlActions::SET_HELP_URL
, makeAny( sId
) );
1150 ++_pControlId
; ++_pHelpId
;
1154 catch( const Exception
& )
1156 OSL_FAIL( "FileDialogHelper_Impl::setControlHelpIds: caught an exception while setting the help ids!" );
1160 IMPL_LINK_NOARG( FileDialogHelper_Impl
, InitControls
)
1162 mnPostUserEventId
= 0;
1163 enablePasswordBox( true );
1164 updateFilterOptionsBox( );
1165 updateSelectionBox( );
1170 void FileDialogHelper_Impl::preExecute()
1173 setDefaultValues( );
1174 updatePreviewState( false );
1176 implInitializeFileName( );
1178 #if !(defined(MACOSX) && defined(MACOSX)) && !defined(WNT)
1179 // allow for dialog implementations which need to be executed before they return valid values for
1180 // current filter and such
1182 // On Vista (at least SP1) it's the same as on MacOSX, the modal dialog won't let message pass
1183 // through before it returns from execution
1184 mnPostUserEventId
= Application::PostUserEvent( LINK( this, FileDialogHelper_Impl
, InitControls
) );
1186 // However, the Mac OS X implementation's pickers run modally in execute and so the event doesn't
1187 // get through in time... so we call the methods directly
1188 enablePasswordBox( true );
1189 updateFilterOptionsBox( );
1190 updateSelectionBox( );
1194 void FileDialogHelper_Impl::postExecute( sal_Int16 _nResult
)
1196 if ( ExecutableDialogResults::CANCEL
!= _nResult
)
1200 void FileDialogHelper_Impl::implInitializeFileName( )
1202 if ( !maFileName
.isEmpty() )
1204 INetURLObject
aObj( maPath
);
1205 aObj
.Append( maFileName
);
1207 // in case we're operating as save dialog, and "auto extension" is checked,
1208 // cut the extension from the name
1209 if ( mbIsSaveDlg
&& mbHasAutoExt
)
1213 bool bAutoExtChecked
= false;
1215 uno::Reference
< XFilePickerControlAccess
> xControlAccess( mxFileDlg
, UNO_QUERY
);
1216 if ( xControlAccess
.is()
1217 && ( xControlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0 )
1222 if ( bAutoExtChecked
)
1223 { // cut the extension
1224 aObj
.removeExtension( );
1225 mxFileDlg
->setDefaultName( aObj
.GetName( INetURLObject::DECODE_WITH_CHARSET
) );
1229 catch( const Exception
& )
1231 OSL_FAIL( "FileDialogHelper_Impl::implInitializeFileName: could not ask for the auto-extension current-value!" );
1237 sal_Int16
FileDialogHelper_Impl::implDoExecute()
1241 sal_Int16 nRet
= ExecutableDialogResults::CANCEL
;
1243 //On MacOSX the native file picker has to run in the primordial thread because of drawing issues
1244 //On Linux the native gtk file picker, when backed by gnome-vfs2, needs to be run in the same
1245 //primordial thread as the ucb gnome-vfs2 provider was initialized in.
1251 if ( mbSystemPicker
)
1253 SolarMutexReleaser aSolarMutex
;
1254 nRet
= mxFileDlg
->execute();
1258 nRet
= mxFileDlg
->execute();
1260 catch( const Exception
& )
1262 SAL_WARN( "sfx.dialog", "FileDialogHelper_Impl::implDoExecute: caught an exception!" );
1266 postExecute( nRet
);
1271 void FileDialogHelper_Impl::implStartExecute()
1273 DBG_ASSERT( mxFileDlg
.is(), "invalid file dialog" );
1277 if ( mbSystemPicker
)
1284 uno::Reference
< XAsynchronousExecutableDialog
> xAsyncDlg( mxFileDlg
, UNO_QUERY
);
1285 if ( xAsyncDlg
.is() )
1286 xAsyncDlg
->startExecuteModal( this );
1288 catch( const Exception
& )
1290 SAL_WARN( "sfx.dialog", "FileDialogHelper_Impl::implDoExecute: caught an exception!" );
1295 void lcl_saveLastURLs(std::vector
<OUString
>& rpURLList
,
1296 ::std::vector
< OUString
>& lLastURLs
)
1299 for(std::vector
<OUString
>::iterator i
= rpURLList
.begin(); i
!= rpURLList
.end(); ++i
)
1300 lLastURLs
.push_back(*i
);
1303 void FileDialogHelper_Impl::implGetAndCacheFiles(const uno::Reference
< XInterface
>& xPicker
, std::vector
<OUString
>& rpURLList
, const SfxFilter
* pFilter
)
1307 OUString sExtension
;
1310 sExtension
= pFilter
->GetDefaultExtension ();
1311 sExtension
= comphelper::string::remove(sExtension
, '*');
1312 sExtension
= comphelper::string::remove(sExtension
, '.');
1315 // a) the new way (optional!)
1316 uno::Reference
< XFilePicker2
> xPickNew(xPicker
, UNO_QUERY
);
1319 Sequence
< OUString
> lFiles
= xPickNew
->getSelectedFiles();
1320 ::sal_Int32 nFiles
= lFiles
.getLength();
1321 for(sal_Int32 i
= 0; i
< nFiles
; ++i
)
1322 rpURLList
.push_back(lFiles
[i
]);
1325 // b) the olde way ... non optional.
1328 uno::Reference
< XFilePicker
> xPickOld(xPicker
, UNO_QUERY_THROW
);
1329 Sequence
< OUString
> lFiles
= xPickOld
->getFiles();
1330 ::sal_Int32 nFiles
= lFiles
.getLength();
1333 rpURLList
.push_back(lFiles
[0]);
1335 else if ( nFiles
> 1 )
1337 INetURLObject
aPath( lFiles
[0] );
1338 aPath
.setFinalSlash();
1340 for (::sal_Int32 i
= 1; i
< nFiles
; i
++)
1343 aPath
.Append( lFiles
[i
] );
1345 aPath
.setName( lFiles
[i
] );
1347 rpURLList
.push_back(aPath
.GetMainURL(INetURLObject::NO_DECODE
));
1352 lcl_saveLastURLs(rpURLList
, mlLastURLs
);
1355 ErrCode
FileDialogHelper_Impl::execute( std::vector
<OUString
>& rpURLList
,
1356 SfxItemSet
*& rpSet
,
1359 // rFilter is a pure output parameter, it shouldn't be used for anything else
1360 // changing this would surely break code
1361 // rpSet is in/out parameter, usually just a media-descriptor that can be changed by dialog
1363 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
1365 // retrieves parameters from rpSet
1366 // for now only Password is used
1369 // check password checkbox if the document had password before
1372 SFX_ITEMSET_ARG( rpSet
, pPassItem
, SfxBoolItem
, SID_PASSWORDINTERACTION
, false );
1373 mbPwdCheckBoxState
= ( pPassItem
!= NULL
&& pPassItem
->GetValue() );
1375 // in case the document has password to modify, the dialog should be shown
1376 SFX_ITEMSET_ARG( rpSet
, pPassToModifyItem
, SfxUnoAnyItem
, SID_MODIFYPASSWORDINFO
, false );
1377 mbPwdCheckBoxState
|= ( pPassToModifyItem
&& pPassToModifyItem
->GetValue().hasValue() );
1380 SFX_ITEMSET_ARG( rpSet
, pSelectItem
, SfxBoolItem
, SID_SELECTION
, false );
1382 mbSelection
= pSelectItem
->GetValue();
1384 mbSelectionEnabled
= false;
1386 // the password will be set in case user decide so
1387 rpSet
->ClearItem( SID_PASSWORDINTERACTION
);
1388 rpSet
->ClearItem( SID_PASSWORD
);
1389 rpSet
->ClearItem( SID_ENCRYPTIONDATA
);
1390 rpSet
->ClearItem( SID_RECOMMENDREADONLY
);
1391 rpSet
->ClearItem( SID_MODIFYPASSWORDINFO
);
1395 if ( mbHasPassword
&& !mbPwdCheckBoxState
)
1397 SvtSecurityOptions aSecOpt
;
1398 mbPwdCheckBoxState
= (
1399 aSecOpt
.IsOptionSet( SvtSecurityOptions::E_DOCWARN_RECOMMENDPASSWORD
) );
1404 if ( ! mxFileDlg
.is() )
1405 return ERRCODE_ABORT
;
1407 if ( ExecutableDialogResults::CANCEL
!= implDoExecute() )
1409 // create an itemset if there is no
1411 rpSet
= new SfxAllItemSet( SfxGetpApp()->GetPool() );
1413 // the item should remain only if it was set by the dialog
1414 rpSet
->ClearItem( SID_SELECTION
);
1416 if( mbExport
&& mbHasSelectionBox
)
1420 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0 );
1421 bool bSelection
= false;
1422 if ( aValue
>>= bSelection
)
1423 rpSet
->Put( SfxBoolItem( SID_SELECTION
, bSelection
) );
1425 catch( const IllegalArgumentException
& )
1427 OSL_FAIL( "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
1432 // set the read-only flag. When inserting a file, this flag is always set
1434 rpSet
->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
1437 if ( ( FILEOPEN_READONLY_VERSION
== m_nDialogType
) && xCtrlAccess
.is() )
1441 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY
, 0 );
1442 bool bReadOnly
= false;
1443 if ( ( aValue
>>= bReadOnly
) && bReadOnly
)
1444 rpSet
->Put( SfxBoolItem( SID_DOC_READONLY
, bReadOnly
) );
1446 catch( const IllegalArgumentException
& )
1448 OSL_FAIL( "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
1452 if ( mbHasVersions
&& xCtrlAccess
.is() )
1456 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
1457 ControlActions::GET_SELECTED_ITEM_INDEX
);
1458 sal_Int32 nVersion
= 0;
1459 if ( ( aValue
>>= nVersion
) && nVersion
> 0 )
1460 // open a special version; 0 == current version
1461 rpSet
->Put( SfxInt16Item( SID_VERSION
, (short)nVersion
) );
1463 catch( const IllegalArgumentException
& ){}
1467 getRealFilter( rFilter
);
1469 const SfxFilter
* pCurrentFilter
= getCurentSfxFilter();
1471 // fill the rpURLList
1472 implGetAndCacheFiles( mxFileDlg
, rpURLList
, pCurrentFilter
);
1473 if ( rpURLList
.empty() )
1474 return ERRCODE_ABORT
;
1476 // check, whether or not we have to display a password box
1477 if ( pCurrentFilter
&& mbHasPassword
&& mbIsPwdEnabled
&& xCtrlAccess
.is() )
1481 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0 );
1482 bool bPassWord
= false;
1483 if ( ( aValue
>>= bPassWord
) && bPassWord
)
1485 // ask for a password
1486 OUString
aDocName(rpURLList
[0]);
1487 ErrCode errCode
= RequestPassword(pCurrentFilter
, aDocName
, rpSet
);
1488 if (errCode
!= ERRCODE_NONE
)
1492 catch( const IllegalArgumentException
& ){}
1495 SaveLastUsedFilter();
1496 return ERRCODE_NONE
;
1499 return ERRCODE_ABORT
;
1502 ErrCode
FileDialogHelper_Impl::execute()
1504 if ( ! mxFileDlg
.is() )
1505 return ERRCODE_ABORT
;
1507 sal_Int16 nRet
= implDoExecute();
1509 maPath
= mxFileDlg
->getDisplayDirectory();
1511 if ( ExecutableDialogResults::CANCEL
== nRet
)
1512 return ERRCODE_ABORT
;
1515 return ERRCODE_NONE
;
1519 OUString
FileDialogHelper_Impl::getPath() const
1523 if ( mxFileDlg
.is() )
1524 aPath
= mxFileDlg
->getDisplayDirectory();
1526 if ( aPath
.isEmpty() )
1532 OUString
FileDialogHelper_Impl::getFilter() const
1534 OUString aFilter
= getCurrentFilterUIName();
1536 if( aFilter
.isEmpty() )
1537 aFilter
= maCurFilter
;
1542 void FileDialogHelper_Impl::getRealFilter( OUString
& _rFilter
) const
1544 _rFilter
= getCurrentFilterUIName();
1546 if ( _rFilter
.isEmpty() )
1547 _rFilter
= maCurFilter
;
1549 if ( !_rFilter
.isEmpty() && mpMatcher
)
1551 const SfxFilter
* pFilter
=
1552 mpMatcher
->GetFilter4UIName( _rFilter
, m_nMustFlags
, m_nDontFlags
);
1553 _rFilter
= pFilter
? pFilter
->GetFilterName() : OUString("");
1557 void FileDialogHelper_Impl::verifyPath()
1560 // lp#905355, fdo#43895
1561 // Check that the file has read only permission and is in /tmp -- this is
1562 // the case if we have opened the file from the web with firefox only.
1563 if (maFileName
.isEmpty()) {
1566 INetURLObject
url(maPath
);
1567 if (url
.GetProtocol() != INetProtocol::File
1568 || url
.getName(0, true, INetURLObject::DECODE_WITH_CHARSET
) != "tmp")
1572 if (maFileName
.indexOf('/') != -1) {
1573 SAL_WARN("sfx.dialog", maFileName
<< " contains /");
1577 maFileName
, false, INetURLObject::LAST_SEGMENT
, true,
1578 INetURLObject::ENCODE_ALL
);
1580 osl::FileBase::RC e
= osl::FileBase::getSystemPathFromFileURL(
1581 url
.GetMainURL(INetURLObject::NO_DECODE
), sysPathU
);
1582 if (e
!= osl::FileBase::E_None
) {
1585 "getSystemPathFromFileURL("
1586 << url
.GetMainURL(INetURLObject::NO_DECODE
) << ") failed with "
1591 if (!sysPathU
.convertToString(
1592 &sysPathC
, osl_getThreadTextEncoding(),
1593 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
1594 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
1598 "convertToString(" << sysPathU
<< ") failed for encoding "
1599 << +osl_getThreadTextEncoding());
1602 struct stat aFileStat
;
1603 if (stat(sysPathC
.getStr(), &aFileStat
) == -1) {
1606 "stat(" << sysPathC
.getStr() << ") failed with errno " << errno
);
1609 if ((aFileStat
.st_mode
& (S_IRWXO
| S_IRWXG
| S_IRWXU
)) == S_IRUSR
) {
1610 maPath
= SvtPathOptions().GetWorkPath();
1611 mxFileDlg
->setDisplayDirectory( maPath
);
1616 void FileDialogHelper_Impl::displayFolder( const OUString
& _rPath
)
1618 if ( _rPath
.isEmpty() )
1623 if ( mxFileDlg
.is() )
1627 mxFileDlg
->setDisplayDirectory( maPath
);
1630 catch( const IllegalArgumentException
& )
1632 OSL_FAIL( "FileDialogHelper_Impl::displayFolder: caught an exception!" );
1637 void FileDialogHelper_Impl::setFileName( const OUString
& _rFile
)
1639 maFileName
= _rFile
;
1640 if ( mxFileDlg
.is() )
1644 mxFileDlg
->setDefaultName( maFileName
);
1647 catch( const IllegalArgumentException
& )
1649 OSL_FAIL( "FileDialogHelper_Impl::setFileName: caught an exception!" );
1654 void FileDialogHelper_Impl::setFilter( const OUString
& rFilter
)
1656 DBG_ASSERT( rFilter
.indexOf(':') == -1, "Old filter name used!");
1658 maCurFilter
= rFilter
;
1660 if ( !rFilter
.isEmpty() && mpMatcher
)
1662 const SfxFilter
* pFilter
= mpMatcher
->GetFilter4FilterName(
1663 rFilter
, m_nMustFlags
, m_nDontFlags
);
1665 maCurFilter
= pFilter
->GetUIName();
1668 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
1670 if ( !maCurFilter
.isEmpty() && xFltMgr
.is() )
1674 xFltMgr
->setCurrentFilter( maCurFilter
);
1676 catch( const IllegalArgumentException
& ){}
1680 void FileDialogHelper_Impl::createMatcher( const OUString
& rFactory
)
1682 if (mbDeleteMatcher
)
1685 mpMatcher
= new SfxFilterMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory
) );
1686 mbDeleteMatcher
= true;
1689 void FileDialogHelper_Impl::addFilters( const OUString
& rFactory
,
1690 SfxFilterFlags nMust
,
1691 SfxFilterFlags nDont
)
1693 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
1695 if ( ! xFltMgr
.is() )
1698 if (mbDeleteMatcher
)
1701 // we still need a matcher to convert UI names to filter names
1702 if ( rFactory
.isEmpty() )
1704 SfxApplication
*pSfxApp
= SfxGetpApp();
1705 mpMatcher
= &pSfxApp
->GetFilterMatcher();
1706 mbDeleteMatcher
= false;
1710 mpMatcher
= new SfxFilterMatcher( rFactory
);
1711 mbDeleteMatcher
= true;
1714 uno::Reference
< XMultiServiceFactory
> xSMGR
= ::comphelper::getProcessServiceFactory();
1715 uno::Reference
< XContainerQuery
> xFilterCont(
1716 xSMGR
->createInstance("com.sun.star.document.FilterFactory"),
1718 if ( ! xFilterCont
.is() )
1721 m_nMustFlags
|= nMust
;
1722 m_nDontFlags
|= nDont
;
1724 // create the list of filters
1725 OUStringBuffer
sQuery(256);
1726 sQuery
.append("getSortedFilterList()");
1727 sQuery
.append(":module=");
1728 sQuery
.append(rFactory
); // use long name here !
1729 sQuery
.append(":iflags=");
1730 sQuery
.append(OUString::number(static_cast<sal_Int32
>(m_nMustFlags
)));
1731 sQuery
.append(":eflags=");
1732 sQuery
.append(OUString::number(static_cast<sal_Int32
>(m_nDontFlags
)));
1734 uno::Reference
< XEnumeration
> xResult
;
1737 xResult
= xFilterCont
->createSubSetEnumerationByQuery(sQuery
.makeStringAndClear());
1739 catch( const uno::Exception
& )
1741 SAL_WARN( "sfx.dialog", "Could not get filters from the configuration!" );
1744 TSortedFilterList
aIter (xResult
);
1746 // append the filters
1747 OUString sFirstFilter
;
1748 if (OPEN
== lcl_OpenOrSave(m_nDialogType
))
1749 ::sfx2::appendFiltersForOpen( aIter
, xFltMgr
, sFirstFilter
, *this );
1750 else if ( mbExport
)
1751 ::sfx2::appendExportFilters( aIter
, xFltMgr
, sFirstFilter
, *this );
1753 ::sfx2::appendFiltersForSave( aIter
, xFltMgr
, sFirstFilter
, *this, rFactory
);
1755 // set our initial selected filter (if we do not already have one)
1756 if ( maSelectFilter
.isEmpty() )
1757 maSelectFilter
= sFirstFilter
;
1760 void FileDialogHelper_Impl::addFilter( const OUString
& rFilterName
,
1761 const OUString
& rExtension
)
1763 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
1765 if ( ! xFltMgr
.is() )
1770 xFltMgr
->appendFilter( rFilterName
, rExtension
);
1772 if ( maSelectFilter
.isEmpty() )
1773 maSelectFilter
= rFilterName
;
1775 catch( const IllegalArgumentException
& )
1777 SAL_WARN( "sfx.dialog", "Could not append Filter" << rFilterName
);
1781 void FileDialogHelper_Impl::addGraphicFilter()
1783 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
1785 if ( ! xFltMgr
.is() )
1788 // create the list of filters
1789 mpGraphicFilter
= new GraphicFilter
;
1790 sal_uInt16 i
, j
, nCount
= mpGraphicFilter
->GetImportFormatCount();
1792 // compute the extension string for all known import filters
1793 OUString aExtensions
;
1795 for ( i
= 0; i
< nCount
; i
++ )
1801 sWildcard
= mpGraphicFilter
->GetImportWildcard( i
, j
++ );
1802 if ( sWildcard
.isEmpty() )
1804 if ( aExtensions
.indexOf( sWildcard
) == -1 )
1806 if ( !aExtensions
.isEmpty() )
1808 aExtensions
+= sWildcard
;
1814 if ( aExtensions
.getLength() > 240 )
1815 aExtensions
= FILEDIALOG_FILTER_ALL
;
1817 bool bIsInOpenMode
= isInOpenMode();
1821 OUString aAllFilterName
= SfxResId( STR_SFX_IMPORT_ALL
).toString();
1822 aAllFilterName
= ::sfx2::addExtension( aAllFilterName
, aExtensions
, bIsInOpenMode
, *this );
1824 xFltMgr
->appendFilter( aAllFilterName
, aExtensions
);
1825 maSelectFilter
= aAllFilterName
;
1827 catch( const IllegalArgumentException
& )
1829 SAL_WARN( "sfx.dialog", "Could not append Filter" );
1832 // Now add the filter
1833 for ( i
= 0; i
< nCount
; i
++ )
1835 OUString aName
= mpGraphicFilter
->GetImportFormatName( i
);
1841 sWildcard
= mpGraphicFilter
->GetImportWildcard( i
, j
++ );
1842 if ( sWildcard
.isEmpty() )
1844 if ( aExt
.indexOf( sWildcard
) == -1 )
1846 if ( !aExt
.isEmpty() )
1851 aName
= ::sfx2::addExtension( aName
, aExt
, bIsInOpenMode
, *this );
1854 xFltMgr
->appendFilter( aName
, aExt
);
1856 catch( const IllegalArgumentException
& )
1858 SAL_WARN( "sfx.dialog", "Could not append Filter" );
1863 #define GRF_CONFIG_STR " "
1864 #define STD_CONFIG_STR "1 "
1866 static void SetToken( OUString
& rOrigStr
, sal_Int32 nToken
, sal_Unicode cTok
, const OUString
& rStr
)
1868 const sal_Unicode
* pStr
= rOrigStr
.getStr();
1869 sal_Int32 nLen
= rOrigStr
.getLength();
1871 sal_Int32 nFirstChar
= 0;
1872 sal_Int32 i
= nFirstChar
;
1874 // Determine token position and length
1878 // Increase token count if match
1879 if ( *pStr
== cTok
)
1883 if ( nTok
== nToken
)
1887 if ( nTok
> nToken
)
1896 if ( nTok
>= nToken
)
1897 rOrigStr
= rOrigStr
.replaceAt( nFirstChar
, i
-nFirstChar
, rStr
);
1901 void FileDialogHelper_Impl::saveConfig()
1903 uno::Reference
< XFilePickerControlAccess
> xDlg( mxFileDlg
, UNO_QUERY
);
1911 SvtViewOptions
aDlgOpt( E_DIALOG
, IMPGRF_CONFIGNAME
);
1912 OUString
aUserData(GRF_CONFIG_STR
);
1916 aValue
= xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0 );
1917 bool bValue
= false;
1919 SetToken( aUserData
, 1, ' ', OUString::number( (sal_Int32
) bValue
) );
1921 INetURLObject
aObj( getPath() );
1923 if ( aObj
.GetProtocol() == INetProtocol::File
)
1924 SetToken( aUserData
, 2, ' ', aObj
.GetMainURL( INetURLObject::NO_DECODE
) );
1926 OUString aFilter
= getFilter();
1927 aFilter
= EncodeSpaces_Impl( aFilter
);
1928 SetToken( aUserData
, 3, ' ', aFilter
);
1930 aDlgOpt
.SetUserItem( USERITEM_NAME
, makeAny( aUserData
) );
1932 catch( const IllegalArgumentException
& ){}
1936 bool bWriteConfig
= false;
1937 SvtViewOptions
aDlgOpt( E_DIALOG
, IODLG_CONFIGNAME
);
1938 OUString
aUserData(STD_CONFIG_STR
);
1940 if ( aDlgOpt
.Exists() )
1942 Any aUserItem
= aDlgOpt
.GetUserItem( USERITEM_NAME
);
1944 if ( aUserItem
>>= aTemp
)
1952 aValue
= xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0 );
1953 bool bAutoExt
= true;
1954 aValue
>>= bAutoExt
;
1955 SetToken( aUserData
, 0, ' ', OUString::number( (sal_Int32
) bAutoExt
) );
1956 bWriteConfig
= true;
1958 catch( const IllegalArgumentException
& ){}
1961 if ( ! mbIsSaveDlg
)
1963 OUString aPath
= getPath();
1964 if ( !aPath
.isEmpty() &&
1965 utl::LocalFileHelper::IsLocalFile( aPath
) )
1967 SetToken( aUserData
, 1, ' ', aPath
);
1968 bWriteConfig
= true;
1972 if( mbHasSelectionBox
&& mbSelectionFltrEnabled
)
1976 aValue
= xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0 );
1977 bool bSelection
= true;
1978 aValue
>>= bSelection
;
1979 if ( comphelper::string::getTokenCount(aUserData
, ' ') < 3 )
1981 SetToken( aUserData
, 2, ' ', OUString::number( (sal_Int32
) bSelection
) );
1982 bWriteConfig
= true;
1984 catch( const IllegalArgumentException
& ){}
1988 aDlgOpt
.SetUserItem( USERITEM_NAME
, makeAny( OUString( aUserData
) ) );
1991 SfxApplication
*pSfxApp
= SfxGetpApp();
1992 pSfxApp
->SetLastDir_Impl( getPath() );
1997 static OUString
getInitPath( const OUString
& _rFallback
, const sal_Int32 _nFallbackToken
)
1999 SfxApplication
*pSfxApp
= SfxGetpApp();
2000 OUString sPath
= pSfxApp
->GetLastDir_Impl();
2002 if ( sPath
.isEmpty() )
2003 sPath
= _rFallback
.getToken( _nFallbackToken
, ' ' );
2005 // check if the path points to a valid (accessible) directory
2006 bool bValid
= false;
2007 if ( !sPath
.isEmpty() )
2009 OUString
sPathCheck( sPath
);
2010 if ( sPathCheck
[ sPathCheck
.getLength() - 1 ] != '/' )
2015 ::ucbhelper::Content
aContent( sPathCheck
, uno::Reference
< ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
2016 bValid
= aContent
.isFolder();
2018 catch( const Exception
& ) {}
2028 void FileDialogHelper_Impl::loadConfig()
2030 uno::Reference
< XFilePickerControlAccess
> xDlg( mxFileDlg
, UNO_QUERY
);
2038 SvtViewOptions
aViewOpt( E_DIALOG
, IMPGRF_CONFIGNAME
);
2041 if ( aViewOpt
.Exists() )
2043 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
2045 if ( aUserItem
>>= aTemp
)
2049 if ( !aUserData
.isEmpty() )
2053 // respect the last "insert as link" state
2054 bool bLink
= aUserData
.getToken( 0, ' ' ).toInt32();
2056 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_LINK
, 0, aValue
);
2058 // respect the last "show preview" state
2059 bool bShowPreview
= aUserData
.getToken( 1, ' ' ).toInt32();
2060 aValue
<<= bShowPreview
;
2061 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0, aValue
);
2063 if ( maPath
.isEmpty() )
2064 displayFolder( getInitPath( aUserData
, 2 ) );
2066 if ( maCurFilter
.isEmpty() )
2068 OUString aFilter
= aUserData
.getToken( 3, ' ' );
2069 aFilter
= DecodeSpaces_Impl( aFilter
);
2070 setFilter( aFilter
);
2073 // set the member so we know that we have to show the preview
2074 mbShowPreview
= bShowPreview
;
2076 catch( const IllegalArgumentException
& ){}
2079 if ( maPath
.isEmpty() )
2080 displayFolder( SvtPathOptions().GetGraphicPath() );
2084 SvtViewOptions
aViewOpt( E_DIALOG
, IODLG_CONFIGNAME
);
2087 if ( aViewOpt
.Exists() )
2089 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
2091 if ( aUserItem
>>= aTemp
)
2095 if ( aUserData
.isEmpty() )
2096 aUserData
= STD_CONFIG_STR
;
2098 if ( maPath
.isEmpty() )
2099 displayFolder( getInitPath( aUserData
, 1 ) );
2103 sal_Int32 nFlag
= aUserData
.getToken( 0, ' ' ).toInt32();
2104 aValue
<<= (bool) nFlag
;
2107 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0, aValue
);
2109 catch( const IllegalArgumentException
& ){}
2112 if( mbHasSelectionBox
)
2114 sal_Int32 nFlag
= aUserData
.getToken( 2, ' ' ).toInt32();
2115 aValue
<<= (bool) nFlag
;
2118 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0, aValue
);
2120 catch( const IllegalArgumentException
& ){}
2123 if ( maPath
.isEmpty() )
2124 displayFolder( SvtPathOptions().GetWorkPath() );
2128 void FileDialogHelper_Impl::setDefaultValues()
2130 // when no filter is set, we set the curentFilter to <all>
2131 if ( maCurFilter
.isEmpty() && !maSelectFilter
.isEmpty() )
2133 uno::Reference
< XFilterManager
> xFltMgr( mxFileDlg
, UNO_QUERY
);
2136 xFltMgr
->setCurrentFilter( maSelectFilter
);
2138 catch( const IllegalArgumentException
& )
2142 // when no path is set, we use the standard 'work' folder
2143 if ( maPath
.isEmpty() )
2145 OUString aWorkFolder
= SvtPathOptions().GetWorkPath();
2148 mxFileDlg
->setDisplayDirectory( aWorkFolder
);
2150 catch( const Exception
& )
2152 OSL_FAIL( "FileDialogHelper_Impl::setDefaultValues: caught an exception while setting the display directory!" );
2157 bool FileDialogHelper_Impl::isShowFilterExtensionEnabled() const
2159 return !maFilters
.empty();
2162 void FileDialogHelper_Impl::addFilterPair( const OUString
& rFilter
,
2163 const OUString
& rFilterWithExtension
)
2165 maFilters
.push_back( FilterPair( rFilter
, rFilterWithExtension
) );
2169 OUString
FileDialogHelper_Impl::getFilterName( const OUString
& rFilterWithExtension
) const
2172 for( ::std::vector
< FilterPair
>::const_iterator pIter
= maFilters
.begin(); pIter
!= maFilters
.end(); ++pIter
)
2174 if ( (*pIter
).Second
== rFilterWithExtension
)
2176 sRet
= (*pIter
).First
;
2183 OUString
FileDialogHelper_Impl::getFilterWithExtension( const OUString
& rFilter
) const
2186 for( ::std::vector
< FilterPair
>::const_iterator pIter
= maFilters
.begin(); pIter
!= maFilters
.end(); ++pIter
)
2188 if ( (*pIter
).First
== rFilter
)
2190 sRet
= (*pIter
).Second
;
2197 void FileDialogHelper_Impl::SetContext( FileDialogHelper::Context _eNewContext
)
2199 meContext
= _eNewContext
;
2201 const OUString
* pConfigId
= GetLastFilterConfigId( _eNewContext
);
2203 LoadLastUsedFilter( *pConfigId
);
2208 FileDialogHelper::FileDialogHelper(
2209 sal_Int16 nDialogType
,
2211 const OUString
& rFact
,
2212 SfxFilterFlags nMust
,
2213 SfxFilterFlags nDont
)
2216 mpImp
= new FileDialogHelper_Impl( this, nDialogType
, nFlags
);
2219 // create the list of filters
2221 SfxObjectShell::GetServiceNameFromFactory(rFact
), nMust
, nDont
);
2224 FileDialogHelper::FileDialogHelper(
2225 sal_Int16 nDialogType
,
2227 const OUString
& rFact
,
2229 SfxFilterFlags nMust
,
2230 SfxFilterFlags nDont
,
2231 const OUString
& rStandardDir
,
2232 const ::com::sun::star::uno::Sequence
< OUString
>& rBlackList
)
2235 mpImp
= new FileDialogHelper_Impl( this, nDialogType
, nFlags
, nDialog
, NULL
, rStandardDir
, rBlackList
);
2238 // create the list of filters
2240 SfxObjectShell::GetServiceNameFromFactory(rFact
), nMust
, nDont
);
2243 FileDialogHelper::FileDialogHelper(
2244 sal_Int16 nDialogType
,
2246 vcl::Window
* _pPreferredParent
)
2249 mpImp
= new FileDialogHelper_Impl( this, nDialogType
, nFlags
, SFX2_IMPL_DIALOG_CONFIG
, _pPreferredParent
);
2253 FileDialogHelper::FileDialogHelper(
2254 sal_Int16 nDialogType
,
2256 const OUString
& aFilterUIName
,
2257 const OUString
& aExtName
,
2258 const OUString
& rStandardDir
,
2259 const ::com::sun::star::uno::Sequence
< OUString
>& rBlackList
,
2260 vcl::Window
* _pPreferredParent
)
2263 mpImp
= new FileDialogHelper_Impl( this, nDialogType
, nFlags
, SFX2_IMPL_DIALOG_CONFIG
, _pPreferredParent
,rStandardDir
, rBlackList
);
2266 // the wildcard here is expected in form "*.extension"
2268 if ( aExtName
.indexOf( (sal_Unicode
)'*' ) != 0 )
2270 if ( !aExtName
.isEmpty() && aExtName
.indexOf( (sal_Unicode
)'.' ) != 0 )
2276 aWildcard
+= aExtName
;
2278 OUString
const aUIString
= ::sfx2::addExtension( aFilterUIName
,
2279 aWildcard
, (OPEN
== lcl_OpenOrSave(mpImp
->m_nDialogType
)), *mpImp
);
2280 AddFilter( aUIString
, aWildcard
);
2283 FileDialogHelper::~FileDialogHelper()
2289 void FileDialogHelper::CreateMatcher( const OUString
& rFactory
)
2291 mpImp
->createMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory
) );
2294 void FileDialogHelper::SetControlHelpIds( const sal_Int16
* _pControlId
, const char** _pHelpId
)
2296 mpImp
->setControlHelpIds( _pControlId
, _pHelpId
);
2299 void FileDialogHelper::SetContext( Context _eNewContext
)
2301 mpImp
->SetContext( _eNewContext
);
2304 IMPL_LINK_NOARG(FileDialogHelper
, ExecuteSystemFilePicker
)
2306 m_nError
= mpImp
->execute();
2307 if ( m_aDialogClosedLink
.IsSet() )
2308 m_aDialogClosedLink
.Call( this );
2313 // rDirPath has to be a directory
2314 ErrCode
FileDialogHelper::Execute( std::vector
<OUString
>& rpURLList
,
2315 SfxItemSet
*& rpSet
,
2317 const OUString
& rDirPath
)
2319 SetDisplayFolder( rDirPath
);
2320 return mpImp
->execute( rpURLList
, rpSet
, rFilter
);
2324 ErrCode
FileDialogHelper::Execute()
2326 return mpImp
->execute();
2329 ErrCode
FileDialogHelper::Execute( SfxItemSet
*& rpSet
,
2333 std::vector
<OUString
> rURLList
;
2334 nRet
= mpImp
->execute(rURLList
, rpSet
, rFilter
);
2338 void FileDialogHelper::StartExecuteModal( const Link
<>& rEndDialogHdl
)
2340 m_aDialogClosedLink
= rEndDialogHdl
;
2341 m_nError
= ERRCODE_NONE
;
2342 if ( mpImp
->isSystemFilePicker() )
2343 Application::PostUserEvent( LINK( this, FileDialogHelper
, ExecuteSystemFilePicker
) );
2345 mpImp
->implStartExecute();
2349 short FileDialogHelper::GetDialogType() const
2351 return mpImp
? mpImp
->m_nDialogType
: 0;
2354 bool FileDialogHelper::IsPasswordEnabled() const
2356 return mpImp
&& mpImp
->isPasswordEnabled();
2359 OUString
FileDialogHelper::GetRealFilter() const
2363 mpImp
->getRealFilter( sFilter
);
2367 void FileDialogHelper::SetTitle( const OUString
& rNewTitle
)
2369 if ( mpImp
->mxFileDlg
.is() )
2370 mpImp
->mxFileDlg
->setTitle( rNewTitle
);
2373 OUString
FileDialogHelper::GetPath() const
2377 if ( mpImp
->mlLastURLs
.size() > 0)
2378 return mpImp
->mlLastURLs
[0];
2380 if ( mpImp
->mxFileDlg
.is() )
2382 Sequence
< OUString
> aPathSeq
= mpImp
->mxFileDlg
->getFiles();
2384 if ( aPathSeq
.getLength() == 1 )
2386 aPath
= aPathSeq
[0];
2393 Sequence
< OUString
> FileDialogHelper::GetMPath() const
2395 if ( mpImp
->mlLastURLs
.size() > 0)
2396 return comphelper::containerToSequence(mpImp
->mlLastURLs
);
2398 if ( mpImp
->mxFileDlg
.is() )
2399 return mpImp
->mxFileDlg
->getFiles();
2402 Sequence
< OUString
> aEmpty
;
2407 Sequence
< OUString
> FileDialogHelper::GetSelectedFiles() const
2409 // a) the new way (optional!)
2410 uno::Sequence
< OUString
> aResultSeq
;
2411 uno::Reference
< XFilePicker2
> xPickNew(mpImp
->mxFileDlg
, UNO_QUERY
);
2414 aResultSeq
= xPickNew
->getSelectedFiles();
2416 // b) the olde way ... non optional.
2419 uno::Reference
< XFilePicker
> xPickOld(mpImp
->mxFileDlg
, UNO_QUERY_THROW
);
2420 Sequence
< OUString
> lFiles
= xPickOld
->getFiles();
2421 ::sal_Int32 nFiles
= lFiles
.getLength();
2424 aResultSeq
= Sequence
< OUString
>( nFiles
-1 );
2426 INetURLObject
aPath( lFiles
[0] );
2427 aPath
.setFinalSlash();
2429 for (::sal_Int32 i
= 1; i
< nFiles
; i
++)
2432 aPath
.Append( lFiles
[i
] );
2434 aPath
.setName( lFiles
[i
] );
2436 aResultSeq
[i
-1] = aPath
.GetMainURL( INetURLObject::NO_DECODE
);
2440 aResultSeq
= lFiles
;
2446 OUString
FileDialogHelper::GetDisplayDirectory() const
2448 return mpImp
->getPath();
2451 OUString
FileDialogHelper::GetCurrentFilter() const
2453 return mpImp
->getFilter();
2456 ErrCode
FileDialogHelper::GetGraphic( Graphic
& rGraphic
) const
2458 return mpImp
->getGraphic( rGraphic
);
2461 static int impl_isFolder( const OUString
& rPath
)
2465 ::ucbhelper::Content
aContent(
2466 rPath
, uno::Reference
< ucb::XCommandEnvironment
> (),
2467 comphelper::getProcessComponentContext() );
2468 if ( aContent
.isFolder() )
2473 catch ( const Exception
& )
2480 void FileDialogHelper::SetDisplayDirectory( const OUString
& _rPath
)
2482 if ( _rPath
.isEmpty() )
2485 // if the given path isn't a folder, we cut off the last part
2486 // and take it as filename and the rest of the path should be
2489 INetURLObject
aObj( _rPath
);
2491 OUString sFileName
= aObj
.GetName( INetURLObject::DECODE_WITH_CHARSET
);
2492 aObj
.removeSegment();
2493 OUString sPath
= aObj
.GetMainURL( INetURLObject::NO_DECODE
);
2495 int nIsFolder
= impl_isFolder( _rPath
);
2496 if ( nIsFolder
== 0 ||
2497 ( nIsFolder
== -1 && impl_isFolder( sPath
) == 1 ) )
2499 mpImp
->setFileName( sFileName
);
2500 mpImp
->displayFolder( sPath
);
2504 INetURLObject
aObjPathName( _rPath
);
2505 OUString
sFolder( aObjPathName
.GetMainURL( INetURLObject::NO_DECODE
) );
2506 if ( sFolder
.isEmpty() )
2508 // _rPath is not a valid path -> fallback to home directory
2509 osl::Security aSecurity
;
2510 aSecurity
.getHomeDir( sFolder
);
2512 mpImp
->displayFolder( sFolder
);
2516 void FileDialogHelper::SetDisplayFolder( const OUString
& _rURL
)
2518 mpImp
->displayFolder( _rURL
);
2521 void FileDialogHelper::SetFileName( const OUString
& _rFileName
)
2523 mpImp
->setFileName( _rFileName
);
2526 void FileDialogHelper::AddFilter( const OUString
& rFilterName
,
2527 const OUString
& rExtension
)
2529 mpImp
->addFilter( rFilterName
, rExtension
);
2532 void FileDialogHelper::SetCurrentFilter( const OUString
& rFilter
)
2534 OUString
sFilter( rFilter
);
2535 if ( mpImp
->isShowFilterExtensionEnabled() )
2536 sFilter
= mpImp
->getFilterWithExtension( rFilter
);
2537 mpImp
->setFilter( sFilter
);
2540 uno::Reference
< XFilePicker
> FileDialogHelper::GetFilePicker() const
2542 return mpImp
->mxFileDlg
;
2545 // XFilePickerListener Methods
2546 void SAL_CALL
FileDialogHelper::FileSelectionChanged( const FilePickerEvent
& aEvent
)
2548 mpImp
->handleFileSelectionChanged( aEvent
);
2551 void SAL_CALL
FileDialogHelper::DirectoryChanged( const FilePickerEvent
& aEvent
)
2553 mpImp
->handleDirectoryChanged( aEvent
);
2556 OUString SAL_CALL
FileDialogHelper::HelpRequested( const FilePickerEvent
& aEvent
)
2558 return sfx2::FileDialogHelper_Impl::handleHelpRequested( aEvent
);
2561 void SAL_CALL
FileDialogHelper::ControlStateChanged( const FilePickerEvent
& aEvent
)
2563 mpImp
->handleControlStateChanged( aEvent
);
2566 void SAL_CALL
FileDialogHelper::DialogSizeChanged()
2568 mpImp
->handleDialogSizeChanged();
2571 void SAL_CALL
FileDialogHelper::DialogClosed( const DialogClosedEvent
& _rEvent
)
2573 m_nError
= ( RET_OK
== _rEvent
.DialogResult
) ? ERRCODE_NONE
: ERRCODE_ABORT
;
2574 if ( m_aDialogClosedLink
.IsSet() )
2575 m_aDialogClosedLink
.Call( this );
2578 ErrCode
FileOpenDialog_Impl( sal_Int16 nDialogType
,
2580 const OUString
& rFact
,
2581 std::vector
<OUString
>& rpURLList
,
2583 SfxItemSet
*& rpSet
,
2584 const OUString
* pPath
,
2586 const OUString
& rStandardDir
,
2587 const ::com::sun::star::uno::Sequence
< OUString
>& rBlackList
)
2590 FileDialogHelper
aDialog( nDialogType
, nFlags
,
2591 rFact
, nDialog
, SfxFilterFlags::NONE
, SfxFilterFlags::NONE
, rStandardDir
, rBlackList
);
2597 nRet
= aDialog
.Execute( rpURLList
, rpSet
, rFilter
, aPath
);
2598 DBG_ASSERT( rFilter
.indexOf(": ") == -1, "Old filter name used!");
2603 ErrCode
RequestPassword(const SfxFilter
* pCurrentFilter
, OUString
& aURL
, SfxItemSet
* pSet
)
2605 uno::Reference
< task::XInteractionHandler2
> xInteractionHandler
= task::InteractionHandler::createWithParent( ::comphelper::getProcessComponentContext(), 0 );
2606 // TODO: need a save way to distinguish MS filters from other filters
2607 // for now MS-filters are the only alien filters that support encryption
2608 bool bMSType
= !pCurrentFilter
->IsOwnFormat();
2609 ::comphelper::DocPasswordRequestType eType
= bMSType
?
2610 ::comphelper::DocPasswordRequestType_MS
:
2611 ::comphelper::DocPasswordRequestType_STANDARD
;
2613 ::rtl::Reference
< ::comphelper::DocPasswordRequest
> pPasswordRequest( new ::comphelper::DocPasswordRequest( eType
, ::com::sun::star::task::PasswordRequestMode_PASSWORD_CREATE
, aURL
, bool( pCurrentFilter
->GetFilterFlags() & SfxFilterFlags::PASSWORDTOMODIFY
) ) );
2615 uno::Reference
< com::sun::star::task::XInteractionRequest
> rRequest( pPasswordRequest
.get() );
2616 xInteractionHandler
->handle( rRequest
);
2617 if ( pPasswordRequest
->isPassword() )
2619 if ( pPasswordRequest
->getPassword().getLength() )
2621 // TODO/LATER: The filters should show the password dialog themself in future
2624 // Check if filter supports OOXML encryption
2625 if ( lclSupportsOOXMLEncryption( pCurrentFilter
->GetFilterName() ) )
2627 ::comphelper::SequenceAsHashMap aHashData
;
2628 aHashData
[ OUString( "OOXPassword" ) ] <<= pPasswordRequest
->getPassword();
2629 pSet
->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aHashData
.getAsConstNamedValueList() ) ) );
2633 uno::Sequence
< sal_Int8
> aUniqueID
= ::comphelper::DocPasswordHelper::GenerateRandomByteSequence( 16 );
2634 uno::Sequence
< sal_Int8
> aEncryptionKey
= ::comphelper::DocPasswordHelper::GenerateStd97Key( pPasswordRequest
->getPassword(), aUniqueID
);
2636 if ( aEncryptionKey
.getLength() )
2638 ::comphelper::SequenceAsHashMap aHashData
;
2639 aHashData
[ OUString( "STD97EncryptionKey" ) ] <<= aEncryptionKey
;
2640 aHashData
[ OUString( "STD97UniqueID" ) ] <<= aUniqueID
;
2642 pSet
->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aHashData
.getAsConstNamedValueList() ) ) );
2646 return ERRCODE_IO_NOTSUPPORTED
;
2652 pSet
->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( ::comphelper::OStorageHelper::CreatePackageEncryptionData( pPasswordRequest
->getPassword() ) ) ) );
2656 if ( pPasswordRequest
->getRecommendReadOnly() )
2657 pSet
->Put( SfxBoolItem( SID_RECOMMENDREADONLY
, true ) );
2661 // the empty password has 0 as Hash
2662 sal_Int32 nHash
= SfxMedium::CreatePasswordToModifyHash( pPasswordRequest
->getPasswordToModify(), OUString( "com.sun.star.text.TextDocument" ).equals( pCurrentFilter
->GetServiceName() ) );
2664 pSet
->Put( SfxUnoAnyItem( SID_MODIFYPASSWORDINFO
, uno::makeAny( nHash
) ) );
2668 uno::Sequence
< beans::PropertyValue
> aModifyPasswordInfo
= ::comphelper::DocPasswordHelper::GenerateNewModifyPasswordInfo( pPasswordRequest
->getPasswordToModify() );
2669 if ( aModifyPasswordInfo
.getLength() )
2670 pSet
->Put( SfxUnoAnyItem( SID_MODIFYPASSWORDINFO
, uno::makeAny( aModifyPasswordInfo
) ) );
2674 return ERRCODE_ABORT
;
2675 return ERRCODE_NONE
;
2678 OUString
EncodeSpaces_Impl( const OUString
& rSource
)
2680 OUString
sRet( rSource
);
2681 sRet
= sRet
.replaceAll( " ", "%20" );
2685 OUString
DecodeSpaces_Impl( const OUString
& rSource
)
2687 OUString
sRet( rSource
);
2688 sRet
= sRet
.replaceAll( "%20", " " );
2692 } // end of namespace sfx2
2694 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */