1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
21 #include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
22 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
23 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
24 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
25 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
26 #include <com/sun/star/view/XSelectionSupplier.hpp>
27 #include <com/sun/star/beans/PropertyExistException.hpp>
28 #include <com/sun/star/beans/XPropertyAccess.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/beans/XPropertyContainer.hpp>
31 #include <com/sun/star/beans/PropertyAttribute.hpp>
32 #include <com/sun/star/document/XExporter.hpp>
33 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
34 #include <com/sun/star/document/XDocumentProperties.hpp>
35 #include <com/sun/star/task/ErrorCodeIOException.hpp>
36 #include <com/sun/star/task/InteractionHandler.hpp>
37 #include <com/sun/star/util/URLTransformer.hpp>
38 #include <com/sun/star/util/XURLTransformer.hpp>
39 #include <com/sun/star/frame/ModuleManager.hpp>
40 #include <com/sun/star/frame/XStorable.hpp>
41 #include <com/sun/star/frame/XStorable2.hpp>
42 #include <com/sun/star/frame/XDispatchProvider.hpp>
43 #include <com/sun/star/frame/XDispatch.hpp>
44 #include <com/sun/star/frame/XTitle.hpp>
45 #include <com/sun/star/util/XModifiable.hpp>
46 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
48 #include <com/sun/star/util/XCloneable.hpp>
50 #include <guisaveas.hxx>
52 #include <sal/log.hxx>
53 #include <unotools/pathoptions.hxx>
54 #include <svl/itemset.hxx>
55 #include <svl/eitem.hxx>
56 #include <unotools/saveopt.hxx>
57 #include <tools/debug.hxx>
58 #include <tools/diagnose_ex.h>
59 #include <tools/urlobj.hxx>
60 #include <comphelper/processfactory.hxx>
61 #include <comphelper/propertysequence.hxx>
62 #include <comphelper/sequenceashashmap.hxx>
63 #include <comphelper/mimeconfighelper.hxx>
64 #include <comphelper/lok.hxx>
65 #include <vcl/svapp.hxx>
66 #include <vcl/weld.hxx>
67 #include <o3tl/char16_t2wchar_t.hxx>
69 #include <sfx2/sfxsids.hrc>
70 #include <sfx2/strings.hrc>
71 #include <sfx2/sfxresid.hxx>
72 #include <sfx2/filedlghelper.hxx>
73 #include <asyncfunc.hxx>
74 #include <sfx2/app.hxx>
75 #include <sfx2/sfxuno.hxx>
76 #include <alienwarn.hxx>
80 #include <officecfg/Office/Common.hxx>
82 #include <vcl/FilterConfigItem.hxx>
83 #include <com/sun/star/system/SystemShellExecute.hpp>
84 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
86 #include <osl/file.hxx>
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 #define SAVEACOPY_REQUESTED 64
103 #define EPUBEXPORT_REQUESTED 128
104 #define EPUBDIRECTEXPORT_REQUESTED 256
105 #define SAVEASREMOTE_REQUESTED -1
107 // possible statuses of save operation
108 #define STATUS_NO_ACTION 0
109 #define STATUS_SAVE 1
110 #define STATUS_SAVEAS 2
111 #define STATUS_SAVEAS_STANDARDNAME 3
113 const char aFilterNameString
[] = "FilterName";
114 const char aFilterOptionsString
[] = "FilterOptions";
115 const char aFilterDataString
[] = "FilterData";
117 using namespace ::com::sun::star
;
118 using namespace css::system
;
122 sal_uInt16
getSlotIDFromMode( sal_Int16 nStoreMode
)
124 // This is a temporary hardcoded solution must be removed when
125 // dialogs do not need parameters in SidSet representation any more
127 sal_uInt16 nResult
= 0;
128 if ( nStoreMode
== EXPORT_REQUESTED
|| nStoreMode
== ( EXPORT_REQUESTED
| SAVEACOPY_REQUESTED
| WIDEEXPORT_REQUESTED
) )
129 nResult
= SID_EXPORTDOC
;
130 else if ( nStoreMode
== ( EXPORT_REQUESTED
| PDFEXPORT_REQUESTED
) )
131 nResult
= SID_EXPORTDOCASPDF
;
132 else if ( nStoreMode
== ( EXPORT_REQUESTED
| EPUBEXPORT_REQUESTED
) )
133 nResult
= SID_EXPORTDOCASEPUB
;
134 else if ( nStoreMode
== ( EXPORT_REQUESTED
| PDFEXPORT_REQUESTED
| PDFDIRECTEXPORT_REQUESTED
) )
135 nResult
= SID_DIRECTEXPORTDOCASPDF
;
136 else if ( nStoreMode
== ( EXPORT_REQUESTED
| EPUBEXPORT_REQUESTED
| EPUBDIRECTEXPORT_REQUESTED
) )
137 nResult
= SID_DIRECTEXPORTDOCASEPUB
;
138 else if ( nStoreMode
== SAVEAS_REQUESTED
|| nStoreMode
== ( EXPORT_REQUESTED
| WIDEEXPORT_REQUESTED
) )
139 nResult
= SID_SAVEASDOC
;
140 else if ( nStoreMode
== SAVEASREMOTE_REQUESTED
)
141 nResult
= SID_SAVEASREMOTE
;
143 SAL_WARN( "sfx.doc", "Unacceptable slot name is provided!" );
150 sal_Int16
getStoreModeFromSlotName( const OUString
& aSlotName
)
152 sal_Int16 nResult
= 0;
153 if ( aSlotName
== "ExportTo" )
154 nResult
= EXPORT_REQUESTED
;
155 else if ( aSlotName
== "ExportToPDF" )
156 nResult
= EXPORT_REQUESTED
| PDFEXPORT_REQUESTED
;
157 else if ( aSlotName
== "ExportDirectToPDF" )
158 nResult
= EXPORT_REQUESTED
| PDFEXPORT_REQUESTED
| PDFDIRECTEXPORT_REQUESTED
;
159 else if ( aSlotName
== "ExportToEPUB" )
160 nResult
= EXPORT_REQUESTED
| EPUBEXPORT_REQUESTED
;
161 else if ( aSlotName
== "ExportDirectToEPUB" )
162 nResult
= EXPORT_REQUESTED
| EPUBEXPORT_REQUESTED
| EPUBDIRECTEXPORT_REQUESTED
;
163 else if ( aSlotName
== "Save" )
164 nResult
= SAVE_REQUESTED
;
165 else if ( aSlotName
== "SaveAs" )
166 nResult
= SAVEAS_REQUESTED
;
167 else if ( aSlotName
== "SaveAsRemote" )
168 nResult
= SAVEASREMOTE_REQUESTED
;
170 throw task::ErrorCodeIOException(
171 ("getStoreModeFromSlotName(\"" + aSlotName
172 + "): ERRCODE_IO_INVALIDPARAMETER"),
173 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_INVALIDPARAMETER
) );
179 SfxFilterFlags
getMustFlags( sal_Int16 nStoreMode
)
181 return ( SfxFilterFlags::EXPORT
182 | ( ( ( nStoreMode
& EXPORT_REQUESTED
) && !( nStoreMode
& WIDEEXPORT_REQUESTED
) ) ? SfxFilterFlags::NONE
: SfxFilterFlags::IMPORT
) );
186 SfxFilterFlags
getDontFlags( sal_Int16 nStoreMode
)
188 return ( SfxFilterFlags::INTERNAL
189 | SfxFilterFlags::NOTINFILEDLG
190 | ( ( ( nStoreMode
& EXPORT_REQUESTED
) && !( nStoreMode
& WIDEEXPORT_REQUESTED
) ) ? SfxFilterFlags::IMPORT
: SfxFilterFlags::NONE
) );
196 class DocumentSettingsGuard
198 uno::Reference
< beans::XPropertySet
> m_xDocumentSettings
;
199 bool m_bPreserveReadOnly
;
200 bool m_bReadOnlySupported
;
202 bool m_bRestoreSettings
;
204 DocumentSettingsGuard( const uno::Reference
< frame::XModel
>& xModel
, bool bReadOnly
, bool bRestore
)
205 : m_bPreserveReadOnly( false )
206 , m_bReadOnlySupported( false )
207 , m_bRestoreSettings( bRestore
)
211 uno::Reference
< lang::XMultiServiceFactory
> xDocSettingsSupplier( xModel
, uno::UNO_QUERY_THROW
);
212 m_xDocumentSettings
.set(
213 xDocSettingsSupplier
->createInstance( "com.sun.star.document.Settings" ),
214 uno::UNO_QUERY_THROW
);
218 OUString
aLoadReadonlyString( "LoadReadonly" );
219 m_xDocumentSettings
->getPropertyValue( aLoadReadonlyString
) >>= m_bPreserveReadOnly
;
220 m_xDocumentSettings
->setPropertyValue( aLoadReadonlyString
, uno::makeAny( bReadOnly
) );
221 m_bReadOnlySupported
= true;
223 catch( const uno::Exception
& )
226 catch( const uno::Exception
& )
229 if ( bReadOnly
&& !m_bReadOnlySupported
)
230 throw uno::RuntimeException(); // the user could provide the data, so it must be stored
233 ~DocumentSettingsGuard()
235 if ( m_bRestoreSettings
)
239 if ( m_bReadOnlySupported
)
240 m_xDocumentSettings
->setPropertyValue( "LoadReadonly", uno::makeAny( m_bPreserveReadOnly
) );
242 catch( const uno::Exception
& )
244 OSL_FAIL( "Unexpected exception!" );
249 } // anonymous namespace
255 SfxStoringHelper
* m_pOwner
;
256 uno::Reference
< frame::XModel
> m_xModel
;
257 uno::Reference
< frame::XStorable
> m_xStorable
;
258 uno::Reference
< frame::XStorable2
> m_xStorable2
;
260 OUString m_aModuleName
;
261 std::unique_ptr
<::comphelper::SequenceAsHashMap
> m_pDocumentPropsHM
;
262 std::unique_ptr
<::comphelper::SequenceAsHashMap
> m_pModulePropsHM
;
264 ::comphelper::SequenceAsHashMap m_aMediaDescrHM
;
266 bool m_bRecommendReadOnly
;
269 ModelData_Impl( SfxStoringHelper
& aOwner
,
270 const uno::Reference
< frame::XModel
>& xModel
,
271 const uno::Sequence
< beans::PropertyValue
>& aMediaDescr
);
275 void FreeDocumentProps();
277 uno::Reference
< frame::XModel
> const & GetModel() const;
278 uno::Reference
< frame::XStorable
> const & GetStorable();
279 uno::Reference
< frame::XStorable2
> const & GetStorable2();
281 ::comphelper::SequenceAsHashMap
& GetMediaDescr() { return m_aMediaDescrHM
; }
283 bool IsRecommendReadOnly() const { return m_bRecommendReadOnly
; }
285 const ::comphelper::SequenceAsHashMap
& GetDocProps();
287 OUString
const & GetModuleName();
288 const ::comphelper::SequenceAsHashMap
& GetModuleProps();
290 void CheckInteractionHandler();
293 OUString
GetDocServiceName();
294 uno::Sequence
< beans::PropertyValue
> GetDocServiceDefaultFilterCheckFlags( SfxFilterFlags nMust
, SfxFilterFlags nDont
);
295 uno::Sequence
< beans::PropertyValue
> GetDocServiceAnyFilter( SfxFilterFlags nMust
, SfxFilterFlags nDont
);
296 uno::Sequence
< beans::PropertyValue
> GetPreselectedFilter_Impl( sal_Int16 nStoreMode
);
297 uno::Sequence
< beans::PropertyValue
> GetDocServiceDefaultFilter();
299 bool ExecuteFilterDialog_Impl( const OUString
& aFilterName
);
301 sal_Int8
CheckSaveAcceptable( sal_Int8 nCurStatus
);
302 sal_Int8
CheckStateForSave();
304 sal_Int8
CheckFilter( const OUString
& );
306 bool CheckFilterOptionsDialogExistence();
308 bool OutputFileDialog( sal_Int16 nStoreMode
,
309 const ::comphelper::SequenceAsHashMap
& aPreselectedFilterPropsHM
,
310 bool bSetStandardName
,
311 OUString
& aSuggestedName
,
312 bool bPreselectPassword
,
313 OUString
& aSuggestedDir
,
315 const OUString
& rStandardDir
,
316 const css::uno::Sequence
< OUString
>& rDenyList
319 bool ShowDocumentInfoDialog(const std::function
< void () >&);
321 static OUString
GetRecommendedExtension( const OUString
& aTypeName
);
322 OUString
GetRecommendedDir( const OUString
& aSuggestedDir
);
323 OUString
GetRecommendedName( const OUString
& aSuggestedName
,
324 const OUString
& aTypeName
);
329 ModelData_Impl::ModelData_Impl( SfxStoringHelper
& aOwner
,
330 const uno::Reference
< frame::XModel
>& xModel
,
331 const uno::Sequence
< beans::PropertyValue
>& aMediaDescr
)
332 : m_pOwner( &aOwner
)
334 , m_aMediaDescrHM( aMediaDescr
)
335 , m_bRecommendReadOnly( false )
337 CheckInteractionHandler();
341 ModelData_Impl::~ModelData_Impl()
344 m_pDocumentPropsHM
.reset();
345 m_pModulePropsHM
.reset();
349 void ModelData_Impl::FreeDocumentProps()
351 m_pDocumentPropsHM
.reset();
355 uno::Reference
< frame::XModel
> const & ModelData_Impl::GetModel() const
357 if ( !m_xModel
.is() )
358 throw uno::RuntimeException();
364 uno::Reference
< frame::XStorable
> const & ModelData_Impl::GetStorable()
366 if ( !m_xStorable
.is() )
368 m_xStorable
.set( m_xModel
, uno::UNO_QUERY_THROW
);
375 uno::Reference
< frame::XStorable2
> const & ModelData_Impl::GetStorable2()
377 if ( !m_xStorable2
.is() )
379 m_xStorable2
.set( m_xModel
, uno::UNO_QUERY_THROW
);
386 const ::comphelper::SequenceAsHashMap
& ModelData_Impl::GetDocProps()
388 if ( !m_pDocumentPropsHM
)
389 m_pDocumentPropsHM
.reset( new ::comphelper::SequenceAsHashMap( GetModel()->getArgs() ) );
391 return *m_pDocumentPropsHM
;
395 OUString
const & ModelData_Impl::GetModuleName()
397 if ( m_aModuleName
.isEmpty() )
399 m_aModuleName
= m_pOwner
->GetModuleManager()->identify(
400 uno::Reference
< uno::XInterface
>( m_xModel
, uno::UNO_QUERY
) );
401 if ( m_aModuleName
.isEmpty() )
402 throw uno::RuntimeException(); // TODO:
404 return m_aModuleName
;
408 const ::comphelper::SequenceAsHashMap
& ModelData_Impl::GetModuleProps()
410 if ( !m_pModulePropsHM
)
412 uno::Sequence
< beans::PropertyValue
> aModuleProps
;
413 m_pOwner
->GetModuleManager()->getByName( GetModuleName() ) >>= aModuleProps
;
414 if ( !aModuleProps
.hasElements() )
415 throw uno::RuntimeException(); // TODO;
416 m_pModulePropsHM
.reset( new ::comphelper::SequenceAsHashMap( aModuleProps
) );
419 return *m_pModulePropsHM
;
423 OUString
ModelData_Impl::GetDocServiceName()
425 return GetModuleProps().getUnpackedValueOrDefault("ooSetupFactoryDocumentService", OUString());
429 void ModelData_Impl::CheckInteractionHandler()
431 const OUString sInteractionHandler
{"InteractionHandler"};
432 ::comphelper::SequenceAsHashMap::const_iterator aInteractIter
=
433 m_aMediaDescrHM
.find( sInteractionHandler
);
435 if ( aInteractIter
== m_aMediaDescrHM
.end() )
438 m_aMediaDescrHM
[ sInteractionHandler
]
439 <<= task::InteractionHandler::createWithParent( comphelper::getProcessComponentContext(), nullptr);
441 catch( const uno::Exception
& )
447 uno::Reference
< task::XInteractionHandler
> xInteract
;
448 DBG_ASSERT( ( aInteractIter
->second
>>= xInteract
) && xInteract
.is(), "Broken interaction handler is provided!\n" );
453 uno::Sequence
< beans::PropertyValue
> ModelData_Impl::GetDocServiceDefaultFilter()
455 uno::Sequence
< beans::PropertyValue
> aProps
;
457 const OUString aFilterName
= GetModuleProps().getUnpackedValueOrDefault( "ooSetupFactoryDefaultFilter", OUString() );
459 m_pOwner
->GetFilterConfiguration()->getByName( aFilterName
) >>= aProps
;
465 uno::Sequence
< beans::PropertyValue
> ModelData_Impl::GetDocServiceDefaultFilterCheckFlags( SfxFilterFlags nMust
,
466 SfxFilterFlags nDont
)
468 uno::Sequence
< beans::PropertyValue
> aFilterProps
;
469 uno::Sequence
< beans::PropertyValue
> aProps
= GetDocServiceDefaultFilter();
470 if ( aProps
.hasElements() )
472 ::comphelper::SequenceAsHashMap
aFiltHM( aProps
);
473 SfxFilterFlags nFlags
= static_cast<SfxFilterFlags
>(aFiltHM
.getUnpackedValueOrDefault("Flags",
475 if ( ( ( nFlags
& nMust
) == nMust
) && !( nFlags
& nDont
) )
476 aFilterProps
= aProps
;
483 uno::Sequence
< beans::PropertyValue
> ModelData_Impl::GetDocServiceAnyFilter( SfxFilterFlags nMust
, SfxFilterFlags nDont
)
485 uno::Sequence
< beans::NamedValue
> aSearchRequest
{ { "DocumentService", css::uno::makeAny(GetDocServiceName()) } };
487 return ::comphelper::MimeConfigurationHelper::SearchForFilter( m_pOwner
->GetFilterQuery(), aSearchRequest
, nMust
, nDont
);
491 uno::Sequence
< beans::PropertyValue
> ModelData_Impl::GetPreselectedFilter_Impl( sal_Int16 nStoreMode
)
493 if ( nStoreMode
== SAVEASREMOTE_REQUESTED
)
494 nStoreMode
= SAVEAS_REQUESTED
;
496 uno::Sequence
< beans::PropertyValue
> aFilterProps
;
498 SfxFilterFlags nMust
= getMustFlags( nStoreMode
);
499 SfxFilterFlags nDont
= getDontFlags( nStoreMode
);
501 if ( ( nStoreMode
!= SAVEASREMOTE_REQUESTED
) && ( nStoreMode
& PDFEXPORT_REQUESTED
) )
503 // Preselect PDF-Filter for EXPORT
504 uno::Sequence
< beans::NamedValue
> aSearchRequest
506 { "Type", css::uno::makeAny(OUString("pdf_Portable_Document_Format")) },
507 { "DocumentService", css::uno::makeAny(GetDocServiceName()) }
510 aFilterProps
= ::comphelper::MimeConfigurationHelper::SearchForFilter( m_pOwner
->GetFilterQuery(), aSearchRequest
, nMust
, nDont
);
512 else if ( ( nStoreMode
!= SAVEASREMOTE_REQUESTED
) && ( nStoreMode
& EPUBEXPORT_REQUESTED
) )
514 // Preselect EPUB filter for export.
515 uno::Sequence
<beans::NamedValue
> aSearchRequest
517 { "Type", css::uno::makeAny(OUString("writer_EPUB_Document")) },
518 { "DocumentService", css::uno::makeAny(GetDocServiceName()) }
521 aFilterProps
= ::comphelper::MimeConfigurationHelper::SearchForFilter( m_pOwner
->GetFilterQuery(), aSearchRequest
, nMust
, nDont
);
525 aFilterProps
= GetDocServiceDefaultFilterCheckFlags( nMust
, nDont
);
527 if ( !aFilterProps
.hasElements() )
529 // the default filter was not found, use just the first acceptable one
530 aFilterProps
= GetDocServiceAnyFilter( nMust
, nDont
);
538 bool ModelData_Impl::ExecuteFilterDialog_Impl( const OUString
& aFilterName
)
540 bool bDialogUsed
= false;
543 uno::Sequence
< beans::PropertyValue
> aProps
;
544 uno::Any aAny
= m_pOwner
->GetFilterConfiguration()->getByName( aFilterName
);
545 if ( aAny
>>= aProps
)
547 auto pProp
= std::find_if(aProps
.begin(), aProps
.end(),
548 [](const beans::PropertyValue
& rProp
) { return rProp
.Name
== "UIComponent"; });
549 if (pProp
!= aProps
.end())
551 OUString aServiceName
;
552 pProp
->Value
>>= aServiceName
;
553 if( !aServiceName
.isEmpty() )
555 uno::Sequence
<uno::Any
> aDialogArgs(comphelper::InitAnyPropertySequence(
557 {"ParentWindow", uno::Any(SfxStoringHelper::GetModelXWindow(m_xModel
))},
560 uno::Reference
< ui::dialogs::XExecutableDialog
> xFilterDialog(
561 comphelper::getProcessServiceFactory()->createInstanceWithArguments(aServiceName
, aDialogArgs
), uno::UNO_QUERY
);
562 uno::Reference
< beans::XPropertyAccess
> xFilterProperties( xFilterDialog
, uno::UNO_QUERY
);
564 if( xFilterDialog
.is() && xFilterProperties
.is() )
568 uno::Reference
< document::XExporter
> xExporter( xFilterDialog
, uno::UNO_QUERY
);
570 xExporter
->setSourceDocument( GetModel() );
572 uno::Sequence
< beans::PropertyValue
> aPropsForDialog
;
573 GetMediaDescr() >> aPropsForDialog
;
574 xFilterProperties
->setPropertyValues( aPropsForDialog
);
576 if( !xFilterDialog
->execute() )
578 throw task::ErrorCodeIOException(
579 ("ModelData_Impl::ExecuteFilterDialog_Impl:"
580 " ERRCODE_IO_ABORT"),
581 uno::Reference
< uno::XInterface
>(),
582 sal_uInt32(ERRCODE_IO_ABORT
));
585 const uno::Sequence
< beans::PropertyValue
> aPropsFromDialog
=
586 xFilterProperties
->getPropertyValues();
587 for ( const auto& rProp
: aPropsFromDialog
)
588 GetMediaDescr()[rProp
.Name
] = rProp
.Value
;
594 catch( const container::NoSuchElementException
& e
)
596 // the filter name is unknown
597 throw task::ErrorCodeIOException(
598 ("ModelData_Impl::ExecuteFilterDialog_Impl: NoSuchElementException"
599 " \"" + e
.Message
+ "\": ERRCODE_IO_ABORT"),
600 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_INVALIDPARAMETER
));
602 catch( const task::ErrorCodeIOException
& )
606 catch( const uno::Exception
& )
608 TOOLS_WARN_EXCEPTION("sfx.doc", "ignoring");
615 sal_Int8
ModelData_Impl::CheckSaveAcceptable( sal_Int8 nCurStatus
)
617 sal_Int8 nResult
= nCurStatus
;
619 if ( nResult
!= STATUS_NO_ACTION
&& GetStorable()->hasLocation() )
621 // the saving is acceptable
622 // in case the configuration entry is not set or set to false
623 // or in case of version creation
624 if ( officecfg::Office::Common::Save::Document::AlwaysSaveAs::get()
625 && GetMediaDescr().find( OUString("VersionComment") ) == GetMediaDescr().end() )
627 // notify the user that SaveAs is going to be done
628 std::unique_ptr
<weld::MessageDialog
> xMessageBox(Application::CreateMessageDialog(SfxStoringHelper::GetModelWindow(m_xModel
),
629 VclMessageType::Question
, VclButtonsType::OkCancel
, SfxResId(STR_NEW_FILENAME_SAVE
)));
630 if (xMessageBox
->run() == RET_OK
)
631 nResult
= STATUS_SAVEAS
;
633 nResult
= STATUS_NO_ACTION
;
641 sal_Int8
ModelData_Impl::CheckStateForSave()
643 // if the document is readonly or a new one a SaveAs operation must be used
644 if ( !GetStorable()->hasLocation() || GetStorable()->isReadonly() )
645 return STATUS_SAVEAS
;
647 // check acceptable entries for media descriptor
648 ::comphelper::SequenceAsHashMap aAcceptedArgs
;
650 const OUString
aVersionCommentString("VersionComment");
651 const OUString
aAuthorString("Author");
652 const OUString
aDontTerminateEdit("DontTerminateEdit");
653 const OUString
aInteractionHandlerString("InteractionHandler");
654 const OUString
aStatusIndicatorString("StatusIndicator");
655 const OUString
aFailOnWarningString("FailOnWarning");
656 const OUString
aNoFileSync("NoFileSync");
658 if ( GetMediaDescr().find( aVersionCommentString
) != GetMediaDescr().end() )
659 aAcceptedArgs
[ aVersionCommentString
] = GetMediaDescr()[ aVersionCommentString
];
660 if ( GetMediaDescr().find( aAuthorString
) != GetMediaDescr().end() )
661 aAcceptedArgs
[ aAuthorString
] = GetMediaDescr()[ aAuthorString
];
662 if ( GetMediaDescr().find( aDontTerminateEdit
) != GetMediaDescr().end() )
663 aAcceptedArgs
[ aDontTerminateEdit
] = GetMediaDescr()[ aDontTerminateEdit
];
664 if ( GetMediaDescr().find( aInteractionHandlerString
) != GetMediaDescr().end() )
665 aAcceptedArgs
[ aInteractionHandlerString
] = GetMediaDescr()[ aInteractionHandlerString
];
666 if ( GetMediaDescr().find( aStatusIndicatorString
) != GetMediaDescr().end() )
667 aAcceptedArgs
[ aStatusIndicatorString
] = GetMediaDescr()[ aStatusIndicatorString
];
668 if ( GetMediaDescr().find( aFailOnWarningString
) != GetMediaDescr().end() )
669 aAcceptedArgs
[ aFailOnWarningString
] = GetMediaDescr()[ aFailOnWarningString
];
670 if (GetMediaDescr().find(aNoFileSync
) != GetMediaDescr().end())
671 aAcceptedArgs
[aNoFileSync
] = GetMediaDescr()[aNoFileSync
];
673 // remove unacceptable entry if there is any
674 DBG_ASSERT( GetMediaDescr().size() == aAcceptedArgs
.size(),
675 "Unacceptable parameters are provided in Save request!\n" );
676 if ( GetMediaDescr().size() != aAcceptedArgs
.size() )
677 GetMediaDescr() = aAcceptedArgs
;
679 // check that the old filter is acceptable
680 return CheckFilter( GetDocProps().getUnpackedValueOrDefault(aFilterNameString
, OUString()) );
683 sal_Int8
ModelData_Impl::CheckFilter( const OUString
& aFilterName
)
685 ::comphelper::SequenceAsHashMap aFiltPropsHM
;
686 SfxFilterFlags nFiltFlags
= SfxFilterFlags::NONE
;
687 if ( !aFilterName
.isEmpty() )
689 // get properties of filter
690 uno::Sequence
< beans::PropertyValue
> aFilterProps
;
691 m_pOwner
->GetFilterConfiguration()->getByName( aFilterName
) >>= aFilterProps
;
693 aFiltPropsHM
= ::comphelper::SequenceAsHashMap( aFilterProps
);
694 nFiltFlags
= static_cast<SfxFilterFlags
>(aFiltPropsHM
.getUnpackedValueOrDefault("Flags", sal_Int32(0) ));
697 // only a temporary solution until default filter retrieving feature is implemented
698 // then GetDocServiceDefaultFilter() must be used
699 ::comphelper::SequenceAsHashMap aDefFiltPropsHM
= GetDocServiceDefaultFilterCheckFlags( SfxFilterFlags::IMPORT
| SfxFilterFlags::EXPORT
, SfxFilterFlags::NONE
);
700 SfxFilterFlags nDefFiltFlags
= static_cast<SfxFilterFlags
>(aDefFiltPropsHM
.getUnpackedValueOrDefault("Flags", sal_Int32(0) ));
704 // if the old filter is not acceptable
705 // and there is no default filter or it is not acceptable for requested parameters then proceed with saveAs
706 if ( ( aFiltPropsHM
.empty() || !( nFiltFlags
& SfxFilterFlags::EXPORT
) )
707 && ( aDefFiltPropsHM
.empty() || !( nDefFiltFlags
& SfxFilterFlags::EXPORT
) || nDefFiltFlags
& SfxFilterFlags::INTERNAL
) )
708 return STATUS_SAVEAS
;
710 // so at this point there is either an acceptable old filter or default one
711 if ( aFiltPropsHM
.empty() || !( nFiltFlags
& SfxFilterFlags::EXPORT
) )
713 // so the default filter must be acceptable
714 return STATUS_SAVEAS_STANDARDNAME
;
716 else if ( ( !( nFiltFlags
& SfxFilterFlags::OWN
) || ( nFiltFlags
& SfxFilterFlags::ALIEN
) )
717 && !aDefFiltPropsHM
.empty()
718 && ( nDefFiltFlags
& SfxFilterFlags::EXPORT
) && !( nDefFiltFlags
& SfxFilterFlags::INTERNAL
))
723 // check if EncryptionData supports this output format
725 OUString aSupportedFilters
;
726 const ::comphelper::SequenceAsHashMap
& rDocumentProperties
= GetDocProps();
727 const css::uno::Sequence
<css::beans::NamedValue
> aEncryptionData
= rDocumentProperties
.getUnpackedValueOrDefault("EncryptionData", css::uno::Sequence
<css::beans::NamedValue
>());
728 if (aEncryptionData
!= css::uno::Sequence
<css::beans::NamedValue
>())
730 for (const css::beans::NamedValue
& aNamedValue
: aEncryptionData
)
732 if (aNamedValue
.Name
== "SupportedFilters")
734 aNamedValue
.Value
>>= aSupportedFilters
;
739 // if 'SupportedFilters' is empty assume that all filters are supported.
740 if (!aSupportedFilters
.isEmpty())
742 const OUString aSelectedFilter
= aFiltPropsHM
.getUnpackedValueOrDefault("UIName", OUString());
744 aSupportedFilters
= ";" + aSupportedFilters
+ ";";
745 const OUString aSearchToken
= ";" + aSelectedFilter
+ ";";
746 bAsk
= (aSupportedFilters
.indexOf(aSearchToken
) < 0);
752 // the default filter is acceptable and the old filter is alien one
753 // so ask to make a saveAs operation
754 const OUString aUIName
= aFiltPropsHM
.getUnpackedValueOrDefault("UIName", OUString() );
755 const OUString aDefUIName
= aDefFiltPropsHM
.getUnpackedValueOrDefault("UIName", OUString() );
756 const OUString aPreusedFilterName
= GetDocProps().getUnpackedValueOrDefault("PreusedFilterName", OUString() );
757 const OUString aDefType
= aDefFiltPropsHM
.getUnpackedValueOrDefault( "Type", OUString() );
758 const OUString aDefExtension
= GetRecommendedExtension( aDefType
);
760 if ( aPreusedFilterName
!= aFilterName
&& aUIName
!= aDefUIName
)
762 if ( !SfxStoringHelper::WarnUnacceptableFormat( GetModel(), aUIName
, aDefExtension
,
763 static_cast<bool>( nDefFiltFlags
& SfxFilterFlags::ALIEN
) ) )
764 return STATUS_SAVEAS_STANDARDNAME
;
772 bool ModelData_Impl::CheckFilterOptionsDialogExistence()
774 uno::Sequence
< beans::NamedValue
> aSearchRequest
{ { "DocumentService", css::uno::makeAny(GetDocServiceName()) } };
776 uno::Reference
< container::XEnumeration
> xFilterEnum
=
777 m_pOwner
->GetFilterQuery()->createSubSetEnumerationByProperties( aSearchRequest
);
779 while ( xFilterEnum
->hasMoreElements() )
781 uno::Sequence
< beans::PropertyValue
> aProps
;
782 if ( xFilterEnum
->nextElement() >>= aProps
)
784 ::comphelper::SequenceAsHashMap
aPropsHM( aProps
);
785 if ( !aPropsHM
.getUnpackedValueOrDefault("UIComponent", OUString()).isEmpty() )
794 bool ModelData_Impl::OutputFileDialog( sal_Int16 nStoreMode
,
795 const ::comphelper::SequenceAsHashMap
& aPreselectedFilterPropsHM
,
796 bool bSetStandardName
,
797 OUString
& aSuggestedName
,
798 bool bPreselectPassword
,
799 OUString
& aSuggestedDir
,
801 const OUString
& rStandardDir
,
802 const css::uno::Sequence
< OUString
>& rDenyList
)
804 if ( nStoreMode
== SAVEASREMOTE_REQUESTED
)
805 nStoreMode
= SAVEAS_REQUESTED
;
807 bool bUseFilterOptions
= false;
809 ::comphelper::SequenceAsHashMap::const_iterator aOverwriteIter
=
810 GetMediaDescr().find( OUString("Overwrite") );
812 // the file name must be specified if overwrite option is set
813 if ( aOverwriteIter
!= GetMediaDescr().end() )
814 throw task::ErrorCodeIOException(
815 "ModelData_Impl::OutputFileDialog: ERRCODE_IO_INVALIDPARAMETER",
816 uno::Reference
< uno::XInterface
>(),
817 sal_uInt32(ERRCODE_IO_INVALIDPARAMETER
));
819 // no target file name is specified
820 // we need to show the file dialog
822 // check if we have a filter which allows for filter options, so we need a corresponding checkbox in the dialog
823 bool bAllowOptions
= false;
825 // in case of Export, filter options dialog is used if available
826 if( !( nStoreMode
& EXPORT_REQUESTED
) || ( nStoreMode
& WIDEEXPORT_REQUESTED
) )
827 bAllowOptions
= CheckFilterOptionsDialogExistence();
829 // get the filename by dialog ...
830 // create the file dialog
831 sal_Int16 aDialogMode
= bAllowOptions
832 ? css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
833 : css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD
;
834 FileDialogFlags aDialogFlags
= FileDialogFlags::NONE
;
836 if( ( nStoreMode
& EXPORT_REQUESTED
) && !( nStoreMode
& WIDEEXPORT_REQUESTED
) )
838 if ( (nStoreMode
& PDFEXPORT_REQUESTED
) || (nStoreMode
& EPUBEXPORT_REQUESTED
) )
839 aDialogMode
= css::ui::dialogs::TemplateDescription::
840 FILESAVE_AUTOEXTENSION
;
842 aDialogMode
= css::ui::dialogs::TemplateDescription::
843 FILESAVE_AUTOEXTENSION_SELECTION
;
844 aDialogFlags
= FileDialogFlags::Export
;
847 if( ( nStoreMode
& EXPORT_REQUESTED
) && ( nStoreMode
& SAVEACOPY_REQUESTED
) && ( nStoreMode
& WIDEEXPORT_REQUESTED
) )
849 aDialogFlags
= FileDialogFlags::SaveACopy
;
852 std::unique_ptr
<sfx2::FileDialogHelper
> pFileDlg
;
854 const OUString aDocServiceName
{GetDocServiceName()};
855 DBG_ASSERT( !aDocServiceName
.isEmpty(), "No document service for this module set!" );
857 SfxFilterFlags nMust
= getMustFlags( nStoreMode
);
858 SfxFilterFlags nDont
= getDontFlags( nStoreMode
);
859 weld::Window
* pFrameWin
= SfxStoringHelper::GetModelWindow(m_xModel
);
860 if ( ( nStoreMode
& EXPORT_REQUESTED
) && !( nStoreMode
& WIDEEXPORT_REQUESTED
) )
862 if ( ( nStoreMode
& PDFEXPORT_REQUESTED
) && !aPreselectedFilterPropsHM
.empty() )
864 // this is a PDF export
865 // the filter options has been shown already
866 const OUString aFilterUIName
= aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( "UIName", OUString() );
867 pFileDlg
.reset(new sfx2::FileDialogHelper( aDialogMode
, aDialogFlags
, aFilterUIName
, "pdf", rStandardDir
, rDenyList
, pFrameWin
));
868 pFileDlg
->SetCurrentFilter( aFilterUIName
);
870 else if ((nStoreMode
& EPUBEXPORT_REQUESTED
) && !aPreselectedFilterPropsHM
.empty())
872 // This is an EPUB export, the filter options has been shown already.
873 const OUString aFilterUIName
= aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( "UIName", OUString() );
874 pFileDlg
.reset(new sfx2::FileDialogHelper(aDialogMode
, aDialogFlags
, aFilterUIName
, "epub", rStandardDir
, rDenyList
, pFrameWin
));
875 pFileDlg
->SetCurrentFilter(aFilterUIName
);
879 // This is the normal dialog
880 pFileDlg
.reset(new sfx2::FileDialogHelper( aDialogMode
, aDialogFlags
, aDocServiceName
, nDialog
, nMust
, nDont
, rStandardDir
, rDenyList
, pFrameWin
));
883 sfx2::FileDialogHelper::Context eCtxt
= sfx2::FileDialogHelper::UNKNOWN_CONTEXT
;
884 if ( aDocServiceName
== "com.sun.star.drawing.DrawingDocument" )
885 eCtxt
= sfx2::FileDialogHelper::SD_EXPORT
;
886 else if ( aDocServiceName
== "com.sun.star.presentation.PresentationDocument" )
887 eCtxt
= sfx2::FileDialogHelper::SI_EXPORT
;
888 else if ( aDocServiceName
== "com.sun.star.text.TextDocument" )
889 eCtxt
= sfx2::FileDialogHelper::SW_EXPORT
;
891 if ( eCtxt
!= sfx2::FileDialogHelper::UNKNOWN_CONTEXT
)
892 pFileDlg
->SetContext( eCtxt
);
894 pFileDlg
->CreateMatcher( aDocServiceName
);
896 uno::Reference
< ui::dialogs::XFilePicker3
> xFilePicker
= pFileDlg
->GetFilePicker();
897 uno::Reference
< ui::dialogs::XFilePickerControlAccess
> xControlAccess( xFilePicker
, uno::UNO_QUERY
);
899 if ( xControlAccess
.is() )
901 xControlAccess
->setLabel( ui::dialogs::CommonFilePickerElementIds::PUSHBUTTON_OK
, SfxResId(STR_EXPORTBUTTON
) );
902 xControlAccess
->setLabel( ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER_LABEL
, SfxResId(STR_LABEL_FILEFORMAT
) );
907 // This is the normal dialog
908 pFileDlg
.reset(new sfx2::FileDialogHelper( aDialogMode
, aDialogFlags
, aDocServiceName
, nDialog
,
909 nMust
, nDont
, rStandardDir
, rDenyList
, pFrameWin
));
910 pFileDlg
->CreateMatcher( aDocServiceName
);
913 OUString aAdjustToType
;
915 const OUString
sFilterNameString(aFilterNameString
);
917 if ( ( nStoreMode
& EXPORT_REQUESTED
) && !( nStoreMode
& WIDEEXPORT_REQUESTED
) )
919 // it is export, set the preselected filter
920 pFileDlg
->SetCurrentFilter( aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( "UIName", OUString() ) );
921 aAdjustToType
= aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( "Type", OUString() );
923 // it is no export, bSetStandardName == true means that user agreed to store document in the default (default default ;-)) format
924 else if ( bSetStandardName
|| GetStorable()->hasLocation() )
926 uno::Sequence
< beans::PropertyValue
> aOldFilterProps
;
927 const OUString aOldFilterName
= GetDocProps().getUnpackedValueOrDefault( sFilterNameString
, OUString() );
929 if ( !aOldFilterName
.isEmpty() )
930 m_pOwner
->GetFilterConfiguration()->getByName( aOldFilterName
) >>= aOldFilterProps
;
932 ::comphelper::SequenceAsHashMap
aOldFiltPropsHM( aOldFilterProps
);
933 SfxFilterFlags nOldFiltFlags
= static_cast<SfxFilterFlags
>(aOldFiltPropsHM
.getUnpackedValueOrDefault("Flags", sal_Int32(0) ));
935 if ( bSetStandardName
|| ( nOldFiltFlags
& nMust
) != nMust
|| bool(nOldFiltFlags
& nDont
) )
937 // the suggested type will be changed, the extension should be adjusted
938 aAdjustToType
= aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( "Type", OUString() );
939 pFileDlg
->SetCurrentFilter( aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( "UIName", OUString() ) );
943 pFileDlg
->SetCurrentFilter( aOldFiltPropsHM
.getUnpackedValueOrDefault(
949 const OUString aRecommendedDir
{GetRecommendedDir( aSuggestedDir
)};
950 if ( !aRecommendedDir
.isEmpty() )
951 pFileDlg
->SetDisplayFolder( aRecommendedDir
);
952 const OUString aRecommendedName
{GetRecommendedName( aSuggestedName
, aAdjustToType
)};
953 if ( !aRecommendedName
.isEmpty() )
954 pFileDlg
->SetFileName( aRecommendedName
);
956 uno::Reference
< view::XSelectionSupplier
> xSel( GetModel()->getCurrentController(), uno::UNO_QUERY
);
957 if ( xSel
.is() && xSel
->getSelection().hasValue() )
958 GetMediaDescr()[OUString("SelectionOnly")] <<= true;
960 // This is a temporary hardcoded solution must be removed when
961 // dialogs do not need parameters in SidSet representation any more
962 sal_uInt16 nSlotID
= getSlotIDFromMode( nStoreMode
);
964 throw lang::IllegalArgumentException(); // TODO:
966 // generate SidSet from MediaDescriptor and provide it into FileDialog
967 // than merge changed SidSet back
968 std::unique_ptr
<SfxItemSet
> pDialogParams(new SfxAllItemSet( SfxGetpApp()->GetPool() ));
969 TransformParameters( nSlotID
,
970 GetMediaDescr().getAsConstPropertyValueList(),
971 static_cast<SfxAllItemSet
&>(*pDialogParams
) );
973 const SfxPoolItem
* pItem
= nullptr;
974 if ( bPreselectPassword
&& pDialogParams
->GetItemState( SID_ENCRYPTIONDATA
, true, &pItem
) != SfxItemState::SET
)
976 // the file dialog preselects the password checkbox if the provided mediadescriptor has encryption data entry
977 // after dialog execution the password interaction flag will be either removed or not
978 pDialogParams
->Put( SfxBoolItem( SID_PASSWORDINTERACTION
, true ) );
981 // aFilterName is a pure output parameter, pDialogParams is an in/out parameter
982 OUString aFilterName
;
983 if ( pFileDlg
->Execute( pDialogParams
, aFilterName
) != ERRCODE_NONE
)
985 throw task::ErrorCodeIOException(
986 "ModelData_Impl::OutputFileDialog: ERRCODE_IO_ABORT",
987 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_ABORT
));
990 // the following two arguments can not be converted in MediaDescriptor,
991 // so they should be removed from the ItemSet after retrieving
992 const SfxBoolItem
* pRecommendReadOnly
= SfxItemSet::GetItem
<SfxBoolItem
>(pDialogParams
.get(), SID_RECOMMENDREADONLY
, false);
993 m_bRecommendReadOnly
= ( pRecommendReadOnly
&& pRecommendReadOnly
->GetValue() );
994 pDialogParams
->ClearItem( SID_RECOMMENDREADONLY
);
996 uno::Sequence
< beans::PropertyValue
> aPropsFromDialog
;
997 TransformItems( nSlotID
, *pDialogParams
, aPropsFromDialog
);
998 GetMediaDescr() << aPropsFromDialog
;
1000 // get the path from the dialog
1001 INetURLObject
aURL( pFileDlg
->GetPath() );
1002 // the path should be provided outside since it might be used for further calls to the dialog
1003 aSuggestedName
= aURL
.GetLastName(INetURLObject::DecodeMechanism::WithCharset
);
1004 aSuggestedDir
= pFileDlg
->GetDisplayDirectory();
1006 // old filter options should be cleared in case different filter is used
1008 const OUString aFilterFromMediaDescr
= GetMediaDescr().getUnpackedValueOrDefault( sFilterNameString
, OUString() );
1009 const OUString aOldFilterName
= GetDocProps().getUnpackedValueOrDefault( sFilterNameString
, OUString() );
1011 const OUString
sFilterOptionsString(aFilterOptionsString
);
1012 const OUString
sFilterDataString(aFilterDataString
);
1014 if ( aFilterName
== aFilterFromMediaDescr
)
1016 // preserve current settings if any
1017 // if there no current settings and the name is the same
1018 // as old filter name use old filter settings
1020 if ( aFilterFromMediaDescr
== aOldFilterName
)
1022 ::comphelper::SequenceAsHashMap::const_iterator aIter
=
1023 GetDocProps().find( sFilterOptionsString
);
1024 if ( aIter
!= GetDocProps().end()
1025 && GetMediaDescr().find( sFilterOptionsString
) == GetMediaDescr().end() )
1026 GetMediaDescr()[aIter
->first
] = aIter
->second
;
1028 aIter
= GetDocProps().find( sFilterDataString
);
1029 if ( aIter
!= GetDocProps().end()
1030 && GetMediaDescr().find( sFilterDataString
) == GetMediaDescr().end() )
1031 GetMediaDescr()[aIter
->first
] = aIter
->second
;
1036 GetMediaDescr().erase( sFilterDataString
);
1037 GetMediaDescr().erase( sFilterOptionsString
);
1039 if ( aFilterName
== aOldFilterName
)
1041 // merge filter option of the document filter
1043 ::comphelper::SequenceAsHashMap::const_iterator aIter
=
1044 GetDocProps().find( sFilterOptionsString
);
1045 if ( aIter
!= GetDocProps().end() )
1046 GetMediaDescr()[aIter
->first
] = aIter
->second
;
1048 aIter
= GetDocProps().find( sFilterDataString
);
1049 if ( aIter
!= GetDocProps().end() )
1050 GetMediaDescr()[aIter
->first
] = aIter
->second
;
1054 uno::Reference
< ui::dialogs::XFilePickerControlAccess
> xExtFileDlg( pFileDlg
->GetFilePicker(), uno::UNO_QUERY
);
1055 if ( xExtFileDlg
.is() )
1057 if ( SfxStoringHelper::CheckFilterOptionsAppearance( m_pOwner
->GetFilterConfiguration(), aFilterName
) )
1058 bUseFilterOptions
= true;
1060 if ( ( !( nStoreMode
& EXPORT_REQUESTED
) || ( nStoreMode
& WIDEEXPORT_REQUESTED
) ) && bUseFilterOptions
)
1064 // for exporters: always show dialog if format uses options
1065 // for save: show dialog if format uses options and no options given or if forced by user
1067 xExtFileDlg
->getValue( ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
, 0 );
1069 aVal
>>= bUseFilterOptions
;
1070 if ( !bUseFilterOptions
)
1072 ( GetMediaDescr().find( sFilterDataString
) == GetMediaDescr().end()
1073 && GetMediaDescr().find( sFilterOptionsString
) == GetMediaDescr().end() );
1075 catch( const lang::IllegalArgumentException
& )
1080 // merge in results of the dialog execution
1081 GetMediaDescr()[OUString("URL")] <<= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1082 GetMediaDescr()[sFilterNameString
] <<= aFilterName
;
1084 return bUseFilterOptions
;
1088 bool ModelData_Impl::ShowDocumentInfoDialog(const std::function
< void () >& aFunc
)
1090 bool bDialogUsed
= false;
1093 uno::Reference
< frame::XController
> xController
= GetModel()->getCurrentController();
1094 if ( xController
.is() )
1096 uno::Reference
< frame::XDispatchProvider
> xFrameDispatch( xController
->getFrame(), uno::UNO_QUERY
);
1097 if ( xFrameDispatch
.is() )
1100 aURL
.Complete
= ".uno:SetDocumentProperties";
1102 uno::Reference
< util::XURLTransformer
> xTransformer( util::URLTransformer::create( comphelper::getProcessComponentContext() ) );
1103 if ( xTransformer
->parseStrict( aURL
) )
1105 uno::Reference
< frame::XDispatch
> xDispatch
= xFrameDispatch
->queryDispatch(
1109 if ( xDispatch
.is() )
1111 uno::Sequence
< beans::PropertyValue
> aProperties(1);
1112 uno::Reference
< lang::XUnoTunnel
> aAsyncFunc(new AsyncFunc(aFunc
));
1113 aProperties
[0].Name
= "AsyncFunc";
1114 aProperties
[0].Value
<<= aAsyncFunc
;
1115 xDispatch
->dispatch( aURL
, aProperties
);
1122 catch ( const uno::Exception
& )
1130 OUString
ModelData_Impl::GetRecommendedExtension( const OUString
& aTypeName
)
1132 if ( aTypeName
.isEmpty() )
1135 uno::Reference
< container::XNameAccess
> xTypeDetection(
1136 comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.TypeDetection"),
1138 if ( xTypeDetection
.is() )
1140 uno::Sequence
< beans::PropertyValue
> aTypeNameProps
;
1141 if ( ( xTypeDetection
->getByName( aTypeName
) >>= aTypeNameProps
) && aTypeNameProps
.hasElements() )
1143 ::comphelper::SequenceAsHashMap
aTypeNamePropsHM( aTypeNameProps
);
1144 uno::Sequence
< OUString
> aExtensions
= aTypeNamePropsHM
.getUnpackedValueOrDefault(
1146 ::uno::Sequence
< OUString
>() );
1147 if ( aExtensions
.hasElements() )
1148 return aExtensions
[0];
1156 OUString
ModelData_Impl::GetRecommendedDir( const OUString
& aSuggestedDir
)
1158 if ( ( !aSuggestedDir
.isEmpty() || GetStorable()->hasLocation() )
1159 && !GetMediaDescr().getUnpackedValueOrDefault("RepairPackage", false ) )
1161 INetURLObject aLocation
;
1162 if ( !aSuggestedDir
.isEmpty() )
1163 aLocation
= INetURLObject( aSuggestedDir
);
1166 const OUString aOldURL
= GetStorable()->getLocation();
1167 if ( !aOldURL
.isEmpty() )
1169 INetURLObject
aTmp( aOldURL
);
1170 if ( aTmp
.removeSegment() )
1174 if ( aLocation
.HasError() )
1175 aLocation
= INetURLObject( SvtPathOptions().GetWorkPath() );
1178 OUString
sLocationURL( aLocation
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
1179 bool bIsInTempPath( false );
1180 OUString sSysTempPath
;
1181 if( osl::FileBase::getTempDirURL( sSysTempPath
) == osl::FileBase::E_None
)
1182 bIsInTempPath
= !sSysTempPath
.isEmpty() && sLocationURL
.startsWith( sSysTempPath
);
1184 if( !bIsInTempPath
)
1186 wchar_t sPath
[MAX_PATH
+1];
1187 HRESULT hRes
= SHGetFolderPathW( nullptr, CSIDL_INTERNET_CACHE
, nullptr, SHGFP_TYPE_CURRENT
, sPath
);
1188 if( SUCCEEDED(hRes
) )
1190 OUString sTempINetFiles
;
1191 if( osl::FileBase::getFileURLFromSystemPath(OUString(o3tl::toU(sPath
)), sTempINetFiles
) == osl::FileBase::E_None
)
1192 bIsInTempPath
= !sTempINetFiles
.isEmpty() && sLocationURL
.startsWith( sTempINetFiles
);
1196 // Suggest somewhere other than the system's temp directory
1198 aLocation
= INetURLObject( SvtPathOptions().GetWorkPath() );
1200 aLocation
.setFinalSlash();
1201 if ( !aLocation
.HasError() )
1202 return aLocation
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1207 return INetURLObject( SvtPathOptions().GetWorkPath() ).GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1211 OUString
ModelData_Impl::GetRecommendedName( const OUString
& aSuggestedName
, const OUString
& aTypeName
)
1213 // the last used name might be provided by aSuggestedName from the old selection, or from the MediaDescriptor
1214 if ( !aSuggestedName
.isEmpty() )
1215 return aSuggestedName
;
1217 OUString aRecommendedName
{ INetURLObject(GetStorable()->getLocation())
1218 .GetLastName(INetURLObject::DecodeMechanism::WithCharset
) };
1219 if ( aRecommendedName
.isEmpty() )
1222 uno::Reference
< frame::XTitle
> xTitle( GetModel(), uno::UNO_QUERY_THROW
);
1223 aRecommendedName
= xTitle
->getTitle();
1224 } catch( const uno::Exception
& ) {}
1227 if ( !aRecommendedName
.isEmpty() && !aTypeName
.isEmpty() )
1229 // adjust the extension to the type
1230 uno::Reference
< container::XNameAccess
> xTypeDetection(
1231 comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.TypeDetection"),
1233 if ( xTypeDetection
.is() )
1235 INetURLObject
aObj( "c:/" + aRecommendedName
, INetProtocol::File
,
1236 INetURLObject::EncodeMechanism::All
, RTL_TEXTENCODING_UTF8
, FSysStyle::Dos
);
1238 const OUString aExtension
= GetRecommendedExtension( aTypeName
);
1239 if ( !aExtension
.isEmpty() )
1240 aObj
.SetExtension( aExtension
);
1242 aRecommendedName
= aObj
.GetLastName(INetURLObject::DecodeMechanism::WithCharset
);
1246 return aRecommendedName
;
1252 SfxStoringHelper::SfxStoringHelper()
1257 uno::Reference
< container::XNameAccess
> const & SfxStoringHelper::GetFilterConfiguration()
1259 if ( !m_xFilterCFG
.is() )
1261 m_xFilterCFG
.set( comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.FilterFactory"),
1262 uno::UNO_QUERY_THROW
);
1265 return m_xFilterCFG
;
1269 uno::Reference
< container::XContainerQuery
> const & SfxStoringHelper::GetFilterQuery()
1271 if ( !m_xFilterQuery
.is() )
1273 m_xFilterQuery
.set( GetFilterConfiguration(), uno::UNO_QUERY_THROW
);
1276 return m_xFilterQuery
;
1280 uno::Reference
< css::frame::XModuleManager2
> const & SfxStoringHelper::GetModuleManager()
1282 if ( !m_xModuleManager
.is() )
1284 m_xModuleManager
= frame::ModuleManager::create(
1285 comphelper::getProcessComponentContext() );
1288 return m_xModuleManager
;
1293 void LaunchPDFViewer(const INetURLObject
& rURL
)
1295 // Launch PDF viewer
1296 FilterConfigItem
aItem( "Office.Common/Filter/PDF/Export/" );
1297 bool aViewPDF
= aItem
.ReadBool( "ViewPDFAfterExport", false );
1301 uno::Reference
<XSystemShellExecute
> xSystemShellExecute(SystemShellExecute::create(::comphelper::getProcessComponentContext()));
1302 xSystemShellExecute
->execute(rURL
.GetMainURL(INetURLObject::DecodeMechanism::NONE
), "", SystemShellExecuteFlags::URIS_ONLY
);
1307 bool SfxStoringHelper::GUIStoreModel( const uno::Reference
< frame::XModel
>& xModel
,
1308 const OUString
& aSlotName
,
1309 uno::Sequence
< beans::PropertyValue
>& aArgsSequence
,
1310 bool bPreselectPassword
,
1311 SignatureState nDocumentSignatureState
)
1313 ModelData_Impl
aModelData( *this, xModel
, aArgsSequence
);
1315 bool bDialogUsed
= false;
1319 bool bSetStandardName
= false; // can be set only for SaveAs
1321 // parse the slot name
1322 bool bRemote
= false;
1323 sal_Int16 nStoreMode
= getStoreModeFromSlotName( aSlotName
);
1325 if ( nStoreMode
== SAVEASREMOTE_REQUESTED
)
1327 nStoreMode
= SAVEAS_REQUESTED
;
1331 sal_Int8 nStatusSave
= STATUS_NO_ACTION
;
1333 ::comphelper::SequenceAsHashMap::const_iterator aSaveACopyIter
=
1334 aModelData
.GetMediaDescr().find( OUString("SaveACopy") );
1335 if ( aSaveACopyIter
!= aModelData
.GetMediaDescr().end() )
1337 bool bSaveACopy
= false;
1338 aSaveACopyIter
->second
>>= bSaveACopy
;
1340 nStoreMode
= EXPORT_REQUESTED
| SAVEACOPY_REQUESTED
| WIDEEXPORT_REQUESTED
;
1342 // handle the special cases
1343 if ( nStoreMode
& SAVEAS_REQUESTED
)
1345 ::comphelper::SequenceAsHashMap::const_iterator aSaveToIter
=
1346 aModelData
.GetMediaDescr().find( OUString("SaveTo") );
1347 if ( aSaveToIter
!= aModelData
.GetMediaDescr().end() )
1349 bool bWideExport
= false;
1350 aSaveToIter
->second
>>= bWideExport
;
1352 nStoreMode
= EXPORT_REQUESTED
| WIDEEXPORT_REQUESTED
;
1355 // if saving is not acceptable the warning must be shown even in case of SaveAs operation
1356 if ( ( nStoreMode
& SAVEAS_REQUESTED
) && aModelData
.CheckSaveAcceptable( STATUS_SAVEAS
) == STATUS_NO_ACTION
)
1357 throw task::ErrorCodeIOException(
1358 "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT",
1359 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_ABORT
));
1361 else if ( nStoreMode
& SAVE_REQUESTED
)
1363 // if saving is not acceptable by the configuration the warning must be shown
1364 nStatusSave
= aModelData
.CheckSaveAcceptable( STATUS_SAVE
);
1366 if ( nStatusSave
== STATUS_NO_ACTION
)
1367 throw task::ErrorCodeIOException(
1368 "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT",
1369 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_ABORT
));
1370 else if ( nStatusSave
== STATUS_SAVE
)
1372 // check whether it is possible to use save operation
1373 nStatusSave
= aModelData
.CheckStateForSave();
1376 if ( nStatusSave
== STATUS_NO_ACTION
)
1378 throw task::ErrorCodeIOException(
1379 "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT",
1380 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_ABORT
));
1382 else if ( nStatusSave
!= STATUS_SAVE
)
1384 // this should be a usual SaveAs operation
1385 nStoreMode
= SAVEAS_REQUESTED
;
1386 if ( nStatusSave
== STATUS_SAVEAS_STANDARDNAME
)
1387 bSetStandardName
= true;
1391 if (!comphelper::LibreOfficeKit::isActive() && !( nStoreMode
& EXPORT_REQUESTED
) )
1393 // if it is no export, warn user that the signature will be removed
1394 if ( SignatureState::OK
== nDocumentSignatureState
1395 || SignatureState::INVALID
== nDocumentSignatureState
1396 || SignatureState::NOTVALIDATED
== nDocumentSignatureState
1397 || SignatureState::PARTIAL_OK
== nDocumentSignatureState
)
1399 std::unique_ptr
<weld::MessageDialog
> xMessageBox(Application::CreateMessageDialog(SfxStoringHelper::GetModelWindow(xModel
),
1400 VclMessageType::Question
, VclButtonsType::YesNo
, SfxResId(RID_SVXSTR_XMLSEC_QUERY_LOSINGSIGNATURE
)));
1401 if (xMessageBox
->run() != RET_YES
)
1403 // the user has decided not to store the document
1404 throw task::ErrorCodeIOException(
1405 "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT (Preserve Signature)",
1406 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_ABORT
));
1411 if ( nStoreMode
& SAVE_REQUESTED
&& nStatusSave
== STATUS_SAVE
)
1413 // Document properties can contain streams that should be freed before storing
1414 aModelData
.FreeDocumentProps();
1416 if ( aModelData
.GetStorable2().is() )
1420 aModelData
.GetStorable2()->storeSelf( aModelData
.GetMediaDescr().getAsConstPropertyValueList() );
1422 catch (const lang::IllegalArgumentException
&)
1424 TOOLS_WARN_EXCEPTION("sfx.doc", "Ignoring parameters! ModelData considers this illegal");
1425 aModelData
.GetStorable()->store();
1430 OSL_FAIL( "XStorable2 is not supported by the model!" );
1431 aModelData
.GetStorable()->store();
1437 // preselect a filter for the storing process
1438 uno::Sequence
< beans::PropertyValue
> aFilterProps
= aModelData
.GetPreselectedFilter_Impl( nStoreMode
);
1440 DBG_ASSERT( aFilterProps
.hasElements(), "No filter for storing!\n" );
1441 if ( !aFilterProps
.hasElements() )
1442 throw task::ErrorCodeIOException(
1443 "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_INVALIDPARAMETER",
1444 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_INVALIDPARAMETER
));
1446 ::comphelper::SequenceAsHashMap
aFilterPropsHM( aFilterProps
);
1447 OUString aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault( "Name", OUString() );
1449 const OUString
sFilterNameString(aFilterNameString
);
1451 const OUString aFilterFromMediaDescr
= aModelData
.GetMediaDescr().getUnpackedValueOrDefault( sFilterNameString
, OUString() );
1452 const OUString aOldFilterName
= aModelData
.GetDocProps().getUnpackedValueOrDefault( sFilterNameString
, OUString() );
1454 bool bUseFilterOptions
= false;
1455 ::comphelper::SequenceAsHashMap::const_iterator aFileNameIter
= aModelData
.GetMediaDescr().find( OUString("URL") );
1457 const OUString
sFilterOptionsString(aFilterOptionsString
);
1458 const OUString
sFilterDataString(aFilterDataString
);
1460 bool bPDFOptions
= (nStoreMode
& PDFEXPORT_REQUESTED
) && !(nStoreMode
& PDFDIRECTEXPORT_REQUESTED
);
1461 bool bEPUBOptions
= (nStoreMode
& EPUBEXPORT_REQUESTED
) && !(nStoreMode
& EPUBDIRECTEXPORT_REQUESTED
);
1462 if ( ( nStoreMode
& EXPORT_REQUESTED
) && (bPDFOptions
|| bEPUBOptions
) )
1464 // this is PDF or EPUB export, the filter options dialog should be shown before the export
1465 aModelData
.GetMediaDescr()[sFilterNameString
] <<= aFilterName
;
1466 if ( aModelData
.GetMediaDescr().find( "FilterFlags" ) == aModelData
.GetMediaDescr().end()
1467 && aModelData
.GetMediaDescr().find( sFilterOptionsString
) == aModelData
.GetMediaDescr().end()
1468 && aModelData
.GetMediaDescr().find( sFilterDataString
) == aModelData
.GetMediaDescr().end() )
1470 // execute filter options dialog since no options are set in the media descriptor
1471 if ( aModelData
.ExecuteFilterDialog_Impl( aFilterName
) )
1476 if ( aFileNameIter
== aModelData
.GetMediaDescr().end() )
1478 sal_Int16 nDialog
= SFX2_IMPL_DIALOG_CONFIG
;
1482 nDialog
= SFX2_IMPL_DIALOG_REMOTE
;
1486 ::comphelper::SequenceAsHashMap::const_iterator aDlgIter
=
1487 aModelData
.GetMediaDescr().find( OUString("UseSystemDialog") );
1488 if ( aDlgIter
!= aModelData
.GetMediaDescr().end() )
1490 bool bUseSystemDialog
= true;
1491 if ( aDlgIter
->second
>>= bUseSystemDialog
)
1493 if ( bUseSystemDialog
)
1494 nDialog
= SFX2_IMPL_DIALOG_SYSTEM
;
1496 nDialog
= SFX2_IMPL_DIALOG_OOO
;
1501 // The Dispatch supports parameter FolderName that overwrites SuggestedSaveAsDir
1502 OUString aSuggestedDir
= aModelData
.GetMediaDescr().getUnpackedValueOrDefault("FolderName", OUString() );
1503 if ( aSuggestedDir
.isEmpty() )
1505 aSuggestedDir
= aModelData
.GetMediaDescr().getUnpackedValueOrDefault("SuggestedSaveAsDir", OUString() );
1506 if ( aSuggestedDir
.isEmpty() )
1507 aSuggestedDir
= aModelData
.GetDocProps().getUnpackedValueOrDefault("SuggestedSaveAsDir", OUString() );
1510 OUString aSuggestedName
= aModelData
.GetMediaDescr().getUnpackedValueOrDefault("SuggestedSaveAsName", OUString() );
1511 if ( aSuggestedName
.isEmpty() )
1512 aSuggestedName
= aModelData
.GetDocProps().getUnpackedValueOrDefault("SuggestedSaveAsName", OUString() );
1514 OUString sStandardDir
;
1515 ::comphelper::SequenceAsHashMap::const_iterator aStdDirIter
=
1516 aModelData
.GetMediaDescr().find( OUString("StandardDir") );
1517 if ( aStdDirIter
!= aModelData
.GetMediaDescr().end() )
1518 aStdDirIter
->second
>>= sStandardDir
;
1520 css::uno::Sequence
< OUString
> aDenyList
;
1522 ::comphelper::SequenceAsHashMap::const_iterator aDenyListIter
=
1523 aModelData
.GetMediaDescr().find( OUString("DenyList") );
1524 if ( aDenyListIter
!= aModelData
.GetMediaDescr().end() )
1525 aDenyListIter
->second
>>= aDenyList
;
1529 // in case the dialog is opened a second time the folder should be the same as previously navigated to by the user, not what was handed over by initial parameters
1530 bUseFilterOptions
= aModelData
.OutputFileDialog( nStoreMode
, aFilterProps
, bSetStandardName
, aSuggestedName
, bPreselectPassword
, aSuggestedDir
, nDialog
, sStandardDir
, aDenyList
);
1531 if ( nStoreMode
== SAVEAS_REQUESTED
)
1533 // in case of saving check filter for possible alien warning
1534 const OUString aSelFilterName
= aModelData
.GetMediaDescr().getUnpackedValueOrDefault( sFilterNameString
, OUString() );
1535 sal_Int8 nStatusFilterSave
= aModelData
.CheckFilter( aSelFilterName
);
1536 if ( nStatusFilterSave
== STATUS_SAVEAS_STANDARDNAME
)
1538 // switch to best filter
1539 bSetStandardName
= true;
1541 else if ( nStatusFilterSave
== STATUS_SAVE
)
1543 // user confirmed alien filter or "good" filter is used
1552 aFileNameIter
= aModelData
.GetMediaDescr().find( OUString("URL") );
1556 // the target file name is provided so check if new filter options
1557 // are provided or old options can be used
1558 if ( aFilterFromMediaDescr
== aOldFilterName
)
1560 ::comphelper::SequenceAsHashMap::const_iterator aIter
=
1561 aModelData
.GetDocProps().find( sFilterOptionsString
);
1562 if ( aIter
!= aModelData
.GetDocProps().end()
1563 && aModelData
.GetMediaDescr().find( sFilterOptionsString
) == aModelData
.GetMediaDescr().end() )
1564 aModelData
.GetMediaDescr()[aIter
->first
] = aIter
->second
;
1566 aIter
= aModelData
.GetDocProps().find( sFilterDataString
);
1567 if ( aIter
!= aModelData
.GetDocProps().end()
1568 && aModelData
.GetMediaDescr().find( sFilterDataString
) == aModelData
.GetMediaDescr().end() )
1569 aModelData
.GetMediaDescr()[aIter
->first
] = aIter
->second
;
1573 if ( aFileNameIter
!= aModelData
.GetMediaDescr().end() )
1576 aFileNameIter
->second
>>= aFileName
;
1577 aURL
.SetURL( aFileName
);
1578 DBG_ASSERT( aURL
.GetProtocol() != INetProtocol::NotValid
, "Illegal URL!" );
1580 ::comphelper::SequenceAsHashMap::const_iterator aIter
=
1581 aModelData
.GetMediaDescr().find( sFilterNameString
);
1583 if ( aIter
!= aModelData
.GetMediaDescr().end() )
1584 aIter
->second
>>= aFilterName
;
1586 aModelData
.GetMediaDescr()[sFilterNameString
] <<= aFilterName
;
1588 DBG_ASSERT( !aFilterName
.isEmpty(), "Illegal filter!" );
1592 SAL_WARN( "sfx.doc", "This code must be unreachable!" );
1593 throw task::ErrorCodeIOException(
1594 "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_INVALIDPARAMETER",
1595 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_INVALIDPARAMETER
));
1598 ::comphelper::SequenceAsHashMap::const_iterator aIter
=
1599 aModelData
.GetMediaDescr().find( OUString("FilterFlags") );
1600 bool bFilterFlagsSet
= ( aIter
!= aModelData
.GetMediaDescr().end() );
1602 // check if the filter Dialog has not been called before
1603 if( !( nStoreMode
& PDFEXPORT_REQUESTED
) && !( nStoreMode
& EPUBEXPORT_REQUESTED
) && !bFilterFlagsSet
1604 && ( ( nStoreMode
& EXPORT_REQUESTED
) || bUseFilterOptions
) )
1606 // execute filter options dialog
1607 if ( aModelData
.ExecuteFilterDialog_Impl( aFilterName
) )
1610 // check if the file is a pdf or not and change the storing mode at convenience
1611 if (aFilterName
.endsWith("pdf_Export"))
1612 nStoreMode
= EXPORT_REQUESTED
| PDFEXPORT_REQUESTED
;
1616 // so the arguments will not change any more and can be stored to the main location
1617 aArgsSequence
= aModelData
.GetMediaDescr().getAsConstPropertyValueList();
1619 // store the document and handle it's docinfo
1620 SvtSaveOptions aOptions
;
1622 DocumentSettingsGuard
aSettingsGuard( aModelData
.GetModel(), aModelData
.IsRecommendReadOnly(), nStoreMode
& EXPORT_REQUESTED
);
1624 OSL_ENSURE( aModelData
.GetMediaDescr().find( OUString( "Password" ) ) == aModelData
.GetMediaDescr().end(), "The Password property of MediaDescriptor should not be used here!" );
1625 if ( aOptions
.IsDocInfoSave()
1626 && ( !aModelData
.GetStorable()->hasLocation()
1627 || INetURLObject( aModelData
.GetStorable()->getLocation() ) != aURL
) )
1629 // this is definitely not a Save operation
1630 // so the document info can be updated
1632 // on export document info must be preserved
1633 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
1634 aModelData
.GetModel(), uno::UNO_QUERY_THROW
);
1635 uno::Reference
<util::XCloneable
> xCloneable(
1636 xDPS
->getDocumentProperties(), uno::UNO_QUERY_THROW
);
1637 uno::Reference
<document::XDocumentProperties
> xOldDocProps(
1638 xCloneable
->createClone(), uno::UNO_QUERY_THROW
);
1640 std::function
< void () > aFunc
= [xModel
, xOldDocProps
, nStoreMode
, aURL
, aArgsSequence
]() {
1641 SfxStoringHelper aStoringHelper
;
1642 ModelData_Impl
aModel(aStoringHelper
, xModel
, aArgsSequence
);
1646 if ( nStoreMode
& EXPORT_REQUESTED
)
1647 aModel
.GetStorable()->storeToURL( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), aArgsSequence
);
1649 aModel
.GetStorable()->storeAsURL( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), aArgsSequence
);
1651 catch( const uno::Exception
& )
1655 if ( nStoreMode
& EXPORT_REQUESTED
)
1657 SfxStoringHelper::SetDocInfoState(aModel
.GetModel(), xOldDocProps
);
1660 // Launch PDF viewer
1661 if (nStoreMode
& PDFEXPORT_REQUESTED
)
1662 LaunchPDFViewer(aURL
);
1666 // use dispatch API to show document info dialog
1667 if ( aModelData
.ShowDocumentInfoDialog(aFunc
) )
1671 OSL_FAIL( "Can't execute document info dialog!" );
1676 // Document properties can contain streams that should be freed before storing
1677 aModelData
.FreeDocumentProps();
1679 // this is actually a save operation with different parameters
1680 // so storeTo or storeAs without DocInfo operations are used
1681 if ( nStoreMode
& EXPORT_REQUESTED
)
1682 aModelData
.GetStorable()->storeToURL( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), aArgsSequence
);
1684 aModelData
.GetStorable()->storeAsURL( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), aArgsSequence
);
1686 // Launch PDF viewer
1687 if (nStoreMode
& PDFEXPORT_REQUESTED
)
1688 LaunchPDFViewer(aURL
);
1696 bool SfxStoringHelper::CheckFilterOptionsAppearance(
1697 const uno::Reference
< container::XNameAccess
>& xFilterCFG
,
1698 const OUString
& aFilterName
)
1700 bool bUseFilterOptions
= false;
1702 DBG_ASSERT( xFilterCFG
.is(), "No filter configuration!\n" );
1703 if( xFilterCFG
.is() )
1706 uno::Sequence
< beans::PropertyValue
> aProps
;
1707 uno::Any aAny
= xFilterCFG
->getByName( aFilterName
);
1708 if ( aAny
>>= aProps
)
1710 ::comphelper::SequenceAsHashMap
aPropsHM( aProps
);
1711 if( !aPropsHM
.getUnpackedValueOrDefault( "UIComponent", OUString() ).isEmpty() )
1712 bUseFilterOptions
= true;
1715 catch( const uno::Exception
& )
1720 return bUseFilterOptions
;
1725 void SfxStoringHelper::SetDocInfoState(
1726 const uno::Reference
< frame::XModel
>& xModel
,
1727 const uno::Reference
< document::XDocumentProperties
>& i_xOldDocProps
)
1729 uno::Reference
<document::XDocumentPropertiesSupplier
> const
1730 xModelDocPropsSupplier(xModel
, uno::UNO_QUERY_THROW
);
1731 uno::Reference
<document::XDocumentProperties
> const xDocPropsToFill
=
1732 xModelDocPropsSupplier
->getDocumentProperties();
1733 uno::Reference
< beans::XPropertySet
> const xPropSet(
1734 i_xOldDocProps
->getUserDefinedProperties(), uno::UNO_QUERY_THROW
);
1736 uno::Reference
< util::XModifiable
> xModifiable( xModel
, uno::UNO_QUERY
);
1737 if ( !xModifiable
.is() )
1738 throw uno::RuntimeException();
1740 bool bIsModified
= xModifiable
->isModified();
1744 uno::Reference
< beans::XPropertySet
> const xSet(
1745 xDocPropsToFill
->getUserDefinedProperties(), uno::UNO_QUERY
);
1746 uno::Reference
< beans::XPropertyContainer
> xContainer( xSet
, uno::UNO_QUERY
);
1747 uno::Reference
< beans::XPropertySetInfo
> xSetInfo
= xSet
->getPropertySetInfo();
1748 const uno::Sequence
< beans::Property
> lProps
= xSetInfo
->getProperties();
1749 for (const beans::Property
& rProp
: lProps
)
1751 uno::Any aValue
= xPropSet
->getPropertyValue( rProp
.Name
);
1752 if ( rProp
.Attributes
& css::beans::PropertyAttribute::REMOVABLE
)
1756 // QUESTION: DefaultValue?!
1757 xContainer
->addProperty( rProp
.Name
, rProp
.Attributes
, aValue
);
1759 catch (beans::PropertyExistException
const&) {}
1762 // it is possible that the propertysets from XML and binary files differ; we shouldn't break then
1763 xSet
->setPropertyValue( rProp
.Name
, aValue
);
1765 catch ( const uno::Exception
& ) {}
1769 // sigh... have to set these manually I'm afraid... wonder why
1770 // SfxObjectShell doesn't handle this internally, should be easier
1771 xDocPropsToFill
->setAuthor(i_xOldDocProps
->getAuthor());
1772 xDocPropsToFill
->setGenerator(i_xOldDocProps
->getGenerator());
1773 xDocPropsToFill
->setCreationDate(i_xOldDocProps
->getCreationDate());
1774 xDocPropsToFill
->setTitle(i_xOldDocProps
->getTitle());
1775 xDocPropsToFill
->setSubject(i_xOldDocProps
->getSubject());
1776 xDocPropsToFill
->setDescription(i_xOldDocProps
->getDescription());
1777 xDocPropsToFill
->setKeywords(i_xOldDocProps
->getKeywords());
1778 xDocPropsToFill
->setModifiedBy(i_xOldDocProps
->getModifiedBy());
1779 xDocPropsToFill
->setModificationDate(i_xOldDocProps
->getModificationDate());
1780 xDocPropsToFill
->setPrintedBy(i_xOldDocProps
->getPrintedBy());
1781 xDocPropsToFill
->setPrintDate(i_xOldDocProps
->getPrintDate());
1782 xDocPropsToFill
->setAutoloadURL(i_xOldDocProps
->getAutoloadURL());
1783 xDocPropsToFill
->setAutoloadSecs(i_xOldDocProps
->getAutoloadSecs());
1784 xDocPropsToFill
->setDefaultTarget(i_xOldDocProps
->getDefaultTarget());
1785 xDocPropsToFill
->setEditingCycles(i_xOldDocProps
->getEditingCycles());
1786 xDocPropsToFill
->setEditingDuration(i_xOldDocProps
->getEditingDuration());
1787 // other attributes e.g. DocumentStatistics are not editable from dialog
1789 catch (const uno::Exception
&)
1791 TOOLS_INFO_EXCEPTION("sfx.doc", "SetDocInfoState");
1794 // set the modified flag back if required
1795 if ( bIsModified
!= bool(xModifiable
->isModified()) )
1796 xModifiable
->setModified( bIsModified
);
1801 bool SfxStoringHelper::WarnUnacceptableFormat( const uno::Reference
< frame::XModel
>& xModel
,
1802 std::u16string_view aOldUIName
,
1803 const OUString
& aDefExtension
,
1806 if ( !SvtSaveOptions().IsWarnAlienFormat() )
1809 weld::Window
* pWin
= SfxStoringHelper::GetModelWindow(xModel
);
1810 SfxAlienWarningDialog
aDlg(pWin
, aOldUIName
, aDefExtension
, bDefIsAlien
);
1812 return aDlg
.run() == RET_OK
;
1815 uno::Reference
<awt::XWindow
> SfxStoringHelper::GetModelXWindow(const uno::Reference
<frame::XModel
>& xModel
)
1820 uno::Reference
< frame::XController
> xController
= xModel
->getCurrentController();
1821 if ( xController
.is() )
1823 uno::Reference
< frame::XFrame
> xFrame
= xController
->getFrame();
1826 return xFrame
->getContainerWindow();
1831 catch ( const uno::Exception
& )
1835 return uno::Reference
<awt::XWindow
>();
1838 weld::Window
* SfxStoringHelper::GetModelWindow( const uno::Reference
< frame::XModel
>& xModel
)
1840 weld::Window
* pWin
= nullptr;
1844 pWin
= Application::GetFrameWeld(GetModelXWindow(xModel
));
1846 catch (const uno::Exception
&)
1853 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */