summaryrefslogtreecommitdiff
path: root/reportdesign/source/core/sdr/UndoEnv.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'reportdesign/source/core/sdr/UndoEnv.cxx')
-rw-r--r--reportdesign/source/core/sdr/UndoEnv.cxx110
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