build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / dbaccess / source / core / dataaccess / documentdefinition.cxx
bloba0cdc67e12bd74cee8a3b773c2b189ceb01f2a5e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "documentdefinition.hxx"
21 #include "dbastrings.hrc"
22 #include "sdbcoretools.hxx"
23 #include <tools/debug.hxx>
24 #include <tools/diagnose_ex.h>
25 #include <osl/diagnose.h>
26 #include <comphelper/property.hxx>
27 #include <comphelper/sequence.hxx>
28 #include <comphelper/namedvaluecollection.hxx>
29 #include <comphelper/classids.hxx>
30 #include <com/sun/star/frame/XUntitledNumbers.hpp>
31 #include <com/sun/star/awt/XTopWindow.hpp>
32 #include <com/sun/star/awt/Size.hpp>
33 #include <com/sun/star/lang/DisposedException.hpp>
34 #include <com/sun/star/beans/PropertyAttribute.hpp>
35 #include <com/sun/star/frame/Desktop.hpp>
36 #include <com/sun/star/frame/XModel.hpp>
37 #include <com/sun/star/frame/XTitle.hpp>
38 #include <com/sun/star/frame/XController.hpp>
39 #include <com/sun/star/task/XJobExecutor.hpp>
40 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
41 #include <com/sun/star/frame/XFramesSupplier.hpp>
42 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
43 #include <com/sun/star/report/XReportDefinition.hpp>
44 #include <com/sun/star/report/XReportEngine.hpp>
45 #include <com/sun/star/ucb/OpenMode.hpp>
46 #include <com/sun/star/embed/XEmbedObjectFactory.hpp>
47 #include <com/sun/star/embed/EmbeddedObjectCreator.hpp>
48 #include <com/sun/star/embed/Aspects.hpp>
49 #include <com/sun/star/embed/OOoEmbeddedObjectFactory.hpp>
50 #include <ucbhelper/cancelcommandexecution.hxx>
51 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
52 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
53 #include <com/sun/star/embed/ElementModes.hpp>
54 #include <com/sun/star/embed/XEmbedPersist.hpp>
55 #include <com/sun/star/embed/EmbedStates.hpp>
56 #include <com/sun/star/embed/XComponentSupplier.hpp>
57 #include <com/sun/star/embed/EntryInitModes.hpp>
58 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
59 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
60 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
61 #include <com/sun/star/util/XCloseBroadcaster.hpp>
62 #include <com/sun/star/frame/XModule.hpp>
63 #include <com/sun/star/datatransfer/DataFlavor.hpp>
64 #include <com/sun/star/datatransfer/XTransferable.hpp>
65 #include <com/sun/star/container/XNameContainer.hpp>
66 #include <com/sun/star/embed/XTransactedObject.hpp>
67 #include <com/sun/star/embed/XCommonEmbedPersist.hpp>
68 #include "intercept.hxx"
69 #include <com/sun/star/sdb/ErrorCondition.hpp>
70 #include <com/sun/star/sdb/XInteractionDocumentSave.hpp>
71 #include <com/sun/star/task/InteractionHandler.hpp>
72 #include <com/sun/star/sdb/DocumentSaveRequest.hpp>
73 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
74 #include <com/sun/star/document/MacroExecMode.hpp>
75 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
76 #include <com/sun/star/container/XIndexContainer.hpp>
77 #include <com/sun/star/form/XFormsSupplier.hpp>
78 #include <com/sun/star/form/XForm.hpp>
79 #include <comphelper/interaction.hxx>
80 #include <connectivity/dbtools.hxx>
81 #include <vcl/svapp.hxx>
82 #include <osl/mutex.hxx>
83 #include <sal/macros.h>
84 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
85 #include "core_resource.hxx"
86 #include "core_resource.hrc"
87 #include "datasource.hxx"
88 #include <com/sun/star/embed/XStateChangeBroadcaster.hpp>
89 #include <com/sun/star/task/XInteractionApprove.hpp>
90 #include <com/sun/star/task/XInteractionDisapprove.hpp>
91 #include <com/sun/star/frame/XLayoutManager.hpp>
92 #include <cppuhelper/compbase.hxx>
93 #include <cppuhelper/exc_hlp.hxx>
94 #include <cppuhelper/implbase.hxx>
95 #include <com/sun/star/frame/FrameSearchFlag.hpp>
96 #include <comphelper/sequenceashashmap.hxx>
97 #include <comphelper/mimeconfighelper.hxx>
98 #include <comphelper/storagehelper.hxx>
99 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
100 #include <com/sun/star/io/WrongFormatException.hpp>
101 #include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
102 #include <com/sun/star/sdb/application/DatabaseObject.hpp>
103 #include <com/sun/star/util/XModifiable2.hpp>
105 using namespace ::com::sun::star;
106 using namespace view;
107 using namespace uno;
108 using namespace util;
109 using namespace ucb;
110 using namespace beans;
111 using namespace lang;
112 using namespace awt;
113 using namespace embed;
114 using namespace frame;
115 using namespace document;
116 using namespace sdbc;
117 using namespace sdb;
118 using namespace io;
119 using namespace container;
120 using namespace datatransfer;
121 using namespace task;
122 using namespace form;
123 using namespace drawing;
124 using namespace ::osl;
125 using namespace ::comphelper;
126 using namespace ::cppu;
128 using sdb::application::XDatabaseDocumentUI;
129 namespace DatabaseObject = sdb::application::DatabaseObject;
131 #define DEFAULT_WIDTH 10000
132 #define DEFAULT_HEIGHT 7500
134 namespace dbaccess
137 typedef ::boost::optional< bool > optional_bool;
139 // helper
140 namespace
142 OUString lcl_determineContentType_nothrow( const Reference< XStorage >& _rxContainerStorage,
143 const OUString& _rEntityName )
145 OUString sContentType;
148 ::utl::SharedUNOComponent< XPropertySet > xStorageProps(
149 _rxContainerStorage->openStorageElement( _rEntityName, ElementModes::READ ), UNO_QUERY_THROW );
150 OSL_VERIFY( xStorageProps->getPropertyValue( INFO_MEDIATYPE ) >>= sContentType );
152 catch( const Exception& )
154 DBG_UNHANDLED_EXCEPTION();
156 return sContentType;
160 // OEmbedObjectHolder
161 typedef ::cppu::WeakComponentImplHelper< embed::XStateChangeListener > TEmbedObjectHolder;
162 class OEmbedObjectHolder : public ::cppu::BaseMutex
163 ,public TEmbedObjectHolder
165 Reference< XEmbeddedObject > m_xBroadCaster;
166 ODocumentDefinition* m_pDefinition;
167 bool m_bInStateChange;
168 protected:
169 virtual void SAL_CALL disposing() override;
170 public:
171 OEmbedObjectHolder(const Reference< XEmbeddedObject >& _xBroadCaster,ODocumentDefinition* _pDefinition)
172 : TEmbedObjectHolder(m_aMutex)
173 ,m_xBroadCaster(_xBroadCaster)
174 ,m_pDefinition(_pDefinition)
175 ,m_bInStateChange(false)
177 osl_atomic_increment( &m_refCount );
179 if ( m_xBroadCaster.is() )
180 m_xBroadCaster->addStateChangeListener(this);
182 osl_atomic_decrement( &m_refCount );
185 virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (embed::WrongStateException, uno::RuntimeException, std::exception) override;
186 virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (uno::RuntimeException, std::exception) override;
187 virtual void SAL_CALL disposing( const lang::EventObject& Source ) throw (uno::RuntimeException, std::exception) override;
190 void SAL_CALL OEmbedObjectHolder::disposing()
192 if ( m_xBroadCaster.is() )
193 m_xBroadCaster->removeStateChangeListener(this);
194 m_xBroadCaster = nullptr;
195 m_pDefinition = nullptr;
198 void SAL_CALL OEmbedObjectHolder::changingState( const lang::EventObject& /*aEvent*/, ::sal_Int32 /*nOldState*/, ::sal_Int32 /*nNewState*/ ) throw (embed::WrongStateException, uno::RuntimeException, std::exception)
202 void SAL_CALL OEmbedObjectHolder::stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (uno::RuntimeException, std::exception)
204 if ( !m_bInStateChange && nNewState == EmbedStates::RUNNING && nOldState == EmbedStates::ACTIVE && m_pDefinition )
206 m_bInStateChange = true;
207 Reference<XInterface> xInt(static_cast< ::cppu::OWeakObject* >(m_pDefinition),UNO_QUERY);
209 Reference<XEmbeddedObject> xEmbeddedObject(aEvent.Source,UNO_QUERY);
210 if ( xEmbeddedObject.is() )
211 xEmbeddedObject->changeState(EmbedStates::LOADED);
213 m_bInStateChange = false;
217 void SAL_CALL OEmbedObjectHolder::disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException, std::exception)
219 m_xBroadCaster = nullptr;
222 // OEmbeddedClientHelper
223 typedef ::cppu::WeakImplHelper< XEmbeddedClient
224 > EmbeddedClientHelper_BASE;
225 class OEmbeddedClientHelper : public EmbeddedClientHelper_BASE
227 ODocumentDefinition* m_pClient;
228 public:
229 explicit OEmbeddedClientHelper(ODocumentDefinition* _pClient) :m_pClient(_pClient) {}
231 virtual void SAL_CALL saveObject( ) throw (ObjectSaveVetoException, Exception, RuntimeException, std::exception) override
234 // XComponentSupplier
235 virtual Reference< util::XCloseable > SAL_CALL getComponent( ) throw (RuntimeException, std::exception) override
237 return Reference< css::util::XCloseable >();
240 // XEmbeddedClient
241 virtual void SAL_CALL visibilityChanged( sal_Bool /*bVisible*/ ) throw (WrongStateException, RuntimeException, std::exception) override
244 inline void resetClient() { m_pClient = nullptr; }
247 // LockModifiable
248 class LockModifiable
250 public:
251 explicit LockModifiable( const Reference< XInterface >& i_rModifiable )
252 :m_xModifiable( i_rModifiable, UNO_QUERY )
254 OSL_ENSURE( m_xModifiable.is(), "LockModifiable::LockModifiable: invalid component!" );
255 if ( m_xModifiable.is() )
257 if ( !m_xModifiable->isSetModifiedEnabled() )
259 // somebody already locked that, no need to lock it, again, and no need to unlock it later
260 m_xModifiable.clear();
262 else
264 m_xModifiable->disableSetModified();
269 ~LockModifiable()
271 if ( m_xModifiable.is() )
272 m_xModifiable->enableSetModified();
275 private:
276 Reference< XModifiable2 > m_xModifiable;
279 // LifetimeCoupler
280 typedef ::cppu::WeakImplHelper< css::lang::XEventListener
281 > LifetimeCoupler_Base;
282 /** helper class which couples the lifetime of a component to the lifetime
283 of another component
285 Instances of this class are constructed with two components. The first is
286 simply held by reference, and thus kept alive. The second one is observed
287 for <code>disposing</code> calls - if they occur, i.e. if the component dies,
288 the reference to the first component is cleared.
290 This way, you can ensure that a certain component is kept alive as long
291 as a second component is not disposed.
293 class LifetimeCoupler : public LifetimeCoupler_Base
295 private:
296 Reference< XInterface > m_xClient;
298 public:
299 inline static void couple( const Reference< XInterface >& _rxClient, const Reference< XComponent >& _rxActor )
301 Reference< css::lang::XEventListener > xEnsureDelete( new LifetimeCoupler( _rxClient, _rxActor ) );
304 private:
305 inline LifetimeCoupler( const Reference< XInterface >& _rxClient, const Reference< XComponent >& _rxActor )
306 :m_xClient( _rxClient )
308 OSL_ENSURE( _rxActor.is(), "LifetimeCoupler::LifetimeCoupler: this will crash!" );
309 osl_atomic_increment( &m_refCount );
311 _rxActor->addEventListener( this );
313 osl_atomic_decrement( &m_refCount );
314 OSL_ENSURE( m_refCount, "LifetimeCoupler::LifetimeCoupler: the actor is not holding us by hard ref - this won't work!" );
317 virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) throw (RuntimeException, std::exception) override;
318 protected:
321 void SAL_CALL LifetimeCoupler::disposing( const css::lang::EventObject& /*Source*/ ) throw (RuntimeException, std::exception)
323 m_xClient.clear();
326 // ODocumentSaveContinuation
327 class ODocumentSaveContinuation : public OInteraction< XInteractionDocumentSave >
329 OUString m_sName;
330 Reference<XContent> m_xParentContainer;
332 public:
333 ODocumentSaveContinuation() { }
335 const Reference<XContent>& getContent() const { return m_xParentContainer; }
336 const OUString& getName() const { return m_sName; }
338 // XInteractionDocumentSave
339 virtual void SAL_CALL setName( const OUString& _sName,const Reference<XContent>& _xParent) throw(RuntimeException, std::exception) override;
342 void SAL_CALL ODocumentSaveContinuation::setName( const OUString& _sName,const Reference<XContent>& _xParent) throw(RuntimeException, std::exception)
344 m_sName = _sName;
345 m_xParentContainer = _xParent;
348 OUString ODocumentDefinition::GetDocumentServiceFromMediaType( const Reference< XStorage >& _rxContainerStorage,
349 const OUString& _rEntityName, const Reference< XComponentContext >& _rContext,
350 Sequence< sal_Int8 >& _rClassId )
352 return GetDocumentServiceFromMediaType(
353 lcl_determineContentType_nothrow( _rxContainerStorage, _rEntityName ),
354 _rContext, _rClassId );
357 OUString ODocumentDefinition::GetDocumentServiceFromMediaType( const OUString& _rMediaType,
358 const Reference< XComponentContext >& _rContext, Sequence< sal_Int8 >& _rClassId )
360 OUString sResult;
363 ::comphelper::MimeConfigurationHelper aConfigHelper( _rContext );
364 sResult = aConfigHelper.GetDocServiceNameFromMediaType( _rMediaType );
365 _rClassId = comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation(aConfigHelper.GetExplicitlyRegisteredObjClassID( _rMediaType ));
366 if ( !_rClassId.getLength() && !sResult.isEmpty() )
368 Reference< XNameAccess > xObjConfig = aConfigHelper.GetObjConfiguration();
369 if ( xObjConfig.is() )
371 Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
372 for ( sal_Int32 nInd = 0; nInd < aClassIDs.getLength(); nInd++ )
374 Reference< XNameAccess > xObjectProps;
375 OUString aEntryDocName;
377 if ( ( xObjConfig->getByName( aClassIDs[nInd] ) >>= xObjectProps ) && xObjectProps.is()
378 && ( xObjectProps->getByName("ObjectDocumentServiceName") >>= aEntryDocName )
379 && aEntryDocName.equals( sResult ) )
381 _rClassId = comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation(aClassIDs[nInd]);
382 break;
387 #if OSL_DEBUG_LEVEL > 0
388 // alternative, shorter approach
389 const Sequence< NamedValue > aProps( aConfigHelper.GetObjectPropsByMediaType( _rMediaType ) );
390 const ::comphelper::NamedValueCollection aMediaTypeProps( aProps );
391 const OUString sAlternativeResult = aMediaTypeProps.getOrDefault( "ObjectDocumentServiceName", OUString() );
392 OSL_ENSURE( sAlternativeResult == sResult, "ODocumentDefinition::GetDocumentServiceFromMediaType: failed, this approach is *not* equivalent (1)!" );
393 const Sequence< sal_Int8 > aAlternativeClassID = aMediaTypeProps.getOrDefault( "ClassID", Sequence< sal_Int8 >() );
394 OSL_ENSURE( aAlternativeClassID == _rClassId, "ODocumentDefinition::GetDocumentServiceFromMediaType: failed, this approach is *not* equivalent (2)!" );
395 #endif
397 catch ( const Exception& )
399 DBG_UNHANDLED_EXCEPTION();
401 return sResult;
404 // ODocumentDefinition
406 ODocumentDefinition::ODocumentDefinition( const Reference< XInterface >& _rxContainer, const Reference< XComponentContext >& _xORB,
407 const TContentPtr& _pImpl, bool _bForm )
408 :OContentHelper(_xORB,_rxContainer,_pImpl)
409 ,OPropertyStateContainer(OContentHelper::rBHelper)
410 ,m_bForm(_bForm)
411 ,m_bOpenInDesign(false)
412 ,m_bInExecute(false)
413 ,m_bRemoveListener(false)
415 registerProperties();
418 void ODocumentDefinition::initialLoad( const Sequence< sal_Int8 >& i_rClassID, const Sequence< PropertyValue >& i_rCreationArgs,
419 const Reference< XConnection >& i_rConnection )
421 OSL_ENSURE( i_rClassID.getLength(), "ODocumentDefinition::initialLoad: illegal class ID!" );
422 if ( !i_rClassID.getLength() )
423 return;
425 loadEmbeddedObject( i_rConnection, i_rClassID, i_rCreationArgs, false, false );
428 ODocumentDefinition::~ODocumentDefinition()
430 if ( !OContentHelper::rBHelper.bInDispose && !OContentHelper::rBHelper.bDisposed )
432 acquire();
433 dispose();
436 if ( m_pInterceptor.is() )
438 m_pInterceptor->dispose();
439 m_pInterceptor.clear();
443 void ODocumentDefinition::closeObject()
445 ::osl::MutexGuard aGuard(m_aMutex);
446 if ( m_xEmbeddedObject.is() )
450 Reference< css::util::XCloseable> xCloseable(m_xEmbeddedObject,UNO_QUERY);
451 if ( xCloseable.is() )
452 xCloseable->close(true);
454 catch(const Exception&)
457 m_xEmbeddedObject = nullptr;
458 if ( m_pClientHelper.is() )
460 m_pClientHelper->resetClient();
461 m_pClientHelper.clear();
466 void SAL_CALL ODocumentDefinition::disposing()
468 OContentHelper::disposing();
469 ::osl::MutexGuard aGuard(m_aMutex);
470 closeObject();
471 ::comphelper::disposeComponent(m_xListener);
472 if ( m_bRemoveListener )
474 Reference<util::XCloseable> xCloseable(m_pImpl->m_pDataSource->getModel_noCreate(),UNO_QUERY);
475 if ( xCloseable.is() )
476 xCloseable->removeCloseListener(this);
480 css::uno::Sequence<sal_Int8> ODocumentDefinition::getImplementationId()
481 throw (css::uno::RuntimeException, std::exception)
483 return css::uno::Sequence<sal_Int8>();
486 IMPLEMENT_GETTYPES3(ODocumentDefinition,OContentHelper,OPropertyStateContainer,ODocumentDefinition_Base);
487 IMPLEMENT_FORWARD_XINTERFACE3( ODocumentDefinition,OContentHelper,OPropertyStateContainer,ODocumentDefinition_Base)
489 void ODocumentDefinition::registerProperties()
491 #define REGISTER_PROPERTY( name, location ) \
492 registerProperty( PROPERTY_##name, PROPERTY_ID_##name, PropertyAttribute::READONLY, &location, cppu::UnoType<decltype(location)>::get() );
494 #define REGISTER_PROPERTY_BV( name, location ) \
495 registerProperty( PROPERTY_##name, PROPERTY_ID_##name, PropertyAttribute::CONSTRAINED | PropertyAttribute::BOUND | PropertyAttribute::READONLY, &location, cppu::UnoType<decltype(location)>::get() );
497 REGISTER_PROPERTY_BV( NAME, m_pImpl->m_aProps.aTitle );
498 REGISTER_PROPERTY ( AS_TEMPLATE, m_pImpl->m_aProps.bAsTemplate );
499 REGISTER_PROPERTY ( PERSISTENT_NAME, m_pImpl->m_aProps.sPersistentName );
500 REGISTER_PROPERTY ( IS_FORM, m_bForm );
503 void SAL_CALL ODocumentDefinition::getFastPropertyValue( Any& o_rValue, sal_Int32 i_nHandle ) const
505 if ( i_nHandle == PROPERTY_ID_PERSISTENT_PATH )
507 OUString sPersistentPath;
508 if ( !m_pImpl->m_aProps.sPersistentName.isEmpty() )
510 OUStringBuffer aBuffer;
511 aBuffer.append( ODatabaseModelImpl::getObjectContainerStorageName( m_bForm ? ODatabaseModelImpl::E_FORM : ODatabaseModelImpl::E_REPORT ) );
512 aBuffer.append( '/' );
513 aBuffer.append( m_pImpl->m_aProps.sPersistentName );
514 sPersistentPath = aBuffer.makeStringAndClear();
516 o_rValue <<= sPersistentPath;
517 return;
520 OPropertyStateContainer::getFastPropertyValue( o_rValue, i_nHandle );
523 Reference< XPropertySetInfo > SAL_CALL ODocumentDefinition::getPropertySetInfo( ) throw(RuntimeException, std::exception)
525 Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
526 return xInfo;
529 IPropertyArrayHelper& ODocumentDefinition::getInfoHelper()
531 return *getArrayHelper();
534 IPropertyArrayHelper* ODocumentDefinition::createArrayHelper( ) const
536 // properties maintained by our base class (see registerProperties)
537 Sequence< Property > aProps;
538 describeProperties( aProps );
540 // properties not maintained by our base class
541 Sequence< Property > aManualProps( 1 );
542 aManualProps[0].Name = PROPERTY_PERSISTENT_PATH;
543 aManualProps[0].Handle = PROPERTY_ID_PERSISTENT_PATH;
544 aManualProps[0].Type = ::cppu::UnoType<OUString>::get();
545 aManualProps[0].Attributes = PropertyAttribute::READONLY;
547 return new OPropertyArrayHelper( ::comphelper::concatSequences( aProps, aManualProps ) );
550 class OExecuteImpl
552 bool& m_rbSet;
553 public:
554 explicit OExecuteImpl(bool& _rbSet) : m_rbSet(_rbSet){ m_rbSet=true; }
555 ~OExecuteImpl(){ m_rbSet = false; }
558 namespace
560 bool lcl_extractOpenMode( const Any& _rValue, sal_Int32& _out_rMode )
562 OpenCommandArgument aOpenCommand;
563 if ( _rValue >>= aOpenCommand )
564 _out_rMode = aOpenCommand.Mode;
565 else
567 OpenCommandArgument2 aOpenCommand2;
568 if ( _rValue >>= aOpenCommand2 )
569 _out_rMode = aOpenCommand2.Mode;
570 else
571 return false;
573 return true;
577 void ODocumentDefinition::impl_removeFrameFromDesktop_throw( const Reference<XComponentContext> & _rxContext, const Reference< XFrame >& _rxFrame )
579 Reference< XDesktop2 > xDesktop = Desktop::create( _rxContext );
580 Reference< XFrames > xFrames( xDesktop->getFrames(), UNO_QUERY_THROW );
581 xFrames->remove( _rxFrame );
584 void ODocumentDefinition::impl_onActivateEmbeddedObject_nothrow( const bool i_bReactivated )
588 Reference< XModel > xModel( getComponent(), UNO_QUERY );
589 Reference< XController > xController( xModel.is() ? xModel->getCurrentController() : Reference< XController >() );
590 if ( !xController.is() )
591 return;
593 if ( !m_xListener.is() )
594 // it's the first time the embedded object has been activated
595 // create an OEmbedObjectHolder
596 m_xListener = new OEmbedObjectHolder( m_xEmbeddedObject, this );
598 // raise the window to top (especially necessary if this is not the first activation)
599 Reference< XFrame > xFrame( xController->getFrame(), UNO_SET_THROW );
600 Reference< XTopWindow > xTopWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW );
601 xTopWindow->toFront();
603 // remove the frame from the desktop's frame collection because we need full control of it.
604 impl_removeFrameFromDesktop_throw( m_aContext, xFrame );
606 // ensure that we ourself are kept alive as long as the embedded object's frame is
607 // opened
608 LifetimeCoupler::couple( *this, xFrame.get() );
610 // init the edit view
611 if ( m_bForm && m_bOpenInDesign && !i_bReactivated )
612 impl_initFormEditView( xController );
614 catch( const RuntimeException& )
616 DBG_UNHANDLED_EXCEPTION();
620 namespace
622 // PreserveVisualAreaSize
623 /** stack-guard for preserving the size of the VisArea of an XModel
625 class PreserveVisualAreaSize
627 private:
628 Reference< XVisualObject > m_xVisObject;
629 awt::Size m_aOriginalSize;
631 public:
632 explicit PreserveVisualAreaSize( const Reference< XModel >& _rxModel )
633 :m_xVisObject( _rxModel, UNO_QUERY )
635 if ( m_xVisObject.is() )
639 m_aOriginalSize = m_xVisObject->getVisualAreaSize( Aspects::MSOLE_CONTENT );
641 catch ( const Exception& )
643 OSL_FAIL( "PreserveVisualAreaSize::PreserveVisualAreaSize: caught an exception!" );
648 inline ~PreserveVisualAreaSize()
650 if ( m_xVisObject.is() && m_aOriginalSize.Width && m_aOriginalSize.Height )
654 m_xVisObject->setVisualAreaSize( Aspects::MSOLE_CONTENT, m_aOriginalSize );
656 catch ( const Exception& )
658 OSL_FAIL( "PreserveVisualAreaSize::~PreserveVisualAreaSize: caught an exception!" );
664 // LayoutManagerLock
665 /** helper class for stack-usage which during its lifetime locks a layout manager
667 class LayoutManagerLock
669 private:
670 Reference< XLayoutManager > m_xLayoutManager;
672 public:
673 explicit LayoutManagerLock( const Reference< XController >& _rxController )
675 OSL_ENSURE( _rxController.is(), "LayoutManagerLock::LayoutManagerLock: this will crash!" );
676 Reference< XFrame > xFrame( _rxController->getFrame() );
679 Reference< XPropertySet > xPropSet( xFrame, UNO_QUERY_THROW );
680 m_xLayoutManager.set(
681 xPropSet->getPropertyValue( "LayoutManager" ),
682 UNO_QUERY_THROW );
683 m_xLayoutManager->lock();
686 catch( const Exception& )
688 OSL_FAIL( "LayoutManagerLock::LayoutManagerLock: caught an exception!" );
692 inline ~LayoutManagerLock()
696 // unlock the layout manager
697 if ( m_xLayoutManager.is() )
698 m_xLayoutManager->unlock();
700 catch( const Exception& )
702 OSL_FAIL( "LayoutManagerLock::~LayoutManagerLock: caught an exception!" );
708 void ODocumentDefinition::impl_initFormEditView( const Reference< XController >& _rxController )
712 Reference< XViewSettingsSupplier > xSettingsSupplier( _rxController, UNO_QUERY_THROW );
713 Reference< XPropertySet > xViewSettings( xSettingsSupplier->getViewSettings(), UNO_QUERY_THROW );
715 // the below code could indirectly tamper with the "modified" flag of the model, temporarily disable this
716 LockModifiable aLockModify( _rxController->getModel() );
718 // The visual area size can be changed by the setting of the following properties
719 // so it should be restored later
720 PreserveVisualAreaSize aPreserveVisAreaSize( _rxController->getModel() );
722 // Layout manager should not layout while the size is still not restored
723 // so it will stay locked for this time
724 LayoutManagerLock aLockLayout( _rxController );
726 // setting of the visual properties
727 xViewSettings->setPropertyValue("ShowRulers",makeAny(true));
728 xViewSettings->setPropertyValue("ShowVertRuler",makeAny(true));
729 xViewSettings->setPropertyValue("ShowHoriRuler",makeAny(true));
730 xViewSettings->setPropertyValue("IsRasterVisible",makeAny(true));
731 xViewSettings->setPropertyValue("IsSnapToRaster",makeAny(true));
732 xViewSettings->setPropertyValue("ShowOnlineLayout",makeAny(true));
733 xViewSettings->setPropertyValue("RasterSubdivisionX",makeAny(sal_Int32(5)));
734 xViewSettings->setPropertyValue("RasterSubdivisionY",makeAny(sal_Int32(5)));
736 catch( const Exception& )
738 DBG_UNHANDLED_EXCEPTION();
742 void ODocumentDefinition::impl_showOrHideComponent_throw( const bool i_bShow )
744 const sal_Int32 nCurrentState = m_xEmbeddedObject.is() ? m_xEmbeddedObject->getCurrentState() : EmbedStates::LOADED;
745 switch ( nCurrentState )
747 default:
748 case EmbedStates::LOADED:
749 throw embed::WrongStateException( OUString(), *this );
751 case EmbedStates::RUNNING:
752 if ( !i_bShow )
753 // fine, a running (and not yet active) object is never visible
754 return;
756 LockModifiable aLockModify( impl_getComponent_throw() );
757 m_xEmbeddedObject->changeState( EmbedStates::ACTIVE );
758 impl_onActivateEmbeddedObject_nothrow( false );
760 break;
762 case EmbedStates::ACTIVE:
764 Reference< XModel > xEmbeddedDoc( impl_getComponent_throw(), UNO_QUERY_THROW );
765 Reference< XController > xEmbeddedController( xEmbeddedDoc->getCurrentController(), UNO_SET_THROW );
766 Reference< XFrame > xEmbeddedFrame( xEmbeddedController->getFrame(), UNO_SET_THROW );
767 Reference< XWindow > xEmbeddedWindow( xEmbeddedFrame->getContainerWindow(), UNO_SET_THROW );
768 xEmbeddedWindow->setVisible( i_bShow );
770 break;
774 Any ODocumentDefinition::onCommandOpenSomething( const Any& _rOpenArgument, const bool _bActivate,
775 const Reference< XCommandEnvironment >& _rxEnvironment )
777 OExecuteImpl aExecuteGuard( m_bInExecute );
779 Reference< XConnection > xConnection;
780 sal_Int32 nOpenMode = OpenMode::DOCUMENT;
782 ::comphelper::NamedValueCollection aDocumentArgs;
784 // for the document, default to the interaction handler as used for loading the DB doc
785 // This might be overwritten below, when examining _rOpenArgument.
786 const ::comphelper::NamedValueCollection& aDBDocArgs( m_pImpl->m_pDataSource->getMediaDescriptor() );
787 Reference< XInteractionHandler > xHandler( aDBDocArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) );
788 if ( xHandler.is() )
789 aDocumentArgs.put( "InteractionHandler", xHandler );
791 ::boost::optional< sal_Int16 > aDocumentMacroMode;
793 if ( !lcl_extractOpenMode( _rOpenArgument, nOpenMode ) )
795 Sequence< PropertyValue > aArguments;
796 if ( _rOpenArgument >>= aArguments )
798 const PropertyValue* pIter = aArguments.getConstArray();
799 const PropertyValue* pEnd = pIter + aArguments.getLength();
800 for ( ;pIter != pEnd; ++pIter )
802 if ( pIter->Name == PROPERTY_ACTIVE_CONNECTION )
804 xConnection.set( pIter->Value, UNO_QUERY );
805 continue;
808 if ( lcl_extractOpenMode( pIter->Value, nOpenMode ) )
809 continue;
811 if ( pIter->Name == "MacroExecutionMode" )
813 sal_Int16 nMacroExecMode( !aDocumentMacroMode ? MacroExecMode::USE_CONFIG : *aDocumentMacroMode );
814 OSL_VERIFY( pIter->Value >>= nMacroExecMode );
815 aDocumentMacroMode.reset( nMacroExecMode );
816 continue;
819 // unknown argument -> pass to the loaded document
820 aDocumentArgs.put( pIter->Name, pIter->Value );
825 bool bExecuteDBDocMacros = m_pImpl->m_pDataSource->checkMacrosOnLoading();
826 // Note that this call implies the user might be asked for the macro execution mode.
827 // Normally, this would happen when the database document is loaded, and subsequent calls
828 // will simply use the user's decision from this point in time.
829 // However, it is possible to programmatically load forms/reports, without actually
830 // loading the database document into a frame. In this case, the user will be asked
831 // here and now.
832 // #i87741#
834 // allow the command arguments to downgrade the macro execution mode, but not to upgrade
835 // it
836 if ( ( m_pImpl->m_pDataSource->getImposedMacroExecMode() == MacroExecMode::USE_CONFIG )
837 && bExecuteDBDocMacros
840 // while loading the whole database document, USE_CONFIG, was passed.
841 // Additionally, *by now* executing macros from the DB doc is allowed (this is what bExecuteDBDocMacros
842 // indicates). This means either one of:
843 // 1. The DB doc or one of the sub docs contained macros and
844 // 1a. the user explicitly allowed executing them
845 // 1b. the configuration allows executing them without asking the user
846 // 2. Neither the DB doc nor the sub docs contained macros, thus macro
847 // execution was silently enabled, assuming that any macro will be a
848 // user-created macro
850 // The problem with this: If the to-be-opened sub document has macros embedded in
851 // the content.xml (which is valid ODF, but normally not produced by OOo itself),
852 // then this has not been detected while loading the database document - it would
853 // be too expensive, as it effectively would require loading all forms/reports.
855 // So, in such a case, and with 2. above, we would silently execute those macros,
856 // regardless of the global security settings - which would be a security issue, of
857 // course.
858 if ( m_pImpl->m_pDataSource->determineEmbeddedMacros() == ODatabaseModelImpl::eNoMacros )
860 // this is case 2. from above
861 // So, pass a USE_CONFIG to the to-be-loaded document. This means that
862 // the user will be prompted with a security message upon opening this
863 // sub document, in case the settings require this, *and* the document
864 // contains scripts in the content.xml. But this is better than the security
865 // issue we had before ...
866 aDocumentMacroMode.reset( MacroExecMode::USE_CONFIG );
870 if ( !aDocumentMacroMode )
872 // nobody so far felt responsible for setting it
873 // => use the DBDoc-wide macro exec mode for the document, too
874 aDocumentMacroMode.reset( bExecuteDBDocMacros ? MacroExecMode::ALWAYS_EXECUTE_NO_WARN : MacroExecMode::NEVER_EXECUTE );
876 aDocumentArgs.put( "MacroExecutionMode", *aDocumentMacroMode );
878 if ( ( nOpenMode == OpenMode::ALL )
879 || ( nOpenMode == OpenMode::FOLDERS )
880 || ( nOpenMode == OpenMode::DOCUMENTS )
881 || ( nOpenMode == OpenMode::DOCUMENT_SHARE_DENY_NONE )
882 || ( nOpenMode == OpenMode::DOCUMENT_SHARE_DENY_WRITE )
885 // not supported
886 ucbhelper::cancelCommandExecution(
887 makeAny( UnsupportedOpenModeException(
888 OUString(),
889 static_cast< cppu::OWeakObject * >( this ),
890 sal_Int16( nOpenMode ) ) ),
891 _rxEnvironment );
892 // Unreachable
893 OSL_FAIL( "unreachable" );
896 OSL_ENSURE( !m_pImpl->m_aProps.sPersistentName.isEmpty(),
897 "ODocumentDefinition::onCommandOpenSomething: no persistent name - cannot load!" );
898 if ( m_pImpl->m_aProps.sPersistentName.isEmpty() )
899 return Any();
901 // embedded objects themself do not support the hidden flag. We implement support for
902 // it by changing the STATE to RUNNING only, instead of ACTIVE.
903 bool bOpenHidden = aDocumentArgs.getOrDefault( "Hidden", false );
904 aDocumentArgs.remove( "Hidden" );
906 loadEmbeddedObject( xConnection, Sequence< sal_Int8 >(), aDocumentArgs.getPropertyValues(), false, !m_bOpenInDesign );
907 OSL_ENSURE( m_xEmbeddedObject.is(), "ODocumentDefinition::onCommandOpenSomething: what's this?" );
908 if ( !m_xEmbeddedObject.is() )
909 return Any();
911 Reference< XModel > xModel( getComponent(), UNO_QUERY );
912 Reference< report::XReportDefinition > xReportDefinition(xModel,UNO_QUERY);
914 Reference< XModule > xModule( xModel, UNO_QUERY );
915 if ( xModule.is() )
917 if ( m_bForm )
918 xModule->setIdentifier( "com.sun.star.sdb.FormDesign" );
919 else if ( !xReportDefinition.is() )
920 xModule->setIdentifier( "com.sun.star.text.TextDocument" );
922 updateDocumentTitle();
925 bool bIsAliveNewStyleReport = ( !m_bOpenInDesign && xReportDefinition.is() );
926 if ( bIsAliveNewStyleReport )
928 // we are in ReadOnly mode
929 // we would like to open the Writer or Calc with the report direct, without design it.
930 Reference< report::XReportEngine > xReportEngine( m_aContext->getServiceManager()->createInstanceWithContext("com.sun.star.comp.report.OReportEngineJFree", m_aContext), UNO_QUERY_THROW );
932 xReportEngine->setReportDefinition(xReportDefinition);
933 xReportEngine->setActiveConnection(m_xLastKnownConnection);
934 if ( bOpenHidden )
935 return makeAny( xReportEngine->createDocumentModel() );
936 return makeAny( xReportEngine->createDocumentAlive( nullptr ) );
939 if ( _bActivate && !bOpenHidden )
941 LockModifiable aLockModify( impl_getComponent_throw() );
942 m_xEmbeddedObject->changeState( EmbedStates::ACTIVE );
943 impl_onActivateEmbeddedObject_nothrow( false );
945 else
947 // ensure that we ourself are kept alive as long as the document is open
948 LifetimeCoupler::couple( *this, xModel.get() );
951 if ( !m_bForm && m_pImpl->m_aProps.bAsTemplate && !m_bOpenInDesign )
952 ODocumentDefinition::fillReportData( m_aContext, getComponent(), xConnection );
954 return makeAny( xModel );
957 Any SAL_CALL ODocumentDefinition::execute( const Command& aCommand, sal_Int32 CommandId, const Reference< XCommandEnvironment >& Environment ) throw (Exception, CommandAbortedException, RuntimeException, std::exception)
959 Any aRet;
961 bool bOpen = aCommand.Name == "open";
962 bool bOpenInDesign = aCommand.Name == "openDesign";
963 bool bOpenForMail = aCommand.Name == "openForMail";
964 if ( bOpen || bOpenInDesign || bOpenForMail )
966 // opening the document involves a lot of VCL code, which is not thread-safe, but needs the SolarMutex locked.
967 // Unfortunately, the DocumentDefinition, as well as the EmbeddedObject implementation, calls into VCL-dependent
968 // components *without* releasing the own mutex, which is a guaranteed recipe for deadlocks.
969 // We have control over this implementation here, and in modifying it to release the own mutex before calling into
970 // the VCL-dependent components is not too difficult (was there, seen it).
971 // However, we do /not/ have control over the EmbeddedObject implementation, and from a first look, it seems as
972 // making it release the own mutex before calling SolarMutex-code is ... difficult, at least.
973 // So, to be on the same side, we lock the SolarMutex here. Yes, it sucks.
974 ::SolarMutexGuard aSolarGuard;
975 ::osl::ClearableMutexGuard aGuard(m_aMutex);
976 if ( m_bInExecute )
977 return aRet;
979 bool bActivateObject = true;
980 if ( bOpenForMail )
982 OSL_FAIL( "ODocumentDefinition::execute: 'openForMail' should not be used anymore - use the 'Hidden' parameter instead!" );
983 bActivateObject = false;
986 // if the object is already opened, do nothing
987 if ( m_xEmbeddedObject.is() )
989 sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState();
990 bool bIsActive = ( nCurrentState == EmbedStates::ACTIVE );
992 if ( bIsActive )
994 // exception: new-style reports always create a new document when "open" is executed
995 Reference< report::XReportDefinition > xReportDefinition( impl_getComponent_throw( false ), UNO_QUERY );
996 bool bIsAliveNewStyleReport = ( xReportDefinition.is() && ( bOpen || bOpenForMail ) );
998 if ( !bIsAliveNewStyleReport )
1000 impl_onActivateEmbeddedObject_nothrow( true );
1001 return makeAny( getComponent() );
1006 m_bOpenInDesign = bOpenInDesign || bOpenForMail;
1007 return onCommandOpenSomething( aCommand.Argument, bActivateObject, Environment );
1010 ::osl::ClearableMutexGuard aGuard(m_aMutex);
1011 if ( m_bInExecute )
1012 return aRet;
1014 if ( aCommand.Name == "copyTo" )
1016 Sequence<Any> aIni;
1017 aCommand.Argument >>= aIni;
1018 if ( aIni.getLength() != 2 )
1020 OSL_FAIL( "Wrong argument type!" );
1021 ucbhelper::cancelCommandExecution(
1022 makeAny( IllegalArgumentException(
1023 OUString(),
1024 static_cast< cppu::OWeakObject * >( this ),
1025 -1 ) ),
1026 Environment );
1027 // Unreachable
1029 Reference< XStorage> xDest(aIni[0],UNO_QUERY);
1030 OUString sPersistentName;
1031 aIni[1] >>= sPersistentName;
1032 Reference< XStorage> xStorage = getContainerStorage();
1034 xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xDest,sPersistentName);
1036 else if ( aCommand.Name == "preview" )
1038 onCommandPreview(aRet);
1040 else if ( aCommand.Name == "insert" )
1042 Sequence<Any> aIni;
1043 aCommand.Argument >>= aIni;
1044 if ( !aIni.getLength() )
1046 OSL_FAIL( "Wrong argument count!" );
1047 ucbhelper::cancelCommandExecution(
1048 makeAny( IllegalArgumentException(
1049 OUString(),
1050 static_cast< cppu::OWeakObject * >( this ),
1051 -1 ) ),
1052 Environment );
1053 // Unreachable
1055 OUString sURL;
1056 aIni[0] >>= sURL;
1057 onCommandInsert( sURL, Environment );
1059 else if ( aCommand.Name == "getdocumentinfo" // compatibility
1060 || aCommand.Name == "getDocumentInfo" )
1062 onCommandGetDocumentProperties( aRet );
1064 else if ( aCommand.Name == "delete" )
1066 // delete
1067 closeObject();
1068 Reference< XStorage> xStorage = getContainerStorage();
1069 if ( xStorage.is() )
1070 xStorage->removeElement(m_pImpl->m_aProps.sPersistentName);
1072 dispose();
1075 else if ( aCommand.Name == "storeOwn" // compatibility
1076 || aCommand.Name == "store"
1079 impl_store_throw();
1081 else if ( aCommand.Name == "shutdown" // compatibility
1082 || aCommand.Name == "close"
1085 aRet <<= impl_close_throw();
1087 else if ( aCommand.Name == "show" )
1089 impl_showOrHideComponent_throw( true );
1091 else if ( aCommand.Name == "hide" )
1093 impl_showOrHideComponent_throw( false );
1095 else
1097 aRet = OContentHelper::execute(aCommand,CommandId,Environment);
1100 return aRet;
1103 namespace
1105 void lcl_resetChildFormsToEmptyDataSource( const Reference< XIndexAccess>& _rxFormsContainer )
1107 OSL_PRECOND( _rxFormsContainer.is(), "lcl_resetChildFormsToEmptyDataSource: illegal call!" );
1108 sal_Int32 count = _rxFormsContainer->getCount();
1109 for ( sal_Int32 i = 0; i < count; ++i )
1111 Reference< XForm > xForm( _rxFormsContainer->getByIndex( i ), UNO_QUERY );
1112 if ( !xForm.is() )
1113 continue;
1115 // if the element is a form, reset its DataSourceName property to an empty string
1118 Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW );
1119 xFormProps->setPropertyValue( PROPERTY_DATASOURCENAME, makeAny( OUString() ) );
1121 catch( const Exception& )
1123 DBG_UNHANDLED_EXCEPTION();
1126 // if the element is a container itself, step down the component hierarchy
1127 Reference< XIndexAccess > xContainer( xForm, UNO_QUERY );
1128 if ( xContainer.is() )
1129 lcl_resetChildFormsToEmptyDataSource( xContainer );
1133 void lcl_resetFormsToEmptyDataSource( const Reference< XEmbeddedObject>& _rxEmbeddedObject )
1137 Reference< XDrawPageSupplier > xSuppPage( _rxEmbeddedObject->getComponent(), UNO_QUERY_THROW );
1138 // if this interface does not exist, then either getComponent returned NULL,
1139 // or the document is a multi-page document. The latter is allowed, but currently
1140 // simply not handled by this code, as it would not normally happen.
1142 Reference< XFormsSupplier > xSuppForms( xSuppPage->getDrawPage(), UNO_QUERY_THROW );
1143 Reference< XIndexAccess > xForms( xSuppForms->getForms(), UNO_QUERY_THROW );
1144 lcl_resetChildFormsToEmptyDataSource( xForms );
1146 catch( const Exception& )
1148 DBG_UNHANDLED_EXCEPTION();
1154 void ODocumentDefinition::onCommandInsert( const OUString& _sURL, const Reference< XCommandEnvironment >& Environment )
1155 throw( Exception )
1157 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1159 // Check, if all required properties were set.
1160 if ( _sURL.isEmpty() || m_xEmbeddedObject.is() )
1162 OSL_FAIL( "Content::onCommandInsert - property value missing!" );
1164 Sequence<OUString> aProps { PROPERTY_URL };
1165 ucbhelper::cancelCommandExecution(
1166 makeAny( MissingPropertiesException(
1167 OUString(),
1168 static_cast< cppu::OWeakObject * >( this ),
1169 aProps ) ),
1170 Environment );
1171 // Unreachable
1174 if ( !m_xEmbeddedObject.is() )
1176 Reference< XStorage> xStorage = getContainerStorage();
1177 if ( xStorage.is() )
1179 Reference< XEmbeddedObjectCreator> xEmbedFactory = EmbeddedObjectCreator::create(m_aContext);
1180 Sequence<PropertyValue> aEmpty,aMediaDesc(1);
1181 aMediaDesc[0].Name = PROPERTY_URL;
1182 aMediaDesc[0].Value <<= _sURL;
1183 m_xEmbeddedObject.set(xEmbedFactory->createInstanceInitFromMediaDescriptor( xStorage
1184 ,m_pImpl->m_aProps.sPersistentName
1185 ,aMediaDesc
1186 ,aEmpty),UNO_QUERY);
1188 lcl_resetFormsToEmptyDataSource( m_xEmbeddedObject );
1189 // #i57669#
1191 Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
1192 if ( xPersist.is() )
1194 xPersist->storeOwn();
1198 Reference< css::util::XCloseable> xCloseable(m_xEmbeddedObject,UNO_QUERY);
1199 if ( xCloseable.is() )
1200 xCloseable->close(true);
1202 catch(const Exception&)
1205 m_xEmbeddedObject = nullptr;
1209 aGuard.clear();
1212 bool ODocumentDefinition::save(bool _bApprove)
1214 // default handling: instantiate an interaction handler and let it handle the parameter request
1215 if ( !m_bOpenInDesign )
1216 return false;
1221 ::SolarMutexGuard aSolarGuard;
1223 // the request
1224 Reference<XNameAccess> xName(m_xParentContainer,UNO_QUERY);
1225 DocumentSaveRequest aRequest;
1226 aRequest.Name = m_pImpl->m_aProps.aTitle;
1227 if ( aRequest.Name.isEmpty() )
1229 if ( m_bForm )
1230 aRequest.Name = DBACORE_RESSTRING( RID_STR_FORM );
1231 else
1232 aRequest.Name = DBACORE_RESSTRING( RID_STR_REPORT );
1233 aRequest.Name = ::dbtools::createUniqueName(xName,aRequest.Name);
1236 aRequest.Content.set(m_xParentContainer,UNO_QUERY);
1237 OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
1238 Reference< XInteractionRequest > xRequest(pRequest);
1239 // some knittings
1240 // two continuations allowed: OK and Cancel
1241 ODocumentSaveContinuation* pDocuSave = nullptr;
1243 if ( m_pImpl->m_aProps.aTitle.isEmpty() )
1245 pDocuSave = new ODocumentSaveContinuation;
1246 pRequest->addContinuation(pDocuSave);
1248 if ( _bApprove )
1250 OInteraction< XInteractionApprove >* pApprove = new OInteraction< XInteractionApprove >;
1251 pRequest->addContinuation(pApprove);
1254 OInteraction< XInteractionDisapprove >* pDisApprove = new OInteraction< XInteractionDisapprove >;
1255 pRequest->addContinuation(pDisApprove);
1257 OInteractionAbort* pAbort = new OInteractionAbort;
1258 pRequest->addContinuation(pAbort);
1260 // create the handler, let it handle the request
1261 Reference< XInteractionHandler2 > xHandler( InteractionHandler::createWithParent(m_aContext, nullptr) );
1262 xHandler->handle(xRequest);
1264 if ( pAbort->wasSelected() )
1265 return false;
1266 if ( pDisApprove->wasSelected() )
1267 return true;
1268 if ( pDocuSave && pDocuSave->wasSelected() )
1270 Reference<XNameContainer> xNC( pDocuSave->getContent(), UNO_QUERY_THROW );
1272 ::osl::ResettableMutexGuard aGuard( m_aMutex );
1273 NameChangeNotifier aNameChangeAndNotify( *this, pDocuSave->getName(), aGuard );
1274 m_pImpl->m_aProps.aTitle = pDocuSave->getName();
1276 Reference< XContent> xContent = this;
1277 xNC->insertByName(pDocuSave->getName(),makeAny(xContent));
1279 updateDocumentTitle();
1283 ::osl::MutexGuard aGuard(m_aMutex);
1284 Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
1285 if ( xPersist.is() )
1287 xPersist->storeOwn();
1288 notifyDataSourceModified();
1291 catch(const Exception&)
1293 OSL_FAIL("ODocumentDefinition::save: caught an Exception (tried to let the InteractionHandler handle it)!");
1295 return true;
1298 void ODocumentDefinition::saveAs()
1300 // default handling: instantiate an interaction handler and let it handle the parameter request
1301 if ( !m_bOpenInDesign )
1302 return;
1305 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1306 if ( m_pImpl->m_aProps.aTitle.isEmpty() )
1308 aGuard.clear();
1309 save(false); // (sal_False) : we don't want an approve dialog
1310 return;
1316 ::SolarMutexGuard aSolarGuard;
1318 // the request
1319 Reference<XNameAccess> xName(m_xParentContainer,UNO_QUERY);
1320 DocumentSaveRequest aRequest;
1321 aRequest.Name = m_pImpl->m_aProps.aTitle;
1323 aRequest.Content.set(m_xParentContainer,UNO_QUERY);
1324 OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
1325 Reference< XInteractionRequest > xRequest(pRequest);
1326 // some knittings
1327 // two continuations allowed: OK and Cancel
1328 ODocumentSaveContinuation* pDocuSave = new ODocumentSaveContinuation;
1329 pRequest->addContinuation(pDocuSave);
1330 OInteraction< XInteractionDisapprove >* pDisApprove = new OInteraction< XInteractionDisapprove >;
1331 pRequest->addContinuation(pDisApprove);
1332 OInteractionAbort* pAbort = new OInteractionAbort;
1333 pRequest->addContinuation(pAbort);
1335 // create the handler, let it handle the request
1336 Reference< XInteractionHandler2 > xHandler( InteractionHandler::createWithParent(m_aContext, nullptr) );
1337 xHandler->handle(xRequest);
1339 if ( pAbort->wasSelected() )
1340 return;
1341 if ( pDisApprove->wasSelected() )
1342 return;
1343 if ( pDocuSave->wasSelected() )
1345 ::osl::MutexGuard aGuard(m_aMutex);
1346 Reference<XNameContainer> xNC(pDocuSave->getContent(),UNO_QUERY);
1347 if ( xNC.is() )
1349 if ( m_pImpl->m_aProps.aTitle != pDocuSave->getName() )
1353 Reference< XStorage> xStorage = getContainerStorage();
1355 OUString sPersistentName = ::dbtools::createUniqueName(xStorage,"Obj");
1356 xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xStorage,sPersistentName);
1358 OUString sOldName = m_pImpl->m_aProps.aTitle;
1359 rename(pDocuSave->getName());
1360 updateDocumentTitle();
1362 Sequence< Any > aArguments(3);
1363 PropertyValue aValue;
1364 // set as folder
1365 aValue.Name = PROPERTY_NAME;
1366 aValue.Value <<= sOldName;
1367 aArguments[0] <<= aValue;
1369 aValue.Name = PROPERTY_PERSISTENT_NAME;
1370 aValue.Value <<= sPersistentName;
1371 aArguments[1] <<= aValue;
1373 aValue.Name = PROPERTY_AS_TEMPLATE;
1374 aValue.Value <<= m_pImpl->m_aProps.bAsTemplate;
1375 aArguments[2] <<= aValue;
1377 Reference< XMultiServiceFactory > xORB( m_xParentContainer, UNO_QUERY_THROW );
1378 Reference< XInterface > xComponent( xORB->createInstanceWithArguments( SERVICE_SDB_DOCUMENTDEFINITION, aArguments ) );
1379 Reference< XNameContainer > xNameContainer( m_xParentContainer, UNO_QUERY_THROW );
1380 xNameContainer->insertByName( sOldName, makeAny( xComponent ) );
1382 catch(const Exception&)
1384 DBG_UNHANDLED_EXCEPTION();
1387 Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
1388 if ( xPersist.is() )
1390 xPersist->storeOwn();
1391 notifyDataSourceModified();
1398 catch(const Exception&)
1400 OSL_FAIL("ODocumentDefinition::save: caught an Exception (tried to let the InteractionHandler handle it)!");
1404 namespace
1406 void lcl_putLoadArgs( ::comphelper::NamedValueCollection& _io_rArgs, const optional_bool& _bSuppressMacros, const optional_bool& _bReadOnly )
1408 if ( !!_bSuppressMacros )
1410 if ( *_bSuppressMacros )
1412 // if we're to suppress macros, do exactly this
1413 _io_rArgs.put( "MacroExecutionMode", MacroExecMode::NEVER_EXECUTE );
1415 else
1417 // otherwise, put the setting only if not already present
1418 if ( !_io_rArgs.has( "MacroExecutionMode" ) )
1420 _io_rArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
1425 if ( !!_bReadOnly )
1426 _io_rArgs.put( "ReadOnly", *_bReadOnly );
1430 namespace
1432 Reference< XFrame > lcl_getDatabaseDocumentFrame( ODatabaseModelImpl& _rImpl )
1434 Reference< XModel > xDatabaseDocumentModel( _rImpl.getModel_noCreate() );
1436 Reference< XController > xDatabaseDocumentController;
1437 if ( xDatabaseDocumentModel.is() )
1438 xDatabaseDocumentController = xDatabaseDocumentModel->getCurrentController();
1440 Reference< XFrame > xFrame;
1441 if ( xDatabaseDocumentController.is() )
1442 xFrame = xDatabaseDocumentController->getFrame();
1444 return xFrame;
1448 bool ODocumentDefinition::objectSupportsEmbeddedScripts() const
1450 bool bAllowDocumentMacros = !m_pImpl->m_pDataSource
1451 || ( m_pImpl->m_pDataSource->determineEmbeddedMacros() == ODatabaseModelImpl::eSubDocumentMacros );
1453 // if *any* of the objects of the database document already has macros, we
1454 // continue to allow it to have them, until the user does a migration.
1455 // If there are no macros, we don't allow them to be created.
1457 return bAllowDocumentMacros;
1460 OUString ODocumentDefinition::determineContentType() const
1462 return lcl_determineContentType_nothrow( getContainerStorage(), m_pImpl->m_aProps.sPersistentName );
1465 void ODocumentDefinition::separateOpenCommandArguments( const Sequence< PropertyValue >& i_rOpenCommandArguments,
1466 ::comphelper::NamedValueCollection& o_rDocumentLoadArgs, ::comphelper::NamedValueCollection& o_rEmbeddedObjectDescriptor )
1468 ::comphelper::NamedValueCollection aOpenCommandArguments( i_rOpenCommandArguments );
1470 const char* pObjectDescriptorArgs[] =
1472 "RecoveryStorage"
1474 for (const char* pObjectDescriptorArg : pObjectDescriptorArgs)
1476 if ( aOpenCommandArguments.has( pObjectDescriptorArg ) )
1478 o_rEmbeddedObjectDescriptor.put( pObjectDescriptorArg, aOpenCommandArguments.get( pObjectDescriptorArg ) );
1479 aOpenCommandArguments.remove( pObjectDescriptorArg );
1483 o_rDocumentLoadArgs.merge( aOpenCommandArguments, false );
1486 Sequence< PropertyValue > ODocumentDefinition::fillLoadArgs( const Reference< XConnection>& _xConnection, const bool _bSuppressMacros, const bool _bReadOnly,
1487 const Sequence< PropertyValue >& i_rOpenCommandArguments, Sequence< PropertyValue >& _out_rEmbeddedObjectDescriptor )
1489 // (re-)create interceptor, and put it into the descriptor of the embedded object
1490 if ( m_pInterceptor.is() )
1492 m_pInterceptor->dispose();
1493 m_pInterceptor.clear();
1496 m_pInterceptor = new OInterceptor( this );
1497 Reference<XDispatchProviderInterceptor> xInterceptor = m_pInterceptor.get();
1499 ::comphelper::NamedValueCollection aEmbeddedDescriptor;
1500 aEmbeddedDescriptor.put( "OutplaceDispatchInterceptor", xInterceptor );
1502 ::comphelper::NamedValueCollection aMediaDesc;
1503 separateOpenCommandArguments( i_rOpenCommandArguments, aMediaDesc, aEmbeddedDescriptor );
1505 // create the OutplaceFrameProperties, and put them into the descriptor of the embedded object
1506 ::comphelper::NamedValueCollection OutplaceFrameProperties;
1507 OutplaceFrameProperties.put( "TopWindow", true );
1508 OutplaceFrameProperties.put( "SupportPersistentWindowState", true );
1510 Reference< XFrame > xParentFrame;
1511 if ( m_pImpl->m_pDataSource )
1512 xParentFrame = lcl_getDatabaseDocumentFrame( *m_pImpl->m_pDataSource );
1513 if ( !xParentFrame.is() )
1514 { // i87957 we need a parent frame
1515 Reference< XDesktop2 > xDesktop = Desktop::create( m_aContext );
1516 xParentFrame.set( xDesktop, UNO_QUERY_THROW );
1517 Reference<util::XCloseable> xCloseable(m_pImpl->m_pDataSource->getModel_noCreate(),UNO_QUERY);
1518 if ( xCloseable.is() )
1520 xCloseable->addCloseListener(this);
1521 m_bRemoveListener = true;
1524 OSL_ENSURE( xParentFrame.is(), "ODocumentDefinition::fillLoadArgs: no parent frame!" );
1525 if ( xParentFrame.is() )
1526 OutplaceFrameProperties.put( "ParentFrame", xParentFrame );
1528 aEmbeddedDescriptor.put( "OutplaceFrameProperties", OutplaceFrameProperties.getNamedValues() );
1530 // tell the embedded object to have (or not have) script support
1531 aEmbeddedDescriptor.put( "EmbeddedScriptSupport", objectSupportsEmbeddedScripts() );
1533 // tell the embedded object to not participate in the document recovery game - the DB doc will handle it
1534 aEmbeddedDescriptor.put( "DocumentRecoverySupport", false );
1536 // pass the descriptor of the embedded object to the caller
1537 aEmbeddedDescriptor >>= _out_rEmbeddedObjectDescriptor;
1539 // create the ComponentData, and put it into the document's media descriptor
1541 ::comphelper::NamedValueCollection aComponentData;
1542 aComponentData.put( "ActiveConnection", _xConnection );
1543 aComponentData.put( "ApplyFormDesignMode", !_bReadOnly );
1544 aMediaDesc.put( "ComponentData", aComponentData.getPropertyValues() );
1547 if ( !m_pImpl->m_aProps.aTitle.isEmpty() )
1548 aMediaDesc.put( "DocumentTitle", m_pImpl->m_aProps.aTitle );
1550 aMediaDesc.put( "DocumentBaseURL", m_pImpl->m_pDataSource->getURL() );
1552 // put the common load arguments into the document's media descriptor
1553 lcl_putLoadArgs( aMediaDesc, optional_bool( _bSuppressMacros ), optional_bool( _bReadOnly ) );
1555 return aMediaDesc.getPropertyValues();
1558 void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& i_rConnection, const Sequence< sal_Int8 >& _aClassID,
1559 const Sequence< PropertyValue >& i_rOpenCommandArguments, const bool _bSuppressMacros, const bool _bReadOnly )
1561 if ( !m_xEmbeddedObject.is() )
1563 Reference< XStorage> xStorage = getContainerStorage();
1564 if ( xStorage.is() )
1566 Reference< XEmbeddedObjectCreator> xEmbedFactory = OOoEmbeddedObjectFactory::create(m_aContext);
1567 OUString sDocumentService;
1568 bool bSetSize = false;
1569 sal_Int32 nEntryConnectionMode = EntryInitModes::DEFAULT_INIT;
1570 Sequence< sal_Int8 > aClassID = _aClassID;
1571 if ( aClassID.getLength() )
1573 nEntryConnectionMode = EntryInitModes::TRUNCATE_INIT;
1574 bSetSize = true;
1576 else
1578 sDocumentService = GetDocumentServiceFromMediaType( getContentType(), m_aContext, aClassID );
1579 // check if we are not a form and
1580 // the org.libreoffice.report.pentaho.SOReportJobFactory is not present.
1581 if ( !m_bForm && !(sDocumentService == "com.sun.star.text.TextDocument"))
1583 // we seem to be a "new style" report, check if report extension is present.
1584 Reference< XContentEnumerationAccess > xEnumAccess( m_aContext->getServiceManager(), UNO_QUERY );
1585 const OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_aContext);
1586 Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(sReportEngineServiceName);
1587 if ( !xEnumDrivers.is() || !xEnumDrivers->hasMoreElements() )
1589 css::io::WrongFormatException aWFE;
1590 aWFE.Message = DBACORE_RESSTRING( RID_STR_MISSING_EXTENSION );
1591 throw aWFE;
1594 if ( !aClassID.getLength() )
1596 if ( m_bForm )
1597 aClassID = MimeConfigurationHelper::GetSequenceClassID(SO3_SW_CLASSID);
1598 else
1600 aClassID = MimeConfigurationHelper::GetSequenceClassID(SO3_RPT_CLASSID_90);
1605 OSL_ENSURE( aClassID.getLength(),"No Class ID" );
1607 Sequence< PropertyValue > aEmbeddedObjectDescriptor;
1608 Sequence< PropertyValue > aLoadArgs( fillLoadArgs(
1609 i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) );
1611 m_xEmbeddedObject.set(xEmbedFactory->createInstanceUserInit(aClassID
1612 ,sDocumentService
1613 ,xStorage
1614 ,m_pImpl->m_aProps.sPersistentName
1615 ,nEntryConnectionMode
1616 ,aLoadArgs
1617 ,aEmbeddedObjectDescriptor
1618 ),UNO_QUERY);
1619 if ( m_xEmbeddedObject.is() )
1621 if ( !m_pClientHelper.is() )
1623 m_pClientHelper = new OEmbeddedClientHelper(this);
1625 Reference<XEmbeddedClient> xClient = m_pClientHelper.get();
1626 m_xEmbeddedObject->setClientSite(xClient);
1627 m_xEmbeddedObject->changeState(EmbedStates::RUNNING);
1628 if ( bSetSize )
1630 LockModifiable aLockModify( impl_getComponent_throw( false ) );
1632 awt::Size aSize( DEFAULT_WIDTH, DEFAULT_HEIGHT );
1633 m_xEmbeddedObject->setVisualAreaSize(Aspects::MSOLE_CONTENT,aSize);
1638 else
1640 sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState();
1641 if ( nCurrentState == EmbedStates::LOADED )
1643 if ( !m_pClientHelper.is() )
1645 m_pClientHelper = new OEmbeddedClientHelper(this);
1647 Reference<XEmbeddedClient> xClient = m_pClientHelper.get();
1648 m_xEmbeddedObject->setClientSite(xClient);
1650 Sequence< PropertyValue > aEmbeddedObjectDescriptor;
1651 Sequence< PropertyValue > aLoadArgs( fillLoadArgs(
1652 i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) );
1654 Reference<XCommonEmbedPersist> xCommon(m_xEmbeddedObject,UNO_QUERY);
1655 OSL_ENSURE(xCommon.is(),"unsupported interface!");
1656 if ( xCommon.is() )
1657 xCommon->reload( aLoadArgs, aEmbeddedObjectDescriptor );
1658 m_xEmbeddedObject->changeState(EmbedStates::RUNNING);
1660 else
1662 OSL_ENSURE( ( nCurrentState == EmbedStates::RUNNING ) || ( nCurrentState == EmbedStates::ACTIVE ),
1663 "ODocumentDefinition::loadEmbeddedObject: unexpected state!" );
1665 // if the document was already loaded (which means the embedded object is in state RUNNING or ACTIVE),
1666 // then just re-set some model parameters
1669 // ensure the media descriptor doesn't contain any values which are intended for the
1670 // EmbeddedObjectDescriptor only
1671 ::comphelper::NamedValueCollection aEmbeddedObjectDescriptor;
1672 ::comphelper::NamedValueCollection aNewMediaDesc;
1673 separateOpenCommandArguments( i_rOpenCommandArguments, aNewMediaDesc, aEmbeddedObjectDescriptor );
1675 // merge the new media descriptor into the existing media descriptor
1676 const Reference< XModel > xModel( getComponent(), UNO_QUERY_THROW );
1677 const Sequence< PropertyValue > aArgs = xModel->getArgs();
1678 ::comphelper::NamedValueCollection aExistentMediaDesc( aArgs );
1679 aExistentMediaDesc.merge( aNewMediaDesc, false );
1681 lcl_putLoadArgs( aExistentMediaDesc, optional_bool(), optional_bool() );
1682 // don't put _bSuppressMacros and _bReadOnly here - if the document was already
1683 // loaded, we should not tamper with its settings.
1684 // #i88977# #i86872#
1686 xModel->attachResource( xModel->getURL(), aExistentMediaDesc.getPropertyValues() );
1688 catch( const Exception& )
1690 DBG_UNHANDLED_EXCEPTION();
1695 // set the OfficeDatabaseDocument instance as parent of the embedded document
1696 // #i40358#
1697 Reference< XChild > xDepdendDocAsChild( getComponent(), UNO_QUERY );
1698 if ( xDepdendDocAsChild.is() )
1702 if ( !xDepdendDocAsChild->getParent().is() )
1703 { // first encounter
1704 xDepdendDocAsChild->setParent( getDataSource( m_xParentContainer ) );
1707 catch( const Exception& )
1709 DBG_UNHANDLED_EXCEPTION();
1713 if ( i_rConnection.is() )
1714 m_xLastKnownConnection = i_rConnection;
1717 void ODocumentDefinition::onCommandPreview(Any& _rImage)
1719 loadEmbeddedObjectForPreview();
1720 if ( m_xEmbeddedObject.is() )
1724 Reference<XTransferable> xTransfer(getComponent(),UNO_QUERY);
1725 if ( xTransfer.is() )
1727 DataFlavor aFlavor;
1728 aFlavor.MimeType = "image/png";
1729 aFlavor.HumanPresentableName = "Portable Network Graphics";
1730 aFlavor.DataType = cppu::UnoType<Sequence < sal_Int8 >>::get();
1732 _rImage = xTransfer->getTransferData( aFlavor );
1735 catch( const Exception& )
1741 void ODocumentDefinition::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
1743 _rDefault.clear();
1746 void ODocumentDefinition::onCommandGetDocumentProperties( Any& _rProps )
1748 loadEmbeddedObjectForPreview();
1749 if ( m_xEmbeddedObject.is() )
1753 Reference<XDocumentPropertiesSupplier> xDocSup(
1754 getComponent(), UNO_QUERY );
1755 if ( xDocSup.is() )
1756 _rProps <<= xDocSup->getDocumentProperties();
1758 catch( const Exception& )
1760 DBG_UNHANDLED_EXCEPTION();
1765 Reference< util::XCloseable > ODocumentDefinition::impl_getComponent_throw( const bool i_ForceCreate )
1767 OSL_ENSURE(m_xEmbeddedObject.is(),"Illegal call for embeddedObject");
1768 Reference< util::XCloseable > xComp;
1769 if ( m_xEmbeddedObject.is() )
1771 int nState = m_xEmbeddedObject->getCurrentState();
1772 if ( ( nState == EmbedStates::LOADED ) && i_ForceCreate )
1774 m_xEmbeddedObject->changeState( EmbedStates::RUNNING );
1775 nState = m_xEmbeddedObject->getCurrentState();
1776 OSL_ENSURE( nState == EmbedStates::RUNNING, "ODocumentDefinition::impl_getComponent_throw: could not switch to RUNNING!" );
1779 if ( nState == EmbedStates::ACTIVE || nState == EmbedStates::RUNNING )
1781 Reference<XComponentSupplier> xCompProv(m_xEmbeddedObject,UNO_QUERY);
1782 if ( xCompProv.is() )
1784 xComp = xCompProv->getComponent();
1785 OSL_ENSURE(xComp.is(),"No valid component");
1789 return xComp;
1792 Reference< util::XCloseable > ODocumentDefinition::getComponent() throw (RuntimeException, std::exception)
1794 ::osl::MutexGuard aGuard( m_aMutex );
1795 return impl_getComponent_throw();
1798 namespace
1800 Reference< XDatabaseDocumentUI > lcl_getDatabaseDocumentUI( ODatabaseModelImpl& _rModelImpl )
1802 Reference< XDatabaseDocumentUI > xUI;
1804 Reference< XModel > xModel( _rModelImpl.getModel_noCreate() );
1805 if ( xModel.is() )
1806 xUI.set( xModel->getCurrentController(), UNO_QUERY );
1807 return xUI;
1811 Reference< XComponent > ODocumentDefinition::impl_openUI_nolck_throw( bool _bForEditing )
1813 ::osl::ClearableMutexGuard aGuard( m_aMutex );
1814 if ( !m_pImpl || !m_pImpl->m_pDataSource )
1815 throw DisposedException();
1817 Reference< XComponent > xComponent;
1820 Reference< XDatabaseDocumentUI > xUI( lcl_getDatabaseDocumentUI( *m_pImpl->m_pDataSource ) );
1821 if ( !xUI.is() )
1823 // no XDatabaseDocumentUI -> just execute the respective command
1824 m_bOpenInDesign = _bForEditing;
1825 xComponent = Reference<XComponent>(onCommandOpenSomething(Any(), true, nullptr), UNO_QUERY);
1826 OSL_ENSURE( xComponent.is(), "ODocumentDefinition::impl_openUI_nolck_throw: opening the thingie failed." );
1827 return xComponent;
1831 OUString sName( impl_getHierarchicalName( false ) );
1832 sal_Int32 nObjectType = m_bForm ? DatabaseObject::FORM : DatabaseObject::REPORT;
1833 aGuard.clear();
1835 xComponent = xUI->loadComponent(
1836 nObjectType, sName, _bForEditing
1839 catch( const RuntimeException& ) { throw; }
1840 catch( const Exception& )
1842 throw WrappedTargetException(
1843 OUString(), *this, ::cppu::getCaughtException() );
1846 return xComponent;
1849 void ODocumentDefinition::impl_store_throw()
1851 Reference<XEmbedPersist> xPersist( m_xEmbeddedObject, UNO_QUERY );
1852 if ( xPersist.is() )
1854 xPersist->storeOwn();
1855 notifyDataSourceModified();
1859 bool ODocumentDefinition::impl_close_throw()
1861 bool bSuccess = prepareClose();
1862 if ( bSuccess && m_xEmbeddedObject.is() )
1864 m_xEmbeddedObject->changeState( EmbedStates::LOADED );
1865 bSuccess = m_xEmbeddedObject->getCurrentState() == EmbedStates::LOADED;
1867 return bSuccess;
1870 Reference< XComponent > SAL_CALL ODocumentDefinition::open( ) throw (WrappedTargetException, RuntimeException, std::exception)
1872 return impl_openUI_nolck_throw( false );
1875 Reference< XComponent > SAL_CALL ODocumentDefinition::openDesign( ) throw (WrappedTargetException, RuntimeException, std::exception)
1877 return impl_openUI_nolck_throw( true );
1880 void SAL_CALL ODocumentDefinition::store( ) throw (WrappedTargetException, RuntimeException, std::exception)
1882 ::osl::MutexGuard aGuard( m_aMutex );
1885 impl_store_throw();
1887 catch( const RuntimeException& ) { throw; }
1888 catch( const Exception& )
1890 throw WrappedTargetException(
1891 OUString(), *this, ::cppu::getCaughtException() );
1895 sal_Bool SAL_CALL ODocumentDefinition::close( ) throw (WrappedTargetException, RuntimeException, std::exception)
1897 ::osl::MutexGuard aGuard( m_aMutex );
1899 bool bSuccess = false;
1902 bSuccess = impl_close_throw();
1904 catch( const RuntimeException& ) { throw; }
1905 catch( const Exception& )
1907 throw WrappedTargetException(
1908 OUString(), *this, ::cppu::getCaughtException() );
1910 return bSuccess;
1913 OUString SAL_CALL ODocumentDefinition::getHierarchicalName() throw (RuntimeException, std::exception)
1915 ::osl::MutexGuard aGuard( m_aMutex );
1916 return impl_getHierarchicalName( false );
1919 OUString SAL_CALL ODocumentDefinition::composeHierarchicalName( const OUString& i_rRelativeName ) throw (IllegalArgumentException, NoSupportException, RuntimeException, std::exception)
1921 OUStringBuffer aBuffer;
1922 aBuffer.append( getHierarchicalName() );
1923 aBuffer.append( '/' );
1924 aBuffer.append( i_rRelativeName );
1925 return aBuffer.makeStringAndClear();
1928 void SAL_CALL ODocumentDefinition::rename( const OUString& _rNewName ) throw (SQLException, ElementExistException, RuntimeException, std::exception)
1932 ::osl::ResettableMutexGuard aGuard(m_aMutex);
1933 if ( _rNewName.equals( m_pImpl->m_aProps.aTitle ) )
1934 return;
1936 // document definitions are organized in a hierarchical way, so reject names
1937 // which contain a /, as this is reserved for hierarchy level separation
1938 if ( _rNewName.indexOf( '/' ) != -1 )
1939 m_aErrorHelper.raiseException( ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES, *this );
1941 NameChangeNotifier aNameChangeAndNotify( *this, _rNewName, aGuard );
1942 m_pImpl->m_aProps.aTitle = _rNewName;
1944 if ( m_xEmbeddedObject.is() && m_xEmbeddedObject->getCurrentState() == EmbedStates::ACTIVE )
1945 updateDocumentTitle();
1947 catch(const PropertyVetoException&)
1949 throw ElementExistException(_rNewName,*this);
1953 Reference< XStorage> ODocumentDefinition::getContainerStorage() const
1955 return m_pImpl->m_pDataSource
1956 ? m_pImpl->m_pDataSource->getStorage( m_bForm ? ODatabaseModelImpl::E_FORM : ODatabaseModelImpl::E_REPORT )
1957 : Reference< XStorage>();
1960 bool ODocumentDefinition::isModified()
1962 osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex);
1963 bool bRet = false;
1964 if ( m_xEmbeddedObject.is() )
1966 Reference<XModifiable> xModel(getComponent(),UNO_QUERY);
1967 bRet = xModel.is() && xModel->isModified();
1969 return bRet;
1972 bool ODocumentDefinition::prepareClose()
1974 if ( !m_xEmbeddedObject.is() )
1975 return true;
1979 // suspend the controller. Embedded objects are not allowed to raise
1980 // own UI at their own discretion, instead, this has always to be triggered
1981 // by the embedding component. Thus, we do the suspend call here.
1982 // #i49370#
1984 Reference< util::XCloseable > xComponent( impl_getComponent_throw( false ) );
1985 if ( !xComponent.is() )
1986 return true;
1988 Reference< XModel > xModel( xComponent, UNO_QUERY );
1989 Reference< XController > xController;
1990 if ( xModel.is() )
1991 xController = xModel->getCurrentController();
1993 OSL_ENSURE( xController.is() || ( m_xEmbeddedObject->getCurrentState() < EmbedStates::ACTIVE ),
1994 "ODocumentDefinition::prepareClose: no controller!" );
1995 if ( !xController.is() )
1996 // document has not yet been activated, i.e. has no UI, yet
1997 return true;
1999 bool bCouldSuspend = xController->suspend( true );
2000 if ( !bCouldSuspend )
2001 // controller vetoed the closing
2002 return false;
2004 if ( isModified() )
2006 Reference< XFrame > xFrame( xController->getFrame() );
2007 if ( xFrame.is() )
2009 Reference< XTopWindow > xTopWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW );
2010 xTopWindow->toFront();
2012 if ( !save( true ) )
2014 if ( bCouldSuspend )
2015 // revert suspension
2016 xController->suspend( false );
2017 // saving failed or was cancelled
2018 return false;
2022 catch( const Exception& )
2024 DBG_UNHANDLED_EXCEPTION();
2027 return true;
2030 void ODocumentDefinition::fillReportData( const Reference< XComponentContext >& _rContext,
2031 const Reference< util::XCloseable >& _rxComponent,
2032 const Reference< XConnection >& _rxActiveConnection )
2034 Sequence< Any > aArgs(2);
2035 PropertyValue aValue;
2036 aValue.Name = "TextDocument";
2037 aValue.Value <<= _rxComponent;
2038 aArgs[0] <<= aValue;
2039 aValue.Name = "ActiveConnection";
2040 aValue.Value <<= _rxActiveConnection;
2041 aArgs[1] <<= aValue;
2045 Reference< XJobExecutor > xExecuteable(
2046 _rContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.wizards.report.CallReportWizard", aArgs, _rContext), UNO_QUERY_THROW );
2047 xExecuteable->trigger( "fill" );
2049 catch( const Exception& )
2051 DBG_UNHANDLED_EXCEPTION();
2055 void ODocumentDefinition::updateDocumentTitle()
2057 OUString sName = m_pImpl->m_aProps.aTitle;
2058 if ( m_pImpl->m_pDataSource )
2060 if ( sName.isEmpty() )
2062 if ( m_bForm )
2063 sName = DBACORE_RESSTRING( RID_STR_FORM );
2064 else
2065 sName = DBACORE_RESSTRING( RID_STR_REPORT );
2066 Reference< XUntitledNumbers > xUntitledProvider(m_pImpl->m_pDataSource->getModel_noCreate(), UNO_QUERY );
2067 if ( xUntitledProvider.is() )
2068 sName += OUString::number( xUntitledProvider->leaseNumber(getComponent()) );
2071 Reference< XTitle > xDatabaseDocumentModel(m_pImpl->m_pDataSource->getModel_noCreate(),uno::UNO_QUERY);
2072 if ( xDatabaseDocumentModel.is() )
2073 sName = xDatabaseDocumentModel->getTitle() + " : " + sName;
2075 Reference< XTitle> xTitle(getComponent(),UNO_QUERY);
2076 if ( xTitle.is() )
2077 xTitle->setTitle(sName);
2080 void SAL_CALL ODocumentDefinition::queryClosing( const lang::EventObject& Source, sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException, std::exception)
2082 (void) Source;
2083 (void) GetsOwnership;
2086 if ( !close() )
2087 throw util::CloseVetoException();
2089 catch(const lang::WrappedTargetException&)
2091 throw util::CloseVetoException();
2095 void SAL_CALL ODocumentDefinition::notifyClosing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException, std::exception)
2099 void SAL_CALL ODocumentDefinition::disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException, std::exception)
2103 void ODocumentDefinition::firePropertyChange( sal_Int32 i_nHandle, const Any& i_rNewValue, const Any& i_rOldValue,
2104 bool i_bVetoable, const NotifierAccess& )
2106 fire( &i_nHandle, &i_rNewValue, &i_rOldValue, 1, i_bVetoable );
2109 // NameChangeNotifier
2110 NameChangeNotifier::NameChangeNotifier( ODocumentDefinition& i_rDocumentDefinition, const OUString& i_rNewName,
2111 ::osl::ResettableMutexGuard& i_rClearForNotify )
2112 :m_rDocumentDefinition( i_rDocumentDefinition )
2113 ,m_aOldValue( makeAny( i_rDocumentDefinition.getCurrentName() ) )
2114 ,m_aNewValue( makeAny( i_rNewName ) )
2115 ,m_rClearForNotify( i_rClearForNotify )
2117 impl_fireEvent_throw( true );
2120 NameChangeNotifier::~NameChangeNotifier()
2122 impl_fireEvent_throw( false );
2125 void NameChangeNotifier::impl_fireEvent_throw( const bool i_bVetoable )
2127 m_rClearForNotify.clear();
2128 m_rDocumentDefinition.firePropertyChange(
2129 PROPERTY_ID_NAME, m_aNewValue, m_aOldValue, i_bVetoable, ODocumentDefinition::NotifierAccess() );
2130 m_rClearForNotify.reset();
2133 } // namespace dbaccess
2135 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */