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