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