1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sfx2.hxx" 30 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> 31 #include <com/sun/star/ui/dialogs/XFilePicker.hpp> 32 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> 33 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> 34 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> 35 #include "com/sun/star/ui/dialogs/TemplateDescription.hpp" 36 #include <com/sun/star/view/XSelectionSupplier.hpp> 37 #include <com/sun/star/beans/XPropertyAccess.hpp> 38 #include <com/sun/star/beans/XPropertySet.hpp> 39 #include <com/sun/star/beans/XPropertyContainer.hpp> 40 #include <com/sun/star/beans/PropertyAttribute.hpp> 41 #include <com/sun/star/document/XExporter.hpp> 42 #include <com/sun/star/document/XDocumentInfoSupplier.hpp> 43 #include <com/sun/star/document/XDocumentInfo.hpp> 44 #include <com/sun/star/task/XInteractionHandler.hpp> 45 #include <com/sun/star/util/DateTime.hpp> 46 #include <com/sun/star/util/XURLTransformer.hpp> 47 #include <com/sun/star/frame/XStorable.hpp> 48 #include <com/sun/star/frame/XStorable2.hpp> 49 #include <com/sun/star/frame/XDispatchProvider.hpp> 50 #include <com/sun/star/frame/XDispatch.hpp> 51 #include <com/sun/star/frame/XTitle.hpp> 52 #include <com/sun/star/util/XModifyListener.hpp> 53 #include <com/sun/star/util/XModifiable.hpp> 54 #include <com/sun/star/util/XModifyBroadcaster.hpp> 55 56 #include <com/sun/star/util/XCloneable.hpp> 57 #include <com/sun/star/frame/XModuleManager.hpp> 58 #include <com/sun/star/io/IOException.hpp> 59 60 #include "guisaveas.hxx" 61 62 #include <unotools/pathoptions.hxx> 63 #include <unotools/pathoptions.hxx> 64 #include <svl/itemset.hxx> 65 #include <svl/eitem.hxx> 66 #include <svl/stritem.hxx> 67 #include <svl/intitem.hxx> 68 #include <unotools/useroptions.hxx> 69 #include <unotools/saveopt.hxx> 70 #include <tools/debug.hxx> 71 #include <tools/urlobj.hxx> 72 #include <comphelper/processfactory.hxx> 73 #include <comphelper/configurationhelper.hxx> 74 #include <comphelper/mimeconfighelper.hxx> 75 #include <vcl/msgbox.hxx> 76 #include <vcl/window.hxx> 77 #include <toolkit/awt/vclxwindow.hxx> 78 79 #include <sfx2/sfxsids.hrc> 80 #include <doc.hrc> 81 #include <sfx2/sfxresid.hxx> 82 #include <sfx2/docfilt.hxx> 83 #include <sfx2/filedlghelper.hxx> 84 #include <sfx2/app.hxx> 85 #include <sfx2/objsh.hxx> 86 #include <sfx2/dinfdlg.hxx> 87 #include <sfx2/request.hxx> 88 #include <sfxtypes.hxx> 89 #include "alienwarn.hxx" 90 91 #include "../appl/app.hrc" 92 93 #define DOCPROPSNUM 17 94 95 // flags that specify requested operation 96 #define EXPORT_REQUESTED 1 97 #define PDFEXPORT_REQUESTED 2 98 #define PDFDIRECTEXPORT_REQUESTED 4 99 #define WIDEEXPORT_REQUESTED 8 100 #define SAVE_REQUESTED 16 101 #define SAVEAS_REQUESTED 32 102 103 // possible statuses of save operation 104 #define STATUS_NO_ACTION 0 105 #define STATUS_SAVE 1 106 #define STATUS_SAVEAS 2 107 #define STATUS_SAVEAS_STANDARDNAME 3 108 109 const ::rtl::OUString aFilterNameString = ::rtl::OUString::createFromAscii( "FilterName" ); 110 const ::rtl::OUString aFilterOptionsString = ::rtl::OUString::createFromAscii( "FilterOptions" ); 111 const ::rtl::OUString aFilterDataString = ::rtl::OUString::createFromAscii( "FilterData" ); 112 const ::rtl::OUString aFilterFlagsString = ::rtl::OUString::createFromAscii( "FilterFlags" ); 113 114 using namespace ::com::sun::star; 115 116 namespace { 117 //------------------------------------------------------------------------- 118 static sal_uInt16 getSlotIDFromMode( sal_Int8 nStoreMode ) 119 { 120 // This is a temporary hardcoded solution must be removed when 121 // dialogs do not need parameters in SidSet representation any more 122 123 sal_uInt16 nResult = 0; 124 if ( nStoreMode == EXPORT_REQUESTED ) 125 nResult = SID_EXPORTDOC; 126 else if ( nStoreMode == ( EXPORT_REQUESTED | PDFEXPORT_REQUESTED ) ) 127 nResult = SID_EXPORTDOCASPDF; 128 else if ( nStoreMode == ( EXPORT_REQUESTED | PDFEXPORT_REQUESTED | PDFDIRECTEXPORT_REQUESTED ) ) 129 nResult = SID_DIRECTEXPORTDOCASPDF; 130 else if ( nStoreMode == SAVEAS_REQUESTED || nStoreMode == ( EXPORT_REQUESTED | WIDEEXPORT_REQUESTED ) ) 131 nResult = SID_SAVEASDOC; 132 else { 133 DBG_ASSERT( sal_False, "Unacceptable slot name is provided!\n" ); 134 } 135 136 return nResult; 137 } 138 139 //------------------------------------------------------------------------- 140 static sal_uInt8 getStoreModeFromSlotName( const ::rtl::OUString& aSlotName ) 141 { 142 sal_uInt8 nResult = 0; 143 if ( aSlotName.equalsAscii( "ExportTo" ) ) 144 nResult = EXPORT_REQUESTED; 145 else if ( aSlotName.equalsAscii( "ExportToPDF" ) ) 146 nResult = EXPORT_REQUESTED | PDFEXPORT_REQUESTED; 147 else if ( aSlotName.equalsAscii( "ExportDirectToPDF" ) ) 148 nResult = EXPORT_REQUESTED | PDFEXPORT_REQUESTED | PDFDIRECTEXPORT_REQUESTED; 149 else if ( aSlotName.equalsAscii( "Save" ) ) 150 nResult = SAVE_REQUESTED; 151 else if ( aSlotName.equalsAscii( "SaveAs" ) ) 152 nResult = SAVEAS_REQUESTED; 153 else 154 throw task::ErrorCodeIOException( ::rtl::OUString(), 155 uno::Reference< uno::XInterface >(), 156 ERRCODE_IO_INVALIDPARAMETER ); 157 158 return nResult; 159 } 160 161 //------------------------------------------------------------------------- 162 static sal_Int32 getMustFlags( sal_Int8 nStoreMode ) 163 { 164 return ( SFX_FILTER_EXPORT 165 | ( ( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) ) ? 0 : SFX_FILTER_IMPORT ) ); 166 } 167 168 //------------------------------------------------------------------------- 169 static sal_Int32 getDontFlags( sal_Int8 nStoreMode ) 170 { 171 return ( SFX_FILTER_INTERNAL 172 | SFX_FILTER_NOTINFILEDLG 173 | ( ( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) ) ? SFX_FILTER_IMPORT : 0 ) ); 174 } 175 176 //========================================================================= 177 // class DocumentSettingsGuard 178 //========================================================================= 179 180 class DocumentSettingsGuard 181 { 182 uno::Reference< beans::XPropertySet > m_xDocumentSettings; 183 sal_Bool m_bPreserveReadOnly; 184 sal_Bool m_bReadOnlySupported; 185 186 sal_Bool m_bRestoreSettings; 187 public: 188 DocumentSettingsGuard( const uno::Reference< frame::XModel >& xModel, sal_Bool bReadOnly, sal_Bool bRestore ) 189 : m_bPreserveReadOnly( sal_False ) 190 , m_bReadOnlySupported( sal_False ) 191 , m_bRestoreSettings( bRestore ) 192 { 193 try 194 { 195 uno::Reference< lang::XMultiServiceFactory > xDocSettingsSupplier( xModel, uno::UNO_QUERY_THROW ); 196 m_xDocumentSettings.set( 197 xDocSettingsSupplier->createInstance( 198 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.Settings" ) ) ), 199 uno::UNO_QUERY_THROW ); 200 201 ::rtl::OUString aLoadReadonlyString( RTL_CONSTASCII_USTRINGPARAM( "LoadReadonly" ) ); 202 203 try 204 { 205 m_xDocumentSettings->getPropertyValue( aLoadReadonlyString ) >>= m_bPreserveReadOnly; 206 m_xDocumentSettings->setPropertyValue( aLoadReadonlyString, uno::makeAny( bReadOnly ) ); 207 m_bReadOnlySupported = sal_True; 208 } 209 catch( uno::Exception& ) 210 {} 211 } 212 catch( uno::Exception& ) 213 {} 214 215 if ( ( bReadOnly && !m_bReadOnlySupported ) ) 216 throw uno::RuntimeException(); // the user could provide the data, so it must be stored 217 } 218 219 ~DocumentSettingsGuard() 220 { 221 if ( m_bRestoreSettings ) 222 { 223 ::rtl::OUString aLoadReadonlyString( RTL_CONSTASCII_USTRINGPARAM( "LoadReadonly" ) ); 224 225 try 226 { 227 if ( m_bReadOnlySupported ) 228 m_xDocumentSettings->setPropertyValue( aLoadReadonlyString, uno::makeAny( m_bPreserveReadOnly ) ); 229 } 230 catch( uno::Exception& ) 231 { 232 OSL_ASSERT( "Unexpected exception!" ); 233 } 234 } 235 } 236 }; 237 } // anonymous namespace 238 239 //========================================================================= 240 // class ModelData_Impl 241 //========================================================================= 242 class ModelData_Impl 243 { 244 SfxStoringHelper* m_pOwner; 245 uno::Reference< frame::XModel > m_xModel; 246 uno::Reference< frame::XStorable > m_xStorable; 247 uno::Reference< frame::XStorable2 > m_xStorable2; 248 uno::Reference< util::XModifiable > m_xModifiable; 249 250 ::rtl::OUString m_aModuleName; 251 ::comphelper::SequenceAsHashMap* m_pDocumentPropsHM; 252 ::comphelper::SequenceAsHashMap* m_pModulePropsHM; 253 254 ::comphelper::SequenceAsHashMap m_aMediaDescrHM; 255 256 sal_Bool m_bRecommendReadOnly; 257 258 public: 259 ModelData_Impl( SfxStoringHelper& aOwner, 260 const uno::Reference< frame::XModel >& xModel, 261 const uno::Sequence< beans::PropertyValue >& aMediaDescr ); 262 263 ~ModelData_Impl(); 264 265 void FreeDocumentProps(); 266 267 uno::Reference< frame::XModel > GetModel(); 268 uno::Reference< frame::XStorable > GetStorable(); 269 uno::Reference< frame::XStorable2 > GetStorable2(); 270 uno::Reference< util::XModifiable > GetModifiable(); 271 272 ::comphelper::SequenceAsHashMap& GetMediaDescr() { return m_aMediaDescrHM; } 273 274 sal_Bool IsRecommendReadOnly() { return m_bRecommendReadOnly; } 275 276 const ::comphelper::SequenceAsHashMap& GetDocProps(); 277 278 ::rtl::OUString GetModuleName(); 279 const ::comphelper::SequenceAsHashMap& GetModuleProps(); 280 281 void CheckInteractionHandler(); 282 283 284 ::rtl::OUString GetDocServiceName(); 285 uno::Sequence< beans::PropertyValue > GetDocServiceDefaultFilterCheckFlags( sal_Int32 nMust, sal_Int32 nDont ); 286 uno::Sequence< beans::PropertyValue > GetDocServiceAnyFilter( sal_Int32 nMust, sal_Int32 nDont ); 287 uno::Sequence< beans::PropertyValue > GetPreselectedFilter_Impl( sal_Int8 nStoreMode ); 288 uno::Sequence< beans::PropertyValue > GetDocServiceDefaultFilter(); 289 290 sal_Bool ExecuteFilterDialog_Impl( const ::rtl::OUString& aFilterName ); 291 292 sal_Int8 CheckSaveAcceptable( sal_Int8 nCurStatus ); 293 sal_Int8 CheckStateForSave(); 294 295 sal_Int8 CheckFilter( const ::rtl::OUString& ); 296 297 sal_Bool CheckFilterOptionsDialogExistence(); 298 299 sal_Bool OutputFileDialog( sal_Int8 nStoreMode, 300 const ::comphelper::SequenceAsHashMap& aPreselectedFilterPropsHM, 301 sal_Bool bSetStandardName, 302 ::rtl::OUString& aSuggestedName, 303 sal_Bool bPreselectPassword, 304 const ::rtl::OUString& aSuggestedDir, 305 sal_Int16 nDialog, 306 const ::rtl::OUString& rStandardDir, 307 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList 308 ); 309 310 sal_Bool ShowDocumentInfoDialog(); 311 312 ::rtl::OUString GetReccomendedDir( const ::rtl::OUString& aSuggestedDir, 313 const sfx2::FileDialogHelper::Context& aCtxt ); 314 ::rtl::OUString GetReccomendedName( const ::rtl::OUString& aSuggestedName, 315 const ::rtl::OUString& aTypeName ); 316 317 }; 318 319 //------------------------------------------------------------------------- 320 ModelData_Impl::ModelData_Impl( SfxStoringHelper& aOwner, 321 const uno::Reference< frame::XModel >& xModel, 322 const uno::Sequence< beans::PropertyValue >& aMediaDescr ) 323 : m_pOwner( &aOwner ) 324 , m_xModel( xModel ) 325 , m_pDocumentPropsHM( NULL ) 326 , m_pModulePropsHM( NULL ) 327 , m_aMediaDescrHM( aMediaDescr ) 328 , m_bRecommendReadOnly( sal_False ) 329 { 330 CheckInteractionHandler(); 331 } 332 333 //------------------------------------------------------------------------- 334 ModelData_Impl::~ModelData_Impl() 335 { 336 FreeDocumentProps(); 337 if ( m_pDocumentPropsHM ) 338 delete m_pDocumentPropsHM; 339 340 if ( m_pModulePropsHM ) 341 delete m_pModulePropsHM; 342 } 343 344 //------------------------------------------------------------------------- 345 void ModelData_Impl::FreeDocumentProps() 346 { 347 if ( m_pDocumentPropsHM ) 348 { 349 delete m_pDocumentPropsHM; 350 m_pDocumentPropsHM = NULL; 351 } 352 } 353 354 //------------------------------------------------------------------------- 355 uno::Reference< frame::XModel > ModelData_Impl::GetModel() 356 { 357 if ( !m_xModel.is() ) 358 throw uno::RuntimeException(); 359 360 return m_xModel; 361 } 362 363 //------------------------------------------------------------------------- 364 uno::Reference< frame::XStorable > ModelData_Impl::GetStorable() 365 { 366 if ( !m_xStorable.is() ) 367 { 368 m_xStorable = uno::Reference< frame::XStorable >( m_xModel, uno::UNO_QUERY ); 369 if ( !m_xStorable.is() ) 370 throw uno::RuntimeException(); 371 } 372 373 return m_xStorable; 374 } 375 376 //------------------------------------------------------------------------- 377 uno::Reference< frame::XStorable2 > ModelData_Impl::GetStorable2() 378 { 379 if ( !m_xStorable2.is() ) 380 { 381 m_xStorable2 = uno::Reference< frame::XStorable2 >( m_xModel, uno::UNO_QUERY ); 382 if ( !m_xStorable2.is() ) 383 throw uno::RuntimeException(); 384 } 385 386 return m_xStorable2; 387 } 388 389 //------------------------------------------------------------------------- 390 uno::Reference< util::XModifiable > ModelData_Impl::GetModifiable() 391 { 392 if ( !m_xModifiable.is() ) 393 { 394 m_xModifiable = uno::Reference< util::XModifiable >( m_xModel, uno::UNO_QUERY ); 395 if ( !m_xModifiable.is() ) 396 throw uno::RuntimeException(); 397 } 398 399 return m_xModifiable; 400 } 401 402 //------------------------------------------------------------------------- 403 const ::comphelper::SequenceAsHashMap& ModelData_Impl::GetDocProps() 404 { 405 if ( !m_pDocumentPropsHM ) 406 m_pDocumentPropsHM = new ::comphelper::SequenceAsHashMap( GetModel()->getArgs() ); 407 408 return *m_pDocumentPropsHM; 409 } 410 411 //------------------------------------------------------------------------- 412 ::rtl::OUString ModelData_Impl::GetModuleName() 413 { 414 if ( !m_aModuleName.getLength() ) 415 { 416 m_aModuleName = m_pOwner->GetModuleManager()->identify( 417 uno::Reference< uno::XInterface >( m_xModel, uno::UNO_QUERY ) ); 418 if ( !m_aModuleName.getLength() ) 419 throw uno::RuntimeException(); // TODO: 420 } 421 return m_aModuleName; 422 } 423 424 //------------------------------------------------------------------------- 425 const ::comphelper::SequenceAsHashMap& ModelData_Impl::GetModuleProps() 426 { 427 if ( !m_pModulePropsHM ) 428 { 429 uno::Sequence< beans::PropertyValue > aModuleProps; 430 m_pOwner->GetNamedModuleManager()->getByName( GetModuleName() ) >>= aModuleProps; 431 if ( !aModuleProps.getLength() ) 432 throw uno::RuntimeException(); // TODO; 433 m_pModulePropsHM = new ::comphelper::SequenceAsHashMap( aModuleProps ); 434 } 435 436 return *m_pModulePropsHM; 437 } 438 439 //------------------------------------------------------------------------- 440 ::rtl::OUString ModelData_Impl::GetDocServiceName() 441 { 442 return GetModuleProps().getUnpackedValueOrDefault(::rtl::OUString::createFromAscii( "ooSetupFactoryDocumentService" ), ::rtl::OUString()); 443 } 444 445 //------------------------------------------------------------------------- 446 void ModelData_Impl::CheckInteractionHandler() 447 { 448 ::comphelper::SequenceAsHashMap::const_iterator aInteractIter = 449 m_aMediaDescrHM.find( ::rtl::OUString::createFromAscii( "InteractionHandler" ) ); 450 451 if ( aInteractIter == m_aMediaDescrHM.end() ) 452 { 453 try { 454 m_aMediaDescrHM[ ::rtl::OUString::createFromAscii( "InteractionHandler" ) ] 455 <<= uno::Reference< task::XInteractionHandler >( 456 m_pOwner->GetServiceFactory()->createInstance( 457 DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), 458 uno::UNO_QUERY ); 459 } 460 catch( uno::Exception& ) 461 { 462 } 463 } 464 else 465 { 466 uno::Reference< task::XInteractionHandler > xInteract; 467 DBG_ASSERT( ( aInteractIter->second >>= xInteract ) && xInteract.is(), "Broken interaction handler is provided!\n" ); 468 } 469 } 470 471 //------------------------------------------------------------------------- 472 uno::Sequence< beans::PropertyValue > ModelData_Impl::GetDocServiceDefaultFilter() 473 { 474 uno::Sequence< beans::PropertyValue > aProps; 475 476 ::rtl::OUString aFilterName = GetModuleProps().getUnpackedValueOrDefault( 477 ::rtl::OUString::createFromAscii( "ooSetupFactoryDefaultFilter" ), 478 ::rtl::OUString() ); 479 480 m_pOwner->GetFilterConfiguration()->getByName( aFilterName ) >>= aProps; 481 482 return aProps; 483 } 484 485 //------------------------------------------------------------------------- 486 uno::Sequence< beans::PropertyValue > ModelData_Impl::GetDocServiceDefaultFilterCheckFlags( sal_Int32 nMust, 487 sal_Int32 nDont ) 488 { 489 uno::Sequence< beans::PropertyValue > aFilterProps; 490 uno::Sequence< beans::PropertyValue > aProps = GetDocServiceDefaultFilter(); 491 if ( aProps.getLength() ) 492 { 493 ::comphelper::SequenceAsHashMap aFiltHM( aProps ); 494 sal_Int32 nFlags = aFiltHM.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "Flags" ), 495 (sal_Int32)0 ); 496 if ( ( ( nFlags & nMust ) == nMust ) && !( nFlags & nDont ) ) 497 aFilterProps = aProps; 498 } 499 500 return aFilterProps; 501 } 502 503 504 //------------------------------------------------------------------------- 505 uno::Sequence< beans::PropertyValue > ModelData_Impl::GetDocServiceAnyFilter( sal_Int32 nMust, sal_Int32 nDont ) 506 { 507 uno::Sequence< beans::NamedValue > aSearchRequest( 1 ); 508 aSearchRequest[0].Name = ::rtl::OUString::createFromAscii( "DocumentService" ); 509 aSearchRequest[0].Value <<= GetDocServiceName(); 510 511 return ::comphelper::MimeConfigurationHelper::SearchForFilter( m_pOwner->GetFilterQuery(), aSearchRequest, nMust, nDont ); 512 } 513 514 //------------------------------------------------------------------------- 515 uno::Sequence< beans::PropertyValue > ModelData_Impl::GetPreselectedFilter_Impl( sal_Int8 nStoreMode ) 516 { 517 uno::Sequence< beans::PropertyValue > aFilterProps; 518 519 sal_Int32 nMust = getMustFlags( nStoreMode ); 520 sal_Int32 nDont = getDontFlags( nStoreMode ); 521 522 if ( nStoreMode & PDFEXPORT_REQUESTED ) 523 { 524 // Preselect PDF-Filter for EXPORT 525 uno::Sequence< beans::NamedValue > aSearchRequest( 2 ); 526 aSearchRequest[0].Name = ::rtl::OUString::createFromAscii( "Type" ); 527 aSearchRequest[0].Value <<= ::rtl::OUString::createFromAscii( "pdf_Portable_Document_Format" ); 528 aSearchRequest[1].Name = ::rtl::OUString::createFromAscii( "DocumentService" ); 529 aSearchRequest[1].Value <<= GetDocServiceName(); 530 531 aFilterProps = ::comphelper::MimeConfigurationHelper::SearchForFilter( m_pOwner->GetFilterQuery(), aSearchRequest, nMust, nDont ); 532 } 533 else 534 { 535 aFilterProps = GetDocServiceDefaultFilterCheckFlags( nMust, nDont ); 536 537 if ( !aFilterProps.getLength() ) 538 { 539 // the default filter was not faund, use just the first acceptable one 540 aFilterProps = GetDocServiceAnyFilter( nMust, nDont ); 541 } 542 } 543 544 return aFilterProps; 545 } 546 547 //------------------------------------------------------------------------- 548 sal_Bool ModelData_Impl::ExecuteFilterDialog_Impl( const ::rtl::OUString& aFilterName ) 549 { 550 sal_Bool bDialogUsed = sal_False; 551 552 try { 553 uno::Sequence < beans::PropertyValue > aProps; 554 uno::Any aAny = m_pOwner->GetFilterConfiguration()->getByName( aFilterName ); 555 if ( aAny >>= aProps ) 556 { 557 sal_Int32 nPropertyCount = aProps.getLength(); 558 for( sal_Int32 nProperty=0; nProperty < nPropertyCount; ++nProperty ) 559 if( aProps[nProperty].Name.equals( ::rtl::OUString::createFromAscii("UIComponent")) ) 560 { 561 ::rtl::OUString aServiceName; 562 aProps[nProperty].Value >>= aServiceName; 563 if( aServiceName.getLength() ) 564 { 565 uno::Reference< ui::dialogs::XExecutableDialog > xFilterDialog( 566 m_pOwner->GetServiceFactory()->createInstance( aServiceName ), uno::UNO_QUERY ); 567 uno::Reference< beans::XPropertyAccess > xFilterProperties( xFilterDialog, uno::UNO_QUERY ); 568 569 if( xFilterDialog.is() && xFilterProperties.is() ) 570 { 571 bDialogUsed = sal_True; 572 573 uno::Reference< document::XExporter > xExporter( xFilterDialog, uno::UNO_QUERY ); 574 if( xExporter.is() ) 575 xExporter->setSourceDocument( 576 uno::Reference< lang::XComponent >( GetModel(), uno::UNO_QUERY ) ); 577 578 uno::Sequence< beans::PropertyValue > aPropsForDialog; 579 GetMediaDescr() >> aPropsForDialog; 580 xFilterProperties->setPropertyValues( aPropsForDialog ); 581 582 if( xFilterDialog->execute() ) 583 { 584 uno::Sequence< beans::PropertyValue > aPropsFromDialog = 585 xFilterProperties->getPropertyValues(); 586 for ( sal_Int32 nInd = 0; nInd < aPropsFromDialog.getLength(); nInd++ ) 587 GetMediaDescr()[aPropsFromDialog[nInd].Name] = aPropsFromDialog[nInd].Value; 588 } 589 else 590 { 591 throw task::ErrorCodeIOException( ::rtl::OUString(), 592 uno::Reference< uno::XInterface >(), 593 ERRCODE_IO_ABORT ); 594 } 595 } 596 } 597 598 break; 599 } 600 } 601 } 602 catch( container::NoSuchElementException& ) 603 { 604 // the filter name is unknown 605 throw task::ErrorCodeIOException( ::rtl::OUString(), 606 uno::Reference< uno::XInterface >(), 607 ERRCODE_IO_INVALIDPARAMETER ); 608 } 609 catch( task::ErrorCodeIOException& ) 610 { 611 throw; 612 } 613 catch( uno::Exception& ) 614 { 615 } 616 617 return bDialogUsed; 618 } 619 620 //------------------------------------------------------------------------- 621 sal_Int8 ModelData_Impl::CheckSaveAcceptable( sal_Int8 nCurStatus ) 622 { 623 sal_Int8 nResult = nCurStatus; 624 625 if ( nResult != STATUS_NO_ACTION && GetStorable()->hasLocation() ) 626 { 627 // check whether save is acceptable by the configuration 628 // it is done only for documents that have persistence already 629 uno::Reference< uno::XInterface > xCommonConfig = ::comphelper::ConfigurationHelper::openConfig( 630 m_pOwner->GetServiceFactory(), 631 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ), 632 ::comphelper::ConfigurationHelper::E_STANDARD ); 633 if ( !xCommonConfig.is() ) 634 throw uno::RuntimeException(); // should the saving proceed as usual instead? 635 636 try 637 { 638 sal_Bool bAlwaysSaveAs = sal_False; 639 640 // the saving is acceptable 641 // in case the configuration entry is not set or set to false 642 // or in case of version creation 643 ::rtl::OUString aVersionCommentString = ::rtl::OUString::createFromAscii( "VersionComment" ); 644 if ( ( ::comphelper::ConfigurationHelper::readRelativeKey( 645 xCommonConfig, 646 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Save/Document/" ) ), 647 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AlwaysSaveAs" ) ) ) >>= bAlwaysSaveAs ) 648 && bAlwaysSaveAs 649 && GetMediaDescr().find( aVersionCommentString ) == GetMediaDescr().end() ) 650 { 651 // notify the user that SaveAs is going to be done 652 String aString( SfxResId( STR_NEW_FILENAME_SAVE ) ); 653 Window* pWin = SfxStoringHelper::GetModelWindow( m_xModel ); 654 QueryBox aMessageBox( pWin, WB_OK_CANCEL | WB_DEF_OK, aString ); 655 if ( aMessageBox.Execute() == RET_OK ) 656 nResult = STATUS_SAVEAS; 657 else 658 nResult = STATUS_NO_ACTION; 659 } 660 } 661 catch( uno::Exception& ) 662 { 663 // impossibility to get the configuration access means normal saving flow for now 664 } 665 } 666 667 return nResult; 668 } 669 670 //------------------------------------------------------------------------- 671 sal_Int8 ModelData_Impl::CheckStateForSave() 672 { 673 // if the document is readonly or a new one a SaveAs operation must be used 674 if ( !GetStorable()->hasLocation() || GetStorable()->isReadonly() ) 675 return STATUS_SAVEAS; 676 677 // check acceptable entries for media descriptor 678 sal_Bool bVersInfoNeedsStore = sal_False; 679 ::comphelper::SequenceAsHashMap aAcceptedArgs; 680 681 ::rtl::OUString aVersionCommentString = ::rtl::OUString::createFromAscii( "VersionComment" ); 682 ::rtl::OUString aAuthorString = ::rtl::OUString::createFromAscii( "Author" ); 683 ::rtl::OUString aInteractionHandlerString = ::rtl::OUString::createFromAscii( "InteractionHandler" ); 684 ::rtl::OUString aStatusIndicatorString = ::rtl::OUString::createFromAscii( "StatusIndicator" ); 685 686 if ( GetMediaDescr().find( aVersionCommentString ) != GetMediaDescr().end() ) 687 { 688 bVersInfoNeedsStore = sal_True; 689 aAcceptedArgs[ aVersionCommentString ] = GetMediaDescr()[ aVersionCommentString ]; 690 } 691 if ( GetMediaDescr().find( aAuthorString ) != GetMediaDescr().end() ) 692 aAcceptedArgs[ aAuthorString ] = GetMediaDescr()[ aAuthorString ]; 693 if ( GetMediaDescr().find( aInteractionHandlerString ) != GetMediaDescr().end() ) 694 aAcceptedArgs[ aInteractionHandlerString ] = GetMediaDescr()[ aInteractionHandlerString ]; 695 if ( GetMediaDescr().find( aStatusIndicatorString ) != GetMediaDescr().end() ) 696 aAcceptedArgs[ aStatusIndicatorString ] = GetMediaDescr()[ aStatusIndicatorString ]; 697 698 // remove unacceptable entry if there is any 699 DBG_ASSERT( GetMediaDescr().size() == aAcceptedArgs.size(), 700 "Unacceptable parameters are provided in Save request!\n" ); 701 if ( GetMediaDescr().size() != aAcceptedArgs.size() ) 702 GetMediaDescr() = aAcceptedArgs; 703 704 // the document must be modified 705 if ( !GetModifiable()->isModified() && !bVersInfoNeedsStore ) 706 return STATUS_NO_ACTION; 707 708 // check that the old filter is acceptable 709 ::rtl::OUString aOldFilterName = GetDocProps().getUnpackedValueOrDefault( 710 aFilterNameString, 711 ::rtl::OUString() ); 712 sal_Int8 nResult = CheckFilter( aOldFilterName ); 713 714 return nResult; 715 } 716 717 sal_Int8 ModelData_Impl::CheckFilter( const ::rtl::OUString& aFilterName ) 718 { 719 ::comphelper::SequenceAsHashMap aFiltPropsHM; 720 sal_Int32 nFiltFlags = 0; 721 if ( aFilterName.getLength() ) 722 { 723 // get properties of filter 724 uno::Sequence< beans::PropertyValue > aFilterProps; 725 if ( aFilterName.getLength() ) 726 m_pOwner->GetFilterConfiguration()->getByName( aFilterName ) >>= aFilterProps; 727 728 aFiltPropsHM = ::comphelper::SequenceAsHashMap( aFilterProps ); 729 nFiltFlags = aFiltPropsHM.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "Flags" ), (sal_Int32)0 ); 730 } 731 732 // only a temporary solution until default filter retrieving feature is implemented 733 // then GetDocServiceDefaultFilter() must be used 734 ::comphelper::SequenceAsHashMap aDefFiltPropsHM = GetDocServiceDefaultFilterCheckFlags( 3, 0 ); 735 sal_Int32 nDefFiltFlags = aDefFiltPropsHM.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "Flags" ), (sal_Int32)0 ); 736 737 // if the old filter is not acceptable 738 // and there is no default filter or it is not acceptable for requested parameters then proceed with saveAs 739 if ( ( !aFiltPropsHM.size() || !( nFiltFlags & SFX_FILTER_EXPORT ) ) 740 && ( !aDefFiltPropsHM.size() || !( nDefFiltFlags & SFX_FILTER_EXPORT ) || nDefFiltFlags & SFX_FILTER_INTERNAL ) ) 741 return STATUS_SAVEAS; 742 743 // so at this point there is either an acceptable old filter or default one 744 if ( !aFiltPropsHM.size() || !( nFiltFlags & SFX_FILTER_EXPORT ) ) 745 { 746 // so the default filter must be acceptable 747 return STATUS_SAVEAS_STANDARDNAME; 748 } 749 else if ( ( !( nFiltFlags & SFX_FILTER_OWN ) || ( nFiltFlags & SFX_FILTER_ALIEN ) ) 750 && aDefFiltPropsHM.size() 751 && ( nDefFiltFlags & SFX_FILTER_EXPORT ) && !( nDefFiltFlags & SFX_FILTER_INTERNAL )) 752 { 753 // the default filter is acceptable and the old filter is alian one 754 // so ask to make a saveAs operation 755 ::rtl::OUString aUIName = aFiltPropsHM.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "UIName" ), 756 ::rtl::OUString() ); 757 ::rtl::OUString aDefUIName = aDefFiltPropsHM.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "UIName" ), 758 ::rtl::OUString() ); 759 ::rtl::OUString aPreusedFilterName = GetDocProps().getUnpackedValueOrDefault( 760 ::rtl::OUString::createFromAscii( "PreusedFilterName" ), 761 ::rtl::OUString() ); 762 if ( !aPreusedFilterName.equals( aFilterName ) && !aUIName.equals( aDefUIName ) ) 763 { 764 if ( !SfxStoringHelper::WarnUnacceptableFormat( GetModel(), aUIName, aDefUIName, sal_True ) ) 765 return STATUS_SAVEAS_STANDARDNAME; 766 } 767 } 768 769 return STATUS_SAVE; 770 } 771 772 //------------------------------------------------------------------------- 773 sal_Bool ModelData_Impl::CheckFilterOptionsDialogExistence() 774 { 775 uno::Sequence< beans::NamedValue > aSearchRequest( 1 ); 776 aSearchRequest[0].Name = ::rtl::OUString::createFromAscii( "DocumentService" ); 777 aSearchRequest[0].Value <<= GetDocServiceName(); 778 779 uno::Reference< container::XEnumeration > xFilterEnum = 780 m_pOwner->GetFilterQuery()->createSubSetEnumerationByProperties( aSearchRequest ); 781 782 while ( xFilterEnum->hasMoreElements() ) 783 { 784 uno::Sequence< beans::PropertyValue > pProps; 785 if ( xFilterEnum->nextElement() >>= pProps ) 786 { 787 ::comphelper::SequenceAsHashMap aPropsHM( pProps ); 788 ::rtl::OUString aUIServName = aPropsHM.getUnpackedValueOrDefault( 789 ::rtl::OUString::createFromAscii( "UIComponent" ), 790 ::rtl::OUString() ); 791 if ( aUIServName.getLength() ) 792 return sal_True; 793 } 794 } 795 796 return sal_False; 797 } 798 799 //------------------------------------------------------------------------- 800 sal_Bool ModelData_Impl::OutputFileDialog( sal_Int8 nStoreMode, 801 const ::comphelper::SequenceAsHashMap& aPreselectedFilterPropsHM, 802 sal_Bool bSetStandardName, 803 ::rtl::OUString& aSuggestedName, 804 sal_Bool bPreselectPassword, 805 const ::rtl::OUString& aSuggestedDir, 806 sal_Int16 nDialog, 807 const ::rtl::OUString& rStandardDir, 808 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList) 809 { 810 sal_Bool bUseFilterOptions = sal_False; 811 812 ::comphelper::SequenceAsHashMap::const_iterator aOverwriteIter = 813 GetMediaDescr().find( ::rtl::OUString::createFromAscii( "Overwrite" ) ); 814 815 // the file name must be specified if overwrite option is set 816 if ( aOverwriteIter != GetMediaDescr().end() ) 817 throw task::ErrorCodeIOException( ::rtl::OUString(), 818 uno::Reference< uno::XInterface >(), 819 ERRCODE_IO_INVALIDPARAMETER ); 820 821 // no target file name is specified 822 // we need to show the file dialog 823 824 // check if we have a filter which allows for filter options, so we need a corresponding checkbox in the dialog 825 sal_Bool bAllowOptions = sal_False; 826 827 // in case of Export, filter options dialog is used if available 828 if( !( nStoreMode & EXPORT_REQUESTED ) || ( nStoreMode & WIDEEXPORT_REQUESTED ) ) 829 bAllowOptions = CheckFilterOptionsDialogExistence(); 830 831 // get the filename by dialog ... 832 // create the file dialog 833 sal_Int16 aDialogMode = bAllowOptions 834 ? (com::sun::star::ui::dialogs::TemplateDescription:: 835 FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS) 836 : (com::sun::star::ui::dialogs::TemplateDescription:: 837 FILESAVE_AUTOEXTENSION_PASSWORD); 838 sal_Int64 aDialogFlags = 0; 839 840 if( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) ) 841 { 842 if ( nStoreMode & PDFEXPORT_REQUESTED ) 843 aDialogMode = com::sun::star::ui::dialogs::TemplateDescription:: 844 FILESAVE_AUTOEXTENSION; 845 else 846 aDialogMode = com::sun::star::ui::dialogs::TemplateDescription:: 847 FILESAVE_AUTOEXTENSION_SELECTION; 848 aDialogFlags = SFXWB_EXPORT; 849 } 850 851 sfx2::FileDialogHelper* pFileDlg = NULL; 852 853 ::rtl::OUString aDocServiceName = GetDocServiceName(); 854 DBG_ASSERT( aDocServiceName.getLength(), "No document service for this module set!" ); 855 856 sal_Int32 nMust = getMustFlags( nStoreMode ); 857 sal_Int32 nDont = getDontFlags( nStoreMode ); 858 sfx2::FileDialogHelper::Context eCtxt = sfx2::FileDialogHelper::UNKNOWN_CONTEXT; 859 860 if ( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) ) 861 { 862 if ( ( nStoreMode & PDFEXPORT_REQUESTED ) && aPreselectedFilterPropsHM.size() ) 863 { 864 // this is a PDF export 865 // the filter options has been shown already 866 ::rtl::OUString aFilterUIName = aPreselectedFilterPropsHM.getUnpackedValueOrDefault( 867 ::rtl::OUString::createFromAscii( "UIName" ), 868 ::rtl::OUString() ); 869 870 pFileDlg = new sfx2::FileDialogHelper( aDialogMode, aDialogFlags, aFilterUIName, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "pdf" ) ), rStandardDir, rBlackList ); 871 pFileDlg->SetCurrentFilter( aFilterUIName ); 872 } 873 else 874 { 875 // This is the normal dialog 876 pFileDlg = new sfx2::FileDialogHelper( aDialogMode, aDialogFlags, aDocServiceName, nDialog, nMust, nDont, rStandardDir, rBlackList ); 877 } 878 879 if( aDocServiceName.equalsAscii( "com.sun.star.drawing.DrawingDocument" ) ) 880 eCtxt = sfx2::FileDialogHelper::SD_EXPORT; 881 if( aDocServiceName.equalsAscii( "com.sun.star.presentation.PresentationDocument" ) ) 882 eCtxt = sfx2::FileDialogHelper::SI_EXPORT; 883 if( aDocServiceName.equalsAscii( "com.sun.star.text.TextDocument" ) ) 884 eCtxt = sfx2::FileDialogHelper::SW_EXPORT; 885 886 if ( eCtxt != sfx2::FileDialogHelper::UNKNOWN_CONTEXT ) 887 pFileDlg->SetContext( eCtxt ); 888 889 pFileDlg->CreateMatcher( aDocServiceName ); 890 891 uno::Reference< ui::dialogs::XFilePicker > xFilePicker = pFileDlg->GetFilePicker(); 892 uno::Reference< ui::dialogs::XFilePickerControlAccess > xControlAccess = 893 uno::Reference< ui::dialogs::XFilePickerControlAccess >( xFilePicker, uno::UNO_QUERY ); 894 895 if ( xControlAccess.is() ) 896 { 897 ::rtl::OUString aCtrlText = String( SfxResId( STR_EXPORTBUTTON ) ); 898 xControlAccess->setLabel( ui::dialogs::CommonFilePickerElementIds::PUSHBUTTON_OK, aCtrlText ); 899 900 aCtrlText = ::rtl::OUString( String( SfxResId( STR_LABEL_FILEFORMAT ) ) ); 901 xControlAccess->setLabel( ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER_LABEL, aCtrlText ); 902 } 903 } 904 else 905 { 906 // This is the normal dialog 907 pFileDlg = new sfx2::FileDialogHelper( aDialogMode, aDialogFlags, aDocServiceName, nDialog, nMust, nDont, rStandardDir, rBlackList ); 908 pFileDlg->CreateMatcher( aDocServiceName ); 909 } 910 911 ::rtl::OUString aAdjustToType; 912 913 if ( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) ) 914 { 915 // it is export, set the preselected filter 916 ::rtl::OUString aFilterUIName = aPreselectedFilterPropsHM.getUnpackedValueOrDefault( 917 ::rtl::OUString::createFromAscii( "UIName" ), 918 ::rtl::OUString() ); 919 pFileDlg->SetCurrentFilter( aFilterUIName ); 920 } 921 // it is no export, bSetStandardName == true means that user agreed to store document in the default (default default ;-)) format 922 else if ( bSetStandardName || GetStorable()->hasLocation() ) 923 { 924 uno::Sequence< beans::PropertyValue > aOldFilterProps; 925 ::rtl::OUString aOldFilterName = GetDocProps().getUnpackedValueOrDefault( 926 aFilterNameString, 927 ::rtl::OUString() ); 928 929 if ( aOldFilterName.getLength() ) 930 m_pOwner->GetFilterConfiguration()->getByName( aOldFilterName ) >>= aOldFilterProps; 931 932 ::comphelper::SequenceAsHashMap aOldFiltPropsHM( aOldFilterProps ); 933 sal_Int32 nOldFiltFlags = aOldFiltPropsHM.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "Flags" ), (sal_Int32)0 ); 934 935 if ( bSetStandardName || ( nOldFiltFlags & nMust ) != nMust || nOldFiltFlags & nDont ) 936 { 937 // the suggested type will be changed, the extension should be adjusted 938 aAdjustToType = aPreselectedFilterPropsHM.getUnpackedValueOrDefault( 939 ::rtl::OUString::createFromAscii( "Type" ), 940 ::rtl::OUString() ); 941 942 ::rtl::OUString aFilterUIName = aPreselectedFilterPropsHM.getUnpackedValueOrDefault( 943 ::rtl::OUString::createFromAscii( "UIName" ), 944 ::rtl::OUString() ); 945 pFileDlg->SetCurrentFilter( aFilterUIName ); 946 } 947 else 948 { 949 pFileDlg->SetCurrentFilter( aOldFiltPropsHM.getUnpackedValueOrDefault( 950 ::rtl::OUString::createFromAscii( "UIName" ), 951 ::rtl::OUString() ) ); 952 } 953 } 954 955 ::rtl::OUString aReccomendedDir = GetReccomendedDir( aSuggestedDir, eCtxt ); 956 if ( aReccomendedDir.getLength() ) 957 pFileDlg->SetDisplayDirectory( aReccomendedDir ); 958 ::rtl::OUString aReccomendedName = GetReccomendedName( aSuggestedName, aAdjustToType ); 959 if ( aReccomendedName.getLength() ) 960 pFileDlg->SetFileName( aReccomendedName ); 961 962 uno::Reference < view::XSelectionSupplier > xSel( GetModel()->getCurrentController(), uno::UNO_QUERY ); 963 if ( xSel.is() && xSel->getSelection().hasValue() ) 964 GetMediaDescr()[::rtl::OUString::createFromAscii( "SelectionOnly" )] <<= sal_True; 965 966 // This is a temporary hardcoded solution must be removed when 967 // dialogs do not need parameters in SidSet representation any more 968 sal_uInt16 nSlotID = getSlotIDFromMode( nStoreMode ); 969 if ( !nSlotID ) 970 throw lang::IllegalArgumentException(); // TODO: 971 972 // generate SidSet from MediaDescriptor and provide it into FileDialog 973 // than merge changed SidSet back 974 SfxAllItemSet aDialogParams( SFX_APP()->GetPool() ); 975 SfxItemSet* pDialogParams = &aDialogParams; 976 TransformParameters( nSlotID, 977 GetMediaDescr().getAsConstPropertyValueList(), 978 aDialogParams, 979 NULL ); 980 981 const SfxPoolItem* pItem = NULL; 982 if ( bPreselectPassword && aDialogParams.GetItemState( SID_ENCRYPTIONDATA, sal_True, &pItem ) != SFX_ITEM_SET ) 983 { 984 // the file dialog preselects the password checkbox if the provided mediadescriptor has encryption data entry 985 // after dialog execution the password interaction flag will be either removed or not 986 aDialogParams.Put( SfxBoolItem( SID_PASSWORDINTERACTION, sal_True ) ); 987 } 988 989 // aStringTypeFN is a pure output parameter, pDialogParams is an in/out parameter 990 String aStringTypeFN; 991 if ( pFileDlg->Execute( pDialogParams, aStringTypeFN ) != ERRCODE_NONE ) 992 { 993 delete pFileDlg; 994 throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT ); 995 } 996 997 ::rtl::OUString aFilterName = aStringTypeFN; 998 999 // the following two arguments can not be converted in MediaDescriptor, 1000 // so they should be removed from the ItemSet after retrieving 1001 SFX_ITEMSET_ARG( pDialogParams, pRecommendReadOnly, SfxBoolItem, SID_RECOMMENDREADONLY, sal_False ); 1002 m_bRecommendReadOnly = ( pRecommendReadOnly && pRecommendReadOnly->GetValue() ); 1003 pDialogParams->ClearItem( SID_RECOMMENDREADONLY ); 1004 1005 uno::Sequence< beans::PropertyValue > aPropsFromDialog; 1006 TransformItems( nSlotID, *pDialogParams, aPropsFromDialog, NULL ); 1007 GetMediaDescr() << aPropsFromDialog; 1008 1009 // get the path from the dialog 1010 INetURLObject aURL( pFileDlg->GetPath() ); 1011 // the path should be provided outside since it might be used for further calls to the dialog 1012 aSuggestedName = aURL.GetName( INetURLObject::DECODE_WITH_CHARSET ); 1013 1014 // old filter options should be cleared in case different filter is used 1015 1016 ::rtl::OUString aFilterFromMediaDescr = GetMediaDescr().getUnpackedValueOrDefault( 1017 aFilterNameString, 1018 ::rtl::OUString() ); 1019 ::rtl::OUString aOldFilterName = GetDocProps().getUnpackedValueOrDefault( 1020 aFilterNameString, 1021 ::rtl::OUString() ); 1022 if ( aFilterName.equals( aFilterFromMediaDescr ) ) 1023 { 1024 // preserv current settings if any 1025 // if there no current settings and the name is the same 1026 // as old filter name use old filter settings 1027 1028 if ( aFilterFromMediaDescr.equals( aOldFilterName ) ) 1029 { 1030 ::comphelper::SequenceAsHashMap::const_iterator aIter = 1031 GetDocProps().find( aFilterOptionsString ); 1032 if ( aIter != GetDocProps().end() 1033 && GetMediaDescr().find( aFilterOptionsString ) == GetMediaDescr().end() ) 1034 GetMediaDescr()[aIter->first] = aIter->second; 1035 1036 aIter = GetDocProps().find( aFilterDataString ); 1037 if ( aIter != GetDocProps().end() 1038 && GetMediaDescr().find( aFilterDataString ) == GetMediaDescr().end() ) 1039 GetMediaDescr()[aIter->first] = aIter->second; 1040 } 1041 } 1042 else 1043 { 1044 GetMediaDescr().erase( aFilterDataString ); 1045 GetMediaDescr().erase( aFilterOptionsString ); 1046 1047 if ( aFilterName.equals( aOldFilterName ) ) 1048 { 1049 // merge filter option of the document filter 1050 1051 ::comphelper::SequenceAsHashMap::const_iterator aIter = 1052 GetDocProps().find( aFilterOptionsString ); 1053 if ( aIter != GetDocProps().end() ) 1054 GetMediaDescr()[aIter->first] = aIter->second; 1055 1056 aIter = GetDocProps().find( aFilterDataString ); 1057 if ( aIter != GetDocProps().end() ) 1058 GetMediaDescr()[aIter->first] = aIter->second; 1059 } 1060 } 1061 1062 uno::Reference< ui::dialogs::XFilePickerControlAccess > xExtFileDlg( pFileDlg->GetFilePicker(), uno::UNO_QUERY ); 1063 if ( xExtFileDlg.is() ) 1064 { 1065 if ( SfxStoringHelper::CheckFilterOptionsAppearence( m_pOwner->GetFilterConfiguration(), aFilterName ) ) 1066 bUseFilterOptions = sal_True; 1067 1068 if ( ( !( nStoreMode & EXPORT_REQUESTED ) || ( nStoreMode & WIDEEXPORT_REQUESTED ) ) && bUseFilterOptions ) 1069 { 1070 try 1071 { 1072 // for exporters: always show dialog if format uses options 1073 // for save: show dialog if format uses options and no options given or if forced by user 1074 uno::Any aVal = 1075 xExtFileDlg->getValue( ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS, 0 ); 1076 1077 aVal >>= bUseFilterOptions; 1078 if ( !bUseFilterOptions ) 1079 bUseFilterOptions = 1080 ( GetMediaDescr().find( aFilterDataString ) == GetMediaDescr().end() 1081 && GetMediaDescr().find( aFilterOptionsString ) == GetMediaDescr().end() ); 1082 } 1083 catch( lang::IllegalArgumentException& ) 1084 {} 1085 } 1086 } 1087 1088 delete pFileDlg; 1089 1090 // merge in results of the dialog execution 1091 GetMediaDescr()[::rtl::OUString::createFromAscii( "URL" )] <<= 1092 ::rtl::OUString( aURL.GetMainURL( INetURLObject::NO_DECODE )); 1093 GetMediaDescr()[aFilterNameString] <<= aFilterName; 1094 1095 return bUseFilterOptions; 1096 } 1097 1098 //------------------------------------------------------------------------- 1099 sal_Bool ModelData_Impl::ShowDocumentInfoDialog() 1100 { 1101 sal_Bool bDialogUsed = sal_False; 1102 1103 try { 1104 uno::Reference< frame::XController > xController = GetModel()->getCurrentController(); 1105 if ( xController.is() ) 1106 { 1107 uno::Reference< frame::XDispatchProvider > xFrameDispatch( xController->getFrame(), uno::UNO_QUERY ); 1108 if ( xFrameDispatch.is() ) 1109 { 1110 util::URL aURL; 1111 aURL.Complete = ::rtl::OUString::createFromAscii( ".uno:SetDocumentProperties" ); 1112 1113 uno::Reference< util::XURLTransformer > xTransformer( 1114 m_pOwner->GetServiceFactory()->createInstance( 1115 DEFINE_CONST_UNICODE("com.sun.star.util.URLTransformer") ), 1116 uno::UNO_QUERY ); 1117 if ( xTransformer.is() && xTransformer->parseStrict( aURL ) ) 1118 { 1119 uno::Reference< frame::XDispatch > xDispatch = xFrameDispatch->queryDispatch( 1120 aURL, 1121 ::rtl::OUString::createFromAscii( "_self" ), 1122 0 ); 1123 if ( xDispatch.is() ) 1124 { 1125 xDispatch->dispatch( aURL, uno::Sequence< beans::PropertyValue >() ); 1126 bDialogUsed = sal_True; 1127 } 1128 } 1129 } 1130 } 1131 } 1132 catch ( uno::Exception& ) 1133 { 1134 } 1135 1136 return bDialogUsed; 1137 } 1138 1139 //------------------------------------------------------------------------- 1140 ::rtl::OUString ModelData_Impl::GetReccomendedDir( const ::rtl::OUString& aSuggestedDir, const sfx2::FileDialogHelper::Context& aCtxt ) 1141 { 1142 ::rtl::OUString aReccomendedDir; 1143 1144 if ( ( aSuggestedDir.getLength() || GetStorable()->hasLocation() ) 1145 && !GetMediaDescr().getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "RepairPackage" ), 1146 sal_False ) ) 1147 { 1148 INetURLObject aLocation; 1149 if ( aSuggestedDir.getLength() ) 1150 aLocation = INetURLObject( aSuggestedDir ); 1151 else 1152 { 1153 ::rtl::OUString aOldURL = GetStorable()->getLocation(); 1154 if ( aOldURL.getLength() ) 1155 { 1156 INetURLObject aTmp( aOldURL ); 1157 if ( aTmp.removeSegment() ) 1158 aLocation = aTmp; 1159 } 1160 1161 if ( aLocation.HasError() ) 1162 aLocation = INetURLObject( SvtPathOptions().GetWorkPath() ); 1163 } 1164 1165 aLocation.setFinalSlash(); 1166 if ( !aLocation.HasError() ) 1167 aReccomendedDir = aLocation.GetMainURL( INetURLObject::NO_DECODE ); 1168 } 1169 else 1170 { 1171 // pb: set graphic path if context == SD_EXPORT or SI_EXPORT else work path 1172 ::rtl::OUString aConfigSuggestion( ( aCtxt != sfx2::FileDialogHelper::UNKNOWN_CONTEXT ) ? SvtPathOptions().GetGraphicPath() : SvtPathOptions().GetWorkPath() ); 1173 aReccomendedDir = INetURLObject( aConfigSuggestion ).GetMainURL( INetURLObject::NO_DECODE ); 1174 } 1175 1176 return aReccomendedDir; 1177 } 1178 1179 //------------------------------------------------------------------------- 1180 ::rtl::OUString ModelData_Impl::GetReccomendedName( const ::rtl::OUString& aSuggestedName, const ::rtl::OUString& aTypeName ) 1181 { 1182 // the last used name might be provided by aSuggestedName from the old selection, or from the MediaDescriptor 1183 ::rtl::OUString aReccomendedName; 1184 1185 if ( aSuggestedName.getLength() ) 1186 aReccomendedName = aSuggestedName; 1187 else 1188 { 1189 aReccomendedName = INetURLObject( GetStorable()->getLocation() ).GetName( INetURLObject::DECODE_WITH_CHARSET ); 1190 if ( !aReccomendedName.getLength() ) 1191 { 1192 try { 1193 uno::Reference< frame::XTitle > xTitle( GetModel(), uno::UNO_QUERY_THROW ); 1194 aReccomendedName = xTitle->getTitle(); 1195 } catch( uno::Exception& ) {} 1196 } 1197 1198 if ( aReccomendedName.getLength() && aTypeName.getLength() ) 1199 { 1200 // adjust the extension to the type 1201 uno::Reference< container::XNameAccess > xTypeDetection = uno::Reference< container::XNameAccess >( 1202 m_pOwner->GetServiceFactory()->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.TypeDetection" ) ), 1203 uno::UNO_QUERY ); 1204 if ( xTypeDetection.is() ) 1205 { 1206 INetURLObject aObj( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "file:///c:/" ) ) + aReccomendedName ); 1207 1208 uno::Sequence< beans::PropertyValue > aTypeNameProps; 1209 if ( ( xTypeDetection->getByName( aTypeName ) >>= aTypeNameProps ) && aTypeNameProps.getLength() ) 1210 { 1211 ::comphelper::SequenceAsHashMap aTypeNamePropsHM( aTypeNameProps ); 1212 uno::Sequence< ::rtl::OUString > aExtensions = aTypeNamePropsHM.getUnpackedValueOrDefault( 1213 ::rtl::OUString::createFromAscii( "Extensions" ), 1214 ::uno::Sequence< ::rtl::OUString >() ); 1215 if ( aExtensions.getLength() ) 1216 aObj.SetExtension( aExtensions[0] ); 1217 } 1218 1219 aReccomendedName = aObj.GetName( INetURLObject::DECODE_WITH_CHARSET ); 1220 } 1221 } 1222 } 1223 1224 return aReccomendedName; 1225 } 1226 1227 1228 //========================================================================= 1229 // class SfxStoringHelper 1230 //========================================================================= 1231 //------------------------------------------------------------------------- 1232 SfxStoringHelper::SfxStoringHelper( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 1233 : m_xFactory( xFactory ) 1234 { 1235 } 1236 1237 //------------------------------------------------------------------------- 1238 uno::Reference< lang::XMultiServiceFactory > SfxStoringHelper::GetServiceFactory() 1239 { 1240 if ( !m_xFactory.is() ) 1241 { 1242 m_xFactory = ::comphelper::getProcessServiceFactory(); 1243 if( !m_xFactory.is() ) 1244 throw uno::RuntimeException(); // TODO: 1245 } 1246 1247 return m_xFactory; 1248 } 1249 1250 //------------------------------------------------------------------------- 1251 uno::Reference< container::XNameAccess > SfxStoringHelper::GetFilterConfiguration() 1252 { 1253 if ( !m_xFilterCFG.is() ) 1254 { 1255 m_xFilterCFG = uno::Reference< container::XNameAccess >( 1256 GetServiceFactory()->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ), 1257 uno::UNO_QUERY ); 1258 1259 if ( !m_xFilterCFG.is() ) 1260 throw uno::RuntimeException(); 1261 } 1262 1263 return m_xFilterCFG; 1264 } 1265 1266 //------------------------------------------------------------------------- 1267 uno::Reference< container::XContainerQuery > SfxStoringHelper::GetFilterQuery() 1268 { 1269 if ( !m_xFilterQuery.is() ) 1270 { 1271 m_xFilterQuery = uno::Reference< container::XContainerQuery >( GetFilterConfiguration(), uno::UNO_QUERY ); 1272 if ( !m_xFilterQuery.is() ) 1273 throw uno::RuntimeException(); 1274 } 1275 1276 return m_xFilterQuery; 1277 } 1278 1279 //------------------------------------------------------------------------- 1280 uno::Reference< ::com::sun::star::frame::XModuleManager > SfxStoringHelper::GetModuleManager() 1281 { 1282 if ( !m_xModuleManager.is() ) 1283 { 1284 m_xModuleManager = uno::Reference< ::com::sun::star::frame::XModuleManager >( 1285 GetServiceFactory()->createInstance( 1286 ::rtl::OUString::createFromAscii( "com.sun.star.frame.ModuleManager" ) ), 1287 uno::UNO_QUERY ); 1288 1289 if ( !m_xModuleManager.is() ) 1290 throw uno::RuntimeException(); 1291 } 1292 1293 return m_xModuleManager; 1294 } 1295 1296 //------------------------------------------------------------------------- 1297 uno::Reference< container::XNameAccess > SfxStoringHelper::GetNamedModuleManager() 1298 { 1299 if ( !m_xNamedModManager.is() ) 1300 { 1301 m_xNamedModManager = uno::Reference< container::XNameAccess >( GetModuleManager(), uno::UNO_QUERY ); 1302 if ( !m_xNamedModManager.is() ) 1303 throw uno::RuntimeException(); 1304 } 1305 1306 return m_xNamedModManager; 1307 } 1308 1309 //------------------------------------------------------------------------- 1310 sal_Bool SfxStoringHelper::GUIStoreModel( const uno::Reference< frame::XModel >& xModel, 1311 const ::rtl::OUString& aSlotName, 1312 uno::Sequence< beans::PropertyValue >& aArgsSequence, 1313 sal_Bool bPreselectPassword, 1314 ::rtl::OUString aSuggestedName, 1315 sal_uInt16 nDocumentSignatureState ) 1316 { 1317 ModelData_Impl aModelData( *this, xModel, aArgsSequence ); 1318 1319 sal_Bool bDialogUsed = sal_False; 1320 1321 INetURLObject aURL; 1322 1323 sal_Bool bSetStandardName = sal_False; // can be set only for SaveAs 1324 1325 // parse the slot name 1326 sal_Int8 nStoreMode = getStoreModeFromSlotName( aSlotName ); 1327 sal_Int8 nStatusSave = STATUS_NO_ACTION; 1328 1329 // handle the special cases 1330 if ( nStoreMode & SAVEAS_REQUESTED ) 1331 { 1332 ::comphelper::SequenceAsHashMap::const_iterator aSaveToIter = 1333 aModelData.GetMediaDescr().find( ::rtl::OUString::createFromAscii( "SaveTo" ) ); 1334 if ( aSaveToIter != aModelData.GetMediaDescr().end() ) 1335 { 1336 sal_Bool bWideExport = sal_False; 1337 aSaveToIter->second >>= bWideExport; 1338 if ( bWideExport ) 1339 nStoreMode = EXPORT_REQUESTED | WIDEEXPORT_REQUESTED; 1340 } 1341 1342 // if saving is not acceptable the warning must be shown even in case of SaveAs operation 1343 if ( ( nStoreMode & SAVEAS_REQUESTED ) && aModelData.CheckSaveAcceptable( STATUS_SAVEAS ) == STATUS_NO_ACTION ) 1344 throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT ); 1345 } 1346 else if ( nStoreMode & SAVE_REQUESTED ) 1347 { 1348 // if saving is not acceptable by the configuration the warning must be shown 1349 nStatusSave = aModelData.CheckSaveAcceptable( STATUS_SAVE ); 1350 1351 if ( nStatusSave == STATUS_NO_ACTION ) 1352 throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT ); 1353 else if ( nStatusSave == STATUS_SAVE ) 1354 { 1355 // check whether it is possible to use save operation 1356 nStatusSave = aModelData.CheckStateForSave(); 1357 } 1358 1359 if ( nStatusSave == STATUS_NO_ACTION ) 1360 { 1361 throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT ); 1362 } 1363 else if ( nStatusSave != STATUS_SAVE ) 1364 { 1365 // this should be a usual SaveAs operation 1366 nStoreMode = SAVEAS_REQUESTED; 1367 if ( nStatusSave == STATUS_SAVEAS_STANDARDNAME ) 1368 bSetStandardName = sal_True; 1369 } 1370 } 1371 1372 if ( !( nStoreMode & EXPORT_REQUESTED ) ) 1373 { 1374 // if it is no export, warn user that the signature will be removed 1375 if ( SIGNATURESTATE_SIGNATURES_OK == nDocumentSignatureState 1376 || SIGNATURESTATE_SIGNATURES_INVALID == nDocumentSignatureState 1377 || SIGNATURESTATE_SIGNATURES_NOTVALIDATED == nDocumentSignatureState 1378 || SIGNATURESTATE_SIGNATURES_PARTIAL_OK == nDocumentSignatureState) 1379 { 1380 if ( QueryBox( NULL, SfxResId( RID_XMLSEC_QUERY_LOSINGSIGNATURE ) ).Execute() != RET_YES ) 1381 { 1382 // the user has decided not to store the document 1383 throw task::ErrorCodeIOException( ::rtl::OUString(), 1384 uno::Reference< uno::XInterface >(), 1385 ERRCODE_IO_ABORT ); 1386 } 1387 } 1388 } 1389 1390 if ( nStoreMode & SAVE_REQUESTED && nStatusSave == STATUS_SAVE ) 1391 { 1392 // Document properties can contain streams that should be freed before storing 1393 aModelData.FreeDocumentProps(); 1394 1395 if ( aModelData.GetStorable2().is() ) 1396 { 1397 try 1398 { 1399 aModelData.GetStorable2()->storeSelf( aModelData.GetMediaDescr().getAsConstPropertyValueList() ); 1400 } 1401 catch( lang::IllegalArgumentException& ) 1402 { 1403 OSL_ENSURE( sal_False, "ModelData didn't handle illegal parameters, all the parameters are ignored!\n" ); 1404 aModelData.GetStorable()->store(); 1405 } 1406 } 1407 else 1408 { 1409 OSL_ENSURE( sal_False, "XStorable2 is not supported by the model!\n" ); 1410 aModelData.GetStorable()->store(); 1411 } 1412 1413 return sal_False; 1414 } 1415 1416 // preselect a filter for the storing process 1417 uno::Sequence< beans::PropertyValue > aFilterProps = aModelData.GetPreselectedFilter_Impl( nStoreMode ); 1418 1419 DBG_ASSERT( aFilterProps.getLength(), "No filter for storing!\n" ); 1420 if ( !aFilterProps.getLength() ) 1421 throw task::ErrorCodeIOException( ::rtl::OUString(), 1422 uno::Reference< uno::XInterface >(), 1423 ERRCODE_IO_INVALIDPARAMETER ); 1424 1425 ::comphelper::SequenceAsHashMap aFilterPropsHM( aFilterProps ); 1426 ::rtl::OUString aFilterName = aFilterPropsHM.getUnpackedValueOrDefault( 1427 ::rtl::OUString::createFromAscii( "Name" ), 1428 ::rtl::OUString() ); 1429 1430 ::rtl::OUString aFilterFromMediaDescr = aModelData.GetMediaDescr().getUnpackedValueOrDefault( 1431 aFilterNameString, 1432 ::rtl::OUString() ); 1433 ::rtl::OUString aOldFilterName = aModelData.GetDocProps().getUnpackedValueOrDefault( 1434 aFilterNameString, 1435 ::rtl::OUString() ); 1436 1437 sal_Bool bUseFilterOptions = sal_False; 1438 ::comphelper::SequenceAsHashMap::const_iterator aFileNameIter = aModelData.GetMediaDescr().find( ::rtl::OUString::createFromAscii( "URL" ) ); 1439 1440 if ( ( nStoreMode & EXPORT_REQUESTED ) && ( nStoreMode & PDFEXPORT_REQUESTED ) && !( nStoreMode & PDFDIRECTEXPORT_REQUESTED ) ) 1441 { 1442 // this is PDF export, the filter options dialog should be shown before the export 1443 aModelData.GetMediaDescr()[aFilterNameString] <<= aFilterName; 1444 if ( aModelData.GetMediaDescr().find( aFilterFlagsString ) == aModelData.GetMediaDescr().end() 1445 && aModelData.GetMediaDescr().find( aFilterOptionsString ) == aModelData.GetMediaDescr().end() 1446 && aModelData.GetMediaDescr().find( aFilterDataString ) == aModelData.GetMediaDescr().end() ) 1447 { 1448 // execute filter options dialog since no options are set in the media descriptor 1449 if ( aModelData.ExecuteFilterDialog_Impl( aFilterName ) ) 1450 bDialogUsed = sal_True; 1451 } 1452 } 1453 1454 if ( aFileNameIter == aModelData.GetMediaDescr().end() ) 1455 { 1456 sal_Int16 nDialog = SFX2_IMPL_DIALOG_CONFIG; 1457 ::comphelper::SequenceAsHashMap::const_iterator aDlgIter = 1458 aModelData.GetMediaDescr().find( ::rtl::OUString::createFromAscii( "UseSystemDialog" ) ); 1459 if ( aDlgIter != aModelData.GetMediaDescr().end() ) 1460 { 1461 sal_Bool bUseSystemDialog = sal_True; 1462 if ( aDlgIter->second >>= bUseSystemDialog ) 1463 { 1464 if ( bUseSystemDialog ) 1465 nDialog = SFX2_IMPL_DIALOG_SYSTEM; 1466 else 1467 nDialog = SFX2_IMPL_DIALOG_OOO; 1468 } 1469 } 1470 1471 // The Dispatch supports parameter FolderName that overwrites SuggestedSaveAsDir 1472 ::rtl::OUString aSuggestedDir = aModelData.GetMediaDescr().getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FolderName" ) ), ::rtl::OUString() ); 1473 if ( !aSuggestedDir.getLength() ) 1474 { 1475 aSuggestedDir = aModelData.GetMediaDescr().getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SuggestedSaveAsDir" ) ), ::rtl::OUString() ); 1476 if ( !aSuggestedDir.getLength() ) 1477 aSuggestedDir = aModelData.GetDocProps().getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SuggestedSaveAsDir" ) ), ::rtl::OUString() ); 1478 } 1479 1480 aSuggestedName = aModelData.GetMediaDescr().getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SuggestedSaveAsName" ) ), ::rtl::OUString() ); 1481 if ( !aSuggestedName.getLength() ) 1482 aSuggestedName = aModelData.GetDocProps().getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SuggestedSaveAsName" ) ), ::rtl::OUString() ); 1483 1484 ::rtl::OUString sStandardDir; 1485 ::comphelper::SequenceAsHashMap::const_iterator aStdDirIter = 1486 aModelData.GetMediaDescr().find( ::rtl::OUString::createFromAscii( "StandardDir" ) ); 1487 if ( aStdDirIter != aModelData.GetMediaDescr().end() ) 1488 aStdDirIter->second >>= sStandardDir; 1489 1490 ::com::sun::star::uno::Sequence< ::rtl::OUString > aBlackList; 1491 1492 ::comphelper::SequenceAsHashMap::const_iterator aBlackListIter = 1493 aModelData.GetMediaDescr().find( ::rtl::OUString::createFromAscii( "BlackList" ) ); 1494 if ( aBlackListIter != aModelData.GetMediaDescr().end() ) 1495 aBlackListIter->second >>= aBlackList; 1496 1497 sal_Bool bExit = sal_False; 1498 while ( !bExit ) 1499 { 1500 bUseFilterOptions = aModelData.OutputFileDialog( nStoreMode, aFilterProps, bSetStandardName, aSuggestedName, bPreselectPassword, aSuggestedDir, nDialog, sStandardDir, aBlackList ); 1501 1502 // in case the dialog is opend a second time the folder should be the same as before, not what was handed over by parameters 1503 aSuggestedDir = ::rtl::OUString(); 1504 if ( nStoreMode == SAVEAS_REQUESTED ) 1505 { 1506 // in case of saving check filter for possible alien warning 1507 ::rtl::OUString aSelFilterName = aModelData.GetMediaDescr().getUnpackedValueOrDefault( 1508 aFilterNameString, 1509 ::rtl::OUString() ); 1510 sal_Int8 nStatusFilterSave = aModelData.CheckFilter( aSelFilterName ); 1511 if ( nStatusFilterSave == STATUS_SAVEAS_STANDARDNAME ) 1512 { 1513 // switch to best filter 1514 bSetStandardName = sal_True; 1515 } 1516 else if ( nStatusFilterSave == STATUS_SAVE ) 1517 { 1518 // user confirmed alien filter or "good" filter is used 1519 bExit = sal_True; 1520 } 1521 } 1522 else 1523 bExit = sal_True; 1524 } 1525 1526 bDialogUsed = sal_True; 1527 aFileNameIter = aModelData.GetMediaDescr().find( ::rtl::OUString::createFromAscii( "URL" ) ); 1528 } 1529 else 1530 { 1531 // the target file name is provided so check if new filter options 1532 // are provided or old options can be used 1533 if ( aFilterFromMediaDescr.equals( aOldFilterName ) ) 1534 { 1535 ::comphelper::SequenceAsHashMap::const_iterator aIter = 1536 aModelData.GetDocProps().find( aFilterOptionsString ); 1537 if ( aIter != aModelData.GetDocProps().end() 1538 && aModelData.GetMediaDescr().find( aFilterOptionsString ) == aModelData.GetMediaDescr().end() ) 1539 aModelData.GetMediaDescr()[aIter->first] = aIter->second; 1540 1541 aIter = aModelData.GetDocProps().find( aFilterDataString ); 1542 if ( aIter != aModelData.GetDocProps().end() 1543 && aModelData.GetMediaDescr().find( aFilterDataString ) == aModelData.GetMediaDescr().end() ) 1544 aModelData.GetMediaDescr()[aIter->first] = aIter->second; 1545 } 1546 } 1547 1548 if ( aFileNameIter != aModelData.GetMediaDescr().end() ) 1549 { 1550 ::rtl::OUString aFileName; 1551 aFileNameIter->second >>= aFileName; 1552 aURL.SetURL( aFileName ); 1553 DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "Illegal URL!" ); 1554 1555 ::comphelper::SequenceAsHashMap::const_iterator aIter = 1556 aModelData.GetMediaDescr().find( aFilterNameString ); 1557 1558 if ( aIter != aModelData.GetMediaDescr().end() ) 1559 aIter->second >>= aFilterName; 1560 else 1561 aModelData.GetMediaDescr()[aFilterNameString] <<= aFilterName; 1562 1563 DBG_ASSERT( aFilterName.getLength(), "Illegal filter!" ); 1564 } 1565 else 1566 { 1567 DBG_ASSERT( sal_False, "This code must be unreachable!\n" ); 1568 throw task::ErrorCodeIOException( ::rtl::OUString(), 1569 uno::Reference< uno::XInterface >(), 1570 ERRCODE_IO_INVALIDPARAMETER ); 1571 } 1572 1573 ::comphelper::SequenceAsHashMap::const_iterator aIter = 1574 aModelData.GetMediaDescr().find( ::rtl::OUString::createFromAscii( "FilterFlags" ) ); 1575 sal_Bool bFilterFlagsSet = ( aIter != aModelData.GetMediaDescr().end() ); 1576 1577 if( !( nStoreMode & PDFEXPORT_REQUESTED ) && !bFilterFlagsSet 1578 && ( ( nStoreMode & EXPORT_REQUESTED ) || bUseFilterOptions ) ) 1579 { 1580 // execute filter options dialog 1581 if ( aModelData.ExecuteFilterDialog_Impl( aFilterName ) ) 1582 bDialogUsed = sal_True; 1583 } 1584 1585 // so the arguments will not change any more and can be stored to the main location 1586 aArgsSequence = aModelData.GetMediaDescr().getAsConstPropertyValueList(); 1587 1588 // store the document and handle it's docinfo 1589 SvtSaveOptions aOptions; 1590 1591 DocumentSettingsGuard aSettingsGuard( aModelData.GetModel(), aModelData.IsRecommendReadOnly(), nStoreMode & EXPORT_REQUESTED ); 1592 1593 OSL_ENSURE( aModelData.GetMediaDescr().find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Password" ) ) ) == aModelData.GetMediaDescr().end(), "The Password property of MediaDescriptor should not be used here!" ); 1594 if ( aOptions.IsDocInfoSave() 1595 && ( !aModelData.GetStorable()->hasLocation() 1596 || INetURLObject( aModelData.GetStorable()->getLocation() ) != aURL ) ) 1597 { 1598 // this is defenitly not a Save operation 1599 // so the document info can be updated 1600 1601 // on export document info must be preserved 1602 uno::Reference<document::XDocumentInfoSupplier> xDIS( 1603 aModelData.GetModel(), uno::UNO_QUERY_THROW); 1604 uno::Reference<util::XCloneable> xCloneable( 1605 xDIS->getDocumentInfo(), uno::UNO_QUERY_THROW); 1606 uno::Reference<document::XDocumentInfo> xOldDocInfo( 1607 xCloneable->createClone(), uno::UNO_QUERY_THROW); 1608 1609 // use dispatch API to show document info dialog 1610 if ( aModelData.ShowDocumentInfoDialog() ) 1611 bDialogUsed = sal_True; 1612 else 1613 { 1614 DBG_ERROR( "Can't execute document info dialog!\n" ); 1615 } 1616 1617 try { 1618 // Document properties can contain streams that should be freed before storing 1619 aModelData.FreeDocumentProps(); 1620 if ( ( nStoreMode & EXPORT_REQUESTED ) ) 1621 aModelData.GetStorable()->storeToURL( aURL.GetMainURL( INetURLObject::NO_DECODE ), aArgsSequence ); 1622 else 1623 aModelData.GetStorable()->storeAsURL( aURL.GetMainURL( INetURLObject::NO_DECODE ), aArgsSequence ); 1624 } 1625 catch( uno::Exception& ) 1626 { 1627 if ( ( nStoreMode & EXPORT_REQUESTED ) ) 1628 SetDocInfoState( aModelData.GetModel(), xOldDocInfo, sal_True ); 1629 1630 throw; 1631 } 1632 1633 if ( ( nStoreMode & EXPORT_REQUESTED ) ) 1634 SetDocInfoState( aModelData.GetModel(), xOldDocInfo, sal_True ); 1635 } 1636 else 1637 { 1638 // Document properties can contain streams that should be freed before storing 1639 aModelData.FreeDocumentProps(); 1640 1641 // this is actually a save operation with different parameters 1642 // so storeTo or storeAs without DocInfo operations are used 1643 if ( ( nStoreMode & EXPORT_REQUESTED ) ) 1644 aModelData.GetStorable()->storeToURL( aURL.GetMainURL( INetURLObject::NO_DECODE ), aArgsSequence ); 1645 else 1646 aModelData.GetStorable()->storeAsURL( aURL.GetMainURL( INetURLObject::NO_DECODE ), aArgsSequence ); 1647 } 1648 1649 return bDialogUsed; 1650 } 1651 1652 //------------------------------------------------------------------------- 1653 // static 1654 sal_Bool SfxStoringHelper::CheckFilterOptionsAppearence( 1655 const uno::Reference< container::XNameAccess >& xFilterCFG, 1656 const ::rtl::OUString& aFilterName ) 1657 { 1658 sal_Bool bUseFilterOptions = sal_False; 1659 1660 DBG_ASSERT( xFilterCFG.is(), "No filter configuration!\n" ); 1661 if( xFilterCFG.is() ) 1662 { 1663 try { 1664 uno::Sequence < beans::PropertyValue > aProps; 1665 uno::Any aAny = xFilterCFG->getByName( aFilterName ); 1666 if ( aAny >>= aProps ) 1667 { 1668 ::comphelper::SequenceAsHashMap aPropsHM( aProps ); 1669 ::rtl::OUString aServiceName = aPropsHM.getUnpackedValueOrDefault( 1670 ::rtl::OUString::createFromAscii( "UIComponent" ), 1671 ::rtl::OUString() ); 1672 if( aServiceName.getLength() ) 1673 bUseFilterOptions = sal_True; 1674 } 1675 } 1676 catch( uno::Exception& ) 1677 { 1678 } 1679 } 1680 1681 return bUseFilterOptions; 1682 } 1683 1684 //------------------------------------------------------------------------- 1685 // static 1686 void SfxStoringHelper::SetDocInfoState( 1687 const uno::Reference< frame::XModel >& xModel, 1688 const uno::Reference< document::XDocumentInfo >& i_xOldDocInfo, 1689 sal_Bool bNoModify ) 1690 { 1691 uno::Reference< document::XDocumentInfoSupplier > xModelDocInfoSupplier( xModel, uno::UNO_QUERY ); 1692 if ( !xModelDocInfoSupplier.is() ) 1693 throw uno::RuntimeException(); // TODO: 1694 1695 uno::Reference< document::XDocumentInfo > xDocInfoToFill = xModelDocInfoSupplier->getDocumentInfo(); 1696 uno::Reference< beans::XPropertySet > xPropSet( i_xOldDocInfo, 1697 uno::UNO_QUERY_THROW ); 1698 1699 uno::Reference< util::XModifiable > xModifiable( xModel, uno::UNO_QUERY ); 1700 if ( bNoModify && !xModifiable.is() ) 1701 throw uno::RuntimeException(); 1702 1703 sal_Bool bIsModified = bNoModify && xModifiable->isModified(); 1704 1705 try 1706 { 1707 uno::Reference< beans::XPropertySet > xSet( xDocInfoToFill, uno::UNO_QUERY ); 1708 uno::Reference< beans::XPropertyContainer > xContainer( xSet, uno::UNO_QUERY ); 1709 uno::Reference< beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo(); 1710 uno::Sequence< beans::Property > lProps = xSetInfo->getProperties(); 1711 const beans::Property* pProps = lProps.getConstArray(); 1712 sal_Int32 c = lProps.getLength(); 1713 sal_Int32 i = 0; 1714 for (i=0; i<c; ++i) 1715 { 1716 uno::Any aValue = xPropSet->getPropertyValue( pProps[i].Name ); 1717 if ( pProps[i].Attributes & ::com::sun::star::beans::PropertyAttribute::REMOVABLE ) 1718 // QUESTION: DefaultValue?! 1719 xContainer->addProperty( pProps[i].Name, pProps[i].Attributes, aValue ); 1720 try 1721 { 1722 // it is possible that the propertysets from XML and binary files differ; we shouldn't break then 1723 xSet->setPropertyValue( pProps[i].Name, aValue ); 1724 } 1725 catch ( uno::Exception& ) {} 1726 } 1727 1728 sal_Int16 nCount = i_xOldDocInfo->getUserFieldCount(); 1729 sal_Int16 nSupportedCount = xDocInfoToFill->getUserFieldCount(); 1730 for ( sal_Int16 nInd = 0; nInd < nCount && nInd < nSupportedCount; nInd++ ) 1731 { 1732 ::rtl::OUString aPropName = i_xOldDocInfo->getUserFieldName( nInd ); 1733 xDocInfoToFill->setUserFieldName( nInd, aPropName ); 1734 ::rtl::OUString aPropVal = i_xOldDocInfo->getUserFieldValue( nInd ); 1735 xDocInfoToFill->setUserFieldValue( nInd, aPropVal ); 1736 } 1737 } 1738 catch ( uno::Exception& ) {} 1739 1740 // set the modified flag back if required 1741 if ( bNoModify && bIsModified != xModifiable->isModified() ) 1742 xModifiable->setModified( bIsModified ); 1743 } 1744 1745 //------------------------------------------------------------------------- 1746 // static 1747 sal_Bool SfxStoringHelper::WarnUnacceptableFormat( const uno::Reference< frame::XModel >& xModel, 1748 ::rtl::OUString aOldUIName, 1749 ::rtl::OUString /*aDefUIName*/, 1750 sal_Bool /*bCanProceedFurther*/ ) 1751 { 1752 if ( !SvtSaveOptions().IsWarnAlienFormat() ) 1753 return sal_True; 1754 1755 Window* pWin = SfxStoringHelper::GetModelWindow( xModel ); 1756 SfxAlienWarningDialog aDlg( pWin, aOldUIName ); 1757 1758 return aDlg.Execute() == RET_OK; 1759 } 1760 1761 // static 1762 void SfxStoringHelper::ExecuteFilterDialog( SfxStoringHelper& _rStorageHelper 1763 ,const ::rtl::OUString& _sFilterName 1764 ,const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _xModel 1765 ,/*OUT*/::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rArgsSequence) 1766 { 1767 ModelData_Impl aModelData( _rStorageHelper, _xModel, _rArgsSequence ); 1768 if ( aModelData.ExecuteFilterDialog_Impl( _sFilterName ) ) 1769 _rArgsSequence = aModelData.GetMediaDescr().getAsConstPropertyValueList(); 1770 } 1771 1772 // static 1773 Window* SfxStoringHelper::GetModelWindow( const uno::Reference< frame::XModel >& xModel ) 1774 { 1775 Window* pWin = 0; 1776 try { 1777 if ( xModel.is() ) 1778 { 1779 uno::Reference< frame::XController > xController = xModel->getCurrentController(); 1780 if ( xController.is() ) 1781 { 1782 uno::Reference< frame::XFrame > xFrame = xController->getFrame(); 1783 if ( xFrame.is() ) 1784 { 1785 uno::Reference< awt::XWindow > xWindow = xFrame->getContainerWindow(); 1786 if ( xWindow.is() ) 1787 { 1788 VCLXWindow* pVCLWindow = VCLXWindow::GetImplementation( xWindow ); 1789 if ( pVCLWindow ) 1790 pWin = pVCLWindow->GetWindow(); 1791 } 1792 } 1793 } 1794 } 1795 } 1796 catch ( uno::Exception& ) 1797 { 1798 } 1799 1800 return pWin; 1801 } 1802 1803