nss: upgrade to release 3.73
[LibreOffice.git] / dbaccess / source / core / dataaccess / documentdefinition.cxx
blob2bfee3800b3b883b89a020ed57f0bdd1b5462296
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 <ModelImpl.hxx>
22 #include <stringconstants.hxx>
23 #include <sdbcoretools.hxx>
24 #include <tools/diagnose_ex.h>
25 #include <osl/diagnose.h>
26 #include <comphelper/sequence.hxx>
27 #include <comphelper/namedvaluecollection.hxx>
28 #include <comphelper/classids.hxx>
29 #include <comphelper/propertysequence.hxx>
30 #include <comphelper/types.hxx>
31 #include <com/sun/star/frame/XUntitledNumbers.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/report/XReportDefinition.hpp>
41 #include <com/sun/star/report/XReportEngine.hpp>
42 #include <com/sun/star/ucb/OpenMode.hpp>
43 #include <com/sun/star/embed/WrongStateException.hpp>
44 #include <com/sun/star/embed/EmbeddedObjectCreator.hpp>
45 #include <com/sun/star/embed/Aspects.hpp>
46 #include <com/sun/star/embed/OOoEmbeddedObjectFactory.hpp>
47 #include <ucbhelper/cancelcommandexecution.hxx>
48 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
49 #include <com/sun/star/embed/ElementModes.hpp>
50 #include <com/sun/star/embed/XEmbedPersist.hpp>
51 #include <com/sun/star/embed/EmbedStates.hpp>
52 #include <com/sun/star/embed/EntryInitModes.hpp>
53 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
54 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
55 #include <com/sun/star/util/CloseVetoException.hpp>
56 #include <com/sun/star/frame/XModule.hpp>
57 #include <com/sun/star/datatransfer/DataFlavor.hpp>
58 #include <com/sun/star/datatransfer/XTransferable.hpp>
59 #include <com/sun/star/container/XNameContainer.hpp>
60 #include <com/sun/star/embed/XCommonEmbedPersist.hpp>
61 #include "intercept.hxx"
62 #include <com/sun/star/sdb/ErrorCondition.hpp>
63 #include <com/sun/star/sdb/XInteractionDocumentSave.hpp>
64 #include <com/sun/star/task/InteractionHandler.hpp>
65 #include <com/sun/star/sdb/DocumentSaveRequest.hpp>
66 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
67 #include <com/sun/star/document/MacroExecMode.hpp>
68 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
69 #include <com/sun/star/form/XFormsSupplier.hpp>
70 #include <com/sun/star/form/XForm.hpp>
71 #include <comphelper/interaction.hxx>
72 #include <connectivity/dbtools.hxx>
73 #include <vcl/svapp.hxx>
74 #include <osl/mutex.hxx>
75 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
76 #include <core_resource.hxx>
77 #include <strings.hrc>
78 #include <com/sun/star/task/XInteractionApprove.hpp>
79 #include <com/sun/star/task/XInteractionDisapprove.hpp>
80 #include <com/sun/star/frame/XLayoutManager.hpp>
81 #include <cppuhelper/compbase.hxx>
82 #include <cppuhelper/exc_hlp.hxx>
83 #include <cppuhelper/implbase.hxx>
84 #include <comphelper/mimeconfighelper.hxx>
85 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
86 #include <com/sun/star/io/WrongFormatException.hpp>
87 #include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
88 #include <com/sun/star/sdb/application/DatabaseObject.hpp>
89 #include <com/sun/star/util/XModifiable2.hpp>
91 using namespace ::com::sun::star;
92 using namespace view;
93 using namespace uno;
94 using namespace util;
95 using namespace ucb;
96 using namespace beans;
97 using namespace lang;
98 using namespace awt;
99 using namespace embed;
100 using namespace frame;
101 using namespace document;
102 using namespace sdbc;
103 using namespace sdb;
104 using namespace io;
105 using namespace container;
106 using namespace datatransfer;
107 using namespace task;
108 using namespace form;
109 using namespace drawing;
110 using namespace ::osl;
111 using namespace ::comphelper;
112 using namespace ::cppu;
114 using sdb::application::XDatabaseDocumentUI;
115 namespace DatabaseObject = sdb::application::DatabaseObject;
117 #define DEFAULT_WIDTH 10000
118 #define DEFAULT_HEIGHT 7500
120 namespace dbaccess
123 typedef ::std::optional< bool > optional_bool;
125 // helper
126 namespace
128 OUString lcl_determineContentType_nothrow( const Reference< XStorage >& _rxContainerStorage,
129 const OUString& _rEntityName )
131 OUString sContentType;
134 ::utl::SharedUNOComponent< XPropertySet > xStorageProps(
135 _rxContainerStorage->openStorageElement( _rEntityName, ElementModes::READ ), UNO_QUERY_THROW );
136 OSL_VERIFY( xStorageProps->getPropertyValue( INFO_MEDIATYPE ) >>= sContentType );
138 catch( const Exception& )
140 DBG_UNHANDLED_EXCEPTION("dbaccess");
142 return sContentType;
146 // OEmbedObjectHolder
147 typedef ::cppu::WeakComponentImplHelper< embed::XStateChangeListener > TEmbedObjectHolder;
149 namespace {
151 class OEmbedObjectHolder : public ::cppu::BaseMutex
152 ,public TEmbedObjectHolder
154 Reference< XEmbeddedObject > m_xBroadCaster;
155 ODocumentDefinition* m_pDefinition;
156 bool m_bInStateChange;
157 protected:
158 virtual void SAL_CALL disposing() override;
159 public:
160 OEmbedObjectHolder(const Reference< XEmbeddedObject >& _xBroadCaster,ODocumentDefinition* _pDefinition)
161 : TEmbedObjectHolder(m_aMutex)
162 ,m_xBroadCaster(_xBroadCaster)
163 ,m_pDefinition(_pDefinition)
164 ,m_bInStateChange(false)
166 osl_atomic_increment( &m_refCount );
168 if ( m_xBroadCaster.is() )
169 m_xBroadCaster->addStateChangeListener(this);
171 osl_atomic_decrement( &m_refCount );
174 virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) override;
175 virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) override;
176 virtual void SAL_CALL disposing( const lang::EventObject& Source ) override;
181 void SAL_CALL OEmbedObjectHolder::disposing()
183 if ( m_xBroadCaster.is() )
184 m_xBroadCaster->removeStateChangeListener(this);
185 m_xBroadCaster = nullptr;
186 m_pDefinition = nullptr;
189 void SAL_CALL OEmbedObjectHolder::changingState( const lang::EventObject& /*aEvent*/, ::sal_Int32 /*nOldState*/, ::sal_Int32 /*nNewState*/ )
193 void SAL_CALL OEmbedObjectHolder::stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
195 if ( !m_bInStateChange && nNewState == EmbedStates::RUNNING && nOldState == EmbedStates::ACTIVE && m_pDefinition )
197 m_bInStateChange = true;
198 Reference<XInterface> xHoldAlive(static_cast< ::cppu::OWeakObject* >(m_pDefinition),UNO_QUERY);
200 Reference<XEmbeddedObject> xEmbeddedObject(aEvent.Source,UNO_QUERY);
201 if ( xEmbeddedObject.is() )
202 xEmbeddedObject->changeState(EmbedStates::LOADED);
204 m_bInStateChange = false;
208 void SAL_CALL OEmbedObjectHolder::disposing( const lang::EventObject& /*Source*/ )
210 m_xBroadCaster = nullptr;
213 // OEmbeddedClientHelper
214 class OEmbeddedClientHelper : public ::cppu::WeakImplHelper<XEmbeddedClient>
216 public:
217 virtual void SAL_CALL saveObject( ) override
220 // XComponentSupplier
221 virtual Reference< util::XCloseable > SAL_CALL getComponent( ) override
223 return Reference< css::util::XCloseable >();
226 // XEmbeddedClient
227 virtual void SAL_CALL visibilityChanged( sal_Bool /*bVisible*/ ) override
232 namespace {
234 // LockModifiable
235 class LockModifiable
237 public:
238 explicit LockModifiable( const Reference< XInterface >& i_rModifiable )
239 :m_xModifiable( i_rModifiable, UNO_QUERY )
241 OSL_ENSURE( m_xModifiable.is(), "LockModifiable::LockModifiable: invalid component!" );
242 if ( m_xModifiable.is() )
244 if ( !m_xModifiable->isSetModifiedEnabled() )
246 // somebody already locked that, no need to lock it, again, and no need to unlock it later
247 m_xModifiable.clear();
249 else
251 m_xModifiable->disableSetModified();
256 ~LockModifiable()
258 if ( m_xModifiable.is() )
259 m_xModifiable->enableSetModified();
262 private:
263 Reference< XModifiable2 > m_xModifiable;
268 // LifetimeCoupler
269 typedef ::cppu::WeakImplHelper< css::lang::XEventListener
270 > LifetimeCoupler_Base;
272 namespace {
274 /** helper class which couples the lifetime of a component to the lifetime
275 of another component
277 Instances of this class are constructed with two components. The first is
278 simply held by reference, and thus kept alive. The second one is observed
279 for <code>disposing</code> calls - if they occur, i.e. if the component dies,
280 the reference to the first component is cleared.
282 This way, you can ensure that a certain component is kept alive as long
283 as a second component is not disposed.
285 class LifetimeCoupler : public LifetimeCoupler_Base
287 private:
288 Reference< XInterface > m_xClient;
290 public:
291 static void couple( const Reference< XInterface >& _rxClient, const Reference< XComponent >& _rxActor )
293 new LifetimeCoupler( _rxClient, _rxActor );
296 private:
297 LifetimeCoupler( const Reference< XInterface >& _rxClient, const Reference< XComponent >& _rxActor )
298 :m_xClient( _rxClient )
300 OSL_ENSURE( _rxActor.is(), "LifetimeCoupler::LifetimeCoupler: this will crash!" );
301 osl_atomic_increment( &m_refCount );
303 _rxActor->addEventListener( this );
305 osl_atomic_decrement( &m_refCount );
306 OSL_ENSURE( m_refCount, "LifetimeCoupler::LifetimeCoupler: the actor is not holding us by hard ref - this won't work!" );
309 virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
310 protected:
315 void SAL_CALL LifetimeCoupler::disposing( const css::lang::EventObject& /*Source*/ )
317 m_xClient.clear();
320 namespace {
322 // ODocumentSaveContinuation
323 class ODocumentSaveContinuation : public OInteraction< XInteractionDocumentSave >
325 OUString m_sName;
326 Reference<XContent> m_xParentContainer;
328 public:
329 ODocumentSaveContinuation() { }
331 const Reference<XContent>& getContent() const { return m_xParentContainer; }
332 const OUString& getName() const { return m_sName; }
334 // XInteractionDocumentSave
335 virtual void SAL_CALL setName( const OUString& _sName,const Reference<XContent>& _xParent) override;
340 void SAL_CALL ODocumentSaveContinuation::setName( const OUString& _sName,const Reference<XContent>& _xParent)
342 m_sName = _sName;
343 m_xParentContainer = _xParent;
346 OUString ODocumentDefinition::GetDocumentServiceFromMediaType( const Reference< XStorage >& _rxContainerStorage,
347 const OUString& _rEntityName, const Reference< XComponentContext >& _rContext,
348 Sequence< sal_Int8 >& _rClassId )
350 return GetDocumentServiceFromMediaType(
351 lcl_determineContentType_nothrow( _rxContainerStorage, _rEntityName ),
352 _rContext, _rClassId );
355 OUString ODocumentDefinition::GetDocumentServiceFromMediaType( const OUString& _rMediaType,
356 const Reference< XComponentContext >& _rContext, Sequence< sal_Int8 >& _rClassId )
358 OUString sResult;
361 ::comphelper::MimeConfigurationHelper aConfigHelper( _rContext );
362 sResult = aConfigHelper.GetDocServiceNameFromMediaType( _rMediaType );
363 _rClassId = comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation(aConfigHelper.GetExplicitlyRegisteredObjClassID( _rMediaType ));
364 if ( !_rClassId.hasElements() && !sResult.isEmpty() )
366 Reference< XNameAccess > xObjConfig = aConfigHelper.GetObjConfiguration();
367 if ( xObjConfig.is() )
369 const Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
370 for ( OUString const & classId : aClassIDs )
372 Reference< XNameAccess > xObjectProps;
373 OUString aEntryDocName;
375 if ( ( xObjConfig->getByName( classId ) >>= xObjectProps ) && xObjectProps.is()
376 && ( xObjectProps->getByName("ObjectDocumentServiceName") >>= aEntryDocName )
377 && aEntryDocName == sResult )
379 _rClassId = comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation(classId);
380 break;
385 #if OSL_DEBUG_LEVEL > 0
386 // alternative, shorter approach
387 const Sequence< NamedValue > aProps( aConfigHelper.GetObjectPropsByMediaType( _rMediaType ) );
388 const ::comphelper::NamedValueCollection aMediaTypeProps( aProps );
389 const OUString sAlternativeResult = aMediaTypeProps.getOrDefault( "ObjectDocumentServiceName", OUString() );
390 OSL_ENSURE( sAlternativeResult == sResult, "ODocumentDefinition::GetDocumentServiceFromMediaType: failed, this approach is *not* equivalent (1)!" );
391 const Sequence< sal_Int8 > aAlternativeClassID = aMediaTypeProps.getOrDefault( "ClassID", Sequence< sal_Int8 >() );
392 OSL_ENSURE( aAlternativeClassID == _rClassId, "ODocumentDefinition::GetDocumentServiceFromMediaType: failed, this approach is *not* equivalent (2)!" );
393 #endif
395 catch ( const Exception& )
397 DBG_UNHANDLED_EXCEPTION("dbaccess");
399 return sResult;
402 // ODocumentDefinition
404 ODocumentDefinition::ODocumentDefinition( const Reference< XInterface >& _rxContainer, const Reference< XComponentContext >& _xORB,
405 const TContentPtr& _pImpl, bool _bForm )
406 :OContentHelper(_xORB,_rxContainer,_pImpl)
407 ,OPropertyStateContainer(OContentHelper::rBHelper)
408 ,m_bForm(_bForm)
409 ,m_bOpenInDesign(false)
410 ,m_bInExecute(false)
411 ,m_bRemoveListener(false)
413 registerProperties();
416 void ODocumentDefinition::initialLoad( const Sequence< sal_Int8 >& i_rClassID, const Sequence< PropertyValue >& i_rCreationArgs,
417 const Reference< XConnection >& i_rConnection )
419 OSL_ENSURE( i_rClassID.hasElements(), "ODocumentDefinition::initialLoad: illegal class ID!" );
420 if ( !i_rClassID.hasElements() )
421 return;
423 loadEmbeddedObject( i_rConnection, i_rClassID, i_rCreationArgs, false, false );
426 ODocumentDefinition::~ODocumentDefinition()
428 if ( !OContentHelper::rBHelper.bInDispose && !OContentHelper::rBHelper.bDisposed )
430 acquire();
431 dispose();
434 if ( m_pInterceptor.is() )
436 m_pInterceptor->dispose();
437 m_pInterceptor.clear();
441 void ODocumentDefinition::closeObject()
443 ::osl::MutexGuard aGuard(m_aMutex);
444 if ( m_xEmbeddedObject.is() )
448 m_xEmbeddedObject->close(true);
450 catch(const Exception&)
453 m_xEmbeddedObject = nullptr;
454 m_pClientHelper.clear();
458 void SAL_CALL ODocumentDefinition::disposing()
460 OContentHelper::disposing();
461 ::osl::MutexGuard aGuard(m_aMutex);
462 closeObject();
463 ::comphelper::disposeComponent(m_xListener);
464 if ( m_bRemoveListener )
466 Reference<util::XCloseable> xCloseable(m_pImpl->m_pDataSource->getModel_noCreate(),UNO_QUERY);
467 if ( xCloseable.is() )
468 xCloseable->removeCloseListener(this);
472 css::uno::Sequence<sal_Int8> ODocumentDefinition::getImplementationId()
474 return css::uno::Sequence<sal_Int8>();
477 IMPLEMENT_GETTYPES3(ODocumentDefinition,OContentHelper,OPropertyStateContainer,ODocumentDefinition_Base);
478 IMPLEMENT_FORWARD_XINTERFACE3( ODocumentDefinition,OContentHelper,OPropertyStateContainer,ODocumentDefinition_Base)
480 void ODocumentDefinition::registerProperties()
482 #define REGISTER_PROPERTY( name, location ) \
483 registerProperty( PROPERTY_##name, PROPERTY_ID_##name, PropertyAttribute::READONLY, &location, cppu::UnoType<decltype(location)>::get() );
485 #define REGISTER_PROPERTY_BV( name, location ) \
486 registerProperty( PROPERTY_##name, PROPERTY_ID_##name, PropertyAttribute::CONSTRAINED | PropertyAttribute::BOUND | PropertyAttribute::READONLY, &location, cppu::UnoType<decltype(location)>::get() );
488 REGISTER_PROPERTY_BV( NAME, m_pImpl->m_aProps.aTitle );
489 REGISTER_PROPERTY ( AS_TEMPLATE, m_pImpl->m_aProps.bAsTemplate );
490 REGISTER_PROPERTY ( PERSISTENT_NAME, m_pImpl->m_aProps.sPersistentName );
491 REGISTER_PROPERTY ( IS_FORM, m_bForm );
494 void SAL_CALL ODocumentDefinition::getFastPropertyValue( Any& o_rValue, sal_Int32 i_nHandle ) const
496 if ( i_nHandle == PROPERTY_ID_PERSISTENT_PATH )
498 OUString sPersistentPath;
499 if ( !m_pImpl->m_aProps.sPersistentName.isEmpty() )
501 OUStringBuffer aBuffer;
502 aBuffer.append( ODatabaseModelImpl::getObjectContainerStorageName( m_bForm ? ODatabaseModelImpl::E_FORM : ODatabaseModelImpl::E_REPORT ) );
503 aBuffer.append( '/' );
504 aBuffer.append( m_pImpl->m_aProps.sPersistentName );
505 sPersistentPath = aBuffer.makeStringAndClear();
507 o_rValue <<= sPersistentPath;
508 return;
511 OPropertyStateContainer::getFastPropertyValue( o_rValue, i_nHandle );
514 Reference< XPropertySetInfo > SAL_CALL ODocumentDefinition::getPropertySetInfo( )
516 Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
517 return xInfo;
520 IPropertyArrayHelper& ODocumentDefinition::getInfoHelper()
522 return *getArrayHelper();
525 IPropertyArrayHelper* ODocumentDefinition::createArrayHelper( ) const
527 // properties maintained by our base class (see registerProperties)
528 Sequence< Property > aProps;
529 describeProperties( aProps );
531 // properties not maintained by our base class
532 Sequence< Property > aManualProps( 1 );
533 aManualProps[0].Name = PROPERTY_PERSISTENT_PATH;
534 aManualProps[0].Handle = PROPERTY_ID_PERSISTENT_PATH;
535 aManualProps[0].Type = ::cppu::UnoType<OUString>::get();
536 aManualProps[0].Attributes = PropertyAttribute::READONLY;
538 return new OPropertyArrayHelper( ::comphelper::concatSequences( aProps, aManualProps ) );
541 namespace {
543 class OExecuteImpl
545 bool& m_rbSet;
546 public:
547 explicit OExecuteImpl(bool& _rbSet) : m_rbSet(_rbSet){ m_rbSet=true; }
548 ~OExecuteImpl(){ m_rbSet = false; }
551 bool lcl_extractOpenMode( const Any& _rValue, sal_Int32& _out_rMode )
553 OpenCommandArgument aOpenCommand;
554 if ( _rValue >>= aOpenCommand )
555 _out_rMode = aOpenCommand.Mode;
556 else
558 OpenCommandArgument2 aOpenCommand2;
559 if ( _rValue >>= aOpenCommand2 )
560 _out_rMode = aOpenCommand2.Mode;
561 else
562 return false;
564 return true;
568 void ODocumentDefinition::impl_removeFrameFromDesktop_throw( const Reference<XComponentContext> & _rxContext, const Reference< XFrame >& _rxFrame )
570 Reference< XDesktop2 > xDesktop = Desktop::create( _rxContext );
571 Reference< XFrames > xFrames( xDesktop->getFrames(), UNO_SET_THROW );
572 xFrames->remove( _rxFrame );
575 void ODocumentDefinition::impl_onActivateEmbeddedObject_nothrow( const bool i_bReactivated )
579 Reference< XModel > xModel( getComponent(), UNO_QUERY );
580 Reference< XController > xController( xModel.is() ? xModel->getCurrentController() : Reference< XController >() );
581 if ( !xController.is() )
582 return;
584 if ( !m_xListener.is() )
585 // it's the first time the embedded object has been activated
586 // create an OEmbedObjectHolder
587 m_xListener = new OEmbedObjectHolder( m_xEmbeddedObject, this );
589 // raise the window to top (especially necessary if this is not the first activation)
590 Reference< XFrame > xFrame( xController->getFrame(), UNO_SET_THROW );
591 Reference< XTopWindow > xTopWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW );
592 xTopWindow->toFront();
594 // remove the frame from the desktop's frame collection because we need full control of it.
595 impl_removeFrameFromDesktop_throw( m_aContext, xFrame );
597 // ensure that we ourself are kept alive as long as the embedded object's frame is
598 // opened
599 LifetimeCoupler::couple( *this, xFrame.get() );
601 // init the edit view
602 if ( m_bForm && m_bOpenInDesign && !i_bReactivated )
603 impl_initFormEditView( xController );
605 catch( const RuntimeException& )
607 DBG_UNHANDLED_EXCEPTION("dbaccess");
611 namespace
613 // PreserveVisualAreaSize
614 /** stack-guard for preserving the size of the VisArea of an XModel
616 class PreserveVisualAreaSize
618 private:
619 Reference< XVisualObject > m_xVisObject;
620 awt::Size m_aOriginalSize;
622 public:
623 explicit PreserveVisualAreaSize( const Reference< XModel >& _rxModel )
624 :m_xVisObject( _rxModel, UNO_QUERY )
626 if ( m_xVisObject.is() )
630 m_aOriginalSize = m_xVisObject->getVisualAreaSize( Aspects::MSOLE_CONTENT );
632 catch ( const Exception& )
634 TOOLS_WARN_EXCEPTION( "dbaccess", "PreserveVisualAreaSize::PreserveVisualAreaSize" );
639 ~PreserveVisualAreaSize()
641 if ( m_xVisObject.is() && m_aOriginalSize.Width && m_aOriginalSize.Height )
645 m_xVisObject->setVisualAreaSize( Aspects::MSOLE_CONTENT, m_aOriginalSize );
647 catch ( const Exception& )
649 TOOLS_WARN_EXCEPTION( "dbaccess", "PreserveVisualAreaSize::~PreserveVisualAreaSize" );
655 // LayoutManagerLock
656 /** helper class for stack-usage which during its lifetime locks a layout manager
658 class LayoutManagerLock
660 private:
661 Reference< XLayoutManager > m_xLayoutManager;
663 public:
664 explicit LayoutManagerLock( const Reference< XController >& _rxController )
666 OSL_ENSURE( _rxController.is(), "LayoutManagerLock::LayoutManagerLock: this will crash!" );
667 Reference< XFrame > xFrame( _rxController->getFrame() );
670 Reference< XPropertySet > xPropSet( xFrame, UNO_QUERY_THROW );
671 m_xLayoutManager.set(
672 xPropSet->getPropertyValue( "LayoutManager" ),
673 UNO_QUERY_THROW );
674 m_xLayoutManager->lock();
677 catch( const Exception& )
679 TOOLS_WARN_EXCEPTION( "dbaccess", "LayoutManagerLock::LayoutManagerLock" );
683 ~LayoutManagerLock()
687 // unlock the layout manager
688 if ( m_xLayoutManager.is() )
689 m_xLayoutManager->unlock();
691 catch( const Exception& )
693 TOOLS_WARN_EXCEPTION( "dbaccess", "LayoutManagerLock::~LayoutManagerLock" );
699 void ODocumentDefinition::impl_initFormEditView( const Reference< XController >& _rxController )
703 Reference< XViewSettingsSupplier > xSettingsSupplier( _rxController, UNO_QUERY_THROW );
704 Reference< XPropertySet > xViewSettings( xSettingsSupplier->getViewSettings(), UNO_SET_THROW );
706 // the below code could indirectly tamper with the "modified" flag of the model, temporarily disable this
707 LockModifiable aLockModify( _rxController->getModel() );
709 // The visual area size can be changed by the setting of the following properties
710 // so it should be restored later
711 PreserveVisualAreaSize aPreserveVisAreaSize( _rxController->getModel() );
713 // Layout manager should not layout while the size is still not restored
714 // so it will stay locked for this time
715 LayoutManagerLock aLockLayout( _rxController );
717 // setting of the visual properties
718 xViewSettings->setPropertyValue("ShowRulers",makeAny(true));
719 xViewSettings->setPropertyValue("ShowVertRuler",makeAny(true));
720 xViewSettings->setPropertyValue("ShowHoriRuler",makeAny(true));
721 xViewSettings->setPropertyValue("IsRasterVisible",makeAny(true));
722 xViewSettings->setPropertyValue("IsSnapToRaster",makeAny(true));
723 xViewSettings->setPropertyValue("ShowOnlineLayout",makeAny(true));
724 xViewSettings->setPropertyValue("RasterSubdivisionX",makeAny(sal_Int32(5)));
725 xViewSettings->setPropertyValue("RasterSubdivisionY",makeAny(sal_Int32(5)));
727 catch( const Exception& )
729 DBG_UNHANDLED_EXCEPTION("dbaccess");
733 void ODocumentDefinition::impl_showOrHideComponent_throw( const bool i_bShow )
735 const sal_Int32 nCurrentState = m_xEmbeddedObject.is() ? m_xEmbeddedObject->getCurrentState() : EmbedStates::LOADED;
736 switch ( nCurrentState )
738 default:
739 case EmbedStates::LOADED:
740 throw embed::WrongStateException( OUString(), *this );
742 case EmbedStates::RUNNING:
743 if ( !i_bShow )
744 // fine, a running (and not yet active) object is never visible
745 return;
747 LockModifiable aLockModify( impl_getComponent_throw() );
748 m_xEmbeddedObject->changeState( EmbedStates::ACTIVE );
749 impl_onActivateEmbeddedObject_nothrow( false );
751 break;
753 case EmbedStates::ACTIVE:
755 Reference< XModel > xEmbeddedDoc( impl_getComponent_throw(), UNO_QUERY_THROW );
756 Reference< XController > xEmbeddedController( xEmbeddedDoc->getCurrentController(), UNO_SET_THROW );
757 Reference< XFrame > xEmbeddedFrame( xEmbeddedController->getFrame(), UNO_SET_THROW );
758 Reference< XWindow > xEmbeddedWindow( xEmbeddedFrame->getContainerWindow(), UNO_SET_THROW );
759 xEmbeddedWindow->setVisible( i_bShow );
761 break;
765 Any ODocumentDefinition::onCommandOpenSomething( const Any& _rOpenArgument, const bool _bActivate,
766 const Reference< XCommandEnvironment >& _rxEnvironment )
768 OExecuteImpl aExecuteGuard( m_bInExecute );
770 Reference< XConnection > xConnection;
771 sal_Int32 nOpenMode = OpenMode::DOCUMENT;
773 ::comphelper::NamedValueCollection aDocumentArgs;
775 // for the document, default to the interaction handler as used for loading the DB doc
776 // This might be overwritten below, when examining _rOpenArgument.
777 const ::comphelper::NamedValueCollection& aDBDocArgs( m_pImpl->m_pDataSource->getMediaDescriptor() );
778 Reference< XInteractionHandler > xHandler( aDBDocArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) );
779 if ( xHandler.is() )
780 aDocumentArgs.put( "InteractionHandler", xHandler );
782 ::std::optional< sal_Int16 > aDocumentMacroMode;
784 if ( !lcl_extractOpenMode( _rOpenArgument, nOpenMode ) )
786 Sequence< PropertyValue > aArguments;
787 if ( _rOpenArgument >>= aArguments )
789 const PropertyValue* pIter = aArguments.getConstArray();
790 const PropertyValue* pEnd = pIter + aArguments.getLength();
791 for ( ;pIter != pEnd; ++pIter )
793 if ( pIter->Name == PROPERTY_ACTIVE_CONNECTION )
795 xConnection.set( pIter->Value, UNO_QUERY );
796 continue;
799 if ( lcl_extractOpenMode( pIter->Value, nOpenMode ) )
800 continue;
802 if ( pIter->Name == "MacroExecutionMode" )
804 sal_Int16 nMacroExecMode( !aDocumentMacroMode ? MacroExecMode::USE_CONFIG : *aDocumentMacroMode );
805 OSL_VERIFY( pIter->Value >>= nMacroExecMode );
806 aDocumentMacroMode = nMacroExecMode;
807 continue;
810 // unknown argument -> pass to the loaded document
811 aDocumentArgs.put( pIter->Name, pIter->Value );
816 bool bExecuteDBDocMacros = m_pImpl->m_pDataSource->checkMacrosOnLoading();
817 // Note that this call implies the user might be asked for the macro execution mode.
818 // Normally, this would happen when the database document is loaded, and subsequent calls
819 // will simply use the user's decision from this point in time.
820 // However, it is possible to programmatically load forms/reports, without actually
821 // loading the database document into a frame. In this case, the user will be asked
822 // here and now.
823 // #i87741#
825 // allow the command arguments to downgrade the macro execution mode, but not to upgrade
826 // it
827 if ( ( m_pImpl->m_pDataSource->getImposedMacroExecMode() == MacroExecMode::USE_CONFIG )
828 && bExecuteDBDocMacros
831 // while loading the whole database document, USE_CONFIG, was passed.
832 // Additionally, *by now* executing macros from the DB doc is allowed (this is what bExecuteDBDocMacros
833 // indicates). This means either one of:
834 // 1. The DB doc or one of the sub docs contained macros and
835 // 1a. the user explicitly allowed executing them
836 // 1b. the configuration allows executing them without asking the user
837 // 2. Neither the DB doc nor the sub docs contained macros, thus macro
838 // execution was silently enabled, assuming that any macro will be a
839 // user-created macro
841 // The problem with this: If the to-be-opened sub document has macros embedded in
842 // the content.xml (which is valid ODF, but normally not produced by OOo itself),
843 // then this has not been detected while loading the database document - it would
844 // be too expensive, as it effectively would require loading all forms/reports.
846 // So, in such a case, and with 2. above, we would silently execute those macros,
847 // regardless of the global security settings - which would be a security issue, of
848 // course.
849 if ( m_pImpl->m_pDataSource->determineEmbeddedMacros() == ODatabaseModelImpl::eNoMacros )
851 // this is case 2. from above
852 // So, pass a USE_CONFIG to the to-be-loaded document. This means that
853 // the user will be prompted with a security message upon opening this
854 // sub document, in case the settings require this, *and* the document
855 // contains scripts in the content.xml. But this is better than the security
856 // issue we had before ...
857 aDocumentMacroMode = MacroExecMode::USE_CONFIG;
861 if ( !aDocumentMacroMode )
863 // nobody so far felt responsible for setting it
864 // => use the DBDoc-wide macro exec mode for the document, too
865 aDocumentMacroMode = bExecuteDBDocMacros ? MacroExecMode::ALWAYS_EXECUTE_NO_WARN
866 : MacroExecMode::NEVER_EXECUTE;
868 aDocumentArgs.put( "MacroExecutionMode", *aDocumentMacroMode );
870 if ( ( nOpenMode == OpenMode::ALL )
871 || ( nOpenMode == OpenMode::FOLDERS )
872 || ( nOpenMode == OpenMode::DOCUMENTS )
873 || ( nOpenMode == OpenMode::DOCUMENT_SHARE_DENY_NONE )
874 || ( nOpenMode == OpenMode::DOCUMENT_SHARE_DENY_WRITE )
877 // not supported
878 ucbhelper::cancelCommandExecution(
879 makeAny( UnsupportedOpenModeException(
880 OUString(),
881 static_cast< cppu::OWeakObject * >( this ),
882 sal_Int16( nOpenMode ) ) ),
883 _rxEnvironment );
884 // Unreachable
885 OSL_FAIL( "unreachable" );
888 OSL_ENSURE( !m_pImpl->m_aProps.sPersistentName.isEmpty(),
889 "ODocumentDefinition::onCommandOpenSomething: no persistent name - cannot load!" );
890 if ( m_pImpl->m_aProps.sPersistentName.isEmpty() )
891 return Any();
893 // embedded objects themself do not support the hidden flag. We implement support for
894 // it by changing the STATE to RUNNING only, instead of ACTIVE.
895 bool bOpenHidden = aDocumentArgs.getOrDefault( "Hidden", false );
896 aDocumentArgs.remove( "Hidden" );
898 loadEmbeddedObject( xConnection, Sequence< sal_Int8 >(), aDocumentArgs.getPropertyValues(), false, !m_bOpenInDesign );
899 OSL_ENSURE( m_xEmbeddedObject.is(), "ODocumentDefinition::onCommandOpenSomething: what's this?" );
900 if ( !m_xEmbeddedObject.is() )
901 return Any();
903 Reference< XModel > xModel( getComponent(), UNO_QUERY );
904 Reference< report::XReportDefinition > xReportDefinition(xModel,UNO_QUERY);
906 Reference< XModule > xModule( xModel, UNO_QUERY );
907 if ( xModule.is() )
909 if ( m_bForm )
910 xModule->setIdentifier( "com.sun.star.sdb.FormDesign" );
911 else if ( !xReportDefinition.is() )
912 xModule->setIdentifier( "com.sun.star.text.TextDocument" );
914 updateDocumentTitle();
917 bool bIsAliveNewStyleReport = ( !m_bOpenInDesign && xReportDefinition.is() );
918 if ( bIsAliveNewStyleReport )
920 // we are in ReadOnly mode
921 // we would like to open the Writer or Calc with the report direct, without design it.
922 Reference< report::XReportEngine > xReportEngine( m_aContext->getServiceManager()->createInstanceWithContext("com.sun.star.comp.report.OReportEngineJFree", m_aContext), UNO_QUERY_THROW );
924 xReportEngine->setReportDefinition(xReportDefinition);
925 xReportEngine->setActiveConnection(m_xLastKnownConnection);
926 if ( bOpenHidden )
927 return makeAny( xReportEngine->createDocumentModel() );
928 return makeAny( xReportEngine->createDocumentAlive( nullptr ) );
931 if ( _bActivate && !bOpenHidden )
933 LockModifiable aLockModify( impl_getComponent_throw() );
934 m_xEmbeddedObject->changeState( EmbedStates::ACTIVE );
935 impl_onActivateEmbeddedObject_nothrow( false );
937 else
939 // ensure that we ourself are kept alive as long as the document is open
940 LifetimeCoupler::couple( *this, xModel.get() );
943 if ( !m_bForm && m_pImpl->m_aProps.bAsTemplate && !m_bOpenInDesign )
944 ODocumentDefinition::fillReportData( m_aContext, getComponent(), xConnection );
946 return makeAny( xModel );
949 Any SAL_CALL ODocumentDefinition::execute( const Command& aCommand, sal_Int32 CommandId, const Reference< XCommandEnvironment >& Environment )
951 Any aRet;
953 bool bOpen = aCommand.Name == "open";
954 bool bOpenInDesign = aCommand.Name == "openDesign";
955 bool bOpenForMail = aCommand.Name == "openForMail";
956 if ( bOpen || bOpenInDesign || bOpenForMail )
958 // opening the document involves a lot of VCL code, which is not thread-safe, but needs the SolarMutex locked.
959 // Unfortunately, the DocumentDefinition, as well as the EmbeddedObject implementation, calls into VCL-dependent
960 // components *without* releasing the own mutex, which is a guaranteed recipe for deadlocks.
961 // We have control over this implementation here, and in modifying it to release the own mutex before calling into
962 // the VCL-dependent components is not too difficult (was there, seen it).
963 // However, we do /not/ have control over the EmbeddedObject implementation, and from a first look, it seems as
964 // making it release the own mutex before calling SolarMutex-code is ... difficult, at least.
965 // So, to be on the same side, we lock the SolarMutex here. Yes, it sucks.
966 ::SolarMutexGuard aSolarGuard;
967 osl::MutexGuard aGuard(m_aMutex);
968 if ( m_bInExecute )
969 return aRet;
971 bool bActivateObject = true;
972 if ( bOpenForMail )
974 OSL_FAIL( "ODocumentDefinition::execute: 'openForMail' should not be used anymore - use the 'Hidden' parameter instead!" );
975 bActivateObject = false;
978 // if the object is already opened, do nothing
979 if ( m_xEmbeddedObject.is() )
981 sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState();
982 bool bIsActive = ( nCurrentState == EmbedStates::ACTIVE );
984 if ( bIsActive )
986 // exception: new-style reports always create a new document when "open" is executed
987 Reference< report::XReportDefinition > xReportDefinition( impl_getComponent_throw( false ), UNO_QUERY );
988 bool bIsAliveNewStyleReport = ( xReportDefinition.is() && ( bOpen || bOpenForMail ) );
990 if ( !bIsAliveNewStyleReport )
992 impl_onActivateEmbeddedObject_nothrow( true );
993 return makeAny( getComponent() );
998 m_bOpenInDesign = bOpenInDesign || bOpenForMail;
999 return onCommandOpenSomething( aCommand.Argument, bActivateObject, Environment );
1002 osl::MutexGuard aGuard(m_aMutex);
1003 if ( m_bInExecute )
1004 return aRet;
1006 if ( aCommand.Name == "copyTo" )
1008 Sequence<Any> aIni;
1009 aCommand.Argument >>= aIni;
1010 if ( aIni.getLength() != 2 )
1012 OSL_FAIL( "Wrong argument type!" );
1013 ucbhelper::cancelCommandExecution(
1014 makeAny( IllegalArgumentException(
1015 OUString(),
1016 static_cast< cppu::OWeakObject * >( this ),
1017 -1 ) ),
1018 Environment );
1019 // Unreachable
1021 Reference< XStorage> xDest(aIni[0],UNO_QUERY);
1022 OUString sPersistentName;
1023 aIni[1] >>= sPersistentName;
1024 Reference< XStorage> xStorage = getContainerStorage();
1026 xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xDest,sPersistentName);
1028 else if ( aCommand.Name == "preview" )
1030 onCommandPreview(aRet);
1032 else if ( aCommand.Name == "insert" )
1034 Sequence<Any> aIni;
1035 aCommand.Argument >>= aIni;
1036 if ( !aIni.hasElements() )
1038 OSL_FAIL( "Wrong argument count!" );
1039 ucbhelper::cancelCommandExecution(
1040 makeAny( IllegalArgumentException(
1041 OUString(),
1042 static_cast< cppu::OWeakObject * >( this ),
1043 -1 ) ),
1044 Environment );
1045 // Unreachable
1047 OUString sURL;
1048 aIni[0] >>= sURL;
1049 onCommandInsert( sURL, Environment );
1051 else if ( aCommand.Name == "getdocumentinfo" // compatibility
1052 || aCommand.Name == "getDocumentInfo" )
1054 onCommandGetDocumentProperties( aRet );
1056 else if ( aCommand.Name == "delete" )
1058 // delete
1059 closeObject();
1060 Reference< XStorage> xStorage = getContainerStorage();
1061 if ( xStorage.is() )
1062 xStorage->removeElement(m_pImpl->m_aProps.sPersistentName);
1064 dispose();
1067 else if ( aCommand.Name == "storeOwn" // compatibility
1068 || aCommand.Name == "store"
1071 impl_store_throw();
1073 else if ( aCommand.Name == "shutdown" // compatibility
1074 || aCommand.Name == "close"
1077 aRet <<= impl_close_throw();
1079 else if ( aCommand.Name == "show" )
1081 impl_showOrHideComponent_throw( true );
1083 else if ( aCommand.Name == "hide" )
1085 impl_showOrHideComponent_throw( false );
1087 else
1089 aRet = OContentHelper::execute(aCommand,CommandId,Environment);
1092 return aRet;
1095 namespace
1097 void lcl_resetChildFormsToEmptyDataSource( const Reference< XIndexAccess>& _rxFormsContainer )
1099 OSL_PRECOND( _rxFormsContainer.is(), "lcl_resetChildFormsToEmptyDataSource: illegal call!" );
1100 sal_Int32 count = _rxFormsContainer->getCount();
1101 for ( sal_Int32 i = 0; i < count; ++i )
1103 Reference< XForm > xForm( _rxFormsContainer->getByIndex( i ), UNO_QUERY );
1104 if ( !xForm.is() )
1105 continue;
1107 // if the element is a form, reset its DataSourceName property to an empty string
1110 Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW );
1111 xFormProps->setPropertyValue( PROPERTY_DATASOURCENAME, makeAny( OUString() ) );
1113 catch( const Exception& )
1115 DBG_UNHANDLED_EXCEPTION("dbaccess");
1118 // if the element is a container itself, step down the component hierarchy
1119 Reference< XIndexAccess > xContainer( xForm, UNO_QUERY );
1120 if ( xContainer.is() )
1121 lcl_resetChildFormsToEmptyDataSource( xContainer );
1125 void lcl_resetFormsToEmptyDataSource( const Reference< XEmbeddedObject>& _rxEmbeddedObject )
1129 Reference< XDrawPageSupplier > xSuppPage( _rxEmbeddedObject->getComponent(), UNO_QUERY_THROW );
1130 // if this interface does not exist, then either getComponent returned NULL,
1131 // or the document is a multi-page document. The latter is allowed, but currently
1132 // simply not handled by this code, as it would not normally happen.
1134 Reference< XFormsSupplier > xSuppForms( xSuppPage->getDrawPage(), UNO_QUERY_THROW );
1135 Reference< XIndexAccess > xForms( xSuppForms->getForms(), UNO_QUERY_THROW );
1136 lcl_resetChildFormsToEmptyDataSource( xForms );
1138 catch( const Exception& )
1140 DBG_UNHANDLED_EXCEPTION("dbaccess");
1146 void ODocumentDefinition::onCommandInsert( const OUString& _sURL, const Reference< XCommandEnvironment >& Environment )
1148 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1150 // Check, if all required properties were set.
1151 if ( _sURL.isEmpty() || m_xEmbeddedObject.is() )
1153 OSL_FAIL( "Content::onCommandInsert - property value missing!" );
1155 Sequence<OUString> aProps { PROPERTY_URL };
1156 ucbhelper::cancelCommandExecution(
1157 makeAny( MissingPropertiesException(
1158 OUString(),
1159 static_cast< cppu::OWeakObject * >( this ),
1160 aProps ) ),
1161 Environment );
1162 // Unreachable
1165 if ( !m_xEmbeddedObject.is() )
1167 Reference< XStorage> xStorage = getContainerStorage();
1168 if ( xStorage.is() )
1170 Reference< XEmbeddedObjectCreator> xEmbedFactory = EmbeddedObjectCreator::create(m_aContext);
1171 Sequence<PropertyValue> aEmpty,aMediaDesc(1);
1172 aMediaDesc[0].Name = PROPERTY_URL;
1173 aMediaDesc[0].Value <<= _sURL;
1174 m_xEmbeddedObject.set(xEmbedFactory->createInstanceInitFromMediaDescriptor( xStorage
1175 ,m_pImpl->m_aProps.sPersistentName
1176 ,aMediaDesc
1177 ,aEmpty),UNO_QUERY);
1179 lcl_resetFormsToEmptyDataSource( m_xEmbeddedObject );
1180 // #i57669#
1182 Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
1183 if ( xPersist.is() )
1185 xPersist->storeOwn();
1189 if ( m_xEmbeddedObject.is() )
1190 m_xEmbeddedObject->close(true);
1192 catch(const Exception&)
1195 m_xEmbeddedObject = nullptr;
1199 aGuard.clear();
1202 bool ODocumentDefinition::save(bool _bApprove, const css::uno::Reference<css::awt::XTopWindow>& rDialogParent)
1204 // default handling: instantiate an interaction handler and let it handle the parameter request
1205 if ( !m_bOpenInDesign )
1206 return false;
1211 ::SolarMutexGuard aSolarGuard;
1213 // the request
1214 Reference<XNameAccess> xName(m_xParentContainer,UNO_QUERY);
1215 DocumentSaveRequest aRequest;
1216 aRequest.Name = m_pImpl->m_aProps.aTitle;
1217 if ( aRequest.Name.isEmpty() )
1219 if ( m_bForm )
1220 aRequest.Name = DBA_RES( RID_STR_FORM );
1221 else
1222 aRequest.Name = DBA_RES( RID_STR_REPORT );
1223 aRequest.Name = ::dbtools::createUniqueName(xName,aRequest.Name);
1226 aRequest.Content.set(m_xParentContainer,UNO_QUERY);
1227 OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
1228 Reference< XInteractionRequest > xRequest(pRequest);
1229 // some knittings
1230 // two continuations allowed: OK and Cancel
1231 ODocumentSaveContinuation* pDocuSave = nullptr;
1233 if ( m_pImpl->m_aProps.aTitle.isEmpty() )
1235 pDocuSave = new ODocumentSaveContinuation;
1236 pRequest->addContinuation(pDocuSave);
1238 if ( _bApprove )
1240 OInteraction< XInteractionApprove >* pApprove = new OInteraction< XInteractionApprove >;
1241 pRequest->addContinuation(pApprove);
1244 OInteraction< XInteractionDisapprove >* pDisApprove = new OInteraction< XInteractionDisapprove >;
1245 pRequest->addContinuation(pDisApprove);
1247 OInteractionAbort* pAbort = new OInteractionAbort;
1248 pRequest->addContinuation(pAbort);
1250 Reference<XWindow> xDialogParent(rDialogParent, UNO_QUERY);
1252 // create the handler, let it handle the request
1253 Reference<XInteractionHandler2> xHandler(InteractionHandler::createWithParent(m_aContext, xDialogParent));
1254 xHandler->handle(xRequest);
1256 if ( pAbort->wasSelected() )
1257 return false;
1258 if ( pDisApprove->wasSelected() )
1259 return true;
1260 if ( pDocuSave && pDocuSave->wasSelected() )
1262 Reference<XNameContainer> xNC( pDocuSave->getContent(), UNO_QUERY_THROW );
1264 ::osl::ResettableMutexGuard aGuard( m_aMutex );
1265 NameChangeNotifier aNameChangeAndNotify( *this, pDocuSave->getName(), aGuard );
1266 m_pImpl->m_aProps.aTitle = pDocuSave->getName();
1268 Reference< XContent> xContent = this;
1269 xNC->insertByName(pDocuSave->getName(),makeAny(xContent));
1271 updateDocumentTitle();
1275 ::osl::MutexGuard aGuard(m_aMutex);
1276 Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
1277 if ( xPersist.is() )
1279 xPersist->storeOwn();
1280 notifyDataSourceModified();
1283 catch(const Exception&)
1285 OSL_FAIL("ODocumentDefinition::save: caught an Exception (tried to let the InteractionHandler handle it)!");
1287 return true;
1290 void ODocumentDefinition::saveAs()
1292 // default handling: instantiate an interaction handler and let it handle the parameter request
1293 if ( !m_bOpenInDesign )
1294 return;
1297 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1298 if ( m_pImpl->m_aProps.aTitle.isEmpty() )
1300 aGuard.clear();
1301 save(false, css::uno::Reference<css::awt::XTopWindow>()); // (sal_False) : we don't want an approve dialog
1302 return;
1307 ::SolarMutexGuard aSolarGuard;
1309 // the request
1310 DocumentSaveRequest aRequest;
1311 aRequest.Name = m_pImpl->m_aProps.aTitle;
1313 aRequest.Content.set(m_xParentContainer,UNO_QUERY);
1314 OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
1315 Reference< XInteractionRequest > xRequest(pRequest);
1316 // some knittings
1317 // two continuations allowed: OK and Cancel
1318 ODocumentSaveContinuation* pDocuSave = new ODocumentSaveContinuation;
1319 pRequest->addContinuation(pDocuSave);
1320 OInteraction< XInteractionDisapprove >* pDisApprove = new OInteraction< XInteractionDisapprove >;
1321 pRequest->addContinuation(pDisApprove);
1322 OInteractionAbort* pAbort = new OInteractionAbort;
1323 pRequest->addContinuation(pAbort);
1325 // create the handler, let it handle the request
1326 Reference< XInteractionHandler2 > xHandler( InteractionHandler::createWithParent(m_aContext, nullptr) );
1327 xHandler->handle(xRequest);
1329 if ( pAbort->wasSelected() )
1330 return;
1331 if ( pDisApprove->wasSelected() )
1332 return;
1333 if ( pDocuSave->wasSelected() )
1335 ::osl::MutexGuard aGuard(m_aMutex);
1336 Reference<XNameContainer> xNC(pDocuSave->getContent(),UNO_QUERY);
1337 if ( xNC.is() )
1339 if ( m_pImpl->m_aProps.aTitle != pDocuSave->getName() )
1343 Reference< XStorage> xStorage = getContainerStorage();
1345 OUString sPersistentName = ::dbtools::createUniqueName(xStorage,"Obj");
1346 xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xStorage,sPersistentName);
1348 OUString sOldName = m_pImpl->m_aProps.aTitle;
1349 rename(pDocuSave->getName());
1350 updateDocumentTitle();
1352 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
1354 {PROPERTY_NAME, uno::Any(sOldName)}, // set as folder
1355 {PROPERTY_PERSISTENT_NAME, uno::Any(sPersistentName)},
1356 {PROPERTY_AS_TEMPLATE, uno::Any(m_pImpl->m_aProps.bAsTemplate)},
1357 }));
1358 Reference< XMultiServiceFactory > xORB( m_xParentContainer, UNO_QUERY_THROW );
1359 Reference< XInterface > xComponent( xORB->createInstanceWithArguments( SERVICE_SDB_DOCUMENTDEFINITION, aArguments ) );
1360 Reference< XNameContainer > xNameContainer( m_xParentContainer, UNO_QUERY_THROW );
1361 xNameContainer->insertByName( sOldName, makeAny( xComponent ) );
1363 catch(const Exception&)
1365 DBG_UNHANDLED_EXCEPTION("dbaccess");
1368 Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
1369 if ( xPersist.is() )
1371 xPersist->storeOwn();
1372 notifyDataSourceModified();
1377 catch(const Exception&)
1379 OSL_FAIL("ODocumentDefinition::save: caught an Exception (tried to let the InteractionHandler handle it)!");
1383 namespace
1385 void lcl_putLoadArgs( ::comphelper::NamedValueCollection& _io_rArgs, const optional_bool& _bSuppressMacros, const optional_bool& _bReadOnly )
1387 if ( !!_bSuppressMacros )
1389 if ( *_bSuppressMacros )
1391 // if we're to suppress macros, do exactly this
1392 _io_rArgs.put( "MacroExecutionMode", MacroExecMode::NEVER_EXECUTE );
1394 else
1396 // otherwise, put the setting only if not already present
1397 if ( !_io_rArgs.has( "MacroExecutionMode" ) )
1399 _io_rArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
1404 if ( !!_bReadOnly )
1405 _io_rArgs.put( "ReadOnly", *_bReadOnly );
1409 namespace
1411 Reference< XFrame > lcl_getDatabaseDocumentFrame( ODatabaseModelImpl const & _rImpl )
1413 Reference< XModel > xDatabaseDocumentModel( _rImpl.getModel_noCreate() );
1415 Reference< XController > xDatabaseDocumentController;
1416 if ( xDatabaseDocumentModel.is() )
1417 xDatabaseDocumentController = xDatabaseDocumentModel->getCurrentController();
1419 Reference< XFrame > xFrame;
1420 if ( xDatabaseDocumentController.is() )
1421 xFrame = xDatabaseDocumentController->getFrame();
1423 return xFrame;
1427 bool ODocumentDefinition::objectSupportsEmbeddedScripts() const
1429 bool bAllowDocumentMacros = !m_pImpl->m_pDataSource
1430 || ( m_pImpl->m_pDataSource->determineEmbeddedMacros() == ODatabaseModelImpl::eSubDocumentMacros );
1432 // if *any* of the objects of the database document already has macros, we
1433 // continue to allow it to have them, until the user does a migration.
1434 // If there are no macros, we don't allow them to be created.
1436 return bAllowDocumentMacros;
1439 OUString ODocumentDefinition::determineContentType() const
1441 return lcl_determineContentType_nothrow( getContainerStorage(), m_pImpl->m_aProps.sPersistentName );
1444 void ODocumentDefinition::separateOpenCommandArguments( const Sequence< PropertyValue >& i_rOpenCommandArguments,
1445 ::comphelper::NamedValueCollection& o_rDocumentLoadArgs, ::comphelper::NamedValueCollection& o_rEmbeddedObjectDescriptor )
1447 ::comphelper::NamedValueCollection aOpenCommandArguments( i_rOpenCommandArguments );
1449 const char* const pObjectDescriptorArgs[] =
1451 "RecoveryStorage"
1453 for (const char* pObjectDescriptorArg : pObjectDescriptorArgs)
1455 if ( aOpenCommandArguments.has( pObjectDescriptorArg ) )
1457 o_rEmbeddedObjectDescriptor.put( pObjectDescriptorArg, aOpenCommandArguments.get( pObjectDescriptorArg ) );
1458 aOpenCommandArguments.remove( pObjectDescriptorArg );
1462 o_rDocumentLoadArgs.merge( aOpenCommandArguments, false );
1465 Sequence< PropertyValue > ODocumentDefinition::fillLoadArgs( const Reference< XConnection>& _xConnection, const bool _bSuppressMacros, const bool _bReadOnly,
1466 const Sequence< PropertyValue >& i_rOpenCommandArguments, Sequence< PropertyValue >& _out_rEmbeddedObjectDescriptor )
1468 // (re-)create interceptor, and put it into the descriptor of the embedded object
1469 if ( m_pInterceptor.is() )
1471 m_pInterceptor->dispose();
1472 m_pInterceptor.clear();
1475 m_pInterceptor = new OInterceptor( this );
1476 Reference<XDispatchProviderInterceptor> xInterceptor = m_pInterceptor.get();
1478 ::comphelper::NamedValueCollection aEmbeddedDescriptor;
1479 aEmbeddedDescriptor.put( "OutplaceDispatchInterceptor", xInterceptor );
1481 ::comphelper::NamedValueCollection aMediaDesc;
1482 separateOpenCommandArguments( i_rOpenCommandArguments, aMediaDesc, aEmbeddedDescriptor );
1484 // create the OutplaceFrameProperties, and put them into the descriptor of the embedded object
1485 ::comphelper::NamedValueCollection OutplaceFrameProperties;
1486 OutplaceFrameProperties.put( "TopWindow", true );
1487 OutplaceFrameProperties.put( "SupportPersistentWindowState", true );
1489 Reference< XFrame > xParentFrame;
1490 if ( m_pImpl->m_pDataSource )
1491 xParentFrame = lcl_getDatabaseDocumentFrame( *m_pImpl->m_pDataSource );
1492 if ( !xParentFrame.is() )
1493 { // i87957 we need a parent frame
1494 Reference< XDesktop2 > xDesktop = Desktop::create( m_aContext );
1495 xParentFrame.set( xDesktop, UNO_QUERY_THROW );
1496 Reference<util::XCloseable> xCloseable(m_pImpl->m_pDataSource->getModel_noCreate(),UNO_QUERY);
1497 if ( xCloseable.is() )
1499 xCloseable->addCloseListener(this);
1500 m_bRemoveListener = true;
1503 OSL_ENSURE( xParentFrame.is(), "ODocumentDefinition::fillLoadArgs: no parent frame!" );
1504 if ( xParentFrame.is() )
1505 OutplaceFrameProperties.put( "ParentFrame", xParentFrame );
1507 aEmbeddedDescriptor.put( "OutplaceFrameProperties", OutplaceFrameProperties.getNamedValues() );
1509 // tell the embedded object to have (or not have) script support
1510 aEmbeddedDescriptor.put( "EmbeddedScriptSupport", objectSupportsEmbeddedScripts() );
1512 // tell the embedded object to not participate in the document recovery game - the DB doc will handle it
1513 aEmbeddedDescriptor.put( "DocumentRecoverySupport", false );
1515 // pass the descriptor of the embedded object to the caller
1516 aEmbeddedDescriptor >>= _out_rEmbeddedObjectDescriptor;
1518 // create the ComponentData, and put it into the document's media descriptor
1520 ::comphelper::NamedValueCollection aComponentData;
1521 aComponentData.put( "ActiveConnection", _xConnection );
1522 aComponentData.put( "ApplyFormDesignMode", !_bReadOnly );
1523 aMediaDesc.put( "ComponentData", aComponentData.getPropertyValues() );
1526 if ( !m_pImpl->m_aProps.aTitle.isEmpty() )
1527 aMediaDesc.put( "DocumentTitle", m_pImpl->m_aProps.aTitle );
1529 aMediaDesc.put( "DocumentBaseURL", m_pImpl->m_pDataSource->getURL() );
1531 // put the common load arguments into the document's media descriptor
1532 lcl_putLoadArgs( aMediaDesc, optional_bool( _bSuppressMacros ), optional_bool( _bReadOnly ) );
1534 return aMediaDesc.getPropertyValues();
1537 void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& i_rConnection, const Sequence< sal_Int8 >& _aClassID,
1538 const Sequence< PropertyValue >& i_rOpenCommandArguments, const bool _bSuppressMacros, const bool _bReadOnly )
1540 if ( !m_xEmbeddedObject.is() )
1542 Reference< XStorage> xStorage = getContainerStorage();
1543 if ( xStorage.is() )
1545 Reference< XEmbeddedObjectCreator> xEmbedFactory = OOoEmbeddedObjectFactory::create(m_aContext);
1546 OUString sDocumentService;
1547 bool bSetSize = false;
1548 sal_Int32 nEntryConnectionMode = EntryInitModes::DEFAULT_INIT;
1549 Sequence< sal_Int8 > aClassID = _aClassID;
1550 if ( aClassID.hasElements() )
1552 nEntryConnectionMode = EntryInitModes::TRUNCATE_INIT;
1553 bSetSize = true;
1555 else
1557 sDocumentService = GetDocumentServiceFromMediaType( getContentType(), m_aContext, aClassID );
1558 // check if we are not a form and
1559 // the org.libreoffice.report.pentaho.SOReportJobFactory is not present.
1560 if ( !m_bForm && sDocumentService != "com.sun.star.text.TextDocument")
1562 // we seem to be a "new style" report, check if report extension is present.
1563 Reference< XContentEnumerationAccess > xEnumAccess( m_aContext->getServiceManager(), UNO_QUERY );
1564 const OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_aContext);
1565 Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(sReportEngineServiceName);
1566 if ( !xEnumDrivers.is() || !xEnumDrivers->hasMoreElements() )
1568 css::io::WrongFormatException aWFE;
1569 aWFE.Message = DBA_RES( RID_STR_MISSING_EXTENSION );
1570 throw aWFE;
1573 if ( !aClassID.hasElements() )
1575 if ( m_bForm )
1576 aClassID = MimeConfigurationHelper::GetSequenceClassID(SO3_SW_CLASSID);
1577 else
1579 aClassID = MimeConfigurationHelper::GetSequenceClassID(SO3_RPT_CLASSID_90);
1584 OSL_ENSURE( aClassID.hasElements(),"No Class ID" );
1586 Sequence< PropertyValue > aEmbeddedObjectDescriptor;
1587 Sequence< PropertyValue > aLoadArgs( fillLoadArgs(
1588 i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) );
1590 m_xEmbeddedObject.set(xEmbedFactory->createInstanceUserInit(aClassID
1591 ,sDocumentService
1592 ,xStorage
1593 ,m_pImpl->m_aProps.sPersistentName
1594 ,nEntryConnectionMode
1595 ,aLoadArgs
1596 ,aEmbeddedObjectDescriptor
1597 ),UNO_QUERY);
1598 if ( m_xEmbeddedObject.is() )
1600 if ( !m_pClientHelper.is() )
1602 m_pClientHelper = new OEmbeddedClientHelper;
1604 Reference<XEmbeddedClient> xClient = m_pClientHelper.get();
1605 m_xEmbeddedObject->setClientSite(xClient);
1606 m_xEmbeddedObject->changeState(EmbedStates::RUNNING);
1607 if ( bSetSize )
1609 LockModifiable aLockModify( impl_getComponent_throw( false ) );
1611 awt::Size aSize( DEFAULT_WIDTH, DEFAULT_HEIGHT );
1612 m_xEmbeddedObject->setVisualAreaSize(Aspects::MSOLE_CONTENT,aSize);
1617 else
1619 sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState();
1620 if ( nCurrentState == EmbedStates::LOADED )
1622 if ( !m_pClientHelper.is() )
1624 m_pClientHelper = new OEmbeddedClientHelper;
1626 Reference<XEmbeddedClient> xClient = m_pClientHelper.get();
1627 m_xEmbeddedObject->setClientSite(xClient);
1629 Sequence< PropertyValue > aEmbeddedObjectDescriptor;
1630 Sequence< PropertyValue > aLoadArgs( fillLoadArgs(
1631 i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) );
1633 Reference<XCommonEmbedPersist> xCommon(m_xEmbeddedObject,UNO_QUERY);
1634 OSL_ENSURE(xCommon.is(),"unsupported interface!");
1635 if ( xCommon.is() )
1636 xCommon->reload( aLoadArgs, aEmbeddedObjectDescriptor );
1637 m_xEmbeddedObject->changeState(EmbedStates::RUNNING);
1639 else
1641 OSL_ENSURE( ( nCurrentState == EmbedStates::RUNNING ) || ( nCurrentState == EmbedStates::ACTIVE ),
1642 "ODocumentDefinition::loadEmbeddedObject: unexpected state!" );
1644 // if the document was already loaded (which means the embedded object is in state RUNNING or ACTIVE),
1645 // then just re-set some model parameters
1648 // ensure the media descriptor doesn't contain any values which are intended for the
1649 // EmbeddedObjectDescriptor only
1650 ::comphelper::NamedValueCollection aEmbeddedObjectDescriptor;
1651 ::comphelper::NamedValueCollection aNewMediaDesc;
1652 separateOpenCommandArguments( i_rOpenCommandArguments, aNewMediaDesc, aEmbeddedObjectDescriptor );
1654 // merge the new media descriptor into the existing media descriptor
1655 const Reference< XModel > xModel( getComponent(), UNO_QUERY_THROW );
1656 const Sequence< PropertyValue > aArgs = xModel->getArgs();
1657 ::comphelper::NamedValueCollection aExistentMediaDesc( aArgs );
1658 aExistentMediaDesc.merge( aNewMediaDesc, false );
1660 lcl_putLoadArgs( aExistentMediaDesc, optional_bool(), optional_bool() );
1661 // don't put _bSuppressMacros and _bReadOnly here - if the document was already
1662 // loaded, we should not tamper with its settings.
1663 // #i88977# #i86872#
1665 xModel->attachResource( xModel->getURL(), aExistentMediaDesc.getPropertyValues() );
1667 catch( const Exception& )
1669 DBG_UNHANDLED_EXCEPTION("dbaccess");
1674 // set the OfficeDatabaseDocument instance as parent of the embedded document
1675 // #i40358#
1676 Reference< XChild > xDepdendDocAsChild( getComponent(), UNO_QUERY );
1677 if ( xDepdendDocAsChild.is() )
1681 if ( !xDepdendDocAsChild->getParent().is() )
1682 { // first encounter
1683 xDepdendDocAsChild->setParent( getDataSource( m_xParentContainer ) );
1686 catch( const Exception& )
1688 DBG_UNHANDLED_EXCEPTION("dbaccess");
1692 if ( i_rConnection.is() )
1693 m_xLastKnownConnection = i_rConnection;
1696 void ODocumentDefinition::onCommandPreview(Any& _rImage)
1698 loadEmbeddedObjectForPreview();
1699 if ( !m_xEmbeddedObject.is() )
1700 return;
1704 Reference<XTransferable> xTransfer(getComponent(),UNO_QUERY);
1705 if ( xTransfer.is() )
1707 DataFlavor aFlavor;
1708 aFlavor.MimeType = "image/png";
1709 aFlavor.HumanPresentableName = "Portable Network Graphics";
1710 aFlavor.DataType = cppu::UnoType<Sequence < sal_Int8 >>::get();
1712 _rImage = xTransfer->getTransferData( aFlavor );
1715 catch( const Exception& )
1720 void ODocumentDefinition::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
1722 _rDefault.clear();
1725 void ODocumentDefinition::onCommandGetDocumentProperties( Any& _rProps )
1727 loadEmbeddedObjectForPreview();
1728 if ( !m_xEmbeddedObject.is() )
1729 return;
1733 Reference<XDocumentPropertiesSupplier> xDocSup(
1734 getComponent(), UNO_QUERY );
1735 if ( xDocSup.is() )
1736 _rProps <<= xDocSup->getDocumentProperties();
1738 catch( const Exception& )
1740 DBG_UNHANDLED_EXCEPTION("dbaccess");
1744 Reference< util::XCloseable > ODocumentDefinition::impl_getComponent_throw( const bool i_ForceCreate )
1746 OSL_ENSURE(m_xEmbeddedObject.is(),"Illegal call for embeddedObject");
1747 Reference< util::XCloseable > xComp;
1748 if ( m_xEmbeddedObject.is() )
1750 int nState = m_xEmbeddedObject->getCurrentState();
1751 if ( ( nState == EmbedStates::LOADED ) && i_ForceCreate )
1753 m_xEmbeddedObject->changeState( EmbedStates::RUNNING );
1754 nState = m_xEmbeddedObject->getCurrentState();
1755 OSL_ENSURE( nState == EmbedStates::RUNNING, "ODocumentDefinition::impl_getComponent_throw: could not switch to RUNNING!" );
1758 if ( nState == EmbedStates::ACTIVE || nState == EmbedStates::RUNNING )
1760 if ( m_xEmbeddedObject.is() )
1762 xComp = m_xEmbeddedObject->getComponent();
1763 OSL_ENSURE(xComp.is(),"No valid component");
1767 return xComp;
1770 Reference< util::XCloseable > ODocumentDefinition::getComponent()
1772 ::osl::MutexGuard aGuard( m_aMutex );
1773 return impl_getComponent_throw();
1776 namespace
1778 Reference< XDatabaseDocumentUI > lcl_getDatabaseDocumentUI( ODatabaseModelImpl const & _rModelImpl )
1780 Reference< XDatabaseDocumentUI > xUI;
1782 Reference< XModel > xModel( _rModelImpl.getModel_noCreate() );
1783 if ( xModel.is() )
1784 xUI.set( xModel->getCurrentController(), UNO_QUERY );
1785 return xUI;
1789 Reference< XComponent > ODocumentDefinition::impl_openUI_nolck_throw( bool _bForEditing )
1791 ::osl::ClearableMutexGuard aGuard( m_aMutex );
1792 if ( !m_pImpl || !m_pImpl->m_pDataSource )
1793 throw DisposedException();
1795 Reference< XComponent > xComponent;
1798 Reference< XDatabaseDocumentUI > xUI( lcl_getDatabaseDocumentUI( *m_pImpl->m_pDataSource ) );
1799 if ( !xUI.is() )
1801 // no XDatabaseDocumentUI -> just execute the respective command
1802 m_bOpenInDesign = _bForEditing;
1803 xComponent = Reference<XComponent>(onCommandOpenSomething(Any(), true, nullptr), UNO_QUERY);
1804 OSL_ENSURE( xComponent.is(), "ODocumentDefinition::impl_openUI_nolck_throw: opening the thingie failed." );
1805 return xComponent;
1809 OUString sName( impl_getHierarchicalName( false ) );
1810 sal_Int32 nObjectType = m_bForm ? DatabaseObject::FORM : DatabaseObject::REPORT;
1811 aGuard.clear();
1813 xComponent = xUI->loadComponent(
1814 nObjectType, sName, _bForEditing
1817 catch( const RuntimeException& ) { throw; }
1818 catch( const Exception& )
1820 throw WrappedTargetException(
1821 OUString(), *this, ::cppu::getCaughtException() );
1824 return xComponent;
1827 void ODocumentDefinition::impl_store_throw()
1829 Reference<XEmbedPersist> xPersist( m_xEmbeddedObject, UNO_QUERY );
1830 if ( xPersist.is() )
1832 xPersist->storeOwn();
1833 notifyDataSourceModified();
1837 bool ODocumentDefinition::impl_close_throw()
1839 bool bSuccess = prepareClose();
1840 if ( bSuccess && m_xEmbeddedObject.is() )
1842 m_xEmbeddedObject->changeState( EmbedStates::LOADED );
1843 bSuccess = m_xEmbeddedObject->getCurrentState() == EmbedStates::LOADED;
1845 return bSuccess;
1848 Reference< XComponent > SAL_CALL ODocumentDefinition::open( )
1850 return impl_openUI_nolck_throw( false );
1853 Reference< XComponent > SAL_CALL ODocumentDefinition::openDesign( )
1855 return impl_openUI_nolck_throw( true );
1858 void SAL_CALL ODocumentDefinition::store( )
1860 ::osl::MutexGuard aGuard( m_aMutex );
1863 impl_store_throw();
1865 catch( const RuntimeException& ) { throw; }
1866 catch( const Exception& )
1868 throw WrappedTargetException(
1869 OUString(), *this, ::cppu::getCaughtException() );
1873 sal_Bool SAL_CALL ODocumentDefinition::close( )
1875 ::osl::MutexGuard aGuard( m_aMutex );
1877 bool bSuccess = false;
1880 bSuccess = impl_close_throw();
1882 catch( const RuntimeException& ) { throw; }
1883 catch( const Exception& )
1885 throw WrappedTargetException(
1886 OUString(), *this, ::cppu::getCaughtException() );
1888 return bSuccess;
1891 OUString SAL_CALL ODocumentDefinition::getHierarchicalName()
1893 ::osl::MutexGuard aGuard( m_aMutex );
1894 return impl_getHierarchicalName( false );
1897 OUString SAL_CALL ODocumentDefinition::composeHierarchicalName( const OUString& i_rRelativeName )
1899 OUStringBuffer aBuffer;
1900 aBuffer.append( getHierarchicalName() );
1901 aBuffer.append( '/' );
1902 aBuffer.append( i_rRelativeName );
1903 return aBuffer.makeStringAndClear();
1906 void SAL_CALL ODocumentDefinition::rename( const OUString& _rNewName )
1910 ::osl::ResettableMutexGuard aGuard(m_aMutex);
1911 if ( _rNewName == m_pImpl->m_aProps.aTitle )
1912 return;
1914 // document definitions are organized in a hierarchical way, so reject names
1915 // which contain a /, as this is reserved for hierarchy level separation
1916 if ( _rNewName.indexOf( '/' ) != -1 )
1917 m_aErrorHelper.raiseException( ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES, *this );
1919 NameChangeNotifier aNameChangeAndNotify( *this, _rNewName, aGuard );
1920 m_pImpl->m_aProps.aTitle = _rNewName;
1922 if ( m_xEmbeddedObject.is() && m_xEmbeddedObject->getCurrentState() == EmbedStates::ACTIVE )
1923 updateDocumentTitle();
1925 catch(const PropertyVetoException&)
1927 throw ElementExistException(_rNewName,*this);
1931 Reference< XStorage> ODocumentDefinition::getContainerStorage() const
1933 return m_pImpl->m_pDataSource
1934 ? m_pImpl->m_pDataSource->getStorage( m_bForm ? ODatabaseModelImpl::E_FORM : ODatabaseModelImpl::E_REPORT )
1935 : Reference< XStorage>();
1938 bool ODocumentDefinition::isModified()
1940 osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex);
1941 bool bRet = false;
1942 if ( m_xEmbeddedObject.is() )
1944 Reference<XModifiable> xModel(getComponent(),UNO_QUERY);
1945 bRet = xModel.is() && xModel->isModified();
1947 return bRet;
1950 bool ODocumentDefinition::prepareClose()
1952 if ( !m_xEmbeddedObject.is() )
1953 return true;
1957 // suspend the controller. Embedded objects are not allowed to raise
1958 // own UI at their own discretion, instead, this has always to be triggered
1959 // by the embedding component. Thus, we do the suspend call here.
1960 // #i49370#
1962 Reference< util::XCloseable > xComponent( impl_getComponent_throw( false ) );
1963 if ( !xComponent.is() )
1964 return true;
1966 Reference< XModel > xModel( xComponent, UNO_QUERY );
1967 Reference< XController > xController;
1968 if ( xModel.is() )
1969 xController = xModel->getCurrentController();
1971 OSL_ENSURE( xController.is() || ( m_xEmbeddedObject->getCurrentState() < EmbedStates::ACTIVE ),
1972 "ODocumentDefinition::prepareClose: no controller!" );
1973 if ( !xController.is() )
1974 // document has not yet been activated, i.e. has no UI, yet
1975 return true;
1977 if (!xController->suspend(true))
1978 // controller vetoed the closing
1979 return false;
1981 if ( isModified() )
1983 Reference< XFrame > xFrame( xController->getFrame() );
1984 Reference<XTopWindow> xTopWindow;
1985 if ( xFrame.is() )
1987 xTopWindow = Reference<XTopWindow>(xFrame->getContainerWindow(), UNO_QUERY_THROW);
1988 xTopWindow->toFront();
1990 if (!save(true, xTopWindow))
1992 // revert suspension
1993 xController->suspend(false);
1994 // saving failed or was cancelled
1995 return false;
1999 catch( const Exception& )
2001 DBG_UNHANDLED_EXCEPTION("dbaccess");
2004 return true;
2007 void ODocumentDefinition::fillReportData( const Reference< XComponentContext >& _rContext,
2008 const Reference< util::XCloseable >& _rxComponent,
2009 const Reference< XConnection >& _rxActiveConnection )
2011 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
2013 {"TextDocument", uno::Any(_rxComponent)},
2014 {"ActiveConnection", uno::Any(_rxActiveConnection)}
2015 }));
2018 Reference< XJobExecutor > xExecutable(
2019 _rContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.wizards.report.CallReportWizard", aArgs, _rContext), UNO_QUERY_THROW );
2020 xExecutable->trigger( "fill" );
2022 catch( const Exception& )
2024 DBG_UNHANDLED_EXCEPTION("dbaccess");
2028 void ODocumentDefinition::updateDocumentTitle()
2030 OUString sName = m_pImpl->m_aProps.aTitle;
2031 if ( m_pImpl->m_pDataSource )
2033 if ( sName.isEmpty() )
2035 if ( m_bForm )
2036 sName = DBA_RES( RID_STR_FORM );
2037 else
2038 sName = DBA_RES( RID_STR_REPORT );
2039 Reference< XUntitledNumbers > xUntitledProvider(m_pImpl->m_pDataSource->getModel_noCreate(), UNO_QUERY );
2040 if ( xUntitledProvider.is() )
2041 sName += OUString::number( xUntitledProvider->leaseNumber(getComponent()) );
2044 Reference< XTitle > xDatabaseDocumentModel(m_pImpl->m_pDataSource->getModel_noCreate(),uno::UNO_QUERY);
2045 if ( xDatabaseDocumentModel.is() )
2046 sName = xDatabaseDocumentModel->getTitle() + " : " + sName;
2048 Reference< XTitle> xTitle(getComponent(),UNO_QUERY);
2049 if ( xTitle.is() )
2050 xTitle->setTitle(sName);
2053 void SAL_CALL ODocumentDefinition::queryClosing( const lang::EventObject&, sal_Bool )
2057 if ( !close() )
2058 throw util::CloseVetoException();
2060 catch(const lang::WrappedTargetException&)
2062 throw util::CloseVetoException();
2066 void SAL_CALL ODocumentDefinition::notifyClosing( const lang::EventObject& /*Source*/ )
2070 void SAL_CALL ODocumentDefinition::disposing( const lang::EventObject& /*Source*/ )
2074 void ODocumentDefinition::firePropertyChange( sal_Int32 i_nHandle, const Any& i_rNewValue, const Any& i_rOldValue,
2075 bool i_bVetoable, const NotifierAccess& )
2077 fire( &i_nHandle, &i_rNewValue, &i_rOldValue, 1, i_bVetoable );
2080 // NameChangeNotifier
2081 NameChangeNotifier::NameChangeNotifier( ODocumentDefinition& i_rDocumentDefinition, const OUString& i_rNewName,
2082 ::osl::ResettableMutexGuard& i_rClearForNotify )
2083 :m_rDocumentDefinition( i_rDocumentDefinition )
2084 ,m_aOldValue( makeAny( i_rDocumentDefinition.getCurrentName() ) )
2085 ,m_aNewValue( makeAny( i_rNewName ) )
2086 ,m_rClearForNotify( i_rClearForNotify )
2088 impl_fireEvent_throw( true );
2091 NameChangeNotifier::~NameChangeNotifier()
2093 impl_fireEvent_throw( false );
2096 void NameChangeNotifier::impl_fireEvent_throw( const bool i_bVetoable )
2098 m_rClearForNotify.clear();
2099 m_rDocumentDefinition.firePropertyChange(
2100 PROPERTY_ID_NAME, m_aNewValue, m_aOldValue, i_bVetoable, ODocumentDefinition::NotifierAccess() );
2101 m_rClearForNotify.reset();
2104 } // namespace dbaccess
2106 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */