diff options
Diffstat (limited to 'reportdesign/source/core/sdr/UndoEnv.cxx')
-rw-r--r-- | reportdesign/source/core/sdr/UndoEnv.cxx | 110 |
1 files changed, 93 insertions, 17 deletions
diff --git a/reportdesign/source/core/sdr/UndoEnv.cxx b/reportdesign/source/core/sdr/UndoEnv.cxx index 911279ed6f71..f4dd0a7f8645 100644 --- a/reportdesign/source/core/sdr/UndoEnv.cxx +++ b/reportdesign/source/core/sdr/UndoEnv.cxx @@ -44,12 +44,15 @@ #include <com/sun/star/container/XNameContainer.hpp> #include <com/sun/star/beans/PropertyAttribute.hpp> #include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <com/sun/star/beans/XIntrospectionAccess.hpp> +#include <com/sun/star/beans/XIntrospection.hpp> /** === end UNO includes === **/ #include <connectivity/dbtools.hxx> #include <svl/smplhint.hxx> #include <tools/diagnose_ex.h> #include <comphelper/stl_types.hxx> +#include <comphelper/componentcontext.hxx> #include <vcl/svapp.hxx> #include <dbaccess/singledoccontroller.hxx> #include <svx/unoshape.hxx> @@ -69,8 +72,36 @@ namespace rptui //---------------------------------------------------------------------------- -DECLARE_STL_USTRINGACCESS_MAP(bool, AllProperties); -DECLARE_STL_STDKEY_MAP(uno::Reference< beans::XPropertySet >, AllProperties, PropertySetInfoCache); +struct PropertyInfo +{ + bool bIsReadonlyOrTransient; + + PropertyInfo() + :bIsReadonlyOrTransient( false ) + { + } + + PropertyInfo( const bool i_bIsTransientOrReadOnly ) + :bIsReadonlyOrTransient( i_bIsTransientOrReadOnly ) + { + } +}; + +typedef ::std::hash_map< ::rtl::OUString, PropertyInfo, ::rtl::OUStringHash > PropertiesInfo; + +struct ObjectInfo +{ + PropertiesInfo aProperties; + Reference< XPropertySet > xPropertyIntrospection; + + ObjectInfo() + :aProperties() + ,xPropertyIntrospection() + { + } +}; + +typedef ::std::map< Reference< XPropertySet >, ObjectInfo, ::comphelper::OInterfaceCompare< XPropertySet > > PropertySetInfoCache; // ----------------------------------------------------------------------------- @@ -85,6 +116,7 @@ public: ConditionUpdater m_aConditionUpdater; ::osl::Mutex m_aMutex; ::std::vector< uno::Reference< container::XChild> > m_aSections; + Reference< XIntrospection > m_xIntrospection; oslInterlockedCount m_nLocks; sal_Bool m_bReadOnly; sal_Bool m_bIsUndo; @@ -154,7 +186,7 @@ void OXUndoEnvironment::Clear(const Accessor& /*_r*/) { uno::Reference<beans::XPropertySet> xProp(aIter->first,uno::UNO_QUERY); xProp->getPropertySetInfo(); - int nlen = aIter->second.size(); + int nlen = aIter->second.aProperties.size(); nlen = nlen; } #endif @@ -240,29 +272,73 @@ void SAL_CALL OXUndoEnvironment::propertyChange( const PropertyChangeEvent& _rEv int nlen = m_pImpl->m_aPropertySetCache.size(); nlen = nlen; #endif - PropertySetInfoCache::iterator aSetPos = m_pImpl->m_aPropertySetCache.find(xSet); - if (aSetPos == m_pImpl->m_aPropertySetCache.end()) + PropertySetInfoCache::iterator objectPos = m_pImpl->m_aPropertySetCache.find(xSet); + if (objectPos == m_pImpl->m_aPropertySetCache.end()) { - AllProperties aNewEntry; - aSetPos = m_pImpl->m_aPropertySetCache.insert(PropertySetInfoCache::value_type(xSet,aNewEntry)).first; - DBG_ASSERT(aSetPos != m_pImpl->m_aPropertySetCache.end(), "OXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?"); + objectPos = m_pImpl->m_aPropertySetCache.insert( PropertySetInfoCache::value_type( + xSet, ObjectInfo() + ) ).first; + DBG_ASSERT(objectPos != m_pImpl->m_aPropertySetCache.end(), "OXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?"); } - if ( aSetPos == m_pImpl->m_aPropertySetCache.end() ) + if ( objectPos == m_pImpl->m_aPropertySetCache.end() ) return; // now we have access to the cached info about the set // let's see what we know about the property - AllProperties& rPropInfos = aSetPos->second; - AllPropertiesIterator aPropertyPos = rPropInfos.find( _rEvent.PropertyName ); - if (aPropertyPos == rPropInfos.end()) + ObjectInfo& rObjectInfo = objectPos->second; + PropertiesInfo::iterator aPropertyPos = rObjectInfo.aProperties.find( _rEvent.PropertyName ); + if ( aPropertyPos == rObjectInfo.aProperties.end() ) { // nothing 'til now ... have to change this .... // the attributes - INT32 nAttributes = xSet->getPropertySetInfo()->getPropertyByName( _rEvent.PropertyName ).Attributes; - bool bTransReadOnly = ((nAttributes & PropertyAttribute::READONLY) != 0) || ((nAttributes & PropertyAttribute::TRANSIENT) != 0); + Reference< XPropertySetInfo > xPSI( xSet->getPropertySetInfo(), UNO_SET_THROW ); + INT32 nPropertyAttributes = 0; + try + { + if ( xPSI->hasPropertyByName( _rEvent.PropertyName ) ) + { + nPropertyAttributes = xPSI->getPropertyByName( _rEvent.PropertyName ).Attributes; + } + else + { + // it's perfectly valid for a component to notify a change in a property which it doesn't have - as long + // as it has an attribute with this name + if ( !rObjectInfo.xPropertyIntrospection.is() ) + { + if ( !m_pImpl->m_xIntrospection.is() ) + { + ::comphelper::ComponentContext aContext( m_pImpl->m_rModel.getController()->getORB() ); + OSL_VERIFY( aContext.createComponent( "com.sun.star.beans.Introspection", m_pImpl->m_xIntrospection ) ); + } + if ( m_pImpl->m_xIntrospection.is() ) + { + Reference< XIntrospectionAccess > xIntrospection( + m_pImpl->m_xIntrospection->inspect( makeAny( _rEvent.Source ) ), + UNO_SET_THROW + ); + rObjectInfo.xPropertyIntrospection.set( xIntrospection->queryAdapter( XPropertySet::static_type() ), UNO_QUERY_THROW ); + } + } + if ( rObjectInfo.xPropertyIntrospection.is() ) + { + xPSI.set( rObjectInfo.xPropertyIntrospection->getPropertySetInfo(), UNO_SET_THROW ); + nPropertyAttributes = xPSI->getPropertyByName( _rEvent.PropertyName ).Attributes; + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + const bool bTransReadOnly = + ( ( nPropertyAttributes & PropertyAttribute::READONLY ) != 0 ) + || ( ( nPropertyAttributes & PropertyAttribute::TRANSIENT ) != 0 ); // insert the new entry - aPropertyPos = rPropInfos.insert( AllProperties::value_type( _rEvent.PropertyName, bTransReadOnly ) ).first; - DBG_ASSERT(aPropertyPos != rPropInfos.end(), "OXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?"); + aPropertyPos = rObjectInfo.aProperties.insert( PropertiesInfo::value_type( + _rEvent.PropertyName, + PropertyInfo( bTransReadOnly ) + ) ).first; + DBG_ASSERT(aPropertyPos != rObjectInfo.aProperties.end(), "OXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?"); } implSetModified(); @@ -271,7 +347,7 @@ void SAL_CALL OXUndoEnvironment::propertyChange( const PropertyChangeEvent& _rEv // and are able to decide wether or not we need an undo action // no UNDO for transient/readonly properties - if ( aPropertyPos->second ) + if ( aPropertyPos->second.bIsReadonlyOrTransient ) return; // give components with sub responsibilities a chance |