tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / sfx2 / source / doc / sfxbasemodel.cxx
blob18dc4e87a1cb93deec9d7773dfed34a74b1cbb1d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <sal/config.h>
22 #include <algorithm>
23 #include <chrono>
24 #include <memory>
25 #include <optional>
26 #include <config_features.h>
28 #include <sfx2/sfxbasemodel.hxx>
30 #include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp>
31 #include <com/sun/star/task/XInteractionHandler.hpp>
32 #include <com/sun/star/task/ErrorCodeIOException.hpp>
33 #include <com/sun/star/task/ErrorCodeRequest2.hpp>
34 #include <com/sun/star/view/XSelectionSupplier.hpp>
35 #include <com/sun/star/view/XPrintJobListener.hpp>
36 #include <com/sun/star/lang/DisposedException.hpp>
37 #include <com/sun/star/lang/IllegalArgumentException.hpp>
38 #include <com/sun/star/lang/NoSupportException.hpp>
39 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
40 #include <com/sun/star/lang/NotInitializedException.hpp>
41 #include <com/sun/star/frame/Desktop.hpp>
42 #include <com/sun/star/frame/IllegalArgumentIOException.hpp>
43 #include <com/sun/star/frame/XUntitledNumbers.hpp>
44 #include <com/sun/star/frame/DoubleInitializationException.hpp>
45 #include <com/sun/star/embed/XStorage.hpp>
46 #include <com/sun/star/document/XStorageChangeListener.hpp>
47 #include <com/sun/star/beans/XPropertySet.hpp>
48 #include <com/sun/star/beans/XPropertySetInfo.hpp>
49 #include <com/sun/star/container/XIndexContainer.hpp>
50 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
51 #include <com/sun/star/script/provider/XScriptProvider.hpp>
52 #include <com/sun/star/ui/UIConfigurationManager.hpp>
53 #include <com/sun/star/embed/ElementModes.hpp>
54 #include <com/sun/star/embed/Aspects.hpp>
55 #include <com/sun/star/document/DocumentProperties.hpp>
56 #include <com/sun/star/frame/XTransientDocumentsDocumentContentFactory.hpp>
57 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
58 #include <com/sun/star/ucb/ContentCreationException.hpp>
59 #include <com/sun/star/ucb/CommandAbortedException.hpp>
60 #include <com/sun/star/util/XCloneable.hpp>
61 #include <com/sun/star/util/InvalidStateException.hpp>
62 #include <com/sun/star/util/CloseVetoException.hpp>
63 #include <comphelper/enumhelper.hxx>
64 #include <comphelper/indexedpropertyvalues.hxx>
65 #include <comphelper/interfacecontainer3.hxx>
66 #include <comphelper/string.hxx>
68 #include <cppuhelper/implbase.hxx>
69 #include <comphelper/lok.hxx>
70 #include <comphelper/multicontainer2.hxx>
71 #include <cppuhelper/exc_hlp.hxx>
72 #include <comphelper/processfactory.hxx>
73 #include <comphelper/propertyvalue.hxx>
74 #include <comphelper/sequenceashashmap.hxx>
75 #include <comphelper/namedvaluecollection.hxx>
76 #include <o3tl/safeint.hxx>
77 #include <o3tl/string_view.hxx>
78 #include <svl/itemset.hxx>
79 #include <svl/stritem.hxx>
80 #include <svl/eitem.hxx>
81 #include <svl/grabbagitem.hxx>
82 #include <tools/urlobj.hxx>
83 #include <tools/debug.hxx>
84 #include <comphelper/diagnose_ex.hxx>
85 #include <tools/svborder.hxx>
86 #include <unotools/tempfile.hxx>
87 #include <osl/mutex.hxx>
88 #include <comphelper/errcode.hxx>
89 #include <vcl/filter/SvmWriter.hxx>
90 #include <vcl/salctype.hxx>
91 #include <vcl/gdimtf.hxx>
92 #include <comphelper/fileformat.h>
93 #include <comphelper/servicehelper.hxx>
94 #include <comphelper/storagehelper.hxx>
95 #include <toolkit/helper/vclunohelper.hxx>
96 #include <vcl/transfer.hxx>
97 #include <svtools/ehdl.hxx>
98 #include <svtools/sfxecode.hxx>
99 #include <sal/log.hxx>
100 #include <framework/configimporter.hxx>
101 #include <framework/titlehelper.hxx>
102 #include <comphelper/numberedcollection.hxx>
103 #include <unotools/ucbhelper.hxx>
104 #include <ucbhelper/content.hxx>
106 #include <sfx2/sfxbasecontroller.hxx>
107 #include <sfx2/viewfac.hxx>
108 #include <workwin.hxx>
109 #include <sfx2/signaturestate.hxx>
110 #include <sfx2/sfxuno.hxx>
111 #include <objshimp.hxx>
112 #include <sfx2/viewfrm.hxx>
113 #include <sfx2/viewsh.hxx>
114 #include <sfx2/docfile.hxx>
115 #include <sfx2/docfilt.hxx>
116 #include <sfx2/dispatch.hxx>
117 #include <sfx2/module.hxx>
118 #include <basic/basmgr.hxx>
119 #include <sfx2/event.hxx>
120 #include <eventsupplier.hxx>
121 #include <sfx2/sfxsids.hrc>
122 #include <sfx2/strings.hrc>
123 #include <sfx2/app.hxx>
124 #include <sfx2/docfac.hxx>
125 #include <sfx2/fcontnr.hxx>
126 #include <sfx2/docstoragemodifylistener.hxx>
127 #include <sfx2/brokenpackageint.hxx>
128 #include "graphhelp.hxx"
129 #include <docundomanager.hxx>
130 #include <openurlhint.hxx>
131 #include <sfx2/msgpool.hxx>
132 #include <sfx2/DocumentMetadataAccess.hxx>
133 #include "printhelper.hxx"
134 #include <sfx2/sfxresid.hxx>
135 #include <sfx2/filedlghelper.hxx>
136 #include <comphelper/profilezone.hxx>
137 #include <vcl/threadex.hxx>
138 #include <unotools/mediadescriptor.hxx>
140 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
142 // namespaces
145 using namespace ::com::sun::star;
146 using namespace ::com::sun::star::uno;
147 using ::com::sun::star::beans::PropertyValue;
148 using ::com::sun::star::document::CmisProperty;
149 using ::com::sun::star::frame::XFrame;
150 using ::com::sun::star::frame::XController;
151 using ::com::sun::star::frame::XController2;
152 using ::com::sun::star::lang::IllegalArgumentException;
153 using ::com::sun::star::io::IOException;
154 using ::com::sun::star::uno::Sequence;
155 using ::com::sun::star::document::XDocumentRecovery;
156 using ::com::sun::star::document::XUndoManager;
157 using ::com::sun::star::document::XUndoAction;
158 using ::com::sun::star::frame::XModel;
160 namespace {
162 /** This Listener is used to get notified when the XDocumentProperties of the
163 XModel change.
165 class SfxDocInfoListener_Impl : public ::cppu::WeakImplHelper<
166 util::XModifyListener >
169 public:
170 SfxObjectShell& m_rShell;
172 explicit SfxDocInfoListener_Impl( SfxObjectShell& i_rDoc )
173 : m_rShell(i_rDoc)
174 { };
176 virtual void SAL_CALL disposing( const lang::EventObject& ) override;
177 virtual void SAL_CALL modified( const lang::EventObject& ) override;
182 void SAL_CALL SfxDocInfoListener_Impl::modified( const lang::EventObject& )
184 SolarMutexGuard aSolarGuard;
186 // notify changes to the SfxObjectShell
187 m_rShell.FlushDocInfo();
190 void SAL_CALL SfxDocInfoListener_Impl::disposing( const lang::EventObject& )
195 // impl. declarations
198 struct IMPL_SfxBaseModel_DataContainer : public ::sfx2::IModifiableDocument
200 // counter for SfxBaseModel instances created.
201 inline static std::atomic<sal_Int64> g_nInstanceCounter = 0 ;
202 SfxObjectShellRef m_pObjectShell ;
203 OUString m_sURL ;
204 OUString m_sRuntimeUID ;
205 OUString m_aPreusedFilterName ;
206 comphelper::OInterfaceContainerHelper3<view::XPrintJobListener> m_aPrintJobListeners;
207 comphelper::OInterfaceContainerHelper3<lang::XEventListener> m_aEventListeners;
208 comphelper::OInterfaceContainerHelper3<util::XModifyListener> m_aModifyListeners;
209 comphelper::OInterfaceContainerHelper3<document::XEventListener> m_aDocumentEventListeners1;
210 comphelper::OInterfaceContainerHelper3<document::XDocumentEventListener> m_aDocumentEventListeners2;
211 comphelper::OInterfaceContainerHelper3<document::XStorageChangeListener> m_aStorageChangeListeners;
212 comphelper::OInterfaceContainerHelper3<util::XCloseListener> m_aCloseListeners;
213 std::unordered_map<css::uno::Reference< css::drawing::XShape >,
214 std::vector<css::uno::Reference< css::document::XShapeEventListener >>> maShapeListeners;
215 Reference< XInterface > m_xParent ;
216 Reference< frame::XController > m_xCurrent ;
217 Reference< document::XDocumentProperties > m_xDocumentProperties ;
218 Reference< script::XStarBasicAccess > m_xStarBasicAccess ;
219 rtl::Reference< SfxEvents_Impl > m_xEvents ;
220 Sequence< beans::PropertyValue> m_seqArguments ;
221 std::vector< Reference< frame::XController > > m_seqControllers ;
222 Reference< container::XIndexAccess > m_contViewData ;
223 sal_uInt16 m_nControllerLockCount ;
224 bool m_bClosed ;
225 bool m_bClosing ;
226 bool m_bSaving ;
227 bool m_bSuicide ;
228 bool m_bExternalTitle ;
229 bool m_bDisposing ;
230 rtl::Reference< SfxPrintHelper> m_xPrintable ;
231 Reference< ui::XUIConfigurationManager2 > m_xUIConfigurationManager;
232 ::rtl::Reference< ::sfx2::DocumentStorageModifyListener > m_pStorageModifyListen ;
233 OUString m_sModuleIdentifier ;
234 rtl::Reference< ::framework::TitleHelper > m_xTitleHelper ;
235 rtl::Reference< ::comphelper::NumberedCollection > m_xNumberedControllers ;
236 rtl::Reference<::sfx2::DocumentMetadataAccess> m_xDocumentMetadata ;
237 ::rtl::Reference< ::sfx2::DocumentUndoManager > m_pDocumentUndoManager ;
238 Sequence< document::CmisProperty> m_cmisProperties ;
239 std::shared_ptr<SfxGrabBagItem> m_xGrabBagItem ;
240 std::optional<std::chrono::steady_clock::time_point> m_oDirtyTimestamp ;
242 IMPL_SfxBaseModel_DataContainer( ::osl::Mutex& rMutex, SfxObjectShell* pObjectShell )
243 : m_pObjectShell ( pObjectShell )
244 , m_aPrintJobListeners ( rMutex )
245 , m_aEventListeners ( rMutex )
246 , m_aModifyListeners ( rMutex )
247 , m_aDocumentEventListeners1( rMutex )
248 , m_aDocumentEventListeners2( rMutex )
249 , m_aStorageChangeListeners ( rMutex )
250 , m_aCloseListeners ( rMutex )
251 , m_nControllerLockCount ( 0 )
252 , m_bClosed ( false )
253 , m_bClosing ( false )
254 , m_bSaving ( false )
255 , m_bSuicide ( false )
256 , m_bExternalTitle ( false )
257 , m_bDisposing ( false )
259 // increase global instance counter, and set own Runtime UID
260 m_sRuntimeUID = OUString::number(++g_nInstanceCounter);
263 virtual ~IMPL_SfxBaseModel_DataContainer()
267 // ::sfx2::IModifiableDocument
268 virtual void storageIsModified() override
270 if ( m_pObjectShell.is() && !m_pObjectShell->IsModified() )
271 m_pObjectShell->SetModified();
274 void impl_setDocumentProperties(
275 const Reference< document::XDocumentProperties >& );
277 Reference<rdf::XDocumentMetadataAccess> GetDMA()
279 if (!m_xDocumentMetadata.is())
281 OSL_ENSURE(m_pObjectShell.is(), "GetDMA: no object shell?");
282 if (!m_pObjectShell.is())
284 return nullptr;
287 const Reference<XComponentContext>& xContext(
288 ::comphelper::getProcessComponentContext());
289 const Reference<frame::XModel> xModel(
290 m_pObjectShell->GetModel());
291 const Reference<lang::XMultiComponentFactory> xMsf(
292 xContext->getServiceManager());
293 const Reference<frame::
294 XTransientDocumentsDocumentContentFactory> xTDDCF(
295 xMsf->createInstanceWithContext(
296 u"com.sun.star.frame.TransientDocumentsDocumentContentFactory"_ustr,
297 xContext),
298 UNO_QUERY_THROW);
299 const Reference<ucb::XContent> xContent(
300 xTDDCF->createDocumentContent(xModel) );
301 OSL_ENSURE(xContent.is(), "GetDMA: cannot create DocumentContent");
302 if (!xContent.is())
304 return nullptr;
306 OUString uri = xContent->getIdentifier()->getContentIdentifier();
307 OSL_ENSURE(!uri.isEmpty(), "GetDMA: empty uri?");
308 if (!uri.isEmpty() && !uri.endsWith("/"))
310 uri += "/";
313 m_xDocumentMetadata = new ::sfx2::DocumentMetadataAccess(
314 xContext, *m_pObjectShell, uri);
316 return m_xDocumentMetadata;
319 rtl::Reference<::sfx2::DocumentMetadataAccess> CreateDMAUninitialized()
321 return (m_pObjectShell.is())
322 ? new ::sfx2::DocumentMetadataAccess(
323 ::comphelper::getProcessComponentContext(), *m_pObjectShell)
324 : nullptr;
327 void setModifiedForAutoSave(bool val)
329 if (val)
331 if (!m_oDirtyTimestamp)
332 m_oDirtyTimestamp.emplace(std::chrono::steady_clock::now());
334 else
336 m_oDirtyTimestamp.reset();
341 namespace {
343 // Listener that forwards notifications from the PrintHelper to the "real" listeners
344 class SfxPrintHelperListener_Impl : public ::cppu::WeakImplHelper< view::XPrintJobListener >
346 public:
347 IMPL_SfxBaseModel_DataContainer* m_pData;
348 explicit SfxPrintHelperListener_Impl( IMPL_SfxBaseModel_DataContainer* pData )
349 : m_pData( pData )
352 virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) override ;
353 virtual void SAL_CALL printJobEvent( const view::PrintJobEvent& rEvent ) override;
358 void SAL_CALL SfxPrintHelperListener_Impl::disposing( const lang::EventObject& )
360 m_pData->m_xPrintable = nullptr;
363 void SAL_CALL SfxPrintHelperListener_Impl::printJobEvent( const view::PrintJobEvent& rEvent )
365 if ( m_pData->m_aPrintJobListeners.getLength() )
367 m_pData->m_aPrintJobListeners.notifyEach(&view::XPrintJobListener::printJobEvent, rEvent);
371 namespace {
373 // SfxOwnFramesLocker ====================================================================================
374 // allows to lock all the frames related to the provided SfxObjectShell
375 class SfxOwnFramesLocker
377 Sequence< Reference< frame::XFrame > > m_aLockedFrames;
379 static vcl::Window* GetVCLWindow( const Reference< frame::XFrame >& xFrame );
380 public:
381 explicit SfxOwnFramesLocker( SfxObjectShell const * ObjechShell );
382 ~SfxOwnFramesLocker();
387 SfxOwnFramesLocker::SfxOwnFramesLocker( SfxObjectShell const * pObjectShell )
389 if ( !pObjectShell )
390 return;
392 if ( comphelper::LibreOfficeKit::isForkedChild() )
393 return; // no need to tweak UI when in the background
395 for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pObjectShell );
396 pFrame;
397 pFrame = SfxViewFrame::GetNext( *pFrame, pObjectShell )
400 SfxFrame& rSfxFrame = pFrame->GetFrame();
403 // get vcl window related to the frame and lock it if it is still not locked
404 const Reference< frame::XFrame >& xFrame = rSfxFrame.GetFrameInterface();
405 vcl::Window* pWindow = GetVCLWindow( xFrame );
406 if ( !pWindow )
407 throw RuntimeException();
409 if ( pWindow->IsEnabled() )
411 pWindow->Disable();
415 sal_Int32 nLen = m_aLockedFrames.getLength();
416 m_aLockedFrames.realloc( nLen + 1 );
417 m_aLockedFrames.getArray()[nLen] = xFrame;
419 catch( Exception& )
421 pWindow->Enable();
422 throw;
426 catch( Exception& )
428 OSL_FAIL( "Not possible to lock the frame window!" );
433 SfxOwnFramesLocker::~SfxOwnFramesLocker()
435 for ( auto& rFrame : asNonConstRange(m_aLockedFrames) )
439 if ( rFrame.is() )
441 // get vcl window related to the frame and unlock it
442 vcl::Window* pWindow = GetVCLWindow( rFrame );
443 if ( !pWindow )
444 throw RuntimeException();
446 pWindow->Enable();
448 rFrame.clear();
451 catch( Exception& )
453 OSL_FAIL( "Can't unlock the frame window!" );
458 vcl::Window* SfxOwnFramesLocker::GetVCLWindow( const Reference< frame::XFrame >& xFrame )
460 VclPtr<vcl::Window> pWindow;
462 if ( xFrame.is() )
464 Reference< awt::XWindow > xWindow = xFrame->getContainerWindow();
465 if ( xWindow.is() )
466 pWindow = VCLUnoHelper::GetWindow( xWindow );
469 return pWindow;
472 namespace {
474 // SfxSaveGuard ====================================================================================
475 class SfxSaveGuard
477 private:
478 Reference< frame::XModel > m_xModel;
479 IMPL_SfxBaseModel_DataContainer* m_pData;
480 std::unique_ptr<SfxOwnFramesLocker> m_pFramesLock;
482 SfxSaveGuard(SfxSaveGuard const &) = delete;
483 void operator =(const SfxSaveGuard&) = delete;
485 public:
486 SfxSaveGuard(const Reference< frame::XModel >& xModel ,
487 IMPL_SfxBaseModel_DataContainer* pData);
488 ~SfxSaveGuard();
493 SfxSaveGuard::SfxSaveGuard(const Reference< frame::XModel >& xModel ,
494 IMPL_SfxBaseModel_DataContainer* pData)
495 : m_xModel ( xModel )
496 , m_pData ( pData )
498 if ( m_pData->m_bClosed )
499 throw lang::DisposedException(u"Object already disposed."_ustr);
501 m_pData->m_bSaving = true;
502 m_pFramesLock.reset(new SfxOwnFramesLocker( m_pData->m_pObjectShell.get() ));
505 SfxSaveGuard::~SfxSaveGuard()
507 m_pFramesLock.reset();
509 m_pData->m_bSaving = false;
511 // m_bSuicide was set e.g. in case someone tried to close a document, while it was used for
512 // storing at the same time. Further m_bSuicide was set to sal_True only if close(sal_True) was called.
513 // So the ownership was delegated to the place where a veto exception was thrown.
514 // Now we have to call close() again and delegate the ownership to the next one, which
515 // can't accept that. Close(sal_False) can't work in this case. Because then the document will may be never closed...
517 if ( !m_pData->m_bSuicide )
518 return;
520 // Reset this state. In case the new close() request is not accepted by someone else...
521 // it's not a good idea to have two "owners" for close.-)
522 m_pData->m_bSuicide = false;
525 Reference< util::XCloseable > xClose(m_xModel, UNO_QUERY);
526 if (xClose.is())
527 xClose->close(true);
529 catch(const util::CloseVetoException&)
533 SfxBaseModel::SfxBaseModel( SfxObjectShell *pObjectShell )
534 : BaseMutex()
535 , m_pData( std::make_shared<IMPL_SfxBaseModel_DataContainer>( m_aMutex, pObjectShell ) )
536 , m_bSupportEmbeddedScripts( pObjectShell && pObjectShell->Get_Impl() && !pObjectShell->Get_Impl()->m_bNoBasicCapabilities )
537 , m_bSupportDocRecovery( pObjectShell && pObjectShell->Get_Impl() && pObjectShell->Get_Impl()->m_bDocRecoverySupport )
539 if ( pObjectShell != nullptr )
541 StartListening( *pObjectShell ) ;
545 // destructor
546 SfxBaseModel::~SfxBaseModel()
550 // XInterface
551 Any SAL_CALL SfxBaseModel::queryInterface( const uno::Type& rType )
553 if ( ( !m_bSupportEmbeddedScripts && rType.equals( cppu::UnoType<document::XEmbeddedScripts>::get() ) )
554 || ( !m_bSupportDocRecovery && (rType.equals( cppu::UnoType<XDocumentRecovery>::get() ) || rType.equals( cppu::UnoType<XDocumentRecovery2>::get() )) )
556 return Any();
558 return SfxBaseModel_Base::queryInterface( rType );
562 // XTypeProvider
565 namespace
567 void lcl_stripType( Sequence< uno::Type >& io_rTypes, const uno::Type& i_rTypeToStrip )
569 Sequence< uno::Type > aStrippedTypes( io_rTypes.getLength() - 1 );
570 ::std::remove_copy_if(
571 std::cbegin(io_rTypes),
572 std::cend(io_rTypes),
573 aStrippedTypes.getArray(),
574 [&i_rTypeToStrip](const uno::Type& aType) { return aType == i_rTypeToStrip; }
576 io_rTypes = std::move(aStrippedTypes);
580 Sequence< uno::Type > SAL_CALL SfxBaseModel::getTypes()
582 Sequence< uno::Type > aTypes( SfxBaseModel_Base::getTypes() );
584 if ( !m_bSupportEmbeddedScripts )
585 lcl_stripType( aTypes, cppu::UnoType<document::XEmbeddedScripts>::get() );
587 if ( !m_bSupportDocRecovery )
588 lcl_stripType( aTypes, cppu::UnoType<XDocumentRecovery2>::get() );
590 return aTypes;
594 // XTypeProvider
597 Sequence< sal_Int8 > SAL_CALL SfxBaseModel::getImplementationId()
599 return css::uno::Sequence<sal_Int8>();
603 // XStarBasicAccess
605 #if HAVE_FEATURE_SCRIPTING
607 static Reference< script::XStarBasicAccess > implGetStarBasicAccess( SfxObjectShell const * pObjectShell )
609 Reference< script::XStarBasicAccess > xRet;
611 #if !HAVE_FEATURE_SCRIPTING
612 (void) pObjectShell;
613 #else
614 if( pObjectShell )
616 BasicManager* pMgr = pObjectShell->GetBasicManager();
617 xRet = getStarBasicAccess( pMgr );
619 #endif
620 return xRet;
623 #endif
625 Reference< container::XNameContainer > SAL_CALL SfxBaseModel::getLibraryContainer()
627 #if !HAVE_FEATURE_SCRIPTING
628 Reference< container::XNameContainer > dummy;
630 return dummy;
631 #else
632 SfxModelGuard aGuard( *this );
634 Reference< script::XStarBasicAccess >& rxAccess = m_pData->m_xStarBasicAccess;
635 if( !rxAccess.is() && m_pData->m_pObjectShell.is() )
636 rxAccess = implGetStarBasicAccess( m_pData->m_pObjectShell.get() );
638 Reference< container::XNameContainer > xRet;
639 if( rxAccess.is() )
640 xRet = rxAccess->getLibraryContainer();
641 return xRet;
642 #endif
645 /**___________________________________________________________________________________________________
646 @seealso XStarBasicAccess
648 void SAL_CALL SfxBaseModel::createLibrary( const OUString& LibName, const OUString& Password,
649 const OUString& ExternalSourceURL, const OUString& LinkTargetURL )
651 #if !HAVE_FEATURE_SCRIPTING
652 (void) LibName;
653 (void) Password;
654 (void) ExternalSourceURL;
655 (void) LinkTargetURL;
656 #else
657 SfxModelGuard aGuard( *this );
659 Reference< script::XStarBasicAccess >& rxAccess = m_pData->m_xStarBasicAccess;
660 if( !rxAccess.is() && m_pData->m_pObjectShell.is() )
661 rxAccess = implGetStarBasicAccess( m_pData->m_pObjectShell.get() );
663 if( rxAccess.is() )
664 rxAccess->createLibrary( LibName, Password, ExternalSourceURL, LinkTargetURL );
665 #endif
668 /**___________________________________________________________________________________________________
669 @seealso XStarBasicAccess
671 void SAL_CALL SfxBaseModel::addModule( const OUString& LibraryName, const OUString& ModuleName,
672 const OUString& Language, const OUString& Source )
674 #if !HAVE_FEATURE_SCRIPTING
675 (void) LibraryName;
676 (void) ModuleName;
677 (void) Language;
678 (void) Source;
679 #else
680 SfxModelGuard aGuard( *this );
682 Reference< script::XStarBasicAccess >& rxAccess = m_pData->m_xStarBasicAccess;
683 if( !rxAccess.is() && m_pData->m_pObjectShell.is() )
684 rxAccess = implGetStarBasicAccess( m_pData->m_pObjectShell.get() );
686 if( rxAccess.is() )
687 rxAccess->addModule( LibraryName, ModuleName, Language, Source );
688 #endif
691 /**___________________________________________________________________________________________________
692 @seealso XStarBasicAccess
694 void SAL_CALL SfxBaseModel::addDialog( const OUString& LibraryName, const OUString& DialogName,
695 const Sequence< sal_Int8 >& Data )
697 #if !HAVE_FEATURE_SCRIPTING
698 (void) LibraryName;
699 (void) DialogName;
700 (void) Data;
701 #else
702 SfxModelGuard aGuard( *this );
704 Reference< script::XStarBasicAccess >& rxAccess = m_pData->m_xStarBasicAccess;
705 if( !rxAccess.is() && m_pData->m_pObjectShell.is() )
706 rxAccess = implGetStarBasicAccess( m_pData->m_pObjectShell.get() );
708 if( rxAccess.is() )
709 rxAccess->addDialog( LibraryName, DialogName, Data );
710 #endif
714 // XChild
717 Reference< XInterface > SAL_CALL SfxBaseModel::getParent()
719 SfxModelGuard aGuard( *this );
721 return m_pData->m_xParent;
725 // XChild
728 void SAL_CALL SfxBaseModel::setParent(const Reference< XInterface >& Parent)
730 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
731 m_pData->m_xParent = Parent;
735 // XChild
738 void SAL_CALL SfxBaseModel::dispose()
740 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
742 if ( !m_pData->m_bClosed )
744 // gracefully accept wrong dispose calls instead of close call
745 // and try to make it work (may be really disposed later!)
748 close( true );
750 catch ( util::CloseVetoException& )
754 return;
757 if ( m_pData->m_bDisposing )
758 return;
759 m_pData->m_bDisposing = true;
761 if ( m_pData->m_pStorageModifyListen.is() )
763 m_pData->m_pStorageModifyListen->dispose();
764 m_pData->m_pStorageModifyListen = nullptr;
767 if ( m_pData->m_pDocumentUndoManager.is() )
769 m_pData->m_pDocumentUndoManager->disposing();
770 m_pData->m_pDocumentUndoManager = nullptr;
773 lang::EventObject aEvent( static_cast<frame::XModel *>(this) );
774 m_pData->m_aPrintJobListeners.disposeAndClear( aEvent );
775 m_pData->m_aEventListeners.disposeAndClear( aEvent );
776 m_pData->m_aModifyListeners.disposeAndClear( aEvent );
777 m_pData->m_aDocumentEventListeners1.disposeAndClear( aEvent );
778 m_pData->m_aDocumentEventListeners2.disposeAndClear( aEvent );
779 m_pData->m_aStorageChangeListeners.disposeAndClear( aEvent );
780 m_pData->m_aCloseListeners.disposeAndClear( aEvent );
782 m_pData->m_xDocumentProperties.clear();
784 m_pData->m_xDocumentMetadata.clear();
786 if ( m_pData->m_pObjectShell.is() )
788 EndListening( *m_pData->m_pObjectShell );
791 m_pData->m_xCurrent.clear();
792 m_pData->m_seqControllers.clear();
794 // m_pData member must be set to zero before delete is called to
795 // force disposed exception whenever someone tries to access our
796 // instance while in the dtor.
797 m_pData.reset();
801 // XChild
804 void SAL_CALL SfxBaseModel::addEventListener( const Reference< lang::XEventListener >& aListener )
806 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
807 m_pData->m_aEventListeners.addInterface( aListener );
811 // XChild
814 void SAL_CALL SfxBaseModel::removeEventListener( const Reference< lang::XEventListener >& aListener )
816 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
817 m_pData->m_aEventListeners.removeInterface( aListener );
820 void
821 IMPL_SfxBaseModel_DataContainer::impl_setDocumentProperties(
822 const Reference< document::XDocumentProperties >& rxNewDocProps)
824 m_xDocumentProperties.set(rxNewDocProps, UNO_SET_THROW);
825 if (m_pObjectShell.is())
827 Reference<util::XModifyBroadcaster> const xMB(
828 m_xDocumentProperties, UNO_QUERY_THROW);
829 xMB->addModifyListener(new SfxDocInfoListener_Impl(*m_pObjectShell));
833 // document::XDocumentPropertiesSupplier:
834 Reference< document::XDocumentProperties > SAL_CALL
835 SfxBaseModel::getDocumentProperties()
837 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
838 if ( !m_pData->m_xDocumentProperties.is() )
840 Reference< document::XDocumentProperties > xDocProps(
841 document::DocumentProperties::create( ::comphelper::getProcessComponentContext() ) );
842 m_pData->impl_setDocumentProperties(xDocProps);
845 return m_pData->m_xDocumentProperties;
849 // lang::XEventListener
852 void SAL_CALL SfxBaseModel::disposing( const lang::EventObject& aObject )
854 SolarMutexGuard aGuard;
855 if ( impl_isDisposed() )
856 return;
858 Reference< util::XModifyListener > xMod( aObject.Source, UNO_QUERY );
859 Reference< lang::XEventListener > xListener( aObject.Source, UNO_QUERY );
860 Reference< document::XEventListener > xDocListener( aObject.Source, UNO_QUERY );
862 if ( xMod.is() )
863 m_pData->m_aModifyListeners.removeInterface( xMod );
864 else if ( xListener.is() )
865 m_pData->m_aEventListeners.removeInterface( xListener );
866 else if ( xDocListener.is() )
867 m_pData->m_aDocumentEventListeners1.removeInterface( xDocListener );
871 // frame::XModel
874 sal_Bool SAL_CALL SfxBaseModel::attachResource( const OUString& rURL ,
875 const Sequence< beans::PropertyValue >& rArgs )
877 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
878 if ( rURL.isEmpty() && rArgs.getLength() == 1 && rArgs[0].Name == "SetEmbedded" )
880 // allows to set a windowless document to EMBEDDED state
881 // but _only_ before load() or initNew() methods
882 if ( m_pData->m_pObjectShell.is() && !m_pData->m_pObjectShell->GetMedium() )
884 bool bEmb(false);
885 if ( ( rArgs[0].Value >>= bEmb ) && bEmb )
886 m_pData->m_pObjectShell->SetCreateMode_Impl( SfxObjectCreateMode::EMBEDDED );
889 return true;
892 if ( m_pData->m_pObjectShell.is() )
894 m_pData->m_sURL = rURL;
896 SfxObjectShell* pObjectShell = m_pData->m_pObjectShell.get();
898 Sequence< sal_Int32 > aWinExtent;
899 for (const beans::PropertyValue & rProp : rArgs)
901 if (rProp.Name == "WinExtent" && (rProp.Value >>= aWinExtent) && ( aWinExtent.getLength() == 4 ) )
903 tools::Rectangle aVisArea( aWinExtent[0], aWinExtent[1], aWinExtent[2], aWinExtent[3] );
904 aVisArea = OutputDevice::LogicToLogic(aVisArea, MapMode(MapUnit::Map100thMM), MapMode(pObjectShell->GetMapUnit()));
905 pObjectShell->SetVisArea( aVisArea );
907 bool bBreakMacroSign = false;
908 if ( rProp.Name == "BreakMacroSignature" && (rProp.Value >>= bBreakMacroSign) )
910 pObjectShell->BreakMacroSign_Impl( bBreakMacroSign );
912 bool bMacroEventRead = false;
913 if ( rProp.Name == "MacroEventRead" && (rProp.Value >>= bMacroEventRead) && bMacroEventRead)
915 pObjectShell->SetMacroCallsSeenWhileLoading();
918 Sequence<beans::PropertyValue> aStrippedArgs(rArgs.getLength());
919 beans::PropertyValue* pStripped = aStrippedArgs.getArray();
920 for (const beans::PropertyValue & rProp : rArgs)
922 if (rProp.Name == "WinExtent"
923 || rProp.Name == "BreakMacroSignature"
924 || rProp.Name == "MacroEventRead"
925 || rProp.Name == "Stream"
926 || rProp.Name == "InputStream"
927 || rProp.Name == "URL"
928 || rProp.Name == "Frame"
929 || rProp.Name == "Password"
930 || rProp.Name == "EncryptionData")
931 continue;
932 *pStripped++ = rProp;
934 aStrippedArgs.realloc(pStripped - aStrippedArgs.getArray());
936 // TODO/LATER: all the parameters that are accepted by ItemSet of the DocShell must be removed here
938 m_pData->m_seqArguments = std::move(aStrippedArgs);
940 SfxMedium* pMedium = pObjectShell->GetMedium();
941 if ( pMedium )
943 SfxAllItemSet aSet( pObjectShell->GetPool() );
944 TransformParameters( SID_OPENDOC, rArgs, aSet );
946 // the arguments are not allowed to reach the medium
947 aSet.ClearItem( SID_FILE_NAME );
948 aSet.ClearItem( SID_FILLFRAME );
950 pMedium->GetItemSet().Put( aSet );
951 const SfxStringItem* pItem = aSet.GetItem<SfxStringItem>(SID_FILTER_NAME, false);
952 if ( pItem )
953 pMedium->SetFilter(
954 pObjectShell->GetFactory().GetFilterContainer()->GetFilter4FilterName( pItem->GetValue() ) );
956 const SfxStringItem* pTitleItem = aSet.GetItem<SfxStringItem>(SID_DOCINFO_TITLE, false);
957 if ( pTitleItem )
959 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pObjectShell );
960 if ( pFrame )
961 pFrame->UpdateTitle();
966 return true ;
970 // frame::XModel
973 OUString SAL_CALL SfxBaseModel::getURL()
975 SfxModelGuard aGuard( *this );
976 return m_pData->m_sURL ;
980 // frame::XModel
982 Sequence< beans::PropertyValue > SAL_CALL SfxBaseModel::getArgs()
984 return getArgs2({});
987 // frame::XModel3
989 Sequence< beans::PropertyValue > SAL_CALL SfxBaseModel::getArgs2(const Sequence<OUString> & requestedArgsSeq )
991 SfxModelGuard aGuard( *this );
993 if (!SfxApplication::Get()) // tdf#113755
995 SAL_WARN("sfx.appl", "Unexpected operations on model");
996 return m_pData->m_seqArguments;
999 std::set<std::u16string_view> requestedArgs;
1000 for (OUString const & s : requestedArgsSeq)
1001 requestedArgs.insert(s);
1003 if ( m_pData->m_pObjectShell.is() )
1005 Sequence< beans::PropertyValue > seqArgsNew;
1006 Sequence< beans::PropertyValue > seqArgsOld;
1007 SfxAllItemSet aSet( m_pData->m_pObjectShell->GetPool() );
1009 // we need to know which properties are supported by the transformer
1010 // hopefully it is a temporary solution, I guess nonconvertable properties
1011 // should not be supported so then there will be only ItemSet from medium
1013 TransformItems( SID_OPENDOC, m_pData->m_pObjectShell->GetMedium()->GetItemSet(), seqArgsNew );
1014 TransformParameters( SID_OPENDOC, m_pData->m_seqArguments, aSet );
1015 TransformItems( SID_OPENDOC, aSet, seqArgsOld );
1017 sal_Int32 nNewLength = seqArgsNew.getLength();
1019 if (requestedArgs.empty() || requestedArgs.count(u"WinExtent"))
1021 // "WinExtent" property should be updated always.
1022 // We can store it now to overwrite an old value
1023 // since it is not from ItemSet
1024 tools::Rectangle aTmpRect = m_pData->m_pObjectShell->GetVisArea( ASPECT_CONTENT );
1025 aTmpRect = OutputDevice::LogicToLogic(aTmpRect, MapMode(m_pData->m_pObjectShell->GetMapUnit()), MapMode(MapUnit::Map100thMM));
1027 Sequence< sal_Int32 > aRectSeq
1029 o3tl::narrowing<int>(aTmpRect.Left()),
1030 o3tl::narrowing<int>(aTmpRect.Top()),
1031 o3tl::narrowing<int>(aTmpRect.IsWidthEmpty() ? aTmpRect.Left() : aTmpRect.Right()),
1032 o3tl::narrowing<int>(aTmpRect.IsHeightEmpty() ? aTmpRect.Top() : aTmpRect.Bottom())
1035 seqArgsNew.realloc( ++nNewLength );
1036 auto pseqArgsNew = seqArgsNew.getArray();
1037 pseqArgsNew[ nNewLength - 1 ].Name = "WinExtent";
1038 pseqArgsNew[ nNewLength - 1 ].Value <<= aRectSeq;
1041 if (requestedArgs.empty() || requestedArgs.count(u"PreusedFilterName"))
1043 if ( !m_pData->m_aPreusedFilterName.isEmpty() )
1045 seqArgsNew.realloc( ++nNewLength );
1046 auto pseqArgsNew = seqArgsNew.getArray();
1047 pseqArgsNew[ nNewLength - 1 ].Name = "PreusedFilterName";
1048 pseqArgsNew[ nNewLength - 1 ].Value <<= m_pData->m_aPreusedFilterName;
1052 if (requestedArgs.empty() || requestedArgs.count(u"DocumentBorder"))
1054 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get() );
1055 if ( pFrame )
1057 SvBorder aBorder = pFrame->GetBorderPixelImpl();
1059 Sequence< sal_Int32 > aBorderSeq
1061 o3tl::narrowing<int>(aBorder.Left()),
1062 o3tl::narrowing<int>(aBorder.Top()),
1063 o3tl::narrowing<int>(aBorder.Right()),
1064 o3tl::narrowing<int>(aBorder.Bottom())
1067 seqArgsNew.realloc( ++nNewLength );
1068 auto pseqArgsNew = seqArgsNew.getArray();
1069 pseqArgsNew[ nNewLength - 1 ].Name = "DocumentBorder";
1070 pseqArgsNew[ nNewLength - 1 ].Value <<= aBorderSeq;
1074 if (requestedArgs.empty())
1076 // only the values that are not supported by the ItemSet must be cached here
1077 Sequence< beans::PropertyValue > aFinalCache;
1078 sal_Int32 nFinalLength = 0;
1080 for (const auto& rOrg : m_pData->m_seqArguments)
1082 auto bNew = std::none_of(std::cbegin(seqArgsOld), std::cend(seqArgsOld),
1083 [&rOrg](const beans::PropertyValue& rOld){ return rOld.Name == rOrg.Name; });
1084 if ( bNew )
1086 // the entity with this name should be new for seqArgsNew
1087 // since it is not supported by transformer
1089 seqArgsNew.realloc( ++nNewLength );
1090 seqArgsNew.getArray()[ nNewLength - 1 ] = rOrg;
1092 aFinalCache.realloc( ++nFinalLength );
1093 aFinalCache.getArray()[ nFinalLength - 1 ] = rOrg;
1097 m_pData->m_seqArguments = std::move(aFinalCache);
1100 return seqArgsNew;
1103 return m_pData->m_seqArguments;
1106 void SAL_CALL SfxBaseModel::setArgs(const Sequence<beans::PropertyValue>& aArgs)
1108 SfxModelGuard aGuard( *this );
1110 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
1111 if (!pMedium)
1113 throw util::InvalidStateException(
1114 u"Medium could not be retrieved, unable to execute setArgs"_ustr);
1117 for (const auto& rArg : aArgs)
1119 OUString sValue;
1120 bool bValue;
1121 bool ok = false;
1122 if (rArg.Name == "SuggestedSaveAsName")
1124 if (rArg.Value >>= sValue)
1126 pMedium->GetItemSet().Put(SfxStringItem(SID_SUGGESTEDSAVEASNAME, sValue));
1127 ok = true;
1130 else if (rArg.Name == "SuggestedSaveAsDir")
1132 if (rArg.Value >>= sValue)
1134 pMedium->GetItemSet().Put(SfxStringItem(SID_SUGGESTEDSAVEASDIR, sValue));
1135 ok = true;
1138 else if (rArg.Name == "LockContentExtraction")
1140 if (rArg.Value >>= bValue)
1142 pMedium->GetItemSet().Put(SfxBoolItem(SID_LOCK_CONTENT_EXTRACTION, bValue));
1143 ok = true;
1146 else if (rArg.Name == "LockExport")
1148 if (rArg.Value >>= bValue)
1150 pMedium->GetItemSet().Put(SfxBoolItem(SID_LOCK_EXPORT, bValue));
1151 ok = true;
1154 else if (rArg.Name == "LockPrint")
1156 if (rArg.Value >>= bValue)
1158 pMedium->GetItemSet().Put(SfxBoolItem(SID_LOCK_PRINT, bValue));
1159 ok = true;
1162 else if (rArg.Name == "LockSave")
1164 if (rArg.Value >>= bValue)
1166 pMedium->GetItemSet().Put(SfxBoolItem(SID_LOCK_SAVE, bValue));
1167 ok = true;
1170 else if (rArg.Name == "LockEditDoc")
1172 if (rArg.Value >>= bValue)
1174 pMedium->GetItemSet().Put(SfxBoolItem(SID_LOCK_EDITDOC, bValue));
1175 ok = true;
1178 else if (rArg.Name == "Replaceable")
1180 if (rArg.Value >>= bValue)
1182 pMedium->GetItemSet().Put(SfxBoolItem(SID_REPLACEABLE, bValue));
1183 ok = true;
1186 else if (rArg.Name == "EncryptionData")
1188 pMedium->GetItemSet().Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, rArg.Value));
1189 ok = true;
1191 else if (rArg.Name == "FilterName")
1193 // HACK: Needed a way to tweak the filter after loading has started,
1194 // but changing this must be avoided unless clearly intentional.
1195 if (aArgs.size() == 1)
1197 if (rArg.Value >>= sValue)
1199 pMedium->GetItemSet().Put(SfxStringItem(SID_FILTER_NAME, sValue));
1200 ok = true;
1204 if (!ok)
1206 throw lang::IllegalArgumentException("Setting property not supported: " + rArg.Name,
1207 comphelper::getProcessComponentContext(), 0);
1212 // frame::XModel
1215 void SAL_CALL SfxBaseModel::connectController( const Reference< frame::XController >& xController )
1217 SfxModelGuard aGuard( *this );
1218 OSL_PRECOND( xController.is(), "SfxBaseModel::connectController: invalid controller!" );
1219 if ( !xController.is() )
1220 return;
1222 m_pData->m_seqControllers.push_back(xController);
1224 if ( m_pData->m_seqControllers.size() == 1 )
1226 SfxViewFrame* pViewFrame = SfxViewFrame::Get( xController, GetObjectShell() );
1227 ENSURE_OR_THROW( pViewFrame, "SFX document without SFX view!?" );
1228 pViewFrame->UpdateDocument_Impl();
1229 const OUString sDocumentURL = GetObjectShell()->GetMedium()->GetName();
1230 if ( !sDocumentURL.isEmpty() )
1231 SfxGetpApp()->Broadcast( SfxOpenUrlHint( sDocumentURL ) );
1236 // frame::XModel
1239 void SAL_CALL SfxBaseModel::disconnectController( const Reference< frame::XController >& xController )
1241 SfxModelGuard aGuard( *this );
1243 if ( m_pData->m_seqControllers.empty() )
1244 return;
1246 auto& vec = m_pData->m_seqControllers;
1247 std::erase(vec, xController);
1249 if ( xController == m_pData->m_xCurrent )
1250 m_pData->m_xCurrent.clear();
1253 namespace
1255 class ControllerLockUndoAction : public ::cppu::WeakImplHelper< XUndoAction >
1257 public:
1258 ControllerLockUndoAction( const Reference< XModel >& i_model, const bool i_undoIsUnlock )
1259 :m_xModel( i_model )
1260 ,m_bUndoIsUnlock( i_undoIsUnlock )
1264 // XUndoAction
1265 virtual OUString SAL_CALL getTitle() override;
1266 virtual void SAL_CALL undo( ) override;
1267 virtual void SAL_CALL redo( ) override;
1269 private:
1270 const Reference< XModel > m_xModel;
1271 const bool m_bUndoIsUnlock;
1274 OUString SAL_CALL ControllerLockUndoAction::getTitle()
1276 // this action is intended to be used within an UndoContext only, so nobody will ever see this title ...
1277 return OUString();
1280 void SAL_CALL ControllerLockUndoAction::undo( )
1282 if ( m_bUndoIsUnlock )
1283 m_xModel->unlockControllers();
1284 else
1285 m_xModel->lockControllers();
1288 void SAL_CALL ControllerLockUndoAction::redo( )
1290 if ( m_bUndoIsUnlock )
1291 m_xModel->lockControllers();
1292 else
1293 m_xModel->unlockControllers();
1298 // frame::XModel
1301 void SAL_CALL SfxBaseModel::lockControllers()
1303 SfxModelGuard aGuard( *this );
1305 ++m_pData->m_nControllerLockCount ;
1307 if ( m_pData->m_pDocumentUndoManager.is()
1308 && m_pData->m_pDocumentUndoManager->isInContext()
1309 && !m_pData->m_pDocumentUndoManager->isLocked()
1312 m_pData->m_pDocumentUndoManager->addUndoAction( new ControllerLockUndoAction( this, true ) );
1317 // frame::XModel
1320 void SAL_CALL SfxBaseModel::unlockControllers()
1322 SfxModelGuard aGuard( *this );
1324 --m_pData->m_nControllerLockCount ;
1326 if ( m_pData->m_pDocumentUndoManager.is()
1327 && m_pData->m_pDocumentUndoManager->isInContext()
1328 && !m_pData->m_pDocumentUndoManager->isLocked()
1331 m_pData->m_pDocumentUndoManager->addUndoAction( new ControllerLockUndoAction( this, false ) );
1336 // frame::XModel
1339 sal_Bool SAL_CALL SfxBaseModel::hasControllersLocked()
1341 SfxModelGuard aGuard( *this );
1342 return ( m_pData->m_nControllerLockCount != 0 ) ;
1346 // frame::XModel
1349 Reference< frame::XController > SAL_CALL SfxBaseModel::getCurrentController()
1351 SfxModelGuard aGuard( *this );
1353 // get the last active controller of this model
1354 if ( m_pData->m_xCurrent.is() )
1355 return m_pData->m_xCurrent;
1357 // get the first controller of this model
1358 return !m_pData->m_seqControllers.empty() ? m_pData->m_seqControllers.front() : m_pData->m_xCurrent;
1362 // frame::XModel
1365 void SAL_CALL SfxBaseModel::setCurrentController( const Reference< frame::XController >& xCurrentController )
1367 SfxModelGuard aGuard( *this );
1369 m_pData->m_xCurrent = xCurrentController;
1373 // frame::XModel
1376 Reference< XInterface > SAL_CALL SfxBaseModel::getCurrentSelection()
1378 SfxModelGuard aGuard( *this );
1380 Reference< XInterface > xReturn;
1381 Reference< frame::XController > xController = getCurrentController() ;
1383 if ( xController.is() )
1385 Reference< view::XSelectionSupplier > xDocView( xController, UNO_QUERY );
1386 if ( xDocView.is() )
1388 Any aSel = xDocView->getSelection();
1389 aSel >>= xReturn ;
1393 return xReturn ;
1397 // XModifiable2
1400 sal_Bool SAL_CALL SfxBaseModel::disableSetModified()
1402 SfxModelGuard aGuard( *this );
1404 if ( !m_pData->m_pObjectShell.is() )
1405 throw RuntimeException();
1407 bool bResult = m_pData->m_pObjectShell->IsEnableSetModified();
1408 m_pData->m_pObjectShell->EnableSetModified( false );
1410 return bResult;
1413 sal_Bool SAL_CALL SfxBaseModel::enableSetModified()
1415 SfxModelGuard aGuard( *this );
1417 if ( !m_pData->m_pObjectShell.is() )
1418 throw RuntimeException();
1420 bool bResult = m_pData->m_pObjectShell->IsEnableSetModified();
1421 m_pData->m_pObjectShell->EnableSetModified();
1423 return bResult;
1426 sal_Bool SAL_CALL SfxBaseModel::isSetModifiedEnabled()
1428 SfxModelGuard aGuard( *this );
1430 if ( !m_pData->m_pObjectShell.is() )
1431 throw RuntimeException();
1433 return m_pData->m_pObjectShell->IsEnableSetModified();
1437 // XModifiable
1440 sal_Bool SAL_CALL SfxBaseModel::isModified()
1442 SfxModelGuard aGuard( *this );
1444 return m_pData->m_pObjectShell.is() && m_pData->m_pObjectShell->IsModified();
1448 // XModifiable
1451 void SAL_CALL SfxBaseModel::setModified( sal_Bool bModified )
1453 SfxModelGuard aGuard( *this );
1455 if ( m_pData->m_pObjectShell.is() )
1456 m_pData->m_pObjectShell->SetModified(bModified);
1460 // XModifiable
1463 void SAL_CALL SfxBaseModel::addModifyListener(const Reference< util::XModifyListener >& xListener)
1465 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
1467 m_pData->m_aModifyListeners.addInterface( xListener );
1471 // XModifiable
1474 void SAL_CALL SfxBaseModel::removeModifyListener(const Reference< util::XModifyListener >& xListener)
1476 SfxModelGuard aGuard( *this );
1478 m_pData->m_aModifyListeners.removeInterface( xListener );
1482 // XCloseable
1485 void SAL_CALL SfxBaseModel::close( sal_Bool bDeliverOwnership )
1487 SolarMutexGuard aGuard;
1488 if ( impl_isDisposed() || m_pData->m_bClosed || m_pData->m_bClosing )
1489 return;
1491 Reference< XInterface > xSelfHold( getXWeak() );
1492 lang::EventObject aSource ( getXWeak() );
1493 if (m_pData->m_aCloseListeners.getLength())
1495 comphelper::OInterfaceIteratorHelper3 pIterator(m_pData->m_aCloseListeners);
1496 while (pIterator.hasMoreElements())
1500 pIterator.next()->queryClosing( aSource, bDeliverOwnership );
1502 catch( RuntimeException& )
1504 pIterator.remove();
1509 if ( m_pData->m_bSaving )
1511 if (bDeliverOwnership)
1512 m_pData->m_bSuicide = true;
1513 throw util::CloseVetoException(
1514 u"Can not close while saving."_ustr,
1515 static_cast< util::XCloseable* >(this));
1518 // no own objections against closing!
1519 m_pData->m_bClosing = true;
1520 if (m_pData->m_aCloseListeners.getLength())
1522 comphelper::OInterfaceIteratorHelper3 pCloseIterator(m_pData->m_aCloseListeners);
1523 while (pCloseIterator.hasMoreElements())
1527 pCloseIterator.next()->notifyClosing( aSource );
1529 catch( RuntimeException& )
1531 pCloseIterator.remove();
1536 m_pData->m_bClosed = true;
1537 m_pData->m_bClosing = false;
1539 dispose();
1543 // XCloseBroadcaster
1546 void SAL_CALL SfxBaseModel::addCloseListener( const Reference< util::XCloseListener >& xListener )
1548 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
1550 m_pData->m_aCloseListeners.addInterface( xListener );
1554 // XCloseBroadcaster
1557 void SAL_CALL SfxBaseModel::removeCloseListener( const Reference< util::XCloseListener >& xListener )
1559 SfxModelGuard aGuard( *this );
1561 m_pData->m_aCloseListeners.removeInterface( xListener );
1565 // XPrintable
1568 Sequence< beans::PropertyValue > SAL_CALL SfxBaseModel::getPrinter()
1570 SfxModelGuard aGuard( *this );
1572 impl_getPrintHelper();
1573 return m_pData->m_xPrintable->getPrinter();
1576 void SAL_CALL SfxBaseModel::setPrinter(const Sequence< beans::PropertyValue >& rPrinter)
1578 SfxModelGuard aGuard( *this );
1580 impl_getPrintHelper();
1581 m_pData->m_xPrintable->setPrinter( rPrinter );
1584 void SAL_CALL SfxBaseModel::print(const Sequence< beans::PropertyValue >& rOptions)
1586 SfxModelGuard aGuard( *this );
1588 impl_getPrintHelper();
1590 // tdf#123728 Always print on main thread to avoid deadlocks
1591 vcl::solarthread::syncExecute([this, &rOptions]() { m_pData->m_xPrintable->print(rOptions); });
1594 // XStorable
1597 sal_Bool SAL_CALL SfxBaseModel::hasLocation()
1599 SfxModelGuard aGuard( *this );
1601 return m_pData->m_pObjectShell.is() && m_pData->m_pObjectShell->HasName();
1605 // XStorable
1608 OUString SAL_CALL SfxBaseModel::getLocation()
1610 SfxModelGuard aGuard( *this );
1612 if ( m_pData->m_pObjectShell.is() )
1614 // TODO/LATER: is it correct that the shared document returns shared file location?
1615 if ( m_pData->m_pObjectShell->IsDocShared() )
1616 return m_pData->m_pObjectShell->GetSharedFileURL();
1617 else
1618 return m_pData->m_pObjectShell->GetMedium()->GetName();
1621 return m_pData->m_sURL;
1625 // XStorable
1628 sal_Bool SAL_CALL SfxBaseModel::isReadonly()
1630 SfxModelGuard aGuard( *this );
1632 return !m_pData->m_pObjectShell.is() || m_pData->m_pObjectShell->IsReadOnly();
1635 // XStorable2
1638 void SAL_CALL SfxBaseModel::storeSelf( const Sequence< beans::PropertyValue >& aSeqArgs )
1640 SfxModelGuard aGuard( *this );
1642 if ( !m_pData->m_pObjectShell.is() )
1643 return;
1645 SfxSaveGuard aSaveGuard(this, m_pData.get());
1647 bool bCheckIn = false;
1648 bool bOnMainThread = false;
1649 for ( const auto& rArg : aSeqArgs )
1651 // check that only acceptable parameters are provided here
1652 if ( rArg.Name != "VersionComment" && rArg.Name != "Author"
1653 && rArg.Name != "DontTerminateEdit"
1654 && rArg.Name != "InteractionHandler" && rArg.Name != "StatusIndicator"
1655 && rArg.Name != "VersionMajor"
1656 && rArg.Name != "FailOnWarning"
1657 && rArg.Name != "CheckIn"
1658 && rArg.Name != "NoFileSync"
1659 && rArg.Name != "OnMainThread" )
1661 const OUString aMessage( "Unexpected MediaDescriptor parameter: " + rArg.Name );
1662 throw lang::IllegalArgumentException( aMessage, Reference< XInterface >(), 1 );
1664 else if ( rArg.Name == "CheckIn" )
1666 rArg.Value >>= bCheckIn;
1668 else if (rArg.Name == "OnMainThread")
1670 rArg.Value >>= bOnMainThread;
1674 // Remove CheckIn property if needed
1675 sal_uInt16 nSlotId = SID_SAVEDOC;
1676 Sequence< beans::PropertyValue > aArgs = aSeqArgs;
1677 if ( bCheckIn )
1679 nSlotId = SID_CHECKIN;
1680 sal_Int32 nLength = aSeqArgs.getLength( );
1681 aArgs = Sequence< beans::PropertyValue >( nLength - 1 );
1682 std::copy_if(aSeqArgs.begin(), aSeqArgs.end(), aArgs.getArray(),
1683 [](const beans::PropertyValue& rProp) { return rProp.Name != "CheckIn"; });
1686 std::optional<SfxAllItemSet> pParams(SfxGetpApp()->GetPool() );
1687 TransformParameters( nSlotId, aArgs, *pParams );
1689 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::SaveDoc, GlobalEventConfig::GetEventName(GlobalEventId::SAVEDOC), m_pData->m_pObjectShell.get() ) );
1691 bool bRet = false;
1693 // TODO/LATER: let the embedded case of saving be handled more careful
1694 if ( m_pData->m_pObjectShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
1696 // If this is an embedded object that has no URL based location it should be stored to own storage.
1697 // An embedded object can have a location based on URL in case it is a link, then it should be
1698 // stored in normal way.
1699 if ( !hasLocation() || getLocation().startsWith("private:") )
1701 // actually in this very rare case only UI parameters have sense
1702 // TODO/LATER: should be done later, after integration of sb19
1703 bRet = m_pData->m_pObjectShell->DoSave()
1704 && m_pData->m_pObjectShell->DoSaveCompleted();
1706 else
1708 bRet = m_pData->m_pObjectShell->Save_Impl( &*pParams );
1711 else
1713 // Tell the SfxMedium if we are in checkin instead of normal save
1714 m_pData->m_pObjectShell->GetMedium( )->SetInCheckIn( nSlotId == SID_CHECKIN );
1715 if (bOnMainThread)
1716 bRet = vcl::solarthread::syncExecute(
1717 [this, &pParams] { return m_pData->m_pObjectShell->Save_Impl(&*pParams); });
1718 else
1719 bRet = m_pData->m_pObjectShell->Save_Impl(&*pParams);
1720 m_pData->m_pObjectShell->GetMedium( )->SetInCheckIn( nSlotId != SID_CHECKIN );
1723 pParams.reset();
1725 ErrCodeMsg nErrCode = m_pData->m_pObjectShell->GetErrorIgnoreWarning();
1726 m_pData->m_pObjectShell->ResetError();
1728 if ( bRet )
1730 m_pData->m_aPreusedFilterName = GetMediumFilterName_Impl();
1732 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::SaveDocDone, GlobalEventConfig::GetEventName(GlobalEventId::SAVEDOCDONE), m_pData->m_pObjectShell.get() ) );
1734 else
1736 if (!nErrCode)
1737 nErrCode = ERRCODE_IO_CANTWRITE;
1738 // write the contents of the logger to the file
1739 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::SaveDocFailed, GlobalEventConfig::GetEventName(GlobalEventId::SAVEDOCFAILED), m_pData->m_pObjectShell.get() ) );
1741 throw task::ErrorCodeIOException(
1742 "SfxBaseModel::storeSelf: " + nErrCode.toString(),
1743 Reference< XInterface >(), sal_uInt32(nErrCode.GetCode()));
1748 // XStorable
1751 void SAL_CALL SfxBaseModel::store()
1753 comphelper::ProfileZone aZone("store");
1754 storeSelf( Sequence< beans::PropertyValue >() );
1758 // XStorable
1761 void SAL_CALL SfxBaseModel::storeAsURL( const OUString& rURL ,
1762 const Sequence< beans::PropertyValue >& rArgs )
1764 SfxModelGuard aGuard( *this );
1765 comphelper::ProfileZone aZone("storeAs");
1767 if ( !m_pData->m_pObjectShell.is() )
1768 return;
1770 SfxSaveGuard aSaveGuard(this, m_pData.get());
1772 utl::MediaDescriptor aDescriptor(rArgs);
1773 bool bOnMainThread = aDescriptor.getUnpackedValueOrDefault(u"OnMainThread"_ustr, false);
1774 if (bOnMainThread)
1776 vcl::solarthread::syncExecute([this, rURL, rArgs]() { impl_store(rURL, rArgs, false); });
1778 else
1780 impl_store(rURL, rArgs, false);
1783 Sequence< beans::PropertyValue > aSequence ;
1784 TransformItems( SID_OPENDOC, m_pData->m_pObjectShell->GetMedium()->GetItemSet(), aSequence );
1785 attachResource( rURL, aSequence );
1787 loadCmisProperties( );
1789 #if OSL_DEBUG_LEVEL > 0
1790 const SfxStringItem* pPasswdItem = m_pData->m_pObjectShell->GetMedium()->GetItemSet().GetItem(SID_PASSWORD, false);
1791 OSL_ENSURE( !pPasswdItem, "There should be no Password property in the document MediaDescriptor!" );
1792 #endif
1796 // XUndoManagerSupplier
1798 Reference< XUndoManager > SAL_CALL SfxBaseModel::getUndoManager( )
1800 SfxModelGuard aGuard( *this );
1801 if ( !m_pData->m_pDocumentUndoManager.is() )
1802 m_pData->m_pDocumentUndoManager.set( new ::sfx2::DocumentUndoManager( *this ) );
1803 return m_pData->m_pDocumentUndoManager;
1807 // XStorable
1810 void SAL_CALL SfxBaseModel::storeToURL( const OUString& rURL ,
1811 const Sequence< beans::PropertyValue >& rArgs )
1813 SfxModelGuard aGuard( *this );
1814 comphelper::ProfileZone aZone("storeToURL");
1816 if ( !m_pData->m_pObjectShell.is() )
1817 return;
1819 SfxSaveGuard aSaveGuard(this, m_pData.get());
1820 try {
1821 utl::MediaDescriptor aDescriptor(rArgs);
1822 bool bOnMainThread = aDescriptor.getUnpackedValueOrDefault(u"OnMainThread"_ustr, false);
1823 if (bOnMainThread)
1824 vcl::solarthread::syncExecute([this, rURL, rArgs]() { impl_store(rURL, rArgs, true); });
1825 else
1826 impl_store(rURL, rArgs, true);
1828 catch (const uno::Exception &e)
1830 // convert to the exception we announce in the throw
1831 // (eg. neon likes to throw InteractiveAugmentedIOException which
1832 // is not an io::IOException)
1833 throw io::IOException(e.Message, e.Context);
1837 sal_Bool SAL_CALL SfxBaseModel::wasModifiedSinceLastSave()
1839 SfxModelGuard aGuard( *this );
1840 return m_pData->m_oDirtyTimestamp.has_value();
1843 void SAL_CALL SfxBaseModel::storeToRecoveryFile( const OUString& i_TargetLocation, const Sequence< PropertyValue >& i_MediaDescriptor )
1845 SfxModelGuard aGuard( *this );
1847 // delegate
1848 SfxSaveGuard aSaveGuard( this, m_pData.get() );
1849 impl_store( i_TargetLocation, i_MediaDescriptor, true );
1851 // no need for subsequent calls to storeToRecoveryFile, unless we're modified, again
1852 m_pData->setModifiedForAutoSave(false);
1855 sal_Int64 SAL_CALL SfxBaseModel::getModifiedStateDuration()
1857 SfxModelGuard aGuard(*this);
1858 if (!m_pData->m_oDirtyTimestamp)
1859 return -1;
1860 auto ms = std::chrono::ceil<std::chrono::milliseconds>(std::chrono::steady_clock::now()
1861 - *m_pData->m_oDirtyTimestamp);
1862 return ms.count();
1865 void SAL_CALL SfxBaseModel::recoverFromFile( const OUString& i_SourceLocation, const OUString& i_SalvagedFile, const Sequence< PropertyValue >& i_MediaDescriptor )
1867 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
1869 // delegate to our "load" method
1870 ::comphelper::NamedValueCollection aMediaDescriptor( i_MediaDescriptor );
1872 // our load implementation expects the SalvagedFile to be in the media descriptor
1873 OSL_ENSURE( !aMediaDescriptor.has( u"SalvagedFile"_ustr ) || ( aMediaDescriptor.getOrDefault( u"SalvagedFile"_ustr, OUString() ) == i_SalvagedFile ),
1874 "SfxBaseModel::recoverFromFile: inconsistent information!" );
1875 aMediaDescriptor.put( u"SalvagedFile"_ustr, i_SalvagedFile );
1877 // similar for the to-be-loaded file
1878 OSL_ENSURE( !aMediaDescriptor.has( u"URL"_ustr ) || ( aMediaDescriptor.getOrDefault( u"URL"_ustr, OUString() ) == i_SourceLocation ),
1879 "SfxBaseModel::recoverFromFile: inconsistent information!" );
1880 aMediaDescriptor.put( u"URL"_ustr, i_SourceLocation );
1882 load( aMediaDescriptor.getPropertyValues() );
1884 // Note: The XDocumentRecovery interface specification requires us to do an attachResource after loading.
1885 // However, we will not do this here, as we know that our load implementation (respectively some method
1886 // called from there) already did so.
1887 // In particular, the load process might already have modified some elements of the media
1888 // descriptor, for instance the MacroExecMode (in case the user was involved to decide about it), and we do
1889 // not want to overwrite it with the "old" elements passed to this method here.
1893 // XLoadable
1896 void SAL_CALL SfxBaseModel::initNew()
1898 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
1899 if ( IsInitialized() )
1900 throw frame::DoubleInitializationException( OUString(), *this );
1902 // the object shell should exist always
1903 DBG_ASSERT( m_pData->m_pObjectShell.is(), "Model is useless without an ObjectShell" );
1904 if ( !m_pData->m_pObjectShell.is() )
1905 return;
1907 if( m_pData->m_pObjectShell->GetMedium() )
1908 throw frame::DoubleInitializationException();
1910 bool bRes = m_pData->m_pObjectShell->DoInitNew();
1911 ErrCodeMsg nErrCode = m_pData->m_pObjectShell->GetErrorIgnoreWarning() ?
1912 m_pData->m_pObjectShell->GetErrorIgnoreWarning() : ERRCODE_IO_CANTCREATE;
1913 m_pData->m_pObjectShell->ResetError();
1915 if ( !bRes )
1916 throw task::ErrorCodeIOException(
1917 "SfxBaseModel::initNew: " + nErrCode.toString(),
1918 Reference< XInterface >(), sal_uInt32(nErrCode.GetCode()));
1921 namespace {
1923 OUString getFilterProvider( SfxMedium const & rMedium )
1925 const std::shared_ptr<const SfxFilter>& pFilter = rMedium.GetFilter();
1926 if (!pFilter)
1927 return OUString();
1929 return pFilter->GetProviderName();
1932 void setUpdatePickList( SfxMedium* pMedium )
1934 if (!pMedium)
1935 return;
1937 bool bHidden = false;
1938 const SfxBoolItem* pHidItem = pMedium->GetItemSet().GetItem(SID_HIDDEN, false);
1939 if (pHidItem)
1940 bHidden = pHidItem->GetValue();
1942 pMedium->SetUpdatePickList(!bHidden);
1947 void SAL_CALL SfxBaseModel::load( const Sequence< beans::PropertyValue >& seqArguments )
1949 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
1950 if ( IsInitialized() )
1951 throw frame::DoubleInitializationException( OUString(), *this );
1953 // the object shell should exist always
1954 DBG_ASSERT( m_pData->m_pObjectShell.is(), "Model is useless without an ObjectShell" );
1956 if (!m_pData->m_pObjectShell.is())
1957 return;
1959 if( m_pData->m_pObjectShell->GetMedium() )
1960 // if a Medium is present, the document is already initialized
1961 throw frame::DoubleInitializationException();
1963 SfxMedium* pMedium = new SfxMedium( seqArguments );
1965 ErrCodeMsg nError = ERRCODE_NONE;
1966 if (!getFilterProvider(*pMedium).isEmpty())
1968 if (!m_pData->m_pObjectShell->DoLoadExternal(pMedium))
1969 nError = ERRCODE_IO_GENERAL;
1971 pMedium = handleLoadError(nError, pMedium);
1972 setUpdatePickList(pMedium);
1973 return;
1976 OUString aFilterName;
1977 const SfxStringItem* pFilterNameItem = pMedium->GetItemSet().GetItem(SID_FILTER_NAME, false);
1978 if( pFilterNameItem )
1979 aFilterName = pFilterNameItem->GetValue();
1980 if( !m_pData->m_pObjectShell->GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName ) )
1982 // filtername is not valid
1983 delete pMedium;
1984 throw frame::IllegalArgumentIOException();
1987 const SfxStringItem* pSalvageItem = pMedium->GetItemSet().GetItem(SID_DOC_SALVAGE, false);
1988 bool bSalvage = pSalvageItem != nullptr;
1990 // load document
1991 if ( !m_pData->m_pObjectShell->DoLoad(pMedium) )
1992 nError=ERRCODE_IO_GENERAL;
1994 // QUESTION: if the following happens outside of DoLoad, something important is missing there!
1995 Reference< task::XInteractionHandler > xHandler = pMedium->GetInteractionHandler();
1996 if( m_pData->m_pObjectShell->GetErrorCode() )
1998 nError = m_pData->m_pObjectShell->GetErrorCode();
1999 if ( nError == ERRCODE_IO_BROKENPACKAGE && xHandler.is() )
2001 const OUString aDocName( pMedium->GetURLObject().getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset ) );
2002 if (!pMedium->IsRepairPackage())
2004 RequestPackageReparation aRequest( aDocName );
2005 xHandler->handle( aRequest.GetRequest() );
2006 if( aRequest.isApproved() )
2008 // lok: we want to overwrite file in jail, so don't use template flag
2009 bool bIsLOK = comphelper::LibreOfficeKit::isActive();
2010 // broken package: try second loading and allow repair
2011 pMedium->GetItemSet().Put( SfxBoolItem( SID_REPAIRPACKAGE, true ) );
2012 pMedium->GetItemSet().Put( SfxBoolItem( SID_TEMPLATE, !bIsLOK ) );
2013 pMedium->GetItemSet().Put( SfxStringItem( SID_DOCINFO_TITLE, aDocName ) );
2015 // the error must be reset and the storage must be reopened in new mode
2016 pMedium->ResetError();
2017 pMedium->CloseStorage();
2018 m_pData->m_pObjectShell->PrepareSecondTryLoad_Impl();
2019 nError = ERRCODE_NONE;
2020 if ( !m_pData->m_pObjectShell->DoLoad(pMedium) )
2021 nError=ERRCODE_IO_GENERAL;
2022 if (m_pData->m_pObjectShell->GetErrorCode())
2023 nError = m_pData->m_pObjectShell->GetErrorCode();
2027 if ( nError == ERRCODE_IO_BROKENPACKAGE )
2029 // repair either not allowed or not successful
2030 NotifyBrokenPackage aRequest( aDocName );
2031 xHandler->handle( aRequest.GetRequest() );
2036 if( m_pData->m_pObjectShell->IsAbortingImport() )
2037 nError = ERRCODE_ABORT;
2039 if (bSalvage && nError == ERRCODE_NONE)
2041 // file recovery: restore original filter
2042 const SfxStringItem* pFilterItem = pMedium->GetItemSet().GetItem(SID_FILTER_NAME, false);
2043 SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher();
2044 std::shared_ptr<const SfxFilter> pSetFilter = rMatcher.GetFilter4FilterName( pFilterItem->GetValue() );
2045 pMedium->SetFilter( pSetFilter );
2046 m_pData->m_pObjectShell->SetModified();
2049 // TODO/LATER: maybe the mode should be retrieved from outside and the preused filter should not be set
2050 if ( m_pData->m_pObjectShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
2052 const SfxStringItem* pFilterItem = pMedium->GetItemSet().GetItem(SID_FILTER_NAME, false);
2053 if ( pFilterItem )
2054 m_pData->m_aPreusedFilterName = pFilterItem->GetValue();
2057 if ( !nError )
2058 nError = pMedium->GetErrorIgnoreWarning();
2060 m_pData->m_pObjectShell->ResetError();
2062 pMedium = handleLoadError(nError, pMedium);
2063 loadCmisProperties();
2064 setUpdatePickList(pMedium);
2066 #if OSL_DEBUG_LEVEL > 0
2067 const SfxStringItem* pPasswdItem = pMedium->GetItemSet().GetItem(SID_PASSWORD, false);
2068 OSL_ENSURE( !pPasswdItem, "There should be no Password property in the document MediaDescriptor!" );
2069 #endif
2073 // XTransferable
2076 Any SAL_CALL SfxBaseModel::getTransferData( const datatransfer::DataFlavor& aFlavor )
2078 SfxModelGuard aGuard( *this );
2080 Any aAny;
2082 if ( m_pData->m_pObjectShell.is() )
2084 if ( aFlavor.MimeType == "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"" )
2086 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
2087 throw datatransfer::UnsupportedFlavorException();
2089 TransferableObjectDescriptor aDesc;
2091 aDesc.maClassName = m_pData->m_pObjectShell->GetClassName();
2092 aDesc.maTypeName = aFlavor.HumanPresentableName;
2094 // TODO/LATER: ViewAspect needs to be sal_Int64
2095 aDesc.mnViewAspect = sal::static_int_cast< sal_uInt16 >( embed::Aspects::MSOLE_CONTENT );
2097 Size aSize = m_pData->m_pObjectShell->GetVisArea().GetSize();
2099 MapUnit aMapUnit = m_pData->m_pObjectShell->GetMapUnit();
2100 aDesc.maSize = OutputDevice::LogicToLogic(aSize, MapMode(aMapUnit), MapMode(MapUnit::Map100thMM));
2101 aDesc.maDragStartPos = Point();
2102 aDesc.maDisplayName.clear();
2104 SvMemoryStream aMemStm( 1024, 1024 );
2105 WriteTransferableObjectDescriptor( aMemStm, aDesc );
2106 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Tell() );
2108 else if ( aFlavor.MimeType == "application/x-openoffice-embed-source;windows_formatname=\"Star EMBS\"" )
2110 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
2111 throw datatransfer::UnsupportedFlavorException();
2115 utl::TempFileNamed aTmp;
2116 aTmp.EnableKillingFile();
2117 storeToURL( aTmp.GetURL(), Sequence < beans::PropertyValue >() );
2118 std::unique_ptr<SvStream> pStream(aTmp.GetStream( StreamMode::READ ));
2119 const sal_uInt32 nLen = pStream->TellEnd();
2120 Sequence< sal_Int8 > aSeq( nLen );
2121 pStream->ReadBytes(aSeq.getArray(), nLen);
2122 if( aSeq.hasElements() )
2123 aAny <<= aSeq;
2125 catch ( Exception& )
2129 else if ( aFlavor.MimeType == "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" )
2131 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
2132 throw datatransfer::UnsupportedFlavorException();
2135 std::shared_ptr<GDIMetaFile> xMetaFile =
2136 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2138 if (xMetaFile)
2140 SvMemoryStream aMemStm( 65535, 65535 );
2141 aMemStm.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2143 SvmWriter aWriter( aMemStm );
2144 aWriter.Write( *xMetaFile );
2145 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( aMemStm.GetData() ),
2146 aMemStm.TellEnd() );
2149 else if ( aFlavor.MimeType == "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" )
2151 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
2152 throw datatransfer::UnsupportedFlavorException();
2154 std::shared_ptr<GDIMetaFile> xMetaFile =
2155 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2157 if (xMetaFile)
2159 SvMemoryStream aMemStm( 65535, 65535 );
2160 aMemStm.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2162 SvmWriter aWriter( aMemStm );
2163 aWriter.Write( *xMetaFile );
2164 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( aMemStm.GetData() ),
2165 aMemStm.TellEnd() );
2168 else if ( aFlavor.MimeType == "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" )
2170 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2172 std::shared_ptr<GDIMetaFile> xMetaFile =
2173 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2175 if (xMetaFile)
2177 std::unique_ptr<SvMemoryStream> xStream(
2178 GraphicHelper::getFormatStrFromGDI_Impl(
2179 xMetaFile.get(), ConvertDataFormat::EMF ) );
2180 if (xStream)
2182 xStream->SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2183 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( xStream->GetData() ),
2184 xStream->TellEnd() );
2188 else if ( GraphicHelper::supportsMetaFileHandle_Impl()
2189 && aFlavor.DataType == cppu::UnoType<sal_uInt64>::get())
2191 std::shared_ptr<GDIMetaFile> xMetaFile =
2192 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2194 if (xMetaFile)
2196 aAny <<= reinterpret_cast< sal_uInt64 >(
2197 GraphicHelper::getEnhMetaFileFromGDI_Impl( xMetaFile.get() ) );
2200 else
2201 throw datatransfer::UnsupportedFlavorException();
2203 else if ( aFlavor.MimeType == "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" )
2205 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2207 std::shared_ptr<GDIMetaFile> xMetaFile =
2208 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2210 if (xMetaFile)
2212 std::unique_ptr<SvMemoryStream> xStream(
2213 GraphicHelper::getFormatStrFromGDI_Impl(
2214 xMetaFile.get(), ConvertDataFormat::WMF ) );
2216 if (xStream)
2218 xStream->SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2219 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( xStream->GetData() ),
2220 xStream->TellEnd() );
2224 else if ( GraphicHelper::supportsMetaFileHandle_Impl()
2225 && aFlavor.DataType == cppu::UnoType<sal_uInt64>::get())
2227 // means HGLOBAL handler to memory storage containing METAFILEPICT structure
2229 std::shared_ptr<GDIMetaFile> xMetaFile =
2230 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2232 if (xMetaFile)
2234 Size aMetaSize = xMetaFile->GetPrefSize();
2235 aAny <<= reinterpret_cast< sal_uInt64 >(
2236 GraphicHelper::getWinMetaFileFromGDI_Impl(
2237 xMetaFile.get(), aMetaSize ) );
2240 else
2241 throw datatransfer::UnsupportedFlavorException();
2243 else if ( aFlavor.MimeType == "image/svg+xml" )
2245 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
2246 throw datatransfer::UnsupportedFlavorException();
2248 std::shared_ptr<GDIMetaFile> xMetaFile =
2249 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2251 if (xMetaFile)
2253 std::unique_ptr<SvMemoryStream> xStream(
2254 GraphicHelper::getFormatStrFromGDI_Impl(
2255 xMetaFile.get(), ConvertDataFormat::SVG ) );
2257 if (xStream)
2259 xStream->SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2260 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( xStream->GetData() ),
2261 xStream->TellEnd() );
2265 else if ( aFlavor.MimeType == "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" )
2267 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
2268 throw datatransfer::UnsupportedFlavorException();
2270 std::shared_ptr<GDIMetaFile> xMetaFile =
2271 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2273 if (xMetaFile)
2275 std::unique_ptr<SvMemoryStream> xStream(
2276 GraphicHelper::getFormatStrFromGDI_Impl(
2277 xMetaFile.get(), ConvertDataFormat::BMP ) );
2279 if (xStream)
2281 xStream->SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2282 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( xStream->GetData() ),
2283 xStream->TellEnd() );
2287 else if ( aFlavor.MimeType == "image/png" )
2289 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
2290 throw datatransfer::UnsupportedFlavorException();
2292 std::shared_ptr<GDIMetaFile> xMetaFile =
2293 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2295 if (xMetaFile)
2297 std::unique_ptr<SvMemoryStream> xStream(
2298 GraphicHelper::getFormatStrFromGDI_Impl(
2299 xMetaFile.get(), ConvertDataFormat::PNG ) );
2301 if (xStream)
2303 xStream->SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2304 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( xStream->GetData() ),
2305 xStream->TellEnd() );
2309 else
2310 throw datatransfer::UnsupportedFlavorException();
2313 return aAny;
2317 // XTransferable
2320 Sequence< datatransfer::DataFlavor > SAL_CALL SfxBaseModel::getTransferDataFlavors()
2322 SfxModelGuard aGuard( *this );
2324 const sal_Int32 nSuppFlavors = GraphicHelper::supportsMetaFileHandle_Impl() ? 11 : 9;
2325 Sequence< datatransfer::DataFlavor > aFlavorSeq( nSuppFlavors );
2326 auto pFlavorSeq = aFlavorSeq.getArray();
2328 pFlavorSeq[0].MimeType =
2329 "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"";
2330 pFlavorSeq[0].HumanPresentableName = "GDIMetaFile";
2331 pFlavorSeq[0].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2333 pFlavorSeq[1].MimeType =
2334 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"";
2335 pFlavorSeq[1].HumanPresentableName = "GDIMetaFile";
2336 pFlavorSeq[1].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2338 pFlavorSeq[2].MimeType =
2339 "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" ;
2340 pFlavorSeq[2].HumanPresentableName = "Enhanced Windows MetaFile";
2341 pFlavorSeq[2].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2343 pFlavorSeq[3].MimeType =
2344 "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"";
2345 pFlavorSeq[3].HumanPresentableName = "Windows MetaFile";
2346 pFlavorSeq[3].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2348 pFlavorSeq[4].MimeType =
2349 "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"";
2350 pFlavorSeq[4].HumanPresentableName = "Star Object Descriptor (XML)";
2351 pFlavorSeq[4].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2353 pFlavorSeq[5].MimeType =
2354 "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
2355 pFlavorSeq[5].HumanPresentableName = "Star Embed Source (XML)";
2356 pFlavorSeq[5].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2358 pFlavorSeq[6].MimeType =
2359 "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"";
2360 pFlavorSeq[6].HumanPresentableName = "Bitmap";
2361 pFlavorSeq[6].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2363 pFlavorSeq[7].MimeType = "image/png";
2364 pFlavorSeq[7].HumanPresentableName = "PNG";
2365 pFlavorSeq[7].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2367 pFlavorSeq[8].MimeType = "image/svg+xml";
2368 pFlavorSeq[8].HumanPresentableName = "SVG";
2369 pFlavorSeq[8].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2371 if ( nSuppFlavors == 11 )
2373 pFlavorSeq[9].MimeType =
2374 "application/x-openoffice-emf;windows_formatname=\"Image EMF\"";
2375 pFlavorSeq[9].HumanPresentableName = "Enhanced Windows MetaFile";
2376 pFlavorSeq[9].DataType = cppu::UnoType<sal_uInt64>::get();
2378 pFlavorSeq[10].MimeType =
2379 "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"";
2380 pFlavorSeq[10].HumanPresentableName = "Windows MetaFile";
2381 pFlavorSeq[10].DataType = cppu::UnoType<sal_uInt64>::get();
2384 return aFlavorSeq;
2388 // XTransferable
2391 sal_Bool SAL_CALL SfxBaseModel::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
2393 SfxModelGuard aGuard( *this );
2395 if ( aFlavor.MimeType == "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" )
2397 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2398 return true;
2400 else if ( aFlavor.MimeType == "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" )
2402 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2403 return true;
2405 else if ( aFlavor.MimeType == "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" )
2407 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2408 return true;
2409 else if ( GraphicHelper::supportsMetaFileHandle_Impl()
2410 && aFlavor.DataType == cppu::UnoType<sal_uInt64>::get())
2411 return true;
2413 else if ( aFlavor.MimeType == "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" )
2415 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2416 return true;
2417 else if ( GraphicHelper::supportsMetaFileHandle_Impl()
2418 && aFlavor.DataType == cppu::UnoType<sal_uInt64>::get())
2419 return true;
2421 else if ( aFlavor.MimeType == "image/svg+xml" )
2423 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2424 return true;
2426 else if ( aFlavor.MimeType == "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"" )
2428 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2429 return true;
2431 else if ( aFlavor.MimeType == "application/x-openoffice-embed-source;windows_formatname=\"Star EMBS\"" )
2433 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2434 return true;
2436 else if ( aFlavor.MimeType == "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" )
2438 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2439 return true;
2441 else if ( aFlavor.MimeType == "image/png" )
2443 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2444 return true;
2447 return false;
2451 // XEventsSupplier
2454 Reference< container::XNameReplace > SAL_CALL SfxBaseModel::getEvents()
2456 SfxModelGuard aGuard( *this );
2458 if ( ! m_pData->m_xEvents.is() )
2460 m_pData->m_xEvents = new SfxEvents_Impl( m_pData->m_pObjectShell.get(), this );
2463 return m_pData->m_xEvents;
2467 // XEmbeddedScripts
2470 Reference< script::XStorageBasedLibraryContainer > SAL_CALL SfxBaseModel::getBasicLibraries()
2472 SfxModelGuard aGuard( *this );
2474 Reference< script::XStorageBasedLibraryContainer > xBasicLibraries;
2475 if ( m_pData->m_pObjectShell.is() )
2476 xBasicLibraries.set(m_pData->m_pObjectShell->GetBasicContainer(), UNO_QUERY);
2477 return xBasicLibraries;
2480 Reference< script::XStorageBasedLibraryContainer > SAL_CALL SfxBaseModel::getDialogLibraries()
2482 SfxModelGuard aGuard( *this );
2484 Reference< script::XStorageBasedLibraryContainer > xDialogLibraries;
2485 if ( m_pData->m_pObjectShell.is() )
2486 xDialogLibraries.set(m_pData->m_pObjectShell->GetDialogContainer(), UNO_QUERY);
2487 return xDialogLibraries;
2490 sal_Bool SAL_CALL SfxBaseModel::getAllowMacroExecution()
2492 SfxModelGuard aGuard( *this );
2494 if ( m_pData->m_pObjectShell.is() )
2495 return m_pData->m_pObjectShell->AdjustMacroMode();
2496 return false;
2500 // XScriptInvocationContext
2503 Reference< document::XEmbeddedScripts > SAL_CALL SfxBaseModel::getScriptContainer()
2505 SfxModelGuard aGuard( *this );
2507 Reference< document::XEmbeddedScripts > xDocumentScripts;
2511 Reference< frame::XModel > xDocument( this );
2512 xDocumentScripts.set( xDocument, UNO_QUERY );
2513 while ( !xDocumentScripts.is() && xDocument.is() )
2515 Reference< container::XChild > xDocAsChild( xDocument, UNO_QUERY );
2516 if ( !xDocAsChild.is() )
2518 xDocument = nullptr;
2519 break;
2522 xDocument.set( xDocAsChild->getParent(), UNO_QUERY );
2523 xDocumentScripts.set( xDocument, UNO_QUERY );
2526 catch( const Exception& )
2528 DBG_UNHANDLED_EXCEPTION("sfx.doc");
2529 xDocumentScripts = nullptr;
2532 return xDocumentScripts;
2536 // XEventBroadcaster
2539 void SAL_CALL SfxBaseModel::addEventListener( const Reference< document::XEventListener >& aListener )
2541 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
2543 m_pData->m_aDocumentEventListeners1.addInterface( aListener );
2547 // XEventBroadcaster
2550 void SAL_CALL SfxBaseModel::removeEventListener( const Reference< document::XEventListener >& aListener )
2552 SfxModelGuard aGuard( *this );
2554 m_pData->m_aDocumentEventListeners1.removeInterface( aListener );
2557 // XShapeEventBroadcaster
2559 void SAL_CALL SfxBaseModel::addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const Reference< document::XShapeEventListener >& xListener )
2561 assert(xShape.is() && "no shape?");
2562 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
2564 m_pData->maShapeListeners[xShape].push_back(xListener);
2568 // XShapeEventBroadcaster
2571 void SAL_CALL SfxBaseModel::removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const Reference< document::XShapeEventListener >& xListener )
2573 SfxModelGuard aGuard( *this );
2575 auto it = m_pData->maShapeListeners.find(xShape);
2576 if (it != m_pData->maShapeListeners.end())
2578 auto rVec = it->second;
2579 auto it2 = std::find(rVec.begin(), rVec.end(), xListener);
2580 if (it2 != rVec.end())
2582 rVec.erase(it2);
2583 if (rVec.empty())
2584 m_pData->maShapeListeners.erase(it);
2589 // XDocumentEventBroadcaster
2592 void SAL_CALL SfxBaseModel::addDocumentEventListener( const Reference< document::XDocumentEventListener >& aListener )
2594 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
2595 m_pData->m_aDocumentEventListeners2.addInterface( aListener );
2599 void SAL_CALL SfxBaseModel::removeDocumentEventListener( const Reference< document::XDocumentEventListener >& aListener )
2601 SfxModelGuard aGuard( *this );
2602 m_pData->m_aDocumentEventListeners2.removeInterface( aListener );
2606 void SAL_CALL SfxBaseModel::notifyDocumentEvent( const OUString&, const Reference< frame::XController2 >&, const Any& )
2608 throw lang::NoSupportException(u"SfxBaseModel controls all the sent notifications itself!"_ustr );
2611 Sequence<document::CmisProperty> SAL_CALL SfxBaseModel::getCmisProperties()
2613 if (impl_isDisposed())
2614 return Sequence<document::CmisProperty>();
2615 return m_pData->m_cmisProperties;
2618 void SAL_CALL SfxBaseModel::setCmisProperties( const Sequence< document::CmisProperty >& _cmisproperties )
2620 m_pData->m_cmisProperties = _cmisproperties;
2623 void SAL_CALL SfxBaseModel::updateCmisProperties( const Sequence< document::CmisProperty >& aProperties )
2625 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2626 if ( !pMedium )
2627 return;
2631 ::ucbhelper::Content aContent( pMedium->GetName( ),
2632 Reference<ucb::XCommandEnvironment>(),
2633 comphelper::getProcessComponentContext() );
2635 aContent.executeCommand( u"updateProperties"_ustr, uno::Any( aProperties ) );
2636 loadCmisProperties( );
2638 catch (const Exception & e)
2640 css::uno::Any anyEx = cppu::getCaughtException();
2641 throw lang::WrappedTargetRuntimeException( e.Message,
2642 e.Context, anyEx );
2647 void SAL_CALL SfxBaseModel::checkOut( )
2649 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2650 if ( !pMedium )
2651 return;
2655 ::ucbhelper::Content aContent( pMedium->GetName(),
2656 Reference<ucb::XCommandEnvironment>(),
2657 comphelper::getProcessComponentContext() );
2659 Any aResult = aContent.executeCommand( u"checkout"_ustr, Any( ) );
2660 OUString sURL;
2661 aResult >>= sURL;
2663 m_pData->m_pObjectShell->GetMedium( )->SetName( sURL );
2664 m_pData->m_pObjectShell->GetMedium( )->GetMedium_Impl( );
2665 m_pData->m_xDocumentProperties->setTitle( getTitle( ) );
2666 Sequence< beans::PropertyValue > aSequence ;
2667 TransformItems( SID_OPENDOC, pMedium->GetItemSet(), aSequence );
2668 attachResource( sURL, aSequence );
2670 // Reload the CMIS properties
2671 loadCmisProperties( );
2673 catch ( const Exception & e )
2675 css::uno::Any anyEx = cppu::getCaughtException();
2676 throw lang::WrappedTargetRuntimeException( e.Message,
2677 e.Context, anyEx );
2681 void SAL_CALL SfxBaseModel::cancelCheckOut( )
2683 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2684 if ( !pMedium )
2685 return;
2689 ::ucbhelper::Content aContent( pMedium->GetName(),
2690 Reference<ucb::XCommandEnvironment>(),
2691 comphelper::getProcessComponentContext() );
2693 Any aResult = aContent.executeCommand( u"cancelCheckout"_ustr, Any( ) );
2694 OUString sURL;
2695 aResult >>= sURL;
2697 m_pData->m_pObjectShell->GetMedium( )->SetName( sURL );
2699 catch ( const Exception & e )
2701 css::uno::Any anyEx = cppu::getCaughtException();
2702 throw lang::WrappedTargetRuntimeException( e.Message,
2703 e.Context, anyEx );
2707 void SAL_CALL SfxBaseModel::checkIn( sal_Bool bIsMajor, const OUString& rMessage )
2709 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2710 if ( !pMedium )
2711 return;
2715 Sequence< beans::PropertyValue > aProps{
2716 comphelper::makePropertyValue(u"VersionMajor"_ustr, bIsMajor),
2717 comphelper::makePropertyValue(u"VersionComment"_ustr, rMessage),
2718 comphelper::makePropertyValue(u"CheckIn"_ustr, true)
2721 const OUString sName( pMedium->GetName( ) );
2722 storeSelf( aProps );
2724 // Refresh pMedium as it has probably changed during the storeSelf call
2725 pMedium = m_pData->m_pObjectShell->GetMedium( );
2726 const OUString sNewName( pMedium->GetName( ) );
2728 // URL has changed, update the document
2729 if ( sName != sNewName )
2731 m_pData->m_xDocumentProperties->setTitle( getTitle( ) );
2732 Sequence< beans::PropertyValue > aSequence ;
2733 TransformItems( SID_OPENDOC, pMedium->GetItemSet(), aSequence );
2734 attachResource( sNewName, aSequence );
2736 // Reload the CMIS properties
2737 loadCmisProperties( );
2740 catch ( const Exception & e )
2742 css::uno::Any anyEx = cppu::getCaughtException();
2743 throw lang::WrappedTargetRuntimeException( e.Message,
2744 e.Context, anyEx );
2748 uno::Sequence< document::CmisVersion > SAL_CALL SfxBaseModel::getAllVersions( )
2750 uno::Sequence<document::CmisVersion> aVersions;
2751 if (impl_isDisposed())
2752 return aVersions;
2753 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2754 if ( pMedium )
2758 ::ucbhelper::Content aContent( pMedium->GetName(),
2759 Reference<ucb::XCommandEnvironment>(),
2760 comphelper::getProcessComponentContext() );
2762 Any aResult = aContent.executeCommand( u"getAllVersions"_ustr, Any( ) );
2763 aResult >>= aVersions;
2765 catch ( const Exception & e )
2767 css::uno::Any anyEx = cppu::getCaughtException();
2768 throw lang::WrappedTargetRuntimeException( e.Message,
2769 e.Context, anyEx );
2772 return aVersions;
2775 bool SfxBaseModel::getBoolPropertyValue( const OUString& rName )
2777 bool bValue = false;
2778 if ( m_pData->m_pObjectShell.is() )
2780 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2781 if ( pMedium )
2785 ::ucbhelper::Content aContent( pMedium->GetName( ),
2786 utl::UCBContentHelper::getDefaultCommandEnvironment(),
2787 comphelper::getProcessComponentContext() );
2788 Reference < beans::XPropertySetInfo > xProps = aContent.getProperties();
2789 if ( xProps->hasPropertyByName( rName ) )
2791 aContent.getPropertyValue( rName ) >>= bValue;
2794 catch ( const Exception & )
2796 // Simply ignore it: it's likely the document isn't versionable in that case
2797 bValue = false;
2801 return bValue;
2804 sal_Bool SAL_CALL SfxBaseModel::isVersionable( )
2806 return getBoolPropertyValue( u"IsVersionable"_ustr );
2809 sal_Bool SAL_CALL SfxBaseModel::canCheckOut( )
2811 return getBoolPropertyValue( u"CanCheckOut"_ustr );
2814 sal_Bool SAL_CALL SfxBaseModel::canCancelCheckOut( )
2816 return getBoolPropertyValue( u"CanCancelCheckOut"_ustr );
2819 sal_Bool SAL_CALL SfxBaseModel::canCheckIn( )
2821 return getBoolPropertyValue( u"CanCheckIn"_ustr );
2824 void SfxBaseModel::loadCmisProperties( )
2826 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2827 if ( !pMedium )
2828 return;
2832 ::ucbhelper::Content aContent( pMedium->GetName( ),
2833 utl::UCBContentHelper::getDefaultCommandEnvironment(),
2834 comphelper::getProcessComponentContext() );
2835 Reference < beans::XPropertySetInfo > xProps = aContent.getProperties();
2836 static constexpr OUString aCmisProps( u"CmisProperties"_ustr );
2837 if ( xProps->hasPropertyByName( aCmisProps ) )
2839 Sequence< document::CmisProperty> aCmisProperties;
2840 aContent.getPropertyValue( aCmisProps ) >>= aCmisProperties;
2841 setCmisProperties( aCmisProperties );
2844 catch (const ucb::ContentCreationException &)
2847 catch (const ucb::CommandAbortedException &)
2852 SfxMedium* SfxBaseModel::handleLoadError( const ErrCodeMsg& rError, SfxMedium* pMedium )
2854 if (!rError)
2856 // No error condition.
2857 return pMedium;
2860 ErrCodeMsg nError = rError;
2861 bool bSilent = false;
2862 const SfxBoolItem* pSilentItem = pMedium->GetItemSet().GetItem(SID_SILENT, false);
2863 if( pSilentItem )
2864 bSilent = pSilentItem->GetValue();
2866 bool bWarning = nError.IsWarning();
2867 if ( nError != ERRCODE_IO_BROKENPACKAGE && !bSilent )
2869 // broken package was handled already
2870 if ( SfxObjectShell::UseInteractionToHandleError(pMedium->GetInteractionHandler(), nError) && !bWarning)
2872 // abort loading (except for warnings)
2873 nError = ERRCODE_IO_ABORT;
2877 if ( m_pData->m_pObjectShell->GetMedium() != pMedium )
2879 // for whatever reason document now has another medium
2880 OSL_FAIL("Document has rejected the medium?!");
2881 delete pMedium;
2882 pMedium = nullptr;
2885 if ( !bWarning ) // #i30711# don't abort loading if it's only a warning
2887 nError = nError ? nError : ERRCODE_IO_CANTREAD;
2888 throw task::ErrorCodeIOException(
2889 "SfxBaseModel::handleLoadError: 0x" + nError.toString(),
2890 Reference< XInterface >(), sal_uInt32(nError.GetCode()));
2892 else
2893 pMedium->SetWarningError(nError);
2895 return pMedium;
2899 // SfxListener
2902 static void addTitle_Impl( Sequence < beans::PropertyValue >& rSeq, const OUString& rTitle )
2904 auto [begin, end] = asNonConstRange(rSeq);
2905 auto pProp = std::find_if(begin, end,
2906 [](const beans::PropertyValue& rProp) { return rProp.Name == "Title"; });
2907 if (pProp != end)
2909 pProp->Value <<= rTitle;
2911 else
2913 sal_Int32 nCount = rSeq.getLength();
2914 rSeq.realloc( nCount+1 );
2915 auto& el = rSeq.getArray()[nCount];
2916 el.Name = "Title";
2917 el.Value <<= rTitle;
2921 void SfxBaseModel::Notify( SfxBroadcaster& rBC ,
2922 const SfxHint& rHint )
2924 if ( !m_pData )
2925 return;
2927 if ( &rBC != m_pData->m_pObjectShell.get() )
2928 return;
2930 if ( rHint.GetId() == SfxHintId::DocChanged )
2931 changing();
2932 else if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
2934 const SfxEventHint& rNamedHint = static_cast<const SfxEventHint&>(rHint);
2935 switch (rNamedHint.GetEventId())
2937 case SfxEventHintId::StorageChanged:
2939 if ( m_pData->m_xUIConfigurationManager.is()
2940 && m_pData->m_pObjectShell->GetCreateMode() != SfxObjectCreateMode::EMBEDDED )
2942 Reference< embed::XStorage > xConfigStorage;
2943 static constexpr OUString aUIConfigFolderName( u"Configurations2"_ustr );
2945 xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, embed::ElementModes::READWRITE );
2946 if ( !xConfigStorage.is() )
2947 xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, embed::ElementModes::READ );
2949 if ( xConfigStorage.is() || !m_pData->m_pObjectShell->GetStorage()->hasByName( aUIConfigFolderName ) )
2951 // the storage is different, since otherwise it could not be opened, so it must be exchanged
2952 m_pData->m_xUIConfigurationManager->setStorage( xConfigStorage );
2954 else
2956 OSL_FAIL( "Unexpected scenario!" );
2960 ListenForStorage_Impl( m_pData->m_pObjectShell->GetStorage() );
2962 break;
2964 case SfxEventHintId::LoadFinished:
2966 impl_getPrintHelper();
2967 ListenForStorage_Impl( m_pData->m_pObjectShell->GetStorage() );
2968 m_pData->setModifiedForAutoSave(false);
2970 break;
2972 case SfxEventHintId::SaveAsDocDone:
2974 m_pData->m_sURL = m_pData->m_pObjectShell->GetMedium()->GetName();
2976 Sequence< beans::PropertyValue > aArgs;
2977 TransformItems( SID_SAVEASDOC, m_pData->m_pObjectShell->GetMedium()->GetItemSet(), aArgs );
2978 addTitle_Impl( aArgs, m_pData->m_pObjectShell->GetTitle() );
2979 attachResource( m_pData->m_pObjectShell->GetMedium()->GetName(), aArgs );
2981 break;
2983 case SfxEventHintId::DocCreated:
2985 impl_getPrintHelper();
2986 m_pData->setModifiedForAutoSave(false);
2988 break;
2990 case SfxEventHintId::ModifyChanged:
2992 m_pData->setModifiedForAutoSave(isModified());
2994 break;
2995 default: break;
2998 Any aSupplement;
2999 if (rNamedHint.GetEventId() == SfxEventHintId::PrintDoc)
3000 aSupplement <<= static_cast<const SfxPrintingHint*>(&rHint)->GetWhich();
3001 const SfxViewEventHint* pViewHint = dynamic_cast<const SfxViewEventHint*>(&rHint);
3002 postEvent_Impl( rNamedHint.GetEventName(), pViewHint ? pViewHint->GetController() : Reference< frame::XController2 >(), aSupplement );
3004 else if ( rHint.GetId() == SfxHintId::TitleChanged )
3006 addTitle_Impl( m_pData->m_seqArguments, m_pData->m_pObjectShell->GetTitle() );
3007 postEvent_Impl( GlobalEventConfig::GetEventName( GlobalEventId::TITLECHANGED ) );
3009 else if ( rHint.GetId() == SfxHintId::ModeChanged )
3011 postEvent_Impl( GlobalEventConfig::GetEventName( GlobalEventId::MODECHANGED ) );
3016 // public impl.
3019 void SfxBaseModel::NotifyModifyListeners_Impl() const
3021 if ( m_pData->m_aModifyListeners.getLength() )
3023 lang::EventObject aEvent( static_cast<frame::XModel *>(const_cast<SfxBaseModel *>(this)) );
3024 m_pData->m_aModifyListeners.notifyEach( &util::XModifyListener::modified, aEvent );
3027 // this notification here is done too generously, we cannot simply assume that we're really modified
3028 // now, but we need to check it ...
3029 m_pData->setModifiedForAutoSave(const_cast<SfxBaseModel*>(this)->isModified());
3032 void SfxBaseModel::changing()
3034 SfxModelGuard aGuard( *this );
3036 // the notification should not be sent if the document can not be modified
3037 if ( !m_pData->m_pObjectShell.is() || !m_pData->m_pObjectShell->IsEnableSetModified() )
3038 return;
3040 NotifyModifyListeners_Impl();
3044 // public impl.
3047 SfxObjectShell* SfxBaseModel::GetObjectShell() const
3049 return m_pData ? m_pData->m_pObjectShell.get() : nullptr;
3053 // public impl.
3056 bool SfxBaseModel::IsInitialized() const
3058 if ( !m_pData || !m_pData->m_pObjectShell.is() )
3060 OSL_FAIL( "SfxBaseModel::IsInitialized: this should have been caught earlier!" );
3061 return false;
3064 return m_pData->m_pObjectShell->GetMedium() != nullptr;
3067 void SfxBaseModel::MethodEntryCheck( const bool i_mustBeInitialized ) const
3069 if ( impl_isDisposed() )
3070 throw lang::DisposedException( OUString(), *const_cast< SfxBaseModel* >( this ) );
3071 if ( i_mustBeInitialized && !IsInitialized() )
3072 throw lang::NotInitializedException( OUString(), *const_cast< SfxBaseModel* >( this ) );
3075 bool SfxBaseModel::impl_isDisposed() const
3077 return ( m_pData == nullptr ) ;
3081 // private impl.
3084 OUString SfxBaseModel::GetMediumFilterName_Impl() const
3086 std::shared_ptr<const SfxFilter> pFilter;
3087 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
3088 if ( pMedium )
3089 pFilter = pMedium->GetFilter();
3091 if ( pFilter )
3092 return pFilter->GetName();
3094 return OUString();
3097 void SfxBaseModel::impl_store( const OUString& sURL ,
3098 const Sequence< beans::PropertyValue >& seqArguments ,
3099 bool bSaveTo )
3101 if( sURL.isEmpty() )
3102 throw frame::IllegalArgumentIOException();
3104 if (!m_pData->m_pObjectShell)
3105 return;
3107 ::comphelper::SequenceAsHashMap aArgHash(seqArguments);
3108 if ( !bSaveTo && !sURL.isEmpty()
3109 && !sURL.startsWith( "private:stream" )
3110 && ::utl::UCBContentHelper::EqualURLs( getLocation(), sURL ) )
3112 // this is the same file URL as the current document location, try to use storeOwn if possible
3114 static constexpr OUString aFilterString( u"FilterName"_ustr );
3115 const OUString aFilterName( aArgHash.getUnpackedValueOrDefault( aFilterString, OUString() ) );
3116 if ( !aFilterName.isEmpty() )
3118 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
3119 if ( pMedium )
3121 const std::shared_ptr<const SfxFilter>& pFilter = pMedium->GetFilter();
3122 if ( pFilter && aFilterName == pFilter->GetFilterName() )
3124 // #i119366# - If the former file saving with password, do not trying in StoreSelf anyway...
3125 bool bFormerPassword = false;
3127 uno::Sequence< beans::NamedValue > aOldEncryptionData;
3128 if (GetEncryptionData_Impl( &pMedium->GetItemSet(), aOldEncryptionData ))
3130 bFormerPassword = true;
3133 if ( !bFormerPassword )
3135 aArgHash.erase( aFilterString );
3136 aArgHash.erase( u"URL"_ustr );
3140 storeSelf( aArgHash.getAsConstPropertyValueList() );
3141 return;
3143 catch( const lang::IllegalArgumentException& )
3145 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
3146 // some additional arguments do not allow to use saving, SaveAs should be done
3147 // but only for normal documents, the shared documents would be overwritten in this case
3148 // that would mean an information loss
3149 // TODO/LATER: need a new interaction for this case
3150 if ( m_pData->m_pObjectShell->IsDocShared() )
3152 uno::Sequence< beans::NamedValue > aNewEncryptionData = aArgHash.getUnpackedValueOrDefault(u"EncryptionData"_ustr, uno::Sequence< beans::NamedValue >() );
3153 if ( !aNewEncryptionData.hasElements() )
3155 aNewEncryptionData = ::comphelper::OStorageHelper::CreatePackageEncryptionData( aArgHash.getUnpackedValueOrDefault(u"Password"_ustr, OUString()) );
3158 uno::Sequence< beans::NamedValue > aOldEncryptionData;
3159 (void)GetEncryptionData_Impl( &pMedium->GetItemSet(), aOldEncryptionData );
3161 if ( !aOldEncryptionData.hasElements() && !aNewEncryptionData.hasElements() )
3162 throw;
3163 else
3165 // if the password is changed a special error should be used in case of shared document
3166 throw task::ErrorCodeIOException(u"Can not change password for shared document."_ustr, uno::Reference< uno::XInterface >(), sal_uInt32(ERRCODE_SFX_SHARED_NOPASSWORDCHANGE) );
3169 #endif
3177 SfxGetpApp()->NotifyEvent( SfxEventHint( bSaveTo ? SfxEventHintId::SaveToDoc : SfxEventHintId::SaveAsDoc, GlobalEventConfig::GetEventName( bSaveTo ? GlobalEventId::SAVETODOC : GlobalEventId::SAVEASDOC ),
3178 m_pData->m_pObjectShell.get() ) );
3180 const OUString aFilterName(aArgHash.getUnpackedValueOrDefault(u"FilterName"_ustr, OUString()));
3181 OUString aPassword, aPasswordToModify;
3182 if (!aArgHash.getUnpackedValueOrDefault(u"EncryptionData"_ustr, Sequence<beans::NamedValue>())
3183 .hasElements())
3184 aPassword = aArgHash.getUnpackedValueOrDefault(u"Password"_ustr, OUString());
3185 if (!aArgHash.getUnpackedValueOrDefault(u"ModifyPasswordInfo"_ustr, Sequence<beans::PropertyValue>())
3186 .hasElements()
3187 && aArgHash.getUnpackedValueOrDefault(u"ModifyPasswordInfo"_ustr, static_cast<sal_Int32>(0)) == 0)
3188 aPasswordToModify = aArgHash.getUnpackedValueOrDefault(u"PasswordToModify"_ustr, OUString());
3189 aArgHash.erase(u"PasswordToModify"_ustr);
3191 std::optional<SfxAllItemSet> pItemSet(SfxGetpApp()->GetPool());
3192 pItemSet->Put(SfxStringItem(SID_FILE_NAME, sURL));
3193 if ( bSaveTo )
3194 pItemSet->Put(SfxBoolItem(SID_SAVETO, true));
3196 if (!aFilterName.isEmpty() && (!aPassword.isEmpty() || !aPasswordToModify.isEmpty()))
3197 sfx2::SetPassword(SfxGetpApp()->GetFilterMatcher().GetFilter4FilterName(aFilterName),
3198 &*pItemSet, aPassword, aPasswordToModify, false);
3200 TransformParameters(SID_SAVEASDOC, seqArguments, *pItemSet);
3202 const SfxBoolItem* pCopyStreamItem = pItemSet->GetItem<SfxBoolItem>(SID_COPY_STREAM_IF_POSSIBLE, false);
3204 if ( pCopyStreamItem && pCopyStreamItem->GetValue() && !bSaveTo )
3206 throw frame::IllegalArgumentIOException(
3207 u"CopyStreamIfPossible parameter is not acceptable for storeAsURL() call!"_ustr );
3210 sal_uInt32 nModifyPasswordHash = 0;
3211 Sequence< beans::PropertyValue > aModifyPasswordInfo;
3212 const SfxUnoAnyItem* pModifyPasswordInfoItem = pItemSet->GetItem<SfxUnoAnyItem>(SID_MODIFYPASSWORDINFO, false);
3213 if ( pModifyPasswordInfoItem )
3215 // it contains either a simple hash or a set of PropertyValues
3216 // TODO/LATER: the sequence of PropertyValue should replace the hash completely in future
3217 sal_Int32 nMPHTmp = 0;
3218 pModifyPasswordInfoItem->GetValue() >>= nMPHTmp;
3219 nModifyPasswordHash = static_cast<sal_uInt32>(nMPHTmp);
3220 pModifyPasswordInfoItem->GetValue() >>= aModifyPasswordInfo;
3222 pItemSet->ClearItem(SID_MODIFYPASSWORDINFO);
3223 sal_uInt32 nOldModifyPasswordHash = m_pData->m_pObjectShell->GetModifyPasswordHash();
3224 m_pData->m_pObjectShell->SetModifyPasswordHash( nModifyPasswordHash );
3225 Sequence< beans::PropertyValue > aOldModifyPasswordInfo = m_pData->m_pObjectShell->GetModifyPasswordInfo();
3226 m_pData->m_pObjectShell->SetModifyPasswordInfo( aModifyPasswordInfo );
3228 // since saving a document modifies its DocumentProperties, the current
3229 // DocumentProperties must be saved on "SaveTo", so it can be restored
3230 // after saving
3231 bool bCopyTo = bSaveTo ||
3232 m_pData->m_pObjectShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED;
3233 Reference<document::XDocumentProperties> xOldDocProps;
3234 if ( bCopyTo )
3236 xOldDocProps = getDocumentProperties();
3237 const Reference<util::XCloneable> xCloneable(xOldDocProps,
3238 UNO_QUERY_THROW);
3239 const Reference<document::XDocumentProperties> xNewDocProps(
3240 xCloneable->createClone(), UNO_QUERY_THROW);
3241 m_pData->m_xDocumentProperties = xNewDocProps;
3244 bool bRet = m_pData->m_pObjectShell->APISaveAs_Impl(sURL, *pItemSet, seqArguments);
3246 if ( bCopyTo )
3248 // restore DocumentProperties if a copy was created
3249 m_pData->m_xDocumentProperties = std::move(xOldDocProps);
3252 Reference < task::XInteractionHandler > xHandler;
3253 const SfxUnoAnyItem* pItem = pItemSet->GetItem<SfxUnoAnyItem>(SID_INTERACTIONHANDLER, false);
3254 if ( pItem )
3255 pItem->GetValue() >>= xHandler;
3257 pItemSet.reset();
3259 ErrCodeMsg nErrCode = m_pData->m_pObjectShell->GetErrorCode();
3260 if ( !bRet && !nErrCode )
3262 SAL_WARN("sfx.doc", "Storing has failed, no error is set!");
3263 nErrCode = ERRCODE_IO_CANTWRITE;
3265 m_pData->m_pObjectShell->ResetError();
3267 if ( bRet )
3269 if ( nErrCode )
3271 // must be a warning - use Interactionhandler if possible or abandon
3272 if ( xHandler.is() )
3274 // TODO/LATER: a general way to set the error context should be available
3275 SfxErrorContext aEc( ERRCTX_SFX_SAVEASDOC, m_pData->m_pObjectShell->GetTitle() );
3277 task::ErrorCodeRequest2 aErrorCode(OUString(), uno::Reference<XInterface>(),
3278 sal_Int32(sal_uInt32(nErrCode.GetCode())), nErrCode.GetArg1(), nErrCode.GetArg2(),
3279 static_cast<sal_Int16>(nErrCode.GetDialogMask()));
3280 SfxMedium::CallApproveHandler( xHandler, Any( aErrorCode ), false );
3284 if ( !bSaveTo )
3286 m_pData->m_aPreusedFilterName = GetMediumFilterName_Impl();
3287 m_pData->m_pObjectShell->SetModifyPasswordEntered();
3289 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::SaveAsDocDone, GlobalEventConfig::GetEventName(GlobalEventId::SAVEASDOCDONE), m_pData->m_pObjectShell.get() ) );
3291 else
3293 m_pData->m_pObjectShell->SetModifyPasswordHash( nOldModifyPasswordHash );
3294 m_pData->m_pObjectShell->SetModifyPasswordInfo( aOldModifyPasswordInfo );
3296 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::SaveToDocDone, GlobalEventConfig::GetEventName(GlobalEventId::SAVETODOCDONE), m_pData->m_pObjectShell.get() ) );
3299 else
3301 m_pData->m_pObjectShell->SetModifyPasswordHash( nOldModifyPasswordHash );
3302 m_pData->m_pObjectShell->SetModifyPasswordInfo( aOldModifyPasswordInfo );
3305 SfxGetpApp()->NotifyEvent( SfxEventHint( bSaveTo ? SfxEventHintId::SaveToDocFailed : SfxEventHintId::SaveAsDocFailed, GlobalEventConfig::GetEventName( bSaveTo ? GlobalEventId::SAVETODOCFAILED : GlobalEventId::SAVEASDOCFAILED),
3306 m_pData->m_pObjectShell.get() ) );
3308 if (SfxViewShell* pNotifyView = comphelper::LibreOfficeKit::isActive() ? SfxViewShell::Current() : nullptr)
3309 pNotifyView->libreOfficeKitViewCallback(LOK_CALLBACK_EXPORT_FILE, "ERROR"_ostr);
3311 std::stringstream aErrCode;
3312 aErrCode << nErrCode;
3313 throw task::ErrorCodeIOException(
3314 "SfxBaseModel::impl_store <" + sURL + "> failed: " + OUString::fromUtf8(aErrCode.str()),
3315 Reference< XInterface >(), sal_uInt32(nErrCode.GetCode()));
3320 namespace {
3321 template< typename ListenerT, typename EventT >
3322 class NotifySingleListenerIgnoreRE
3324 private:
3325 typedef void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& );
3326 NotificationMethod m_pMethod;
3327 const EventT& m_rEvent;
3328 public:
3329 NotifySingleListenerIgnoreRE( NotificationMethod method, const EventT& event ) : m_pMethod( method ), m_rEvent( event ) { }
3331 void operator()( const Reference<ListenerT>& listener ) const
3335 (listener.get()->*m_pMethod)( m_rEvent );
3337 catch( RuntimeException& )
3339 // this exception is ignored to avoid problems with invalid listeners, the listener should be probably thrown away in future
3340 TOOLS_WARN_EXCEPTION("sfx.appl", "ignoring");
3344 } // anonymous namespace
3346 void SfxBaseModel::postEvent_Impl( const OUString& aName, const Reference< frame::XController2 >& xController, const Any& supplement )
3348 if (aName.isEmpty())
3350 SAL_WARN("sfx.doc", "postEvent_Impl: Empty event name!");
3351 return;
3354 // also make sure this object doesn't self-destruct while notifying
3355 rtl::Reference<SfxBaseModel> xHoldAlive(this);
3356 // keep m_pData alive, if notified target would dispose the document
3357 std::shared_ptr<IMPL_SfxBaseModel_DataContainer> xKeepAlive(m_pData);
3359 // object already disposed?
3360 if ( impl_isDisposed() )
3361 return;
3363 if ( xKeepAlive->m_aDocumentEventListeners2.getLength() )
3365 SAL_INFO("sfx.doc", "SfxDocumentEvent: " + aName);
3367 document::DocumentEvent aDocumentEvent( static_cast<frame::XModel*>(this), aName, xController, supplement );
3369 xKeepAlive->m_aDocumentEventListeners2.forEach(
3370 NotifySingleListenerIgnoreRE< document::XDocumentEventListener, document::DocumentEvent >(
3371 &document::XDocumentEventListener::documentEventOccured,
3372 aDocumentEvent ) );
3375 if ( xKeepAlive->m_aDocumentEventListeners1.getLength() )
3377 SAL_INFO("sfx.doc", "SfxEvent: " + aName);
3379 document::EventObject aEvent( static_cast<frame::XModel*>(this), aName );
3381 xKeepAlive->m_aDocumentEventListeners1.forEach(
3382 NotifySingleListenerIgnoreRE< document::XEventListener, document::EventObject >(
3383 &document::XEventListener::notifyEvent,
3384 aEvent ) );
3388 Reference < container::XIndexAccess > SAL_CALL SfxBaseModel::getViewData()
3390 SfxModelGuard aGuard( *this );
3392 if ( m_pData->m_pObjectShell.is() && !m_pData->m_contViewData.is() )
3394 SfxViewFrame *pActFrame = SfxViewFrame::Current();
3395 if ( !pActFrame || pActFrame->GetObjectShell() != m_pData->m_pObjectShell.get() )
3396 pActFrame = SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get() );
3398 if ( !pActFrame || !pActFrame->GetViewShell() )
3399 // currently no frame for this document at all or View is under construction
3400 return Reference < container::XIndexAccess >();
3402 m_pData->m_contViewData = new comphelper::IndexedPropertyValuesContainer();
3404 if ( !m_pData->m_contViewData.is() )
3406 // error: no container class available!
3407 return Reference < container::XIndexAccess >();
3410 Reference < container::XIndexContainer > xCont( m_pData->m_contViewData, UNO_QUERY );
3411 sal_Int32 nCount = 0;
3412 Sequence < beans::PropertyValue > aSeq;
3413 for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get() ); pFrame;
3414 pFrame = SfxViewFrame::GetNext( *pFrame, m_pData->m_pObjectShell.get() ) )
3416 bool bIsActive = ( pFrame == pActFrame );
3417 pFrame->GetViewShell()->WriteUserDataSequence( aSeq );
3418 xCont->insertByIndex( bIsActive ? 0 : nCount, Any(aSeq) );
3419 nCount++;
3423 return m_pData->m_contViewData;
3426 void SAL_CALL SfxBaseModel::setViewData( const Reference < container::XIndexAccess >& aData )
3428 SfxModelGuard aGuard( *this );
3430 m_pData->m_contViewData = aData;
3433 /** calls all XEventListeners */
3434 void SfxBaseModel::notifyEvent( const document::EventObject& aEvent ) const
3436 // object already disposed?
3437 if ( impl_isDisposed() )
3438 return;
3440 if( !m_pData->m_aDocumentEventListeners1.getLength() )
3442 return;
3444 comphelper::OInterfaceIteratorHelper3 aIt( m_pData->m_aDocumentEventListeners1 );
3445 while( aIt.hasMoreElements() )
3449 aIt.next()->notifyEvent( aEvent );
3451 catch( RuntimeException& )
3453 aIt.remove();
3456 // for right now, we're only doing the event that this particular performance problem needed
3457 if (aEvent.EventName == "ShapeModified")
3459 uno::Reference<drawing::XShape> xShape(aEvent.Source, uno::UNO_QUERY);
3460 if (xShape.is())
3462 auto it = m_pData->maShapeListeners.find(xShape);
3463 if (it != m_pData->maShapeListeners.end())
3464 for (auto const & rListenerUnoRef : it->second)
3465 rListenerUnoRef->notifyShapeEvent(aEvent);
3470 /** returns true if someone added a XEventListener to this XEventBroadcaster */
3471 bool SfxBaseModel::hasEventListeners() const
3473 return !impl_isDisposed()
3474 && ( m_pData->m_aDocumentEventListeners1.getLength() != 0
3475 || !m_pData->maShapeListeners.empty());
3478 void SAL_CALL SfxBaseModel::addPrintJobListener( const Reference< view::XPrintJobListener >& xListener )
3480 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
3482 impl_getPrintHelper();
3483 if ( m_pData->m_xPrintable.is() )
3484 m_pData->m_xPrintable->addPrintJobListener( xListener );
3487 void SAL_CALL SfxBaseModel::removePrintJobListener( const Reference< view::XPrintJobListener >& xListener )
3489 SfxModelGuard aGuard( *this );
3491 impl_getPrintHelper();
3492 if ( m_pData->m_xPrintable.is() )
3493 m_pData->m_xPrintable->removePrintJobListener( xListener );
3496 sal_Int64 SAL_CALL SfxBaseModel::getSomething( const Sequence< sal_Int8 >& aIdentifier )
3498 SvGlobalName aName( aIdentifier );
3499 if (aName == SvGlobalName( SFX_GLOBAL_CLASSID ))
3501 SolarMutexGuard aGuard;
3502 SfxObjectShell *const pObjectShell(GetObjectShell());
3503 if (pObjectShell)
3505 return comphelper::getSomething_cast(pObjectShell);
3509 return 0;
3513 // XDocumentSubStorageSupplier
3516 void SfxBaseModel::ListenForStorage_Impl( const Reference< embed::XStorage >& xStorage )
3518 Reference< util::XModifiable > xModifiable( xStorage, UNO_QUERY );
3519 if ( xModifiable.is() )
3521 if ( !m_pData->m_pStorageModifyListen.is() )
3523 m_pData->m_pStorageModifyListen = new ::sfx2::DocumentStorageModifyListener( *m_pData, Application::GetSolarMutex() );
3526 // no need to deregister the listening for old storage since it should be disposed automatically
3527 xModifiable->addModifyListener( m_pData->m_pStorageModifyListen );
3531 Reference< embed::XStorage > SAL_CALL SfxBaseModel::getDocumentSubStorage( const OUString& aStorageName, sal_Int32 nMode )
3533 SfxModelGuard aGuard( *this );
3535 Reference< embed::XStorage > xResult;
3536 if ( m_pData->m_pObjectShell.is() )
3538 Reference< embed::XStorage > xStorage = m_pData->m_pObjectShell->GetStorage();
3539 if ( xStorage.is() )
3543 xResult = xStorage->openStorageElement( aStorageName, nMode );
3545 catch ( Exception& )
3551 return xResult;
3554 Sequence< OUString > SAL_CALL SfxBaseModel::getDocumentSubStoragesNames()
3556 SfxModelGuard aGuard( *this );
3558 Sequence< OUString > aResult;
3559 bool bSuccess = false;
3560 if ( m_pData->m_pObjectShell.is() )
3562 Reference < embed::XStorage > xStorage = m_pData->m_pObjectShell->GetStorage();
3563 if ( xStorage.is() )
3565 const Sequence< OUString > aTemp = xStorage->getElementNames();
3566 sal_Int32 nResultSize = 0;
3567 for ( const auto& rName : aTemp )
3569 if ( xStorage->isStorageElement( rName ) )
3571 aResult.realloc( ++nResultSize );
3572 aResult.getArray()[ nResultSize - 1 ] = rName;
3576 bSuccess = true;
3580 if ( !bSuccess )
3581 throw io::IOException();
3583 return aResult;
3587 // XScriptProviderSupplier
3590 Reference< script::provider::XScriptProvider > SAL_CALL SfxBaseModel::getScriptProvider()
3592 SfxModelGuard aGuard( *this );
3594 Reference< script::provider::XScriptProviderFactory > xScriptProviderFactory =
3595 script::provider::theMasterScriptProviderFactory::get( ::comphelper::getProcessComponentContext() );
3597 Reference< XScriptInvocationContext > xScriptContext( this );
3599 Reference< script::provider::XScriptProvider > xScriptProvider(
3600 xScriptProviderFactory->createScriptProvider( Any( xScriptContext ) ),
3601 UNO_SET_THROW );
3603 return xScriptProvider;
3607 // XUIConfigurationManagerSupplier
3610 OUString const & SfxBaseModel::getRuntimeUID() const
3612 OSL_ENSURE( !m_pData->m_sRuntimeUID.isEmpty(),
3613 "SfxBaseModel::getRuntimeUID - ID is empty!" );
3614 return m_pData->m_sRuntimeUID;
3617 bool SfxBaseModel::hasValidSignatures() const
3619 SolarMutexGuard aGuard;
3620 if ( m_pData->m_pObjectShell.is() )
3621 return ( m_pData->m_pObjectShell->ImplGetSignatureState() == SignatureState::OK );
3622 return false;
3625 void SfxBaseModel::getGrabBagItem(css::uno::Any& rVal) const
3627 if (m_pData->m_xGrabBagItem)
3628 m_pData->m_xGrabBagItem->QueryValue(rVal);
3629 else
3630 rVal <<= uno::Sequence<beans::PropertyValue>();
3633 void SfxBaseModel::setGrabBagItem(const css::uno::Any& rVal)
3635 if (!m_pData->m_xGrabBagItem)
3636 m_pData->m_xGrabBagItem = std::make_shared<SfxGrabBagItem>();
3638 m_pData->m_xGrabBagItem->PutValue(rVal, 0);
3641 static void GetCommandFromSequence( OUString& rCommand, sal_Int32& nIndex, const Sequence< beans::PropertyValue >& rSeqPropValue )
3643 nIndex = -1;
3645 auto pPropValue = std::find_if(rSeqPropValue.begin(), rSeqPropValue.end(),
3646 [](const beans::PropertyValue& rPropValue) { return rPropValue.Name == "Command"; });
3647 if (pPropValue != rSeqPropValue.end())
3649 pPropValue->Value >>= rCommand;
3650 nIndex = static_cast<sal_Int32>(std::distance(rSeqPropValue.begin(), pPropValue));
3654 static void ConvertSlotsToCommands( SfxObjectShell const * pDoc, Reference< container::XIndexContainer > const & rToolbarDefinition )
3656 if ( !pDoc )
3657 return;
3659 SfxModule* pModule( pDoc->GetFactory().GetModule() );
3660 Sequence< beans::PropertyValue > aSeqPropValue;
3662 for ( sal_Int32 i = 0; i < rToolbarDefinition->getCount(); i++ )
3664 if ( rToolbarDefinition->getByIndex( i ) >>= aSeqPropValue )
3666 OUString aCommand;
3667 sal_Int32 nIndex( -1 );
3668 GetCommandFromSequence( aCommand, nIndex, aSeqPropValue );
3669 if ( nIndex >= 0 && aCommand.startsWith( "slot:" ) )
3671 const sal_uInt16 nSlot = o3tl::toInt32(aCommand.subView( 5 ));
3673 // We have to replace the old "slot-Command" with our new ".uno:-Command"
3674 const SfxSlot* pSlot = pModule->GetSlotPool()->GetSlot( nSlot );
3675 if ( pSlot )
3677 aCommand = pSlot->GetCommand();
3678 aSeqPropValue.getArray()[nIndex].Value <<= aCommand;
3679 rToolbarDefinition->replaceByIndex( i, Any( aSeqPropValue ));
3686 Reference< ui::XUIConfigurationManager > SAL_CALL SfxBaseModel::getUIConfigurationManager()
3688 return Reference< ui::XUIConfigurationManager >( getUIConfigurationManager2(), UNO_QUERY_THROW );
3691 Reference< ui::XUIConfigurationManager2 > SfxBaseModel::getUIConfigurationManager2()
3693 SfxModelGuard aGuard( *this );
3695 if ( !m_pData->m_xUIConfigurationManager.is() )
3697 Reference< ui::XUIConfigurationManager2 > xNewUIConfMan =
3698 ui::UIConfigurationManager::create( comphelper::getProcessComponentContext() );
3700 Reference< embed::XStorage > xConfigStorage;
3702 OUString aUIConfigFolderName( u"Configurations2"_ustr );
3703 // First try to open with READWRITE and then READ
3704 xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, embed::ElementModes::READWRITE );
3705 if ( xConfigStorage.is() )
3707 static constexpr OUString aMediaTypeProp( u"MediaType"_ustr );
3708 OUString aMediaType;
3709 Reference< beans::XPropertySet > xPropSet( xConfigStorage, UNO_QUERY );
3710 Any a = xPropSet->getPropertyValue( aMediaTypeProp );
3711 if ( !( a >>= aMediaType ) || aMediaType.isEmpty())
3713 xPropSet->setPropertyValue( aMediaTypeProp, Any(u"application/vnd.sun.xml.ui.configuration"_ustr) );
3716 else
3717 xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, embed::ElementModes::READ );
3719 // initialize ui configuration manager with document substorage
3720 xNewUIConfMan->setStorage( xConfigStorage );
3722 // embedded objects did not support local configuration data until OOo 3.0, so there's nothing to
3723 // migrate
3724 if ( m_pData->m_pObjectShell->GetCreateMode() != SfxObjectCreateMode::EMBEDDED )
3726 // Import old UI configuration from OOo 1.x
3728 // Try to open with READ
3729 Reference< embed::XStorage > xOOo1ConfigStorage = getDocumentSubStorage( u"Configurations"_ustr, embed::ElementModes::READ );
3730 if ( xOOo1ConfigStorage.is() )
3732 const Reference< XComponentContext >& xContext( ::comphelper::getProcessComponentContext() );
3733 std::vector< Reference< container::XIndexContainer > > rToolbars;
3735 bool bImported = framework::UIConfigurationImporterOOo1x::ImportCustomToolbars(
3736 xNewUIConfMan, rToolbars, xContext, xOOo1ConfigStorage );
3737 if ( bImported )
3739 SfxObjectShell* pObjShell = SfxBaseModel::GetObjectShell();
3741 for ( size_t i = 0; i < rToolbars.size(); i++ )
3743 const OUString sId(OUString::number( i + 1 ));
3744 const OUString aCustomTbxName = "private:resource/toolbar/custom_OOo1x_" + sId;
3746 const Reference< container::XIndexContainer >& xToolbar = rToolbars[i];
3747 ConvertSlotsToCommands( pObjShell, xToolbar );
3748 if ( !xNewUIConfMan->hasSettings( aCustomTbxName ))
3750 // Set UIName for the toolbar with container property
3751 Reference< beans::XPropertySet > xPropSet( xToolbar, UNO_QUERY );
3752 if ( xPropSet.is() )
3756 xPropSet->setPropertyValue( u"UIName"_ustr, Any( "Toolbar " + sId ) );
3758 catch ( beans::UnknownPropertyException& )
3763 xNewUIConfMan->insertSettings( aCustomTbxName, xToolbar );
3764 xNewUIConfMan->store();
3771 m_pData->m_xUIConfigurationManager = std::move(xNewUIConfMan);
3774 return m_pData->m_xUIConfigurationManager;
3778 // XVisualObject
3781 void SAL_CALL SfxBaseModel::setVisualAreaSize( sal_Int64 nAspect, const awt::Size& aSize )
3783 SfxModelGuard aGuard( *this );
3785 if ( !m_pData->m_pObjectShell.is() )
3786 throw Exception(u"no object shell"_ustr, nullptr); // TODO: error handling
3788 SfxViewFrame* pViewFrm = SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get(), false );
3789 if ( pViewFrm && m_pData->m_pObjectShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED && !pViewFrm->GetFrame().IsInPlace() )
3791 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( pViewFrm->GetFrame().GetFrameInterface()->getContainerWindow() );
3792 Size aWinSize = pWindow->GetSizePixel();
3793 awt::Size aCurrent = getVisualAreaSize( nAspect );
3794 Size aDiff( aSize.Width-aCurrent.Width, aSize.Height-aCurrent.Height );
3795 aDiff = pViewFrm->GetViewShell()->GetWindow()->LogicToPixel( aDiff );
3796 aWinSize.AdjustWidth(aDiff.Width() );
3797 aWinSize.AdjustHeight(aDiff.Height() );
3798 pWindow->SetSizePixel( aWinSize );
3800 else
3802 tools::Rectangle aTmpRect = m_pData->m_pObjectShell->GetVisArea( ASPECT_CONTENT );
3803 aTmpRect.SetSize( Size( aSize.Width, aSize.Height ) );
3804 m_pData->m_pObjectShell->SetVisArea( aTmpRect );
3808 awt::Size SAL_CALL SfxBaseModel::getVisualAreaSize( sal_Int64 /*nAspect*/ )
3810 SfxModelGuard aGuard( *this );
3812 if ( !m_pData->m_pObjectShell.is() )
3813 throw Exception(u"no object shell"_ustr, nullptr); // TODO: error handling
3815 tools::Rectangle aTmpRect = m_pData->m_pObjectShell->GetVisArea( ASPECT_CONTENT );
3817 return awt::Size( aTmpRect.GetWidth(), aTmpRect.GetHeight() );
3821 sal_Int32 SAL_CALL SfxBaseModel::getMapUnit( sal_Int64 /*nAspect*/ )
3823 SfxModelGuard aGuard( *this );
3825 if ( !m_pData->m_pObjectShell.is() )
3826 throw Exception(u"no object shell"_ustr, nullptr); // TODO: error handling
3828 return VCLUnoHelper::VCL2UnoEmbedMapUnit( m_pData->m_pObjectShell->GetMapUnit() );
3831 embed::VisualRepresentation SAL_CALL SfxBaseModel::getPreferredVisualRepresentation( ::sal_Int64 /*nAspect*/ )
3833 SfxModelGuard aGuard( *this );
3835 datatransfer::DataFlavor aDataFlavor(
3836 u"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""_ustr,
3837 u"GDIMetaFile"_ustr,
3838 cppu::UnoType<Sequence< sal_Int8 >>::get() );
3840 embed::VisualRepresentation aVisualRepresentation;
3841 aVisualRepresentation.Data = getTransferData( aDataFlavor );
3842 aVisualRepresentation.Flavor = std::move(aDataFlavor);
3844 return aVisualRepresentation;
3848 // XStorageBasedDocument
3851 void SAL_CALL SfxBaseModel::loadFromStorage( const Reference< embed::XStorage >& xStorage,
3852 const Sequence< beans::PropertyValue >& aMediaDescriptor )
3854 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
3855 if ( IsInitialized() )
3856 throw frame::DoubleInitializationException( OUString(), *this );
3858 // after i36090 is fixed the pool from object shell can be used
3859 // SfxAllItemSet aSet( m_pData->m_pObjectShell->GetPool() );
3860 SfxAllItemSet aSet( SfxGetpApp()->GetPool() );
3862 // the BaseURL is part of the ItemSet
3863 SfxMedium* pMedium = new SfxMedium( xStorage, OUString() );
3864 TransformParameters( SID_OPENDOC, aMediaDescriptor, aSet );
3865 pMedium->GetItemSet().Put( aSet );
3867 // allow to use an interactionhandler (if there is one)
3868 pMedium->UseInteractionHandler( true );
3870 const SfxBoolItem* pTemplateItem = aSet.GetItem<SfxBoolItem>(SID_TEMPLATE, false);
3871 bool bTemplate = pTemplateItem && pTemplateItem->GetValue();
3872 m_pData->m_pObjectShell->SetActivateEvent_Impl( bTemplate ? SfxEventHintId::CreateDoc : SfxEventHintId::OpenDoc );
3873 m_pData->m_pObjectShell->Get_Impl()->bOwnsStorage = false;
3875 // load document
3876 if ( !m_pData->m_pObjectShell->DoLoad(pMedium) )
3878 ErrCodeMsg nError = m_pData->m_pObjectShell->GetErrorCode();
3879 nError = nError ? nError : ERRCODE_IO_CANTREAD;
3880 throw task::ErrorCodeIOException(
3881 "SfxBaseModel::loadFromStorage: " + nError.toString(),
3882 Reference< XInterface >(), sal_uInt32(nError.GetCode()));
3884 loadCmisProperties( );
3887 void SAL_CALL SfxBaseModel::storeToStorage( const Reference< embed::XStorage >& xStorage,
3888 const Sequence< beans::PropertyValue >& aMediaDescriptor )
3890 SfxModelGuard aGuard( *this );
3892 if ( !m_pData->m_pObjectShell.is() )
3893 throw io::IOException(); // TODO:
3895 auto xSet = std::make_shared<SfxAllItemSet>(m_pData->m_pObjectShell->GetPool());
3896 TransformParameters( SID_SAVEASDOC, aMediaDescriptor, *xSet );
3898 // TODO/LATER: maybe a special URL "private:storage" should be used
3899 const SfxStringItem* pItem = xSet->GetItem<SfxStringItem>(SID_FILTER_NAME, false);
3900 sal_Int32 nVersion = SOFFICE_FILEFORMAT_CURRENT;
3901 if( pItem )
3903 std::shared_ptr<const SfxFilter> pFilter = SfxGetpApp()->GetFilterMatcher().GetFilter4FilterName( pItem->GetValue() );
3904 if ( pFilter && pFilter->UsesStorage() )
3905 nVersion = pFilter->GetVersion();
3908 bool bSuccess = false;
3909 if ( xStorage == m_pData->m_pObjectShell->GetStorage() )
3911 // storing to the own storage
3912 bSuccess = m_pData->m_pObjectShell->DoSave();
3914 else
3916 // TODO/LATER: if the provided storage has some data inside the storing might fail, probably the storage must be truncated
3917 // TODO/LATER: is it possible to have a template here?
3918 m_pData->m_pObjectShell->SetupStorage( xStorage, nVersion, false );
3920 // BaseURL is part of the ItemSet
3921 SfxMedium aMedium( xStorage, OUString(), xSet );
3922 aMedium.CanDisposeStorage_Impl( false );
3923 if ( aMedium.GetFilter() )
3925 // storing without a valid filter will often crash
3926 bSuccess = m_pData->m_pObjectShell->DoSaveObjectAs( aMedium, true );
3927 m_pData->m_pObjectShell->DoSaveCompleted();
3931 ErrCodeMsg nError = m_pData->m_pObjectShell->GetErrorCode();
3932 m_pData->m_pObjectShell->ResetError();
3934 // the warnings are currently not transported
3935 if ( !bSuccess )
3937 nError = nError ? nError : ERRCODE_IO_GENERAL;
3938 throw task::ErrorCodeIOException(
3939 "SfxBaseModel::storeToStorage: " + nError.toString(),
3940 Reference< XInterface >(), sal_uInt32(nError.GetCode()));
3944 void SAL_CALL SfxBaseModel::switchToStorage( const Reference< embed::XStorage >& xStorage )
3946 SfxModelGuard aGuard( *this );
3948 if ( !m_pData->m_pObjectShell.is() )
3949 throw io::IOException(); // TODO:
3951 // the persistence should be switched only if the storage is different
3952 if ( xStorage != m_pData->m_pObjectShell->GetStorage() )
3954 if ( !m_pData->m_pObjectShell->SwitchPersistence( xStorage ) )
3956 ErrCodeMsg nError = m_pData->m_pObjectShell->GetErrorCode();
3957 nError = nError ? nError : ERRCODE_IO_GENERAL;
3958 throw task::ErrorCodeIOException(
3959 "SfxBaseModel::switchToStorage: " + nError.toString(),
3960 Reference< XInterface >(), sal_uInt32(nError.GetCode()));
3962 else
3964 // UICfgMgr has a reference to the old storage, update it
3965 getUIConfigurationManager2()->setStorage( xStorage );
3968 m_pData->m_pObjectShell->Get_Impl()->bOwnsStorage = false;
3971 Reference< embed::XStorage > SAL_CALL SfxBaseModel::getDocumentStorage()
3973 SfxModelGuard aGuard( *this );
3975 if ( !m_pData->m_pObjectShell.is() )
3976 throw io::IOException(); // TODO
3978 return m_pData->m_pObjectShell->GetStorage();
3981 void SAL_CALL SfxBaseModel::addStorageChangeListener(
3982 const Reference< document::XStorageChangeListener >& xListener )
3984 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
3986 m_pData->m_aStorageChangeListeners.addInterface( xListener );
3989 void SAL_CALL SfxBaseModel::removeStorageChangeListener(
3990 const Reference< document::XStorageChangeListener >& xListener )
3992 SfxModelGuard aGuard( *this );
3994 m_pData->m_aStorageChangeListeners.removeInterface( xListener );
3997 void SfxBaseModel::impl_getPrintHelper()
3999 if ( m_pData->m_xPrintable.is() )
4000 return;
4001 m_pData->m_xPrintable = new SfxPrintHelper();
4002 m_pData->m_xPrintable->initialize( { Any(Reference < frame::XModel > (this)) } );
4003 m_pData->m_xPrintable->addPrintJobListener( new SfxPrintHelperListener_Impl( m_pData.get() ) );
4007 // css.frame.XModule
4008 void SAL_CALL SfxBaseModel::setIdentifier(const OUString& Identifier)
4010 SfxModelGuard aGuard( *this );
4011 m_pData->m_sModuleIdentifier = Identifier;
4015 // css.frame.XModule
4016 OUString SAL_CALL SfxBaseModel::getIdentifier()
4018 SfxModelGuard aGuard( *this );
4019 if (!m_pData->m_sModuleIdentifier.isEmpty())
4020 return m_pData->m_sModuleIdentifier;
4021 if (m_pData->m_pObjectShell.is())
4022 return m_pData->m_pObjectShell->GetFactory().GetDocumentServiceName();
4023 return OUString();
4027 Reference< frame::XTitle > SfxBaseModel::impl_getTitleHelper ()
4029 SfxModelGuard aGuard( *this );
4031 if ( ! m_pData->m_xTitleHelper.is ())
4033 const Reference< XComponentContext >& xContext = ::comphelper::getProcessComponentContext();
4034 Reference< frame::XUntitledNumbers > xDesktop( frame::Desktop::create(xContext), UNO_QUERY_THROW);
4036 m_pData->m_xTitleHelper = new ::framework::TitleHelper(xContext, Reference< frame::XModel >(this), xDesktop);
4039 return m_pData->m_xTitleHelper;
4043 Reference< frame::XUntitledNumbers > SfxBaseModel::impl_getUntitledHelper ()
4045 SfxModelGuard aGuard( *this );
4047 if ( ! m_pData->m_xNumberedControllers.is ())
4049 m_pData->m_xNumberedControllers = new ::comphelper::NumberedCollection();
4050 m_pData->m_xNumberedControllers->setOwner (Reference< frame::XModel >(this));
4051 m_pData->m_xNumberedControllers->setUntitledPrefix (u" : "_ustr);
4054 return m_pData->m_xNumberedControllers;
4058 // css.frame.XTitle
4059 OUString SAL_CALL SfxBaseModel::getTitle()
4061 // SYNCHRONIZED ->
4062 SfxModelGuard aGuard( *this );
4064 OUString aResult = impl_getTitleHelper()->getTitle ();
4065 if ( !m_pData->m_bExternalTitle && m_pData->m_pObjectShell )
4067 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
4068 if ( pMedium )
4070 try {
4071 ::ucbhelper::Content aContent( pMedium->GetName(),
4072 utl::UCBContentHelper::getDefaultCommandEnvironment(),
4073 comphelper::getProcessComponentContext() );
4074 const Reference < beans::XPropertySetInfo > xProps
4075 = aContent.getProperties();
4076 if ( xProps.is() )
4078 static constexpr OUString aServerTitle( u"TitleOnServer"_ustr );
4079 if ( xProps->hasPropertyByName( aServerTitle ) )
4081 Any aAny = aContent.getPropertyValue( aServerTitle );
4082 aAny >>= aResult;
4086 catch (const ucb::ContentCreationException &)
4089 catch (const ucb::CommandAbortedException &)
4092 if (pMedium->IsRepairPackage())
4093 aResult += SfxResId(STR_REPAIREDDOCUMENT);
4096 if ( m_pData->m_pObjectShell->IsReadOnlyUI() || (pMedium && pMedium->IsReadOnly()) )
4097 aResult += SfxResId(STR_READONLY);
4098 else if ( m_pData->m_pObjectShell->IsDocShared() )
4099 aResult += SfxResId(STR_SHARED);
4101 if ( m_pData->m_pObjectShell->GetDocumentSignatureState() == SignatureState::OK )
4102 aResult += SfxResId(RID_XMLSEC_DOCUMENTSIGNED);
4105 return aResult;
4109 // css.frame.XTitle
4110 void SAL_CALL SfxBaseModel::setTitle( const OUString& sTitle )
4112 // SYNCHRONIZED ->
4113 SfxModelGuard aGuard( *this );
4115 impl_getTitleHelper()->setTitle (sTitle);
4116 m_pData->m_bExternalTitle = true;
4120 // css.frame.XTitleChangeBroadcaster
4121 void SAL_CALL SfxBaseModel::addTitleChangeListener( const Reference< frame::XTitleChangeListener >& xListener )
4123 // SYNCHRONIZED ->
4124 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
4126 Reference< frame::XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper(), UNO_QUERY);
4127 if (xBroadcaster.is ())
4128 xBroadcaster->addTitleChangeListener (xListener);
4132 // css.frame.XTitleChangeBroadcaster
4133 void SAL_CALL SfxBaseModel::removeTitleChangeListener( const Reference< frame::XTitleChangeListener >& xListener )
4135 // SYNCHRONIZED ->
4136 SfxModelGuard aGuard( *this );
4138 Reference< frame::XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper(), UNO_QUERY);
4139 if (xBroadcaster.is ())
4140 xBroadcaster->removeTitleChangeListener (xListener);
4144 // css.frame.XUntitledNumbers
4145 ::sal_Int32 SAL_CALL SfxBaseModel::leaseNumber( const Reference< XInterface >& xComponent )
4147 SfxModelGuard aGuard( *this );
4149 return impl_getUntitledHelper ()->leaseNumber (xComponent);
4153 // css.frame.XUntitledNumbers
4154 void SAL_CALL SfxBaseModel::releaseNumber( ::sal_Int32 nNumber )
4156 SfxModelGuard aGuard( *this );
4157 impl_getUntitledHelper ()->releaseNumber (nNumber);
4161 // css.frame.XUntitledNumbers
4162 void SAL_CALL SfxBaseModel::releaseNumberForComponent( const Reference< XInterface >& xComponent )
4164 SfxModelGuard aGuard( *this );
4165 impl_getUntitledHelper ()->releaseNumberForComponent (xComponent);
4169 // css.frame.XUntitledNumbers
4170 OUString SAL_CALL SfxBaseModel::getUntitledPrefix()
4172 SfxModelGuard aGuard( *this );
4173 return impl_getUntitledHelper ()->getUntitledPrefix ();
4177 // frame::XModel2
4178 Reference< container::XEnumeration > SAL_CALL SfxBaseModel::getControllers()
4180 SfxModelGuard aGuard( *this );
4182 sal_Int32 c = m_pData->m_seqControllers.size();
4183 Sequence< Any > lEnum(c);
4184 std::transform(m_pData->m_seqControllers.begin(), m_pData->m_seqControllers.end(),
4185 lEnum.getArray(), [](const auto& x) { return css::uno::Any(x); });
4187 return new ::comphelper::OAnyEnumeration(lEnum);
4191 // frame::XModel2
4192 Sequence< OUString > SAL_CALL SfxBaseModel::getAvailableViewControllerNames()
4194 SfxModelGuard aGuard( *this );
4196 const SfxObjectFactory& rDocumentFactory = GetObjectShell()->GetFactory();
4197 const sal_Int16 nViewFactoryCount = rDocumentFactory.GetViewFactoryCount();
4199 Sequence< OUString > aViewNames( nViewFactoryCount );
4200 auto aViewNamesRange = asNonConstRange(aViewNames);
4201 for ( sal_Int16 nViewNo = 0; nViewNo < nViewFactoryCount; ++nViewNo )
4202 aViewNamesRange[nViewNo] = rDocumentFactory.GetViewFactory( nViewNo ).GetAPIViewName();
4203 return aViewNames;
4207 // frame::XModel2
4208 Reference< frame::XController2 > SAL_CALL SfxBaseModel::createDefaultViewController( const Reference< frame::XFrame >& i_rFrame )
4210 SfxModelGuard aGuard( *this );
4212 const SfxObjectFactory& rDocumentFactory = GetObjectShell()->GetFactory();
4213 const OUString sDefaultViewName = rDocumentFactory.GetViewFactory().GetAPIViewName();
4215 aGuard.clear();
4217 return createViewController( sDefaultViewName, Sequence< PropertyValue >(), i_rFrame );
4221 namespace sfx::intern {
4223 /** a class which, in its dtor, cleans up various objects (well, at the moment only the frame) collected during
4224 the creation of a document view, unless the creation was successful.
4226 class ViewCreationGuard
4228 public:
4229 ViewCreationGuard()
4230 :m_bSuccess( false )
4234 ~ViewCreationGuard()
4236 if ( !m_bSuccess && m_aWeakFrame && !m_aWeakFrame->GetCurrentDocument() )
4238 m_aWeakFrame->SetFrameInterface_Impl( nullptr );
4239 m_aWeakFrame->DoClose();
4243 void takeFrameOwnership( SfxFrame* i_pFrame )
4245 OSL_PRECOND( !m_aWeakFrame, "ViewCreationGuard::takeFrameOwnership: already have a frame!" );
4246 OSL_PRECOND( i_pFrame != nullptr, "ViewCreationGuard::takeFrameOwnership: invalid frame!" );
4247 m_aWeakFrame = i_pFrame;
4250 void releaseAll()
4252 m_bSuccess = true;
4255 private:
4256 bool m_bSuccess;
4257 SfxFrameWeakRef m_aWeakFrame;
4262 SfxViewFrame* SfxBaseModel::FindOrCreateViewFrame_Impl( const Reference< XFrame >& i_rFrame, ::sfx::intern::ViewCreationGuard& i_rGuard ) const
4264 SfxViewFrame* pViewFrame = nullptr;
4265 for ( pViewFrame = SfxViewFrame::GetFirst( GetObjectShell(), false );
4266 pViewFrame;
4267 pViewFrame= SfxViewFrame::GetNext( *pViewFrame, GetObjectShell(), false )
4270 if ( pViewFrame->GetFrame().GetFrameInterface() == i_rFrame )
4271 break;
4273 if ( !pViewFrame )
4275 #if OSL_DEBUG_LEVEL > 0
4276 for ( SfxFrame* pCheckFrame = SfxFrame::GetFirst();
4277 pCheckFrame;
4278 pCheckFrame = SfxFrame::GetNext( *pCheckFrame )
4281 if ( pCheckFrame->GetFrameInterface() == i_rFrame )
4283 if ( ( pCheckFrame->GetCurrentViewFrame() != nullptr )
4284 || ( pCheckFrame->GetCurrentDocument() != nullptr )
4286 // Note that it is perfectly legitimate that during loading into an XFrame which already contains
4287 // a document, there exist two SfxFrame instances bound to this XFrame - the old one, which will be
4288 // destroyed later, and the new one, which we're going to create
4289 continue;
4291 OSL_FAIL( "SfxBaseModel::FindOrCreateViewFrame_Impl: there already is an SfxFrame for the given XFrame, but no view in it!" );
4292 // nowadays, we're the only instance allowed to create an SfxFrame for an XFrame, so this case here should not happen
4293 break;
4296 #endif
4298 SfxFrame* pTargetFrame = SfxFrame::Create( i_rFrame );
4299 ENSURE_OR_THROW( pTargetFrame, "could not create an SfxFrame" );
4300 i_rGuard.takeFrameOwnership( pTargetFrame );
4302 // prepare it
4303 pTargetFrame->PrepareForDoc_Impl( *GetObjectShell() );
4305 // create view frame
4306 pViewFrame = new SfxViewFrame( *pTargetFrame, GetObjectShell() );
4308 return pViewFrame;
4312 // frame::XModel2
4313 Reference< frame::XController2 > SAL_CALL SfxBaseModel::createViewController(
4314 const OUString& i_rViewName, const Sequence< PropertyValue >& i_rArguments, const Reference< XFrame >& i_rFrame )
4316 SfxModelGuard aGuard( *this );
4318 if ( !i_rFrame.is() )
4319 throw lang::IllegalArgumentException( OUString(), *this, 3 );
4321 // find the proper SFX view factory
4322 SfxViewFactory* pViewFactory = GetObjectShell()->GetFactory().GetViewFactoryByViewName( i_rViewName );
4323 if ( !pViewFactory )
4324 throw IllegalArgumentException( OUString(), *this, 1 );
4326 // determine previous shell (used in some special cases)
4327 Reference< XController > xPreviousController( i_rFrame->getController() );
4328 const Reference< XModel > xMe( this );
4329 if ( ( xPreviousController.is() )
4330 && ( xMe != xPreviousController->getModel() )
4333 xPreviousController.clear();
4335 SfxViewShell* pOldViewShell = SfxViewShell::Get( xPreviousController );
4336 OSL_ENSURE( !xPreviousController.is() || ( pOldViewShell != nullptr ),
4337 "SfxBaseModel::createViewController: invalid old controller!" );
4339 // a guard which will clean up in case of failure
4340 ::sfx::intern::ViewCreationGuard aViewCreationGuard;
4342 // determine the ViewFrame belonging to the given XFrame
4343 SfxViewFrame* pViewFrame = FindOrCreateViewFrame_Impl( i_rFrame, aViewCreationGuard );
4344 assert(pViewFrame && "SfxBaseModel::createViewController: no frame");
4346 // delegate to SFX' view factory
4347 pViewFrame->GetBindings().ENTERREGISTRATIONS();
4348 SfxViewShell* pViewShell = pViewFactory->CreateInstance(*pViewFrame, pOldViewShell);
4349 pViewFrame->GetBindings().LEAVEREGISTRATIONS();
4350 ENSURE_OR_THROW( pViewShell, "invalid view shell provided by factory" );
4352 // by setting the ViewShell it is prevented that disposing the Controller will destroy this ViewFrame also
4353 pViewFrame->GetDispatcher()->SetDisableFlags( SfxDisableFlags::NONE );
4354 pViewFrame->SetViewShell_Impl( pViewShell );
4356 // remember ViewID
4357 pViewFrame->SetCurViewId_Impl( pViewFactory->GetOrdinal() );
4359 // ensure a default controller, if the view shell did not provide an own implementation
4360 if ( !pViewShell->GetController().is() )
4361 pViewShell->SetController( new SfxBaseController( pViewShell ) );
4363 // pass the creation arguments to the controller
4364 SfxBaseController* pBaseController = pViewShell->GetBaseController_Impl();
4365 ENSURE_OR_THROW( pBaseController, "invalid controller implementation!" );
4366 pBaseController->SetCreationArguments_Impl( i_rArguments );
4368 // some initial view settings, coming from our most recent attachResource call
4369 ::comphelper::NamedValueCollection aDocumentLoadArgs( getArgs2( { u"ViewOnly"_ustr, u"PluginMode"_ustr } ) );
4370 if ( aDocumentLoadArgs.getOrDefault( u"ViewOnly"_ustr, false ) )
4371 pViewFrame->GetFrame().SetMenuBarOn_Impl( false );
4373 const sal_Int16 nPluginMode = aDocumentLoadArgs.getOrDefault( u"PluginMode"_ustr, sal_Int16( 0 ) );
4374 if ( nPluginMode == 1 )
4376 pViewFrame->ForceOuterResize_Impl();
4377 pViewFrame->GetBindings().HidePopups();
4379 SfxFrame& rFrame = pViewFrame->GetFrame();
4380 // MBA: layoutmanager of inplace frame starts locked and invisible
4381 rFrame.GetWorkWindow_Impl()->MakeVisible_Impl( false );
4382 rFrame.GetWorkWindow_Impl()->Lock_Impl( true );
4384 rFrame.GetWindow().SetBorderStyle( WindowBorderStyle::NOBORDER );
4385 pViewFrame->GetWindow().SetBorderStyle( WindowBorderStyle::NOBORDER );
4388 // tell the guard we were successful
4389 aViewCreationGuard.releaseAll();
4391 // outta here
4392 return pBaseController;
4396 // RDF DocumentMetadataAccess
4398 // rdf::XRepositorySupplier:
4399 Reference< rdf::XRepository > SAL_CALL
4400 SfxBaseModel::getRDFRepository()
4402 SfxModelGuard aGuard( *this );
4404 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4405 if (!xDMA.is()) {
4406 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4409 return xDMA->getRDFRepository();
4412 // rdf::XNode:
4413 OUString SAL_CALL
4414 SfxBaseModel::getStringValue()
4416 SfxModelGuard aGuard( *this );
4418 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4419 if (!xDMA.is()) {
4420 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4423 return xDMA->getStringValue();
4426 // rdf::XURI:
4427 OUString SAL_CALL
4428 SfxBaseModel::getNamespace()
4430 SfxModelGuard aGuard( *this );
4432 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4433 if (!xDMA.is()) {
4434 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4437 return xDMA->getNamespace();
4440 OUString SAL_CALL
4441 SfxBaseModel::getLocalName()
4443 SfxModelGuard aGuard( *this );
4445 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4446 if (!xDMA.is()) {
4447 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4450 return xDMA->getLocalName();
4453 // rdf::XDocumentMetadataAccess:
4454 Reference< rdf::XMetadatable > SAL_CALL
4455 SfxBaseModel::getElementByMetadataReference(
4456 const beans::StringPair & i_rReference)
4458 SfxModelGuard aGuard( *this );
4460 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4461 if (!xDMA.is()) {
4462 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4465 return xDMA->getElementByMetadataReference(i_rReference);
4468 Reference< rdf::XMetadatable > SAL_CALL
4469 SfxBaseModel::getElementByURI(const Reference< rdf::XURI > & i_xURI)
4471 SfxModelGuard aGuard( *this );
4473 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4474 if (!xDMA.is()) {
4475 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4478 return xDMA->getElementByURI(i_xURI);
4481 Sequence< Reference< rdf::XURI > > SAL_CALL
4482 SfxBaseModel::getMetadataGraphsWithType(
4483 const Reference<rdf::XURI> & i_xType)
4485 SfxModelGuard aGuard( *this );
4487 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4488 if (!xDMA.is()) {
4489 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4492 return xDMA->getMetadataGraphsWithType(i_xType);
4495 Reference<rdf::XURI> SAL_CALL
4496 SfxBaseModel::addMetadataFile(const OUString & i_rFileName,
4497 const Sequence < Reference< rdf::XURI > > & i_rTypes)
4499 SfxModelGuard aGuard( *this );
4501 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4502 if (!xDMA.is()) {
4503 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4506 return xDMA->addMetadataFile(i_rFileName, i_rTypes);
4509 Reference<rdf::XURI> SAL_CALL
4510 SfxBaseModel::importMetadataFile(::sal_Int16 i_Format,
4511 const Reference< io::XInputStream > & i_xInStream,
4512 const OUString & i_rFileName,
4513 const Reference< rdf::XURI > & i_xBaseURI,
4514 const Sequence < Reference< rdf::XURI > > & i_rTypes)
4516 SfxModelGuard aGuard( *this );
4518 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4519 if (!xDMA.is()) {
4520 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4523 return xDMA->importMetadataFile(i_Format,
4524 i_xInStream, i_rFileName, i_xBaseURI, i_rTypes);
4527 void SAL_CALL
4528 SfxBaseModel::removeMetadataFile(
4529 const Reference< rdf::XURI > & i_xGraphName)
4531 SfxModelGuard aGuard( *this );
4533 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4534 if (!xDMA.is()) {
4535 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4538 return xDMA->removeMetadataFile(i_xGraphName);
4541 void SAL_CALL
4542 SfxBaseModel::addContentOrStylesFile(const OUString & i_rFileName)
4544 SfxModelGuard aGuard( *this );
4546 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4547 if (!xDMA.is()) {
4548 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4551 return xDMA->addContentOrStylesFile(i_rFileName);
4554 void SAL_CALL
4555 SfxBaseModel::removeContentOrStylesFile(const OUString & i_rFileName)
4557 SfxModelGuard aGuard( *this );
4559 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4560 if (!xDMA.is()) {
4561 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4564 return xDMA->removeContentOrStylesFile(i_rFileName);
4567 void SAL_CALL
4568 SfxBaseModel::loadMetadataFromStorage(
4569 Reference< embed::XStorage > const & i_xStorage,
4570 Reference<rdf::XURI> const & i_xBaseURI,
4571 Reference<task::XInteractionHandler> const & i_xHandler)
4573 SfxModelGuard aGuard( *this );
4575 rtl::Reference<::sfx2::DocumentMetadataAccess> xDMA(
4576 m_pData->CreateDMAUninitialized());
4577 if (!xDMA.is()) {
4578 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4581 try {
4582 xDMA->loadMetadataFromStorage(i_xStorage, i_xBaseURI, i_xHandler);
4583 } catch (lang::IllegalArgumentException &) {
4584 throw; // not initialized
4585 } catch (Exception &) {
4586 // UGLY: if it's a RuntimeException, we can't be sure DMA is initialized
4587 m_pData->m_xDocumentMetadata = xDMA;
4588 throw;
4590 m_pData->m_xDocumentMetadata = std::move(xDMA);
4593 void SAL_CALL
4594 SfxBaseModel::storeMetadataToStorage(
4595 Reference< embed::XStorage > const & i_xStorage)
4597 SfxModelGuard aGuard( *this );
4599 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4600 if (!xDMA.is()) {
4601 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4604 return xDMA->storeMetadataToStorage(i_xStorage);
4607 void SAL_CALL
4608 SfxBaseModel::loadMetadataFromMedium(
4609 const Sequence< beans::PropertyValue > & i_rMedium)
4611 SfxModelGuard aGuard( *this );
4613 rtl::Reference<::sfx2::DocumentMetadataAccess> xDMA(
4614 m_pData->CreateDMAUninitialized());
4615 if (!xDMA.is()) {
4616 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4619 try {
4620 xDMA->loadMetadataFromMedium(i_rMedium);
4621 } catch (lang::IllegalArgumentException &) {
4622 throw; // not initialized
4623 } catch (Exception &) {
4624 // UGLY: if it's a RuntimeException, we can't be sure DMA is initialized
4625 m_pData->m_xDocumentMetadata = xDMA;
4626 throw;
4628 m_pData->m_xDocumentMetadata = std::move(xDMA);
4631 void SAL_CALL
4632 SfxBaseModel::storeMetadataToMedium(
4633 const Sequence< beans::PropertyValue > & i_rMedium)
4635 SfxModelGuard aGuard( *this );
4637 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4638 if (!xDMA.is()) {
4639 throw RuntimeException( u"model has no document metadata"_ustr, *this );
4642 return xDMA->storeMetadataToMedium(i_rMedium);
4646 // = SfxModelSubComponent
4649 SfxModelSubComponent::~SfxModelSubComponent()
4653 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */