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 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sfx2.hxx" 26 #include <sfx2/filedlghelper.hxx> 27 #include <sal/types.h> 28 #include <com/sun/star/lang/XInitialization.hpp> 29 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> 30 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> 31 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> 32 #include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp> 33 #include <com/sun/star/ui/dialogs/ControlActions.hpp> 34 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp> 35 #include <com/sun/star/ui/dialogs/XControlInformation.hpp> 36 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> 37 #include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> 38 #include <com/sun/star/ui/dialogs/XFilePreview.hpp> 39 #include <com/sun/star/ui/dialogs/XFilterManager.hpp> 40 #include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> 41 #include <com/sun/star/ui/dialogs/XFolderPicker.hpp> 42 #include <com/sun/star/ui/dialogs/XFilePicker2.hpp> 43 #include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp> 44 #include <com/sun/star/lang/XServiceInfo.hpp> 45 #include <com/sun/star/beans/XPropertySet.hpp> 46 #include <com/sun/star/beans/NamedValue.hpp> 47 #include <com/sun/star/embed/ElementModes.hpp> 48 #include <com/sun/star/container/XEnumeration.hpp> 49 #include <com/sun/star/container/XContainerQuery.hpp> 50 #include <com/sun/star/task/XInteractionRequest.hpp> 51 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> 52 53 #include <comphelper/processfactory.hxx> 54 #include <comphelper/types.hxx> 55 #include <comphelper/sequenceashashmap.hxx> 56 #include <comphelper/stillreadwriteinteraction.hxx> 57 #include <tools/urlobj.hxx> 58 #include <vcl/help.hxx> 59 #include <unotools/ucbstreamhelper.hxx> 60 #include <unotools/ucbhelper.hxx> 61 #include <unotools/localfilehelper.hxx> 62 #include <vos/thread.hxx> 63 #include <vos/mutex.hxx> 64 #include <vos/security.hxx> 65 #include <vcl/cvtgrf.hxx> 66 #include <vcl/msgbox.hxx> 67 #include <vcl/mnemonic.hxx> 68 #include <unotools/pathoptions.hxx> 69 #include <unotools/securityoptions.hxx> 70 #include <svl/itemset.hxx> 71 #include <svl/eitem.hxx> 72 #include <svl/intitem.hxx> 73 #include <svl/stritem.hxx> 74 #include <svtools/filter.hxx> 75 #include <unotools/viewoptions.hxx> 76 #include <unotools/moduleoptions.hxx> 77 #include <svtools/helpid.hrc> 78 #include <comphelper/docpasswordrequest.hxx> 79 #include <comphelper/docpasswordhelper.hxx> 80 #include <ucbhelper/content.hxx> 81 #include <ucbhelper/commandenvironment.hxx> 82 #include <comphelper/storagehelper.hxx> 83 #include <toolkit/helper/vclunohelper.hxx> 84 #include <sfx2/app.hxx> 85 #include <sfx2/frame.hxx> 86 #include <sfx2/docfile.hxx> 87 #include <sfx2/docfac.hxx> 88 #include "openflag.hxx" 89 #include <sfx2/passwd.hxx> 90 #include "sfx2/sfxresid.hxx" 91 #include <sfx2/sfxsids.hrc> 92 #include "filedlghelper.hrc" 93 #include "filtergrouping.hxx" 94 #include <sfx2/request.hxx> 95 #include "filedlgimpl.hxx" 96 #include <helpid.hrc> 97 #include <sfxlocal.hrc> 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 753 // scale the bitmap to the correct size 754 sal_Int32 nOutWidth = xFilePicker->getAvailableWidth(); 755 sal_Int32 nOutHeight = xFilePicker->getAvailableHeight(); 756 sal_Int32 nBmpWidth = aBmp.GetSizePixel().Width(); 757 sal_Int32 nBmpHeight = aBmp.GetSizePixel().Height(); 758 759 double nXRatio = (double) nOutWidth / nBmpWidth; 760 double nYRatio = (double) nOutHeight / nBmpHeight; 761 762 if ( nXRatio < nYRatio ) 763 aBmp.Scale( nXRatio, nXRatio ); 764 else 765 aBmp.Scale( nYRatio, nYRatio ); 766 767 // #94505# Convert to true color, to allow CopyPixel 768 aBmp.Convert( BMP_CONVERSION_24BIT ); 769 770 // and copy it into the Any 771 SvMemoryStream aData; 772 773 aData << aBmp; 774 775 const Sequence < sal_Int8 > aBuffer( 776 static_cast< const sal_Int8* >(aData.GetData()), 777 aData.GetEndOfData() ); 778 779 aAny <<= aBuffer; 780 } 781 } 782 783 try 784 { 785 OReleaseSolarMutex aReleaseForCallback; 786 // clear the preview window 787 xFilePicker->setImage( FilePreviewImageFormats::BITMAP, aAny ); 788 } 789 catch( IllegalArgumentException ) 790 { 791 } 792 793 return 0; 794 } 795 796 // ------------------------------------------------------------------------ 797 ErrCode FileDialogHelper_Impl::getGraphic( const OUString& rURL, 798 Graphic& rGraphic ) const 799 { 800 if ( utl::UCBContentHelper::IsFolder( rURL ) ) 801 return ERRCODE_IO_NOTAFILE; 802 803 if ( !mpGraphicFilter ) 804 return ERRCODE_IO_NOTSUPPORTED; 805 806 // select graphic filter from dialog filter selection 807 OUString aCurFilter( getFilter() ); 808 809 sal_uInt16 nFilter = aCurFilter.getLength() && mpGraphicFilter->GetImportFormatCount() 810 ? mpGraphicFilter->GetImportFormatNumber( aCurFilter ) 811 : GRFILTER_FORMAT_DONTKNOW; 812 813 INetURLObject aURLObj( rURL ); 814 815 if ( aURLObj.HasError() || INET_PROT_NOT_VALID == aURLObj.GetProtocol() ) 816 { 817 aURLObj.SetSmartProtocol( INET_PROT_FILE ); 818 aURLObj.SetSmartURL( rURL ); 819 } 820 821 ErrCode nRet = ERRCODE_NONE; 822 823 sal_uInt32 nFilterImportFlags = GRFILTER_I_FLAGS_SET_LOGSIZE_FOR_JPEG; 824 // non-local? 825 if ( INET_PROT_FILE != aURLObj.GetProtocol() ) 826 { 827 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( rURL, STREAM_READ ); 828 829 if( pStream ) 830 nRet = mpGraphicFilter->ImportGraphic( rGraphic, rURL, *pStream, nFilter, NULL, nFilterImportFlags ); 831 else 832 nRet = mpGraphicFilter->ImportGraphic( rGraphic, aURLObj, nFilter, NULL, nFilterImportFlags ); 833 delete pStream; 834 } 835 else 836 { 837 nRet = mpGraphicFilter->ImportGraphic( rGraphic, aURLObj, nFilter, NULL, nFilterImportFlags ); 838 } 839 840 return nRet; 841 } 842 843 // ------------------------------------------------------------------------ 844 ErrCode FileDialogHelper_Impl::getGraphic( Graphic& rGraphic ) const 845 { 846 ErrCode nRet = ERRCODE_NONE; 847 848 if ( ! maGraphic ) 849 { 850 OUString aPath;; 851 Sequence < OUString > aPathSeq = mxFileDlg->getFiles(); 852 853 if ( aPathSeq.getLength() == 1 ) 854 { 855 aPath = aPathSeq[0]; 856 } 857 858 if ( aPath.getLength() ) 859 nRet = getGraphic( aPath, rGraphic ); 860 else 861 nRet = ERRCODE_IO_GENERAL; 862 } 863 else 864 rGraphic = maGraphic; 865 866 return nRet; 867 } 868 869 // ------------------------------------------------------------------------ 870 sal_Bool lcl_isSystemFilePicker( const uno::Reference< XFilePicker >& _rxFP ) 871 { 872 try 873 { 874 uno::Reference< XServiceInfo > xSI( _rxFP, UNO_QUERY ); 875 if ( xSI.is() && xSI->supportsService( DEFINE_CONST_OUSTRING( "com.sun.star.ui.dialogs.SystemFilePicker" ) ) ) 876 return sal_True; 877 } 878 catch( const Exception& ) 879 { 880 } 881 return sal_False; 882 } 883 884 885 // ------------------------------------------------------------------------ 886 // ----------- FileDialogHelper_Impl --------------------------- 887 // ------------------------------------------------------------------------ 888 889 FileDialogHelper_Impl::FileDialogHelper_Impl( 890 FileDialogHelper* _pAntiImpl, 891 sal_Int16 nDialogType, 892 sal_Int64 nFlags, 893 sal_Int16 nDialog, 894 Window* _pPreferredParentWindow, 895 const String& sStandardDir, 896 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList 897 ) 898 :m_nDialogType ( nDialogType ) 899 ,meContext ( FileDialogHelper::UNKNOWN_CONTEXT ) 900 { 901 const char* pServiceName=0; 902 if ( nDialog == SFX2_IMPL_DIALOG_SYSTEM ) 903 pServiceName = FILE_OPEN_SERVICE_NAME_OOO; 904 else if ( nDialog == SFX2_IMPL_DIALOG_OOO ) 905 pServiceName = FILE_OPEN_SERVICE_NAME_OOO; 906 else 907 pServiceName = FILE_OPEN_SERVICE_NAME; 908 OUString aService = ::rtl::OUString::createFromAscii( pServiceName ); 909 910 uno::Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); 911 912 // create the file open dialog 913 // the flags can be SFXWB_INSERT or SFXWB_MULTISELECTION 914 915 mpPreferredParentWindow = _pPreferredParentWindow; 916 mpAntiImpl = _pAntiImpl; 917 mnError = ERRCODE_NONE; 918 mbHasAutoExt = sal_False; 919 mbHasPassword = sal_False; 920 m_bHaveFilterOptions = sal_False; 921 mbIsPwdEnabled = sal_True; 922 mbHasVersions = sal_False; 923 mbHasPreview = sal_False; 924 mbShowPreview = sal_False; 925 mbHasLink = sal_False; 926 mbDeleteMatcher = sal_False; 927 mbInsert = SFXWB_INSERT == ( nFlags & SFXWB_INSERT ); 928 mbExport = SFXWB_EXPORT == ( nFlags & SFXWB_EXPORT ); 929 mbIsSaveDlg = sal_False; 930 mbPwdCheckBoxState = sal_False; 931 mbSelection = sal_False; 932 mbSelectionEnabled = sal_True; 933 mbHasSelectionBox = sal_False; 934 mbSelectionFltrEnabled = sal_False; 935 936 // default settings 937 m_nDontFlags = SFX_FILTER_INTERNAL | SFX_FILTER_NOTINFILEDLG | SFX_FILTER_NOTINSTALLED; 938 if( WB_OPEN == ( nFlags & WB_OPEN ) ) 939 m_nMustFlags = SFX_FILTER_IMPORT; 940 else 941 m_nMustFlags = SFX_FILTER_EXPORT; 942 943 944 mpMatcher = NULL; 945 mpGraphicFilter = NULL; 946 mnPostUserEventId = 0; 947 948 // create the picker component 949 mxFileDlg = mxFileDlg.query( xFactory->createInstance( aService ) ); 950 mbSystemPicker = lcl_isSystemFilePicker( mxFileDlg ); 951 952 uno::Reference< XFilePickerNotifier > xNotifier( mxFileDlg, UNO_QUERY ); 953 uno::Reference< XInitialization > xInit( mxFileDlg, UNO_QUERY ); 954 955 if ( ! mxFileDlg.is() || ! xNotifier.is() ) 956 { 957 mnError = ERRCODE_ABORT; 958 return; 959 } 960 961 962 if ( xInit.is() ) 963 { 964 sal_Int16 nTemplateDescription = TemplateDescription::FILEOPEN_SIMPLE; 965 966 switch ( m_nDialogType ) 967 { 968 case FILEOPEN_SIMPLE: 969 nTemplateDescription = TemplateDescription::FILEOPEN_SIMPLE; 970 break; 971 972 case FILESAVE_SIMPLE: 973 nTemplateDescription = TemplateDescription::FILESAVE_SIMPLE; 974 mbIsSaveDlg = sal_True; 975 break; 976 977 case FILESAVE_AUTOEXTENSION_PASSWORD: 978 nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD; 979 mbHasPassword = sal_True; 980 mbHasAutoExt = sal_True; 981 mbIsSaveDlg = sal_True; 982 break; 983 984 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: 985 nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS; 986 mbHasPassword = sal_True; 987 988 m_bHaveFilterOptions = sal_True; 989 if( xFactory.is() ) 990 { 991 mxFilterCFG = uno::Reference< XNameAccess >( 992 xFactory->createInstance( DEFINE_CONST_OUSTRING( "com.sun.star.document.FilterFactory" ) ), 993 UNO_QUERY ); 994 } 995 996 mbHasAutoExt = sal_True; 997 mbIsSaveDlg = sal_True; 998 break; 999 1000 case FILESAVE_AUTOEXTENSION_SELECTION: 1001 nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION; 1002 mbHasAutoExt = sal_True; 1003 mbIsSaveDlg = sal_True; 1004 mbHasSelectionBox = sal_True; 1005 if ( mbExport && !mxFilterCFG.is() && xFactory.is() ) 1006 { 1007 mxFilterCFG = uno::Reference< XNameAccess >( 1008 xFactory->createInstance( DEFINE_CONST_OUSTRING( "com.sun.star.document.FilterFactory" ) ), 1009 UNO_QUERY ); 1010 } 1011 break; 1012 1013 case FILESAVE_AUTOEXTENSION_TEMPLATE: 1014 nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE; 1015 mbHasAutoExt = sal_True; 1016 mbIsSaveDlg = sal_True; 1017 break; 1018 1019 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: 1020 nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE; 1021 mbHasPreview = sal_True; 1022 mbHasLink = sal_True; 1023 1024 // aPreviewTimer 1025 maPreViewTimer.SetTimeout( 500 ); 1026 maPreViewTimer.SetTimeoutHdl( LINK( this, FileDialogHelper_Impl, TimeOutHdl_Impl ) ); 1027 break; 1028 1029 case FILEOPEN_PLAY: 1030 nTemplateDescription = TemplateDescription::FILEOPEN_PLAY; 1031 break; 1032 1033 case FILEOPEN_READONLY_VERSION: 1034 nTemplateDescription = TemplateDescription::FILEOPEN_READONLY_VERSION; 1035 mbHasVersions = sal_True; 1036 break; 1037 1038 case FILEOPEN_LINK_PREVIEW: 1039 nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PREVIEW; 1040 mbHasPreview = sal_True; 1041 mbHasLink = sal_True; 1042 // aPreviewTimer 1043 maPreViewTimer.SetTimeout( 500 ); 1044 maPreViewTimer.SetTimeoutHdl( LINK( this, FileDialogHelper_Impl, TimeOutHdl_Impl ) ); 1045 break; 1046 1047 case FILESAVE_AUTOEXTENSION: 1048 nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION; 1049 mbHasAutoExt = sal_True; 1050 mbIsSaveDlg = sal_True; 1051 break; 1052 1053 default: 1054 DBG_ERRORFILE( "FileDialogHelper::ctor with unknown type" ); 1055 break; 1056 } 1057 1058 1059 1060 //Sequence < Any > aInitArguments( mbSystemPicker || !mpPreferredParentWindow ? 1 : 3 ); 1061 Sequence < Any > aInitArguments( !mpPreferredParentWindow ? 3 : 4 ); 1062 1063 // This is a hack. We currently know that the internal file picker implementation 1064 // supports the extended arguments as specified below. 1065 // TODO: 1066 // a) adjust the service description so that it includes the TemplateDescription and ParentWindow args 1067 // b) adjust the implementation of the system file picker to that it recognizes it 1068 if ( mbSystemPicker ) 1069 { 1070 aInitArguments[0] <<= nTemplateDescription; 1071 } 1072 else 1073 { 1074 aInitArguments[0] <<= NamedValue( 1075 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TemplateDescription" ) ), 1076 makeAny( nTemplateDescription ) 1077 ); 1078 1079 ::rtl::OUString sStandardDirTemp = ::rtl::OUString( sStandardDir ); 1080 1081 aInitArguments[1] <<= NamedValue( 1082 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StandardDir" ) ), 1083 makeAny( sStandardDirTemp ) 1084 ); 1085 1086 aInitArguments[2] <<= NamedValue( 1087 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BlackList" ) ), 1088 makeAny( rBlackList ) 1089 ); 1090 1091 1092 if ( mpPreferredParentWindow ) 1093 aInitArguments[3] <<= NamedValue( 1094 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" ) ), 1095 makeAny( VCLUnoHelper::GetInterface( mpPreferredParentWindow ) ) 1096 ); 1097 1098 1099 } 1100 1101 try 1102 { 1103 xInit->initialize( aInitArguments ); 1104 } 1105 catch( const Exception& ) 1106 { 1107 DBG_ERROR( "FileDialogHelper_Impl::FileDialogHelper_Impl: could not initialize the picker!" ); 1108 } 1109 } 1110 1111 1112 // set multiselection mode 1113 if ( nFlags & SFXWB_MULTISELECTION ) 1114 mxFileDlg->setMultiSelectionMode( sal_True ); 1115 1116 if ( mbHasLink ) // generate graphic filter only on demand 1117 addGraphicFilter(); 1118 1119 // Export dialog 1120 if ( mbExport ) 1121 { 1122 mxFileDlg->setTitle( OUString( String( SfxResId( STR_SFX_EXPLORERFILE_EXPORT ) ) ) ); 1123 try { 1124 com::sun::star::uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY_THROW ); 1125 xCtrlAccess->enableControl( ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR, sal_True ); 1126 } 1127 catch( const Exception & ) { } 1128 } 1129 1130 // the "insert file" dialog needs another title 1131 if ( mbInsert ) 1132 { 1133 mxFileDlg->setTitle( OUString( String( SfxResId( STR_SFX_EXPLORERFILE_INSERT ) ) ) ); 1134 uno::Reference < XFilePickerControlAccess > xExtDlg( mxFileDlg, UNO_QUERY ); 1135 if ( xExtDlg.is() ) 1136 { 1137 try 1138 { 1139 xExtDlg->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK, 1140 OUString( String( SfxResId( STR_SFX_EXPLORERFILE_BUTTONINSERT ) ) ) ); 1141 } 1142 catch( IllegalArgumentException ){} 1143 } 1144 } 1145 1146 // add the event listener 1147 xNotifier->addFilePickerListener( this ); 1148 } 1149 1150 // ------------------------------------------------------------------------ 1151 FileDialogHelper_Impl::~FileDialogHelper_Impl() 1152 { 1153 // Remove user event if we haven't received it yet 1154 if ( mnPostUserEventId ) 1155 Application::RemoveUserEvent( mnPostUserEventId ); 1156 mnPostUserEventId = 0; 1157 1158 delete mpGraphicFilter; 1159 1160 if ( mbDeleteMatcher ) 1161 delete mpMatcher; 1162 1163 maPreViewTimer.SetTimeoutHdl( Link() ); 1164 1165 ::comphelper::disposeComponent( mxFileDlg ); 1166 } 1167 1168 #define nMagic -1 1169 1170 class PickerThread_Impl : public ::vos::OThread 1171 { 1172 uno::Reference < XFilePicker > mxPicker; 1173 ::vos::OMutex maMutex; 1174 virtual void SAL_CALL run(); 1175 sal_Int16 mnRet; 1176 public: 1177 PickerThread_Impl( const uno::Reference < XFilePicker >& rPicker ) 1178 : mxPicker( rPicker ), mnRet(nMagic) {} 1179 1180 sal_Int16 GetReturnValue() 1181 { ::vos::OGuard aGuard( maMutex ); return mnRet; } 1182 1183 void SetReturnValue( sal_Int16 aRetValue ) 1184 { ::vos::OGuard aGuard( maMutex ); mnRet = aRetValue; } 1185 }; 1186 1187 void SAL_CALL PickerThread_Impl::run() 1188 { 1189 try 1190 { 1191 sal_Int16 n = mxPicker->execute(); 1192 SetReturnValue( n ); 1193 } 1194 catch( RuntimeException& ) 1195 { 1196 SetReturnValue( ExecutableDialogResults::CANCEL ); 1197 DBG_ERRORFILE( "RuntimeException caught" ); 1198 } 1199 } 1200 1201 // ------------------------------------------------------------------------ 1202 void FileDialogHelper_Impl::setControlHelpIds( const sal_Int16* _pControlId, const char** _pHelpId ) 1203 { 1204 DBG_ASSERT( _pControlId && _pHelpId, "FileDialogHelper_Impl::setControlHelpIds: invalid array pointers!" ); 1205 if ( !_pControlId || !_pHelpId ) 1206 return; 1207 1208 // forward these ids to the file picker 1209 try 1210 { 1211 const ::rtl::OUString sHelpIdPrefix( RTL_CONSTASCII_USTRINGPARAM( INET_HID_SCHEME ) ); 1212 // the ids for the single controls 1213 uno::Reference< XFilePickerControlAccess > xControlAccess( mxFileDlg, UNO_QUERY ); 1214 if ( xControlAccess.is() ) 1215 { 1216 while ( *_pControlId ) 1217 { 1218 DBG_ASSERT( INetURLObject( rtl::OStringToOUString( *_pHelpId, RTL_TEXTENCODING_UTF8 ) ).GetProtocol() == INET_PROT_NOT_VALID, "Wrong HelpId!" ); 1219 ::rtl::OUString sId( sHelpIdPrefix ); 1220 sId += ::rtl::OUString( *_pHelpId, strlen( *_pHelpId ), RTL_TEXTENCODING_UTF8 ); 1221 xControlAccess->setValue( *_pControlId, ControlActions::SET_HELP_URL, makeAny( sId ) ); 1222 1223 ++_pControlId; ++_pHelpId; 1224 } 1225 } 1226 } 1227 catch( const Exception& ) 1228 { 1229 DBG_ERROR( "FileDialogHelper_Impl::setControlHelpIds: caught an exception while setting the help ids!" ); 1230 } 1231 } 1232 1233 // ------------------------------------------------------------------------ 1234 IMPL_LINK( FileDialogHelper_Impl, InitControls, void*, NOTINTERESTEDIN ) 1235 { 1236 (void)NOTINTERESTEDIN; 1237 mnPostUserEventId = 0; 1238 enablePasswordBox( sal_True ); 1239 updateFilterOptionsBox( ); 1240 updateSelectionBox( ); 1241 1242 return 0L; 1243 } 1244 1245 // ------------------------------------------------------------------------ 1246 void FileDialogHelper_Impl::preExecute() 1247 { 1248 loadConfig( ); 1249 setDefaultValues( ); 1250 updatePreviewState( sal_False ); 1251 1252 implInitializeFileName( ); 1253 // #106079# / 2002-12-09 / fs@openoffice.org 1254 1255 #if !(defined(MACOSX) && defined(QUARTZ)) && !defined(WNT) 1256 // allow for dialog implementations which need to be executed before they return valid values for 1257 // current filter and such 1258 1259 // On Vista (at least SP1) it's the same as on MacOSX, the modal dialog won't let message pass 1260 // through before it returns from execution 1261 mnPostUserEventId = Application::PostUserEvent( LINK( this, FileDialogHelper_Impl, InitControls ) ); 1262 #else 1263 // However, the Mac OS X implementation's pickers run modally in execute and so the event doesn't 1264 // get through in time... so we call the methods directly 1265 enablePasswordBox( sal_True ); 1266 updateFilterOptionsBox( ); 1267 updateSelectionBox( ); 1268 #endif 1269 } 1270 1271 // ------------------------------------------------------------------------ 1272 void FileDialogHelper_Impl::postExecute( sal_Int16 _nResult ) 1273 { 1274 if ( ExecutableDialogResults::CANCEL != _nResult ) 1275 saveConfig(); 1276 } 1277 1278 // ------------------------------------------------------------------------ 1279 void FileDialogHelper_Impl::implInitializeFileName( ) 1280 { 1281 if ( maFileName.getLength() ) 1282 { 1283 INetURLObject aObj( maPath ); 1284 aObj.Append( maFileName ); 1285 1286 // in case we're operating as save dialog, and "auto extension" is checked, 1287 // cut the extension from the name 1288 // #106079# / 2002-12-09 / fs@openoffice.org 1289 if ( mbIsSaveDlg && mbHasAutoExt ) 1290 { 1291 try 1292 { 1293 sal_Bool bAutoExtChecked = sal_False; 1294 1295 uno::Reference < XFilePickerControlAccess > xControlAccess( mxFileDlg, UNO_QUERY ); 1296 if ( xControlAccess.is() 1297 && ( xControlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0 ) 1298 >>= bAutoExtChecked 1299 ) 1300 ) 1301 { 1302 if ( bAutoExtChecked ) 1303 { // cut the extension 1304 aObj.removeExtension( ); 1305 mxFileDlg->setDefaultName( aObj.GetName( INetURLObject::DECODE_WITH_CHARSET ) ); 1306 } 1307 } 1308 } 1309 catch( const Exception& ) 1310 { 1311 DBG_ERROR( "FileDialogHelper_Impl::implInitializeFileName: could not ask for the auto-extension current-value!" ); 1312 } 1313 } 1314 } 1315 } 1316 1317 // ------------------------------------------------------------------------ 1318 sal_Int16 FileDialogHelper_Impl::implDoExecute() 1319 { 1320 preExecute(); 1321 1322 sal_Int16 nRet = ExecutableDialogResults::CANCEL; 1323 1324 //On MacOSX the native file picker has to run in the primordial thread because of drawing issues 1325 //On Linux the native gtk file picker, when backed by gnome-vfs2, needs to be run in the same 1326 //primordial thread as the ucb gnome-vfs2 provider was initialized in. 1327 /* 1328 #ifdef WNT 1329 if ( mbSystemPicker ) 1330 { 1331 PickerThread_Impl* pThread = new PickerThread_Impl( mxFileDlg ); 1332 pThread->create(); 1333 while ( pThread->GetReturnValue() == nMagic ) 1334 Application::Yield(); 1335 pThread->join(); 1336 nRet = pThread->GetReturnValue(); 1337 delete pThread; 1338 } 1339 else 1340 #endif 1341 */ 1342 { 1343 try 1344 { 1345 #ifdef WNT 1346 if ( mbSystemPicker ) 1347 { 1348 OReleaseSolarMutex aSolarMutex; 1349 nRet = mxFileDlg->execute(); 1350 } 1351 else 1352 #endif 1353 nRet = mxFileDlg->execute(); 1354 } 1355 catch( const Exception& ) 1356 { 1357 DBG_ERRORFILE( "FileDialogHelper_Impl::implDoExecute: caught an exception!" ); 1358 } 1359 } 1360 1361 postExecute( nRet ); 1362 1363 return nRet; 1364 } 1365 1366 // ------------------------------------------------------------------------ 1367 void FileDialogHelper_Impl::implStartExecute() 1368 { 1369 DBG_ASSERT( mxFileDlg.is(), "invalid file dialog" ); 1370 1371 preExecute(); 1372 1373 if ( mbSystemPicker ) 1374 { 1375 } 1376 else 1377 { 1378 try 1379 { 1380 uno::Reference< XAsynchronousExecutableDialog > xAsyncDlg( mxFileDlg, UNO_QUERY ); 1381 if ( xAsyncDlg.is() ) 1382 xAsyncDlg->startExecuteModal( this ); 1383 } 1384 catch( const Exception& ) 1385 { 1386 DBG_ERRORFILE( "FileDialogHelper_Impl::implDoExecute: caught an exception!" ); 1387 } 1388 } 1389 } 1390 1391 // ------------------------------------------------------------------------ 1392 String FileDialogHelper_Impl::implEnsureURLExtension(const String& sURL, 1393 const String& /*sExtension*/) 1394 { 1395 return sURL; 1396 /* 1397 // This feature must be active for file save/export only ! 1398 if ( 1399 (! mbIsSaveDlg) && 1400 (! mbExport ) 1401 ) 1402 return sURL; 1403 1404 // no extension available (because "ALL *.*" was selected) ? 1405 // Nod idea what else should happen here .-) 1406 if (sExtension.Len() < 1) 1407 return sURL; 1408 1409 // Some FilePicker implementations already add the right extension ... 1410 // or might be the user used the right one already ... 1411 // Dont create duplicate extension. 1412 INetURLObject aURL(sURL); 1413 if (aURL.getExtension().equals(sExtension)) 1414 return sURL; 1415 1416 // Ignore any other extension set by the user. 1417 // Make sure suitable extension is used always. 1418 // e.g. "test.bla.odt" for "ODT" 1419 ::rtl::OUStringBuffer sNewURL(256); 1420 sNewURL.append (sURL ); 1421 sNewURL.appendAscii("." ); 1422 sNewURL.append (sExtension); 1423 return sNewURL.makeStringAndClear(); 1424 */ 1425 } 1426 1427 // ------------------------------------------------------------------------ 1428 void lcl_saveLastURLs(SvStringsDtor*& rpURLList , 1429 ::comphelper::SequenceAsVector< ::rtl::OUString >& lLastURLs ) 1430 { 1431 lLastURLs.clear(); 1432 sal_uInt16 c = rpURLList->Count(); 1433 sal_uInt16 i = 0; 1434 for (i=0; i<c; ++i) 1435 lLastURLs.push_back(*(rpURLList->GetObject(i))); 1436 } 1437 1438 // ------------------------------------------------------------------------ 1439 void FileDialogHelper_Impl::implGetAndCacheFiles(const uno::Reference< XInterface >& xPicker , 1440 SvStringsDtor*& rpURLList, 1441 const SfxFilter* pFilter ) 1442 { 1443 rpURLList = NULL; 1444 1445 String sExtension; 1446 if (pFilter) 1447 { 1448 sExtension = pFilter->GetDefaultExtension (); 1449 sExtension.EraseAllChars( '*' ); 1450 sExtension.EraseAllChars( '.' ); 1451 } 1452 1453 // a) the new way (optional!) 1454 uno::Reference< XFilePicker2 > xPickNew(xPicker, UNO_QUERY); 1455 if (xPickNew.is()) 1456 { 1457 rpURLList = new SvStringsDtor; 1458 Sequence< OUString > lFiles = xPickNew->getSelectedFiles(); 1459 ::sal_Int32 nFiles = lFiles.getLength(); 1460 for (::sal_Int32 i = 0; i < nFiles; i++) 1461 { 1462 String* pURL = new String(implEnsureURLExtension(lFiles[i], sExtension)); 1463 rpURLList->Insert( pURL, rpURLList->Count() ); 1464 } 1465 } 1466 1467 // b) the olde way ... non optional. 1468 else 1469 { 1470 uno::Reference< XFilePicker > xPickOld(xPicker, UNO_QUERY_THROW); 1471 Sequence< OUString > lFiles = xPickOld->getFiles(); 1472 ::sal_Int32 nFiles = lFiles.getLength(); 1473 if ( nFiles == 1 ) 1474 { 1475 rpURLList = new SvStringsDtor; 1476 String* pURL = new String(implEnsureURLExtension(lFiles[0], sExtension)); 1477 rpURLList->Insert( pURL, 0 ); 1478 } 1479 else 1480 if ( nFiles > 1 ) 1481 { 1482 rpURLList = new SvStringsDtor; 1483 1484 INetURLObject aPath( lFiles[0] ); 1485 aPath.setFinalSlash(); 1486 1487 for (::sal_Int32 i = 1; i < nFiles; i++) 1488 { 1489 if (i == 1) 1490 aPath.Append( lFiles[i] ); 1491 else 1492 aPath.setName( lFiles[i] ); 1493 1494 String* pURL = new String(implEnsureURLExtension(aPath.GetMainURL( INetURLObject::NO_DECODE ), sExtension) ); 1495 rpURLList->Insert( pURL, rpURLList->Count() ); 1496 } 1497 } 1498 } 1499 1500 lcl_saveLastURLs(rpURLList, mlLastURLs); 1501 } 1502 1503 // ------------------------------------------------------------------------ 1504 ErrCode FileDialogHelper_Impl::execute( SvStringsDtor*& rpURLList, 1505 SfxItemSet *& rpSet, 1506 String& rFilter ) 1507 { 1508 // rFilter is a pure output parameter, it shouldn't be used for anything else 1509 // changing this would surely break code 1510 // rpSet is in/out parameter, usually just a media-descriptor that can be changed by dialog 1511 1512 uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY ); 1513 1514 // retrieves parameters from rpSet 1515 // for now only Password is used 1516 if ( rpSet ) 1517 { 1518 // check password checkbox if the document had password before 1519 if( mbHasPassword ) 1520 { 1521 SFX_ITEMSET_ARG( rpSet, pPassItem, SfxBoolItem, SID_PASSWORDINTERACTION, sal_False ); 1522 mbPwdCheckBoxState = ( pPassItem != NULL && pPassItem->GetValue() ); 1523 1524 // in case the document has password to modify, the dialog should be shown 1525 SFX_ITEMSET_ARG( rpSet, pPassToModifyItem, SfxUnoAnyItem, SID_MODIFYPASSWORDINFO, sal_False ); 1526 mbPwdCheckBoxState |= ( pPassToModifyItem && pPassToModifyItem->GetValue().hasValue() ); 1527 } 1528 1529 SFX_ITEMSET_ARG( rpSet, pSelectItem, SfxBoolItem, SID_SELECTION, sal_False ); 1530 if ( pSelectItem ) 1531 mbSelection = pSelectItem->GetValue(); 1532 else 1533 mbSelectionEnabled = sal_False; 1534 1535 // the password will be set in case user decide so 1536 rpSet->ClearItem( SID_PASSWORDINTERACTION ); 1537 rpSet->ClearItem( SID_PASSWORD ); 1538 rpSet->ClearItem( SID_ENCRYPTIONDATA ); 1539 rpSet->ClearItem( SID_RECOMMENDREADONLY ); 1540 rpSet->ClearItem( SID_MODIFYPASSWORDINFO ); 1541 1542 } 1543 1544 if ( mbHasPassword && !mbPwdCheckBoxState ) 1545 { 1546 SvtSecurityOptions aSecOpt; 1547 mbPwdCheckBoxState = ( 1548 aSecOpt.IsOptionSet( SvtSecurityOptions::E_DOCWARN_RECOMMENDPASSWORD ) ); 1549 } 1550 1551 rpURLList = NULL; 1552 1553 if ( ! mxFileDlg.is() ) 1554 return ERRCODE_ABORT; 1555 1556 if ( ExecutableDialogResults::CANCEL != implDoExecute() ) 1557 { 1558 // create an itemset if there is no 1559 if( !rpSet ) 1560 rpSet = new SfxAllItemSet( SFX_APP()->GetPool() ); 1561 1562 // the item should remain only if it was set by the dialog 1563 rpSet->ClearItem( SID_SELECTION ); 1564 1565 if( mbExport && mbHasSelectionBox ) 1566 { 1567 try 1568 { 1569 Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0 ); 1570 sal_Bool bSelection = sal_False; 1571 if ( aValue >>= bSelection ) 1572 rpSet->Put( SfxBoolItem( SID_SELECTION, bSelection ) ); 1573 } 1574 catch( IllegalArgumentException ) 1575 { 1576 DBG_ERROR( "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" ); 1577 } 1578 } 1579 1580 1581 // set the read-only flag. When inserting a file, this flag is always set 1582 if ( mbInsert ) 1583 rpSet->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) ); 1584 else 1585 { 1586 if ( ( FILEOPEN_READONLY_VERSION == m_nDialogType ) && xCtrlAccess.is() ) 1587 { 1588 try 1589 { 1590 Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 ); 1591 sal_Bool bReadOnly = sal_False; 1592 if ( ( aValue >>= bReadOnly ) && bReadOnly ) 1593 rpSet->Put( SfxBoolItem( SID_DOC_READONLY, bReadOnly ) ); 1594 } 1595 catch( IllegalArgumentException ) 1596 { 1597 DBG_ERROR( "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" ); 1598 } 1599 } 1600 } 1601 if ( mbHasVersions && xCtrlAccess.is() ) 1602 { 1603 try 1604 { 1605 Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION, 1606 ControlActions::GET_SELECTED_ITEM_INDEX ); 1607 sal_Int32 nVersion = 0; 1608 if ( ( aValue >>= nVersion ) && nVersion > 0 ) 1609 // open a special version; 0 == current version 1610 rpSet->Put( SfxInt16Item( SID_VERSION, (short)nVersion ) ); 1611 } 1612 catch( IllegalArgumentException ){} 1613 } 1614 1615 // set the filter 1616 getRealFilter( rFilter ); 1617 1618 const SfxFilter* pCurrentFilter = getCurentSfxFilter(); 1619 1620 // fill the rpURLList 1621 implGetAndCacheFiles( mxFileDlg, rpURLList, pCurrentFilter ); 1622 if ( rpURLList == NULL || rpURLList->GetObject(0) == NULL ) 1623 return ERRCODE_ABORT; 1624 1625 // check, wether or not we have to display a password box 1626 if ( pCurrentFilter && mbHasPassword && mbIsPwdEnabled && xCtrlAccess.is() ) 1627 { 1628 try 1629 { 1630 Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0 ); 1631 sal_Bool bPassWord = sal_False; 1632 if ( ( aValue >>= bPassWord ) && bPassWord ) 1633 { 1634 // ask for a password 1635 uno::Reference < ::com::sun::star::task::XInteractionHandler > xInteractionHandler( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.comp.uui.UUIInteractionHandler")), UNO_QUERY ); 1636 1637 if( xInteractionHandler.is() ) 1638 { 1639 // TODO: need a save way to distinguish MS filters from other filters 1640 // for now MS-filters are the only alien filters that support encryption 1641 sal_Bool bMSType = !pCurrentFilter->IsOwnFormat(); 1642 ::comphelper::DocPasswordRequestType eType = bMSType ? 1643 ::comphelper::DocPasswordRequestType_MS : 1644 ::comphelper::DocPasswordRequestType_STANDARD; 1645 1646 ::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 ) ); 1647 1648 uno::Reference< com::sun::star::task::XInteractionRequest > rRequest( pPasswordRequest.get() ); 1649 xInteractionHandler->handle( rRequest ); 1650 if ( pPasswordRequest->isPassword() ) 1651 { 1652 if ( pPasswordRequest->getPassword().getLength() ) 1653 { 1654 // TODO/LATER: The filters should show the password dialog themself in future 1655 if ( bMSType ) 1656 { 1657 // all the current MS-filters use MSCodec_Std97 implementation 1658 uno::Sequence< sal_Int8 > aUniqueID = ::comphelper::DocPasswordHelper::GenerateRandomByteSequence( 16 ); 1659 uno::Sequence< sal_Int8 > aEncryptionKey = ::comphelper::DocPasswordHelper::GenerateStd97Key( pPasswordRequest->getPassword(), aUniqueID ); 1660 1661 if ( aEncryptionKey.getLength() ) 1662 { 1663 ::comphelper::SequenceAsHashMap aHashData; 1664 aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97EncryptionKey" ) ) ] <<= aEncryptionKey; 1665 aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97UniqueID" ) ) ] <<= aUniqueID; 1666 1667 rpSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aHashData.getAsConstNamedValueList() ) ) ); 1668 } 1669 else 1670 return ERRCODE_IO_NOTSUPPORTED; 1671 } 1672 else 1673 { 1674 rpSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( ::comphelper::OStorageHelper::CreatePackageEncryptionData( pPasswordRequest->getPassword() ) ) ) ); 1675 } 1676 } 1677 1678 if ( pPasswordRequest->getRecommendReadOnly() ) 1679 rpSet->Put( SfxBoolItem( SID_RECOMMENDREADONLY, sal_True ) ); 1680 1681 if ( bMSType ) 1682 { 1683 // the empty password has 0 as Hash 1684 sal_Int32 nHash = SfxMedium::CreatePasswordToModifyHash( pPasswordRequest->getPasswordToModify(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" ) ).equals( pCurrentFilter->GetServiceName() ) ); 1685 if ( nHash ) 1686 rpSet->Put( SfxUnoAnyItem( SID_MODIFYPASSWORDINFO, uno::makeAny( nHash ) ) ); 1687 } 1688 else 1689 { 1690 uno::Sequence< beans::PropertyValue > aModifyPasswordInfo = ::comphelper::DocPasswordHelper::GenerateNewModifyPasswordInfo( pPasswordRequest->getPasswordToModify() ); 1691 if ( aModifyPasswordInfo.getLength() ) 1692 rpSet->Put( SfxUnoAnyItem( SID_MODIFYPASSWORDINFO, uno::makeAny( aModifyPasswordInfo ) ) ); 1693 } 1694 } 1695 else 1696 return ERRCODE_ABORT; 1697 } 1698 } 1699 } 1700 catch( IllegalArgumentException ){} 1701 } 1702 1703 SaveLastUsedFilter(); 1704 return ERRCODE_NONE; 1705 } 1706 else 1707 return ERRCODE_ABORT; 1708 } 1709 1710 // ------------------------------------------------------------------------ 1711 ErrCode FileDialogHelper_Impl::execute() 1712 { 1713 if ( ! mxFileDlg.is() ) 1714 return ERRCODE_ABORT; 1715 1716 sal_Int16 nRet = implDoExecute(); 1717 1718 maPath = mxFileDlg->getDisplayDirectory(); 1719 1720 if ( ExecutableDialogResults::CANCEL == nRet ) 1721 return ERRCODE_ABORT; 1722 else 1723 { 1724 return ERRCODE_NONE; 1725 } 1726 } 1727 1728 // ------------------------------------------------------------------------ 1729 OUString FileDialogHelper_Impl::getPath() const 1730 { 1731 OUString aPath; 1732 1733 if ( mxFileDlg.is() ) 1734 aPath = mxFileDlg->getDisplayDirectory(); 1735 1736 if ( !aPath.getLength() ) 1737 aPath = maPath; 1738 1739 return aPath; 1740 } 1741 1742 // ------------------------------------------------------------------------ 1743 OUString FileDialogHelper_Impl::getFilter() const 1744 { 1745 String aFilter = getCurrentFilterUIName(); 1746 1747 if( !aFilter.Len() ) 1748 aFilter = maCurFilter; 1749 1750 return aFilter; 1751 } 1752 1753 // ------------------------------------------------------------------------ 1754 void FileDialogHelper_Impl::getRealFilter( String& _rFilter ) const 1755 { 1756 _rFilter = getCurrentFilterUIName(); 1757 1758 if ( !_rFilter.Len() ) 1759 _rFilter = maCurFilter; 1760 1761 if ( _rFilter.Len() && mpMatcher ) 1762 { 1763 const SfxFilter* pFilter = 1764 mpMatcher->GetFilter4UIName( _rFilter, m_nMustFlags, m_nDontFlags ); 1765 _rFilter = pFilter ? pFilter->GetFilterName() : _rFilter.Erase(); 1766 } 1767 } 1768 1769 // ------------------------------------------------------------------------ 1770 void FileDialogHelper_Impl::displayFolder( const ::rtl::OUString& _rPath ) 1771 { 1772 if ( ! _rPath.getLength() ) 1773 // nothing to do 1774 return; 1775 1776 /* 1777 if ( !::utl::UCBContentHelper::IsFolder( _rPath ) ) 1778 // only valid folders accepted here 1779 return; 1780 */ 1781 1782 maPath = _rPath; 1783 if ( mxFileDlg.is() ) 1784 { 1785 try 1786 { 1787 mxFileDlg->setDisplayDirectory( maPath ); 1788 } 1789 catch( const IllegalArgumentException& ) 1790 { 1791 DBG_ERROR( "FileDialogHelper_Impl::displayFolder: caught an exception!" ); 1792 } 1793 } 1794 } 1795 1796 // ------------------------------------------------------------------------ 1797 void FileDialogHelper_Impl::setFileName( const ::rtl::OUString& _rFile ) 1798 { 1799 maFileName = _rFile; 1800 if ( mxFileDlg.is() ) 1801 { 1802 try 1803 { 1804 mxFileDlg->setDefaultName( maFileName ); 1805 } 1806 catch( const IllegalArgumentException& ) 1807 { 1808 DBG_ERROR( "FileDialogHelper_Impl::setFileName: caught an exception!" ); 1809 } 1810 } 1811 } 1812 1813 // ------------------------------------------------------------------------ 1814 void FileDialogHelper_Impl::setFilter( const OUString& rFilter ) 1815 { 1816 DBG_ASSERT( rFilter.indexOf(':') == -1, "Old filter name used!"); 1817 1818 maCurFilter = rFilter; 1819 1820 if ( rFilter.getLength() && mpMatcher ) 1821 { 1822 const SfxFilter* pFilter = mpMatcher->GetFilter4FilterName( 1823 rFilter, m_nMustFlags, m_nDontFlags ); 1824 if ( pFilter ) 1825 maCurFilter = pFilter->GetUIName(); 1826 } 1827 1828 uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY ); 1829 1830 if ( maCurFilter.getLength() && xFltMgr.is() ) 1831 { 1832 try 1833 { 1834 xFltMgr->setCurrentFilter( maCurFilter ); 1835 } 1836 catch( IllegalArgumentException ){} 1837 } 1838 } 1839 1840 // ------------------------------------------------------------------------ 1841 void FileDialogHelper_Impl::createMatcher( const String& rFactory ) 1842 { 1843 mpMatcher = new SfxFilterMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory) ); 1844 mbDeleteMatcher = sal_True; 1845 } 1846 1847 // ------------------------------------------------------------------------ 1848 void FileDialogHelper_Impl::addFilters( sal_Int64 nFlags, 1849 const String& rFactory, 1850 SfxFilterFlags nMust, 1851 SfxFilterFlags nDont ) 1852 { 1853 uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY ); 1854 1855 if ( ! xFltMgr.is() ) 1856 return; 1857 1858 // we still need a matcher to convert UI names to filter names 1859 if ( !rFactory.Len() ) 1860 { 1861 SfxApplication *pSfxApp = SFX_APP(); 1862 mpMatcher = &pSfxApp->GetFilterMatcher(); 1863 mbDeleteMatcher = sal_False; 1864 } 1865 else 1866 { 1867 mpMatcher = new SfxFilterMatcher( rFactory ); 1868 mbDeleteMatcher = sal_True; 1869 } 1870 1871 uno::Reference< XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); 1872 uno::Reference< XContainerQuery > xFilterCont( 1873 xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.document.FilterFactory")), 1874 UNO_QUERY); 1875 if ( ! xFilterCont.is() ) 1876 return; 1877 1878 m_nMustFlags |= nMust; 1879 m_nDontFlags |= nDont; 1880 1881 // create the list of filters 1882 ::rtl::OUStringBuffer sQuery(256); 1883 sQuery.appendAscii("getSortedFilterList()"); 1884 sQuery.appendAscii(":module=" ); 1885 sQuery.append (rFactory ); // use long name here ! 1886 sQuery.appendAscii(":iflags=" ); 1887 sQuery.append (::rtl::OUString::valueOf((sal_Int32)m_nMustFlags)); 1888 sQuery.appendAscii(":eflags=" ); 1889 sQuery.append (::rtl::OUString::valueOf((sal_Int32)m_nDontFlags)); 1890 1891 uno::Reference< XEnumeration > xResult; 1892 try 1893 { 1894 xResult = xFilterCont->createSubSetEnumerationByQuery(sQuery.makeStringAndClear()); 1895 } 1896 catch( uno::Exception& ) 1897 { 1898 DBG_ERRORFILE( "Could not get filters from the configuration!" ); 1899 } 1900 1901 TSortedFilterList aIter (xResult); 1902 1903 // no matcher any longer used ... 1904 mbDeleteMatcher = sal_False; 1905 1906 // append the filters 1907 ::rtl::OUString sFirstFilter; 1908 if ( WB_OPEN == ( nFlags & WB_OPEN ) ) 1909 ::sfx2::appendFiltersForOpen( aIter, xFltMgr, sFirstFilter, *this ); 1910 else if ( mbExport ) 1911 ::sfx2::appendExportFilters( aIter, xFltMgr, sFirstFilter, *this ); 1912 else 1913 ::sfx2::appendFiltersForSave( aIter, xFltMgr, sFirstFilter, *this, rFactory ); 1914 1915 // set our initial selected filter (if we do not already have one) 1916 if ( !maSelectFilter.getLength() ) 1917 maSelectFilter = sFirstFilter; 1918 } 1919 1920 // ------------------------------------------------------------------------ 1921 void FileDialogHelper_Impl::addFilter( const OUString& rFilterName, 1922 const OUString& rExtension ) 1923 { 1924 uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY ); 1925 1926 if ( ! xFltMgr.is() ) 1927 return; 1928 1929 try 1930 { 1931 xFltMgr->appendFilter( rFilterName, rExtension ); 1932 1933 if ( !maSelectFilter.getLength() ) 1934 maSelectFilter = rFilterName; 1935 } 1936 catch( IllegalArgumentException ) 1937 { 1938 #ifdef DBG_UTIL 1939 ByteString aMsg( "Could not append Filter" ); 1940 aMsg += ByteString( String( rFilterName ), RTL_TEXTENCODING_UTF8 ); 1941 DBG_ERRORFILE( aMsg.GetBuffer() ); 1942 #endif 1943 } 1944 } 1945 1946 // ------------------------------------------------------------------------ 1947 void FileDialogHelper_Impl::addGraphicFilter() 1948 { 1949 uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY ); 1950 1951 if ( ! xFltMgr.is() ) 1952 return; 1953 1954 // create the list of filters 1955 mpGraphicFilter = new GraphicFilter; 1956 sal_uInt16 i, j, nCount = mpGraphicFilter->GetImportFormatCount(); 1957 1958 // compute the extension string for all known import filters 1959 String aExtensions; 1960 1961 for ( i = 0; i < nCount; i++ ) 1962 { 1963 j = 0; 1964 String sWildcard; 1965 while( sal_True ) 1966 { 1967 sWildcard = mpGraphicFilter->GetImportWildcard( i, j++ ); 1968 if ( !sWildcard.Len() ) 1969 break; 1970 if ( aExtensions.Search( sWildcard ) == STRING_NOTFOUND ) 1971 { 1972 if ( aExtensions.Len() ) 1973 aExtensions += sal_Unicode(';'); 1974 aExtensions += sWildcard; 1975 } 1976 } 1977 } 1978 1979 #if defined(WNT) 1980 if ( aExtensions.Len() > 240 ) 1981 aExtensions = DEFINE_CONST_UNICODE( FILEDIALOG_FILTER_ALL ); 1982 #endif 1983 sal_Bool bIsInOpenMode = isInOpenMode(); 1984 1985 try 1986 { 1987 OUString aAllFilterName = String( SfxResId( STR_SFX_IMPORT_ALL ) ); 1988 aAllFilterName = ::sfx2::addExtension( aAllFilterName, aExtensions, bIsInOpenMode, *this ); 1989 1990 xFltMgr->appendFilter( aAllFilterName, aExtensions ); 1991 maSelectFilter = aAllFilterName; 1992 } 1993 catch( IllegalArgumentException ) 1994 { 1995 DBG_ERRORFILE( "Could not append Filter" ); 1996 } 1997 1998 // Now add the filter 1999 for ( i = 0; i < nCount; i++ ) 2000 { 2001 String aName = mpGraphicFilter->GetImportFormatName( i ); 2002 String aExt; 2003 j = 0; 2004 String sWildcard; 2005 while( sal_True ) 2006 { 2007 sWildcard = mpGraphicFilter->GetImportWildcard( i, j++ ); 2008 if ( !sWildcard.Len() ) 2009 break; 2010 if ( aExt.Search( sWildcard ) == STRING_NOTFOUND ) 2011 { 2012 if ( aExt.Len() ) 2013 aExt += sal_Unicode(';'); 2014 aExt += sWildcard; 2015 } 2016 } 2017 aName = ::sfx2::addExtension( aName, aExt, bIsInOpenMode, *this ); 2018 try 2019 { 2020 xFltMgr->appendFilter( aName, aExt ); 2021 } 2022 catch( IllegalArgumentException ) 2023 { 2024 DBG_ERRORFILE( "Could not append Filter" ); 2025 } 2026 } 2027 } 2028 2029 // ------------------------------------------------------------------------ 2030 #define GRF_CONFIG_STR " " 2031 #define STD_CONFIG_STR "1 " 2032 2033 void FileDialogHelper_Impl::saveConfig() 2034 { 2035 uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY ); 2036 Any aValue; 2037 2038 if ( ! xDlg.is() ) 2039 return; 2040 2041 if ( mbHasPreview ) 2042 { 2043 SvtViewOptions aDlgOpt( E_DIALOG, IMPGRF_CONFIGNAME ); 2044 String aUserData = DEFINE_CONST_UNICODE( GRF_CONFIG_STR ); 2045 2046 try 2047 { 2048 aValue = xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0 ); 2049 sal_Bool bValue = sal_False; 2050 aValue >>= bValue; 2051 aUserData.SetToken( 0, ' ', String::CreateFromInt32( (sal_Int32) bValue ) ); 2052 2053 aValue = xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0 ); 2054 bValue = sal_False; 2055 aValue >>= bValue; 2056 aUserData.SetToken( 1, ' ', String::CreateFromInt32( (sal_Int32) bValue ) ); 2057 2058 INetURLObject aObj( getPath() ); 2059 2060 if ( aObj.GetProtocol() == INET_PROT_FILE ) 2061 aUserData.SetToken( 2, ' ', aObj.GetMainURL( INetURLObject::NO_DECODE ) ); 2062 2063 String aFilter = getFilter(); 2064 aFilter = EncodeSpaces_Impl( aFilter ); 2065 aUserData.SetToken( 3, ' ', aFilter ); 2066 2067 aDlgOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aUserData ) ) ); 2068 } 2069 catch( IllegalArgumentException ){} 2070 } 2071 else 2072 { 2073 sal_Bool bWriteConfig = sal_False; 2074 SvtViewOptions aDlgOpt( E_DIALOG, IODLG_CONFIGNAME ); 2075 String aUserData = DEFINE_CONST_UNICODE( STD_CONFIG_STR ); 2076 2077 if ( aDlgOpt.Exists() ) 2078 { 2079 Any aUserItem = aDlgOpt.GetUserItem( USERITEM_NAME ); 2080 OUString aTemp; 2081 if ( aUserItem >>= aTemp ) 2082 aUserData = String( aTemp ); 2083 } 2084 2085 if ( mbHasAutoExt ) 2086 { 2087 try 2088 { 2089 aValue = xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0 ); 2090 sal_Bool bAutoExt = sal_True; 2091 aValue >>= bAutoExt; 2092 aUserData.SetToken( 0, ' ', String::CreateFromInt32( (sal_Int32) bAutoExt ) ); 2093 bWriteConfig = sal_True; 2094 } 2095 catch( IllegalArgumentException ){} 2096 } 2097 2098 if ( ! mbIsSaveDlg ) 2099 { 2100 OUString aPath = getPath(); 2101 if ( aPath.getLength() && 2102 utl::LocalFileHelper::IsLocalFile( aPath ) ) 2103 { 2104 aUserData.SetToken( 1, ' ', aPath ); 2105 bWriteConfig = sal_True; 2106 } 2107 } 2108 2109 if( mbHasSelectionBox && mbSelectionFltrEnabled ) 2110 { 2111 try 2112 { 2113 aValue = xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0 ); 2114 sal_Bool bSelection = sal_True; 2115 aValue >>= bSelection; 2116 if ( aUserData.GetTokenCount(' ') < 3 ) 2117 aUserData.Append(' '); 2118 aUserData.SetToken( 2, ' ', String::CreateFromInt32( (sal_Int32) bSelection ) ); 2119 bWriteConfig = sal_True; 2120 } 2121 catch( IllegalArgumentException ){} 2122 } 2123 2124 if ( bWriteConfig ) 2125 aDlgOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aUserData ) ) ); 2126 } 2127 2128 SfxApplication *pSfxApp = SFX_APP(); 2129 pSfxApp->SetLastDir_Impl( getPath() ); 2130 } 2131 2132 // ------------------------------------------------------------------------ 2133 namespace 2134 { 2135 static ::rtl::OUString getInitPath( const String& _rFallback, const xub_StrLen _nFallbackToken ) 2136 { 2137 SfxApplication *pSfxApp = SFX_APP(); 2138 String sPath = pSfxApp->GetLastDir_Impl(); 2139 2140 if ( !sPath.Len() ) 2141 sPath = _rFallback.GetToken( _nFallbackToken, ' ' ); 2142 2143 // check if the path points to a valid (accessible) directory 2144 sal_Bool bValid = sal_False; 2145 if ( sPath.Len() ) 2146 { 2147 String sPathCheck( sPath ); 2148 if ( sPathCheck.GetBuffer()[ sPathCheck.Len() - 1 ] != '/' ) 2149 sPathCheck += '/'; 2150 sPathCheck += '.'; 2151 try 2152 { 2153 ::ucbhelper::Content aContent( sPathCheck, uno::Reference< ucb::XCommandEnvironment >() ); 2154 bValid = aContent.isFolder(); 2155 } 2156 catch( Exception& ) {} 2157 } 2158 2159 if ( !bValid ) 2160 sPath.Erase(); 2161 2162 return sPath; 2163 } 2164 } 2165 2166 // ------------------------------------------------------------------------ 2167 void FileDialogHelper_Impl::loadConfig() 2168 { 2169 uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY ); 2170 Any aValue; 2171 2172 if ( ! xDlg.is() ) 2173 return; 2174 2175 if ( mbHasPreview ) 2176 { 2177 SvtViewOptions aViewOpt( E_DIALOG, IMPGRF_CONFIGNAME ); 2178 String aUserData; 2179 2180 if ( aViewOpt.Exists() ) 2181 { 2182 Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME ); 2183 OUString aTemp; 2184 if ( aUserItem >>= aTemp ) 2185 aUserData = String( aTemp ); 2186 } 2187 2188 if ( aUserData.Len() > 0 ) 2189 { 2190 try 2191 { 2192 // respect the last "insert as link" state 2193 sal_Bool bLink = (sal_Bool) aUserData.GetToken( 0, ' ' ).ToInt32(); 2194 aValue <<= bLink; 2195 xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, aValue ); 2196 2197 // respect the last "show preview" state 2198 sal_Bool bShowPreview = (sal_Bool) aUserData.GetToken( 1, ' ' ).ToInt32(); 2199 aValue <<= bShowPreview; 2200 xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0, aValue ); 2201 2202 if ( !maPath.getLength() ) 2203 displayFolder( getInitPath( aUserData, 2 ) ); 2204 2205 if ( ! maCurFilter.getLength() ) 2206 { 2207 String aFilter = aUserData.GetToken( 3, ' ' ); 2208 aFilter = DecodeSpaces_Impl( aFilter ); 2209 setFilter( aFilter ); 2210 } 2211 2212 // set the member so we know that we have to show the preview 2213 mbShowPreview = bShowPreview; 2214 } 2215 catch( IllegalArgumentException ){} 2216 } 2217 2218 if ( !maPath.getLength() ) 2219 displayFolder( SvtPathOptions().GetGraphicPath() ); 2220 } 2221 else 2222 { 2223 SvtViewOptions aViewOpt( E_DIALOG, IODLG_CONFIGNAME ); 2224 String aUserData; 2225 2226 if ( aViewOpt.Exists() ) 2227 { 2228 Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME ); 2229 OUString aTemp; 2230 if ( aUserItem >>= aTemp ) 2231 aUserData = String( aTemp ); 2232 } 2233 2234 if ( ! aUserData.Len() ) 2235 aUserData = DEFINE_CONST_UNICODE( STD_CONFIG_STR ); 2236 2237 if ( ! maPath.getLength() ) 2238 displayFolder( getInitPath( aUserData, 1 ) ); 2239 2240 if ( mbHasAutoExt ) 2241 { 2242 sal_Int32 nFlag = aUserData.GetToken( 0, ' ' ).ToInt32(); 2243 aValue <<= (sal_Bool) nFlag; 2244 try 2245 { 2246 xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, aValue ); 2247 } 2248 catch( IllegalArgumentException ){} 2249 } 2250 2251 if( mbHasSelectionBox ) 2252 { 2253 sal_Int32 nFlag = aUserData.GetToken( 2, ' ' ).ToInt32(); 2254 aValue <<= (sal_Bool) nFlag; 2255 try 2256 { 2257 xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0, aValue ); 2258 } 2259 catch( IllegalArgumentException ){} 2260 } 2261 2262 if ( !maPath.getLength() ) 2263 displayFolder( SvtPathOptions().GetWorkPath() ); 2264 } 2265 } 2266 2267 // ------------------------------------------------------------------------ 2268 void FileDialogHelper_Impl::setDefaultValues() 2269 { 2270 // when no filter is set, we set the curentFilter to <all> 2271 if ( !maCurFilter.getLength() && maSelectFilter.getLength() ) 2272 { 2273 uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY ); 2274 try 2275 { 2276 xFltMgr->setCurrentFilter( maSelectFilter ); 2277 } 2278 catch( IllegalArgumentException ) 2279 {} 2280 } 2281 2282 // when no path is set, we use the standard 'work' folder 2283 if ( ! maPath.getLength() ) 2284 { 2285 OUString aWorkFolder = SvtPathOptions().GetWorkPath(); 2286 try 2287 { 2288 mxFileDlg->setDisplayDirectory( aWorkFolder ); 2289 } 2290 catch( const Exception& ) 2291 { 2292 DBG_ERROR( "FileDialogHelper_Impl::setDefaultValues: caught an exception while setting the display directory!" ); 2293 } 2294 2295 // INetURLObject aStdDirObj( SvtPathOptions().GetWorkPath() ); 2296 //SetStandardDir( aStdDirObj.GetMainURL( INetURLObject::NO_DECODE ) ); 2297 } 2298 } 2299 2300 sal_Bool FileDialogHelper_Impl::isShowFilterExtensionEnabled() const 2301 { 2302 return !maFilters.empty(); 2303 } 2304 2305 void FileDialogHelper_Impl::addFilterPair( const OUString& rFilter, 2306 const OUString& rFilterWithExtension ) 2307 { 2308 maFilters.push_back( FilterPair( rFilter, rFilterWithExtension ) ); 2309 2310 } 2311 2312 OUString FileDialogHelper_Impl::getFilterName( const OUString& rFilterWithExtension ) const 2313 { 2314 OUString sRet; 2315 for( ::std::vector< FilterPair >::const_iterator pIter = maFilters.begin(); pIter != maFilters.end(); ++pIter ) 2316 { 2317 if ( (*pIter).Second == rFilterWithExtension ) 2318 { 2319 sRet = (*pIter).First; 2320 break; 2321 } 2322 } 2323 return sRet; 2324 } 2325 2326 OUString FileDialogHelper_Impl::getFilterWithExtension( const OUString& rFilter ) const 2327 { 2328 OUString sRet; 2329 for( ::std::vector< FilterPair >::const_iterator pIter = maFilters.begin(); pIter != maFilters.end(); ++pIter ) 2330 { 2331 if ( (*pIter).First == rFilter ) 2332 { 2333 sRet = (*pIter).Second; 2334 break; 2335 } 2336 } 2337 return sRet; 2338 } 2339 2340 void FileDialogHelper_Impl::SetContext( FileDialogHelper::Context _eNewContext ) 2341 { 2342 meContext = _eNewContext; 2343 2344 sal_Int32 nNewHelpId = 0; 2345 OUString aConfigId; 2346 2347 switch( _eNewContext ) 2348 { 2349 // #104952# dependency to SVX not allowed! When used again, another solution has to be found 2350 // case FileDialogHelper::SW_INSERT_GRAPHIC: 2351 // case FileDialogHelper::SC_INSERT_GRAPHIC: 2352 // case FileDialogHelper::SD_INSERT_GRAPHIC: nNewHelpId = SID_INSERT_GRAPHIC; break; 2353 case FileDialogHelper::SW_INSERT_SOUND: 2354 case FileDialogHelper::SC_INSERT_SOUND: 2355 case FileDialogHelper::SD_INSERT_SOUND: nNewHelpId = SID_INSERT_SOUND; break; 2356 case FileDialogHelper::SW_INSERT_VIDEO: 2357 case FileDialogHelper::SC_INSERT_VIDEO: 2358 case FileDialogHelper::SD_INSERT_VIDEO: nNewHelpId = SID_INSERT_VIDEO; break; 2359 default: break; 2360 } 2361 2362 const OUString* pConfigId = GetLastFilterConfigId( _eNewContext ); 2363 if( pConfigId ) 2364 LoadLastUsedFilter( *pConfigId ); 2365 } 2366 2367 // ------------------------------------------------------------------------ 2368 // ----------- FileDialogHelper --------------------------- 2369 // ------------------------------------------------------------------------ 2370 2371 FileDialogHelper::FileDialogHelper( 2372 sal_Int64 nFlags, 2373 const String& rFact, 2374 SfxFilterFlags nMust, 2375 SfxFilterFlags nDont ) 2376 { 2377 mpImp = new FileDialogHelper_Impl( this, getDialogType( nFlags ), nFlags ); 2378 mxImp = mpImp; 2379 2380 // create the list of filters 2381 mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont ); 2382 } 2383 2384 FileDialogHelper::FileDialogHelper( 2385 sal_Int64 nFlags, 2386 const String& rFact, 2387 sal_Int16 nDialog, 2388 SfxFilterFlags nMust, 2389 SfxFilterFlags nDont, 2390 const String& rStandardDir, 2391 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList) 2392 { 2393 mpImp = new FileDialogHelper_Impl( this, getDialogType( nFlags ), nFlags, nDialog, NULL , rStandardDir, rBlackList ); 2394 mxImp = mpImp; 2395 2396 // create the list of filters 2397 mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont ); 2398 } 2399 2400 FileDialogHelper::FileDialogHelper( 2401 sal_Int64 nFlags, 2402 const String& rFact, 2403 sal_Int16 nDialog, 2404 SfxFilterFlags nMust, 2405 SfxFilterFlags nDont ) 2406 { 2407 mpImp = new FileDialogHelper_Impl( this, getDialogType( nFlags ), nFlags, nDialog ); 2408 mxImp = mpImp; 2409 2410 // create the list of filters 2411 mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont ); 2412 } 2413 2414 // ------------------------------------------------------------------------ 2415 FileDialogHelper::FileDialogHelper( sal_Int64 nFlags ) 2416 { 2417 sal_Int16 nDialogType = getDialogType( nFlags ); 2418 2419 mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags ); 2420 mxImp = mpImp; 2421 } 2422 2423 // ------------------------------------------------------------------------ 2424 FileDialogHelper::FileDialogHelper( 2425 sal_Int16 nDialogType, 2426 sal_Int64 nFlags, 2427 const String& rFact, 2428 SfxFilterFlags nMust, 2429 SfxFilterFlags nDont ) 2430 { 2431 mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags ); 2432 mxImp = mpImp; 2433 2434 // create the list of filters 2435 mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont ); 2436 } 2437 2438 // ------------------------------------------------------------------------ 2439 FileDialogHelper::FileDialogHelper( 2440 sal_Int16 nDialogType, 2441 sal_Int64 nFlags, 2442 const String& rFact, 2443 sal_Int16 nDialog, 2444 SfxFilterFlags nMust, 2445 SfxFilterFlags nDont, 2446 const String& rStandardDir, 2447 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList) 2448 { 2449 mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags, nDialog, NULL, rStandardDir, rBlackList ); 2450 mxImp = mpImp; 2451 2452 // create the list of filters 2453 mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont ); 2454 } 2455 2456 // ------------------------------------------------------------------------ 2457 FileDialogHelper::FileDialogHelper( 2458 sal_Int16 nDialogType, 2459 sal_Int64 nFlags, 2460 Window* _pPreferredParent ) 2461 { 2462 mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags, SFX2_IMPL_DIALOG_CONFIG, _pPreferredParent ); 2463 mxImp = mpImp; 2464 } 2465 2466 // ------------------------------------------------------------------------ 2467 FileDialogHelper::FileDialogHelper( 2468 sal_Int16 nDialogType, 2469 sal_Int64 nFlags, 2470 const ::rtl::OUString& aFilterUIName, 2471 const ::rtl::OUString& aExtName, 2472 const ::rtl::OUString& rStandardDir, 2473 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList, 2474 Window* _pPreferredParent ) 2475 { 2476 mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags, SFX2_IMPL_DIALOG_CONFIG, _pPreferredParent,rStandardDir, rBlackList ); 2477 mxImp = mpImp; 2478 2479 // the wildcard here is expected in form "*.extension" 2480 ::rtl::OUString aWildcard; 2481 if ( aExtName.indexOf( (sal_Unicode)'*' ) != 0 ) 2482 { 2483 if ( aExtName.getLength() && aExtName.indexOf( (sal_Unicode)'.' ) != 0 ) 2484 aWildcard = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*." ) ); 2485 else 2486 aWildcard = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*" ) ); 2487 } 2488 2489 aWildcard += aExtName; 2490 2491 ::rtl::OUString aUIString = 2492 ::sfx2::addExtension( aFilterUIName, aWildcard, ( WB_OPEN == ( nFlags & WB_OPEN ) ), *mpImp ); 2493 AddFilter( aUIString, aWildcard ); 2494 } 2495 2496 // ------------------------------------------------------------------------ 2497 FileDialogHelper::~FileDialogHelper() 2498 { 2499 mpImp->dispose(); 2500 mxImp.clear(); 2501 } 2502 2503 // ------------------------------------------------------------------------ 2504 void FileDialogHelper::CreateMatcher( const String& rFactory ) 2505 { 2506 mpImp->createMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory) ); 2507 } 2508 2509 // ------------------------------------------------------------------------ 2510 void FileDialogHelper::SetControlHelpIds( const sal_Int16* _pControlId, const char** _pHelpId ) 2511 { 2512 mpImp->setControlHelpIds( _pControlId, _pHelpId ); 2513 } 2514 2515 void FileDialogHelper::SetContext( Context _eNewContext ) 2516 { 2517 mpImp->SetContext( _eNewContext ); 2518 } 2519 2520 // ------------------------------------------------------------------------ 2521 IMPL_LINK( FileDialogHelper, ExecuteSystemFilePicker, void*, EMPTYARG ) 2522 { 2523 m_nError = mpImp->execute(); 2524 if ( m_aDialogClosedLink.IsSet() ) 2525 m_aDialogClosedLink.Call( this ); 2526 2527 return 0L; 2528 } 2529 2530 // ------------------------------------------------------------------------ 2531 // rDirPath has to be a directory 2532 ErrCode FileDialogHelper::Execute( SvStringsDtor*& rpURLList, 2533 SfxItemSet *& rpSet, 2534 String& rFilter, 2535 const String& rDirPath ) 2536 { 2537 SetDisplayFolder( rDirPath ); 2538 return mpImp->execute( rpURLList, rpSet, rFilter ); 2539 } 2540 2541 2542 // ------------------------------------------------------------------------ 2543 ErrCode FileDialogHelper::Execute() 2544 { 2545 return mpImp->execute(); 2546 } 2547 2548 // ------------------------------------------------------------------------ 2549 ErrCode FileDialogHelper::Execute( SfxItemSet *& rpSet, 2550 String& rFilter ) 2551 { 2552 ErrCode nRet; 2553 SvStringsDtor* pURLList; 2554 2555 nRet = mpImp->execute( pURLList, rpSet, rFilter ); 2556 2557 delete pURLList; 2558 2559 return nRet; 2560 } 2561 2562 void FileDialogHelper::StartExecuteModal( const Link& rEndDialogHdl ) 2563 { 2564 m_aDialogClosedLink = rEndDialogHdl; 2565 m_nError = ERRCODE_NONE; 2566 if ( mpImp->isSystemFilePicker() ) 2567 Application::PostUserEvent( LINK( this, FileDialogHelper, ExecuteSystemFilePicker ) ); 2568 else 2569 mpImp->implStartExecute(); 2570 } 2571 2572 // ------------------------------------------------------------------------ 2573 2574 short FileDialogHelper::GetDialogType() const 2575 { 2576 return mpImp ? mpImp->m_nDialogType : 0; 2577 } 2578 2579 // ------------------------------------------------------------------------ 2580 2581 sal_Bool FileDialogHelper::IsPasswordEnabled() const 2582 { 2583 return mpImp ? mpImp->isPasswordEnabled() : sal_False; 2584 } 2585 2586 // ------------------------------------------------------------------------ 2587 2588 String FileDialogHelper::GetRealFilter() const 2589 { 2590 String sFilter; 2591 if ( mpImp ) 2592 mpImp->getRealFilter( sFilter ); 2593 return sFilter; 2594 } 2595 2596 // ------------------------------------------------------------------------ 2597 void FileDialogHelper::SetTitle( const String& rNewTitle ) 2598 { 2599 if ( mpImp->mxFileDlg.is() ) 2600 mpImp->mxFileDlg->setTitle( rNewTitle ); 2601 } 2602 2603 // ------------------------------------------------------------------------ 2604 String FileDialogHelper::GetPath() const 2605 { 2606 OUString aPath; 2607 2608 if ( mpImp->mlLastURLs.size() > 0) 2609 return mpImp->mlLastURLs[0]; 2610 2611 if ( mpImp->mxFileDlg.is() ) 2612 { 2613 Sequence < OUString > aPathSeq = mpImp->mxFileDlg->getFiles(); 2614 2615 if ( aPathSeq.getLength() == 1 ) 2616 { 2617 aPath = aPathSeq[0]; 2618 } 2619 } 2620 2621 return aPath; 2622 } 2623 2624 // ------------------------------------------------------------------------ 2625 Sequence < OUString > FileDialogHelper::GetMPath() const 2626 { 2627 if ( mpImp->mlLastURLs.size() > 0) 2628 return mpImp->mlLastURLs.getAsConstList(); 2629 2630 if ( mpImp->mxFileDlg.is() ) 2631 return mpImp->mxFileDlg->getFiles(); 2632 else 2633 { 2634 Sequence < OUString > aEmpty; 2635 return aEmpty; 2636 } 2637 } 2638 2639 // ------------------------------------------------------------------------ 2640 Sequence< ::rtl::OUString > FileDialogHelper::GetSelectedFiles() const 2641 { 2642 // a) the new way (optional!) 2643 uno::Sequence< ::rtl::OUString > aResultSeq; 2644 uno::Reference< XFilePicker2 > xPickNew(mpImp->mxFileDlg, UNO_QUERY); 2645 if (xPickNew.is()) 2646 { 2647 aResultSeq = xPickNew->getSelectedFiles(); 2648 } 2649 // b) the olde way ... non optional. 2650 else 2651 { 2652 uno::Reference< XFilePicker > xPickOld(mpImp->mxFileDlg, UNO_QUERY_THROW); 2653 Sequence< OUString > lFiles = xPickOld->getFiles(); 2654 ::sal_Int32 nFiles = lFiles.getLength(); 2655 if ( nFiles > 1 ) 2656 { 2657 aResultSeq = Sequence< ::rtl::OUString >( nFiles-1 ); 2658 2659 INetURLObject aPath( lFiles[0] ); 2660 aPath.setFinalSlash(); 2661 2662 for (::sal_Int32 i = 1; i < nFiles; i++) 2663 { 2664 if (i == 1) 2665 aPath.Append( lFiles[i] ); 2666 else 2667 aPath.setName( lFiles[i] ); 2668 2669 aResultSeq[i-1] = ::rtl::OUString(aPath.GetMainURL( INetURLObject::NO_DECODE )); 2670 } 2671 } 2672 else 2673 aResultSeq = lFiles; 2674 } 2675 2676 return aResultSeq; 2677 } 2678 2679 // ------------------------------------------------------------------------ 2680 String FileDialogHelper::GetDisplayDirectory() const 2681 { 2682 return mpImp->getPath(); 2683 } 2684 2685 // ------------------------------------------------------------------------ 2686 String FileDialogHelper::GetCurrentFilter() const 2687 { 2688 return mpImp->getFilter(); 2689 } 2690 2691 // ------------------------------------------------------------------------ 2692 ErrCode FileDialogHelper::GetGraphic( Graphic& rGraphic ) const 2693 { 2694 return mpImp->getGraphic( rGraphic ); 2695 } 2696 2697 // ------------------------------------------------------------------------ 2698 static int impl_isFolder( const OUString& rPath ) 2699 { 2700 uno::Reference< task::XInteractionHandler > xHandler; 2701 try 2702 { 2703 uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW ); 2704 xHandler.set( xFactory->createInstance( DEFINE_CONST_OUSTRING( "com.sun.star.task.InteractionHandler" ) ), 2705 uno::UNO_QUERY_THROW ); 2706 } 2707 catch ( Exception const & ) 2708 { 2709 } 2710 2711 ::rtl::Reference< ::comphelper::StillReadWriteInteraction > aHandler = new ::comphelper::StillReadWriteInteraction( xHandler ); 2712 2713 try 2714 { 2715 ::ucbhelper::Content aContent( 2716 rPath, new ::ucbhelper::CommandEnvironment( static_cast< task::XInteractionHandler* > ( aHandler.get() ), uno::Reference< ucb::XProgressHandler >() ) ); 2717 if ( aContent.isFolder() ) 2718 return 1; 2719 2720 return 0; 2721 } 2722 catch ( Exception const & ) 2723 { 2724 } 2725 2726 return -1; 2727 } 2728 2729 void FileDialogHelper::SetDisplayDirectory( const String& _rPath ) 2730 { 2731 if ( !_rPath.Len() ) 2732 return; 2733 2734 // if the given path isn't a folder, we cut off the last part 2735 // and take it as filename and the rest of the path should be 2736 // the folder 2737 2738 INetURLObject aObj( _rPath ); 2739 2740 ::rtl::OUString sFileName = aObj.GetName( INetURLObject::DECODE_WITH_CHARSET ); 2741 aObj.removeSegment(); 2742 ::rtl::OUString sPath = aObj.GetMainURL( INetURLObject::NO_DECODE ); 2743 2744 int nIsFolder = impl_isFolder( _rPath ); 2745 if ( nIsFolder == 0 || 2746 ( nIsFolder == -1 && impl_isFolder( sPath ) == 1 ) ) 2747 { 2748 mpImp->setFileName( sFileName ); 2749 mpImp->displayFolder( sPath ); 2750 } 2751 else 2752 { 2753 INetURLObject aObjPathName( _rPath ); 2754 ::rtl::OUString sFolder( aObjPathName.GetMainURL( INetURLObject::NO_DECODE ) ); 2755 if ( sFolder.getLength() == 0 ) 2756 { 2757 // _rPath is not a valid path -> fallback to home directory 2758 vos:: OSecurity aSecurity; 2759 aSecurity.getHomeDir( sFolder ); 2760 } 2761 mpImp->displayFolder( sFolder ); 2762 } 2763 } 2764 2765 // ------------------------------------------------------------------------ 2766 void FileDialogHelper::SetDisplayFolder( const String& _rURL ) 2767 { 2768 mpImp->displayFolder( _rURL ); 2769 } 2770 2771 // ------------------------------------------------------------------------ 2772 void FileDialogHelper::SetFileName( const String& _rFileName ) 2773 { 2774 mpImp->setFileName( _rFileName ); 2775 } 2776 2777 // ------------------------------------------------------------------------ 2778 void FileDialogHelper::AddFilter( const String& rFilterName, 2779 const String& rExtension ) 2780 { 2781 mpImp->addFilter( rFilterName, rExtension ); 2782 } 2783 2784 // ------------------------------------------------------------------------ 2785 void FileDialogHelper::SetCurrentFilter( const String& rFilter ) 2786 { 2787 String sFilter( rFilter ); 2788 if ( mpImp->isShowFilterExtensionEnabled() ) 2789 sFilter = mpImp->getFilterWithExtension( rFilter ); 2790 mpImp->setFilter( sFilter ); 2791 } 2792 2793 // ------------------------------------------------------------------------ 2794 uno::Reference < XFilePicker > FileDialogHelper::GetFilePicker() const 2795 { 2796 return mpImp->mxFileDlg; 2797 } 2798 2799 // ------------------------------------------------------------------------ 2800 sal_Int16 FileDialogHelper::getDialogType( sal_Int64 nFlags ) const 2801 { 2802 sal_Int16 nDialogType = FILEOPEN_SIMPLE; 2803 2804 if ( nFlags & WB_SAVEAS ) 2805 { 2806 if ( nFlags & SFXWB_PASSWORD ) 2807 nDialogType = FILESAVE_AUTOEXTENSION_PASSWORD; 2808 else 2809 nDialogType = FILESAVE_SIMPLE; 2810 } 2811 else if ( nFlags & SFXWB_GRAPHIC ) 2812 { 2813 if ( nFlags & SFXWB_SHOWSTYLES ) 2814 nDialogType = FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE; 2815 else 2816 nDialogType = FILEOPEN_LINK_PREVIEW; 2817 } 2818 else if ( SFXWB_INSERT != ( nFlags & SFXWB_INSERT ) ) 2819 nDialogType = FILEOPEN_READONLY_VERSION; 2820 2821 return nDialogType; 2822 } 2823 2824 // ------------------------------------------------------------------------ 2825 // XFilePickerListener Methods 2826 // ------------------------------------------------------------------------ 2827 void SAL_CALL FileDialogHelper::FileSelectionChanged( const FilePickerEvent& aEvent ) 2828 { 2829 mpImp->handleFileSelectionChanged( aEvent ); 2830 } 2831 2832 // ------------------------------------------------------------------------ 2833 void SAL_CALL FileDialogHelper::DirectoryChanged( const FilePickerEvent& aEvent ) 2834 { 2835 mpImp->handleDirectoryChanged( aEvent ); 2836 } 2837 2838 // ------------------------------------------------------------------------ 2839 OUString SAL_CALL FileDialogHelper::HelpRequested( const FilePickerEvent& aEvent ) 2840 { 2841 return mpImp->handleHelpRequested( aEvent ); 2842 } 2843 2844 // ------------------------------------------------------------------------ 2845 void SAL_CALL FileDialogHelper::ControlStateChanged( const FilePickerEvent& aEvent ) 2846 { 2847 mpImp->handleControlStateChanged( aEvent ); 2848 } 2849 2850 // ------------------------------------------------------------------------ 2851 void SAL_CALL FileDialogHelper::DialogSizeChanged() 2852 { 2853 mpImp->handleDialogSizeChanged(); 2854 } 2855 2856 // ------------------------------------------------------------------------ 2857 void SAL_CALL FileDialogHelper::DialogClosed( const DialogClosedEvent& _rEvent ) 2858 { 2859 m_nError = ( RET_OK == _rEvent.DialogResult ) ? ERRCODE_NONE : ERRCODE_ABORT; 2860 if ( m_aDialogClosedLink.IsSet() ) 2861 m_aDialogClosedLink.Call( this ); 2862 } 2863 2864 // ------------------------------------------------------------------------ 2865 // ------------------------------------------------------------------------ 2866 // ------------------------------------------------------------------------ 2867 2868 ErrCode FileOpenDialog_Impl( sal_Int64 nFlags, 2869 const String& rFact, 2870 SvStringsDtor *& rpURLList, 2871 String& rFilter, 2872 SfxItemSet *& rpSet, 2873 const String* pPath, 2874 sal_Int16 nDialog, 2875 const String& rStandardDir, 2876 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList ) 2877 { 2878 ErrCode nRet; 2879 FileDialogHelper aDialog( nFlags, rFact, nDialog, 0, 0, rStandardDir, rBlackList ); 2880 2881 String aPath; 2882 if ( pPath ) 2883 aPath = *pPath; 2884 2885 nRet = aDialog.Execute( rpURLList, rpSet, rFilter, aPath ); 2886 DBG_ASSERT( rFilter.SearchAscii(": ") == STRING_NOTFOUND, "Old filter name used!"); 2887 2888 return nRet; 2889 } 2890 2891 2892 // ------------------------------------------------------------------------ 2893 String EncodeSpaces_Impl( const String& rSource ) 2894 { 2895 String sRet( rSource ); 2896 sRet.SearchAndReplaceAll( DEFINE_CONST_UNICODE( " " ), DEFINE_CONST_UNICODE( "%20" ) ); 2897 return sRet; 2898 } 2899 2900 // ------------------------------------------------------------------------ 2901 String DecodeSpaces_Impl( const String& rSource ) 2902 { 2903 String sRet( rSource ); 2904 sRet.SearchAndReplaceAll( DEFINE_CONST_UNICODE( "%20" ), DEFINE_CONST_UNICODE( " " ) ); 2905 return sRet; 2906 } 2907 2908 // ------------------------------------------------------------------------ 2909 2910 } // end of namespace sfx2 2911 2912