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 .
19 #include <config_gpgme.h>
20 #if HAVE_FEATURE_GPGME
21 #include <com/sun/star/xml/crypto/GPGSEInitializer.hpp>
22 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
23 #include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
25 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
26 #include <com/sun/star/security/XCertificate.hpp>
28 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
29 #include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
30 #include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
31 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
32 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
33 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
34 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
35 #include <com/sun/star/view/XSelectionSupplier.hpp>
36 #include <com/sun/star/beans/PropertyExistException.hpp>
37 #include <com/sun/star/beans/XPropertyAccess.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/beans/XPropertyContainer.hpp>
40 #include <com/sun/star/beans/PropertyAttribute.hpp>
41 #include <com/sun/star/document/XExporter.hpp>
42 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
43 #include <com/sun/star/document/XDocumentProperties.hpp>
44 #include <com/sun/star/task/ErrorCodeIOException.hpp>
45 #include <com/sun/star/task/InteractionHandler.hpp>
46 #include <com/sun/star/util/URLTransformer.hpp>
47 #include <com/sun/star/util/XURLTransformer.hpp>
48 #include <com/sun/star/frame/ModuleManager.hpp>
49 #include <com/sun/star/frame/XStorable.hpp>
50 #include <com/sun/star/frame/XStorable2.hpp>
51 #include <com/sun/star/frame/XDispatchProvider.hpp>
52 #include <com/sun/star/frame/XDispatch.hpp>
53 #include <com/sun/star/frame/XTitle.hpp>
54 #include <com/sun/star/util/XModifiable.hpp>
55 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
57 #include <com/sun/star/util/XCloneable.hpp>
59 #include <guisaveas.hxx>
61 #include <sal/log.hxx>
62 #include <svl/itemset.hxx>
63 #include <svl/eitem.hxx>
64 #include <tools/debug.hxx>
65 #include <comphelper/diagnose_ex.hxx>
66 #include <tools/urlobj.hxx>
67 #include <tools/json_writer.hxx>
68 #include <comphelper/processfactory.hxx>
69 #include <comphelper/propertysequence.hxx>
70 #include <comphelper/propertyvalue.hxx>
71 #include <comphelper/sequenceashashmap.hxx>
72 #include <comphelper/mimeconfighelper.hxx>
73 #include <comphelper/lok.hxx>
74 #include <comphelper/xmlsechelper.hxx>
75 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
77 #include <vcl/svapp.hxx>
78 #include <vcl/weld.hxx>
79 #include <o3tl/char16_t2wchar_t.hxx>
80 #include <unotools/tempfile.hxx>
81 #include <unotools/useroptions.hxx>
83 #include <sfx2/objsh.hxx>
84 #include <sfx2/sfxsids.hrc>
85 #include <sfx2/strings.hrc>
86 #include <sfx2/sfxresid.hxx>
87 #include <sfx2/filedlghelper.hxx>
88 #include <sfx2/app.hxx>
89 #include <sfx2/sfxuno.hxx>
90 #include <sfx2/viewsh.hxx>
91 #include <sfx2/bindings.hxx>
92 #include <alienwarn.hxx>
95 #include <string_view>
97 #include <officecfg/Office/Common.hxx>
99 #include <vcl/FilterConfigItem.hxx>
100 #include <com/sun/star/system/SystemShellExecute.hpp>
101 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
103 #include <osl/file.hxx>
104 #include <svl/cryptosign.hxx>
113 // flags that specify requested operation
114 #define EXPORT_REQUESTED 1
115 #define PDFEXPORT_REQUESTED 2
116 #define PDFDIRECTEXPORT_REQUESTED 4
117 #define WIDEEXPORT_REQUESTED 8
118 #define SAVE_REQUESTED 16
119 #define SAVEAS_REQUESTED 32
120 #define SAVEACOPY_REQUESTED 64
121 #define EPUBEXPORT_REQUESTED 128
122 #define EPUBDIRECTEXPORT_REQUESTED 256
123 #define SAVEASREMOTE_REQUESTED -1
125 // possible statuses of save operation
126 #define STATUS_NO_ACTION 0
127 #define STATUS_SAVE 1
128 #define STATUS_SAVEAS 2
129 #define STATUS_SAVEAS_STANDARDNAME 3
131 constexpr OUString aFilterNameString
= u
"FilterName"_ustr
;
132 constexpr OUString aFilterOptionsString
= u
"FilterOptions"_ustr
;
133 constexpr OUString aFilterDataString
= u
"FilterData"_ustr
;
135 using namespace ::com::sun::star
;
136 using namespace css::system
;
140 sal_uInt16
getSlotIDFromMode( sal_Int16 nStoreMode
)
142 // This is a temporary hardcoded solution must be removed when
143 // dialogs do not need parameters in SidSet representation any more
145 sal_uInt16 nResult
= 0;
146 if ( nStoreMode
== EXPORT_REQUESTED
|| nStoreMode
== ( EXPORT_REQUESTED
| SAVEACOPY_REQUESTED
| WIDEEXPORT_REQUESTED
) )
147 nResult
= SID_EXPORTDOC
;
148 else if ( nStoreMode
== ( EXPORT_REQUESTED
| PDFEXPORT_REQUESTED
) )
149 nResult
= SID_EXPORTDOCASPDF
;
150 else if ( nStoreMode
== ( EXPORT_REQUESTED
| EPUBEXPORT_REQUESTED
) )
151 nResult
= SID_EXPORTDOCASEPUB
;
152 else if ( nStoreMode
== ( EXPORT_REQUESTED
| PDFEXPORT_REQUESTED
| PDFDIRECTEXPORT_REQUESTED
) )
153 nResult
= SID_DIRECTEXPORTDOCASPDF
;
154 else if ( nStoreMode
== ( EXPORT_REQUESTED
| EPUBEXPORT_REQUESTED
| EPUBDIRECTEXPORT_REQUESTED
) )
155 nResult
= SID_DIRECTEXPORTDOCASEPUB
;
156 else if ( nStoreMode
== SAVEAS_REQUESTED
|| nStoreMode
== ( EXPORT_REQUESTED
| WIDEEXPORT_REQUESTED
) )
157 nResult
= SID_SAVEASDOC
;
158 else if ( nStoreMode
== SAVEASREMOTE_REQUESTED
)
159 nResult
= SID_SAVEASREMOTE
;
161 SAL_WARN( "sfx.doc", "Unacceptable slot name is provided!" );
168 sal_Int16
getStoreModeFromSlotName( std::u16string_view aSlotName
)
170 sal_Int16 nResult
= 0;
171 if ( aSlotName
== u
"ExportTo" )
172 nResult
= EXPORT_REQUESTED
;
173 else if ( aSlotName
== u
"ExportToPDF" )
174 nResult
= EXPORT_REQUESTED
| PDFEXPORT_REQUESTED
;
175 else if ( aSlotName
== u
"ExportDirectToPDF" )
176 nResult
= EXPORT_REQUESTED
| PDFEXPORT_REQUESTED
| PDFDIRECTEXPORT_REQUESTED
;
177 else if ( aSlotName
== u
"ExportToEPUB" )
178 nResult
= EXPORT_REQUESTED
| EPUBEXPORT_REQUESTED
;
179 else if ( aSlotName
== u
"ExportDirectToEPUB" )
180 nResult
= EXPORT_REQUESTED
| EPUBEXPORT_REQUESTED
| EPUBDIRECTEXPORT_REQUESTED
;
181 else if ( aSlotName
== u
"Save" )
182 nResult
= SAVE_REQUESTED
;
183 else if ( aSlotName
== u
"SaveAs" )
184 nResult
= SAVEAS_REQUESTED
;
185 else if ( aSlotName
== u
"SaveAsRemote" )
186 nResult
= SAVEASREMOTE_REQUESTED
;
188 throw task::ErrorCodeIOException(
189 (OUString::Concat("getStoreModeFromSlotName(\"") + aSlotName
190 + "): ERRCODE_IO_INVALIDPARAMETER"),
191 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_INVALIDPARAMETER
) );
197 SfxFilterFlags
getMustFlags( sal_Int16 nStoreMode
)
199 return ( SfxFilterFlags::EXPORT
200 | ( ( ( nStoreMode
& EXPORT_REQUESTED
) && !( nStoreMode
& WIDEEXPORT_REQUESTED
) ) ? SfxFilterFlags::NONE
: SfxFilterFlags::IMPORT
) );
204 SfxFilterFlags
getDontFlags( sal_Int16 nStoreMode
)
206 return ( SfxFilterFlags::INTERNAL
207 | SfxFilterFlags::NOTINFILEDLG
208 | ( ( ( nStoreMode
& EXPORT_REQUESTED
) && !( nStoreMode
& WIDEEXPORT_REQUESTED
) ) ? SfxFilterFlags::IMPORT
: SfxFilterFlags::NONE
) );
214 class DocumentSettingsGuard
216 uno::Reference
< beans::XPropertySet
> m_xDocumentSettings
;
217 bool m_bPreserveReadOnly
;
218 bool m_bReadOnlySupported
;
220 bool m_bRestoreSettings
;
222 DocumentSettingsGuard( const uno::Reference
< frame::XModel
>& xModel
, bool bReadOnly
, bool bRestore
)
223 : m_bPreserveReadOnly( false )
224 , m_bReadOnlySupported( false )
225 , m_bRestoreSettings( bRestore
)
229 uno::Reference
< lang::XMultiServiceFactory
> xDocSettingsSupplier( xModel
, uno::UNO_QUERY
);
230 if (xDocSettingsSupplier
)
232 m_xDocumentSettings
.set(
233 xDocSettingsSupplier
->createInstance( u
"com.sun.star.document.Settings"_ustr
),
235 if (m_xDocumentSettings
)
237 OUString
aLoadReadonlyString( u
"LoadReadonly"_ustr
);
238 m_xDocumentSettings
->getPropertyValue( aLoadReadonlyString
) >>= m_bPreserveReadOnly
;
239 m_xDocumentSettings
->setPropertyValue( aLoadReadonlyString
, uno::Any( bReadOnly
) );
240 m_bReadOnlySupported
= true;
244 catch( const uno::Exception
& )
247 if ( bReadOnly
&& !m_bReadOnlySupported
)
248 throw uno::RuntimeException(); // the user could provide the data, so it must be stored
251 ~DocumentSettingsGuard()
253 if ( m_bRestoreSettings
)
257 if ( m_bReadOnlySupported
)
258 m_xDocumentSettings
->setPropertyValue( u
"LoadReadonly"_ustr
, uno::Any( m_bPreserveReadOnly
) );
260 catch( const uno::Exception
& )
262 TOOLS_WARN_EXCEPTION( "sfx.doc", "" );
267 } // anonymous namespace
273 SfxStoringHelper
* m_pOwner
;
274 uno::Reference
< frame::XModel
> m_xModel
;
275 uno::Reference
< frame::XStorable
> m_xStorable
;
276 uno::Reference
< frame::XStorable2
> m_xStorable2
;
278 OUString m_aModuleName
;
279 std::unique_ptr
<::comphelper::SequenceAsHashMap
> m_pDocumentPropsHM
;
280 std::unique_ptr
<::comphelper::SequenceAsHashMap
> m_pModulePropsHM
;
282 uno::Reference
<beans::XPropertyAccess
> m_xFilterProperties
;
283 uno::Reference
<ui::dialogs::XAsynchronousExecutableDialog
> m_xFilterDialog
;
285 ::comphelper::SequenceAsHashMap m_aMediaDescrHM
;
287 bool m_bRecommendReadOnly
;
288 bool m_bSignWithDefaultSignature
;
290 DECL_LINK(OptionsDialogClosedHdl
, css::ui::dialogs::DialogClosedEvent
*, void);
293 ModelData_Impl( SfxStoringHelper
& aOwner
,
294 uno::Reference
< frame::XModel
> xModel
,
295 const uno::Sequence
< beans::PropertyValue
>& aMediaDescr
);
299 void FreeDocumentProps();
301 uno::Reference
< frame::XModel
> const & GetModel() const;
302 uno::Reference
< frame::XStorable
> const & GetStorable();
303 uno::Reference
< frame::XStorable2
> const & GetStorable2();
305 ::comphelper::SequenceAsHashMap
& GetMediaDescr() { return m_aMediaDescrHM
; }
307 bool IsRecommendReadOnly() const { return m_bRecommendReadOnly
; }
308 bool IsSignWithDefaultSignature() const { return m_bSignWithDefaultSignature
; }
310 const ::comphelper::SequenceAsHashMap
& GetDocProps();
312 OUString
const & GetModuleName();
313 const ::comphelper::SequenceAsHashMap
& GetModuleProps();
315 void CheckInteractionHandler();
318 OUString
GetDocServiceName();
319 uno::Sequence
< beans::PropertyValue
> GetDocServiceDefaultFilterCheckFlags( SfxFilterFlags nMust
, SfxFilterFlags nDont
);
320 uno::Sequence
< beans::PropertyValue
> GetDocServiceAnyFilter( SfxFilterFlags nMust
, SfxFilterFlags nDont
);
321 uno::Sequence
< beans::PropertyValue
> GetPreselectedFilter_Impl( sal_Int16 nStoreMode
);
322 uno::Sequence
< beans::PropertyValue
> GetDocServiceDefaultFilter();
324 bool ExecuteFilterDialog_Impl( const OUString
& aFilterName
, bool bAsync
);
326 sal_Int8
CheckSaveAcceptable( sal_Int8 nCurStatus
);
327 sal_Int8
CheckStateForSave();
329 sal_Int8
CheckFilter( const OUString
& );
331 bool CheckFilterOptionsDialogExistence();
333 bool OutputFileDialog( sal_Int16 nStoreMode
,
334 const ::comphelper::SequenceAsHashMap
& aPreselectedFilterPropsHM
,
335 bool bSetStandardName
,
336 OUString
& aSuggestedName
,
337 bool bPreselectPassword
,
338 OUString
& aSuggestedDir
,
340 const OUString
& rStandardDir
,
341 const css::uno::Sequence
< OUString
>& rDenyList
344 bool ShowDocumentInfoDialog();
346 static OUString
GetRecommendedExtension( const OUString
& aTypeName
);
347 OUString
GetRecommendedDir( const OUString
& aSuggestedDir
);
348 OUString
GetRecommendedName( const OUString
& aSuggestedName
,
349 const OUString
& aTypeName
);
353 ModelData_Impl::ModelData_Impl( SfxStoringHelper
& aOwner
,
354 uno::Reference
< frame::XModel
> xModel
,
355 const uno::Sequence
< beans::PropertyValue
>& aMediaDescr
)
356 : m_pOwner( &aOwner
)
357 , m_xModel(std::move( xModel
))
358 , m_aMediaDescrHM( aMediaDescr
)
359 , m_bRecommendReadOnly( false )
360 , m_bSignWithDefaultSignature( false )
362 CheckInteractionHandler();
366 ModelData_Impl::~ModelData_Impl()
369 m_pDocumentPropsHM
.reset();
370 m_pModulePropsHM
.reset();
371 if (m_xFilterProperties
)
372 m_xFilterProperties
.clear();
376 void ModelData_Impl::FreeDocumentProps()
378 m_pDocumentPropsHM
.reset();
382 uno::Reference
< frame::XModel
> const & ModelData_Impl::GetModel() const
384 if ( !m_xModel
.is() )
385 throw uno::RuntimeException();
391 uno::Reference
< frame::XStorable
> const & ModelData_Impl::GetStorable()
393 if ( !m_xStorable
.is() )
395 m_xStorable
.set( m_xModel
, uno::UNO_QUERY_THROW
);
402 uno::Reference
< frame::XStorable2
> const & ModelData_Impl::GetStorable2()
404 if ( !m_xStorable2
.is() )
406 m_xStorable2
.set( m_xModel
, uno::UNO_QUERY_THROW
);
413 const ::comphelper::SequenceAsHashMap
& ModelData_Impl::GetDocProps()
415 if ( !m_pDocumentPropsHM
)
416 m_pDocumentPropsHM
.reset( new ::comphelper::SequenceAsHashMap( GetModel()->getArgs() ) );
418 return *m_pDocumentPropsHM
;
422 OUString
const & ModelData_Impl::GetModuleName()
424 if ( m_aModuleName
.isEmpty() )
426 m_aModuleName
= m_pOwner
->GetModuleManager()->identify(
427 uno::Reference
< uno::XInterface
>( m_xModel
, uno::UNO_QUERY
) );
428 if ( m_aModuleName
.isEmpty() )
429 throw uno::RuntimeException(); // TODO:
431 return m_aModuleName
;
435 const ::comphelper::SequenceAsHashMap
& ModelData_Impl::GetModuleProps()
437 if ( !m_pModulePropsHM
)
439 uno::Sequence
< beans::PropertyValue
> aModuleProps
;
440 m_pOwner
->GetModuleManager()->getByName( GetModuleName() ) >>= aModuleProps
;
441 if ( !aModuleProps
.hasElements() )
442 throw uno::RuntimeException(); // TODO;
443 m_pModulePropsHM
.reset( new ::comphelper::SequenceAsHashMap( aModuleProps
) );
446 return *m_pModulePropsHM
;
450 OUString
ModelData_Impl::GetDocServiceName()
452 return GetModuleProps().getUnpackedValueOrDefault(u
"ooSetupFactoryDocumentService"_ustr
, OUString());
456 void ModelData_Impl::CheckInteractionHandler()
458 static constexpr OUString sInteractionHandler
{u
"InteractionHandler"_ustr
};
459 ::comphelper::SequenceAsHashMap::const_iterator aInteractIter
=
460 m_aMediaDescrHM
.find( sInteractionHandler
);
462 if ( aInteractIter
== m_aMediaDescrHM
.end() )
465 m_aMediaDescrHM
[ sInteractionHandler
]
466 <<= task::InteractionHandler::createWithParent( comphelper::getProcessComponentContext(), nullptr);
468 catch( const uno::Exception
& )
474 uno::Reference
< task::XInteractionHandler
> xInteract
;
475 DBG_ASSERT( ( aInteractIter
->second
>>= xInteract
) && xInteract
.is(), "Broken interaction handler is provided!\n" );
480 uno::Sequence
< beans::PropertyValue
> ModelData_Impl::GetDocServiceDefaultFilter()
482 uno::Sequence
< beans::PropertyValue
> aProps
;
484 const OUString aFilterName
= GetModuleProps().getUnpackedValueOrDefault( u
"ooSetupFactoryDefaultFilter"_ustr
, OUString() );
486 m_pOwner
->GetFilterConfiguration()->getByName( aFilterName
) >>= aProps
;
492 uno::Sequence
< beans::PropertyValue
> ModelData_Impl::GetDocServiceDefaultFilterCheckFlags( SfxFilterFlags nMust
,
493 SfxFilterFlags nDont
)
495 uno::Sequence
< beans::PropertyValue
> aFilterProps
;
496 uno::Sequence
< beans::PropertyValue
> aProps
= GetDocServiceDefaultFilter();
497 if ( aProps
.hasElements() )
499 ::comphelper::SequenceAsHashMap
aFiltHM( aProps
);
500 SfxFilterFlags nFlags
= static_cast<SfxFilterFlags
>(aFiltHM
.getUnpackedValueOrDefault(u
"Flags"_ustr
,
502 if ( ( ( nFlags
& nMust
) == nMust
) && !( nFlags
& nDont
) )
503 aFilterProps
= std::move(aProps
);
510 uno::Sequence
< beans::PropertyValue
> ModelData_Impl::GetDocServiceAnyFilter( SfxFilterFlags nMust
, SfxFilterFlags nDont
)
512 uno::Sequence
< beans::NamedValue
> aSearchRequest
{ { u
"DocumentService"_ustr
, css::uno::Any(GetDocServiceName()) } };
514 return ::comphelper::MimeConfigurationHelper::SearchForFilter( m_pOwner
->GetFilterQuery(), aSearchRequest
, nMust
, nDont
);
518 uno::Sequence
< beans::PropertyValue
> ModelData_Impl::GetPreselectedFilter_Impl( sal_Int16 nStoreMode
)
520 if ( nStoreMode
== SAVEASREMOTE_REQUESTED
)
521 nStoreMode
= SAVEAS_REQUESTED
;
523 uno::Sequence
< beans::PropertyValue
> aFilterProps
;
525 SfxFilterFlags nMust
= getMustFlags( nStoreMode
);
526 SfxFilterFlags nDont
= getDontFlags( nStoreMode
);
528 if ( ( nStoreMode
!= SAVEASREMOTE_REQUESTED
) && ( nStoreMode
& PDFEXPORT_REQUESTED
) )
530 // Preselect PDF-Filter for EXPORT
531 uno::Sequence
< beans::NamedValue
> aSearchRequest
533 { u
"Type"_ustr
, css::uno::Any(u
"pdf_Portable_Document_Format"_ustr
) },
534 { u
"DocumentService"_ustr
, css::uno::Any(GetDocServiceName()) }
537 aFilterProps
= ::comphelper::MimeConfigurationHelper::SearchForFilter( m_pOwner
->GetFilterQuery(), aSearchRequest
, nMust
, nDont
);
539 else if ( ( nStoreMode
!= SAVEASREMOTE_REQUESTED
) && ( nStoreMode
& EPUBEXPORT_REQUESTED
) )
541 // Preselect EPUB filter for export.
542 uno::Sequence
<beans::NamedValue
> aSearchRequest
544 { u
"Type"_ustr
, css::uno::Any(u
"writer_EPUB_Document"_ustr
) },
545 { u
"DocumentService"_ustr
, css::uno::Any(GetDocServiceName()) }
548 aFilterProps
= ::comphelper::MimeConfigurationHelper::SearchForFilter( m_pOwner
->GetFilterQuery(), aSearchRequest
, nMust
, nDont
);
552 aFilterProps
= GetDocServiceDefaultFilterCheckFlags( nMust
, nDont
);
554 if ( !aFilterProps
.hasElements() )
556 // the default filter was not found, use just the first acceptable one
557 aFilterProps
= GetDocServiceAnyFilter( nMust
, nDont
);
565 bool ModelData_Impl::ExecuteFilterDialog_Impl( const OUString
& aFilterName
, bool bIsAsync
)
567 bool bDialogUsed
= false;
570 uno::Sequence
< beans::PropertyValue
> aProps
;
571 uno::Any aAny
= m_pOwner
->GetFilterConfiguration()->getByName( aFilterName
);
572 if ( aAny
>>= aProps
)
574 auto pProp
= std::find_if(std::cbegin(aProps
), std::cend(aProps
),
575 [](const beans::PropertyValue
& rProp
) { return rProp
.Name
== "UIComponent"; });
576 if (pProp
!= std::cend(aProps
))
578 OUString aServiceName
;
579 pProp
->Value
>>= aServiceName
;
580 if( !aServiceName
.isEmpty() )
582 uno::Sequence
<uno::Any
> aDialogArgs(comphelper::InitAnyPropertySequence(
584 {"ParentWindow", uno::Any(SfxStoringHelper::GetModelXWindow(m_xModel
))},
587 uno::Reference
< beans::XPropertyAccess
> xFilterProperties
;
588 uno::Reference
< ui::dialogs::XExecutableDialog
> xFilterDialog
;
589 uno::Reference
< ui::dialogs::XAsynchronousExecutableDialog
> xAsyncFilterDialog
;
590 uno::Reference
< document::XExporter
> xExporter
;
594 xAsyncFilterDialog
= uno::Reference
< ui::dialogs::XAsynchronousExecutableDialog
>(
595 comphelper::getProcessServiceFactory()->createInstanceWithArguments( aServiceName
, aDialogArgs
), uno::UNO_QUERY
);
596 OSL_ENSURE(xAsyncFilterDialog
.is(), "ModelData_Impl::ExecuteFilterDialog_Impl: Dialog is not async!");
597 xFilterProperties
= uno::Reference
< beans::XPropertyAccess
>( xAsyncFilterDialog
, uno::UNO_QUERY
);
598 xExporter
= uno::Reference
< document::XExporter
>( xAsyncFilterDialog
, uno::UNO_QUERY
);
602 xFilterDialog
= uno::Reference
< ui::dialogs::XExecutableDialog
>(
603 comphelper::getProcessServiceFactory()->createInstanceWithArguments( aServiceName
, aDialogArgs
), uno::UNO_QUERY
);
604 xFilterProperties
= uno::Reference
< beans::XPropertyAccess
>( xFilterDialog
, uno::UNO_QUERY
);
605 xExporter
= uno::Reference
< document::XExporter
>( xFilterDialog
, uno::UNO_QUERY
);
608 if ( xFilterProperties
.is() && ( xFilterDialog
.is() || xAsyncFilterDialog
.is() ) )
613 xExporter
->setSourceDocument( GetModel() );
615 uno::Sequence
< beans::PropertyValue
> aPropsForDialog
;
616 GetMediaDescr() >> aPropsForDialog
;
617 xFilterProperties
->setPropertyValues( aPropsForDialog
);
621 m_xFilterProperties
= std::move(xFilterProperties
);
622 m_xFilterDialog
= std::move(xAsyncFilterDialog
);
624 auto aDialogClosedListener
= rtl::Reference(new svt::DialogClosedListener());
625 aDialogClosedListener
->SetDialogClosedLink( LINK( this, ModelData_Impl
, OptionsDialogClosedHdl
) );
627 m_xFilterDialog
->startExecuteModal( aDialogClosedListener
);
631 if( !xFilterDialog
->execute() )
633 throw task::ErrorCodeIOException(
634 (u
"ModelData_Impl::ExecuteFilterDialog_Impl:"
635 " ERRCODE_IO_ABORT"_ustr
),
636 uno::Reference
< uno::XInterface
>(),
637 sal_uInt32(ERRCODE_IO_ABORT
));
640 const uno::Sequence
< beans::PropertyValue
> aPropsFromDialog
=
641 xFilterProperties
->getPropertyValues();
642 for ( const auto& rProp
: aPropsFromDialog
)
643 GetMediaDescr()[rProp
.Name
] = rProp
.Value
;
650 catch( const container::NoSuchElementException
& e
)
652 // the filter name is unknown
653 throw task::ErrorCodeIOException(
654 ("ModelData_Impl::ExecuteFilterDialog_Impl: NoSuchElementException"
655 " \"" + e
.Message
+ "\": ERRCODE_IO_ABORT"),
656 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_INVALIDPARAMETER
));
658 catch( const task::ErrorCodeIOException
& )
662 catch( const uno::Exception
& )
664 TOOLS_WARN_EXCEPTION("sfx.doc", "ignoring");
670 void SfxStoringHelper::CallFinishGUIStoreModel()
672 ::comphelper::SequenceAsHashMap::const_iterator aFileNameIter
= m_xModelData
->GetMediaDescr().find( u
"URL"_ustr
);
673 uno::Sequence
< beans::PropertyValue
> aFilterProps
= m_xModelData
->GetPreselectedFilter_Impl( m_nStoreMode
);
674 const OUString aFilterFromMediaDescr
= m_xModelData
->GetMediaDescr().getUnpackedValueOrDefault( aFilterNameString
, OUString() );
675 const OUString aOldFilterName
= m_xModelData
->GetDocProps().getUnpackedValueOrDefault( aFilterNameString
, OUString() );
676 ::comphelper::SequenceAsHashMap
aFilterPropsHM( aFilterProps
);
677 OUString aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault( u
"Name"_ustr
, OUString() );
679 SfxStoringHelper::FinishGUIStoreModel(aFileNameIter
, *m_xModelData
, m_bRemote
, m_nStoreMode
, aFilterProps
,
680 m_bSetStandardName
, m_bPreselectPassword
, m_bDialogUsed
,
681 aFilterFromMediaDescr
, aOldFilterName
, m_aArgsSequence
, aFilterName
);
683 if (SfxViewShell::Current())
684 SfxViewShell::Current()->SetStoringHelper(nullptr);
687 IMPL_LINK( ModelData_Impl
, OptionsDialogClosedHdl
, css::ui::dialogs::DialogClosedEvent
*, pEvt
, void )
689 SfxViewShell
* pNotifier
= comphelper::LibreOfficeKit::isActive() ? SfxViewShell::Current() : nullptr;
691 if (pEvt
->DialogResult
== RET_OK
&& m_xFilterProperties
)
694 pNotifier
->libreOfficeKitViewCallback( LOK_CALLBACK_EXPORT_FILE
, "PENDING"_ostr
);
696 const uno::Sequence
< beans::PropertyValue
> aPropsFromDialog
= m_xFilterProperties
->getPropertyValues();
697 for ( const auto& rProp
: aPropsFromDialog
)
698 GetMediaDescr()[rProp
.Name
] = rProp
.Value
;
700 m_pOwner
->CallFinishGUIStoreModel();
704 pNotifier
->libreOfficeKitViewCallback( LOK_CALLBACK_EXPORT_FILE
, "ABORT"_ostr
);
708 sal_Int8
ModelData_Impl::CheckSaveAcceptable( sal_Int8 nCurStatus
)
710 sal_Int8 nResult
= nCurStatus
;
712 if ( nResult
!= STATUS_NO_ACTION
&& GetStorable()->hasLocation() )
714 // the saving is acceptable
715 // in case the configuration entry is not set or set to false
716 // or in case of version creation
717 if ( officecfg::Office::Common::Save::Document::AlwaysSaveAs::get()
718 && GetMediaDescr().find( u
"VersionComment"_ustr
) == GetMediaDescr().end() )
720 // notify the user that SaveAs is going to be done
721 std::unique_ptr
<weld::MessageDialog
> xMessageBox(Application::CreateMessageDialog(SfxStoringHelper::GetModelWindow(m_xModel
),
722 VclMessageType::Question
, VclButtonsType::OkCancel
, SfxResId(STR_NEW_FILENAME_SAVE
)));
723 if (xMessageBox
->run() == RET_OK
)
724 nResult
= STATUS_SAVEAS
;
726 nResult
= STATUS_NO_ACTION
;
734 sal_Int8
ModelData_Impl::CheckStateForSave()
736 // if the document is readonly or a new one a SaveAs operation must be used
737 if ( !GetStorable()->hasLocation() || GetStorable()->isReadonly() )
738 return STATUS_SAVEAS
;
740 // check acceptable entries for media descriptor
741 ::comphelper::SequenceAsHashMap aAcceptedArgs
;
743 static constexpr OUString
aVersionCommentString(u
"VersionComment"_ustr
);
744 static constexpr OUString
aAuthorString(u
"Author"_ustr
);
745 static constexpr OUString
aDontTerminateEdit(u
"DontTerminateEdit"_ustr
);
746 static constexpr OUString
aInteractionHandlerString(u
"InteractionHandler"_ustr
);
747 static constexpr OUString
aStatusIndicatorString(u
"StatusIndicator"_ustr
);
748 static constexpr OUString
aFailOnWarningString(u
"FailOnWarning"_ustr
);
749 static constexpr OUString
aNoFileSync(u
"NoFileSync"_ustr
);
751 if ( GetMediaDescr().find( aVersionCommentString
) != GetMediaDescr().end() )
752 aAcceptedArgs
[ aVersionCommentString
] = GetMediaDescr()[ aVersionCommentString
];
753 if ( GetMediaDescr().find( aAuthorString
) != GetMediaDescr().end() )
754 aAcceptedArgs
[ aAuthorString
] = GetMediaDescr()[ aAuthorString
];
755 if ( GetMediaDescr().find( aDontTerminateEdit
) != GetMediaDescr().end() )
756 aAcceptedArgs
[ aDontTerminateEdit
] = GetMediaDescr()[ aDontTerminateEdit
];
757 if ( GetMediaDescr().find( aInteractionHandlerString
) != GetMediaDescr().end() )
758 aAcceptedArgs
[ aInteractionHandlerString
] = GetMediaDescr()[ aInteractionHandlerString
];
759 if ( GetMediaDescr().find( aStatusIndicatorString
) != GetMediaDescr().end() )
760 aAcceptedArgs
[ aStatusIndicatorString
] = GetMediaDescr()[ aStatusIndicatorString
];
761 if ( GetMediaDescr().find( aFailOnWarningString
) != GetMediaDescr().end() )
762 aAcceptedArgs
[ aFailOnWarningString
] = GetMediaDescr()[ aFailOnWarningString
];
763 if (GetMediaDescr().find(aNoFileSync
) != GetMediaDescr().end())
764 aAcceptedArgs
[aNoFileSync
] = GetMediaDescr()[aNoFileSync
];
766 // remove unacceptable entry if there is any
767 DBG_ASSERT( GetMediaDescr().size() == aAcceptedArgs
.size(),
768 "Unacceptable parameters are provided in Save request!\n" );
769 if ( GetMediaDescr().size() != aAcceptedArgs
.size() )
770 GetMediaDescr() = std::move(aAcceptedArgs
);
772 // check that the old filter is acceptable
773 return CheckFilter( GetDocProps().getUnpackedValueOrDefault(aFilterNameString
, OUString()) );
776 sal_Int8
ModelData_Impl::CheckFilter( const OUString
& aFilterName
)
778 ::comphelper::SequenceAsHashMap aFiltPropsHM
;
779 SfxFilterFlags nFiltFlags
= SfxFilterFlags::NONE
;
780 if ( !aFilterName
.isEmpty() )
782 // get properties of filter
783 uno::Sequence
< beans::PropertyValue
> aFilterProps
;
784 m_pOwner
->GetFilterConfiguration()->getByName( aFilterName
) >>= aFilterProps
;
786 aFiltPropsHM
= ::comphelper::SequenceAsHashMap( aFilterProps
);
787 nFiltFlags
= static_cast<SfxFilterFlags
>(aFiltPropsHM
.getUnpackedValueOrDefault(u
"Flags"_ustr
, sal_Int32(0) ));
790 // only a temporary solution until default filter retrieving feature is implemented
791 // then GetDocServiceDefaultFilter() must be used
792 ::comphelper::SequenceAsHashMap aDefFiltPropsHM
= GetDocServiceDefaultFilterCheckFlags( SfxFilterFlags::IMPORT
| SfxFilterFlags::EXPORT
, SfxFilterFlags::NONE
);
793 SfxFilterFlags nDefFiltFlags
= static_cast<SfxFilterFlags
>(aDefFiltPropsHM
.getUnpackedValueOrDefault(u
"Flags"_ustr
, sal_Int32(0) ));
797 // if the old filter is not acceptable
798 // and there is no default filter or it is not acceptable for requested parameters then proceed with saveAs
799 if ( ( aFiltPropsHM
.empty() || !( nFiltFlags
& SfxFilterFlags::EXPORT
) )
800 && ( aDefFiltPropsHM
.empty() || !( nDefFiltFlags
& SfxFilterFlags::EXPORT
) || nDefFiltFlags
& SfxFilterFlags::INTERNAL
) )
801 return STATUS_SAVEAS
;
803 // so at this point there is either an acceptable old filter or default one
804 if ( aFiltPropsHM
.empty() || !( nFiltFlags
& SfxFilterFlags::EXPORT
) )
806 // so the default filter must be acceptable
807 return STATUS_SAVEAS_STANDARDNAME
;
809 else if ( ( !( nFiltFlags
& SfxFilterFlags::OWN
) || ( nFiltFlags
& SfxFilterFlags::ALIEN
) )
810 && !aDefFiltPropsHM
.empty()
811 && ( nDefFiltFlags
& SfxFilterFlags::EXPORT
) && !( nDefFiltFlags
& SfxFilterFlags::INTERNAL
))
816 // check if EncryptionData supports this output format
818 OUString aSupportedFilters
;
819 const ::comphelper::SequenceAsHashMap
& rDocumentProperties
= GetDocProps();
820 const css::uno::Sequence
<css::beans::NamedValue
> aEncryptionData
= rDocumentProperties
.getUnpackedValueOrDefault(u
"EncryptionData"_ustr
, css::uno::Sequence
<css::beans::NamedValue
>());
821 if (aEncryptionData
!= css::uno::Sequence
<css::beans::NamedValue
>())
823 for (const css::beans::NamedValue
& aNamedValue
: aEncryptionData
)
825 if (aNamedValue
.Name
== "SupportedFilters")
827 aNamedValue
.Value
>>= aSupportedFilters
;
832 // if 'SupportedFilters' is empty assume that all filters are supported.
833 if (!aSupportedFilters
.isEmpty())
835 const OUString aSelectedFilter
= aFiltPropsHM
.getUnpackedValueOrDefault(u
"UIName"_ustr
, OUString());
837 aSupportedFilters
= ";" + aSupportedFilters
+ ";";
838 const OUString aSearchToken
= ";" + aSelectedFilter
+ ";";
839 bAsk
= (aSupportedFilters
.indexOf(aSearchToken
) < 0);
845 // the default filter is acceptable and the old filter is alien one
846 // so ask to make a saveAs operation
847 const OUString aUIName
= aFiltPropsHM
.getUnpackedValueOrDefault(u
"UIName"_ustr
, OUString() );
848 const OUString aDefUIName
= aDefFiltPropsHM
.getUnpackedValueOrDefault(u
"UIName"_ustr
, OUString() );
849 const OUString aPreusedFilterName
= GetDocProps().getUnpackedValueOrDefault(u
"PreusedFilterName"_ustr
, OUString() );
850 const OUString aDefType
= aDefFiltPropsHM
.getUnpackedValueOrDefault( u
"Type"_ustr
, OUString() );
851 const OUString aDefExtension
= GetRecommendedExtension( aDefType
);
853 if ( aPreusedFilterName
!= aFilterName
&& aUIName
!= aDefUIName
)
855 if ( !SfxStoringHelper::WarnUnacceptableFormat( GetModel(), aUIName
, aDefExtension
,
856 static_cast<bool>( nDefFiltFlags
& SfxFilterFlags::ALIEN
) ) )
857 return STATUS_SAVEAS_STANDARDNAME
;
865 bool ModelData_Impl::CheckFilterOptionsDialogExistence()
867 uno::Sequence
< beans::NamedValue
> aSearchRequest
{ { u
"DocumentService"_ustr
, css::uno::Any(GetDocServiceName()) } };
869 uno::Reference
< container::XEnumeration
> xFilterEnum
=
870 m_pOwner
->GetFilterQuery()->createSubSetEnumerationByProperties( aSearchRequest
);
872 while ( xFilterEnum
->hasMoreElements() )
874 uno::Sequence
< beans::PropertyValue
> aProps
;
875 if ( xFilterEnum
->nextElement() >>= aProps
)
877 ::comphelper::SequenceAsHashMap
aPropsHM( aProps
);
878 if ( !aPropsHM
.getUnpackedValueOrDefault(u
"UIComponent"_ustr
, OUString()).isEmpty() )
887 bool ModelData_Impl::OutputFileDialog( sal_Int16 nStoreMode
,
888 const ::comphelper::SequenceAsHashMap
& aPreselectedFilterPropsHM
,
889 bool bSetStandardName
,
890 OUString
& aSuggestedName
,
891 bool bPreselectPassword
,
892 OUString
& aSuggestedDir
,
894 const OUString
& rStandardDir
,
895 const css::uno::Sequence
< OUString
>& rDenyList
)
897 if ( nStoreMode
== SAVEASREMOTE_REQUESTED
)
898 nStoreMode
= SAVEAS_REQUESTED
;
900 bool bUseFilterOptions
= false;
902 ::comphelper::SequenceAsHashMap::const_iterator aOverwriteIter
=
903 GetMediaDescr().find( u
"Overwrite"_ustr
);
905 // the file name must be specified if overwrite option is set
906 if ( aOverwriteIter
!= GetMediaDescr().end() )
907 throw task::ErrorCodeIOException(
908 u
"ModelData_Impl::OutputFileDialog: ERRCODE_IO_INVALIDPARAMETER"_ustr
,
909 uno::Reference
< uno::XInterface
>(),
910 sal_uInt32(ERRCODE_IO_INVALIDPARAMETER
));
912 // no target file name is specified
913 // we need to show the file dialog
915 // check if we have a filter which allows for filter options, so we need a corresponding checkbox in the dialog
916 bool bAllowOptions
= false;
918 // in case of Export, filter options dialog is used if available
919 if( !( nStoreMode
& EXPORT_REQUESTED
) || ( nStoreMode
& WIDEEXPORT_REQUESTED
) )
920 bAllowOptions
= CheckFilterOptionsDialogExistence();
922 // get the filename by dialog ...
923 // create the file dialog
924 sal_Int16 aDialogMode
= bAllowOptions
925 ? css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
926 : css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD
;
927 FileDialogFlags aDialogFlags
= FileDialogFlags::NONE
;
929 if( ( nStoreMode
& EXPORT_REQUESTED
) && !( nStoreMode
& WIDEEXPORT_REQUESTED
) )
931 if ( (nStoreMode
& PDFEXPORT_REQUESTED
) || (nStoreMode
& EPUBEXPORT_REQUESTED
) )
932 aDialogMode
= css::ui::dialogs::TemplateDescription::
933 FILESAVE_AUTOEXTENSION
;
935 aDialogMode
= css::ui::dialogs::TemplateDescription::
936 FILESAVE_AUTOEXTENSION_SELECTION
;
937 aDialogFlags
= FileDialogFlags::Export
;
940 if( ( nStoreMode
& EXPORT_REQUESTED
) && ( nStoreMode
& SAVEACOPY_REQUESTED
) && ( nStoreMode
& WIDEEXPORT_REQUESTED
) )
942 aDialogFlags
= FileDialogFlags::SaveACopy
;
945 std::unique_ptr
<sfx2::FileDialogHelper
> pFileDlg
;
947 const OUString aDocServiceName
{GetDocServiceName()};
948 DBG_ASSERT( !aDocServiceName
.isEmpty(), "No document service for this module set!" );
950 SfxFilterFlags nMust
= getMustFlags( nStoreMode
);
951 SfxFilterFlags nDont
= getDontFlags( nStoreMode
);
952 weld::Window
* pFrameWin
= SfxStoringHelper::GetModelWindow(m_xModel
);
953 if ( ( nStoreMode
& EXPORT_REQUESTED
) && !( nStoreMode
& WIDEEXPORT_REQUESTED
) )
955 if ( ( nStoreMode
& PDFEXPORT_REQUESTED
) && !aPreselectedFilterPropsHM
.empty() )
957 // this is a PDF export
958 // the filter options has been shown already
959 const OUString aFilterUIName
= aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( u
"UIName"_ustr
, OUString() );
960 pFileDlg
.reset(new sfx2::FileDialogHelper( aDialogMode
, aDialogFlags
, aFilterUIName
, u
"pdf", rStandardDir
, rDenyList
, pFrameWin
));
961 pFileDlg
->SetCurrentFilter( aFilterUIName
);
963 else if ((nStoreMode
& EPUBEXPORT_REQUESTED
) && !aPreselectedFilterPropsHM
.empty())
965 // This is an EPUB export, the filter options has been shown already.
966 const OUString aFilterUIName
= aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( u
"UIName"_ustr
, OUString() );
967 pFileDlg
.reset(new sfx2::FileDialogHelper(aDialogMode
, aDialogFlags
, aFilterUIName
, u
"epub", rStandardDir
, rDenyList
, pFrameWin
));
968 pFileDlg
->SetCurrentFilter(aFilterUIName
);
972 // This is the normal dialog
973 pFileDlg
.reset(new sfx2::FileDialogHelper( aDialogMode
, aDialogFlags
, aDocServiceName
, nDialog
, nMust
, nDont
, rStandardDir
, rDenyList
, pFrameWin
));
976 sfx2::FileDialogHelper::Context eCtxt
= sfx2::FileDialogHelper::UnknownContext
;
977 if ( aDocServiceName
== "com.sun.star.drawing.DrawingDocument" )
978 eCtxt
= sfx2::FileDialogHelper::DrawExport
;
979 else if ( aDocServiceName
== "com.sun.star.presentation.PresentationDocument" )
980 eCtxt
= sfx2::FileDialogHelper::ImpressExport
;
981 else if ( aDocServiceName
== "com.sun.star.text.TextDocument" )
982 eCtxt
= sfx2::FileDialogHelper::WriterExport
;
983 else if ( aDocServiceName
== "com.sun.star.sheet.SpreadsheetDocument" )
984 eCtxt
= sfx2::FileDialogHelper::CalcExport
;
986 if ( eCtxt
!= sfx2::FileDialogHelper::UnknownContext
)
987 pFileDlg
->SetContext( eCtxt
);
989 pFileDlg
->CreateMatcher( aDocServiceName
);
991 uno::Reference
< ui::dialogs::XFilePicker3
> xFilePicker
= pFileDlg
->GetFilePicker();
992 uno::Reference
< ui::dialogs::XFilePickerControlAccess
> xControlAccess( xFilePicker
, uno::UNO_QUERY
);
994 if ( xControlAccess
.is() )
996 xControlAccess
->setLabel( ui::dialogs::CommonFilePickerElementIds::PUSHBUTTON_OK
, SfxResId(STR_EXPORTBUTTON
) );
997 xControlAccess
->setLabel( ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER_LABEL
, SfxResId(STR_LABEL_FILEFORMAT
) );
1002 // This is the normal save as dialog
1003 pFileDlg
.reset(new sfx2::FileDialogHelper( aDialogMode
, aDialogFlags
, aDocServiceName
, nDialog
,
1004 nMust
, nDont
, rStandardDir
, rDenyList
, pFrameWin
));
1005 pFileDlg
->CreateMatcher( aDocServiceName
);
1007 sfx2::FileDialogHelper::Context eCtxt
= sfx2::FileDialogHelper::UnknownContext
;
1008 if ( aDocServiceName
== "com.sun.star.drawing.DrawingDocument" )
1009 eCtxt
= sfx2::FileDialogHelper::DrawSaveAs
;
1010 else if ( aDocServiceName
== "com.sun.star.presentation.PresentationDocument" )
1011 eCtxt
= sfx2::FileDialogHelper::ImpressSaveAs
;
1012 else if ( aDocServiceName
== "com.sun.star.text.TextDocument" )
1013 eCtxt
= sfx2::FileDialogHelper::WriterSaveAs
;
1014 else if ( aDocServiceName
== "com.sun.star.sheet.SpreadsheetDocument" )
1015 eCtxt
= sfx2::FileDialogHelper::CalcSaveAs
;
1017 if ( eCtxt
!= sfx2::FileDialogHelper::UnknownContext
)
1018 pFileDlg
->SetContext( eCtxt
);
1021 OUString aAdjustToType
;
1023 const OUString
sFilterNameString(aFilterNameString
);
1025 if ( ( nStoreMode
& EXPORT_REQUESTED
) && !( nStoreMode
& WIDEEXPORT_REQUESTED
) )
1027 // it is export, set the preselected filter
1028 pFileDlg
->SetCurrentFilter( aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( u
"UIName"_ustr
, OUString() ) );
1029 aAdjustToType
= aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( u
"Type"_ustr
, OUString() );
1031 // it is no export, bSetStandardName == true means that user agreed to store document in the default (default default ;-)) format
1032 else if ( bSetStandardName
|| GetStorable()->hasLocation() )
1034 uno::Sequence
< beans::PropertyValue
> aOldFilterProps
;
1035 const OUString aOldFilterName
= GetDocProps().getUnpackedValueOrDefault( sFilterNameString
, OUString() );
1037 if ( !aOldFilterName
.isEmpty() )
1038 m_pOwner
->GetFilterConfiguration()->getByName( aOldFilterName
) >>= aOldFilterProps
;
1040 ::comphelper::SequenceAsHashMap
aOldFiltPropsHM( aOldFilterProps
);
1041 SfxFilterFlags nOldFiltFlags
= static_cast<SfxFilterFlags
>(aOldFiltPropsHM
.getUnpackedValueOrDefault(u
"Flags"_ustr
, sal_Int32(0) ));
1043 if ( bSetStandardName
|| ( nOldFiltFlags
& nMust
) != nMust
|| bool(nOldFiltFlags
& nDont
) )
1045 // the suggested type will be changed, the extension should be adjusted
1046 aAdjustToType
= aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( u
"Type"_ustr
, OUString() );
1047 pFileDlg
->SetCurrentFilter( aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( u
"UIName"_ustr
, OUString() ) );
1051 pFileDlg
->SetCurrentFilter( aOldFiltPropsHM
.getUnpackedValueOrDefault(
1057 const OUString aRecommendedDir
{GetRecommendedDir( aSuggestedDir
)};
1058 if ( !aRecommendedDir
.isEmpty() )
1059 pFileDlg
->SetDisplayFolder( aRecommendedDir
);
1060 const OUString aRecommendedName
{GetRecommendedName( aSuggestedName
, aAdjustToType
)};
1061 if ( !aRecommendedName
.isEmpty() )
1062 pFileDlg
->SetFileName( aRecommendedName
);
1064 uno::Reference
< view::XSelectionSupplier
> xSel( GetModel()->getCurrentController(), uno::UNO_QUERY
);
1065 if ( xSel
.is() && xSel
->getSelection().hasValue() )
1066 GetMediaDescr()[u
"SelectionOnly"_ustr
] <<= true;
1068 // This is a temporary hardcoded solution must be removed when
1069 // dialogs do not need parameters in SidSet representation any more
1070 sal_uInt16 nSlotID
= getSlotIDFromMode( nStoreMode
);
1072 throw lang::IllegalArgumentException(); // TODO:
1074 // generate SidSet from MediaDescriptor and provide it into FileDialog
1075 // than merge changed SidSet back
1076 std::optional
<SfxAllItemSet
> pDialogParams( SfxGetpApp()->GetPool() );
1077 TransformParameters( nSlotID
,
1078 GetMediaDescr().getAsConstPropertyValueList(),
1081 if ( bPreselectPassword
&& !pDialogParams
->HasItem( SID_ENCRYPTIONDATA
) )
1083 // the file dialog preselects the password checkbox if the provided mediadescriptor has encryption data entry
1084 // after dialog execution the password interaction flag will be either removed or not
1085 pDialogParams
->Put( SfxBoolItem( SID_PASSWORDINTERACTION
, true ) );
1088 // aFilterName is a pure output parameter, pDialogParams is an in/out parameter
1089 OUString aFilterName
;
1090 // in LOK case we don't show File Picker so it will fail, but execute to do other preparations
1091 if ( pFileDlg
->Execute( pDialogParams
, aFilterName
) != ERRCODE_NONE
1092 && !comphelper::LibreOfficeKit::isActive() )
1094 throw task::ErrorCodeIOException(
1095 u
"ModelData_Impl::OutputFileDialog: ERRCODE_IO_ABORT"_ustr
,
1096 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_ABORT
));
1098 else if (comphelper::LibreOfficeKit::isActive())
1100 aFilterName
= aPreselectedFilterPropsHM
.getUnpackedValueOrDefault( u
"Name"_ustr
, OUString() );
1103 // the following two arguments can not be converted in MediaDescriptor,
1104 // so they should be removed from the ItemSet after retrieving
1105 const SfxBoolItem
* pRecommendReadOnly
= SfxItemSet::GetItem
<SfxBoolItem
>(&*pDialogParams
, SID_RECOMMENDREADONLY
, false);
1106 m_bRecommendReadOnly
= ( pRecommendReadOnly
&& pRecommendReadOnly
->GetValue() );
1107 pDialogParams
->ClearItem( SID_RECOMMENDREADONLY
);
1109 const SfxBoolItem
* pSignWithDefaultKey
= SfxItemSet::GetItem
<SfxBoolItem
>(&*pDialogParams
, SID_GPGSIGN
, false);
1110 m_bSignWithDefaultSignature
= (pSignWithDefaultKey
&& pSignWithDefaultKey
->GetValue());
1111 pDialogParams
->ClearItem( SID_GPGSIGN
);
1113 uno::Sequence
< beans::PropertyValue
> aPropsFromDialog
;
1114 TransformItems( nSlotID
, *pDialogParams
, aPropsFromDialog
);
1115 GetMediaDescr() << aPropsFromDialog
;
1117 // get the path from the dialog
1118 INetURLObject
aURL( pFileDlg
->GetPath() );
1120 if (comphelper::LibreOfficeKit::isActive())
1123 // The iOS app (and maybe the Android app) have fails to set the URL to
1124 // save to so we need to set it to a temporary file.
1125 // Note: the iOS app is responsible for deleting the temporary file.
1126 if (nStoreMode
& EXPORT_REQUESTED
&& aURL
.GetMainURL(INetURLObject::DecodeMechanism::NONE
).isEmpty())
1128 // Mirror the "export/docbasename.pdf" path format to match the
1129 // format used in the "downloadas" message handler in the iOS app's
1130 // -[DocumentViewController userContentController:didReceiveScriptMessage]
1132 // Important note: temporary files created here must be in their
1133 // own subdirectory since the iOS app's UIDocumentPickerDelegate
1134 // will try to delete both the temporary file and its parent
1136 OUString aFullName
= u
"export/" + aRecommendedName
;
1138 OUString aExtension
;
1139 sal_Int32 nPos
= aFullName
.lastIndexOf( '.' );
1142 aBaseName
= aFullName
.copy(0, nPos
);
1143 aExtension
= aFullName
.copy(nPos
, aFullName
.getLength() - nPos
);
1145 aURL
= INetURLObject(::utl::CreateTempURL( aBaseName
, false, aExtension
, nullptr, true));
1147 // Remove any stale files left from a previous export
1148 OUString fileURL
= aURL
.GetMainURL(INetURLObject::DecodeMechanism::NONE
);
1149 if (!fileURL
.isEmpty())
1150 osl::File::remove(fileURL
);
1155 // keep name with extension
1156 aSuggestedName
= aRecommendedName
;
1157 OUString aExtension
;
1158 if (size_t nPos
= aSuggestedName
.lastIndexOf('.') + 1)
1159 aExtension
= aSuggestedName
.copy(nPos
, aSuggestedName
.getLength() - nPos
);
1160 aURL
.SetExtension(aExtension
);
1167 // the path should be provided outside since it might be used for further calls to the dialog
1168 aSuggestedName
= aURL
.GetLastName(INetURLObject::DecodeMechanism::WithCharset
);
1170 aSuggestedDir
= pFileDlg
->GetDisplayDirectory();
1172 // old filter options should be cleared in case different filter is used
1174 const OUString aFilterFromMediaDescr
= GetMediaDescr().getUnpackedValueOrDefault( sFilterNameString
, OUString() );
1175 const OUString aOldFilterName
= GetDocProps().getUnpackedValueOrDefault( sFilterNameString
, OUString() );
1177 if ( aFilterName
== aFilterFromMediaDescr
)
1179 // preserve current settings if any
1180 // if there no current settings and the name is the same
1181 // as old filter name use old filter settings
1183 if ( aFilterFromMediaDescr
== aOldFilterName
)
1185 ::comphelper::SequenceAsHashMap::const_iterator aIter
=
1186 GetDocProps().find( aFilterOptionsString
);
1187 if ( aIter
!= GetDocProps().end()
1188 && GetMediaDescr().find( aFilterOptionsString
) == GetMediaDescr().end() )
1189 GetMediaDescr()[aIter
->first
] = aIter
->second
;
1191 aIter
= GetDocProps().find( aFilterDataString
);
1192 if ( aIter
!= GetDocProps().end()
1193 && GetMediaDescr().find( aFilterDataString
) == GetMediaDescr().end() )
1194 GetMediaDescr()[aIter
->first
] = aIter
->second
;
1199 GetMediaDescr().erase( aFilterDataString
);
1200 GetMediaDescr().erase( aFilterOptionsString
);
1202 if ( aFilterName
== aOldFilterName
)
1204 // merge filter option of the document filter
1206 ::comphelper::SequenceAsHashMap::const_iterator aIter
=
1207 GetDocProps().find( aFilterOptionsString
);
1208 if ( aIter
!= GetDocProps().end() )
1209 GetMediaDescr()[aIter
->first
] = aIter
->second
;
1211 aIter
= GetDocProps().find( aFilterDataString
);
1212 if ( aIter
!= GetDocProps().end() )
1213 GetMediaDescr()[aIter
->first
] = aIter
->second
;
1217 uno::Reference
< ui::dialogs::XFilePickerControlAccess
> xExtFileDlg( pFileDlg
->GetFilePicker(), uno::UNO_QUERY
);
1218 if ( xExtFileDlg
.is() )
1220 if ( SfxStoringHelper::CheckFilterOptionsAppearance( m_pOwner
->GetFilterConfiguration(), aFilterName
) )
1221 bUseFilterOptions
= true;
1223 if ( ( !( nStoreMode
& EXPORT_REQUESTED
) || ( nStoreMode
& WIDEEXPORT_REQUESTED
) ) && bUseFilterOptions
)
1227 // for exporters: always show dialog if format uses options
1228 // for save: show dialog if format uses options and no options given or if forced by user
1230 xExtFileDlg
->getValue( ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
, 0 );
1232 aVal
>>= bUseFilterOptions
;
1233 if ( !bUseFilterOptions
)
1235 ( GetMediaDescr().find( aFilterDataString
) == GetMediaDescr().end()
1236 && GetMediaDescr().find( aFilterOptionsString
) == GetMediaDescr().end() );
1238 catch( const lang::IllegalArgumentException
& )
1243 // merge in results of the dialog execution
1244 GetMediaDescr()[u
"URL"_ustr
] <<= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1245 GetMediaDescr()[sFilterNameString
] <<= aFilterName
;
1247 return bUseFilterOptions
;
1251 bool ModelData_Impl::ShowDocumentInfoDialog()
1253 bool bDialogUsed
= false;
1256 uno::Reference
< frame::XController
> xController
= GetModel()->getCurrentController();
1257 if ( xController
.is() )
1259 uno::Reference
< frame::XDispatchProvider
> xFrameDispatch( xController
->getFrame(), uno::UNO_QUERY
);
1260 if ( xFrameDispatch
.is() )
1263 aURL
.Complete
= ".uno:SetDocumentProperties";
1265 uno::Reference
< util::XURLTransformer
> xTransformer( util::URLTransformer::create( comphelper::getProcessComponentContext() ) );
1266 if ( xTransformer
->parseStrict( aURL
) )
1268 uno::Reference
< frame::XDispatch
> xDispatch
= xFrameDispatch
->queryDispatch(
1272 if ( xDispatch
.is() )
1274 // tdf#119206 use (abuse?) a SynchronMode of true,
1275 // which will become SfxRequest::IsSynchronCall of true
1276 // in SfxObjectShell::ExecFile_Impl to request that we
1277 // do not want the properties dialog to be run async
1278 uno::Sequence
< beans::PropertyValue
> aProperties
{
1279 comphelper::makePropertyValue(u
"SynchronMode"_ustr
, true)
1281 xDispatch
->dispatch(aURL
, aProperties
);
1288 catch ( const uno::Exception
& )
1296 OUString
ModelData_Impl::GetRecommendedExtension( const OUString
& aTypeName
)
1298 if ( aTypeName
.isEmpty() )
1301 uno::Reference
< container::XNameAccess
> xTypeDetection(
1302 comphelper::getProcessServiceFactory()->createInstance(u
"com.sun.star.document.TypeDetection"_ustr
),
1304 if ( xTypeDetection
.is() )
1306 uno::Sequence
< beans::PropertyValue
> aTypeNameProps
;
1307 if ( ( xTypeDetection
->getByName( aTypeName
) >>= aTypeNameProps
) && aTypeNameProps
.hasElements() )
1309 ::comphelper::SequenceAsHashMap
aTypeNamePropsHM( aTypeNameProps
);
1310 uno::Sequence
< OUString
> aExtensions
= aTypeNamePropsHM
.getUnpackedValueOrDefault(
1312 ::uno::Sequence
< OUString
>() );
1313 if ( aExtensions
.hasElements() )
1314 return aExtensions
[0];
1322 OUString
ModelData_Impl::GetRecommendedDir( const OUString
& aSuggestedDir
)
1324 if ( ( !aSuggestedDir
.isEmpty() || GetStorable()->hasLocation() )
1325 && !GetMediaDescr().getUnpackedValueOrDefault(u
"RepairPackage"_ustr
, false ) )
1327 INetURLObject aLocation
;
1328 if ( !aSuggestedDir
.isEmpty() )
1329 aLocation
= INetURLObject( aSuggestedDir
);
1332 const OUString aOldURL
= GetStorable()->getLocation();
1333 if ( !aOldURL
.isEmpty() )
1335 INetURLObject
aTmp( aOldURL
);
1336 if ( aTmp
.removeSegment() )
1337 aLocation
= std::move(aTmp
);
1340 if ( aLocation
.HasError() )
1341 aLocation
= INetURLObject();
1344 OUString
sLocationURL( aLocation
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
1345 bool bIsInTempPath( false );
1346 OUString sSysTempPath
;
1347 if( osl::FileBase::getTempDirURL( sSysTempPath
) == osl::FileBase::E_None
)
1348 bIsInTempPath
= !sSysTempPath
.isEmpty() && sLocationURL
.startsWith( sSysTempPath
);
1350 if( !bIsInTempPath
)
1353 HRESULT hRes
= SHGetKnownFolderPath(FOLDERID_InternetCache
, 0, nullptr, &sPath
);
1354 if( SUCCEEDED(hRes
) )
1356 OUString sTempINetFiles
;
1357 if( osl::FileBase::getFileURLFromSystemPath(OUString(o3tl::toU(sPath
)), sTempINetFiles
) == osl::FileBase::E_None
)
1358 bIsInTempPath
= !sTempINetFiles
.isEmpty() && sLocationURL
.startsWith( sTempINetFiles
);
1360 CoTaskMemFree(sPath
);
1363 // Suggest somewhere other than the system's temp directory
1365 aLocation
= INetURLObject();
1367 aLocation
.setFinalSlash();
1368 if ( !aLocation
.HasError() )
1369 return aLocation
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1378 OUString
ModelData_Impl::GetRecommendedName( const OUString
& aSuggestedName
, const OUString
& aTypeName
)
1380 // the last used name might be provided by aSuggestedName from the old selection, or from the MediaDescriptor
1381 if ( !aSuggestedName
.isEmpty() )
1382 return aSuggestedName
;
1384 OUString aRecommendedName
{ INetURLObject(GetStorable()->getLocation())
1385 .GetLastName(INetURLObject::DecodeMechanism::WithCharset
) };
1386 if ( aRecommendedName
.isEmpty() )
1389 uno::Reference
< frame::XTitle
> xTitle( GetModel(), uno::UNO_QUERY_THROW
);
1390 aRecommendedName
= xTitle
->getTitle();
1391 } catch( const uno::Exception
& ) {}
1394 if ( !aRecommendedName
.isEmpty() && !aTypeName
.isEmpty() )
1396 // adjust the extension to the type
1397 uno::Reference
< container::XNameAccess
> xTypeDetection(
1398 comphelper::getProcessServiceFactory()->createInstance(u
"com.sun.star.document.TypeDetection"_ustr
),
1400 if ( xTypeDetection
.is() )
1402 INetURLObject
aObj( rtl::Concat2View("c:/" + aRecommendedName
), INetProtocol::File
,
1403 INetURLObject::EncodeMechanism::All
, RTL_TEXTENCODING_UTF8
, FSysStyle::Dos
);
1405 const OUString aExtension
= GetRecommendedExtension( aTypeName
);
1406 if ( !aExtension
.isEmpty() )
1407 aObj
.SetExtension( aExtension
);
1409 aRecommendedName
= aObj
.GetLastName(INetURLObject::DecodeMechanism::WithCharset
);
1413 return aRecommendedName
;
1416 SfxStoringHelper::SfxStoringHelper()
1418 , m_bPreselectPassword(false)
1419 , m_bDialogUsed(false)
1420 , m_bSetStandardName(false)
1425 uno::Reference
< container::XNameAccess
> const & SfxStoringHelper::GetFilterConfiguration()
1427 if ( !m_xFilterCFG
.is() )
1429 m_xFilterCFG
.set( comphelper::getProcessServiceFactory()->createInstance(u
"com.sun.star.document.FilterFactory"_ustr
),
1430 uno::UNO_QUERY_THROW
);
1433 return m_xFilterCFG
;
1436 uno::Reference
< container::XContainerQuery
> const & SfxStoringHelper::GetFilterQuery()
1438 if ( !m_xFilterQuery
.is() )
1440 m_xFilterQuery
.set( GetFilterConfiguration(), uno::UNO_QUERY_THROW
);
1443 return m_xFilterQuery
;
1446 uno::Reference
< css::frame::XModuleManager2
> const & SfxStoringHelper::GetModuleManager()
1448 if ( !m_xModuleManager
.is() )
1450 m_xModuleManager
= frame::ModuleManager::create(
1451 comphelper::getProcessComponentContext() );
1454 return m_xModuleManager
;
1457 bool SfxStoringHelper::GUIStoreModel( const uno::Reference
< frame::XModel
>& xModel
,
1458 std::u16string_view aSlotName
,
1459 uno::Sequence
< beans::PropertyValue
>& aArgsSequence
,
1460 bool bPreselectPassword
,
1461 SignatureState nDocumentSignatureState
,
1464 m_xModelData
= std::make_shared
<ModelData_Impl
>( *this, xModel
, aArgsSequence
);
1465 m_aArgsSequence
= aArgsSequence
;
1466 ModelData_Impl
& aModelData
= *m_xModelData
;
1468 m_bDialogUsed
= false;
1470 m_bSetStandardName
= false; // can be set only for SaveAs
1471 m_bPreselectPassword
= bPreselectPassword
;
1473 // parse the slot name
1475 m_nStoreMode
= getStoreModeFromSlotName( aSlotName
);
1477 if ( m_nStoreMode
== SAVEASREMOTE_REQUESTED
)
1479 m_nStoreMode
= SAVEAS_REQUESTED
;
1483 sal_Int8 nStatusSave
= STATUS_NO_ACTION
;
1485 ::comphelper::SequenceAsHashMap::const_iterator aSaveACopyIter
=
1486 aModelData
.GetMediaDescr().find( u
"SaveACopy"_ustr
);
1487 if ( aSaveACopyIter
!= aModelData
.GetMediaDescr().end() )
1489 bool bSaveACopy
= false;
1490 aSaveACopyIter
->second
>>= bSaveACopy
;
1492 m_nStoreMode
= EXPORT_REQUESTED
| SAVEACOPY_REQUESTED
| WIDEEXPORT_REQUESTED
;
1494 // handle the special cases
1495 if ( m_nStoreMode
& SAVEAS_REQUESTED
)
1497 ::comphelper::SequenceAsHashMap::const_iterator aSaveToIter
=
1498 aModelData
.GetMediaDescr().find( u
"SaveTo"_ustr
);
1499 if ( aSaveToIter
!= aModelData
.GetMediaDescr().end() )
1501 bool bWideExport
= false;
1502 aSaveToIter
->second
>>= bWideExport
;
1504 m_nStoreMode
= EXPORT_REQUESTED
| WIDEEXPORT_REQUESTED
;
1507 // if saving is not acceptable the warning must be shown even in case of SaveAs operation
1508 if ( ( m_nStoreMode
& SAVEAS_REQUESTED
) && aModelData
.CheckSaveAcceptable( STATUS_SAVEAS
) == STATUS_NO_ACTION
)
1509 throw task::ErrorCodeIOException(
1510 u
"SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT"_ustr
,
1511 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_ABORT
));
1513 else if ( m_nStoreMode
& SAVE_REQUESTED
)
1515 // if saving is not acceptable by the configuration the warning must be shown
1516 nStatusSave
= aModelData
.CheckSaveAcceptable( STATUS_SAVE
);
1518 if ( nStatusSave
== STATUS_NO_ACTION
)
1519 throw task::ErrorCodeIOException(
1520 u
"SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT"_ustr
,
1521 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_ABORT
));
1522 else if ( nStatusSave
== STATUS_SAVE
)
1524 // check whether it is possible to use save operation
1525 nStatusSave
= aModelData
.CheckStateForSave();
1528 if ( nStatusSave
== STATUS_NO_ACTION
)
1530 throw task::ErrorCodeIOException(
1531 u
"SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT"_ustr
,
1532 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_ABORT
));
1534 else if ( nStatusSave
!= STATUS_SAVE
)
1536 // this should be a usual SaveAs operation
1537 m_nStoreMode
= SAVEAS_REQUESTED
;
1538 if ( nStatusSave
== STATUS_SAVEAS_STANDARDNAME
)
1539 m_bSetStandardName
= true;
1543 if (!comphelper::LibreOfficeKit::isActive() && !( m_nStoreMode
& EXPORT_REQUESTED
) && SfxViewShell::Current() )
1545 SfxObjectShell
* pDocShell
= SfxViewShell::Current()->GetObjectShell();
1547 // if it is no export, warn user that the signature will be removed
1548 if ( !pDocShell
->IsRememberingSignature()
1549 && (SignatureState::OK
== nDocumentSignatureState
1550 || SignatureState::INVALID
== nDocumentSignatureState
1551 || SignatureState::NOTVALIDATED
== nDocumentSignatureState
1552 || SignatureState::PARTIAL_OK
== nDocumentSignatureState
) )
1554 std::unique_ptr
<weld::MessageDialog
> xMessageBox(Application::CreateMessageDialog(SfxStoringHelper::GetModelWindow(xModel
),
1555 VclMessageType::Question
, VclButtonsType::YesNo
, SfxResId(RID_SVXSTR_XMLSEC_QUERY_LOSINGSIGNATURE
)));
1556 if (xMessageBox
->run() != RET_YES
)
1558 // the user has decided not to store the document
1559 throw task::ErrorCodeIOException(
1560 u
"SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT (Preserve Signature)"_ustr
,
1561 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_ABORT
));
1566 if ( m_nStoreMode
& SAVE_REQUESTED
&& nStatusSave
== STATUS_SAVE
)
1568 // Document properties can contain streams that should be freed before storing
1569 aModelData
.FreeDocumentProps();
1571 if ( aModelData
.GetStorable2().is() )
1575 aModelData
.GetStorable2()->storeSelf( aModelData
.GetMediaDescr().getAsConstPropertyValueList() );
1577 catch (const lang::IllegalArgumentException
&)
1579 TOOLS_WARN_EXCEPTION("sfx.doc", "Ignoring parameters! ModelData considers this illegal");
1580 aModelData
.GetStorable()->store();
1585 OSL_FAIL( "XStorable2 is not supported by the model!" );
1586 aModelData
.GetStorable()->store();
1592 // preselect a filter for the storing process
1593 uno::Sequence
< beans::PropertyValue
> aFilterProps
= aModelData
.GetPreselectedFilter_Impl( m_nStoreMode
);
1595 DBG_ASSERT( aFilterProps
.hasElements(), "No filter for storing!\n" );
1596 if ( !aFilterProps
.hasElements() )
1597 throw task::ErrorCodeIOException(
1598 u
"SfxStoringHelper::GUIStoreModel: ERRCODE_IO_INVALIDPARAMETER"_ustr
,
1599 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_INVALIDPARAMETER
));
1601 ::comphelper::SequenceAsHashMap
aFilterPropsHM( aFilterProps
);
1602 OUString aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault( u
"Name"_ustr
, OUString() );
1604 const OUString aFilterFromMediaDescr
= aModelData
.GetMediaDescr().getUnpackedValueOrDefault( aFilterNameString
, OUString() );
1605 const OUString aOldFilterName
= aModelData
.GetDocProps().getUnpackedValueOrDefault( aFilterNameString
, OUString() );
1607 ::comphelper::SequenceAsHashMap::const_iterator aFileNameIter
= aModelData
.GetMediaDescr().find( u
"URL"_ustr
);
1609 bool bPDFOptions
= (m_nStoreMode
& PDFEXPORT_REQUESTED
) && !(m_nStoreMode
& PDFDIRECTEXPORT_REQUESTED
);
1610 bool bEPUBOptions
= (m_nStoreMode
& EPUBEXPORT_REQUESTED
) && !(m_nStoreMode
& EPUBDIRECTEXPORT_REQUESTED
);
1611 if ( ( m_nStoreMode
& EXPORT_REQUESTED
) && (bPDFOptions
|| bEPUBOptions
) )
1613 // this is PDF or EPUB export, the filter options dialog should be shown before the export
1614 aModelData
.GetMediaDescr()[aFilterNameString
] <<= aFilterName
;
1615 if ( aModelData
.GetMediaDescr().find( u
"FilterFlags"_ustr
) == aModelData
.GetMediaDescr().end()
1616 && aModelData
.GetMediaDescr().find( aFilterOptionsString
) == aModelData
.GetMediaDescr().end()
1617 && aModelData
.GetMediaDescr().find( aFilterDataString
) == aModelData
.GetMediaDescr().end() )
1619 // execute filter options dialog since no options are set in the media descriptor
1620 if ( aModelData
.ExecuteFilterDialog_Impl( aFilterName
, bIsAsync
) )
1621 m_bDialogUsed
= true;
1628 return SfxStoringHelper::FinishGUIStoreModel(aFileNameIter
, aModelData
, m_bRemote
, m_nStoreMode
, aFilterProps
,
1629 m_bSetStandardName
, m_bPreselectPassword
, m_bDialogUsed
,
1630 aFilterFromMediaDescr
, aOldFilterName
, aArgsSequence
, aFilterName
);
1633 bool SfxStoringHelper::FinishGUIStoreModel(::comphelper::SequenceAsHashMap::const_iterator
& aFileNameIter
,
1634 ModelData_Impl
& aModelData
, bool bRemote
, sal_Int16 nStoreMode
,
1635 uno::Sequence
< beans::PropertyValue
>& aFilterProps
,
1636 bool bSetStandardName
, bool bPreselectPassword
, bool bDialogUsed
,
1637 std::u16string_view aFilterFromMediaDescr
,
1638 std::u16string_view aOldFilterName
,
1639 uno::Sequence
< beans::PropertyValue
>& aArgsSequence
,
1640 OUString aFilterName
)
1642 const OUString
sFilterNameString(aFilterNameString
);
1643 const OUString
sFilterOptionsString(aFilterOptionsString
);
1644 const OUString
sFilterDataString(aFilterDataString
);
1645 bool bUseFilterOptions
= false;
1648 if ( aFileNameIter
== aModelData
.GetMediaDescr().end() )
1650 sal_Int16 nDialog
= SFX2_IMPL_DIALOG_CONFIG
;
1654 nDialog
= SFX2_IMPL_DIALOG_REMOTE
;
1658 ::comphelper::SequenceAsHashMap::const_iterator aDlgIter
=
1659 aModelData
.GetMediaDescr().find( u
"UseSystemDialog"_ustr
);
1660 if ( aDlgIter
!= aModelData
.GetMediaDescr().end() )
1662 bool bUseSystemDialog
= true;
1663 if ( aDlgIter
->second
>>= bUseSystemDialog
)
1665 if ( bUseSystemDialog
)
1666 nDialog
= SFX2_IMPL_DIALOG_SYSTEM
;
1668 nDialog
= SFX2_IMPL_DIALOG_OOO
;
1673 // The Dispatch supports parameter FolderName that overwrites SuggestedSaveAsDir
1674 OUString aSuggestedDir
= aModelData
.GetMediaDescr().getUnpackedValueOrDefault(u
"FolderName"_ustr
, OUString() );
1675 if ( aSuggestedDir
.isEmpty() )
1677 aSuggestedDir
= aModelData
.GetMediaDescr().getUnpackedValueOrDefault(u
"SuggestedSaveAsDir"_ustr
, OUString() );
1678 if ( aSuggestedDir
.isEmpty() )
1679 aSuggestedDir
= aModelData
.GetDocProps().getUnpackedValueOrDefault(u
"SuggestedSaveAsDir"_ustr
, OUString() );
1682 OUString aSuggestedName
= aModelData
.GetMediaDescr().getUnpackedValueOrDefault(u
"SuggestedSaveAsName"_ustr
, OUString() );
1683 if ( aSuggestedName
.isEmpty() )
1684 aSuggestedName
= aModelData
.GetDocProps().getUnpackedValueOrDefault(u
"SuggestedSaveAsName"_ustr
, OUString() );
1686 OUString sStandardDir
;
1687 ::comphelper::SequenceAsHashMap::const_iterator aStdDirIter
=
1688 aModelData
.GetMediaDescr().find( u
"StandardDir"_ustr
);
1689 if ( aStdDirIter
!= aModelData
.GetMediaDescr().end() )
1690 aStdDirIter
->second
>>= sStandardDir
;
1692 css::uno::Sequence
< OUString
> aDenyList
;
1694 ::comphelper::SequenceAsHashMap::const_iterator aDenyListIter
=
1695 aModelData
.GetMediaDescr().find( u
"DenyList"_ustr
);
1696 if ( aDenyListIter
!= aModelData
.GetMediaDescr().end() )
1697 aDenyListIter
->second
>>= aDenyList
;
1701 // 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
1702 bUseFilterOptions
= aModelData
.OutputFileDialog( nStoreMode
, aFilterProps
, bSetStandardName
, aSuggestedName
, bPreselectPassword
, aSuggestedDir
, nDialog
, sStandardDir
, aDenyList
);
1703 if ( nStoreMode
== SAVEAS_REQUESTED
)
1705 // in case of saving check filter for possible alien warning
1706 const OUString aSelFilterName
= aModelData
.GetMediaDescr().getUnpackedValueOrDefault( sFilterNameString
, OUString() );
1707 sal_Int8 nStatusFilterSave
= aModelData
.CheckFilter( aSelFilterName
);
1708 if ( nStatusFilterSave
== STATUS_SAVEAS_STANDARDNAME
)
1710 // switch to best filter
1711 bSetStandardName
= true;
1713 else if ( nStatusFilterSave
== STATUS_SAVE
)
1715 // user confirmed alien filter or "good" filter is used
1724 aFileNameIter
= aModelData
.GetMediaDescr().find( u
"URL"_ustr
);
1728 // the target file name is provided so check if new filter options
1729 // are provided or old options can be used
1730 if ( aFilterFromMediaDescr
== aOldFilterName
)
1732 ::comphelper::SequenceAsHashMap::const_iterator aIter
=
1733 aModelData
.GetDocProps().find( sFilterOptionsString
);
1734 if ( aIter
!= aModelData
.GetDocProps().end()
1735 && aModelData
.GetMediaDescr().find( sFilterOptionsString
) == aModelData
.GetMediaDescr().end() )
1736 aModelData
.GetMediaDescr()[aIter
->first
] = aIter
->second
;
1738 aIter
= aModelData
.GetDocProps().find( sFilterDataString
);
1739 if ( aIter
!= aModelData
.GetDocProps().end()
1740 && aModelData
.GetMediaDescr().find( sFilterDataString
) == aModelData
.GetMediaDescr().end() )
1741 aModelData
.GetMediaDescr()[aIter
->first
] = aIter
->second
;
1745 if ( aFileNameIter
!= aModelData
.GetMediaDescr().end() )
1748 aFileNameIter
->second
>>= aFileName
;
1749 aURL
.SetURL( aFileName
);
1750 DBG_ASSERT( aURL
.GetProtocol() != INetProtocol::NotValid
, "Illegal URL!" );
1752 ::comphelper::SequenceAsHashMap::const_iterator aIter
=
1753 aModelData
.GetMediaDescr().find( sFilterNameString
);
1755 if ( aIter
!= aModelData
.GetMediaDescr().end() )
1756 aIter
->second
>>= aFilterName
;
1758 aModelData
.GetMediaDescr()[sFilterNameString
] <<= aFilterName
;
1760 DBG_ASSERT( !aFilterName
.isEmpty(), "Illegal filter!" );
1764 SAL_WARN( "sfx.doc", "This code must be unreachable!" );
1765 throw task::ErrorCodeIOException(
1766 u
"SfxStoringHelper::GUIStoreModel: ERRCODE_IO_INVALIDPARAMETER"_ustr
,
1767 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_INVALIDPARAMETER
));
1770 ::comphelper::SequenceAsHashMap::const_iterator aIter
=
1771 aModelData
.GetMediaDescr().find( u
"FilterFlags"_ustr
);
1772 bool bFilterFlagsSet
= ( aIter
!= aModelData
.GetMediaDescr().end() );
1774 // check if the filter Dialog has not been called before
1775 if( !( nStoreMode
& PDFEXPORT_REQUESTED
) && !( nStoreMode
& EPUBEXPORT_REQUESTED
) && !bFilterFlagsSet
1776 && ( ( nStoreMode
& EXPORT_REQUESTED
) || bUseFilterOptions
) )
1778 // execute filter options dialog
1779 if ( aModelData
.ExecuteFilterDialog_Impl( aFilterName
, false ) )
1782 // check if the file is a pdf or not and change the storing mode at convenience
1783 if (aFilterName
.endsWith("pdf_Export"))
1784 nStoreMode
= EXPORT_REQUESTED
| PDFEXPORT_REQUESTED
;
1788 // so the arguments will not change any more and can be stored to the main location
1789 aArgsSequence
= aModelData
.GetMediaDescr().getAsConstPropertyValueList();
1791 // store the document and handle it's docinfo
1793 DocumentSettingsGuard
aSettingsGuard( aModelData
.GetModel(), aModelData
.IsRecommendReadOnly(), nStoreMode
& EXPORT_REQUESTED
);
1795 // Treat attempted PDF export like a print: update document print statistics
1796 if ((nStoreMode
& PDFEXPORT_REQUESTED
) && SfxViewShell::Current())
1798 SfxObjectShell
* pDocShell
= SfxViewShell::Current()->GetObjectShell();
1799 const bool bWasEnableSetModified
= pDocShell
&& pDocShell
->IsEnableSetModified();
1800 bool bResetESM
= false;
1802 if (bWasEnableSetModified
1803 && !officecfg::Office::Common::Print::PrintingModifiesDocument::get())
1805 pDocShell
->EnableSetModified(false); // don't let export mark document as modified
1809 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
1810 aModelData
.GetModel(), uno::UNO_QUERY_THROW
);
1811 uno::Reference
<document::XDocumentProperties
> xDocProps(xDPS
->getDocumentProperties());
1812 xDocProps
->setPrintDate(DateTime(DateTime::SYSTEM
).GetUNODateTime());
1814 OUString
sPrintedBy(SfxResId(STR_SFX_FILTERNAME_PDF
));
1815 if (pDocShell
&& pDocShell
->IsUseUserData())
1817 const OUString sFullName
= SvtUserOptions().GetFullName();
1818 if (!sFullName
.isEmpty())
1819 sPrintedBy
+= ": " + sFullName
;
1821 xDocProps
->setPrintedBy(sPrintedBy
);
1824 pDocShell
->EnableSetModified(true);
1827 OSL_ENSURE( aModelData
.GetMediaDescr().find( u
"Password"_ustr
) == aModelData
.GetMediaDescr().end(), "The Password property of MediaDescriptor should not be used here!" );
1828 if ( officecfg::Office::Common::Save::Document::EditProperty::get()
1829 && ( !aModelData
.GetStorable()->hasLocation()
1830 || INetURLObject( aModelData
.GetStorable()->getLocation() ) != aURL
) )
1832 // this is definitely not a Save operation
1833 // so the document info can be updated
1835 // on export document info must be preserved
1836 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
1837 aModelData
.GetModel(), uno::UNO_QUERY_THROW
);
1838 uno::Reference
<util::XCloneable
> xCloneable(
1839 xDPS
->getDocumentProperties(), uno::UNO_QUERY_THROW
);
1840 uno::Reference
<document::XDocumentProperties
> xOldDocProps(
1841 xCloneable
->createClone(), uno::UNO_QUERY_THROW
);
1843 // use dispatch API to show document info dialog
1844 if ( aModelData
.ShowDocumentInfoDialog() )
1848 OSL_FAIL( "Can't execute document info dialog!" );
1852 // Document properties can contain streams that should be freed before storing
1853 aModelData
.FreeDocumentProps();
1854 if ( nStoreMode
& EXPORT_REQUESTED
)
1855 aModelData
.GetStorable()->storeToURL( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), aArgsSequence
);
1857 aModelData
.GetStorable()->storeAsURL( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), aArgsSequence
);
1859 catch( const uno::Exception
& )
1861 if ( nStoreMode
& EXPORT_REQUESTED
)
1863 SetDocInfoState(aModelData
.GetModel(), xOldDocProps
);
1868 if ( nStoreMode
& EXPORT_REQUESTED
)
1870 SetDocInfoState(aModelData
.GetModel(), xOldDocProps
);
1875 // Document properties can contain streams that should be freed before storing
1876 aModelData
.FreeDocumentProps();
1878 // this is actually a save operation with different parameters
1879 // so storeTo or storeAs without DocInfo operations are used
1884 if ( nStoreMode
& EXPORT_REQUESTED
)
1885 aModelData
.GetStorable()->storeToURL( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), aArgsSequence
);
1887 aModelData
.GetStorable()->storeAsURL( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), aArgsSequence
);
1890 catch( const uno::Exception
& )
1892 // When using the iOS app (and maybe the Android app), the app
1893 // will remain blocked if we rethrow an exception.
1898 if (aModelData
.IsSignWithDefaultSignature())
1900 auto SignWithDefaultSignature
= [&]()
1902 #if HAVE_FEATURE_GPGME
1903 auto aSigningKey
= SvtUserOptions().GetSigningKey();
1904 if (aSigningKey
.isEmpty())
1907 std::vector
<uno::Reference
<xml::crypto::XXMLSecurityContext
>> xSecurityContexts
{
1908 xml::crypto::GPGSEInitializer::create(comphelper::getProcessComponentContext())
1909 ->createSecurityContext({}),
1910 xml::crypto::SEInitializer::create(comphelper::getProcessComponentContext())
1911 ->createSecurityContext({}),
1914 for (const auto& xSecurityContext
: xSecurityContexts
)
1916 if (xSecurityContext
.is())
1918 css::uno::Reference
<css::security::XCertificate
> xCert
1919 = comphelper::xmlsec::FindCertInContext(xSecurityContext
, aSigningKey
);
1921 if (xCert
.is() && SfxViewShell::Current())
1923 SfxObjectShell
* pDocShell
= SfxViewShell::Current()->GetObjectShell();
1924 svl::crypto::SigningContext aSigningContext
;
1925 aSigningContext
.m_xCertificate
= std::move(xCert
);
1926 bool bSigned
= pDocShell
->SignDocumentContentUsingCertificate(aSigningContext
);
1927 if (bSigned
&& pDocShell
->HasValidSignatures())
1929 std::unique_ptr
<weld::MessageDialog
> xBox(
1930 Application::CreateMessageDialog(
1931 SfxStoringHelper::GetModelWindow(aModelData
.GetModel()),
1932 VclMessageType::Question
, VclButtonsType::YesNo
,
1933 SfxResId(STR_QUERY_REMEMBERSIGNATURE
)));
1934 pDocShell
->SetRememberCurrentSignature(xBox
->run() == RET_YES
);
1941 // couldn't find the specified default signing certificate!
1942 // alert the user the document won't be signed
1943 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(
1944 SfxStoringHelper::GetModelWindow(aModelData
.GetModel()),
1945 VclMessageType::Error
, VclButtonsType::Ok
,
1946 SfxResId(STR_ERROR_NOMATCHINGDEFUALTCERT
)));
1951 SignWithDefaultSignature();
1954 // Launch PDF viewer
1955 if ( nStoreMode
& PDFEXPORT_REQUESTED
&& !comphelper::LibreOfficeKit::isActive() )
1957 FilterConfigItem
aItem(u
"Office.Common/Filter/PDF/Export/");
1958 bool aViewPDF
= aItem
.ReadBool( u
"ViewPDFAfterExport"_ustr
, false );
1962 uno::Reference
<XSystemShellExecute
> xSystemShellExecute(SystemShellExecute::create( ::comphelper::getProcessComponentContext() ) );
1963 xSystemShellExecute
->execute( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), u
""_ustr
, SystemShellExecuteFlags::URIS_ONLY
);
1967 if ( comphelper::LibreOfficeKit::isActive() )
1969 if ( SfxViewShell
* pShell
= SfxViewShell::Current() )
1971 OUString sURL
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1972 pShell
->libreOfficeKitViewCallback( LOK_CALLBACK_EXPORT_FILE
, sURL
.toUtf8() );
1981 bool SfxStoringHelper::CheckFilterOptionsAppearance(
1982 const uno::Reference
< container::XNameAccess
>& xFilterCFG
,
1983 const OUString
& aFilterName
)
1985 bool bUseFilterOptions
= false;
1987 DBG_ASSERT( xFilterCFG
.is(), "No filter configuration!\n" );
1988 if( xFilterCFG
.is() )
1991 uno::Sequence
< beans::PropertyValue
> aProps
;
1992 uno::Any aAny
= xFilterCFG
->getByName( aFilterName
);
1993 if ( aAny
>>= aProps
)
1995 ::comphelper::SequenceAsHashMap
aPropsHM( aProps
);
1996 if( !aPropsHM
.getUnpackedValueOrDefault( u
"UIComponent"_ustr
, OUString() ).isEmpty() )
1997 bUseFilterOptions
= true;
2000 catch( const uno::Exception
& )
2005 return bUseFilterOptions
;
2010 void SfxStoringHelper::SetDocInfoState(
2011 const uno::Reference
< frame::XModel
>& xModel
,
2012 const uno::Reference
< document::XDocumentProperties
>& i_xOldDocProps
)
2014 uno::Reference
<document::XDocumentPropertiesSupplier
> const
2015 xModelDocPropsSupplier(xModel
, uno::UNO_QUERY_THROW
);
2016 uno::Reference
<document::XDocumentProperties
> const xDocPropsToFill
=
2017 xModelDocPropsSupplier
->getDocumentProperties();
2018 uno::Reference
< beans::XPropertySet
> const xPropSet(
2019 i_xOldDocProps
->getUserDefinedProperties(), uno::UNO_QUERY_THROW
);
2021 uno::Reference
< util::XModifiable
> xModifiable( xModel
, uno::UNO_QUERY
);
2022 if ( !xModifiable
.is() )
2023 throw uno::RuntimeException();
2025 bool bIsModified
= xModifiable
->isModified();
2029 uno::Reference
< beans::XPropertySet
> const xSet(
2030 xDocPropsToFill
->getUserDefinedProperties(), uno::UNO_QUERY
);
2031 uno::Reference
< beans::XPropertyContainer
> xContainer( xSet
, uno::UNO_QUERY
);
2032 uno::Reference
< beans::XPropertySetInfo
> xSetInfo
= xSet
->getPropertySetInfo();
2033 const uno::Sequence
< beans::Property
> lProps
= xSetInfo
->getProperties();
2034 for (const beans::Property
& rProp
: lProps
)
2036 uno::Any aValue
= xPropSet
->getPropertyValue( rProp
.Name
);
2037 if ( rProp
.Attributes
& css::beans::PropertyAttribute::REMOVABLE
)
2041 // QUESTION: DefaultValue?!
2042 xContainer
->addProperty( rProp
.Name
, rProp
.Attributes
, aValue
);
2044 catch (beans::PropertyExistException
const&) {}
2047 // it is possible that the propertysets from XML and binary files differ; we shouldn't break then
2048 xSet
->setPropertyValue( rProp
.Name
, aValue
);
2050 catch ( const uno::Exception
& ) {}
2054 // sigh... have to set these manually I'm afraid... wonder why
2055 // SfxObjectShell doesn't handle this internally, should be easier
2056 xDocPropsToFill
->setAuthor(i_xOldDocProps
->getAuthor());
2057 xDocPropsToFill
->setGenerator(i_xOldDocProps
->getGenerator());
2058 xDocPropsToFill
->setCreationDate(i_xOldDocProps
->getCreationDate());
2059 xDocPropsToFill
->setTitle(i_xOldDocProps
->getTitle());
2060 xDocPropsToFill
->setSubject(i_xOldDocProps
->getSubject());
2061 xDocPropsToFill
->setDescription(i_xOldDocProps
->getDescription());
2062 xDocPropsToFill
->setKeywords(i_xOldDocProps
->getKeywords());
2063 xDocPropsToFill
->setModifiedBy(i_xOldDocProps
->getModifiedBy());
2064 xDocPropsToFill
->setModificationDate(i_xOldDocProps
->getModificationDate());
2065 xDocPropsToFill
->setPrintedBy(i_xOldDocProps
->getPrintedBy());
2066 xDocPropsToFill
->setPrintDate(i_xOldDocProps
->getPrintDate());
2067 xDocPropsToFill
->setAutoloadURL(i_xOldDocProps
->getAutoloadURL());
2068 xDocPropsToFill
->setAutoloadSecs(i_xOldDocProps
->getAutoloadSecs());
2069 xDocPropsToFill
->setDefaultTarget(i_xOldDocProps
->getDefaultTarget());
2070 xDocPropsToFill
->setEditingCycles(i_xOldDocProps
->getEditingCycles());
2071 xDocPropsToFill
->setEditingDuration(i_xOldDocProps
->getEditingDuration());
2072 // other attributes e.g. DocumentStatistics are not editable from dialog
2074 catch (const uno::Exception
&)
2076 TOOLS_INFO_EXCEPTION("sfx.doc", "SetDocInfoState");
2079 // set the modified flag back if required
2080 if ( bIsModified
!= bool(xModifiable
->isModified()) )
2081 xModifiable
->setModified( bIsModified
);
2086 bool SfxStoringHelper::WarnUnacceptableFormat( const uno::Reference
< frame::XModel
>& xModel
,
2087 std::u16string_view aOldUIName
,
2088 const OUString
& aDefExtension
,
2091 if ( !officecfg::Office::Common::Save::Document::WarnAlienFormat::get() )
2094 weld::Window
* pWin
= SfxStoringHelper::GetModelWindow(xModel
);
2095 SfxAlienWarningDialog
aDlg(pWin
, aOldUIName
, aDefExtension
, bDefIsAlien
);
2097 return aDlg
.run() == RET_OK
;
2100 uno::Reference
<awt::XWindow
> SfxStoringHelper::GetModelXWindow(const uno::Reference
<frame::XModel
>& xModel
)
2105 uno::Reference
< frame::XController
> xController
= xModel
->getCurrentController();
2106 if ( xController
.is() )
2108 uno::Reference
< frame::XFrame
> xFrame
= xController
->getFrame();
2111 return xFrame
->getContainerWindow();
2116 catch ( const uno::Exception
& )
2120 return uno::Reference
<awt::XWindow
>();
2123 weld::Window
* SfxStoringHelper::GetModelWindow( const uno::Reference
< frame::XModel
>& xModel
)
2125 weld::Window
* pWin
= nullptr;
2129 pWin
= Application::GetFrameWeld(GetModelXWindow(xModel
));
2131 catch (const uno::Exception
&)
2138 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */