Commit 682bc879 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum

[ADD] - added information properties - properties that can be used to output...

[ADD] - added information properties - properties that can be used to output values, counts, strings, whatever
parent 2cf67cf8
......@@ -37,6 +37,7 @@ WPropertyBase::WPropertyBase( std::string name, std::string description ):
m_name( name ),
m_description( description ),
m_hidden( false ),
m_purpose( PV_PURPOSE_PARAMETER ),
m_updateCondition( new WConditionSet() )
{
// check name validity
......@@ -67,6 +68,16 @@ PROPERTY_TYPE WPropertyBase::getType() const
return m_type;
}
PROPERTY_PURPOSE WPropertyBase::getPurpose() const
{
return m_purpose;
}
void WPropertyBase::setPurpose( PROPERTY_PURPOSE purpose )
{
m_purpose = purpose;
}
void WPropertyBase::updateType()
{
m_type = PV_UNKNOWN;
......
......@@ -92,6 +92,27 @@ public:
*/
virtual PROPERTY_TYPE getType() const;
/**
* Gets the purpose of a property. See PROPERTY_PURPOSE for more details. For short: it helps the GUI and others to understand what a module
* (or whomever created this property) intents with this property. Typically this value is PV_PURPOSE_PARAMETER, meaning that it is used to
* tune the behaviour of a module.
*
* \note always assume this to be a hint. It does not actually prevent someone from writing or interpreting a parameter property as an
* information property.
*
* \see PROPERTY_PURPOSE
* \return the purpose.
*/
virtual PROPERTY_PURPOSE getPurpose() const;
/**
* Sets the purpose of the property. See \ref getPurpose for more details. You generally should avoid setting this value after
* initialization.
*
* \param purpose the purpose to set.
*/
virtual void setPurpose( PROPERTY_PURPOSE purpose );
/**
* This methods allows properties to be set by a string value. This is especially useful when a property is only available as string and the
* real type of the property is unknown. This is a shortcut for casting the property and then setting the lexically casted value.
......@@ -235,6 +256,11 @@ protected:
*/
PROPERTY_TYPE m_type;
/**
* The purpose of this property. PropertyBase always initializes it with PV_PURPOSE_PARAMETER.
*/
PROPERTY_PURPOSE m_purpose;
/**
* Calculates the type of the property. This has to be done by the implementing class.
*/
......
......@@ -53,20 +53,33 @@ class WProperties;
*/
typedef enum
{
PV_UNKNOWN, // type not know
PV_GROUP, // the group property
PV_INT, // integer value
PV_DOUBLE, // floating point value
PV_BOOL, // boolean
PV_STRING, // a string
PV_PATH, // a Boost Path object denoting a filename/path
PV_SELECTION, // a list of strings, selectable
PV_POSITION, // a position property
PV_COLOR, // a color property
PV_TRIGGER // for triggering an event
PV_UNKNOWN, //!< type not known
PV_GROUP, //!< the group property
PV_INT, //!< integer value
PV_DOUBLE, //!< floating point value
PV_BOOL, //!< boolean
PV_STRING, //!< a string
PV_PATH, //!< a Boost Path object denoting a filename/path
PV_SELECTION, //!< a list of strings, selectable
PV_POSITION, //!< a position property
PV_COLOR, //!< a color property
PV_TRIGGER //!< for triggering an event
}
PROPERTY_TYPE;
/**
* Enum of all possible purpose of a property. The purpose describes which meaning a property has for the creator of it. A PP_PARAMETER is a
* property which is meant to be modified to adopt the behaviour of the module (or whomever has created it). A PP_INFORMATION is only an output
* from the creator who wants to inform the outside world about values, states or whatever.
*/
typedef enum
{
PV_PURPOSE_INFORMATION, //!< information property not meant to be modified from someone (except the creating object)
PV_PURPOSE_PARAMETER //!< a parameter meant to be modified by others to manipulate the behaviour of the module (or whomever created
//!< the property)
}
PROPERTY_PURPOSE;
/**
* Namespace containing all base types of the WPropertyVariables. Use these types instead of issuing int32_t, double, bool, ...
* directly. It also contains some user defined types including the needed operators.
......
......@@ -358,6 +358,7 @@ void WQtDatasetBrowser::selectTreeItem()
boost::shared_ptr< WModule > module;
boost::shared_ptr< WProperties > props;
boost::shared_ptr< WProperties > infoProps;
if ( m_treeWidget->selectedItems().size() != 0 )
{
......@@ -368,6 +369,7 @@ void WQtDatasetBrowser::selectTreeItem()
case DATASET:
module = ( static_cast< WQtDatasetTreeItem* >( m_treeWidget->selectedItems().at( 0 ) ) )->getModule();
props = module->getProperties();
infoProps = module->getInformationProperties();
createCompatibleButtons( module );
break;
case MODULEHEADER:
......@@ -375,6 +377,7 @@ void WQtDatasetBrowser::selectTreeItem()
case MODULE:
module = ( static_cast< WQtModuleTreeItem* >( m_treeWidget->selectedItems().at( 0 ) ) )->getModule();
props = module->getProperties();
infoProps = module->getInformationProperties();
createCompatibleButtons( module );
break;
case ROIHEADER:
......@@ -385,7 +388,8 @@ void WQtDatasetBrowser::selectTreeItem()
break;
}
}
buildPropTab( props );
buildPropTab( props, infoProps );
}
void WQtDatasetBrowser::selectRoiTreeItem()
......@@ -417,12 +421,12 @@ void WQtDatasetBrowser::selectRoiTreeItem()
break;
}
}
buildPropTab( props );
buildPropTab( props, boost::shared_ptr< WProperties >() );
}
WQtDSBWidget* WQtDatasetBrowser::buildPropWidget( boost::shared_ptr< WProperties > props )
{
WQtDSBWidget* tab = new WQtDSBWidget( "Settings" );
WQtDSBWidget* tab = new WQtDSBWidget( QString::fromStdString( props->getName() ) );
if ( props.get() )
{
......@@ -483,10 +487,33 @@ WQtDSBWidget* WQtDatasetBrowser::buildPropWidget( boost::shared_ptr< WPropertie
return tab;
}
void WQtDatasetBrowser::buildPropTab( boost::shared_ptr< WProperties > props )
void WQtDatasetBrowser::buildPropTab( boost::shared_ptr< WProperties > props, boost::shared_ptr< WProperties > infoProps )
{
WQtDSBWidget* tab = buildPropWidget( props );
addTabWidgetContent( tab );
WQtDSBWidget* tab = NULL;
WQtDSBWidget* infoTab = NULL;
if ( props )
{
tab = buildPropWidget( props );
tab->setName( "Settings" );
}
if ( infoProps )
{
infoTab = buildPropWidget( infoProps );
infoTab->setName( "Information" );
}
int infoIdx = addTabWidgetContent( infoTab );
int propIdx = addTabWidgetContent( tab );
// select the property widget preferably
if ( propIdx != -1 )
{
m_tabWidget->setCurrentIndex( propIdx );
}
else if ( infoIdx != -1 )
{
m_tabWidget->setCurrentIndex( infoIdx );
}
}
void WQtDatasetBrowser::createCompatibleButtons( boost::shared_ptr< WModule >module )
......@@ -537,13 +564,18 @@ void WQtDatasetBrowser::changeRoiTreeItem()
}
void WQtDatasetBrowser::addTabWidgetContent( WQtDSBWidget* content )
int WQtDatasetBrowser::addTabWidgetContent( WQtDSBWidget* content )
{
if ( !content )
{
return -1;
}
QScrollArea* sa = new QScrollArea();
sa->setWidget( content );
sa->setWidgetResizable( true );
m_tabWidget->addTab( sa, "Settings" );
return m_tabWidget->addTab( sa, content->getName() );
}
void WQtDatasetBrowser::moveTreeItemDown()
......
......@@ -73,8 +73,10 @@ public:
* adds a page to the context widget
*
* \param content A widget with controls
*
* \return the index of the new tab
*/
void addTabWidgetContent( WQtDSBWidget* content );
int addTabWidgetContent( WQtDSBWidget* content );
/**
* adds a subject entry to the tree widget
......@@ -213,8 +215,9 @@ private slots:
* function that builds the property tab
*
* \param props the properties.
* \param infoProps the information properties shown on a separate tab
*/
void buildPropTab( boost::shared_ptr< WProperties > props );
void buildPropTab( boost::shared_ptr< WProperties > props, boost::shared_ptr< WProperties > infoProps );
/**
* Method builds a widgets containing all properties in props. It recursively calls itself to build group widgets for WPropGroup properties.
......
......@@ -65,6 +65,8 @@ WModule::WModule():
{
// initialize members
m_properties = boost::shared_ptr< WProperties >( new WProperties( "Properties", "Module's properties" ) );
m_infoProperties = boost::shared_ptr< WProperties >( new WProperties( "Informational Properties", "Module's information properties" ) );
m_active = m_properties->addProperty( "active", "Determines whether the module should be activated.", true, true );
m_active->getCondition()->subscribeSignal( boost::bind( &WModule::activate, this ) );
......@@ -325,6 +327,11 @@ boost::shared_ptr< WProperties > WModule::getProperties() const
return m_properties;
}
boost::shared_ptr< WProperties > WModule::getInformationProperties() const
{
return m_infoProperties;
}
boost::shared_ptr< WProgressCombiner > WModule::getRootProgressCombiner()
{
return m_progress;
......
......@@ -123,6 +123,13 @@ public:
*/
boost::shared_ptr< WProperties > getProperties() const;
/**
* Return a pointer to the information properties object of the module. The module intends these properties to not be modified.
*
* \return the properties.
*/
boost::shared_ptr< WProperties > getInformationProperties() const;
/**
* Determines whether the module instance is properly initialized.
*
......@@ -391,6 +398,13 @@ protected:
*/
boost::shared_ptr< WProperties > m_properties;
/**
* The property object for the module containing only module whose purpose is "PV_PURPOSE_INFORMNATION". It is useful to define some property
* to only be of informational nature. The GUI does not modify them. As it is a WProperties instance, you can use it the same way as
* m_properties.
*/
boost::shared_ptr< WProperties > m_infoProperties;
/**
* Progress indicator used as parent for all progress' of this module.
*/
......
......@@ -220,7 +220,7 @@ void WMTemplate::properties()
m_aDouble->setMax( 50.0 );
// The most amazing feature is: custom constraints. Similar to OSG update callbacks, you just need to write your own PropertyConstraint class
// to define the allowed values for your constraint. Take a look at the StringLength class on how to do it.
// to define the allowed values for your constraint. Take a look at the StringLength class in this module's code on how to do it.
m_aString->addConstraint( boost::shared_ptr< StringLength >( new StringLength ) );
// One last thing to mention is the active property. This property is available in all modules and represents the activation state of the
......@@ -232,6 +232,9 @@ void WMTemplate::properties()
// 3: react during your module main loop using the moduleState: m_moduleState.add( m_active->getCondition );
// Additionally, your can also use the m_active variable directly in your update callbacks to en-/disable some OSG nodes.
// This template module uses method number 1. This might be the easiest and most commonly used way.
// TODO(ebaum): write
m_aIntegerOutput = m_infoProperties->addProperty( "Run Count", "Number of run cycles the module made so far.", 0 );
}
void WMTemplate::moduleMain()
......@@ -277,6 +280,12 @@ void WMTemplate::moduleMain()
debugLog() << "Waiting ...";
m_moduleState.wait();
// As you might remember, this property is a information property to provide the number of run cycles to the outside world. It wont't be
// modified but the module can modify it. This is useful to provide statistics, counts, times or even a "hello world" string to the user
// as an information or status report. Please do not abuse these information properties as progress indicators. A short overview on how
// to make progress indicators is provided some lines below. Here, we simply increase the value.
m_aIntegerOutput->set( m_aIntegerOutput->get() +1 );
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// After waking up, the module has to check whether the shutdownFlag fired. If yes, simply quit the module.
......
......@@ -186,6 +186,11 @@ private:
*/
WPropTrigger m_aTrigger;
/**
* A property simply providing a integer value to the outside world.
*/
WPropInt m_aIntegerOutput;
/**
* Node callback to change the color of the shapes inside the root node. For more details on this class, refer to the documentation in
* moduleMain().
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment