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