1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <memory>
21 #include <config_features.h>
22
23 #include <sfx2/sfxbasemodel.hxx>
24
25 #include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp>
26 #include <com/sun/star/task/XInteractionHandler.hpp>
27 #include <com/sun/star/task/ErrorCodeIOException.hpp>
28 #include <com/sun/star/task/ErrorCodeRequest.hpp>
29 #include <com/sun/star/view/XSelectionSupplier.hpp>
30 #include <com/sun/star/view/XPrintJobListener.hpp>
31 #include <com/sun/star/lang/DisposedException.hpp>
32 #include <com/sun/star/lang/IllegalArgumentException.hpp>
33 #include <com/sun/star/lang/NoSupportException.hpp>
34 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
35 #include <com/sun/star/lang/NotInitializedException.hpp>
36 #include <com/sun/star/frame/Desktop.hpp>
37 #include <com/sun/star/frame/IllegalArgumentIOException.hpp>
38 #include <com/sun/star/frame/XUntitledNumbers.hpp>
39 #include <com/sun/star/frame/DoubleInitializationException.hpp>
40 #include <com/sun/star/embed/XTransactionBroadcaster.hpp>
41 #include <com/sun/star/embed/XStorage.hpp>
42 #include <com/sun/star/embed/EmbedMapUnits.hpp>
43 #include <com/sun/star/document/XStorageChangeListener.hpp>
44 #include <com/sun/star/document/XActionLockable.hpp>
45 #include <com/sun/star/document/IndexedPropertyValues.hpp>
46 #include <com/sun/star/beans/XPropertySet.hpp>
47 #include <com/sun/star/beans/XPropertySetInfo.hpp>
48 #include <com/sun/star/container/XIndexContainer.hpp>
49 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
50 #include <com/sun/star/script/provider/XScriptProvider.hpp>
51 #include <com/sun/star/ui/UIConfigurationManager.hpp>
52 #include <com/sun/star/embed/ElementModes.hpp>
53 #include <com/sun/star/embed/Aspects.hpp>
54 #include <com/sun/star/document/DocumentProperties.hpp>
55 #include <com/sun/star/frame/XTransientDocumentsDocumentContentFactory.hpp>
56 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
57 #include <com/sun/star/ucb/ContentCreationException.hpp>
58 #include <com/sun/star/ucb/CommandAbortedException.hpp>
59 #include <com/sun/star/util/XCloneable.hpp>
60 #include <com/sun/star/util/InvalidStateException.hpp>
61 #include <com/sun/star/util/CloseVetoException.hpp>
62 #include <comphelper/enumhelper.hxx>
63
64 #include <cppuhelper/implbase.hxx>
65 #include <cppuhelper/interfacecontainer.hxx>
66 #include <cppuhelper/exc_hlp.hxx>
67 #include <comphelper/processfactory.hxx>
68 #include <comphelper/sequenceashashmap.hxx>
69 #include <comphelper/namedvaluecollection.hxx>
70 #include <svl/itemset.hxx>
71 #include <svl/stritem.hxx>
72 #include <svl/eitem.hxx>
73 #include <svl/intitem.hxx>
74 #include <svl/grabbagitem.hxx>
75 #include <basic/sbx.hxx>
76 #include <basic/sbuno.hxx>
77 #include <tools/urlobj.hxx>
78 #include <tools/diagnose_ex.h>
79 #include <tools/svborder.hxx>
80 #include <unotools/tempfile.hxx>
81 #include <osl/mutex.hxx>
82 #include <vcl/errcode.hxx>
83 #include <vcl/salctype.hxx>
84 #include <vcl/gdimtf.hxx>
85 #include <comphelper/classids.hxx>
86 #include <sot/storinfo.hxx>
87 #include <comphelper/fileformat.h>
88 #include <comphelper/storagehelper.hxx>
89 #include <toolkit/helper/vclunohelper.hxx>
90 #include <vcl/transfer.hxx>
91 #include <svtools/ehdl.hxx>
92 #include <svtools/sfxecode.hxx>
93 #include <rtl/strbuf.hxx>
94 #include <sal/log.hxx>
95 #include <framework/configimporter.hxx>
96 #include <framework/interaction.hxx>
97 #include <framework/titlehelper.hxx>
98 #include <comphelper/numberedcollection.hxx>
99 #include <unotools/ucbhelper.hxx>
100 #include <ucbhelper/content.hxx>
101
102 #include <sfx2/sfxbasecontroller.hxx>
103 #include <sfx2/viewfac.hxx>
104 #include <workwin.hxx>
105 #include <sfx2/signaturestate.hxx>
106 #include <sfx2/sfxuno.hxx>
107 #include <objshimp.hxx>
108 #include <sfx2/viewfrm.hxx>
109 #include <sfx2/viewsh.hxx>
110 #include <sfx2/docfile.hxx>
111 #include <sfx2/docfilt.hxx>
112 #include <sfx2/dispatch.hxx>
113 #include <sfx2/module.hxx>
114 #include <sfx2/request.hxx>
115 #include <sfx2/printer.hxx>
116 #include <basic/basmgr.hxx>
117 #include <sfx2/event.hxx>
118 #include <eventsupplier.hxx>
119 #include <sfx2/evntconf.hxx>
120 #include <sfx2/sfxsids.hrc>
121 #include <sfx2/strings.hrc>
122 #include <sfx2/app.hxx>
123 #include <appdata.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 <comphelper/profilezone.hxx>
136 #include <vcl/threadex.hxx>
137 #include <unotools/mediadescriptor.hxx>
138
139 // namespaces
140
141
142 using namespace ::com::sun::star;
143 using namespace ::com::sun::star::uno;
144 using ::com::sun::star::beans::PropertyValue;
145 using ::com::sun::star::document::CmisProperty;
146 using ::com::sun::star::frame::XFrame;
147 using ::com::sun::star::frame::XController;
148 using ::com::sun::star::frame::XController2;
149 using ::com::sun::star::lang::IllegalArgumentException;
150 using ::com::sun::star::io::IOException;
151 using ::com::sun::star::lang::WrappedTargetException;
152 using ::com::sun::star::uno::Sequence;
153 using ::com::sun::star::document::XDocumentRecovery;
154 using ::com::sun::star::document::XUndoManager;
155 using ::com::sun::star::document::XUndoAction;
156 using ::com::sun::star::frame::XModel;
157
158 /** This Listener is used to get notified when the XDocumentProperties of the
159 XModel change.
160 */
161 class SfxDocInfoListener_Impl : public ::cppu::WeakImplHelper<
162 util::XModifyListener >
163 {
164
165 public:
166 SfxObjectShell& m_rShell;
167
SfxDocInfoListener_Impl(SfxObjectShell & i_rDoc)168 explicit SfxDocInfoListener_Impl( SfxObjectShell& i_rDoc )
169 : m_rShell(i_rDoc)
170 { };
171
172 virtual void SAL_CALL disposing( const lang::EventObject& ) override;
173 virtual void SAL_CALL modified( const lang::EventObject& ) override;
174 };
175
modified(const lang::EventObject &)176 void SAL_CALL SfxDocInfoListener_Impl::modified( const lang::EventObject& )
177 {
178 SolarMutexGuard aSolarGuard;
179
180 // notify changes to the SfxObjectShell
181 m_rShell.FlushDocInfo();
182 }
183
disposing(const lang::EventObject &)184 void SAL_CALL SfxDocInfoListener_Impl::disposing( const lang::EventObject& )
185 {
186 }
187
188
189 // impl. declarations
190
191
192 struct IMPL_SfxBaseModel_DataContainer : public ::sfx2::IModifiableDocument
193 {
194 // counter for SfxBaseModel instances created.
195 static sal_Int64 g_nInstanceCounter ;
196 SfxObjectShellRef m_pObjectShell ;
197 OUString m_sURL ;
198 OUString m_sRuntimeUID ;
199 OUString m_aPreusedFilterName ;
200 ::cppu::OMultiTypeInterfaceContainerHelper m_aInterfaceContainer ;
201 std::unordered_map<css::uno::Reference< css::drawing::XShape >,
202 std::vector<css::uno::Reference< css::document::XShapeEventListener >>> maShapeListeners;
203 Reference< XInterface > m_xParent ;
204 Reference< frame::XController > m_xCurrent ;
205 Reference< document::XDocumentProperties > m_xDocumentProperties ;
206 Reference< script::XStarBasicAccess > m_xStarBasicAccess ;
207 Reference< container::XNameReplace > m_xEvents ;
208 Sequence< beans::PropertyValue> m_seqArguments ;
209 std::vector< Reference< frame::XController > > m_seqControllers ;
210 Reference< container::XIndexAccess > m_contViewData ;
211 sal_uInt16 m_nControllerLockCount ;
212 bool m_bClosed ;
213 bool m_bClosing ;
214 bool m_bSaving ;
215 bool m_bSuicide ;
216 bool m_bExternalTitle ;
217 bool m_bModifiedSinceLastSave ;
218 Reference< view::XPrintable> m_xPrintable ;
219 Reference< ui::XUIConfigurationManager2 > m_xUIConfigurationManager;
220 ::rtl::Reference< ::sfx2::DocumentStorageModifyListener > m_pStorageModifyListen ;
221 OUString m_sModuleIdentifier ;
222 Reference< frame::XTitle > m_xTitleHelper ;
223 Reference< frame::XUntitledNumbers > m_xNumberedControllers ;
224 Reference< rdf::XDocumentMetadataAccess> m_xDocumentMetadata ;
225 ::rtl::Reference< ::sfx2::DocumentUndoManager > m_pDocumentUndoManager ;
226 Sequence< document::CmisProperty> m_cmisProperties ;
227 std::shared_ptr<SfxGrabBagItem> m_xGrabBagItem ;
228
IMPL_SfxBaseModel_DataContainerIMPL_SfxBaseModel_DataContainer229 IMPL_SfxBaseModel_DataContainer( ::osl::Mutex& rMutex, SfxObjectShell* pObjectShell )
230 : m_pObjectShell ( pObjectShell )
231 , m_aInterfaceContainer ( rMutex )
232 , m_nControllerLockCount ( 0 )
233 , m_bClosed ( false )
234 , m_bClosing ( false )
235 , m_bSaving ( false )
236 , m_bSuicide ( false )
237 , m_bExternalTitle ( false )
238 , m_bModifiedSinceLastSave( false )
239 , m_xTitleHelper ()
240 , m_xNumberedControllers ()
241 , m_xDocumentMetadata () // lazy
242 , m_pDocumentUndoManager ()
243 , m_cmisProperties ()
244 {
245 // increase global instance counter.
246 ++g_nInstanceCounter;
247 // set own Runtime UID
248 m_sRuntimeUID = OUString::number( g_nInstanceCounter );
249 }
250
~IMPL_SfxBaseModel_DataContainerIMPL_SfxBaseModel_DataContainer251 virtual ~IMPL_SfxBaseModel_DataContainer()
252 {
253 }
254
255 // ::sfx2::IModifiableDocument
storageIsModifiedIMPL_SfxBaseModel_DataContainer256 virtual void storageIsModified() override
257 {
258 if ( m_pObjectShell.is() && !m_pObjectShell->IsModified() )
259 m_pObjectShell->SetModified();
260 }
261
262 void impl_setDocumentProperties(
263 const Reference< document::XDocumentProperties >& );
264
GetDMAIMPL_SfxBaseModel_DataContainer265 Reference<rdf::XDocumentMetadataAccess> GetDMA()
266 {
267 if (!m_xDocumentMetadata.is())
268 {
269 OSL_ENSURE(m_pObjectShell.is(), "GetDMA: no object shell?");
270 if (!m_pObjectShell.is())
271 {
272 return nullptr;
273 }
274
275 const Reference<XComponentContext> xContext(
276 ::comphelper::getProcessComponentContext());
277 const Reference<frame::XModel> xModel(
278 m_pObjectShell->GetModel());
279 const Reference<lang::XMultiComponentFactory> xMsf(
280 xContext->getServiceManager());
281 const Reference<frame::
282 XTransientDocumentsDocumentContentFactory> xTDDCF(
283 xMsf->createInstanceWithContext(
284 "com.sun.star.frame.TransientDocumentsDocumentContentFactory",
285 xContext),
286 UNO_QUERY_THROW);
287 const Reference<ucb::XContent> xContent(
288 xTDDCF->createDocumentContent(xModel) );
289 OSL_ENSURE(xContent.is(), "GetDMA: cannot create DocumentContent");
290 if (!xContent.is())
291 {
292 return nullptr;
293 }
294 OUString uri = xContent->getIdentifier()->getContentIdentifier();
295 OSL_ENSURE(!uri.isEmpty(), "GetDMA: empty uri?");
296 if (!uri.isEmpty() && !uri.endsWith("/"))
297 {
298 uri += "/";
299 }
300
301 m_xDocumentMetadata = new ::sfx2::DocumentMetadataAccess(
302 xContext, *m_pObjectShell, uri);
303 }
304 return m_xDocumentMetadata;
305 }
306
CreateDMAUninitializedIMPL_SfxBaseModel_DataContainer307 Reference<rdf::XDocumentMetadataAccess> CreateDMAUninitialized()
308 {
309 return (m_pObjectShell.is())
310 ? new ::sfx2::DocumentMetadataAccess(
311 ::comphelper::getProcessComponentContext(), *m_pObjectShell)
312 : nullptr;
313 }
314 };
315
316 // static member initialization.
317 sal_Int64 IMPL_SfxBaseModel_DataContainer::g_nInstanceCounter = 0;
318
319
320 // Listener that forwards notifications from the PrintHelper to the "real" listeners
321 class SfxPrintHelperListener_Impl : public ::cppu::WeakImplHelper< view::XPrintJobListener >
322 {
323 public:
324 IMPL_SfxBaseModel_DataContainer* m_pData;
SfxPrintHelperListener_Impl(IMPL_SfxBaseModel_DataContainer * pData)325 explicit SfxPrintHelperListener_Impl( IMPL_SfxBaseModel_DataContainer* pData )
326 : m_pData( pData )
327 {}
328
329 virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) override ;
330 virtual void SAL_CALL printJobEvent( const view::PrintJobEvent& rEvent ) override;
331 };
332
disposing(const lang::EventObject &)333 void SAL_CALL SfxPrintHelperListener_Impl::disposing( const lang::EventObject& )
334 {
335 m_pData->m_xPrintable = nullptr;
336 }
337
printJobEvent(const view::PrintJobEvent & rEvent)338 void SAL_CALL SfxPrintHelperListener_Impl::printJobEvent( const view::PrintJobEvent& rEvent )
339 {
340 ::cppu::OInterfaceContainerHelper* pContainer = m_pData->m_aInterfaceContainer.getContainer( cppu::UnoType<view::XPrintJobListener>::get());
341 if ( pContainer!=nullptr )
342 {
343 ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
344 while (pIterator.hasMoreElements())
345 static_cast<view::XPrintJobListener*>(pIterator.next())->printJobEvent( rEvent );
346 }
347 }
348
349 // SfxOwnFramesLocker ====================================================================================
350 // allows to lock all the frames related to the provided SfxObjectShell
351 class SfxOwnFramesLocker
352 {
353 Sequence< Reference< frame::XFrame > > m_aLockedFrames;
354
355 static vcl::Window* GetVCLWindow( const Reference< frame::XFrame >& xFrame );
356 public:
357 explicit SfxOwnFramesLocker( SfxObjectShell const * ObjechShell );
358 ~SfxOwnFramesLocker();
359 };
360
SfxOwnFramesLocker(SfxObjectShell const * pObjectShell)361 SfxOwnFramesLocker::SfxOwnFramesLocker( SfxObjectShell const * pObjectShell )
362 {
363 if ( !pObjectShell )
364 return;
365
366 for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pObjectShell );
367 pFrame;
368 pFrame = SfxViewFrame::GetNext( *pFrame, pObjectShell )
369 )
370 {
371 SfxFrame& rSfxFrame = pFrame->GetFrame();
372 try
373 {
374 // get vcl window related to the frame and lock it if it is still not locked
375 const Reference< frame::XFrame >& xFrame = rSfxFrame.GetFrameInterface();
376 vcl::Window* pWindow = GetVCLWindow( xFrame );
377 if ( !pWindow )
378 throw RuntimeException();
379
380 if ( pWindow->IsEnabled() )
381 {
382 pWindow->Disable();
383
384 try
385 {
386 sal_Int32 nLen = m_aLockedFrames.getLength();
387 m_aLockedFrames.realloc( nLen + 1 );
388 m_aLockedFrames[nLen] = xFrame;
389 }
390 catch( Exception& )
391 {
392 pWindow->Enable();
393 throw;
394 }
395 }
396 }
397 catch( Exception& )
398 {
399 OSL_FAIL( "Not possible to lock the frame window!" );
400 }
401 }
402 }
403
~SfxOwnFramesLocker()404 SfxOwnFramesLocker::~SfxOwnFramesLocker()
405 {
406 for ( auto& rFrame : m_aLockedFrames )
407 {
408 try
409 {
410 if ( rFrame.is() )
411 {
412 // get vcl window related to the frame and unlock it
413 vcl::Window* pWindow = GetVCLWindow( rFrame );
414 if ( !pWindow )
415 throw RuntimeException();
416
417 pWindow->Enable();
418
419 rFrame.clear();
420 }
421 }
422 catch( Exception& )
423 {
424 OSL_FAIL( "Can't unlock the frame window!" );
425 }
426 }
427 }
428
GetVCLWindow(const Reference<frame::XFrame> & xFrame)429 vcl::Window* SfxOwnFramesLocker::GetVCLWindow( const Reference< frame::XFrame >& xFrame )
430 {
431 VclPtr<vcl::Window> pWindow;
432
433 if ( xFrame.is() )
434 {
435 Reference< awt::XWindow > xWindow = xFrame->getContainerWindow();
436 if ( xWindow.is() )
437 pWindow = VCLUnoHelper::GetWindow( xWindow );
438 }
439
440 return pWindow;
441 }
442
443 // SfxSaveGuard ====================================================================================
444 class SfxSaveGuard
445 {
446 private:
447 Reference< frame::XModel > m_xModel;
448 IMPL_SfxBaseModel_DataContainer* m_pData;
449 std::unique_ptr<SfxOwnFramesLocker> m_pFramesLock;
450
451 SfxSaveGuard(SfxSaveGuard const &) = delete;
452 void operator =(const SfxSaveGuard&) = delete;
453
454 public:
455 SfxSaveGuard(const Reference< frame::XModel >& xModel ,
456 IMPL_SfxBaseModel_DataContainer* pData);
457 ~SfxSaveGuard();
458 };
459
SfxSaveGuard(const Reference<frame::XModel> & xModel,IMPL_SfxBaseModel_DataContainer * pData)460 SfxSaveGuard::SfxSaveGuard(const Reference< frame::XModel >& xModel ,
461 IMPL_SfxBaseModel_DataContainer* pData)
462 : m_xModel ( xModel )
463 , m_pData ( pData )
464 {
465 if ( m_pData->m_bClosed )
466 throw lang::DisposedException("Object already disposed.");
467
468 m_pData->m_bSaving = true;
469 m_pFramesLock.reset(new SfxOwnFramesLocker( m_pData->m_pObjectShell.get() ));
470 }
471
~SfxSaveGuard()472 SfxSaveGuard::~SfxSaveGuard()
473 {
474 m_pFramesLock.reset();
475
476 m_pData->m_bSaving = false;
477
478 // m_bSuicide was set e.g. in case someone tried to close a document, while it was used for
479 // storing at the same time. Further m_bSuicide was set to sal_True only if close(sal_True) was called.
480 // So the ownership was delegated to the place where a veto exception was thrown.
481 // Now we have to call close() again and delegate the ownership to the next one, which
482 // can't accept that. Close(sal_False) can't work in this case. Because then the document will may be never closed...
483
484 if ( !m_pData->m_bSuicide )
485 return;
486
487 // Reset this state. In case the new close() request is not accepted by someone else...
488 // it's not a good idea to have two "owners" for close.-)
489 m_pData->m_bSuicide = false;
490 try
491 {
492 Reference< util::XCloseable > xClose(m_xModel, UNO_QUERY);
493 if (xClose.is())
494 xClose->close(true);
495 }
496 catch(const util::CloseVetoException&)
497 {}
498 }
499
SfxBaseModel(SfxObjectShell * pObjectShell)500 SfxBaseModel::SfxBaseModel( SfxObjectShell *pObjectShell )
501 : BaseMutex()
502 , m_pData( new IMPL_SfxBaseModel_DataContainer( m_aMutex, pObjectShell ) )
503 , m_bSupportEmbeddedScripts( pObjectShell && pObjectShell->Get_Impl() && !pObjectShell->Get_Impl()->m_bNoBasicCapabilities )
504 , m_bSupportDocRecovery( pObjectShell && pObjectShell->Get_Impl() && pObjectShell->Get_Impl()->m_bDocRecoverySupport )
505 {
506 if ( pObjectShell != nullptr )
507 {
508 StartListening( *pObjectShell ) ;
509 }
510 }
511
512 // destructor
~SfxBaseModel()513 SfxBaseModel::~SfxBaseModel()
514 {
515 }
516
517 // XInterface
queryInterface(const uno::Type & rType)518 Any SAL_CALL SfxBaseModel::queryInterface( const uno::Type& rType )
519 {
520 if ( ( !m_bSupportEmbeddedScripts && rType.equals( cppu::UnoType<document::XEmbeddedScripts>::get() ) )
521 || ( !m_bSupportDocRecovery && rType.equals( cppu::UnoType<XDocumentRecovery>::get() ) )
522 )
523 return Any();
524
525 return SfxBaseModel_Base::queryInterface( rType );
526 }
527
528 // XInterface
acquire()529 void SAL_CALL SfxBaseModel::acquire() throw( )
530 {
531 // Attention:
532 // Don't use mutex or guard in this method!!! Is a method of XInterface.
533
534 // Forward to baseclass
535 OWeakObject::acquire() ;
536 }
537
538
539 // XInterface
540
541
release()542 void SAL_CALL SfxBaseModel::release() throw( )
543 {
544 // Attention:
545 // Don't use mutex or guard in this method!!! Is a method of XInterface.
546
547 // Forward to baseclass
548 OWeakObject::release() ;
549 }
550
551
552 // XTypeProvider
553
554
555 namespace
556 {
lcl_stripType(Sequence<uno::Type> & io_rTypes,const uno::Type & i_rTypeToStrip)557 void lcl_stripType( Sequence< uno::Type >& io_rTypes, const uno::Type& i_rTypeToStrip )
558 {
559 Sequence< uno::Type > aStrippedTypes( io_rTypes.getLength() - 1 );
560 ::std::remove_copy_if(
561 io_rTypes.begin(),
562 io_rTypes.end(),
563 aStrippedTypes.getArray(),
564 [&i_rTypeToStrip](const uno::Type& aType) { return aType == i_rTypeToStrip; }
565 );
566 io_rTypes = aStrippedTypes;
567 }
568 }
569
getTypes()570 Sequence< uno::Type > SAL_CALL SfxBaseModel::getTypes()
571 {
572 Sequence< uno::Type > aTypes( SfxBaseModel_Base::getTypes() );
573
574 if ( !m_bSupportEmbeddedScripts )
575 lcl_stripType( aTypes, cppu::UnoType<document::XEmbeddedScripts>::get() );
576
577 if ( !m_bSupportDocRecovery )
578 lcl_stripType( aTypes, cppu::UnoType<XDocumentRecovery>::get() );
579
580 return aTypes;
581 }
582
583
584 // XTypeProvider
585
586
getImplementationId()587 Sequence< sal_Int8 > SAL_CALL SfxBaseModel::getImplementationId()
588 {
589 return css::uno::Sequence<sal_Int8>();
590 }
591
592
593 // XStarBasicAccess
594
595 #if HAVE_FEATURE_SCRIPTING
596
implGetStarBasicAccess(SfxObjectShell const * pObjectShell)597 static Reference< script::XStarBasicAccess > implGetStarBasicAccess( SfxObjectShell const * pObjectShell )
598 {
599 Reference< script::XStarBasicAccess > xRet;
600
601 #if !HAVE_FEATURE_SCRIPTING
602 (void) pObjectShell;
603 #else
604 if( pObjectShell )
605 {
606 BasicManager* pMgr = pObjectShell->GetBasicManager();
607 xRet = getStarBasicAccess( pMgr );
608 }
609 #endif
610 return xRet;
611 }
612
613 #endif
614
getLibraryContainer()615 Reference< container::XNameContainer > SAL_CALL SfxBaseModel::getLibraryContainer()
616 {
617 #if !HAVE_FEATURE_SCRIPTING
618 Reference< container::XNameContainer > dummy;
619
620 return dummy;
621 #else
622 SfxModelGuard aGuard( *this );
623
624 Reference< script::XStarBasicAccess >& rxAccess = m_pData->m_xStarBasicAccess;
625 if( !rxAccess.is() && m_pData->m_pObjectShell.is() )
626 rxAccess = implGetStarBasicAccess( m_pData->m_pObjectShell.get() );
627
628 Reference< container::XNameContainer > xRet;
629 if( rxAccess.is() )
630 xRet = rxAccess->getLibraryContainer();
631 return xRet;
632 #endif
633 }
634
635 /**___________________________________________________________________________________________________
636 @seealso XStarBasicAccess
637 */
createLibrary(const OUString & LibName,const OUString & Password,const OUString & ExternalSourceURL,const OUString & LinkTargetURL)638 void SAL_CALL SfxBaseModel::createLibrary( const OUString& LibName, const OUString& Password,
639 const OUString& ExternalSourceURL, const OUString& LinkTargetURL )
640 {
641 #if !HAVE_FEATURE_SCRIPTING
642 (void) LibName;
643 (void) Password;
644 (void) ExternalSourceURL;
645 (void) LinkTargetURL;
646 #else
647 SfxModelGuard aGuard( *this );
648
649 Reference< script::XStarBasicAccess >& rxAccess = m_pData->m_xStarBasicAccess;
650 if( !rxAccess.is() && m_pData->m_pObjectShell.is() )
651 rxAccess = implGetStarBasicAccess( m_pData->m_pObjectShell.get() );
652
653 if( rxAccess.is() )
654 rxAccess->createLibrary( LibName, Password, ExternalSourceURL, LinkTargetURL );
655 #endif
656 }
657
658 /**___________________________________________________________________________________________________
659 @seealso XStarBasicAccess
660 */
addModule(const OUString & LibraryName,const OUString & ModuleName,const OUString & Language,const OUString & Source)661 void SAL_CALL SfxBaseModel::addModule( const OUString& LibraryName, const OUString& ModuleName,
662 const OUString& Language, const OUString& Source )
663 {
664 #if !HAVE_FEATURE_SCRIPTING
665 (void) LibraryName;
666 (void) ModuleName;
667 (void) Language;
668 (void) Source;
669 #else
670 SfxModelGuard aGuard( *this );
671
672 Reference< script::XStarBasicAccess >& rxAccess = m_pData->m_xStarBasicAccess;
673 if( !rxAccess.is() && m_pData->m_pObjectShell.is() )
674 rxAccess = implGetStarBasicAccess( m_pData->m_pObjectShell.get() );
675
676 if( rxAccess.is() )
677 rxAccess->addModule( LibraryName, ModuleName, Language, Source );
678 #endif
679 }
680
681 /**___________________________________________________________________________________________________
682 @seealso XStarBasicAccess
683 */
addDialog(const OUString & LibraryName,const OUString & DialogName,const Sequence<sal_Int8> & Data)684 void SAL_CALL SfxBaseModel::addDialog( const OUString& LibraryName, const OUString& DialogName,
685 const Sequence< sal_Int8 >& Data )
686 {
687 #if !HAVE_FEATURE_SCRIPTING
688 (void) LibraryName;
689 (void) DialogName;
690 (void) Data;
691 #else
692 SfxModelGuard aGuard( *this );
693
694 Reference< script::XStarBasicAccess >& rxAccess = m_pData->m_xStarBasicAccess;
695 if( !rxAccess.is() && m_pData->m_pObjectShell.is() )
696 rxAccess = implGetStarBasicAccess( m_pData->m_pObjectShell.get() );
697
698 if( rxAccess.is() )
699 rxAccess->addDialog( LibraryName, DialogName, Data );
700 #endif
701 }
702
703
704 // XChild
705
706
getParent()707 Reference< XInterface > SAL_CALL SfxBaseModel::getParent()
708 {
709 SfxModelGuard aGuard( *this );
710
711 return m_pData->m_xParent;
712 }
713
714
715 // XChild
716
717
setParent(const Reference<XInterface> & Parent)718 void SAL_CALL SfxBaseModel::setParent(const Reference< XInterface >& Parent)
719 {
720 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
721 m_pData->m_xParent = Parent;
722 }
723
724
725 // XChild
726
727
dispose()728 void SAL_CALL SfxBaseModel::dispose()
729 {
730 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
731
732 if ( !m_pData->m_bClosed )
733 {
734 // gracefully accept wrong dispose calls instead of close call
735 // and try to make it work (may be really disposed later!)
736 try
737 {
738 close( true );
739 }
740 catch ( util::CloseVetoException& )
741 {
742 }
743
744 return;
745 }
746
747 if ( m_pData->m_pStorageModifyListen.is() )
748 {
749 m_pData->m_pStorageModifyListen->dispose();
750 m_pData->m_pStorageModifyListen = nullptr;
751 }
752
753 if ( m_pData->m_pDocumentUndoManager.is() )
754 {
755 m_pData->m_pDocumentUndoManager->disposing();
756 m_pData->m_pDocumentUndoManager = nullptr;
757 }
758
759 lang::EventObject aEvent( static_cast<frame::XModel *>(this) );
760 m_pData->m_aInterfaceContainer.disposeAndClear( aEvent );
761
762 m_pData->m_xDocumentProperties.clear();
763
764 m_pData->m_xDocumentMetadata.clear();
765
766 if ( m_pData->m_pObjectShell.is() )
767 {
768 EndListening( *m_pData->m_pObjectShell );
769 }
770
771 m_pData->m_xCurrent.clear();
772 m_pData->m_seqControllers.clear();
773
774 // m_pData member must be set to zero before delete is called to
775 // force disposed exception whenever someone tries to access our
776 // instance while in the dtor.
777 m_pData.reset();
778 }
779
780
781 // XChild
782
783
addEventListener(const Reference<lang::XEventListener> & aListener)784 void SAL_CALL SfxBaseModel::addEventListener( const Reference< lang::XEventListener >& aListener )
785 {
786 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
787 m_pData->m_aInterfaceContainer.addInterface( cppu::UnoType<lang::XEventListener>::get(), aListener );
788 }
789
790
791 // XChild
792
793
removeEventListener(const Reference<lang::XEventListener> & aListener)794 void SAL_CALL SfxBaseModel::removeEventListener( const Reference< lang::XEventListener >& aListener )
795 {
796 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
797 m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<lang::XEventListener>::get(), aListener );
798 }
799
800 void
impl_setDocumentProperties(const Reference<document::XDocumentProperties> & rxNewDocProps)801 IMPL_SfxBaseModel_DataContainer::impl_setDocumentProperties(
802 const Reference< document::XDocumentProperties >& rxNewDocProps)
803 {
804 m_xDocumentProperties.set(rxNewDocProps, UNO_SET_THROW);
805 if (m_pObjectShell.is())
806 {
807 Reference<util::XModifyBroadcaster> const xMB(
808 m_xDocumentProperties, UNO_QUERY_THROW);
809 xMB->addModifyListener(new SfxDocInfoListener_Impl(*m_pObjectShell));
810 }
811 }
812
813 // document::XDocumentPropertiesSupplier:
814 Reference< document::XDocumentProperties > SAL_CALL
getDocumentProperties()815 SfxBaseModel::getDocumentProperties()
816 {
817 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
818 if ( !m_pData->m_xDocumentProperties.is() )
819 {
820 Reference< document::XDocumentProperties > xDocProps(
821 document::DocumentProperties::create( ::comphelper::getProcessComponentContext() ) );
822 m_pData->impl_setDocumentProperties(xDocProps);
823 }
824
825 return m_pData->m_xDocumentProperties;
826 }
827
828
829 // lang::XEventListener
830
831
disposing(const lang::EventObject & aObject)832 void SAL_CALL SfxBaseModel::disposing( const lang::EventObject& aObject )
833 {
834 SolarMutexGuard aGuard;
835 if ( impl_isDisposed() )
836 return;
837
838 Reference< util::XModifyListener > xMod( aObject.Source, UNO_QUERY );
839 Reference< lang::XEventListener > xListener( aObject.Source, UNO_QUERY );
840 Reference< document::XEventListener > xDocListener( aObject.Source, UNO_QUERY );
841
842 if ( xMod.is() )
843 m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<util::XModifyListener>::get(), xMod );
844 else if ( xListener.is() )
845 m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<lang::XEventListener>::get(), xListener );
846 else if ( xDocListener.is() )
847 m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<document::XEventListener>::get(), xListener );
848 }
849
850
851 // frame::XModel
852
853
attachResource(const OUString & rURL,const Sequence<beans::PropertyValue> & rArgs)854 sal_Bool SAL_CALL SfxBaseModel::attachResource( const OUString& rURL ,
855 const Sequence< beans::PropertyValue >& rArgs )
856 {
857 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
858 if ( rURL.isEmpty() && rArgs.getLength() == 1 && rArgs[0].Name == "SetEmbedded" )
859 {
860 // allows to set a windowless document to EMBEDDED state
861 // but _only_ before load() or initNew() methods
862 if ( m_pData->m_pObjectShell.is() && !m_pData->m_pObjectShell->GetMedium() )
863 {
864 bool bEmb(false);
865 if ( ( rArgs[0].Value >>= bEmb ) && bEmb )
866 m_pData->m_pObjectShell->SetCreateMode_Impl( SfxObjectCreateMode::EMBEDDED );
867 }
868
869 return true;
870 }
871
872 if ( m_pData->m_pObjectShell.is() )
873 {
874 m_pData->m_sURL = rURL;
875
876 SfxObjectShell* pObjectShell = m_pData->m_pObjectShell.get();
877
878 ::comphelper::NamedValueCollection aArgs( rArgs );
879
880 Sequence< sal_Int32 > aWinExtent;
881 if ( ( aArgs.get( "WinExtent" ) >>= aWinExtent )&& ( aWinExtent.getLength() == 4 ) )
882 {
883 tools::Rectangle aVisArea( aWinExtent[0], aWinExtent[1], aWinExtent[2], aWinExtent[3] );
884 aVisArea = OutputDevice::LogicToLogic(aVisArea, MapMode(MapUnit::Map100thMM), MapMode(pObjectShell->GetMapUnit()));
885 pObjectShell->SetVisArea( aVisArea );
886 }
887
888 bool bBreakMacroSign = false;
889 if ( aArgs.get( "BreakMacroSignature" ) >>= bBreakMacroSign )
890 {
891 pObjectShell->BreakMacroSign_Impl( bBreakMacroSign );
892 }
893
894 bool bMacroEventRead = false;
895 if ((aArgs.get("MacroEventRead") >>= bMacroEventRead) && bMacroEventRead)
896 {
897 pObjectShell->SetMacroCallsSeenWhileLoading();
898 }
899
900 aArgs.remove( "WinExtent" );
901 aArgs.remove( "BreakMacroSignature" );
902 aArgs.remove( "MacroEventRead" );
903 aArgs.remove( "Stream" );
904 aArgs.remove( "InputStream" );
905 aArgs.remove( "URL" );
906 aArgs.remove( "Frame" );
907 aArgs.remove( "Password" );
908 aArgs.remove( "EncryptionData" );
909
910 // TODO/LATER: all the parameters that are accepted by ItemSet of the DocShell must be removed here
911
912 m_pData->m_seqArguments = aArgs.getPropertyValues();
913
914 SfxMedium* pMedium = pObjectShell->GetMedium();
915 if ( pMedium )
916 {
917 SfxAllItemSet aSet( pObjectShell->GetPool() );
918 TransformParameters( SID_OPENDOC, rArgs, aSet );
919
920 // the arguments are not allowed to reach the medium
921 aSet.ClearItem( SID_FILE_NAME );
922 aSet.ClearItem( SID_FILLFRAME );
923
924 pMedium->GetItemSet()->Put( aSet );
925 const SfxStringItem* pItem = aSet.GetItem<SfxStringItem>(SID_FILTER_NAME, false);
926 if ( pItem )
927 pMedium->SetFilter(
928 pObjectShell->GetFactory().GetFilterContainer()->GetFilter4FilterName( pItem->GetValue() ) );
929
930 const SfxStringItem* pTitleItem = aSet.GetItem<SfxStringItem>(SID_DOCINFO_TITLE, false);
931 if ( pTitleItem )
932 {
933 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pObjectShell );
934 if ( pFrame )
935 pFrame->UpdateTitle();
936 }
937 }
938 }
939
940 return true ;
941 }
942
943
944 // frame::XModel
945
946
getURL()947 OUString SAL_CALL SfxBaseModel::getURL()
948 {
949 SfxModelGuard aGuard( *this );
950 return m_pData->m_sURL ;
951 }
952
953
954 // frame::XModel
955
956
getArgs()957 Sequence< beans::PropertyValue > SAL_CALL SfxBaseModel::getArgs()
958 {
959 SfxModelGuard aGuard( *this );
960
961 if (!SfxApplication::Get()) // tdf#113755
962 {
963 SAL_WARN("sfx.appl", "Unexpected operations on model");
964 return m_pData->m_seqArguments;
965 }
966
967 if ( m_pData->m_pObjectShell.is() )
968 {
969 Sequence< beans::PropertyValue > seqArgsNew;
970 Sequence< beans::PropertyValue > seqArgsOld;
971 SfxAllItemSet aSet( m_pData->m_pObjectShell->GetPool() );
972
973 // we need to know which properties are supported by the transformer
974 // hopefully it is a temporary solution, I guess nonconvertable properties
975 // should not be supported so then there will be only ItemSet from medium
976
977 TransformItems( SID_OPENDOC, *(m_pData->m_pObjectShell->GetMedium()->GetItemSet()), seqArgsNew );
978 TransformParameters( SID_OPENDOC, m_pData->m_seqArguments, aSet );
979 TransformItems( SID_OPENDOC, aSet, seqArgsOld );
980
981 sal_Int32 nNewLength = seqArgsNew.getLength();
982
983 // "WinExtent" property should be updated always.
984 // We can store it now to overwrite an old value
985 // since it is not from ItemSet
986 tools::Rectangle aTmpRect = m_pData->m_pObjectShell->GetVisArea( ASPECT_CONTENT );
987 aTmpRect = OutputDevice::LogicToLogic(aTmpRect, MapMode(m_pData->m_pObjectShell->GetMapUnit()), MapMode(MapUnit::Map100thMM));
988
989 Sequence< sal_Int32 > aRectSeq(4);
990 aRectSeq[0] = aTmpRect.Left();
991 aRectSeq[1] = aTmpRect.Top();
992 aRectSeq[2] = aTmpRect.IsWidthEmpty() ? aTmpRect.Left() : aTmpRect.Right();
993 aRectSeq[3] = aTmpRect.IsHeightEmpty() ? aTmpRect.Top() : aTmpRect.Bottom();
994
995 seqArgsNew.realloc( ++nNewLength );
996 seqArgsNew[ nNewLength - 1 ].Name = "WinExtent";
997 seqArgsNew[ nNewLength - 1 ].Value <<= aRectSeq;
998
999 if ( !m_pData->m_aPreusedFilterName.isEmpty() )
1000 {
1001 seqArgsNew.realloc( ++nNewLength );
1002 seqArgsNew[ nNewLength - 1 ].Name = "PreusedFilterName";
1003 seqArgsNew[ nNewLength - 1 ].Value <<= m_pData->m_aPreusedFilterName;
1004 }
1005
1006 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get() );
1007 if ( pFrame )
1008 {
1009 SvBorder aBorder = pFrame->GetBorderPixelImpl();
1010
1011 Sequence< sal_Int32 > aBorderSeq(4);
1012 aBorderSeq[0] = aBorder.Left();
1013 aBorderSeq[1] = aBorder.Top();
1014 aBorderSeq[2] = aBorder.Right();
1015 aBorderSeq[3] = aBorder.Bottom();
1016
1017 seqArgsNew.realloc( ++nNewLength );
1018 seqArgsNew[ nNewLength - 1 ].Name = "DocumentBorder";
1019 seqArgsNew[ nNewLength - 1 ].Value <<= aBorderSeq;
1020 }
1021
1022 // only the values that are not supported by the ItemSet must be cached here
1023 Sequence< beans::PropertyValue > aFinalCache;
1024 sal_Int32 nFinalLength = 0;
1025
1026 for ( const auto& rOrg : std::as_const(m_pData->m_seqArguments) )
1027 {
1028 auto bNew = std::none_of(seqArgsOld.begin(), seqArgsOld.end(),
1029 [&rOrg](const beans::PropertyValue& rOld){ return rOld.Name == rOrg.Name; });
1030 if ( bNew )
1031 {
1032 // the entity with this name should be new for seqArgsNew
1033 // since it is not supported by transformer
1034
1035 seqArgsNew.realloc( ++nNewLength );
1036 seqArgsNew[ nNewLength - 1 ] = rOrg;
1037
1038 aFinalCache.realloc( ++nFinalLength );
1039 aFinalCache[ nFinalLength - 1 ] = rOrg;
1040 }
1041 }
1042
1043 m_pData->m_seqArguments = aFinalCache;
1044
1045 return seqArgsNew;
1046 }
1047
1048 return m_pData->m_seqArguments;
1049 }
1050
setArgs(const Sequence<beans::PropertyValue> & aArgs)1051 void SAL_CALL SfxBaseModel::setArgs(const Sequence<beans::PropertyValue>& aArgs)
1052 {
1053 SfxModelGuard aGuard( *this );
1054
1055 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
1056 if (!pMedium)
1057 {
1058 throw util::InvalidStateException(
1059 "Medium could not be retrieved, unable to execute setArgs");
1060 }
1061
1062 for (const auto& rArg : aArgs)
1063 {
1064 OUString sValue;
1065 bool bValue;
1066
1067 if (rArg.Name == "SuggestedSaveAsName")
1068 {
1069 rArg.Value >>= sValue;
1070 pMedium->GetItemSet()->Put(SfxStringItem(SID_SUGGESTEDSAVEASNAME, sValue));
1071 }
1072 else if (rArg.Name == "SuggestedSaveAsDir")
1073 {
1074 rArg.Value >>= sValue;
1075 pMedium->GetItemSet()->Put(SfxStringItem(SID_SUGGESTEDSAVEASDIR, sValue));
1076 }
1077 else if (rArg.Name == "LockContentExtraction")
1078 {
1079 rArg.Value >>= bValue;
1080 pMedium->GetItemSet()->Put(SfxBoolItem(SID_LOCK_CONTENT_EXTRACTION, bValue));
1081 }
1082 else if (rArg.Name == "LockExport")
1083 {
1084 rArg.Value >>= bValue;
1085 pMedium->GetItemSet()->Put(SfxBoolItem(SID_LOCK_EXPORT, bValue));
1086 }
1087 else if (rArg.Name == "LockPrint")
1088 {
1089 rArg.Value >>= bValue;
1090 pMedium->GetItemSet()->Put(SfxBoolItem(SID_LOCK_PRINT, bValue));
1091 }
1092 else if (rArg.Name == "LockSave")
1093 {
1094 rArg.Value >>= bValue;
1095 pMedium->GetItemSet()->Put(SfxBoolItem(SID_LOCK_SAVE, bValue));
1096 }
1097 else if (rArg.Name == "LockEditDoc")
1098 {
1099 rArg.Value >>= bValue;
1100 pMedium->GetItemSet()->Put(SfxBoolItem(SID_LOCK_EDITDOC, bValue));
1101 }
1102 else if (rArg.Name == "Replaceable")
1103 {
1104 rArg.Value >>= bValue;
1105 pMedium->GetItemSet()->Put(SfxBoolItem(SID_REPLACEABLE, bValue));
1106 }
1107 else
1108 {
1109 throw lang::IllegalArgumentException("Setting property not supported: " + rArg.Name,
1110 comphelper::getProcessComponentContext(), 0);
1111 }
1112 }
1113 }
1114
1115 // frame::XModel
1116
1117
connectController(const Reference<frame::XController> & xController)1118 void SAL_CALL SfxBaseModel::connectController( const Reference< frame::XController >& xController )
1119 {
1120 SfxModelGuard aGuard( *this );
1121 OSL_PRECOND( xController.is(), "SfxBaseModel::connectController: invalid controller!" );
1122 if ( !xController.is() )
1123 return;
1124
1125 m_pData->m_seqControllers.push_back(xController);
1126
1127 if ( m_pData->m_seqControllers.size() == 1 )
1128 {
1129 SfxViewFrame* pViewFrame = SfxViewFrame::Get( xController, GetObjectShell() );
1130 ENSURE_OR_THROW( pViewFrame, "SFX document without SFX view!?" );
1131 pViewFrame->UpdateDocument_Impl();
1132 const OUString sDocumentURL = GetObjectShell()->GetMedium()->GetName();
1133 if ( !sDocumentURL.isEmpty() )
1134 SfxGetpApp()->Broadcast( SfxOpenUrlHint( sDocumentURL ) );
1135 }
1136 }
1137
1138
1139 // frame::XModel
1140
1141
disconnectController(const Reference<frame::XController> & xController)1142 void SAL_CALL SfxBaseModel::disconnectController( const Reference< frame::XController >& xController )
1143 {
1144 SfxModelGuard aGuard( *this );
1145
1146 if ( m_pData->m_seqControllers.empty() )
1147 return;
1148
1149 auto& vec = m_pData->m_seqControllers;
1150 vec.erase(std::remove(vec.begin(), vec.end(), xController), vec.end());
1151
1152 if ( xController == m_pData->m_xCurrent )
1153 m_pData->m_xCurrent.clear();
1154 }
1155
1156 namespace
1157 {
1158 class ControllerLockUndoAction : public ::cppu::WeakImplHelper< XUndoAction >
1159 {
1160 public:
ControllerLockUndoAction(const Reference<XModel> & i_model,const bool i_undoIsUnlock)1161 ControllerLockUndoAction( const Reference< XModel >& i_model, const bool i_undoIsUnlock )
1162 :m_xModel( i_model )
1163 ,m_bUndoIsUnlock( i_undoIsUnlock )
1164 {
1165 }
1166
1167 // XUndoAction
1168 virtual OUString SAL_CALL getTitle() override;
1169 virtual void SAL_CALL undo( ) override;
1170 virtual void SAL_CALL redo( ) override;
1171
1172 private:
1173 const Reference< XModel > m_xModel;
1174 const bool m_bUndoIsUnlock;
1175 };
1176
getTitle()1177 OUString SAL_CALL ControllerLockUndoAction::getTitle()
1178 {
1179 // this action is intended to be used within an UndoContext only, so nobody will ever see this title ...
1180 return OUString();
1181 }
1182
undo()1183 void SAL_CALL ControllerLockUndoAction::undo( )
1184 {
1185 if ( m_bUndoIsUnlock )
1186 m_xModel->unlockControllers();
1187 else
1188 m_xModel->lockControllers();
1189 }
1190
redo()1191 void SAL_CALL ControllerLockUndoAction::redo( )
1192 {
1193 if ( m_bUndoIsUnlock )
1194 m_xModel->lockControllers();
1195 else
1196 m_xModel->unlockControllers();
1197 }
1198 }
1199
1200
1201 // frame::XModel
1202
1203
lockControllers()1204 void SAL_CALL SfxBaseModel::lockControllers()
1205 {
1206 SfxModelGuard aGuard( *this );
1207
1208 ++m_pData->m_nControllerLockCount ;
1209
1210 if ( m_pData->m_pDocumentUndoManager.is()
1211 && m_pData->m_pDocumentUndoManager->isInContext()
1212 && !m_pData->m_pDocumentUndoManager->isLocked()
1213 )
1214 {
1215 m_pData->m_pDocumentUndoManager->addUndoAction( new ControllerLockUndoAction( this, true ) );
1216 }
1217 }
1218
1219
1220 // frame::XModel
1221
1222
unlockControllers()1223 void SAL_CALL SfxBaseModel::unlockControllers()
1224 {
1225 SfxModelGuard aGuard( *this );
1226
1227 --m_pData->m_nControllerLockCount ;
1228
1229 if ( m_pData->m_pDocumentUndoManager.is()
1230 && m_pData->m_pDocumentUndoManager->isInContext()
1231 && !m_pData->m_pDocumentUndoManager->isLocked()
1232 )
1233 {
1234 m_pData->m_pDocumentUndoManager->addUndoAction( new ControllerLockUndoAction( this, false ) );
1235 }
1236 }
1237
1238
1239 // frame::XModel
1240
1241
hasControllersLocked()1242 sal_Bool SAL_CALL SfxBaseModel::hasControllersLocked()
1243 {
1244 SfxModelGuard aGuard( *this );
1245 return ( m_pData->m_nControllerLockCount != 0 ) ;
1246 }
1247
1248
1249 // frame::XModel
1250
1251
getCurrentController()1252 Reference< frame::XController > SAL_CALL SfxBaseModel::getCurrentController()
1253 {
1254 SfxModelGuard aGuard( *this );
1255
1256 // get the last active controller of this model
1257 if ( m_pData->m_xCurrent.is() )
1258 return m_pData->m_xCurrent;
1259
1260 // get the first controller of this model
1261 return !m_pData->m_seqControllers.empty() ? m_pData->m_seqControllers.front() : m_pData->m_xCurrent;
1262 }
1263
1264
1265 // frame::XModel
1266
1267
setCurrentController(const Reference<frame::XController> & xCurrentController)1268 void SAL_CALL SfxBaseModel::setCurrentController( const Reference< frame::XController >& xCurrentController )
1269 {
1270 SfxModelGuard aGuard( *this );
1271
1272 m_pData->m_xCurrent = xCurrentController;
1273 }
1274
1275
1276 // frame::XModel
1277
1278
getCurrentSelection()1279 Reference< XInterface > SAL_CALL SfxBaseModel::getCurrentSelection()
1280 {
1281 SfxModelGuard aGuard( *this );
1282
1283 Reference< XInterface > xReturn;
1284 Reference< frame::XController > xController = getCurrentController() ;
1285
1286 if ( xController.is() )
1287 {
1288 Reference< view::XSelectionSupplier > xDocView( xController, UNO_QUERY );
1289 if ( xDocView.is() )
1290 {
1291 Any aSel = xDocView->getSelection();
1292 aSel >>= xReturn ;
1293 }
1294 }
1295
1296 return xReturn ;
1297 }
1298
1299
1300 // XModifiable2
1301
1302
disableSetModified()1303 sal_Bool SAL_CALL SfxBaseModel::disableSetModified()
1304 {
1305 SfxModelGuard aGuard( *this );
1306
1307 if ( !m_pData->m_pObjectShell.is() )
1308 throw RuntimeException();
1309
1310 bool bResult = m_pData->m_pObjectShell->IsEnableSetModified();
1311 m_pData->m_pObjectShell->EnableSetModified( false );
1312
1313 return bResult;
1314 }
1315
enableSetModified()1316 sal_Bool SAL_CALL SfxBaseModel::enableSetModified()
1317 {
1318 SfxModelGuard aGuard( *this );
1319
1320 if ( !m_pData->m_pObjectShell.is() )
1321 throw RuntimeException();
1322
1323 bool bResult = m_pData->m_pObjectShell->IsEnableSetModified();
1324 m_pData->m_pObjectShell->EnableSetModified();
1325
1326 return bResult;
1327 }
1328
isSetModifiedEnabled()1329 sal_Bool SAL_CALL SfxBaseModel::isSetModifiedEnabled()
1330 {
1331 SfxModelGuard aGuard( *this );
1332
1333 if ( !m_pData->m_pObjectShell.is() )
1334 throw RuntimeException();
1335
1336 return m_pData->m_pObjectShell->IsEnableSetModified();
1337 }
1338
1339
1340 // XModifiable
1341
1342
isModified()1343 sal_Bool SAL_CALL SfxBaseModel::isModified()
1344 {
1345 SfxModelGuard aGuard( *this );
1346
1347 return m_pData->m_pObjectShell.is() && m_pData->m_pObjectShell->IsModified();
1348 }
1349
1350
1351 // XModifiable
1352
1353
setModified(sal_Bool bModified)1354 void SAL_CALL SfxBaseModel::setModified( sal_Bool bModified )
1355 {
1356 SfxModelGuard aGuard( *this );
1357
1358 if ( m_pData->m_pObjectShell.is() )
1359 m_pData->m_pObjectShell->SetModified(bModified);
1360 }
1361
1362
1363 // XModifiable
1364
1365
addModifyListener(const Reference<util::XModifyListener> & xListener)1366 void SAL_CALL SfxBaseModel::addModifyListener(const Reference< util::XModifyListener >& xListener)
1367 {
1368 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
1369
1370 m_pData->m_aInterfaceContainer.addInterface( cppu::UnoType<util::XModifyListener>::get(),xListener );
1371 }
1372
1373
1374 // XModifiable
1375
1376
removeModifyListener(const Reference<util::XModifyListener> & xListener)1377 void SAL_CALL SfxBaseModel::removeModifyListener(const Reference< util::XModifyListener >& xListener)
1378 {
1379 SfxModelGuard aGuard( *this );
1380
1381 m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<util::XModifyListener>::get(), xListener );
1382 }
1383
1384
1385 // XCloseable
1386
1387
close(sal_Bool bDeliverOwnership)1388 void SAL_CALL SfxBaseModel::close( sal_Bool bDeliverOwnership )
1389 {
1390 SolarMutexGuard aGuard;
1391 if ( impl_isDisposed() || m_pData->m_bClosed || m_pData->m_bClosing )
1392 return;
1393
1394 Reference< XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >(this) );
1395 lang::EventObject aSource ( static_cast< ::cppu::OWeakObject* >(this) );
1396 ::cppu::OInterfaceContainerHelper* pContainer = m_pData->m_aInterfaceContainer.getContainer( cppu::UnoType<util::XCloseListener>::get());
1397 if (pContainer!=nullptr)
1398 {
1399 ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
1400 while (pIterator.hasMoreElements())
1401 {
1402 try
1403 {
1404 static_cast<util::XCloseListener*>(pIterator.next())->queryClosing( aSource, bDeliverOwnership );
1405 }
1406 catch( RuntimeException& )
1407 {
1408 pIterator.remove();
1409 }
1410 }
1411 }
1412
1413 if ( m_pData->m_bSaving )
1414 {
1415 if (bDeliverOwnership)
1416 m_pData->m_bSuicide = true;
1417 throw util::CloseVetoException(
1418 "Can not close while saving.",
1419 static_cast< util::XCloseable* >(this));
1420 }
1421
1422 // no own objections against closing!
1423 m_pData->m_bClosing = true;
1424 pContainer = m_pData->m_aInterfaceContainer.getContainer( cppu::UnoType<util::XCloseListener>::get());
1425 if (pContainer!=nullptr)
1426 {
1427 ::cppu::OInterfaceIteratorHelper pCloseIterator(*pContainer);
1428 while (pCloseIterator.hasMoreElements())
1429 {
1430 try
1431 {
1432 static_cast<util::XCloseListener*>(pCloseIterator.next())->notifyClosing( aSource );
1433 }
1434 catch( RuntimeException& )
1435 {
1436 pCloseIterator.remove();
1437 }
1438 }
1439 }
1440
1441 m_pData->m_bClosed = true;
1442 m_pData->m_bClosing = false;
1443
1444 dispose();
1445 }
1446
1447
1448 // XCloseBroadcaster
1449
1450
addCloseListener(const Reference<util::XCloseListener> & xListener)1451 void SAL_CALL SfxBaseModel::addCloseListener( const Reference< util::XCloseListener >& xListener )
1452 {
1453 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
1454
1455 m_pData->m_aInterfaceContainer.addInterface( cppu::UnoType<util::XCloseListener>::get(), xListener );
1456 }
1457
1458
1459 // XCloseBroadcaster
1460
1461
removeCloseListener(const Reference<util::XCloseListener> & xListener)1462 void SAL_CALL SfxBaseModel::removeCloseListener( const Reference< util::XCloseListener >& xListener )
1463 {
1464 SfxModelGuard aGuard( *this );
1465
1466 m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<util::XCloseListener>::get(), xListener );
1467 }
1468
1469
1470 // XPrintable
1471
1472
getPrinter()1473 Sequence< beans::PropertyValue > SAL_CALL SfxBaseModel::getPrinter()
1474 {
1475 SfxModelGuard aGuard( *this );
1476
1477 impl_getPrintHelper();
1478 return m_pData->m_xPrintable->getPrinter();
1479 }
1480
setPrinter(const Sequence<beans::PropertyValue> & rPrinter)1481 void SAL_CALL SfxBaseModel::setPrinter(const Sequence< beans::PropertyValue >& rPrinter)
1482 {
1483 SfxModelGuard aGuard( *this );
1484
1485 impl_getPrintHelper();
1486 m_pData->m_xPrintable->setPrinter( rPrinter );
1487 }
1488
print(const Sequence<beans::PropertyValue> & rOptions)1489 void SAL_CALL SfxBaseModel::print(const Sequence< beans::PropertyValue >& rOptions)
1490 {
1491 SfxModelGuard aGuard( *this );
1492
1493 impl_getPrintHelper();
1494
1495 // tdf#123728 Always print on main thread to avoid deadlocks
1496 vcl::solarthread::syncExecute([this, &rOptions]() { m_pData->m_xPrintable->print(rOptions); });
1497 }
1498
1499 // XStorable
1500
1501
hasLocation()1502 sal_Bool SAL_CALL SfxBaseModel::hasLocation()
1503 {
1504 SfxModelGuard aGuard( *this );
1505
1506 return m_pData->m_pObjectShell.is() && m_pData->m_pObjectShell->HasName();
1507 }
1508
1509
1510 // XStorable
1511
1512
getLocation()1513 OUString SAL_CALL SfxBaseModel::getLocation()
1514 {
1515 SfxModelGuard aGuard( *this );
1516
1517 if ( m_pData->m_pObjectShell.is() )
1518 {
1519 // TODO/LATER: is it correct that the shared document returns shared file location?
1520 if ( m_pData->m_pObjectShell->IsDocShared() )
1521 return m_pData->m_pObjectShell->GetSharedFileURL();
1522 else
1523 return m_pData->m_pObjectShell->GetMedium()->GetName();
1524 }
1525
1526 return m_pData->m_sURL;
1527 }
1528
1529
1530 // XStorable
1531
1532
isReadonly()1533 sal_Bool SAL_CALL SfxBaseModel::isReadonly()
1534 {
1535 SfxModelGuard aGuard( *this );
1536
1537 return !m_pData->m_pObjectShell.is() || m_pData->m_pObjectShell->IsReadOnly();
1538 }
1539
1540 // XStorable2
1541
1542
storeSelf(const Sequence<beans::PropertyValue> & aSeqArgs)1543 void SAL_CALL SfxBaseModel::storeSelf( const Sequence< beans::PropertyValue >& aSeqArgs )
1544 {
1545 SfxModelGuard aGuard( *this );
1546
1547 if ( !m_pData->m_pObjectShell.is() )
1548 return;
1549
1550 SfxSaveGuard aSaveGuard(this, m_pData.get());
1551
1552 bool bCheckIn = false;
1553 bool bOnMainThread = false;
1554 for ( const auto& rArg : aSeqArgs )
1555 {
1556 // check that only acceptable parameters are provided here
1557 if ( rArg.Name != "VersionComment" && rArg.Name != "Author"
1558 && rArg.Name != "DontTerminateEdit"
1559 && rArg.Name != "InteractionHandler" && rArg.Name != "StatusIndicator"
1560 && rArg.Name != "VersionMajor"
1561 && rArg.Name != "FailOnWarning"
1562 && rArg.Name != "CheckIn"
1563 && rArg.Name != "NoFileSync"
1564 && rArg.Name != "OnMainThread" )
1565 {
1566 const OUString aMessage( "Unexpected MediaDescriptor parameter: " + rArg.Name );
1567 throw lang::IllegalArgumentException( aMessage, Reference< XInterface >(), 1 );
1568 }
1569 else if ( rArg.Name == "CheckIn" )
1570 {
1571 rArg.Value >>= bCheckIn;
1572 }
1573 else if (rArg.Name == "OnMainThread")
1574 {
1575 rArg.Value >>= bOnMainThread;
1576 }
1577 }
1578
1579 // Remove CheckIn property if needed
1580 sal_uInt16 nSlotId = SID_SAVEDOC;
1581 Sequence< beans::PropertyValue > aArgs = aSeqArgs;
1582 if ( bCheckIn )
1583 {
1584 nSlotId = SID_CHECKIN;
1585 sal_Int32 nLength = aSeqArgs.getLength( );
1586 aArgs = Sequence< beans::PropertyValue >( nLength - 1 );
1587 std::copy_if(aSeqArgs.begin(), aSeqArgs.end(), aArgs.begin(),
1588 [](const beans::PropertyValue& rProp) { return rProp.Name != "CheckIn"; });
1589 }
1590
1591 std::unique_ptr<SfxAllItemSet> pParams(new SfxAllItemSet( SfxGetpApp()->GetPool() ));
1592 TransformParameters( nSlotId, aArgs, *pParams );
1593
1594 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::SaveDoc, GlobalEventConfig::GetEventName(GlobalEventId::SAVEDOC), m_pData->m_pObjectShell.get() ) );
1595
1596 bool bRet = false;
1597
1598 // TODO/LATER: let the embedded case of saving be handled more careful
1599 if ( m_pData->m_pObjectShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
1600 {
1601 // If this is an embedded object that has no URL based location it should be stored to own storage.
1602 // An embedded object can have a location based on URL in case it is a link, then it should be
1603 // stored in normal way.
1604 if ( !hasLocation() || getLocation().startsWith("private:") )
1605 {
1606 // actually in this very rare case only UI parameters have sense
1607 // TODO/LATER: should be done later, after integration of sb19
1608 bRet = m_pData->m_pObjectShell->DoSave()
1609 && m_pData->m_pObjectShell->DoSaveCompleted();
1610 }
1611 else
1612 {
1613 bRet = m_pData->m_pObjectShell->Save_Impl( pParams.get() );
1614 }
1615 }
1616 else
1617 {
1618 // Tell the SfxMedium if we are in checkin instead of normal save
1619 m_pData->m_pObjectShell->GetMedium( )->SetInCheckIn( nSlotId == SID_CHECKIN );
1620 if (bOnMainThread)
1621 bRet = vcl::solarthread::syncExecute(
1622 [this, &pParams] { return m_pData->m_pObjectShell->Save_Impl(pParams.get()); });
1623 else
1624 bRet = m_pData->m_pObjectShell->Save_Impl(pParams.get());
1625 m_pData->m_pObjectShell->GetMedium( )->SetInCheckIn( nSlotId != SID_CHECKIN );
1626 }
1627
1628 pParams.reset();
1629
1630 ErrCode nErrCode = m_pData->m_pObjectShell->GetError() ? m_pData->m_pObjectShell->GetError()
1631 : ERRCODE_IO_CANTWRITE;
1632 m_pData->m_pObjectShell->ResetError();
1633
1634 if ( bRet )
1635 {
1636 m_pData->m_aPreusedFilterName = GetMediumFilterName_Impl();
1637
1638 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::SaveDocDone, GlobalEventConfig::GetEventName(GlobalEventId::SAVEDOCDONE), m_pData->m_pObjectShell.get() ) );
1639 }
1640 else
1641 {
1642 // write the contents of the logger to the file
1643 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::SaveDocFailed, GlobalEventConfig::GetEventName(GlobalEventId::SAVEDOCFAILED), m_pData->m_pObjectShell.get() ) );
1644
1645 throw task::ErrorCodeIOException(
1646 "SfxBaseModel::storeSelf: " + nErrCode.toHexString(),
1647 Reference< XInterface >(), sal_uInt32(nErrCode));
1648 }
1649 }
1650
1651
1652 // XStorable
1653
1654
store()1655 void SAL_CALL SfxBaseModel::store()
1656 {
1657 comphelper::ProfileZone aZone("store");
1658 storeSelf( Sequence< beans::PropertyValue >() );
1659 }
1660
1661
1662 // XStorable
1663
1664
storeAsURL(const OUString & rURL,const Sequence<beans::PropertyValue> & rArgs)1665 void SAL_CALL SfxBaseModel::storeAsURL( const OUString& rURL ,
1666 const Sequence< beans::PropertyValue >& rArgs )
1667 {
1668 SfxModelGuard aGuard( *this );
1669 comphelper::ProfileZone aZone("storeAs");
1670
1671 if ( !m_pData->m_pObjectShell.is() )
1672 return;
1673
1674 SfxSaveGuard aSaveGuard(this, m_pData.get());
1675
1676 impl_store( rURL, rArgs, false );
1677
1678 Sequence< beans::PropertyValue > aSequence ;
1679 TransformItems( SID_OPENDOC, *m_pData->m_pObjectShell->GetMedium()->GetItemSet(), aSequence );
1680 attachResource( rURL, aSequence );
1681
1682 loadCmisProperties( );
1683
1684 #if OSL_DEBUG_LEVEL > 0
1685 const SfxStringItem* pPasswdItem = SfxItemSet::GetItem<SfxStringItem>(m_pData->m_pObjectShell->GetMedium()->GetItemSet(), SID_PASSWORD, false);
1686 OSL_ENSURE( !pPasswdItem, "There should be no Password property in the document MediaDescriptor!" );
1687 #endif
1688 }
1689
1690
1691 // XUndoManagerSupplier
1692
getUndoManager()1693 Reference< XUndoManager > SAL_CALL SfxBaseModel::getUndoManager( )
1694 {
1695 SfxModelGuard aGuard( *this );
1696 if ( !m_pData->m_pDocumentUndoManager.is() )
1697 m_pData->m_pDocumentUndoManager.set( new ::sfx2::DocumentUndoManager( *this ) );
1698 return m_pData->m_pDocumentUndoManager.get();
1699 }
1700
1701
1702 // XStorable
1703
1704
storeToURL(const OUString & rURL,const Sequence<beans::PropertyValue> & rArgs)1705 void SAL_CALL SfxBaseModel::storeToURL( const OUString& rURL ,
1706 const Sequence< beans::PropertyValue >& rArgs )
1707 {
1708 SfxModelGuard aGuard( *this );
1709 comphelper::ProfileZone aZone("storeToURL");
1710
1711 if ( !m_pData->m_pObjectShell.is() )
1712 return;
1713
1714 SfxSaveGuard aSaveGuard(this, m_pData.get());
1715 try {
1716 utl::MediaDescriptor aDescriptor(rArgs);
1717 bool bOnMainThread = aDescriptor.getUnpackedValueOrDefault("OnMainThread", false);
1718 if (bOnMainThread)
1719 vcl::solarthread::syncExecute([this, rURL, rArgs]() { impl_store(rURL, rArgs, true); });
1720 else
1721 impl_store(rURL, rArgs, true);
1722 }
1723 catch (const uno::Exception &e)
1724 {
1725 // convert to the exception we announce in the throw
1726 // (eg. neon likes to throw InteractiveAugmentedIOException which
1727 // is not an io::IOException)
1728 throw io::IOException(e.Message, e.Context);
1729 }
1730 }
1731
wasModifiedSinceLastSave()1732 sal_Bool SAL_CALL SfxBaseModel::wasModifiedSinceLastSave()
1733 {
1734 SfxModelGuard aGuard( *this );
1735 return m_pData->m_bModifiedSinceLastSave;
1736 }
1737
storeToRecoveryFile(const OUString & i_TargetLocation,const Sequence<PropertyValue> & i_MediaDescriptor)1738 void SAL_CALL SfxBaseModel::storeToRecoveryFile( const OUString& i_TargetLocation, const Sequence< PropertyValue >& i_MediaDescriptor )
1739 {
1740 SfxModelGuard aGuard( *this );
1741
1742 // delegate
1743 SfxSaveGuard aSaveGuard( this, m_pData.get() );
1744 impl_store( i_TargetLocation, i_MediaDescriptor, true );
1745
1746 // no need for subsequent calls to storeToRecoveryFile, unless we're modified, again
1747 m_pData->m_bModifiedSinceLastSave = false;
1748 }
1749
recoverFromFile(const OUString & i_SourceLocation,const OUString & i_SalvagedFile,const Sequence<PropertyValue> & i_MediaDescriptor)1750 void SAL_CALL SfxBaseModel::recoverFromFile( const OUString& i_SourceLocation, const OUString& i_SalvagedFile, const Sequence< PropertyValue >& i_MediaDescriptor )
1751 {
1752 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
1753
1754 // delegate to our "load" method
1755 ::comphelper::NamedValueCollection aMediaDescriptor( i_MediaDescriptor );
1756
1757 // our load implementation expects the SalvagedFile to be in the media descriptor
1758 OSL_ENSURE( !aMediaDescriptor.has( "SalvagedFile" ) || ( aMediaDescriptor.getOrDefault( "SalvagedFile", OUString() ) == i_SalvagedFile ),
1759 "SfxBaseModel::recoverFromFile: inconsistent information!" );
1760 aMediaDescriptor.put( "SalvagedFile", i_SalvagedFile );
1761
1762 // similar for the to-be-loaded file
1763 OSL_ENSURE( !aMediaDescriptor.has( "URL" ) || ( aMediaDescriptor.getOrDefault( "URL", OUString() ) == i_SourceLocation ),
1764 "SfxBaseModel::recoverFromFile: inconsistent information!" );
1765 aMediaDescriptor.put( "URL", i_SourceLocation );
1766
1767 load( aMediaDescriptor.getPropertyValues() );
1768
1769 // Note: The XDocumentRecovery interface specification requires us to do an attachResource after loading.
1770 // However, we will not do this here, as we know that our load implementation (respectively some method
1771 // called from there) already did so.
1772 // In particular, the load process might already have modified some elements of the media
1773 // descriptor, for instance the MacroExecMode (in case the user was involved to decide about it), and we do
1774 // not want to overwrite it with the "old" elements passed to this method here.
1775 }
1776
1777
1778 // XLoadable
1779
1780
initNew()1781 void SAL_CALL SfxBaseModel::initNew()
1782 {
1783 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
1784 if ( IsInitialized() )
1785 throw frame::DoubleInitializationException( OUString(), *this );
1786
1787 // the object shell should exist always
1788 DBG_ASSERT( m_pData->m_pObjectShell.is(), "Model is useless without an ObjectShell" );
1789 if ( !m_pData->m_pObjectShell.is() )
1790 return;
1791
1792 if( m_pData->m_pObjectShell->GetMedium() )
1793 throw frame::DoubleInitializationException();
1794
1795 bool bRes = m_pData->m_pObjectShell->DoInitNew();
1796 ErrCode nErrCode = m_pData->m_pObjectShell->GetError() ?
1797 m_pData->m_pObjectShell->GetError() : ERRCODE_IO_CANTCREATE;
1798 m_pData->m_pObjectShell->ResetError();
1799
1800 if ( !bRes )
1801 throw task::ErrorCodeIOException(
1802 "SfxBaseModel::initNew: " + nErrCode.toHexString(),
1803 Reference< XInterface >(), sal_uInt32(nErrCode));
1804 }
1805
1806 namespace {
1807
getFilterProvider(SfxMedium const & rMedium)1808 OUString getFilterProvider( SfxMedium const & rMedium )
1809 {
1810 const std::shared_ptr<const SfxFilter>& pFilter = rMedium.GetFilter();
1811 if (!pFilter)
1812 return OUString();
1813
1814 return pFilter->GetProviderName();
1815 }
1816
setUpdatePickList(SfxMedium * pMedium)1817 void setUpdatePickList( SfxMedium* pMedium )
1818 {
1819 if (!pMedium)
1820 return;
1821
1822 bool bHidden = false;
1823 const SfxBoolItem* pHidItem = SfxItemSet::GetItem<SfxBoolItem>(pMedium->GetItemSet(), SID_HIDDEN, false);
1824 if (pHidItem)
1825 bHidden = pHidItem->GetValue();
1826
1827 pMedium->SetUpdatePickList(!bHidden);
1828 }
1829
1830 }
1831
load(const Sequence<beans::PropertyValue> & seqArguments)1832 void SAL_CALL SfxBaseModel::load( const Sequence< beans::PropertyValue >& seqArguments )
1833 {
1834 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
1835 if ( IsInitialized() )
1836 throw frame::DoubleInitializationException( OUString(), *this );
1837
1838 // the object shell should exist always
1839 DBG_ASSERT( m_pData->m_pObjectShell.is(), "Model is useless without an ObjectShell" );
1840
1841 if (!m_pData->m_pObjectShell.is())
1842 return;
1843
1844 if( m_pData->m_pObjectShell->GetMedium() )
1845 // if a Medium is present, the document is already initialized
1846 throw frame::DoubleInitializationException();
1847
1848 SfxMedium* pMedium = new SfxMedium( seqArguments );
1849
1850 ErrCode nError = ERRCODE_NONE;
1851 if (!getFilterProvider(*pMedium).isEmpty())
1852 {
1853 if (!m_pData->m_pObjectShell->DoLoadExternal(pMedium))
1854 nError = ERRCODE_IO_GENERAL;
1855
1856 pMedium = handleLoadError(nError, pMedium);
1857 setUpdatePickList(pMedium);
1858 return;
1859 }
1860
1861 OUString aFilterName;
1862 const SfxStringItem* pFilterNameItem = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_FILTER_NAME, false);
1863 if( pFilterNameItem )
1864 aFilterName = pFilterNameItem->GetValue();
1865 if( !m_pData->m_pObjectShell->GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName ) )
1866 {
1867 // filtername is not valid
1868 delete pMedium;
1869 throw frame::IllegalArgumentIOException();
1870 }
1871
1872 const SfxStringItem* pSalvageItem = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_DOC_SALVAGE, false);
1873 bool bSalvage = pSalvageItem != nullptr;
1874
1875 // load document
1876 if ( !m_pData->m_pObjectShell->DoLoad(pMedium) )
1877 nError=ERRCODE_IO_GENERAL;
1878
1879 // QUESTION: if the following happens outside of DoLoad, something important is missing there!
1880 Reference< task::XInteractionHandler > xHandler = pMedium->GetInteractionHandler();
1881 if( m_pData->m_pObjectShell->GetErrorCode() )
1882 {
1883 nError = m_pData->m_pObjectShell->GetErrorCode();
1884 if ( nError == ERRCODE_IO_BROKENPACKAGE && xHandler.is() )
1885 {
1886 const OUString aDocName( pMedium->GetURLObject().getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset ) );
1887 const SfxBoolItem* pRepairItem = SfxItemSet::GetItem<SfxBoolItem>(pMedium->GetItemSet(), SID_REPAIRPACKAGE, false);
1888 if ( !pRepairItem || !pRepairItem->GetValue() )
1889 {
1890 RequestPackageReparation aRequest( aDocName );
1891 xHandler->handle( aRequest.GetRequest() );
1892 if( aRequest.isApproved() )
1893 {
1894 // broken package: try second loading and allow repair
1895 pMedium->GetItemSet()->Put( SfxBoolItem( SID_REPAIRPACKAGE, true ) );
1896 pMedium->GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE, true ) );
1897 pMedium->GetItemSet()->Put( SfxStringItem( SID_DOCINFO_TITLE, aDocName ) );
1898
1899 // the error must be reset and the storage must be reopened in new mode
1900 pMedium->ResetError();
1901 pMedium->CloseStorage();
1902 m_pData->m_pObjectShell->PrepareSecondTryLoad_Impl();
1903 nError = ERRCODE_NONE;
1904 if ( !m_pData->m_pObjectShell->DoLoad(pMedium) )
1905 nError=ERRCODE_IO_GENERAL;
1906 if (m_pData->m_pObjectShell->GetErrorCode())
1907 nError = m_pData->m_pObjectShell->GetErrorCode();
1908 }
1909 }
1910
1911 if ( nError == ERRCODE_IO_BROKENPACKAGE )
1912 {
1913 // repair either not allowed or not successful
1914 NotifyBrokenPackage aRequest( aDocName );
1915 xHandler->handle( aRequest.GetRequest() );
1916 }
1917 }
1918 }
1919
1920 if( m_pData->m_pObjectShell->IsAbortingImport() )
1921 nError = ERRCODE_ABORT;
1922
1923 if( bSalvage )
1924 {
1925 // file recovery: restore original filter
1926 const SfxStringItem* pFilterItem = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_FILTER_NAME, false);
1927 SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher();
1928 std::shared_ptr<const SfxFilter> pSetFilter = rMatcher.GetFilter4FilterName( pFilterItem->GetValue() );
1929 pMedium->SetFilter( pSetFilter );
1930 m_pData->m_pObjectShell->SetModified();
1931 }
1932
1933 // TODO/LATER: maybe the mode should be retrieved from outside and the preused filter should not be set
1934 if ( m_pData->m_pObjectShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
1935 {
1936 const SfxStringItem* pFilterItem = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_FILTER_NAME, false);
1937 if ( pFilterItem )
1938 m_pData->m_aPreusedFilterName = pFilterItem->GetValue();
1939 }
1940
1941 if ( !nError )
1942 nError = pMedium->GetError();
1943
1944 m_pData->m_pObjectShell->ResetError();
1945
1946 pMedium = handleLoadError(nError, pMedium);
1947 loadCmisProperties();
1948 setUpdatePickList(pMedium);
1949
1950 #if OSL_DEBUG_LEVEL > 0
1951 const SfxStringItem* pPasswdItem = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_PASSWORD, false);
1952 OSL_ENSURE( !pPasswdItem, "There should be no Password property in the document MediaDescriptor!" );
1953 #endif
1954 }
1955
1956
1957 // XTransferable
1958
1959
getTransferData(const datatransfer::DataFlavor & aFlavor)1960 Any SAL_CALL SfxBaseModel::getTransferData( const datatransfer::DataFlavor& aFlavor )
1961 {
1962 SfxModelGuard aGuard( *this );
1963
1964 Any aAny;
1965
1966 if ( m_pData->m_pObjectShell.is() )
1967 {
1968 if ( aFlavor.MimeType == "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"" )
1969 {
1970 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
1971 throw datatransfer::UnsupportedFlavorException();
1972
1973 TransferableObjectDescriptor aDesc;
1974
1975 aDesc.maClassName = m_pData->m_pObjectShell->GetClassName();
1976 aDesc.maTypeName = aFlavor.HumanPresentableName;
1977
1978 // TODO/LATER: ViewAspect needs to be sal_Int64
1979 aDesc.mnViewAspect = sal::static_int_cast< sal_uInt16 >( embed::Aspects::MSOLE_CONTENT );
1980
1981 Size aSize = m_pData->m_pObjectShell->GetVisArea().GetSize();
1982
1983 MapUnit aMapUnit = m_pData->m_pObjectShell->GetMapUnit();
1984 aDesc.maSize = OutputDevice::LogicToLogic(aSize, MapMode(aMapUnit), MapMode(MapUnit::Map100thMM));
1985 aDesc.maDragStartPos = Point();
1986 aDesc.maDisplayName.clear();
1987
1988 SvMemoryStream aMemStm( 1024, 1024 );
1989 WriteTransferableObjectDescriptor( aMemStm, aDesc );
1990 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Tell() );
1991 }
1992 else if ( aFlavor.MimeType == "application/x-openoffice-embed-source;windows_formatname=\"Star EMBS\"" )
1993 {
1994 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
1995 throw datatransfer::UnsupportedFlavorException();
1996
1997 try
1998 {
1999 utl::TempFile aTmp;
2000 aTmp.EnableKillingFile();
2001 storeToURL( aTmp.GetURL(), Sequence < beans::PropertyValue >() );
2002 std::unique_ptr<SvStream> pStream(aTmp.GetStream( StreamMode::READ ));
2003 const sal_uInt32 nLen = pStream->TellEnd();
2004 Sequence< sal_Int8 > aSeq( nLen );
2005 pStream->ReadBytes(aSeq.getArray(), nLen);
2006 if( aSeq.hasElements() )
2007 aAny <<= aSeq;
2008 }
2009 catch ( Exception& )
2010 {
2011 }
2012 }
2013 else if ( aFlavor.MimeType == "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" )
2014 {
2015 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
2016 throw datatransfer::UnsupportedFlavorException();
2017
2018
2019 std::shared_ptr<GDIMetaFile> xMetaFile =
2020 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2021
2022 if (xMetaFile)
2023 {
2024 SvMemoryStream aMemStm( 65535, 65535 );
2025 aMemStm.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2026
2027 xMetaFile->Write( aMemStm );
2028 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( aMemStm.GetData() ),
2029 aMemStm.TellEnd() );
2030 }
2031 }
2032 else if ( aFlavor.MimeType == "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" )
2033 {
2034 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
2035 throw datatransfer::UnsupportedFlavorException();
2036
2037 std::shared_ptr<GDIMetaFile> xMetaFile =
2038 m_pData->m_pObjectShell->CreatePreviewMetaFile_Impl( true );
2039
2040 if (xMetaFile)
2041 {
2042 SvMemoryStream aMemStm( 65535, 65535 );
2043 aMemStm.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2044
2045 xMetaFile->Write( aMemStm );
2046 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( aMemStm.GetData() ),
2047 aMemStm.TellEnd() );
2048 }
2049 }
2050 else if ( aFlavor.MimeType == "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" )
2051 {
2052 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2053 {
2054 std::shared_ptr<GDIMetaFile> xMetaFile =
2055 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2056
2057 if (xMetaFile)
2058 {
2059 std::unique_ptr<SvMemoryStream> xStream(
2060 GraphicHelper::getFormatStrFromGDI_Impl(
2061 xMetaFile.get(), ConvertDataFormat::EMF ) );
2062 if (xStream)
2063 {
2064 xStream->SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2065 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( xStream->GetData() ),
2066 xStream->TellEnd() );
2067 }
2068 }
2069 }
2070 else if ( GraphicHelper::supportsMetaFileHandle_Impl()
2071 && aFlavor.DataType == cppu::UnoType<sal_uInt64>::get())
2072 {
2073 std::shared_ptr<GDIMetaFile> xMetaFile =
2074 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2075
2076 if (xMetaFile)
2077 {
2078 aAny <<= reinterpret_cast< sal_uInt64 >(
2079 GraphicHelper::getEnhMetaFileFromGDI_Impl( xMetaFile.get() ) );
2080 }
2081 }
2082 else
2083 throw datatransfer::UnsupportedFlavorException();
2084 }
2085 else if ( aFlavor.MimeType == "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" )
2086 {
2087 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2088 {
2089 std::shared_ptr<GDIMetaFile> xMetaFile =
2090 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2091
2092 if (xMetaFile)
2093 {
2094 std::unique_ptr<SvMemoryStream> xStream(
2095 GraphicHelper::getFormatStrFromGDI_Impl(
2096 xMetaFile.get(), ConvertDataFormat::WMF ) );
2097
2098 if (xStream)
2099 {
2100 xStream->SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2101 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( xStream->GetData() ),
2102 xStream->TellEnd() );
2103 }
2104 }
2105 }
2106 else if ( GraphicHelper::supportsMetaFileHandle_Impl()
2107 && aFlavor.DataType == cppu::UnoType<sal_uInt64>::get())
2108 {
2109 // means HGLOBAL handler to memory storage containing METAFILEPICT structure
2110
2111 std::shared_ptr<GDIMetaFile> xMetaFile =
2112 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2113
2114 if (xMetaFile)
2115 {
2116 Size aMetaSize = xMetaFile->GetPrefSize();
2117 aAny <<= reinterpret_cast< sal_uInt64 >(
2118 GraphicHelper::getWinMetaFileFromGDI_Impl(
2119 xMetaFile.get(), aMetaSize ) );
2120 }
2121 }
2122 else
2123 throw datatransfer::UnsupportedFlavorException();
2124 }
2125 else if ( aFlavor.MimeType == "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" )
2126 {
2127 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
2128 throw datatransfer::UnsupportedFlavorException();
2129
2130 std::shared_ptr<GDIMetaFile> xMetaFile =
2131 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2132
2133 if (xMetaFile)
2134 {
2135 std::unique_ptr<SvMemoryStream> xStream(
2136 GraphicHelper::getFormatStrFromGDI_Impl(
2137 xMetaFile.get(), ConvertDataFormat::BMP ) );
2138
2139 if (xStream)
2140 {
2141 xStream->SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2142 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( xStream->GetData() ),
2143 xStream->TellEnd() );
2144 }
2145 }
2146 }
2147 else if ( aFlavor.MimeType == "image/png" )
2148 {
2149 if ( aFlavor.DataType != cppu::UnoType<Sequence< sal_Int8 >>::get() )
2150 throw datatransfer::UnsupportedFlavorException();
2151
2152 std::shared_ptr<GDIMetaFile> xMetaFile =
2153 m_pData->m_pObjectShell->GetPreviewMetaFile( true );
2154
2155 if (xMetaFile)
2156 {
2157 std::unique_ptr<SvMemoryStream> xStream(
2158 GraphicHelper::getFormatStrFromGDI_Impl(
2159 xMetaFile.get(), ConvertDataFormat::PNG ) );
2160
2161 if (xStream)
2162 {
2163 xStream->SetVersion( SOFFICE_FILEFORMAT_CURRENT );
2164 aAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( xStream->GetData() ),
2165 xStream->TellEnd() );
2166 }
2167 }
2168 }
2169 else
2170 throw datatransfer::UnsupportedFlavorException();
2171 }
2172
2173 return aAny;
2174 }
2175
2176
2177 // XTransferable
2178
2179
getTransferDataFlavors()2180 Sequence< datatransfer::DataFlavor > SAL_CALL SfxBaseModel::getTransferDataFlavors()
2181 {
2182 SfxModelGuard aGuard( *this );
2183
2184 const sal_Int32 nSuppFlavors = GraphicHelper::supportsMetaFileHandle_Impl() ? 10 : 8;
2185 Sequence< datatransfer::DataFlavor > aFlavorSeq( nSuppFlavors );
2186
2187 aFlavorSeq[0].MimeType =
2188 "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"";
2189 aFlavorSeq[0].HumanPresentableName = "GDIMetaFile";
2190 aFlavorSeq[0].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2191
2192 aFlavorSeq[1].MimeType =
2193 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"";
2194 aFlavorSeq[1].HumanPresentableName = "GDIMetaFile";
2195 aFlavorSeq[1].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2196
2197 aFlavorSeq[2].MimeType =
2198 "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" ;
2199 aFlavorSeq[2].HumanPresentableName = "Enhanced Windows MetaFile";
2200 aFlavorSeq[2].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2201
2202 aFlavorSeq[3].MimeType =
2203 "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"";
2204 aFlavorSeq[3].HumanPresentableName = "Windows MetaFile";
2205 aFlavorSeq[3].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2206
2207 aFlavorSeq[4].MimeType =
2208 "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"";
2209 aFlavorSeq[4].HumanPresentableName = "Star Object Descriptor (XML)";
2210 aFlavorSeq[4].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2211
2212 aFlavorSeq[5].MimeType =
2213 "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
2214 aFlavorSeq[5].HumanPresentableName = "Star Embed Source (XML)";
2215 aFlavorSeq[5].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2216
2217 aFlavorSeq[6].MimeType =
2218 "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"";
2219 aFlavorSeq[6].HumanPresentableName = "Bitmap";
2220 aFlavorSeq[6].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2221
2222 aFlavorSeq[7].MimeType = "image/png";
2223 aFlavorSeq[7].HumanPresentableName = "PNG";
2224 aFlavorSeq[7].DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
2225
2226 if ( nSuppFlavors == 10 )
2227 {
2228 aFlavorSeq[8].MimeType =
2229 "application/x-openoffice-emf;windows_formatname=\"Image EMF\"";
2230 aFlavorSeq[8].HumanPresentableName = "Enhanced Windows MetaFile";
2231 aFlavorSeq[8].DataType = cppu::UnoType<sal_uInt64>::get();
2232
2233 aFlavorSeq[9].MimeType =
2234 "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"";
2235 aFlavorSeq[9].HumanPresentableName = "Windows MetaFile";
2236 aFlavorSeq[9].DataType = cppu::UnoType<sal_uInt64>::get();
2237 }
2238
2239 return aFlavorSeq;
2240 }
2241
2242
2243 // XTransferable
2244
2245
isDataFlavorSupported(const datatransfer::DataFlavor & aFlavor)2246 sal_Bool SAL_CALL SfxBaseModel::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
2247 {
2248 SfxModelGuard aGuard( *this );
2249
2250 if ( aFlavor.MimeType == "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" )
2251 {
2252 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2253 return true;
2254 }
2255 else if ( aFlavor.MimeType == "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" )
2256 {
2257 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2258 return true;
2259 }
2260 else if ( aFlavor.MimeType == "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" )
2261 {
2262 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2263 return true;
2264 else if ( GraphicHelper::supportsMetaFileHandle_Impl()
2265 && aFlavor.DataType == cppu::UnoType<sal_uInt64>::get())
2266 return true;
2267 }
2268 else if ( aFlavor.MimeType == "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" )
2269 {
2270 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2271 return true;
2272 else if ( GraphicHelper::supportsMetaFileHandle_Impl()
2273 && aFlavor.DataType == cppu::UnoType<sal_uInt64>::get())
2274 return true;
2275 }
2276 else if ( aFlavor.MimeType == "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"" )
2277 {
2278 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2279 return true;
2280 }
2281 else if ( aFlavor.MimeType == "application/x-openoffice-embed-source;windows_formatname=\"Star EMBS\"" )
2282 {
2283 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2284 return true;
2285 }
2286 else if ( aFlavor.MimeType == "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" )
2287 {
2288 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2289 return true;
2290 }
2291 else if ( aFlavor.MimeType == "image/png" )
2292 {
2293 if ( aFlavor.DataType == cppu::UnoType<Sequence< sal_Int8 >>::get() )
2294 return true;
2295 }
2296
2297 return false;
2298 }
2299
2300
2301 // XEventsSupplier
2302
2303
getEvents()2304 Reference< container::XNameReplace > SAL_CALL SfxBaseModel::getEvents()
2305 {
2306 SfxModelGuard aGuard( *this );
2307
2308 if ( ! m_pData->m_xEvents.is() )
2309 {
2310 m_pData->m_xEvents = new SfxEvents_Impl( m_pData->m_pObjectShell.get(), this );
2311 }
2312
2313 return m_pData->m_xEvents;
2314 }
2315
2316
2317 // XEmbeddedScripts
2318
2319
getBasicLibraries()2320 Reference< script::XStorageBasedLibraryContainer > SAL_CALL SfxBaseModel::getBasicLibraries()
2321 {
2322 SfxModelGuard aGuard( *this );
2323
2324 Reference< script::XStorageBasedLibraryContainer > xBasicLibraries;
2325 if ( m_pData->m_pObjectShell.is() )
2326 xBasicLibraries.set(m_pData->m_pObjectShell->GetBasicContainer(), UNO_QUERY);
2327 return xBasicLibraries;
2328 }
2329
getDialogLibraries()2330 Reference< script::XStorageBasedLibraryContainer > SAL_CALL SfxBaseModel::getDialogLibraries()
2331 {
2332 SfxModelGuard aGuard( *this );
2333
2334 Reference< script::XStorageBasedLibraryContainer > xDialogLibraries;
2335 if ( m_pData->m_pObjectShell.is() )
2336 xDialogLibraries.set(m_pData->m_pObjectShell->GetDialogContainer(), UNO_QUERY);
2337 return xDialogLibraries;
2338 }
2339
getAllowMacroExecution()2340 sal_Bool SAL_CALL SfxBaseModel::getAllowMacroExecution()
2341 {
2342 SfxModelGuard aGuard( *this );
2343
2344 if ( m_pData->m_pObjectShell.is() )
2345 return m_pData->m_pObjectShell->AdjustMacroMode();
2346 return false;
2347 }
2348
2349
2350 // XScriptInvocationContext
2351
2352
getScriptContainer()2353 Reference< document::XEmbeddedScripts > SAL_CALL SfxBaseModel::getScriptContainer()
2354 {
2355 SfxModelGuard aGuard( *this );
2356
2357 Reference< document::XEmbeddedScripts > xDocumentScripts;
2358
2359 try
2360 {
2361 Reference< frame::XModel > xDocument( this );
2362 xDocumentScripts.set( xDocument, UNO_QUERY );
2363 while ( !xDocumentScripts.is() && xDocument.is() )
2364 {
2365 Reference< container::XChild > xDocAsChild( xDocument, UNO_QUERY );
2366 if ( !xDocAsChild.is() )
2367 {
2368 xDocument = nullptr;
2369 break;
2370 }
2371
2372 xDocument.set( xDocAsChild->getParent(), UNO_QUERY );
2373 xDocumentScripts.set( xDocument, UNO_QUERY );
2374 }
2375 }
2376 catch( const Exception& )
2377 {
2378 DBG_UNHANDLED_EXCEPTION("sfx.doc");
2379 xDocumentScripts = nullptr;
2380 }
2381
2382 return xDocumentScripts;
2383 }
2384
2385
2386 // XEventBroadcaster
2387
2388
addEventListener(const Reference<document::XEventListener> & aListener)2389 void SAL_CALL SfxBaseModel::addEventListener( const Reference< document::XEventListener >& aListener )
2390 {
2391 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
2392
2393 m_pData->m_aInterfaceContainer.addInterface( cppu::UnoType<document::XEventListener>::get(), aListener );
2394 }
2395
2396
2397 // XEventBroadcaster
2398
2399
removeEventListener(const Reference<document::XEventListener> & aListener)2400 void SAL_CALL SfxBaseModel::removeEventListener( const Reference< document::XEventListener >& aListener )
2401 {
2402 SfxModelGuard aGuard( *this );
2403
2404 m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<document::XEventListener>::get(), aListener );
2405 }
2406
2407 // XShapeEventBroadcaster
2408
addShapeEventListener(const css::uno::Reference<css::drawing::XShape> & xShape,const Reference<document::XShapeEventListener> & xListener)2409 void SAL_CALL SfxBaseModel::addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const Reference< document::XShapeEventListener >& xListener )
2410 {
2411 assert(xShape.is() && "no shape?");
2412 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
2413
2414 m_pData->maShapeListeners[xShape].push_back(xListener);
2415 }
2416
2417
2418 // XShapeEventBroadcaster
2419
2420
removeShapeEventListener(const css::uno::Reference<css::drawing::XShape> & xShape,const Reference<document::XShapeEventListener> & xListener)2421 void SAL_CALL SfxBaseModel::removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const Reference< document::XShapeEventListener >& xListener )
2422 {
2423 SfxModelGuard aGuard( *this );
2424
2425 auto it = m_pData->maShapeListeners.find(xShape);
2426 if (it != m_pData->maShapeListeners.end())
2427 {
2428 auto rVec = it->second;
2429 auto it2 = std::find(rVec.begin(), rVec.end(), xListener);
2430 if (it2 != rVec.end())
2431 {
2432 rVec.erase(it2);
2433 if (rVec.empty())
2434 m_pData->maShapeListeners.erase(it);
2435 }
2436 }
2437 }
2438
2439 // XDocumentEventBroadcaster
2440
2441
addDocumentEventListener(const Reference<document::XDocumentEventListener> & aListener)2442 void SAL_CALL SfxBaseModel::addDocumentEventListener( const Reference< document::XDocumentEventListener >& aListener )
2443 {
2444 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
2445 m_pData->m_aInterfaceContainer.addInterface( cppu::UnoType<document::XDocumentEventListener>::get(), aListener );
2446 }
2447
2448
removeDocumentEventListener(const Reference<document::XDocumentEventListener> & aListener)2449 void SAL_CALL SfxBaseModel::removeDocumentEventListener( const Reference< document::XDocumentEventListener >& aListener )
2450 {
2451 SfxModelGuard aGuard( *this );
2452 m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<document::XDocumentEventListener>::get(), aListener );
2453 }
2454
2455
notifyDocumentEvent(const OUString &,const Reference<frame::XController2> &,const Any &)2456 void SAL_CALL SfxBaseModel::notifyDocumentEvent( const OUString&, const Reference< frame::XController2 >&, const Any& )
2457 {
2458 throw lang::NoSupportException("SfxBaseModel controls all the sent notifications itself!" );
2459 }
2460
getCmisProperties()2461 Sequence<document::CmisProperty> SAL_CALL SfxBaseModel::getCmisProperties()
2462 {
2463 if (impl_isDisposed())
2464 return Sequence<document::CmisProperty>();
2465 return m_pData->m_cmisProperties;
2466 }
2467
setCmisProperties(const Sequence<document::CmisProperty> & _cmisproperties)2468 void SAL_CALL SfxBaseModel::setCmisProperties( const Sequence< document::CmisProperty >& _cmisproperties )
2469 {
2470 m_pData->m_cmisProperties = _cmisproperties;
2471 }
2472
updateCmisProperties(const Sequence<document::CmisProperty> & aProperties)2473 void SAL_CALL SfxBaseModel::updateCmisProperties( const Sequence< document::CmisProperty >& aProperties )
2474 {
2475 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2476 if ( !pMedium )
2477 return;
2478
2479 try
2480 {
2481 ::ucbhelper::Content aContent( pMedium->GetName( ),
2482 Reference<ucb::XCommandEnvironment>(),
2483 comphelper::getProcessComponentContext() );
2484
2485 aContent.executeCommand( "updateProperties", uno::makeAny( aProperties ) );
2486 loadCmisProperties( );
2487 }
2488 catch (const Exception & e)
2489 {
2490 css::uno::Any anyEx = cppu::getCaughtException();
2491 throw lang::WrappedTargetRuntimeException( e.Message,
2492 e.Context, anyEx );
2493 }
2494
2495 }
2496
checkOut()2497 void SAL_CALL SfxBaseModel::checkOut( )
2498 {
2499 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2500 if ( !pMedium )
2501 return;
2502
2503 try
2504 {
2505 ::ucbhelper::Content aContent( pMedium->GetName(),
2506 Reference<ucb::XCommandEnvironment>(),
2507 comphelper::getProcessComponentContext() );
2508
2509 Any aResult = aContent.executeCommand( "checkout", Any( ) );
2510 OUString sURL;
2511 aResult >>= sURL;
2512
2513 m_pData->m_pObjectShell->GetMedium( )->SetName( sURL );
2514 m_pData->m_pObjectShell->GetMedium( )->GetMedium_Impl( );
2515 m_pData->m_xDocumentProperties->setTitle( getTitle( ) );
2516 Sequence< beans::PropertyValue > aSequence ;
2517 TransformItems( SID_OPENDOC, *pMedium->GetItemSet(), aSequence );
2518 attachResource( sURL, aSequence );
2519
2520 // Reload the CMIS properties
2521 loadCmisProperties( );
2522 }
2523 catch ( const Exception & e )
2524 {
2525 css::uno::Any anyEx = cppu::getCaughtException();
2526 throw lang::WrappedTargetRuntimeException( e.Message,
2527 e.Context, anyEx );
2528 }
2529 }
2530
cancelCheckOut()2531 void SAL_CALL SfxBaseModel::cancelCheckOut( )
2532 {
2533 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2534 if ( !pMedium )
2535 return;
2536
2537 try
2538 {
2539 ::ucbhelper::Content aContent( pMedium->GetName(),
2540 Reference<ucb::XCommandEnvironment>(),
2541 comphelper::getProcessComponentContext() );
2542
2543 Any aResult = aContent.executeCommand( "cancelCheckout", Any( ) );
2544 OUString sURL;
2545 aResult >>= sURL;
2546
2547 m_pData->m_pObjectShell->GetMedium( )->SetName( sURL );
2548 }
2549 catch ( const Exception & e )
2550 {
2551 css::uno::Any anyEx = cppu::getCaughtException();
2552 throw lang::WrappedTargetRuntimeException( e.Message,
2553 e.Context, anyEx );
2554 }
2555 }
2556
checkIn(sal_Bool bIsMajor,const OUString & rMessage)2557 void SAL_CALL SfxBaseModel::checkIn( sal_Bool bIsMajor, const OUString& rMessage )
2558 {
2559 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2560 if ( !pMedium )
2561 return;
2562
2563 try
2564 {
2565 Sequence< beans::PropertyValue > aProps( 3 );
2566 aProps[0].Name = "VersionMajor";
2567 aProps[0].Value <<= bIsMajor;
2568 aProps[1].Name = "VersionComment";
2569 aProps[1].Value <<= rMessage;
2570 aProps[2].Name = "CheckIn";
2571 aProps[2].Value <<= true;
2572
2573 const OUString sName( pMedium->GetName( ) );
2574 storeSelf( aProps );
2575
2576 // Refresh pMedium as it has probably changed during the storeSelf call
2577 pMedium = m_pData->m_pObjectShell->GetMedium( );
2578 const OUString sNewName( pMedium->GetName( ) );
2579
2580 // URL has changed, update the document
2581 if ( sName != sNewName )
2582 {
2583 m_pData->m_xDocumentProperties->setTitle( getTitle( ) );
2584 Sequence< beans::PropertyValue > aSequence ;
2585 TransformItems( SID_OPENDOC, *pMedium->GetItemSet(), aSequence );
2586 attachResource( sNewName, aSequence );
2587
2588 // Reload the CMIS properties
2589 loadCmisProperties( );
2590 }
2591 }
2592 catch ( const Exception & e )
2593 {
2594 css::uno::Any anyEx = cppu::getCaughtException();
2595 throw lang::WrappedTargetRuntimeException( e.Message,
2596 e.Context, anyEx );
2597 }
2598 }
2599
getAllVersions()2600 uno::Sequence< document::CmisVersion > SAL_CALL SfxBaseModel::getAllVersions( )
2601 {
2602 uno::Sequence<document::CmisVersion> aVersions;
2603 if (impl_isDisposed())
2604 return aVersions;
2605 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2606 if ( pMedium )
2607 {
2608 try
2609 {
2610 ::ucbhelper::Content aContent( pMedium->GetName(),
2611 Reference<ucb::XCommandEnvironment>(),
2612 comphelper::getProcessComponentContext() );
2613
2614 Any aResult = aContent.executeCommand( "getAllVersions", Any( ) );
2615 aResult >>= aVersions;
2616 }
2617 catch ( const Exception & e )
2618 {
2619 css::uno::Any anyEx = cppu::getCaughtException();
2620 throw lang::WrappedTargetRuntimeException( e.Message,
2621 e.Context, anyEx );
2622 }
2623 }
2624 return aVersions;
2625 }
2626
getBoolPropertyValue(const OUString & rName)2627 bool SfxBaseModel::getBoolPropertyValue( const OUString& rName )
2628 {
2629 bool bValue = false;
2630 if ( m_pData->m_pObjectShell.is() )
2631 {
2632 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2633 if ( pMedium )
2634 {
2635 try
2636 {
2637 ::ucbhelper::Content aContent( pMedium->GetName( ),
2638 utl::UCBContentHelper::getDefaultCommandEnvironment(),
2639 comphelper::getProcessComponentContext() );
2640 Reference < beans::XPropertySetInfo > xProps = aContent.getProperties();
2641 if ( xProps->hasPropertyByName( rName ) )
2642 {
2643 aContent.getPropertyValue( rName ) >>= bValue;
2644 }
2645 }
2646 catch ( const Exception & )
2647 {
2648 // Simply ignore it: it's likely the document isn't versionable in that case
2649 bValue = false;
2650 }
2651 }
2652 }
2653 return bValue;
2654 }
2655
isVersionable()2656 sal_Bool SAL_CALL SfxBaseModel::isVersionable( )
2657 {
2658 return getBoolPropertyValue( "IsVersionable" );
2659 }
2660
canCheckOut()2661 sal_Bool SAL_CALL SfxBaseModel::canCheckOut( )
2662 {
2663 return getBoolPropertyValue( "CanCheckOut" );
2664 }
2665
canCancelCheckOut()2666 sal_Bool SAL_CALL SfxBaseModel::canCancelCheckOut( )
2667 {
2668 return getBoolPropertyValue( "CanCancelCheckOut" );
2669 }
2670
canCheckIn()2671 sal_Bool SAL_CALL SfxBaseModel::canCheckIn( )
2672 {
2673 return getBoolPropertyValue( "CanCheckIn" );
2674 }
2675
loadCmisProperties()2676 void SfxBaseModel::loadCmisProperties( )
2677 {
2678 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2679 if ( !pMedium )
2680 return;
2681
2682 try
2683 {
2684 ::ucbhelper::Content aContent( pMedium->GetName( ),
2685 utl::UCBContentHelper::getDefaultCommandEnvironment(),
2686 comphelper::getProcessComponentContext() );
2687 Reference < beans::XPropertySetInfo > xProps = aContent.getProperties();
2688 const OUString aCmisProps( "CmisProperties" );
2689 if ( xProps->hasPropertyByName( aCmisProps ) )
2690 {
2691 Sequence< document::CmisProperty> aCmisProperties;
2692 aContent.getPropertyValue( aCmisProps ) >>= aCmisProperties;
2693 setCmisProperties( aCmisProperties );
2694 }
2695 }
2696 catch (const ucb::ContentCreationException &)
2697 {
2698 }
2699 catch (const ucb::CommandAbortedException &)
2700 {
2701 }
2702 }
2703
handleLoadError(ErrCode nError,SfxMedium * pMedium)2704 SfxMedium* SfxBaseModel::handleLoadError( ErrCode nError, SfxMedium* pMedium )
2705 {
2706 if (!nError)
2707 {
2708 // No error condition.
2709 return pMedium;
2710 }
2711
2712 bool bSilent = false;
2713 const SfxBoolItem* pSilentItem = SfxItemSet::GetItem<SfxBoolItem>(pMedium->GetItemSet(), SID_SILENT, false);
2714 if( pSilentItem )
2715 bSilent = pSilentItem->GetValue();
2716
2717 bool bWarning = nError.IsWarning();
2718 if ( nError != ERRCODE_IO_BROKENPACKAGE && !bSilent )
2719 {
2720 // broken package was handled already
2721 if ( SfxObjectShell::UseInteractionToHandleError(pMedium->GetInteractionHandler(), nError) && !bWarning)
2722 {
2723 // abort loading (except for warnings)
2724 nError = ERRCODE_IO_ABORT;
2725 }
2726 }
2727
2728 if ( m_pData->m_pObjectShell->GetMedium() != pMedium )
2729 {
2730 // for whatever reason document now has another medium
2731 OSL_FAIL("Document has rejected the medium?!");
2732 delete pMedium;
2733 pMedium = nullptr;
2734 }
2735
2736 if ( !bWarning ) // #i30711# don't abort loading if it's only a warning
2737 {
2738 nError = nError ? nError : ERRCODE_IO_CANTREAD;
2739 throw task::ErrorCodeIOException(
2740 "SfxBaseModel::handleLoadError: 0x" + nError.toHexString(),
2741 Reference< XInterface >(), sal_uInt32(nError));
2742 }
2743
2744 return pMedium;
2745 }
2746
2747
2748 // SfxListener
2749
2750
addTitle_Impl(Sequence<beans::PropertyValue> & rSeq,const OUString & rTitle)2751 static void addTitle_Impl( Sequence < beans::PropertyValue >& rSeq, const OUString& rTitle )
2752 {
2753 auto pProp = std::find_if(rSeq.begin(), rSeq.end(),
2754 [](const beans::PropertyValue& rProp) { return rProp.Name == "Title"; });
2755 if (pProp != rSeq.end())
2756 {
2757 pProp->Value <<= rTitle;
2758 }
2759 else
2760 {
2761 sal_Int32 nCount = rSeq.getLength();
2762 rSeq.realloc( nCount+1 );
2763 rSeq[nCount].Name = "Title";
2764 rSeq[nCount].Value <<= rTitle;
2765 }
2766 }
2767
Notify(SfxBroadcaster & rBC,const SfxHint & rHint)2768 void SfxBaseModel::Notify( SfxBroadcaster& rBC ,
2769 const SfxHint& rHint )
2770 {
2771 if ( !m_pData )
2772 return;
2773
2774 if ( &rBC != m_pData->m_pObjectShell.get() )
2775 return;
2776
2777 if ( rHint.GetId() == SfxHintId::DocChanged )
2778 changing();
2779
2780 const SfxEventHint* pNamedHint = dynamic_cast<const SfxEventHint*>(&rHint);
2781 if ( pNamedHint )
2782 {
2783
2784 switch ( pNamedHint->GetEventId() )
2785 {
2786 case SfxEventHintId::StorageChanged:
2787 {
2788 if ( m_pData->m_xUIConfigurationManager.is()
2789 && m_pData->m_pObjectShell->GetCreateMode() != SfxObjectCreateMode::EMBEDDED )
2790 {
2791 Reference< embed::XStorage > xConfigStorage;
2792 const OUString aUIConfigFolderName( "Configurations2" );
2793
2794 xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, embed::ElementModes::READWRITE );
2795 if ( !xConfigStorage.is() )
2796 xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, embed::ElementModes::READ );
2797
2798 if ( xConfigStorage.is() || !m_pData->m_pObjectShell->GetStorage()->hasByName( aUIConfigFolderName ) )
2799 {
2800 // the storage is different, since otherwise it could not be opened, so it must be exchanged
2801 m_pData->m_xUIConfigurationManager->setStorage( xConfigStorage );
2802 }
2803 else
2804 {
2805 OSL_FAIL( "Unexpected scenario!" );
2806 }
2807 }
2808
2809 ListenForStorage_Impl( m_pData->m_pObjectShell->GetStorage() );
2810 }
2811 break;
2812
2813 case SfxEventHintId::LoadFinished:
2814 {
2815 impl_getPrintHelper();
2816 ListenForStorage_Impl( m_pData->m_pObjectShell->GetStorage() );
2817 m_pData->m_bModifiedSinceLastSave = false;
2818 }
2819 break;
2820
2821 case SfxEventHintId::SaveAsDocDone:
2822 {
2823 m_pData->m_sURL = m_pData->m_pObjectShell->GetMedium()->GetName();
2824
2825 SfxItemSet *pSet = m_pData->m_pObjectShell->GetMedium()->GetItemSet();
2826 Sequence< beans::PropertyValue > aArgs;
2827 TransformItems( SID_SAVEASDOC, *pSet, aArgs );
2828 addTitle_Impl( aArgs, m_pData->m_pObjectShell->GetTitle() );
2829 attachResource( m_pData->m_pObjectShell->GetMedium()->GetName(), aArgs );
2830 }
2831 break;
2832
2833 case SfxEventHintId::DocCreated:
2834 {
2835 impl_getPrintHelper();
2836 m_pData->m_bModifiedSinceLastSave = false;
2837 }
2838 break;
2839
2840 case SfxEventHintId::ModifyChanged:
2841 {
2842 m_pData->m_bModifiedSinceLastSave = isModified();
2843 }
2844 break;
2845 default: break;
2846 }
2847
2848 const SfxViewEventHint* pViewHint = dynamic_cast<const SfxViewEventHint*>(&rHint);
2849 postEvent_Impl( pNamedHint->GetEventName(), pViewHint ? pViewHint->GetController() : Reference< frame::XController2 >() );
2850 }
2851
2852 if ( rHint.GetId() == SfxHintId::TitleChanged )
2853 {
2854 addTitle_Impl( m_pData->m_seqArguments, m_pData->m_pObjectShell->GetTitle() );
2855 postEvent_Impl( GlobalEventConfig::GetEventName( GlobalEventId::TITLECHANGED ) );
2856 }
2857 else if ( rHint.GetId() == SfxHintId::ModeChanged )
2858 {
2859 postEvent_Impl( GlobalEventConfig::GetEventName( GlobalEventId::MODECHANGED ) );
2860 }
2861 }
2862
2863
2864 // public impl.
2865
2866
NotifyModifyListeners_Impl() const2867 void SfxBaseModel::NotifyModifyListeners_Impl() const
2868 {
2869 ::cppu::OInterfaceContainerHelper* pIC = m_pData->m_aInterfaceContainer.getContainer( cppu::UnoType<util::XModifyListener>::get());
2870 if ( pIC )
2871 {
2872 lang::EventObject aEvent( static_cast<frame::XModel *>(const_cast<SfxBaseModel *>(this)) );
2873 pIC->notifyEach( &util::XModifyListener::modified, aEvent );
2874 }
2875
2876 // this notification here is done too generously, we cannot simply assume that we're really modified
2877 // now, but we need to check it ...
2878 m_pData->m_bModifiedSinceLastSave = const_cast< SfxBaseModel* >( this )->isModified();
2879 }
2880
changing()2881 void SfxBaseModel::changing()
2882 {
2883 SfxModelGuard aGuard( *this );
2884
2885 // the notification should not be sent if the document can not be modified
2886 if ( !m_pData->m_pObjectShell.is() || !m_pData->m_pObjectShell->IsEnableSetModified() )
2887 return;
2888
2889 NotifyModifyListeners_Impl();
2890 }
2891
2892
2893 // public impl.
2894
2895
GetObjectShell() const2896 SfxObjectShell* SfxBaseModel::GetObjectShell() const
2897 {
2898 return m_pData ? m_pData->m_pObjectShell.get() : nullptr;
2899 }
2900
2901
2902 // public impl.
2903
2904
IsInitialized() const2905 bool SfxBaseModel::IsInitialized() const
2906 {
2907 if ( !m_pData || !m_pData->m_pObjectShell.is() )
2908 {
2909 OSL_FAIL( "SfxBaseModel::IsInitialized: this should have been caught earlier!" );
2910 return false;
2911 }
2912
2913 return m_pData->m_pObjectShell->GetMedium() != nullptr;
2914 }
2915
MethodEntryCheck(const bool i_mustBeInitialized) const2916 void SfxBaseModel::MethodEntryCheck( const bool i_mustBeInitialized ) const
2917 {
2918 if ( impl_isDisposed() )
2919 throw lang::DisposedException( OUString(), *const_cast< SfxBaseModel* >( this ) );
2920 if ( i_mustBeInitialized && !IsInitialized() )
2921 throw lang::NotInitializedException( OUString(), *const_cast< SfxBaseModel* >( this ) );
2922 }
2923
impl_isDisposed() const2924 bool SfxBaseModel::impl_isDisposed() const
2925 {
2926 return ( m_pData == nullptr ) ;
2927 }
2928
2929
2930 // private impl.
2931
2932
GetMediumFilterName_Impl() const2933 OUString SfxBaseModel::GetMediumFilterName_Impl() const
2934 {
2935 std::shared_ptr<const SfxFilter> pFilter;
2936 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2937 if ( pMedium )
2938 pFilter = pMedium->GetFilter();
2939
2940 if ( pFilter )
2941 return pFilter->GetName();
2942
2943 return OUString();
2944 }
2945
impl_store(const OUString & sURL,const Sequence<beans::PropertyValue> & seqArguments,bool bSaveTo)2946 void SfxBaseModel::impl_store( const OUString& sURL ,
2947 const Sequence< beans::PropertyValue >& seqArguments ,
2948 bool bSaveTo )
2949 {
2950 if( sURL.isEmpty() )
2951 throw frame::IllegalArgumentIOException();
2952
2953 bool bSaved = false;
2954 if ( !bSaveTo && m_pData->m_pObjectShell.is() && !sURL.isEmpty()
2955 && !sURL.startsWith( "private:stream" )
2956 && ::utl::UCBContentHelper::EqualURLs( getLocation(), sURL ) )
2957 {
2958 // this is the same file URL as the current document location, try to use storeOwn if possible
2959
2960 ::comphelper::SequenceAsHashMap aArgHash( seqArguments );
2961 const OUString aFilterString( "FilterName" );
2962 const OUString aFilterName( aArgHash.getUnpackedValueOrDefault( aFilterString, OUString() ) );
2963 if ( !aFilterName.isEmpty() )
2964 {
2965 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
2966 if ( pMedium )
2967 {
2968 const std::shared_ptr<const SfxFilter>& pFilter = pMedium->GetFilter();
2969 if ( pFilter && aFilterName == pFilter->GetFilterName() )
2970 {
2971 // #i119366# - If the former file saving with password, do not trying in StoreSelf anyway...
2972 bool bFormerPassword = false;
2973 {
2974 uno::Sequence< beans::NamedValue > aOldEncryptionData;
2975 if (GetEncryptionData_Impl( pMedium->GetItemSet(), aOldEncryptionData ))
2976 {
2977 bFormerPassword = true;
2978 }
2979 }
2980 if ( !bFormerPassword )
2981 {
2982 aArgHash.erase( aFilterString );
2983 aArgHash.erase( "URL" );
2984
2985 try
2986 {
2987 storeSelf( aArgHash.getAsConstPropertyValueList() );
2988 bSaved = true;
2989 }
2990 catch( const lang::IllegalArgumentException& )
2991 {
2992 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
2993 // some additional arguments do not allow to use saving, SaveAs should be done
2994 // but only for normal documents, the shared documents would be overwritten in this case
2995 // that would mean an information loss
2996 // TODO/LATER: need a new interaction for this case
2997 if ( m_pData->m_pObjectShell->IsDocShared() )
2998 {
2999 uno::Sequence< beans::NamedValue > aNewEncryptionData = aArgHash.getUnpackedValueOrDefault("EncryptionData", uno::Sequence< beans::NamedValue >() );
3000 if ( !aNewEncryptionData.hasElements() )
3001 {
3002 aNewEncryptionData = ::comphelper::OStorageHelper::CreatePackageEncryptionData( aArgHash.getUnpackedValueOrDefault("Password", OUString()) );
3003 }
3004
3005 uno::Sequence< beans::NamedValue > aOldEncryptionData;
3006 (void)GetEncryptionData_Impl( pMedium->GetItemSet(), aOldEncryptionData );
3007
3008 if ( !aOldEncryptionData.hasElements() && !aNewEncryptionData.hasElements() )
3009 throw;
3010 else
3011 {
3012 // if the password is changed a special error should be used in case of shared document
3013 throw task::ErrorCodeIOException("Can not change password for shared document.", uno::Reference< uno::XInterface >(), sal_uInt32(ERRCODE_SFX_SHARED_NOPASSWORDCHANGE) );
3014 }
3015 }
3016 #endif
3017 }
3018 }
3019 }
3020 }
3021 }
3022 }
3023
3024 if ( !(!bSaved && m_pData->m_pObjectShell.is()) )
3025 return;
3026
3027 SfxGetpApp()->NotifyEvent( SfxEventHint( bSaveTo ? SfxEventHintId::SaveToDoc : SfxEventHintId::SaveAsDoc, GlobalEventConfig::GetEventName( bSaveTo ? GlobalEventId::SAVETODOC : GlobalEventId::SAVEASDOC ),
3028 m_pData->m_pObjectShell.get() ) );
3029
3030 std::unique_ptr<SfxAllItemSet> pItemSet(new SfxAllItemSet(SfxGetpApp()->GetPool()));
3031 pItemSet->Put(SfxStringItem(SID_FILE_NAME, sURL));
3032 if ( bSaveTo )
3033 pItemSet->Put(SfxBoolItem(SID_SAVETO, true));
3034
3035 TransformParameters(SID_SAVEASDOC, seqArguments, *pItemSet);
3036
3037 const SfxBoolItem* pCopyStreamItem = pItemSet->GetItem<SfxBoolItem>(SID_COPY_STREAM_IF_POSSIBLE, false);
3038
3039 if ( pCopyStreamItem && pCopyStreamItem->GetValue() && !bSaveTo )
3040 {
3041 throw frame::IllegalArgumentIOException(
3042 "CopyStreamIfPossible parameter is not acceptable for storeAsURL() call!" );
3043 }
3044
3045 sal_uInt32 nModifyPasswordHash = 0;
3046 Sequence< beans::PropertyValue > aModifyPasswordInfo;
3047 const SfxUnoAnyItem* pModifyPasswordInfoItem = pItemSet->GetItem<SfxUnoAnyItem>(SID_MODIFYPASSWORDINFO, false);
3048 if ( pModifyPasswordInfoItem )
3049 {
3050 // it contains either a simple hash or a set of PropertyValues
3051 // TODO/LATER: the sequence of PropertyValue should replace the hash completely in future
3052 sal_Int32 nMPHTmp = 0;
3053 pModifyPasswordInfoItem->GetValue() >>= nMPHTmp;
3054 nModifyPasswordHash = static_cast<sal_uInt32>(nMPHTmp);
3055 pModifyPasswordInfoItem->GetValue() >>= aModifyPasswordInfo;
3056 }
3057 pItemSet->ClearItem(SID_MODIFYPASSWORDINFO);
3058 sal_uInt32 nOldModifyPasswordHash = m_pData->m_pObjectShell->GetModifyPasswordHash();
3059 m_pData->m_pObjectShell->SetModifyPasswordHash( nModifyPasswordHash );
3060 Sequence< beans::PropertyValue > aOldModifyPasswordInfo = m_pData->m_pObjectShell->GetModifyPasswordInfo();
3061 m_pData->m_pObjectShell->SetModifyPasswordInfo( aModifyPasswordInfo );
3062
3063 // since saving a document modifies its DocumentProperties, the current
3064 // DocumentProperties must be saved on "SaveTo", so it can be restored
3065 // after saving
3066 bool bCopyTo = bSaveTo ||
3067 m_pData->m_pObjectShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED;
3068 Reference<document::XDocumentProperties> xOldDocProps;
3069 if ( bCopyTo )
3070 {
3071 xOldDocProps = getDocumentProperties();
3072 const Reference<util::XCloneable> xCloneable(xOldDocProps,
3073 UNO_QUERY_THROW);
3074 const Reference<document::XDocumentProperties> xNewDocProps(
3075 xCloneable->createClone(), UNO_QUERY_THROW);
3076 m_pData->m_xDocumentProperties = xNewDocProps;
3077 }
3078
3079 bool bRet = m_pData->m_pObjectShell->APISaveAs_Impl(sURL, *pItemSet);
3080
3081 if ( bCopyTo )
3082 {
3083 // restore DocumentProperties if a copy was created
3084 m_pData->m_xDocumentProperties = xOldDocProps;
3085 }
3086
3087 Reference < task::XInteractionHandler > xHandler;
3088 const SfxUnoAnyItem* pItem = pItemSet->GetItem<SfxUnoAnyItem>(SID_INTERACTIONHANDLER, false);
3089 if ( pItem )
3090 pItem->GetValue() >>= xHandler;
3091
3092 pItemSet.reset();
3093
3094 ErrCode nErrCode = m_pData->m_pObjectShell->GetErrorCode();
3095 if ( !bRet && !nErrCode )
3096 {
3097 SAL_WARN("sfx.doc", "Storing has failed, no error is set!");
3098 nErrCode = ERRCODE_IO_CANTWRITE;
3099 }
3100 m_pData->m_pObjectShell->ResetError();
3101
3102 if ( bRet )
3103 {
3104 if ( nErrCode )
3105 {
3106 // must be a warning - use Interactionhandler if possible or abandon
3107 if ( xHandler.is() )
3108 {
3109 // TODO/LATER: a general way to set the error context should be available
3110 SfxErrorContext aEc( ERRCTX_SFX_SAVEASDOC, m_pData->m_pObjectShell->GetTitle() );
3111
3112 task::ErrorCodeRequest aErrorCode;
3113 aErrorCode.ErrCode = sal_uInt32(nErrCode);
3114 SfxMedium::CallApproveHandler( xHandler, makeAny( aErrorCode ), false );
3115 }
3116 }
3117
3118 if ( !bSaveTo )
3119 {
3120 m_pData->m_aPreusedFilterName = GetMediumFilterName_Impl();
3121 m_pData->m_pObjectShell->SetModifyPasswordEntered();
3122
3123 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::SaveAsDocDone, GlobalEventConfig::GetEventName(GlobalEventId::SAVEASDOCDONE), m_pData->m_pObjectShell.get() ) );
3124 }
3125 else
3126 {
3127 m_pData->m_pObjectShell->SetModifyPasswordHash( nOldModifyPasswordHash );
3128 m_pData->m_pObjectShell->SetModifyPasswordInfo( aOldModifyPasswordInfo );
3129
3130 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::SaveToDocDone, GlobalEventConfig::GetEventName(GlobalEventId::SAVETODOCDONE), m_pData->m_pObjectShell.get() ) );
3131 }
3132 }
3133 else
3134 {
3135 m_pData->m_pObjectShell->SetModifyPasswordHash( nOldModifyPasswordHash );
3136 m_pData->m_pObjectShell->SetModifyPasswordInfo( aOldModifyPasswordInfo );
3137
3138
3139 SfxGetpApp()->NotifyEvent( SfxEventHint( bSaveTo ? SfxEventHintId::SaveToDocFailed : SfxEventHintId::SaveAsDocFailed, GlobalEventConfig::GetEventName( bSaveTo ? GlobalEventId::SAVETODOCFAILED : GlobalEventId::SAVEASDOCFAILED),
3140 m_pData->m_pObjectShell.get() ) );
3141
3142 std::stringstream aErrCode;
3143 aErrCode << nErrCode;
3144 throw task::ErrorCodeIOException(
3145 "SfxBaseModel::impl_store <" + sURL + "> failed: " + OUString::fromUtf8(aErrCode.str().c_str()),
3146 Reference< XInterface >(), sal_uInt32(nErrCode));
3147 }
3148 }
3149
3150
3151 namespace {
3152 template< typename ListenerT, typename EventT >
3153 class NotifySingleListenerIgnoreRE
3154 {
3155 private:
3156 typedef void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& );
3157 NotificationMethod m_pMethod;
3158 const EventT& m_rEvent;
3159 public:
NotifySingleListenerIgnoreRE(NotificationMethod method,const EventT & event)3160 NotifySingleListenerIgnoreRE( NotificationMethod method, const EventT& event ) : m_pMethod( method ), m_rEvent( event ) { }
3161
operator ()(const Reference<ListenerT> & listener) const3162 void operator()( const Reference<ListenerT>& listener ) const
3163 {
3164 try
3165 {
3166 (listener.get()->*m_pMethod)( m_rEvent );
3167 }
3168 catch( RuntimeException& )
3169 {
3170 // this exception is ignored to avoid problems with invalid listeners, the listener should be probably thrown away in future
3171 }
3172 }
3173 };
3174 } // anonymous namespace
3175
postEvent_Impl(const OUString & aName,const Reference<frame::XController2> & xController)3176 void SfxBaseModel::postEvent_Impl( const OUString& aName, const Reference< frame::XController2 >& xController )
3177 {
3178 // object already disposed?
3179 if ( impl_isDisposed() )
3180 return;
3181
3182 // keep m_pData alive, if notified target would dispose the document
3183 std::shared_ptr<IMPL_SfxBaseModel_DataContainer> pData(m_pData);
3184
3185 // also make sure this object doesn't self-destruct while notifying
3186 rtl::Reference<SfxBaseModel> self(this);
3187
3188 DBG_ASSERT( !aName.isEmpty(), "Empty event name!" );
3189 if (aName.isEmpty())
3190 return;
3191
3192 ::cppu::OInterfaceContainerHelper* pIC =
3193 m_pData->m_aInterfaceContainer.getContainer( cppu::UnoType<document::XDocumentEventListener>::get());
3194 if ( pIC )
3195 {
3196 SAL_INFO("sfx.doc", "SfxDocumentEvent: " + aName);
3197
3198 document::DocumentEvent aDocumentEvent( static_cast<frame::XModel*>(this), aName, xController, Any() );
3199
3200 pIC->forEach< document::XDocumentEventListener, NotifySingleListenerIgnoreRE< document::XDocumentEventListener, document::DocumentEvent > >(
3201 NotifySingleListenerIgnoreRE< document::XDocumentEventListener, document::DocumentEvent >(
3202 &document::XDocumentEventListener::documentEventOccured,
3203 aDocumentEvent ) );
3204 }
3205
3206 pIC = m_pData->m_aInterfaceContainer.getContainer( cppu::UnoType<document::XEventListener>::get());
3207 if ( pIC )
3208 {
3209 SAL_INFO("sfx.doc", "SfxEvent: " + aName);
3210
3211 document::EventObject aEvent( static_cast<frame::XModel*>(this), aName );
3212
3213 pIC->forEach< document::XEventListener, NotifySingleListenerIgnoreRE< document::XEventListener, document::EventObject > >(
3214 NotifySingleListenerIgnoreRE< document::XEventListener, document::EventObject >(
3215 &document::XEventListener::notifyEvent,
3216 aEvent ) );
3217 }
3218
3219 }
3220
getViewData()3221 Reference < container::XIndexAccess > SAL_CALL SfxBaseModel::getViewData()
3222 {
3223 SfxModelGuard aGuard( *this );
3224
3225 if ( m_pData->m_pObjectShell.is() && !m_pData->m_contViewData.is() )
3226 {
3227 SfxViewFrame *pActFrame = SfxViewFrame::Current();
3228 if ( !pActFrame || pActFrame->GetObjectShell() != m_pData->m_pObjectShell.get() )
3229 pActFrame = SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get() );
3230
3231 if ( !pActFrame || !pActFrame->GetViewShell() )
3232 // currently no frame for this document at all or View is under construction
3233 return Reference < container::XIndexAccess >();
3234
3235 m_pData->m_contViewData = document::IndexedPropertyValues::create( ::comphelper::getProcessComponentContext() );
3236
3237 if ( !m_pData->m_contViewData.is() )
3238 {
3239 // error: no container class available!
3240 return Reference < container::XIndexAccess >();
3241 }
3242
3243 Reference < container::XIndexContainer > xCont( m_pData->m_contViewData, UNO_QUERY );
3244 sal_Int32 nCount = 0;
3245 Sequence < beans::PropertyValue > aSeq;
3246 for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get() ); pFrame;
3247 pFrame = SfxViewFrame::GetNext( *pFrame, m_pData->m_pObjectShell.get() ) )
3248 {
3249 bool bIsActive = ( pFrame == pActFrame );
3250 pFrame->GetViewShell()->WriteUserDataSequence( aSeq );
3251 xCont->insertByIndex( bIsActive ? 0 : nCount, Any(aSeq) );
3252 nCount++;
3253 }
3254 }
3255
3256 return m_pData->m_contViewData;
3257 }
3258
setViewData(const Reference<container::XIndexAccess> & aData)3259 void SAL_CALL SfxBaseModel::setViewData( const Reference < container::XIndexAccess >& aData )
3260 {
3261 SfxModelGuard aGuard( *this );
3262
3263 m_pData->m_contViewData = aData;
3264 }
3265
3266 /** calls all XEventListeners */
notifyEvent(const document::EventObject & aEvent) const3267 void SfxBaseModel::notifyEvent( const document::EventObject& aEvent ) const
3268 {
3269 // object already disposed?
3270 if ( impl_isDisposed() )
3271 return;
3272
3273 ::cppu::OInterfaceContainerHelper* pIC = m_pData->m_aInterfaceContainer.getContainer(
3274 cppu::UnoType<document::XEventListener>::get());
3275 if( !pIC )
3276
3277 return;
3278
3279 ::cppu::OInterfaceIteratorHelper aIt( *pIC );
3280 while( aIt.hasMoreElements() )
3281 {
3282 try
3283 {
3284 static_cast<document::XEventListener *>(aIt.next())->notifyEvent( aEvent );
3285 }
3286 catch( RuntimeException& )
3287 {
3288 aIt.remove();
3289 }
3290 }
3291 // for right now, we're only doing the event that this particular performance problem needed
3292 if (aEvent.EventName == "ShapeModified")
3293 {
3294 uno::Reference<drawing::XShape> xShape(aEvent.Source, uno::UNO_QUERY);
3295 if (xShape.is())
3296 {
3297 auto it = m_pData->maShapeListeners.find(xShape);
3298 if (it != m_pData->maShapeListeners.end())
3299 for (auto const & rListenerUnoRef : it->second)
3300 rListenerUnoRef->notifyShapeEvent(aEvent);
3301 }
3302 }
3303 }
3304
3305 /** returns true if someone added a XEventListener to this XEventBroadcaster */
hasEventListeners() const3306 bool SfxBaseModel::hasEventListeners() const
3307 {
3308 return !impl_isDisposed()
3309 && ( (nullptr != m_pData->m_aInterfaceContainer.getContainer( cppu::UnoType<document::XEventListener>::get()) )
3310 || !m_pData->maShapeListeners.empty());
3311 }
3312
addPrintJobListener(const Reference<view::XPrintJobListener> & xListener)3313 void SAL_CALL SfxBaseModel::addPrintJobListener( const Reference< view::XPrintJobListener >& xListener )
3314 {
3315 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
3316
3317 impl_getPrintHelper();
3318 Reference < view::XPrintJobBroadcaster > xPJB( m_pData->m_xPrintable, UNO_QUERY );
3319 if ( xPJB.is() )
3320 xPJB->addPrintJobListener( xListener );
3321 }
3322
removePrintJobListener(const Reference<view::XPrintJobListener> & xListener)3323 void SAL_CALL SfxBaseModel::removePrintJobListener( const Reference< view::XPrintJobListener >& xListener )
3324 {
3325 SfxModelGuard aGuard( *this );
3326
3327 impl_getPrintHelper();
3328 Reference < view::XPrintJobBroadcaster > xPJB( m_pData->m_xPrintable, UNO_QUERY );
3329 if ( xPJB.is() )
3330 xPJB->removePrintJobListener( xListener );
3331 }
3332
getSomething(const Sequence<sal_Int8> & aIdentifier)3333 sal_Int64 SAL_CALL SfxBaseModel::getSomething( const Sequence< sal_Int8 >& aIdentifier )
3334 {
3335 SvGlobalName aName( aIdentifier );
3336 if (aName == SvGlobalName( SFX_GLOBAL_CLASSID ))
3337 {
3338 SolarMutexGuard aGuard;
3339 SfxObjectShell *const pObjectShell(GetObjectShell());
3340 if (pObjectShell)
3341 {
3342 return reinterpret_cast<sal_Int64>(pObjectShell);
3343 }
3344 }
3345
3346 return 0;
3347 }
3348
3349
3350 // XDocumentSubStorageSupplier
3351
3352
ListenForStorage_Impl(const Reference<embed::XStorage> & xStorage)3353 void SfxBaseModel::ListenForStorage_Impl( const Reference< embed::XStorage >& xStorage )
3354 {
3355 Reference< util::XModifiable > xModifiable( xStorage, UNO_QUERY );
3356 if ( xModifiable.is() )
3357 {
3358 if ( !m_pData->m_pStorageModifyListen.is() )
3359 {
3360 m_pData->m_pStorageModifyListen = new ::sfx2::DocumentStorageModifyListener( *m_pData, Application::GetSolarMutex() );
3361 }
3362
3363 // no need to deregister the listening for old storage since it should be disposed automatically
3364 xModifiable->addModifyListener( m_pData->m_pStorageModifyListen.get() );
3365 }
3366 }
3367
getDocumentSubStorage(const OUString & aStorageName,sal_Int32 nMode)3368 Reference< embed::XStorage > SAL_CALL SfxBaseModel::getDocumentSubStorage( const OUString& aStorageName, sal_Int32 nMode )
3369 {
3370 SfxModelGuard aGuard( *this );
3371
3372 Reference< embed::XStorage > xResult;
3373 if ( m_pData->m_pObjectShell.is() )
3374 {
3375 Reference< embed::XStorage > xStorage = m_pData->m_pObjectShell->GetStorage();
3376 if ( xStorage.is() )
3377 {
3378 try
3379 {
3380 xResult = xStorage->openStorageElement( aStorageName, nMode );
3381 }
3382 catch ( Exception& )
3383 {
3384 }
3385 }
3386 }
3387
3388 return xResult;
3389 }
3390
getDocumentSubStoragesNames()3391 Sequence< OUString > SAL_CALL SfxBaseModel::getDocumentSubStoragesNames()
3392 {
3393 SfxModelGuard aGuard( *this );
3394
3395 Sequence< OUString > aResult;
3396 bool bSuccess = false;
3397 if ( m_pData->m_pObjectShell.is() )
3398 {
3399 Reference < embed::XStorage > xStorage = m_pData->m_pObjectShell->GetStorage();
3400 if ( xStorage.is() )
3401 {
3402 const Sequence< OUString > aTemp = xStorage->getElementNames();
3403 sal_Int32 nResultSize = 0;
3404 for ( const auto& rName : aTemp )
3405 {
3406 if ( xStorage->isStorageElement( rName ) )
3407 {
3408 aResult.realloc( ++nResultSize );
3409 aResult[ nResultSize - 1 ] = rName;
3410 }
3411 }
3412
3413 bSuccess = true;
3414 }
3415 }
3416
3417 if ( !bSuccess )
3418 throw io::IOException();
3419
3420 return aResult;
3421 }
3422
3423
3424 // XScriptProviderSupplier
3425
3426
getScriptProvider()3427 Reference< script::provider::XScriptProvider > SAL_CALL SfxBaseModel::getScriptProvider()
3428 {
3429 SfxModelGuard aGuard( *this );
3430
3431 Reference< script::provider::XScriptProviderFactory > xScriptProviderFactory =
3432 script::provider::theMasterScriptProviderFactory::get( ::comphelper::getProcessComponentContext() );
3433
3434 Reference< XScriptInvocationContext > xScriptContext( this );
3435
3436 Reference< script::provider::XScriptProvider > xScriptProvider(
3437 xScriptProviderFactory->createScriptProvider( makeAny( xScriptContext ) ),
3438 UNO_SET_THROW );
3439
3440 return xScriptProvider;
3441 }
3442
3443
3444 // XUIConfigurationManagerSupplier
3445
3446
getRuntimeUID() const3447 OUString const & SfxBaseModel::getRuntimeUID() const
3448 {
3449 OSL_ENSURE( !m_pData->m_sRuntimeUID.isEmpty(),
3450 "SfxBaseModel::getRuntimeUID - ID is empty!" );
3451 return m_pData->m_sRuntimeUID;
3452 }
3453
hasValidSignatures() const3454 bool SfxBaseModel::hasValidSignatures() const
3455 {
3456 SolarMutexGuard aGuard;
3457 if ( m_pData->m_pObjectShell.is() )
3458 return ( m_pData->m_pObjectShell->ImplGetSignatureState() == SignatureState::OK );
3459 return false;
3460 }
3461
getGrabBagItem(css::uno::Any & rVal) const3462 void SfxBaseModel::getGrabBagItem(css::uno::Any& rVal) const
3463 {
3464 if (m_pData->m_xGrabBagItem.get())
3465 m_pData->m_xGrabBagItem->QueryValue(rVal);
3466 else
3467 rVal <<= uno::Sequence<beans::PropertyValue>();
3468 }
3469
setGrabBagItem(const css::uno::Any & rVal)3470 void SfxBaseModel::setGrabBagItem(const css::uno::Any& rVal)
3471 {
3472 if (!m_pData->m_xGrabBagItem.get())
3473 m_pData->m_xGrabBagItem.reset(new SfxGrabBagItem);
3474
3475 m_pData->m_xGrabBagItem->PutValue(rVal, 0);
3476 }
3477
GetCommandFromSequence(OUString & rCommand,sal_Int32 & nIndex,const Sequence<beans::PropertyValue> & rSeqPropValue)3478 static void GetCommandFromSequence( OUString& rCommand, sal_Int32& nIndex, const Sequence< beans::PropertyValue >& rSeqPropValue )
3479 {
3480 nIndex = -1;
3481
3482 auto pPropValue = std::find_if(rSeqPropValue.begin(), rSeqPropValue.end(),
3483 [](const beans::PropertyValue& rPropValue) { return rPropValue.Name == "Command"; });
3484 if (pPropValue != rSeqPropValue.end())
3485 {
3486 pPropValue->Value >>= rCommand;
3487 nIndex = static_cast<sal_Int32>(std::distance(rSeqPropValue.begin(), pPropValue));
3488 }
3489 }
3490
ConvertSlotsToCommands(SfxObjectShell const * pDoc,Reference<container::XIndexContainer> const & rToolbarDefinition)3491 static void ConvertSlotsToCommands( SfxObjectShell const * pDoc, Reference< container::XIndexContainer > const & rToolbarDefinition )
3492 {
3493 if ( !pDoc )
3494 return;
3495
3496 SfxModule* pModule( pDoc->GetFactory().GetModule() );
3497 Sequence< beans::PropertyValue > aSeqPropValue;
3498
3499 for ( sal_Int32 i = 0; i < rToolbarDefinition->getCount(); i++ )
3500 {
3501 sal_Int32 nIndex( -1 );
3502 OUString aCommand;
3503
3504 if ( rToolbarDefinition->getByIndex( i ) >>= aSeqPropValue )
3505 {
3506 GetCommandFromSequence( aCommand, nIndex, aSeqPropValue );
3507 if ( nIndex >= 0 && aCommand.startsWith( "slot:" ) )
3508 {
3509 const sal_uInt16 nSlot = aCommand.copy( 5 ).toInt32();
3510
3511 // We have to replace the old "slot-Command" with our new ".uno:-Command"
3512 const SfxSlot* pSlot = pModule->GetSlotPool()->GetSlot( nSlot );
3513 if ( pSlot )
3514 {
3515 OUStringBuffer aStrBuf( ".uno:" );
3516 aStrBuf.appendAscii( pSlot->GetUnoName() );
3517
3518 aCommand = aStrBuf.makeStringAndClear();
3519 aSeqPropValue[nIndex].Value <<= aCommand;
3520 rToolbarDefinition->replaceByIndex( i, Any( aSeqPropValue ));
3521 }
3522 }
3523 }
3524 }
3525 }
3526
getUIConfigurationManager()3527 Reference< ui::XUIConfigurationManager > SAL_CALL SfxBaseModel::getUIConfigurationManager()
3528 {
3529 return Reference< ui::XUIConfigurationManager >( getUIConfigurationManager2(), UNO_QUERY_THROW );
3530 }
3531
getUIConfigurationManager2()3532 Reference< ui::XUIConfigurationManager2 > SfxBaseModel::getUIConfigurationManager2()
3533 {
3534 SfxModelGuard aGuard( *this );
3535
3536 if ( !m_pData->m_xUIConfigurationManager.is() )
3537 {
3538 Reference< ui::XUIConfigurationManager2 > xNewUIConfMan =
3539 ui::UIConfigurationManager::create( comphelper::getProcessComponentContext() );
3540
3541 Reference< embed::XStorage > xConfigStorage;
3542
3543 OUString aUIConfigFolderName( "Configurations2" );
3544 // First try to open with READWRITE and then READ
3545 xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, embed::ElementModes::READWRITE );
3546 if ( xConfigStorage.is() )
3547 {
3548 const OUString aMediaTypeProp( "MediaType" );
3549 OUString aMediaType;
3550 Reference< beans::XPropertySet > xPropSet( xConfigStorage, UNO_QUERY );
3551 Any a = xPropSet->getPropertyValue( aMediaTypeProp );
3552 if ( !( a >>= aMediaType ) || aMediaType.isEmpty())
3553 {
3554 xPropSet->setPropertyValue( aMediaTypeProp, Any(OUString("application/vnd.sun.xml.ui.configuration")) );
3555 }
3556 }
3557 else
3558 xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, embed::ElementModes::READ );
3559
3560 // initialize ui configuration manager with document substorage
3561 xNewUIConfMan->setStorage( xConfigStorage );
3562
3563 // embedded objects did not support local configuration data until OOo 3.0, so there's nothing to
3564 // migrate
3565 if ( m_pData->m_pObjectShell->GetCreateMode() != SfxObjectCreateMode::EMBEDDED )
3566 {
3567 // Import old UI configuration from OOo 1.x
3568
3569 // Try to open with READ
3570 Reference< embed::XStorage > xOOo1ConfigStorage = getDocumentSubStorage( "Configurations", embed::ElementModes::READ );
3571 if ( xOOo1ConfigStorage.is() )
3572 {
3573 Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
3574 std::vector< Reference< container::XIndexContainer > > rToolbars;
3575
3576 bool bImported = framework::UIConfigurationImporterOOo1x::ImportCustomToolbars(
3577 xNewUIConfMan, rToolbars, xContext, xOOo1ConfigStorage );
3578 if ( bImported )
3579 {
3580 SfxObjectShell* pObjShell = SfxBaseModel::GetObjectShell();
3581
3582 for ( size_t i = 0; i < rToolbars.size(); i++ )
3583 {
3584 const OUString sId(OUString::number( i + 1 ));
3585 const OUString aCustomTbxName = "private:resource/toolbar/custom_OOo1x_" + sId;
3586
3587 Reference< container::XIndexContainer > xToolbar = rToolbars[i];
3588 ConvertSlotsToCommands( pObjShell, xToolbar );
3589 if ( !xNewUIConfMan->hasSettings( aCustomTbxName ))
3590 {
3591 // Set UIName for the toolbar with container property
3592 Reference< beans::XPropertySet > xPropSet( xToolbar, UNO_QUERY );
3593 if ( xPropSet.is() )
3594 {
3595 try
3596 {
3597 xPropSet->setPropertyValue( "UIName", Any( "Toolbar " + sId ) );
3598 }
3599 catch ( beans::UnknownPropertyException& )
3600 {
3601 }
3602 }
3603
3604 xNewUIConfMan->insertSettings( aCustomTbxName, xToolbar );
3605 xNewUIConfMan->store();
3606 }
3607 }
3608 }
3609 }
3610 }
3611
3612 m_pData->m_xUIConfigurationManager = xNewUIConfMan;
3613 }
3614
3615 return m_pData->m_xUIConfigurationManager;
3616 }
3617
3618
3619 // XVisualObject
3620
3621
setVisualAreaSize(sal_Int64 nAspect,const awt::Size & aSize)3622 void SAL_CALL SfxBaseModel::setVisualAreaSize( sal_Int64 nAspect, const awt::Size& aSize )
3623 {
3624 SfxModelGuard aGuard( *this );
3625
3626 if ( !m_pData->m_pObjectShell.is() )
3627 throw Exception("no object shell", nullptr); // TODO: error handling
3628
3629 SfxViewFrame* pViewFrm = SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get(), false );
3630 if ( pViewFrm && m_pData->m_pObjectShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED && !pViewFrm->GetFrame().IsInPlace() )
3631 {
3632 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( pViewFrm->GetFrame().GetFrameInterface()->getContainerWindow() );
3633 Size aWinSize = pWindow->GetSizePixel();
3634 awt::Size aCurrent = getVisualAreaSize( nAspect );
3635 Size aDiff( aSize.Width-aCurrent.Width, aSize.Height-aCurrent.Height );
3636 aDiff = pViewFrm->GetViewShell()->GetWindow()->LogicToPixel( aDiff );
3637 aWinSize.AdjustWidth(aDiff.Width() );
3638 aWinSize.AdjustHeight(aDiff.Height() );
3639 pWindow->SetSizePixel( aWinSize );
3640 }
3641 else
3642 {
3643 tools::Rectangle aTmpRect = m_pData->m_pObjectShell->GetVisArea( ASPECT_CONTENT );
3644 aTmpRect.SetSize( Size( aSize.Width, aSize.Height ) );
3645 m_pData->m_pObjectShell->SetVisArea( aTmpRect );
3646 }
3647 }
3648
getVisualAreaSize(sal_Int64)3649 awt::Size SAL_CALL SfxBaseModel::getVisualAreaSize( sal_Int64 /*nAspect*/ )
3650 {
3651 SfxModelGuard aGuard( *this );
3652
3653 if ( !m_pData->m_pObjectShell.is() )
3654 throw Exception("no object shell", nullptr); // TODO: error handling
3655
3656 tools::Rectangle aTmpRect = m_pData->m_pObjectShell->GetVisArea( ASPECT_CONTENT );
3657
3658 return awt::Size( aTmpRect.GetWidth(), aTmpRect.GetHeight() );
3659 }
3660
3661
getMapUnit(sal_Int64)3662 sal_Int32 SAL_CALL SfxBaseModel::getMapUnit( sal_Int64 /*nAspect*/ )
3663 {
3664 SfxModelGuard aGuard( *this );
3665
3666 if ( !m_pData->m_pObjectShell.is() )
3667 throw Exception("no object shell", nullptr); // TODO: error handling
3668
3669 return VCLUnoHelper::VCL2UnoEmbedMapUnit( m_pData->m_pObjectShell->GetMapUnit() );
3670 }
3671
getPreferredVisualRepresentation(::sal_Int64)3672 embed::VisualRepresentation SAL_CALL SfxBaseModel::getPreferredVisualRepresentation( ::sal_Int64 /*nAspect*/ )
3673 {
3674 SfxModelGuard aGuard( *this );
3675
3676 datatransfer::DataFlavor aDataFlavor(
3677 "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"",
3678 "GDIMetaFile",
3679 cppu::UnoType<Sequence< sal_Int8 >>::get() );
3680
3681 embed::VisualRepresentation aVisualRepresentation;
3682 aVisualRepresentation.Data = getTransferData( aDataFlavor );
3683 aVisualRepresentation.Flavor = aDataFlavor;
3684
3685 return aVisualRepresentation;
3686 }
3687
3688
3689 // XStorageBasedDocument
3690
3691
loadFromStorage(const Reference<embed::XStorage> & xStorage,const Sequence<beans::PropertyValue> & aMediaDescriptor)3692 void SAL_CALL SfxBaseModel::loadFromStorage( const Reference< embed::XStorage >& xStorage,
3693 const Sequence< beans::PropertyValue >& aMediaDescriptor )
3694 {
3695 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
3696 if ( IsInitialized() )
3697 throw frame::DoubleInitializationException( OUString(), *this );
3698
3699 // after i36090 is fixed the pool from object shell can be used
3700 // SfxAllItemSet aSet( m_pData->m_pObjectShell->GetPool() );
3701 SfxAllItemSet aSet( SfxGetpApp()->GetPool() );
3702
3703 // the BaseURL is part of the ItemSet
3704 SfxMedium* pMedium = new SfxMedium( xStorage, OUString() );
3705 TransformParameters( SID_OPENDOC, aMediaDescriptor, aSet );
3706 pMedium->GetItemSet()->Put( aSet );
3707
3708 // allow to use an interactionhandler (if there is one)
3709 pMedium->UseInteractionHandler( true );
3710
3711 const SfxBoolItem* pTemplateItem = aSet.GetItem<SfxBoolItem>(SID_TEMPLATE, false);
3712 bool bTemplate = pTemplateItem && pTemplateItem->GetValue();
3713 m_pData->m_pObjectShell->SetActivateEvent_Impl( bTemplate ? SfxEventHintId::CreateDoc : SfxEventHintId::OpenDoc );
3714 m_pData->m_pObjectShell->Get_Impl()->bOwnsStorage = false;
3715
3716 // load document
3717 if ( !m_pData->m_pObjectShell->DoLoad(pMedium) )
3718 {
3719 ErrCode nError = m_pData->m_pObjectShell->GetErrorCode();
3720 nError = nError ? nError : ERRCODE_IO_CANTREAD;
3721 throw task::ErrorCodeIOException(
3722 "SfxBaseModel::loadFromStorage: " + nError.toHexString(),
3723 Reference< XInterface >(), sal_uInt32(nError));
3724 }
3725 loadCmisProperties( );
3726 }
3727
storeToStorage(const Reference<embed::XStorage> & xStorage,const Sequence<beans::PropertyValue> & aMediaDescriptor)3728 void SAL_CALL SfxBaseModel::storeToStorage( const Reference< embed::XStorage >& xStorage,
3729 const Sequence< beans::PropertyValue >& aMediaDescriptor )
3730 {
3731 SfxModelGuard aGuard( *this );
3732
3733 if ( !m_pData->m_pObjectShell.is() )
3734 throw io::IOException(); // TODO:
3735
3736 std::shared_ptr<SfxAllItemSet> xSet( new SfxAllItemSet(m_pData->m_pObjectShell->GetPool()) );
3737 TransformParameters( SID_SAVEASDOC, aMediaDescriptor, *xSet );
3738
3739 // TODO/LATER: maybe a special URL "private:storage" should be used
3740 const SfxStringItem* pItem = xSet->GetItem<SfxStringItem>(SID_FILTER_NAME, false);
3741 sal_Int32 nVersion = SOFFICE_FILEFORMAT_CURRENT;
3742 if( pItem )
3743 {
3744 std::shared_ptr<const SfxFilter> pFilter = SfxGetpApp()->GetFilterMatcher().GetFilter4FilterName( pItem->GetValue() );
3745 if ( pFilter && pFilter->UsesStorage() )
3746 nVersion = pFilter->GetVersion();
3747 }
3748
3749 bool bSuccess = false;
3750 if ( xStorage == m_pData->m_pObjectShell->GetStorage() )
3751 {
3752 // storing to the own storage
3753 bSuccess = m_pData->m_pObjectShell->DoSave();
3754 }
3755 else
3756 {
3757 // TODO/LATER: if the provided storage has some data inside the storing might fail, probably the storage must be truncated
3758 // TODO/LATER: is it possible to have a template here?
3759 m_pData->m_pObjectShell->SetupStorage( xStorage, nVersion, false );
3760
3761 // BaseURL is part of the ItemSet
3762 SfxMedium aMedium( xStorage, OUString(), xSet );
3763 aMedium.CanDisposeStorage_Impl( false );
3764 if ( aMedium.GetFilter() )
3765 {
3766 // storing without a valid filter will often crash
3767 bSuccess = m_pData->m_pObjectShell->DoSaveObjectAs( aMedium, true );
3768 m_pData->m_pObjectShell->DoSaveCompleted();
3769 }
3770 }
3771
3772 ErrCode nError = m_pData->m_pObjectShell->GetErrorCode();
3773 m_pData->m_pObjectShell->ResetError();
3774
3775 // the warnings are currently not transported
3776 if ( !bSuccess )
3777 {
3778 nError = nError ? nError : ERRCODE_IO_GENERAL;
3779 throw task::ErrorCodeIOException(
3780 "SfxBaseModel::storeToStorage: " + nError.toHexString(),
3781 Reference< XInterface >(), sal_uInt32(nError));
3782 }
3783 }
3784
switchToStorage(const Reference<embed::XStorage> & xStorage)3785 void SAL_CALL SfxBaseModel::switchToStorage( const Reference< embed::XStorage >& xStorage )
3786 {
3787 SfxModelGuard aGuard( *this );
3788
3789 if ( !m_pData->m_pObjectShell.is() )
3790 throw io::IOException(); // TODO:
3791
3792 // the persistence should be switched only if the storage is different
3793 if ( xStorage != m_pData->m_pObjectShell->GetStorage() )
3794 {
3795 if ( !m_pData->m_pObjectShell->SwitchPersistance( xStorage ) )
3796 {
3797 ErrCode nError = m_pData->m_pObjectShell->GetErrorCode();
3798 nError = nError ? nError : ERRCODE_IO_GENERAL;
3799 throw task::ErrorCodeIOException(
3800 "SfxBaseModel::switchToStorage: " + nError.toHexString(),
3801 Reference< XInterface >(), sal_uInt32(nError));
3802 }
3803 else
3804 {
3805 // UICfgMgr has a reference to the old storage, update it
3806 getUIConfigurationManager2()->setStorage( xStorage );
3807 }
3808 }
3809 m_pData->m_pObjectShell->Get_Impl()->bOwnsStorage = false;
3810 }
3811
getDocumentStorage()3812 Reference< embed::XStorage > SAL_CALL SfxBaseModel::getDocumentStorage()
3813 {
3814 SfxModelGuard aGuard( *this );
3815
3816 if ( !m_pData->m_pObjectShell.is() )
3817 throw io::IOException(); // TODO
3818
3819 return m_pData->m_pObjectShell->GetStorage();
3820 }
3821
addStorageChangeListener(const Reference<document::XStorageChangeListener> & xListener)3822 void SAL_CALL SfxBaseModel::addStorageChangeListener(
3823 const Reference< document::XStorageChangeListener >& xListener )
3824 {
3825 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
3826
3827 m_pData->m_aInterfaceContainer.addInterface(
3828 cppu::UnoType<document::XStorageChangeListener>::get(), xListener );
3829 }
3830
removeStorageChangeListener(const Reference<document::XStorageChangeListener> & xListener)3831 void SAL_CALL SfxBaseModel::removeStorageChangeListener(
3832 const Reference< document::XStorageChangeListener >& xListener )
3833 {
3834 SfxModelGuard aGuard( *this );
3835
3836 m_pData->m_aInterfaceContainer.removeInterface(
3837 cppu::UnoType<document::XStorageChangeListener>::get(), xListener );
3838 }
3839
impl_getPrintHelper()3840 void SfxBaseModel::impl_getPrintHelper()
3841 {
3842 if ( m_pData->m_xPrintable.is() )
3843 return;
3844 m_pData->m_xPrintable = new SfxPrintHelper();
3845 Reference < lang::XInitialization > xInit( m_pData->m_xPrintable, UNO_QUERY );
3846 Sequence < Any > aValues(1);
3847 aValues[0] <<= Reference < frame::XModel > (static_cast< frame::XModel* >(this), UNO_QUERY );
3848 xInit->initialize( aValues );
3849 Reference < view::XPrintJobBroadcaster > xBrd( m_pData->m_xPrintable, UNO_QUERY );
3850 xBrd->addPrintJobListener( new SfxPrintHelperListener_Impl( m_pData.get() ) );
3851 }
3852
3853
3854 // css.frame.XModule
setIdentifier(const OUString & Identifier)3855 void SAL_CALL SfxBaseModel::setIdentifier(const OUString& Identifier)
3856 {
3857 SfxModelGuard aGuard( *this );
3858 m_pData->m_sModuleIdentifier = Identifier;
3859 }
3860
3861
3862 // css.frame.XModule
getIdentifier()3863 OUString SAL_CALL SfxBaseModel::getIdentifier()
3864 {
3865 SfxModelGuard aGuard( *this );
3866 if (!m_pData->m_sModuleIdentifier.isEmpty())
3867 return m_pData->m_sModuleIdentifier;
3868 if (m_pData->m_pObjectShell.is())
3869 return m_pData->m_pObjectShell->GetFactory().GetDocumentServiceName();
3870 return OUString();
3871 }
3872
3873
impl_getTitleHelper()3874 Reference< frame::XTitle > SfxBaseModel::impl_getTitleHelper ()
3875 {
3876 SfxModelGuard aGuard( *this );
3877
3878 if ( ! m_pData->m_xTitleHelper.is ())
3879 {
3880 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
3881 Reference< frame::XUntitledNumbers > xDesktop( frame::Desktop::create(xContext), UNO_QUERY_THROW);
3882 Reference< frame::XModel > xThis (static_cast< frame::XModel* >(this), UNO_QUERY_THROW);
3883
3884 ::framework::TitleHelper* pHelper = new ::framework::TitleHelper(xContext);
3885 m_pData->m_xTitleHelper.set(static_cast< ::cppu::OWeakObject* >(pHelper), UNO_QUERY_THROW);
3886 pHelper->setOwner (xThis );
3887 pHelper->connectWithUntitledNumbers (xDesktop);
3888 }
3889
3890 return m_pData->m_xTitleHelper;
3891 }
3892
3893
impl_getUntitledHelper()3894 Reference< frame::XUntitledNumbers > SfxBaseModel::impl_getUntitledHelper ()
3895 {
3896 SfxModelGuard aGuard( *this );
3897
3898 if ( ! m_pData->m_xNumberedControllers.is ())
3899 {
3900 Reference< frame::XModel > xThis (static_cast< frame::XModel* >(this), UNO_QUERY_THROW);
3901 ::comphelper::NumberedCollection* pHelper = new ::comphelper::NumberedCollection();
3902
3903 m_pData->m_xNumberedControllers.set(static_cast< ::cppu::OWeakObject* >(pHelper), UNO_QUERY_THROW);
3904
3905 pHelper->setOwner (xThis);
3906 pHelper->setUntitledPrefix (" : ");
3907 }
3908
3909 return m_pData->m_xNumberedControllers;
3910 }
3911
3912
3913 // css.frame.XTitle
getTitle()3914 OUString SAL_CALL SfxBaseModel::getTitle()
3915 {
3916 // SYNCHRONIZED ->
3917 SfxModelGuard aGuard( *this );
3918
3919 OUString aResult = impl_getTitleHelper()->getTitle ();
3920 if ( !m_pData->m_bExternalTitle && m_pData->m_pObjectShell.get() )
3921 {
3922 SfxMedium* pMedium = m_pData->m_pObjectShell->GetMedium();
3923 if ( pMedium )
3924 {
3925 try {
3926 ::ucbhelper::Content aContent( pMedium->GetName(),
3927 utl::UCBContentHelper::getDefaultCommandEnvironment(),
3928 comphelper::getProcessComponentContext() );
3929 const Reference < beans::XPropertySetInfo > xProps
3930 = aContent.getProperties();
3931 if ( xProps.is() )
3932 {
3933 const OUString aServerTitle( "TitleOnServer" );
3934 if ( xProps->hasPropertyByName( aServerTitle ) )
3935 {
3936 Any aAny = aContent.getPropertyValue( aServerTitle );
3937 aAny >>= aResult;
3938 }
3939 }
3940 }
3941 catch (const ucb::ContentCreationException &)
3942 {
3943 }
3944 catch (const ucb::CommandAbortedException &)
3945 {
3946 }
3947 const SfxBoolItem* pRepairedDocItem = SfxItemSet::GetItem<SfxBoolItem>(pMedium->GetItemSet(), SID_REPAIRPACKAGE, false);
3948 if ( pRepairedDocItem && pRepairedDocItem->GetValue() )
3949 aResult += SfxResId(STR_REPAIREDDOCUMENT);
3950 }
3951
3952 if ( m_pData->m_pObjectShell->IsReadOnlyUI() || (pMedium && pMedium->IsReadOnly()) )
3953 aResult += SfxResId(STR_READONLY);
3954 else if ( m_pData->m_pObjectShell->IsDocShared() )
3955 aResult += SfxResId(STR_SHARED);
3956
3957 if ( m_pData->m_pObjectShell->GetDocumentSignatureState() == SignatureState::OK )
3958 aResult += SfxResId(RID_XMLSEC_DOCUMENTSIGNED);
3959 }
3960
3961 return aResult;
3962 }
3963
3964
3965 // css.frame.XTitle
setTitle(const OUString & sTitle)3966 void SAL_CALL SfxBaseModel::setTitle( const OUString& sTitle )
3967 {
3968 // SYNCHRONIZED ->
3969 SfxModelGuard aGuard( *this );
3970
3971 impl_getTitleHelper()->setTitle (sTitle);
3972 m_pData->m_bExternalTitle = true;
3973 }
3974
3975
3976 // css.frame.XTitleChangeBroadcaster
addTitleChangeListener(const Reference<frame::XTitleChangeListener> & xListener)3977 void SAL_CALL SfxBaseModel::addTitleChangeListener( const Reference< frame::XTitleChangeListener >& xListener )
3978 {
3979 // SYNCHRONIZED ->
3980 SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
3981
3982 Reference< frame::XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper(), UNO_QUERY);
3983 if (xBroadcaster.is ())
3984 xBroadcaster->addTitleChangeListener (xListener);
3985 }
3986
3987
3988 // css.frame.XTitleChangeBroadcaster
removeTitleChangeListener(const Reference<frame::XTitleChangeListener> & xListener)3989 void SAL_CALL SfxBaseModel::removeTitleChangeListener( const Reference< frame::XTitleChangeListener >& xListener )
3990 {
3991 // SYNCHRONIZED ->
3992 SfxModelGuard aGuard( *this );
3993
3994 Reference< frame::XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper(), UNO_QUERY);
3995 if (xBroadcaster.is ())
3996 xBroadcaster->removeTitleChangeListener (xListener);
3997 }
3998
3999
4000 // css.frame.XUntitledNumbers
leaseNumber(const Reference<XInterface> & xComponent)4001 ::sal_Int32 SAL_CALL SfxBaseModel::leaseNumber( const Reference< XInterface >& xComponent )
4002 {
4003 SfxModelGuard aGuard( *this );
4004
4005 return impl_getUntitledHelper ()->leaseNumber (xComponent);
4006 }
4007
4008
4009 // css.frame.XUntitledNumbers
releaseNumber(::sal_Int32 nNumber)4010 void SAL_CALL SfxBaseModel::releaseNumber( ::sal_Int32 nNumber )
4011 {
4012 SfxModelGuard aGuard( *this );
4013 impl_getUntitledHelper ()->releaseNumber (nNumber);
4014 }
4015
4016
4017 // css.frame.XUntitledNumbers
releaseNumberForComponent(const Reference<XInterface> & xComponent)4018 void SAL_CALL SfxBaseModel::releaseNumberForComponent( const Reference< XInterface >& xComponent )
4019 {
4020 SfxModelGuard aGuard( *this );
4021 impl_getUntitledHelper ()->releaseNumberForComponent (xComponent);
4022 }
4023
4024
4025 // css.frame.XUntitledNumbers
getUntitledPrefix()4026 OUString SAL_CALL SfxBaseModel::getUntitledPrefix()
4027 {
4028 SfxModelGuard aGuard( *this );
4029 return impl_getUntitledHelper ()->getUntitledPrefix ();
4030 }
4031
4032
4033 // frame::XModel2
getControllers()4034 Reference< container::XEnumeration > SAL_CALL SfxBaseModel::getControllers()
4035 {
4036 SfxModelGuard aGuard( *this );
4037
4038 sal_Int32 c = m_pData->m_seqControllers.size();
4039 sal_Int32 i = 0;
4040 Sequence< Any > lEnum(c);
4041 for (i=0; i<c; ++i)
4042 lEnum[i] <<= m_pData->m_seqControllers[i];
4043
4044 ::comphelper::OAnyEnumeration* pEnum = new ::comphelper::OAnyEnumeration(lEnum);
4045 Reference< container::XEnumeration > xEnum(static_cast< container::XEnumeration* >(pEnum), UNO_QUERY_THROW);
4046 return xEnum;
4047 }
4048
4049
4050 // frame::XModel2
getAvailableViewControllerNames()4051 Sequence< OUString > SAL_CALL SfxBaseModel::getAvailableViewControllerNames()
4052 {
4053 SfxModelGuard aGuard( *this );
4054
4055 const SfxObjectFactory& rDocumentFactory = GetObjectShell()->GetFactory();
4056 const sal_Int16 nViewFactoryCount = rDocumentFactory.GetViewFactoryCount();
4057
4058 Sequence< OUString > aViewNames( nViewFactoryCount );
4059 for ( sal_Int16 nViewNo = 0; nViewNo < nViewFactoryCount; ++nViewNo )
4060 aViewNames[nViewNo] = rDocumentFactory.GetViewFactory( nViewNo ).GetAPIViewName();
4061 return aViewNames;
4062 }
4063
4064
4065 // frame::XModel2
createDefaultViewController(const Reference<frame::XFrame> & i_rFrame)4066 Reference< frame::XController2 > SAL_CALL SfxBaseModel::createDefaultViewController( const Reference< frame::XFrame >& i_rFrame )
4067 {
4068 SfxModelGuard aGuard( *this );
4069
4070 const SfxObjectFactory& rDocumentFactory = GetObjectShell()->GetFactory();
4071 const OUString sDefaultViewName = rDocumentFactory.GetViewFactory().GetAPIViewName();
4072
4073 aGuard.clear();
4074
4075 return createViewController( sDefaultViewName, Sequence< PropertyValue >(), i_rFrame );
4076 }
4077
4078
4079 namespace sfx { namespace intern {
4080
4081 /** a class which, in its dtor, cleans up various objects (well, at the moment only the frame) collected during
4082 the creation of a document view, unless the creation was successful.
4083 */
4084 class ViewCreationGuard
4085 {
4086 public:
ViewCreationGuard()4087 ViewCreationGuard()
4088 :m_bSuccess( false )
4089 {
4090 }
4091
~ViewCreationGuard()4092 ~ViewCreationGuard()
4093 {
4094 if ( !m_bSuccess && m_aWeakFrame && !m_aWeakFrame->GetCurrentDocument() )
4095 {
4096 m_aWeakFrame->SetFrameInterface_Impl( nullptr );
4097 m_aWeakFrame->DoClose();
4098 }
4099 }
4100
takeFrameOwnership(SfxFrame * i_pFrame)4101 void takeFrameOwnership( SfxFrame* i_pFrame )
4102 {
4103 OSL_PRECOND( !m_aWeakFrame, "ViewCreationGuard::takeFrameOwnership: already have a frame!" );
4104 OSL_PRECOND( i_pFrame != nullptr, "ViewCreationGuard::takeFrameOwnership: invalid frame!" );
4105 m_aWeakFrame = i_pFrame;
4106 }
4107
releaseAll()4108 void releaseAll()
4109 {
4110 m_bSuccess = true;
4111 }
4112
4113 private:
4114 bool m_bSuccess;
4115 SfxFrameWeakRef m_aWeakFrame;
4116 };
4117 } }
4118
4119
FindOrCreateViewFrame_Impl(const Reference<XFrame> & i_rFrame,::sfx::intern::ViewCreationGuard & i_rGuard) const4120 SfxViewFrame* SfxBaseModel::FindOrCreateViewFrame_Impl( const Reference< XFrame >& i_rFrame, ::sfx::intern::ViewCreationGuard& i_rGuard ) const
4121 {
4122 SfxViewFrame* pViewFrame = nullptr;
4123 for ( pViewFrame = SfxViewFrame::GetFirst( GetObjectShell(), false );
4124 pViewFrame;
4125 pViewFrame= SfxViewFrame::GetNext( *pViewFrame, GetObjectShell(), false )
4126 )
4127 {
4128 if ( pViewFrame->GetFrame().GetFrameInterface() == i_rFrame )
4129 break;
4130 }
4131 if ( !pViewFrame )
4132 {
4133 #if OSL_DEBUG_LEVEL > 0
4134 for ( SfxFrame* pCheckFrame = SfxFrame::GetFirst();
4135 pCheckFrame;
4136 pCheckFrame = SfxFrame::GetNext( *pCheckFrame )
4137 )
4138 {
4139 if ( pCheckFrame->GetFrameInterface() == i_rFrame )
4140 {
4141 if ( ( pCheckFrame->GetCurrentViewFrame() != nullptr )
4142 || ( pCheckFrame->GetCurrentDocument() != nullptr )
4143 )
4144 // Note that it is perfectly legitimate that during loading into an XFrame which already contains
4145 // a document, there exist two SfxFrame instances bound to this XFrame - the old one, which will be
4146 // destroyed later, and the new one, which we're going to create
4147 continue;
4148
4149 OSL_FAIL( "SfxBaseModel::FindOrCreateViewFrame_Impl: there already is an SfxFrame for the given XFrame, but no view in it!" );
4150 // nowadays, we're the only instance allowed to create an SfxFrame for an XFrame, so this case here should not happen
4151 break;
4152 }
4153 }
4154 #endif
4155
4156 SfxFrame* pTargetFrame = SfxFrame::Create( i_rFrame );
4157 ENSURE_OR_THROW( pTargetFrame, "could not create an SfxFrame" );
4158 i_rGuard.takeFrameOwnership( pTargetFrame );
4159
4160 // prepare it
4161 pTargetFrame->PrepareForDoc_Impl( *GetObjectShell() );
4162
4163 // create view frame
4164 pViewFrame = new SfxViewFrame( *pTargetFrame, GetObjectShell() );
4165 }
4166 return pViewFrame;
4167 }
4168
4169
4170 // frame::XModel2
createViewController(const OUString & i_rViewName,const Sequence<PropertyValue> & i_rArguments,const Reference<XFrame> & i_rFrame)4171 Reference< frame::XController2 > SAL_CALL SfxBaseModel::createViewController(
4172 const OUString& i_rViewName, const Sequence< PropertyValue >& i_rArguments, const Reference< XFrame >& i_rFrame )
4173 {
4174 SfxModelGuard aGuard( *this );
4175
4176 if ( !i_rFrame.is() )
4177 throw lang::IllegalArgumentException( OUString(), *this, 3 );
4178
4179 // find the proper SFX view factory
4180 SfxViewFactory* pViewFactory = GetObjectShell()->GetFactory().GetViewFactoryByViewName( i_rViewName );
4181 if ( !pViewFactory )
4182 throw IllegalArgumentException( OUString(), *this, 1 );
4183
4184 // determine previous shell (used in some special cases)
4185 Reference< XController > xPreviousController( i_rFrame->getController() );
4186 const Reference< XModel > xMe( this );
4187 if ( ( xPreviousController.is() )
4188 && ( xMe != xPreviousController->getModel() )
4189 )
4190 {
4191 xPreviousController.clear();
4192 }
4193 SfxViewShell* pOldViewShell = SfxViewShell::Get( xPreviousController );
4194 OSL_ENSURE( !xPreviousController.is() || ( pOldViewShell != nullptr ),
4195 "SfxBaseModel::createViewController: invalid old controller!" );
4196
4197 // a guard which will clean up in case of failure
4198 ::sfx::intern::ViewCreationGuard aViewCreationGuard;
4199
4200 // determine the ViewFrame belonging to the given XFrame
4201 SfxViewFrame* pViewFrame = FindOrCreateViewFrame_Impl( i_rFrame, aViewCreationGuard );
4202 SAL_WARN_IF( !pViewFrame , "sfx.doc", "SfxBaseModel::createViewController: no frame?" );
4203
4204 // delegate to SFX' view factory
4205 pViewFrame->GetBindings().ENTERREGISTRATIONS();
4206 SfxViewShell* pViewShell = pViewFactory->CreateInstance( pViewFrame, pOldViewShell );
4207 pViewFrame->GetBindings().LEAVEREGISTRATIONS();
4208 ENSURE_OR_THROW( pViewShell, "invalid view shell provided by factory" );
4209
4210 // by setting the ViewShell it is prevented that disposing the Controller will destroy this ViewFrame also
4211 pViewFrame->GetDispatcher()->SetDisableFlags( SfxDisableFlags::NONE );
4212 pViewFrame->SetViewShell_Impl( pViewShell );
4213
4214 // remember ViewID
4215 pViewFrame->SetCurViewId_Impl( pViewFactory->GetOrdinal() );
4216
4217 // ensure a default controller, if the view shell did not provide an own implementation
4218 if ( !pViewShell->GetController().is() )
4219 pViewShell->SetController( new SfxBaseController( pViewShell ) );
4220
4221 // pass the creation arguments to the controller
4222 SfxBaseController* pBaseController = pViewShell->GetBaseController_Impl();
4223 ENSURE_OR_THROW( pBaseController, "invalid controller implementation!" );
4224 pBaseController->SetCreationArguments_Impl( i_rArguments );
4225
4226 // some initial view settings, coming from our most recent attachResource call
4227 ::comphelper::NamedValueCollection aDocumentLoadArgs( getArgs() );
4228 if ( aDocumentLoadArgs.getOrDefault( "ViewOnly", false ) )
4229 pViewFrame->GetFrame().SetMenuBarOn_Impl( false );
4230
4231 const sal_Int16 nPluginMode = aDocumentLoadArgs.getOrDefault( "PluginMode", sal_Int16( 0 ) );
4232 if ( nPluginMode == 1 )
4233 {
4234 pViewFrame->ForceOuterResize_Impl();
4235 pViewFrame->GetBindings().HidePopups();
4236
4237 SfxFrame& rFrame = pViewFrame->GetFrame();
4238 // MBA: layoutmanager of inplace frame starts locked and invisible
4239 rFrame.GetWorkWindow_Impl()->MakeVisible_Impl( false );
4240 rFrame.GetWorkWindow_Impl()->Lock_Impl( true );
4241
4242 rFrame.GetWindow().SetBorderStyle( WindowBorderStyle::NOBORDER );
4243 pViewFrame->GetWindow().SetBorderStyle( WindowBorderStyle::NOBORDER );
4244 }
4245
4246 // tell the guard we were successful
4247 aViewCreationGuard.releaseAll();
4248
4249 // outta here
4250 return pBaseController;
4251 }
4252
4253
4254 // RDF DocumentMetadataAccess
4255
4256 // rdf::XRepositorySupplier:
4257 Reference< rdf::XRepository > SAL_CALL
getRDFRepository()4258 SfxBaseModel::getRDFRepository()
4259 {
4260 SfxModelGuard aGuard( *this );
4261
4262 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4263 if (!xDMA.is()) {
4264 throw RuntimeException( "model has no document metadata", *this );
4265 }
4266
4267 return xDMA->getRDFRepository();
4268 }
4269
4270 // rdf::XNode:
4271 OUString SAL_CALL
getStringValue()4272 SfxBaseModel::getStringValue()
4273 {
4274 SfxModelGuard aGuard( *this );
4275
4276 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4277 if (!xDMA.is()) {
4278 throw RuntimeException( "model has no document metadata", *this );
4279 }
4280
4281 return xDMA->getStringValue();
4282 }
4283
4284 // rdf::XURI:
4285 OUString SAL_CALL
getNamespace()4286 SfxBaseModel::getNamespace()
4287 {
4288 SfxModelGuard aGuard( *this );
4289
4290 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4291 if (!xDMA.is()) {
4292 throw RuntimeException( "model has no document metadata", *this );
4293 }
4294
4295 return xDMA->getNamespace();
4296 }
4297
4298 OUString SAL_CALL
getLocalName()4299 SfxBaseModel::getLocalName()
4300 {
4301 SfxModelGuard aGuard( *this );
4302
4303 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4304 if (!xDMA.is()) {
4305 throw RuntimeException( "model has no document metadata", *this );
4306 }
4307
4308 return xDMA->getLocalName();
4309 }
4310
4311 // rdf::XDocumentMetadataAccess:
4312 Reference< rdf::XMetadatable > SAL_CALL
getElementByMetadataReference(const beans::StringPair & i_rReference)4313 SfxBaseModel::getElementByMetadataReference(
4314 const beans::StringPair & i_rReference)
4315 {
4316 SfxModelGuard aGuard( *this );
4317
4318 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4319 if (!xDMA.is()) {
4320 throw RuntimeException( "model has no document metadata", *this );
4321 }
4322
4323 return xDMA->getElementByMetadataReference(i_rReference);
4324 }
4325
4326 Reference< rdf::XMetadatable > SAL_CALL
getElementByURI(const Reference<rdf::XURI> & i_xURI)4327 SfxBaseModel::getElementByURI(const Reference< rdf::XURI > & i_xURI)
4328 {
4329 SfxModelGuard aGuard( *this );
4330
4331 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4332 if (!xDMA.is()) {
4333 throw RuntimeException( "model has no document metadata", *this );
4334 }
4335
4336 return xDMA->getElementByURI(i_xURI);
4337 }
4338
4339 Sequence< Reference< rdf::XURI > > SAL_CALL
getMetadataGraphsWithType(const Reference<rdf::XURI> & i_xType)4340 SfxBaseModel::getMetadataGraphsWithType(
4341 const Reference<rdf::XURI> & i_xType)
4342 {
4343 SfxModelGuard aGuard( *this );
4344
4345 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4346 if (!xDMA.is()) {
4347 throw RuntimeException( "model has no document metadata", *this );
4348 }
4349
4350 return xDMA->getMetadataGraphsWithType(i_xType);
4351 }
4352
4353 Reference<rdf::XURI> SAL_CALL
addMetadataFile(const OUString & i_rFileName,const Sequence<Reference<rdf::XURI>> & i_rTypes)4354 SfxBaseModel::addMetadataFile(const OUString & i_rFileName,
4355 const Sequence < Reference< rdf::XURI > > & i_rTypes)
4356 {
4357 SfxModelGuard aGuard( *this );
4358
4359 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4360 if (!xDMA.is()) {
4361 throw RuntimeException( "model has no document metadata", *this );
4362 }
4363
4364 return xDMA->addMetadataFile(i_rFileName, i_rTypes);
4365 }
4366
4367 Reference<rdf::XURI> SAL_CALL
importMetadataFile(::sal_Int16 i_Format,const Reference<io::XInputStream> & i_xInStream,const OUString & i_rFileName,const Reference<rdf::XURI> & i_xBaseURI,const Sequence<Reference<rdf::XURI>> & i_rTypes)4368 SfxBaseModel::importMetadataFile(::sal_Int16 i_Format,
4369 const Reference< io::XInputStream > & i_xInStream,
4370 const OUString & i_rFileName,
4371 const Reference< rdf::XURI > & i_xBaseURI,
4372 const Sequence < Reference< rdf::XURI > > & i_rTypes)
4373 {
4374 SfxModelGuard aGuard( *this );
4375
4376 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4377 if (!xDMA.is()) {
4378 throw RuntimeException( "model has no document metadata", *this );
4379 }
4380
4381 return xDMA->importMetadataFile(i_Format,
4382 i_xInStream, i_rFileName, i_xBaseURI, i_rTypes);
4383 }
4384
4385 void SAL_CALL
removeMetadataFile(const Reference<rdf::XURI> & i_xGraphName)4386 SfxBaseModel::removeMetadataFile(
4387 const Reference< rdf::XURI > & i_xGraphName)
4388 {
4389 SfxModelGuard aGuard( *this );
4390
4391 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4392 if (!xDMA.is()) {
4393 throw RuntimeException( "model has no document metadata", *this );
4394 }
4395
4396 return xDMA->removeMetadataFile(i_xGraphName);
4397 }
4398
4399 void SAL_CALL
addContentOrStylesFile(const OUString & i_rFileName)4400 SfxBaseModel::addContentOrStylesFile(const OUString & i_rFileName)
4401 {
4402 SfxModelGuard aGuard( *this );
4403
4404 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4405 if (!xDMA.is()) {
4406 throw RuntimeException( "model has no document metadata", *this );
4407 }
4408
4409 return xDMA->addContentOrStylesFile(i_rFileName);
4410 }
4411
4412 void SAL_CALL
removeContentOrStylesFile(const OUString & i_rFileName)4413 SfxBaseModel::removeContentOrStylesFile(const OUString & i_rFileName)
4414 {
4415 SfxModelGuard aGuard( *this );
4416
4417 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4418 if (!xDMA.is()) {
4419 throw RuntimeException( "model has no document metadata", *this );
4420 }
4421
4422 return xDMA->removeContentOrStylesFile(i_rFileName);
4423 }
4424
4425 void SAL_CALL
loadMetadataFromStorage(Reference<embed::XStorage> const & i_xStorage,Reference<rdf::XURI> const & i_xBaseURI,Reference<task::XInteractionHandler> const & i_xHandler)4426 SfxBaseModel::loadMetadataFromStorage(
4427 Reference< embed::XStorage > const & i_xStorage,
4428 Reference<rdf::XURI> const & i_xBaseURI,
4429 Reference<task::XInteractionHandler> const & i_xHandler)
4430 {
4431 SfxModelGuard aGuard( *this );
4432
4433 const Reference<rdf::XDocumentMetadataAccess> xDMA(
4434 m_pData->CreateDMAUninitialized());
4435 if (!xDMA.is()) {
4436 throw RuntimeException( "model has no document metadata", *this );
4437 }
4438
4439 try {
4440 xDMA->loadMetadataFromStorage(i_xStorage, i_xBaseURI, i_xHandler);
4441 } catch (lang::IllegalArgumentException &) {
4442 throw; // not initialized
4443 } catch (Exception &) {
4444 // UGLY: if it's a RuntimeException, we can't be sure DMA is initialized
4445 m_pData->m_xDocumentMetadata = xDMA;
4446 throw;
4447 }
4448 m_pData->m_xDocumentMetadata = xDMA;
4449
4450 }
4451
4452 void SAL_CALL
storeMetadataToStorage(Reference<embed::XStorage> const & i_xStorage)4453 SfxBaseModel::storeMetadataToStorage(
4454 Reference< embed::XStorage > const & i_xStorage)
4455 {
4456 SfxModelGuard aGuard( *this );
4457
4458 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4459 if (!xDMA.is()) {
4460 throw RuntimeException( "model has no document metadata", *this );
4461 }
4462
4463 return xDMA->storeMetadataToStorage(i_xStorage);
4464 }
4465
4466 void SAL_CALL
loadMetadataFromMedium(const Sequence<beans::PropertyValue> & i_rMedium)4467 SfxBaseModel::loadMetadataFromMedium(
4468 const Sequence< beans::PropertyValue > & i_rMedium)
4469 {
4470 SfxModelGuard aGuard( *this );
4471
4472 const Reference<rdf::XDocumentMetadataAccess> xDMA(
4473 m_pData->CreateDMAUninitialized());
4474 if (!xDMA.is()) {
4475 throw RuntimeException( "model has no document metadata", *this );
4476 }
4477
4478 try {
4479 xDMA->loadMetadataFromMedium(i_rMedium);
4480 } catch (lang::IllegalArgumentException &) {
4481 throw; // not initialized
4482 } catch (Exception &) {
4483 // UGLY: if it's a RuntimeException, we can't be sure DMA is initialized
4484 m_pData->m_xDocumentMetadata = xDMA;
4485 throw;
4486 }
4487 m_pData->m_xDocumentMetadata = xDMA;
4488 }
4489
4490 void SAL_CALL
storeMetadataToMedium(const Sequence<beans::PropertyValue> & i_rMedium)4491 SfxBaseModel::storeMetadataToMedium(
4492 const Sequence< beans::PropertyValue > & i_rMedium)
4493 {
4494 SfxModelGuard aGuard( *this );
4495
4496 const Reference<rdf::XDocumentMetadataAccess> xDMA(m_pData->GetDMA());
4497 if (!xDMA.is()) {
4498 throw RuntimeException( "model has no document metadata", *this );
4499 }
4500
4501 return xDMA->storeMetadataToMedium(i_rMedium);
4502 }
4503
4504
4505 // = SfxModelSubComponent
4506
4507
~SfxModelSubComponent()4508 SfxModelSubComponent::~SfxModelSubComponent()
4509 {
4510 }
4511
4512 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
4513