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