Commit ccbdc8c8 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum

[CHANGE] - all WPropertyBase derived classes can now be deep copied

parent 1665cfc7
......@@ -56,6 +56,14 @@ public:
*/
WFlag( boost::shared_ptr< WCondition > condition, T initial );
/**
* Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get
* created. The subscriptions to a signal are LOST as well as all listeners to a condition.
*
* \param from the instance to copy.
*/
WFlag( const WFlag& from );
/**
* Destructor. It deletes the instance of WCondition specified on construction.
*/
......@@ -189,6 +197,15 @@ WFlag< T >::WFlag( boost::shared_ptr< WCondition > condition, T initial ):
{
}
template < typename T >
WFlag< T >::WFlag( const WFlag& from ):
m_condition( boost::shared_ptr< WCondition >( new WCondition() ) ),
m_valueChangeCondition( boost::shared_ptr< WCondition >( new WCondition() ) ),
m_flag( from.m_flag ),
m_changed( from.m_changed )
{
}
template < typename T >
WFlag< T >::~WFlag()
{
......
......@@ -49,6 +49,28 @@ WProperties::~WProperties()
{
}
WProperties::WProperties( const WProperties& from ):
WPropertyBase( from ),
m_properties(),
m_propAccess( m_properties.getAccessObject() )
{
// copy the properties inside
from.m_propAccess->beginRead();
// we need to make a deep copy here.
for ( PropertyIterator iter = from.m_propAccess->get().begin(); iter != from.m_propAccess->get().end(); ++iter )
{
// clone them to keep dynamic type
m_propAccess->get().push_back( ( *iter )->clone() );
}
from.m_propAccess->endRead();
}
boost::shared_ptr< WPropertyBase > WProperties::clone()
{
// class copy constructor.
return boost::shared_ptr< WProperties >( new WProperties( *this ) );
}
PROPERTY_TYPE WProperties::getType() const
{
return PV_GROUP;
......
......@@ -34,7 +34,7 @@
#include <boost/thread/locks.hpp>
#include <boost/thread.hpp>
#include "WSharedObject.h"
#include "WSharedSequenceContainer.h"
#include "WPropertyBase.h"
#include "WPropertyTypes.h"
#include "WPropertyVariable.h"
......@@ -60,7 +60,7 @@ public:
/**
* The alias for a shared container.
*/
typedef WSharedObject< PropertyContainerType > PropertySharedContainerType;
typedef WSharedSequenceContainer< boost::shared_ptr< WPropertyBase >, PropertyContainerType > PropertySharedContainerType;
/**
* The access type
......@@ -87,11 +87,32 @@ public:
*/
WProperties( std::string name = "unnamed group", std::string description = "an unnamed group of properties" );
/**
* Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get
* created. The subscriptions to a signal are LOST as well as all listeners to a condition.
*
* \note the properties inside this list are also copied deep
*
* \param from the instance to copy.
*/
WProperties( const WProperties& from );
/**
* destructor
*/
virtual ~WProperties();
/**
* This method clones a property and returns the clone. It does a deep copy and, in contrast to a copy constructor, creates property with the
* correct type without explicitly requiring the user to specify it. It creates a NEW change condition and change signal. This means, alls
* subscribed signal handlers are NOT copied.
*
* \note this simply ensures the copy constructor of the runtime type is issued.
*
* \return the deep clone of this property.
*/
virtual boost::shared_ptr< WPropertyBase > clone();
/**
* Simply insert the specified property to the list.
*
......
......@@ -34,10 +34,12 @@
#include "WPropertyVariable.h"
WPropertyBase::WPropertyBase( std::string name, std::string description ):
boost::enable_shared_from_this< WPropertyBase >(),
m_name( name ),
m_description( description ),
m_hidden( false ),
m_purpose( PV_PURPOSE_PARAMETER ),
signal_PropertyChange(),
m_updateCondition( new WConditionSet() )
{
// check name validity
......@@ -48,6 +50,18 @@ WPropertyBase::WPropertyBase( std::string name, std::string description ):
}
}
WPropertyBase::WPropertyBase( const WPropertyBase& from ):
boost::enable_shared_from_this< WPropertyBase >(),
m_name( from.m_name ),
m_description( from.m_description ),
m_hidden( from.m_hidden ),
m_type( from.m_type ),
m_purpose( from.m_purpose ),
signal_PropertyChange(), // create a new and empty signal
m_updateCondition( new WConditionSet() ) // create a new condition set. Do not copy it.
{
}
WPropertyBase::~WPropertyBase()
{
// cleanup
......
......@@ -52,11 +52,30 @@ public:
*/
WPropertyBase( std::string name, std::string description );
/**
* Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get
* created. The subscriptions to a signal are LOST as well as all listeners to a condition.
*
* \param from the instance to copy.
*/
WPropertyBase( const WPropertyBase& from );
/**
* Destructor.
*/
virtual ~WPropertyBase();
/**
* This method clones a property and returns the clone. It does a deep copy and, in contrast to a copy constructor, creates property with the
* correct type without explicitly requiring the user to specify it. It creates a NEW change condition and change signal. This means, alls
* subscribed signal handlers are NOT copied.
*
* \note this simply ensures the copy constructor of the runtime type is issued.
*
* \return the deep clone of this property.
*/
virtual boost::shared_ptr< WPropertyBase > clone() = 0;
/**
* Gets the name of the class.
*
......
......@@ -115,11 +115,30 @@ public:
WPropertyVariable( std::string name, std::string description, const T& initial, boost::shared_ptr< WCondition > condition,
PropertyChangeNotifierType notifier );
/**
* Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get
* created. The subscriptions to a signal are LOST as well as all listeners to a condition.
*
* \param from the instance to copy.
*/
WPropertyVariable( const WPropertyVariable< T >& from );
/**
* Destructor.
*/
virtual ~WPropertyVariable();
/**
* This method clones a property and returns the clone. It does a deep copy and, in contrast to a copy constructor, creates property with the
* correct type without explicitly requiring the user to specify it. It creates a NEW change condition and change signal. This means, alls
* subscribed signal handlers are NOT copied.
*
* \note this simply ensures the copy constructor of the runtime type is issued.
*
* \return the deep clone of this property.
*/
virtual boost::shared_ptr< WPropertyBase > clone();
/**
* Determines whether the specified value is acceptable.
*
......@@ -185,6 +204,13 @@ public:
* \return NULL if the type is unknown or an constraint instance
*/
static boost::shared_ptr< PropertyConstraint > create( PROPERTYCONSTRAINT_TYPE type );
/**
* Method to clone the constraint and create a new one with the correct dynamic type.
*
* \return the constraint.
*/
virtual boost::shared_ptr< PropertyConstraint > clone() = 0;
};
/**
......@@ -440,7 +466,7 @@ WPropertyVariable< T >::WPropertyVariable( std::string name, std::string descrip
m_updateCondition->add( WFlag< T >::getValueChangeCondition() );
// set custom notifier
WFlag< T >::getCondition()->subscribeSignal( boost::bind( &WPropertyVariable< T >::propertyChangeNotifier, this ) );
m_notifierConnection = WFlag< T >::getCondition()->subscribeSignal( boost::bind( &WPropertyVariable< T >::propertyChangeNotifier, this ) );
signal_PropertyChange.connect( notifier );
}
......@@ -460,10 +486,29 @@ WPropertyVariable< T >::WPropertyVariable( std::string name, std::string descrip
m_updateCondition->add( WFlag< T >::getValueChangeCondition() );
// set custom notifier
WFlag< T >::getCondition()->subscribeSignal( boost::bind( &WPropertyVariable< T >::propertyChangeNotifier, this ) );
m_notifierConnection = WFlag< T >::getCondition()->subscribeSignal( boost::bind( &WPropertyVariable< T >::propertyChangeNotifier, this ) );
signal_PropertyChange.connect( notifier );
}
template < typename T >
WPropertyVariable< T >::WPropertyVariable( const WPropertyVariable< T >& from ):
WFlag< T >( from ),
WPropertyBase( from ),
m_constraintsChanged( new WCondition() ),
m_constraints(),
m_constraintsAccess( m_constraints.getAccessObject() )
{
// copy the constraints
from.m_constraintsAccess->beginRead();
// we need to make a deep copy here.
for ( ConstraintContainerIteratorType iter = from.m_constraintsAccess->get().begin(); iter != from.m_constraintsAccess->get().end(); ++iter )
{
// clone them to keep dynamic type
m_constraintsAccess->get().insert( ( *iter )->clone() );
}
from.m_constraintsAccess->endRead();
}
template < typename T >
WPropertyVariable< T >::~WPropertyVariable()
{
......@@ -477,6 +522,12 @@ WPropertyVariable< T >::~WPropertyVariable()
m_constraintsAccess->endWrite();
}
template < typename T >
boost::shared_ptr< WPropertyBase > WPropertyVariable< T >::clone()
{
return boost::shared_ptr< WPropertyBase >( new WPropertyVariable< T >( *this ) );
}
template < typename T >
void WPropertyVariable< T >::propertyChangeNotifier()
{
......
......@@ -41,7 +41,7 @@ public:
/**
* Constructor.
*/
explicit WPropertyConstraintIsDirectory();
WPropertyConstraintIsDirectory();
/**
* Destructor.
......@@ -65,6 +65,13 @@ public:
*/
virtual PROPERTYCONSTRAINT_TYPE getType();
/**
* Method to clone the constraint and create a new one with the correct dynamic type.
*
* \return the constraint.
*/
virtual boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > clone();
private:
};
......@@ -90,5 +97,12 @@ PROPERTYCONSTRAINT_TYPE WPropertyConstraintIsDirectory< T >::getType()
return PC_ISDIRECTORY;
}
template < typename T >
boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > WPropertyConstraintIsDirectory< T >::clone()
{
return boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint >( new WPropertyConstraintIsDirectory< T >( *this ) );
}
#endif // WPROPERTYCONSTRAINTISDIRECTORY_H
......@@ -76,6 +76,13 @@ public:
*/
virtual PROPERTYCONSTRAINT_TYPE getType();
/**
* Method to clone the constraint and create a new one with the correct dynamic type.
*
* \return the constraint.
*/
virtual boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > clone();
private:
/**
......@@ -113,4 +120,10 @@ PROPERTYCONSTRAINT_TYPE WPropertyConstraintMax< T >::getType()
return PC_MAX;
}
template < typename T >
boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > WPropertyConstraintMax< T >::clone()
{
return boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint >( new WPropertyConstraintMax< T >( *this ) );
}
#endif // WPROPERTYCONSTRAINTMAX_H
......@@ -74,6 +74,13 @@ public:
*/
virtual PROPERTYCONSTRAINT_TYPE getType();
/**
* Method to clone the constraint and create a new one with the correct dynamic type.
*
* \return the constraint.
*/
virtual boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > clone();
private:
/**
......@@ -111,5 +118,11 @@ PROPERTYCONSTRAINT_TYPE WPropertyConstraintMin< T >::getType()
return PC_MIN;
}
template < typename T >
boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > WPropertyConstraintMin< T >::clone()
{
return boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint >( new WPropertyConstraintMin< T >( *this ) );
}
#endif // WPROPERTYCONSTRAINTMIN_H
......@@ -66,6 +66,13 @@ public:
*/
virtual PROPERTYCONSTRAINT_TYPE getType();
/**
* Method to clone the constraint and create a new one with the correct dynamic type.
*
* \return the constraint.
*/
virtual boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > clone();
private:
};
......@@ -91,5 +98,11 @@ PROPERTYCONSTRAINT_TYPE WPropertyConstraintNotEmpty< T >::getType()
return PC_NOTEMPTY;
}
template < typename T >
boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > WPropertyConstraintNotEmpty< T >::clone()
{
return boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint >( new WPropertyConstraintNotEmpty< T >( *this ) );
}
#endif // WPROPERTYCONSTRAINTNOTEMPTY_H
......@@ -65,6 +65,13 @@ public:
*/
virtual PROPERTYCONSTRAINT_TYPE getType();
/**
* Method to clone the constraint and create a new one with the correct dynamic type.
*
* \return the constraint.
*/
virtual boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > clone();
private:
};
......@@ -90,5 +97,11 @@ PROPERTYCONSTRAINT_TYPE WPropertyConstraintPathExists< T >::getType()
return PC_PATHEXISTS;
}
template < typename T >
boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > WPropertyConstraintPathExists< T >::clone()
{
return boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint >( new WPropertyConstraintPathExists< T >( *this ) );
}
#endif // WPROPERTYCONSTRAINTPATHEXISTS_H
......@@ -65,6 +65,13 @@ public:
*/
virtual PROPERTYCONSTRAINT_TYPE getType();
/**
* Method to clone the constraint and create a new one with the correct dynamic type.
*
* \return the constraint.
*/
virtual boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > clone();
private:
};
......@@ -90,5 +97,11 @@ PROPERTYCONSTRAINT_TYPE WPropertyConstraintSelectOnlyOne< T >::getType()
return PC_SELECTONLYONE;
}
template < typename T >
boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint > WPropertyConstraintSelectOnlyOne< T >::clone()
{
return boost::shared_ptr< typename WPropertyVariable< T >::PropertyConstraint >( new WPropertyConstraintSelectOnlyOne< T >( *this ) );
}
#endif // WPROPERTYCONSTRAINTSELECTONLYONE_H
......@@ -310,147 +310,9 @@ void WQtConfigWidget::registerComponents()
m_defaultProperties->addProperty( "modules.MC.isoValue", "Marching Cubes isoValue", 100.0, m_propCondition );
}
void WQtConfigWidget::copyProperties( boost::shared_ptr< WProperties > from, boost::shared_ptr< WProperties > to )
boost::shared_ptr< WProperties > WQtConfigWidget::copyProperties( boost::shared_ptr< WProperties > from )
{
// NOTE: property variables are initialized with the change flag = true. This is simply the case because nobody handled the new property
// after initialization. The purpose of the change flag is to detect whether someone has taken care about it. This is why the get( true )
// call is issued here (reset the change flag).
//
// lock both
WProperties::PropertyAccessType toAccess = to->getAccessObject();
WProperties::PropertyAccessType fromAccess = from->getAccessObject();
toAccess->beginWrite();
fromAccess->beginRead();
// clear target
toAccess->get().clear();
WProperties::PropertyConstIterator iter;
for ( iter = fromAccess->get().begin(); iter != fromAccess->get().end(); ++iter )
{
/* // so far we only need those 5 types
switch( ( *iter )->getType() )
{
case PV_GROUP:
{
// recurse all groups
WPropGroup group = to->addPropertyGroup( ( *iter )->getName(), ( *iter )->getDescription() );
copyProperties( ( *iter )->toPropGroup(), group );
break;
}
case PV_INT:
{
WPropInt propInt = to->addProperty( ( *iter )->getName(), ( *iter )->getDescription(), ( *iter )->toPropInt()->get(),
m_propCondition, ( *iter )->isHidden() );
propInt->get( true );
WPVInt::constraintContainer constraints = ( *iter )->toPropInt()->getConstraints();
WPVInt::constraintIterator iter2;
for ( iter2 = constraints.begin(); iter2 != constraints.end(); ++iter2 )
{
switch ( (*iter2)->getType() )
{
case PC_MIN:
{
propInt->setMin( ( *iter )->toPropInt()->getMin()->getMin() );
break;
}
case PC_MAX:
{
propInt->setMax( ( *iter )->toPropInt()->getMax()->getMax() );
break;
}
default:
{
propInt->addConstraint( *iter2 );
break;
}
}
}
break;
}
case PV_DOUBLE:
{
WPropDouble propDouble = to->addProperty( ( *iter )->getName(), ( *iter )->getDescription(), ( *iter )->toPropDouble()->get(),
m_propCondition, ( *iter )->isHidden() );
propDouble->get( true );
WPVDouble::constraintContainer constraints = ( *iter )->toPropDouble()->getConstraints();
WPVDouble::constraintIterator iter2;
for ( iter2 = constraints.begin(); iter2 != constraints.end(); ++iter2 )
{
// again we need a nasty hack because setting a constraint which is min and max will result in a multi set of min and maxes
// which will result in odd behavior
switch ( ( *iter2 )->getType() )
{
case PC_MIN:
{
propDouble->setMin( ( *iter )->toPropDouble()->getMin()->getMin() );
break;
}
case PC_MAX:
{
propDouble->setMax( ( *iter )->toPropDouble()->getMax()->getMax() );
break;
}
default:
{
propDouble->addConstraint( *iter2 );
break;
}
}
}
break;
}
case PV_BOOL:
{
WPropBool propBool = to->addProperty( ( *iter )->getName(), ( *iter )->getDescription(), ( *iter )->toPropBool()->get(),
m_propCondition, ( *iter )->isHidden() );
propBool->get( true );
WPVBool::constraintContainer constraints = ( *iter )->toPropBool()->getConstraints();
WPVBool::constraintIterator iter2;
for ( iter2 = constraints.begin(); iter2 != constraints.end(); ++iter2 )
{
propBool->addConstraint( *iter2 );
}
break;
}
case PV_STRING:
{
WPropString propString = to->addProperty( ( *iter )->getName(), ( *iter )->getDescription(), ( *iter )->toPropString()->get(),
m_propCondition, ( *iter )->isHidden() );
propString->get( true );
WPVString::constraintContainer constraints = ( *iter )->toPropString()->getConstraints();
WPVString::constraintIterator iter2;
for ( iter2 = constraints.begin(); iter2 != constraints.end(); ++iter2 )
{
propString->addConstraint( *iter2 );
}
break;
}
case PV_COLOR:
{
WPropColor propColor = to->addProperty( ( *iter )->getName(), ( *iter )->getDescription(), ( *iter )->toPropColor()->get(),
m_propCondition, ( *iter )->isHidden() );
propColor->get( true );
WPVColor::constraintContainer constraints = ( *iter )->toPropColor()->getConstraints();
WPVColor::constraintIterator iter2;
for ( iter2 = constraints.begin(); iter2 != constraints.end(); ++iter2 )
{
propColor->addConstraint( *iter2 );
}
break;
}
default:
{
// just do nothing so no compiler warning
break;
}
}*/
}
fromAccess->beginRead();
toAccess->endWrite();
return boost::shared_static_cast< WProperties >( from->clone() );
}
void WQtConfigWidget::copyPropertiesContents( boost::shared_ptr< WProperties > from, boost::shared_ptr< WProperties > to )
......@@ -1034,13 +896,13 @@ void WQtConfigWidget::loadConfigFile()
{
m_configLines = WCfgOperations::readCfg( "walnut.cfg" );
// copy all default properties into the loaded properties
copyProperties( m_defaultProperties, m_loadedProperties );
m_loadedProperties = copyProperties( m_defaultProperties );
// parse the config file
createLineAssociation();
// update the loaded properties
updateGui( m_loadedProperties );
// copy all loaded properties into the current propertys where we create the gui from
copyProperties( m_loadedProperties, m_properties );
m_properties = copyProperties( m_loadedProperties );
m_configState.setResetable( true, true );
m_configState.add( m_propCondition );
......
......@@ -98,7 +98,7 @@ private:
/**
* determine if to WPropertieVariable have the same value
* \note also subgroups ar searched and if the property name doesn't exist in either of both groups
* \note also subgroups ar searched and if the property name doesn't exist in either of both groups
* and their subgroups the function returns false
*
* \param prop1 first property group
......@@ -120,7 +120,7 @@ private:
* so the other representations show the same content
*
* \param properties the list on which the change should occur
* \param groupName the name of the group ( this should be added manually inside the function for every group added, so tutorial
* \param groupName the name of the group ( this should be added manually inside the function for every group added, so tutorial
* inside of registerComponents() )
* \param fromConfig do we update from the m_loadedProperties or from the m_properties
*/
......@@ -152,9 +152,9 @@ private:
* see implementation for details
*
* \param from source property group
* \param to target property group
* \return cloned property group
*/
void copyProperties( boost::shared_ptr< WProperties > from, boost::shared_ptr< WProperties > to );
boost::shared_ptr< WProperties > copyProperties( boost::shared_ptr< WProperties > from );
/**
* recursive copy of the values of property groups
......@@ -184,12 +184,12 @@ private:
void createGuiFromProperties( boost::shared_ptr< WProperties > from );
/**
* applies changes to the main program from changed properties
* applies changes to the main program from changed properties
*
* \note if you want to add the effect of a property to the main program implement it in here
* see tutorial and example for details
*
* \result have any properties been set different from the loaded properties and therefore have changes been made to the
* \result have any properties been set different from the loaded properties and therefore have changes been made to the
* main program
*/
bool setWalnutFromProperties();
......
......@@ -615,6 +615,13 @@ bool WMTemplate::StringLength::accept( boost::shared_ptr< WPropertyVariable< WPV