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