Commit ab68042a authored by schultezub's avatar schultezub
Browse files

Further work on property widgets:

 + added PropertyWidgetFactory
 + added AbstractPropertyWidget and StringPropertyWidget
 * replaced own observer implementation of AbstractPipeline and AbstractProperty with sigslot
 * changed PropertyCollection (aggregation) to HasPropertyCollection (inheritance)

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@207 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 2d967f2e
...@@ -7,11 +7,13 @@ MESSAGE(STATUS "Configuring TUMVis Application") ...@@ -7,11 +7,13 @@ MESSAGE(STATUS "Configuring TUMVis Application")
FILE(GLOB TUMVIS_APPLICATION_SOURCES FILE(GLOB TUMVIS_APPLICATION_SOURCES
*.cpp *.cpp
gui/*.cpp gui/*.cpp
gui/properties/*.cpp
) )
FILE(GLOB TUMVIS_APPLICATION_HEADERS FILE(GLOB TUMVIS_APPLICATION_HEADERS
*.h *.h
gui/*.h gui/*.h
gui/properties/*.h
) )
#SET(TUMVIS_APPLICATION_SOURCES #SET(TUMVIS_APPLICATION_SOURCES
...@@ -23,7 +25,10 @@ FILE(GLOB TUMVIS_APPLICATION_HEADERS ...@@ -23,7 +25,10 @@ FILE(GLOB TUMVIS_APPLICATION_HEADERS
SET(TUMVIS_APPLICATION_TO_BE_MOCCED SET(TUMVIS_APPLICATION_TO_BE_MOCCED
gui/mainwindow.h gui/mainwindow.h
gui/pipelinetreewidget.h gui/pipelinetreewidget.h
gui/propertycollectionwidget.h gui/properties/abstractpropertywidget.h
gui/properties/propertycollectionwidget.h
gui/properties/propertywidgetfactory.h
gui/properties/stringpropertywidget.h
) )
# #
......
...@@ -40,8 +40,8 @@ namespace TUMVis { ...@@ -40,8 +40,8 @@ namespace TUMVis {
_pipelineWidget, SIGNAL(clicked(const QModelIndex&)), _pipelineWidget, SIGNAL(clicked(const QModelIndex&)),
this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&))); this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&)));
connect( connect(
this, SIGNAL(updatePropCollectionWidget(PropertyCollection*)), this, SIGNAL(updatePropCollectionWidget(HasPropertyCollection*)),
_propCollectionWidget, SLOT(updatePropCollection(PropertyCollection*))); _propCollectionWidget, SLOT(updatePropCollection(HasPropertyCollection*)));
_application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged); _application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
} }
...@@ -55,7 +55,7 @@ namespace TUMVis { ...@@ -55,7 +55,7 @@ namespace TUMVis {
QVariant item = index.data(Qt::UserRole); QVariant item = index.data(Qt::UserRole);
HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>()); HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>());
if (ptr != 0) { if (ptr != 0) {
emit updatePropCollectionWidget(&(ptr->getPropertyCollection())); emit updatePropCollectionWidget(ptr);
} }
else { else {
emit updatePropCollectionWidget(0); emit updatePropCollectionWidget(0);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include "sigslot/sigslot.h" #include "sigslot/sigslot.h"
#include "application/tumvisapplication.h" #include "application/tumvisapplication.h"
#include "application/gui/pipelinetreewidget.h" #include "application/gui/pipelinetreewidget.h"
#include "application/gui/propertycollectionwidget.h" #include "application/gui/properties/propertycollectionwidget.h"
#include <QMainWindow> #include <QMainWindow>
#include <QVBoxLayout> #include <QVBoxLayout>
...@@ -41,7 +41,7 @@ namespace TUMVis { ...@@ -41,7 +41,7 @@ namespace TUMVis {
/// Qt signal for updating the PipelineWidget. /// Qt signal for updating the PipelineWidget.
void updatePipelineWidget(const std::vector<AbstractPipeline*>&); void updatePipelineWidget(const std::vector<AbstractPipeline*>&);
/// Qt signal for updating the PropertyCollectionWidget /// Qt signal for updating the PropertyCollectionWidget
void updatePropCollectionWidget(PropertyCollection*); void updatePropCollectionWidget(HasPropertyCollection*);
private slots: private slots:
/** /**
......
#include "abstractpropertywidget.h"
#include "core/properties/abstractproperty.h"
namespace TUMVis {
AbstractPropertyWidget::AbstractPropertyWidget(AbstractProperty* property, QWidget* parent /*= 0*/)
: QWidget(parent)
, _property(property)
, _ignorePropertyUpdates(false)
, _layout(0)
{
_layout = new QBoxLayout(QBoxLayout::LeftToRight, this);
_property->s_changed.connect(this, &AbstractPropertyWidget::onPropertyChanged);
}
AbstractPropertyWidget::~AbstractPropertyWidget() {
_property->s_changed.disconnect(this);
}
void AbstractPropertyWidget::addWidget(QWidget* widget) {
_layout->addWidget(widget, 1);
}
void AbstractPropertyWidget::onPropertyChanged(const AbstractProperty* property) {
if (!_ignorePropertyUpdates)
updateWidgetFromProperty();
}
}
\ No newline at end of file
#ifndef ABSTRACTPROPERTYWIDGET_H__
#define ABSTRACTPROPERTYWIDGET_H__
#include "sigslot/sigslot.h"
#include <QWidget>
#include <QBoxLayout>
namespace TUMVis {
class AbstractProperty;
/**
* Abstract base class for property widgets.
*/
class AbstractPropertyWidget : public QWidget, public sigslot::has_slots<> {
Q_OBJECT;
public:
/**
* Creates a new PropertyWidget for the property \a property.
* \param property The property the widget shall handle
* \param parent Parent Qt widget
*/
AbstractPropertyWidget(AbstractProperty* property, QWidget* parent = 0);
/**
* Destructor
*/
virtual ~AbstractPropertyWidget();
public slots:
protected:
/**
* Adds a widget to the local Qt layout.
*/
void addWidget(QWidget* widget);
/**
* Gets called when the property has changed, so that widget can update its state.
*/
virtual void updateWidgetFromProperty() = 0;
AbstractProperty* _property; ///< The property this widget handles
bool _ignorePropertyUpdates; ///< Flag whether the widget shall ignore incoming signals from properties being updated.
private:
/// Slot getting called when the property has changed, so that the widget can be updated.
virtual void onPropertyChanged(const AbstractProperty* property);
QBoxLayout* _layout;
};
}
#endif // ABSTRACTPROPERTYWIDGET_H__
#include "propertycollectionwidget.h" #include "propertycollectionwidget.h"
#include "application/gui/properties/abstractpropertywidget.h"
#include "application/gui/properties/propertywidgetfactory.h"
#include "core/properties/abstractproperty.h" #include "core/properties/abstractproperty.h"
#include "core/properties/propertycollection.h" #include "core/properties/propertycollection.h"
...@@ -20,7 +22,7 @@ namespace TUMVis { ...@@ -20,7 +22,7 @@ namespace TUMVis {
qDeleteAll(_widgetList); qDeleteAll(_widgetList);
} }
void PropertyCollectionWidget::updatePropCollection(PropertyCollection* propertyCollection) { void PropertyCollectionWidget::updatePropCollection(HasPropertyCollection* propertyCollection) {
// just some dummy implementation for property widget listing: // just some dummy implementation for property widget listing:
for (QList<QWidget*>::iterator it = _widgetList.begin(); it != _widgetList.end(); ++it) { for (QList<QWidget*>::iterator it = _widgetList.begin(); it != _widgetList.end(); ++it) {
_layout->removeWidget(*it); _layout->removeWidget(*it);
...@@ -30,7 +32,10 @@ namespace TUMVis { ...@@ -30,7 +32,10 @@ namespace TUMVis {
for (std::vector<AbstractProperty*>::const_iterator it = propertyCollection->getProperties().begin(); it != propertyCollection->getProperties().end(); ++it) { for (std::vector<AbstractProperty*>::const_iterator it = propertyCollection->getProperties().begin(); it != propertyCollection->getProperties().end(); ++it) {
QPushButton* propWidget = new QPushButton(QString::fromStdString((*it)->getTitle())); QWidget* propWidget = PropertyWidgetFactory::createWidget(*it);
if (propWidget == 0)
propWidget = new QPushButton(QString::fromStdString((*it)->getTitle()));
_widgetList.push_back(propWidget); _widgetList.push_back(propWidget);
_layout->addWidget(propWidget); _layout->addWidget(propWidget);
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include <QWidget> #include <QWidget>
namespace TUMVis { namespace TUMVis {
class PropertyCollection; class HasPropertyCollection;
/** /**
* Main Window for the TUMVis application. * Main Window for the TUMVis application.
...@@ -30,9 +30,9 @@ namespace TUMVis { ...@@ -30,9 +30,9 @@ namespace TUMVis {
public slots: public slots:
/** /**
* Updates the property collection this widget works on. * Updates the property collection this widget works on.
* \param propertyCollection New PropertyCollection for this widget, may be 0. * \param propertyCollection New HasPropertyCollection instance for this widget, may be 0.
*/ */
void updatePropCollection(PropertyCollection* propertyCollection); void updatePropCollection(HasPropertyCollection* propertyCollection);
private: private:
...@@ -41,7 +41,7 @@ namespace TUMVis { ...@@ -41,7 +41,7 @@ namespace TUMVis {
*/ */
void setupWidget(); void setupWidget();
PropertyCollection* _propCollection; ///< The PropertyCollection this widget is currently working on. HasPropertyCollection* _propCollection; ///< The HasPropertyCollection instance this widget is currently working on.
QVBoxLayout* _layout; QVBoxLayout* _layout;
QList<QWidget*> _widgetList; QList<QWidget*> _widgetList;
}; };
......
#include "propertywidgetfactory.h"
#include "application/gui/properties/abstractpropertywidget.h"
#include "application/gui/properties/stringpropertywidget.h"
#include "core/properties/abstractproperty.h"
#include "core/properties/genericproperty.h"
#include "core/properties/transferfunctionproperty.h"
namespace TUMVis {
AbstractPropertyWidget* PropertyWidgetFactory::createWidget(AbstractProperty* property) {
tgtAssert(property != 0, "Property must not be 0.");
if (StringProperty* tester = dynamic_cast<StringProperty*>(property)) {
return new StringPropertyWidget(tester);
}
return 0;
}
}
\ No newline at end of file
#ifndef PROPERTYWIDGETFACTORY_H__
#define PROPERTYWIDGETFACTORY_H__
namespace TUMVis {
class AbstractPropertyWidget;
class AbstractProperty;
class PropertyWidgetFactory {
public:
/**
*
* \param property
* \return
*/
static AbstractPropertyWidget* createWidget(AbstractProperty* property);
};
}
#endif // PROPERTYWIDGETFACTORY_H__
#include "stringpropertywidget.h"
namespace TUMVis {
StringPropertyWidget::StringPropertyWidget(StringProperty* property, QWidget* parent /*= 0*/)
: AbstractPropertyWidget(property, parent)
, _lineEdit(0)
{
_lineEdit = new QLineEdit(QString::fromStdString(property->getValue()));
addWidget(_lineEdit);
connect(_lineEdit, SIGNAL(textChanged(const QString&)), this, SIGNAL(onTextChanged(const QString&)));
}
StringPropertyWidget::~StringPropertyWidget() {
}
void StringPropertyWidget::updateWidgetFromProperty() {
StringProperty* prop = static_cast<StringProperty*>(_property);
QString qs = QString::fromStdString(prop->getValue());
if (_lineEdit->text() != qs) {
_lineEdit->blockSignals(true);
_lineEdit->setText(qs);
_lineEdit->blockSignals(false);
}
}
void StringPropertyWidget::onTextChanged(const QString& text) {
StringProperty* prop = static_cast<StringProperty*>(_property);
prop->setValue(text.toStdString());
}
}
\ No newline at end of file
#ifndef STRINGPROPERTYWIDGET_H__
#define STRINGPROPERTYWIDGET_H__
#include "application/gui/properties/abstractpropertywidget.h"
#include "core/properties/genericproperty.h"
#include <QLineEdit>
namespace TUMVis {
/**
* Widget for a StringProperty
*/
class StringPropertyWidget : public AbstractPropertyWidget {
Q_OBJECT;
public:
/**
* Creates a new PropertyWidget for the property \a property.
* \param property The property the widget shall handle
* \param parent Parent Qt widget
*/
StringPropertyWidget(StringProperty* property, QWidget* parent = 0);
/**
* Destructor
*/
virtual ~StringPropertyWidget();
protected:
/**
* Gets called when the property has changed, so that widget can update its state.
*/
virtual void updateWidgetFromProperty();
private slots:
void onTextChanged(const QString& text);
private:
QLineEdit* _lineEdit;
};
}
#endif // STRINGPROPERTYWIDGET_H__
...@@ -38,7 +38,12 @@ namespace TUMVis { ...@@ -38,7 +38,12 @@ namespace TUMVis {
} }
} }
void AbstractPipeline::onNotify(const ProcessorObserverArgs& poa) { void AbstractPipeline::onPropertyChanged(const AbstractProperty* prop) {
_invalidationLevel.setLevel(InvalidationLevel::INVALID_RESULT);
s_PipelineInvalidated();
}
void AbstractPipeline::onProcessorInvalidated(const AbstractProcessor* processor) {
_invalidationLevel.setLevel(InvalidationLevel::INVALID_RESULT); _invalidationLevel.setLevel(InvalidationLevel::INVALID_RESULT);
s_PipelineInvalidated(); s_PipelineInvalidated();
} }
......
...@@ -20,7 +20,7 @@ namespace TUMVis { ...@@ -20,7 +20,7 @@ namespace TUMVis {
* Abstract base class for TUMVis Pipelines. * Abstract base class for TUMVis Pipelines.
* *
*/ */
class AbstractPipeline : public HasPropertyCollection, public GenericObserver<ProcessorObserverArgs> { class AbstractPipeline : public HasPropertyCollection {
friend class PipelineEvaluator; friend class PipelineEvaluator;
public: public:
...@@ -72,19 +72,25 @@ namespace TUMVis { ...@@ -72,19 +72,25 @@ namespace TUMVis {
*/ */
virtual const std::string getName() const = 0; virtual const std::string getName() const = 0;
/**
* Gets called when one of the observed processors changed and thus notifies its observers.
* The default behaviour is just to set the invalidation level to invalid.
* \sa GenericObserver::onNotify, AbstractProcessor
* \param poa ProcessorObserverArgs ObserverArgument struct containing the emitting processor and its InvalidationLevel
*/
virtual void onNotify(const ProcessorObserverArgs& poa);
InvalidationLevel& getInvalidationLevel(); InvalidationLevel& getInvalidationLevel();
sigslot::signal0<> s_PipelineInvalidated; sigslot::signal0<> s_PipelineInvalidated;
/**
* Slot getting called when one of the observed properties changed and notifies its observers.
* The default behaviour is just to set the invalidation level to invalid.
* \param prop Property that emitted the signal
*/
virtual void onPropertyChanged(const AbstractProperty* prop);
/**
* Slot getting called when one of the observed processors got invalidated.
* The default behaviour is just to set the invalidation level to invalid.
* \param processor The processor that emitted the signal
*/
virtual void onProcessorInvalidated(const AbstractProcessor* processor);
protected: protected:
/** /**
* Executes the processor \a processor on the pipeline's data and locks its properties meanwhile. * Executes the processor \a processor on the pipeline's data and locks its properties meanwhile.
......
...@@ -23,14 +23,10 @@ namespace TUMVis { ...@@ -23,14 +23,10 @@ namespace TUMVis {
// If processor is no longer valid, notify observers // If processor is no longer valid, notify observers
if (! _invalidationLevel.isValid()) { if (! _invalidationLevel.isValid()) {
notifyObservers(ProcessorObserverArgs(this, _invalidationLevel)); s_invalidated(this);
} }
} }
void AbstractProcessor::onNotify(const PropertyObserverArgs& poa) {
applyInvalidationLevel(poa._invalidationLevel);
}
void AbstractProcessor::init() { void AbstractProcessor::init() {
} }
...@@ -39,12 +35,15 @@ namespace TUMVis { ...@@ -39,12 +35,15 @@ namespace TUMVis {
void AbstractProcessor::lockProperties() { void AbstractProcessor::lockProperties() {
_properties.lockAllProperties(); lockAllProperties();
} }
void AbstractProcessor::unlockProperties() { void AbstractProcessor::unlockProperties() {
_properties.unlockAllProperties(); unlockAllProperties();
} }
void AbstractProcessor::onPropertyChanged(const AbstractProperty* prop) {
applyInvalidationLevel(prop->getInvalidationLevel());
}
} }
#ifndef PROCESSOR_H__ #ifndef PROCESSOR_H__
#define PROCESSOR_H__ #define PROCESSOR_H__
#include "sigslot/sigslot.h"
#include "tgt/logmanager.h" #include "tgt/logmanager.h"
#include "core/tools/invalidationlevel.h" #include "core/tools/invalidationlevel.h"
#include "core/datastructures/datacontainer.h" #include "core/datastructures/datacontainer.h"
...@@ -11,26 +12,6 @@ ...@@ -11,26 +12,6 @@
#include <vector> #include <vector>
namespace TUMVis { namespace TUMVis {
class AbstractProcessor;
/**
* Observer Arguments for Property observers.
*/
struct ProcessorObserverArgs : public GenericObserverArgs<AbstractProcessor> {
/**
* Creates new PropertyObserverArgs.
* \param subject Subject that emits the notification
* \param invalidationLevel Invalidation level of that property
*/
ProcessorObserverArgs(const AbstractProcessor* subject, InvalidationLevel invalidationLevel)
: GenericObserverArgs<AbstractProcessor>(subject)
, _invalidationLevel(invalidationLevel)
{}
InvalidationLevel _invalidationLevel; ///< Invalidation level of that processor
};
/** /**
* Abstract base class for TUMVis Processors. * Abstract base class for TUMVis Processors.
* A processor implements a specific task, which it performs on the DataCollection passed * A processor implements a specific task, which it performs on the DataCollection passed
...@@ -44,7 +25,7 @@ namespace TUMVis { ...@@ -44,7 +25,7 @@ namespace TUMVis {
* *
* \sa AbstractPipeline * \sa AbstractPipeline
*/ */
class AbstractProcessor : public HasPropertyCollection, public GenericObserver<PropertyObserverArgs>, public GenericObservable<ProcessorObserverArgs> { class AbstractProcessor : public HasPropertyCollection {
/** /**
* We have to find a trade-off: * We have to find a trade-off:
...@@ -108,13 +89,6 @@ namespace TUMVis { ...@@ -108,13 +89,6 @@ namespace TUMVis {
*/ */
void applyInvalidationLevel(InvalidationLevel il); void applyInvalidationLevel(InvalidationLevel il);
/**
* Gets called when one of the observed properties changed notifies its observers.
* \sa GenericObserver::onNotify, AbstractProperty
* \param poa PropertyObserverArgs ObserverArgument struct containing the emitting property and its InvalidationLevel
*/
virtual void onNotify(const PropertyObserverArgs& poa);
/** /**
* Locks all properties in the processor's PropertyCollection and marks them as "in use". * Locks all properties in the processor's PropertyCollection and marks them as "in use".
* \sa AbstractProcessor::unlock * \sa AbstractProcessor::unlock
...@@ -128,6 +102,16 @@ namespace TUMVis { ...@@ -128,6 +102,16 @@ namespace TUMVis {
void unlockProperties(); void unlockProperties();
/// Signal emitted when the processor has been invalidated.
sigslot::signal1<const AbstractProcessor*> s_invalidated;
/**
* Slot getting called when one of the observed properties changed and notifies its observers.
* \param prop Property that emitted the signal
*/
virtual void onPropertyChanged(const AbstractProperty* prop);