The expiration time for new job artifacts in CI/CD pipelines is now 30 days (GitLab default). Previously generated artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

Commit 213ae14c authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

CampvisApplication manages multiple DataContainers, updated PipelineTreeWidget...

CampvisApplication manages multiple DataContainers, updated PipelineTreeWidget to show correct DataContainer/Pipeline/Processor hierarchy
parent 37623c0c
......@@ -47,6 +47,7 @@
#include "application/gui/mainwindow.h"
#include "core/tools/opengljobprocessor.h"
#include "core/tools/simplejobprocessor.h"
#include "core/tools/stringutils.h"
#include "core/tools/quadrenderer.h"
#include "core/pipeline/abstractpipeline.h"
#include "modules/pipelinefactory.h"
......@@ -84,6 +85,9 @@ namespace campvis {
for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
delete *it;
}
for (std::vector<DataContainer*>::iterator it = _dataContainers.begin(); it != _dataContainers.end(); ++it) {
delete *it;
}
}
void CampVisApplication::init() {
......@@ -92,7 +96,8 @@ namespace campvis {
// parse argument list and create pipelines
QStringList pipelinesToAdd = this->arguments();
for (int i = 1; i < pipelinesToAdd.size(); ++i) {
AbstractPipeline* p = PipelineFactory::getRef().createPipeline(pipelinesToAdd[i].toStdString(), &_dataContainer);
DataContainer* dc = createAndAddDataContainer("DataContainer #" + StringUtils::toString(_dataContainers.size() + 1));
AbstractPipeline* p = PipelineFactory::getRef().createPipeline(pipelinesToAdd[i].toStdString(), dc);
if (p != 0)
addPipeline(pipelinesToAdd[i].toStdString(), p);
}
......@@ -270,12 +275,12 @@ namespace campvis {
_mainWindow->addDockWidget(area, dock);
}
DataContainer* CampVisApplication::getDataContainer() {
return &_dataContainer;
DataContainer* CampVisApplication::createAndAddDataContainer(const std::string& name) {
DataContainer* dc = new DataContainer(name);
_dataContainers.push_back(dc);
s_DataContainersChanged();
return dc;
}
const DataContainer* CampVisApplication::getDataContainer() const {
return &_dataContainer;
}
}
......@@ -116,29 +116,23 @@ namespace campvis {
int run();
/**
* Gets the DataContainer of this CampvisApplication
* \return _dataContainer
*/
DataContainer* getDataContainer();
/**
* Gets the DataContainer of this CampvisApplication
* \return _dataContainer
*/
const DataContainer* getDataContainer() const;
DataContainer* createAndAddDataContainer(const std::string& name);
/// Signal emitted when the collection of pipelines has changed.
sigslot::signal0<> s_PipelinesChanged;
/// Signal emitted when the collection of DataContainers has changed.
sigslot::signal0<> s_DataContainersChanged;
private:
/// The (currently) one and only DataContainer in CampvisApplication
DataContainer _dataContainer;
/// All pipelines
std::vector<AbstractPipeline*> _pipelines;
/// All visualisations (i.e. Pipelines with their corresponding painters/canvases)
std::vector< std::pair<AbstractPipeline*, CampVisPainter*> > _visualizations;
/// All DataContainers
std::vector<DataContainer*> _dataContainers;
/// A local OpenGL context used for initialization
tgt::QtThreadedCanvas* _localContext;
/// Main window hosting GUI stuff
......
......@@ -35,6 +35,7 @@
#include "application/gui/datacontainerinspectorcanvas.h"
#include "application/gui/qtdatahandle.h"
#include "application/gui/visualizationpipelinewrapper.h"
#include "core/datastructures/datacontainer.h"
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/abstractprocessor.h"
......@@ -64,6 +65,7 @@ namespace campvis {
MainWindow::~MainWindow() {
_application->s_PipelinesChanged.disconnect(this);
_application->s_DataContainersChanged.disconnect(this);
delete _dcInspectorWidget;
}
......@@ -115,8 +117,8 @@ namespace campvis {
_dcInspectorWidget = new DataContainerInspectorWidget();
connect(
this, SIGNAL(updatePipelineWidget(const std::vector<AbstractPipeline*>&)),
_pipelineWidget, SLOT(update(const std::vector<AbstractPipeline*>&)));
this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)),
_pipelineWidget, SLOT(update(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)));
connect(
_pipelineWidget, SIGNAL(clicked(const QModelIndex&)),
this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&)));
......@@ -130,6 +132,7 @@ namespace campvis {
_btnShowDataContainerInspector, SIGNAL(clicked()),
this, SLOT(onBtnShowDataContainerInspectorClicked()));
_application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
_application->s_DataContainersChanged.connect(this, &MainWindow::onDataContainersChanged);
}
bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
......@@ -142,30 +145,39 @@ namespace campvis {
}
void MainWindow::onPipelinesChanged() {
emit updatePipelineWidget(_application->_pipelines);
emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
}
void MainWindow::onDataContainersChanged() {
emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
}
void MainWindow::onPipelineWidgetItemClicked(const QModelIndex& index) {
if (index.isValid()) {
// Yak, this is so ugly - another reason why GUI programming sucks...
QVariant item = index.data(Qt::UserRole);
HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>());
if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(ptr)) {
_selectedPipeline = pipeline;
_selectedProcessor = 0;
}
else if (AbstractProcessor* processor = dynamic_cast<AbstractProcessor*>(ptr)) {
_selectedProcessor = processor;
if (item.isValid()) {
HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>());
QVariant parentItem = index.parent().data(Qt::UserRole);
HasPropertyCollection* pptr = static_cast<HasPropertyCollection*>(parentItem.value<void*>());
if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(pptr)) {
if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(ptr)) {
_selectedPipeline = pipeline;
_selectedProcessor = 0;
}
else if (AbstractProcessor* processor = dynamic_cast<AbstractProcessor*>(ptr)) {
_selectedProcessor = processor;
QVariant parentItem = index.parent().data(Qt::UserRole);
HasPropertyCollection* pptr = static_cast<HasPropertyCollection*>(parentItem.value<void*>());
if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(pptr)) {
_selectedPipeline = pipeline;
}
}
}
emit updatePropCollectionWidget(ptr, &_selectedPipeline->getDataContainer());
emit updatePropCollectionWidget(ptr, &_selectedPipeline->getDataContainer());
}
else {
emit updatePropCollectionWidget(0, 0);
}
}
else {
emit updatePropCollectionWidget(0, 0);
......
......@@ -80,11 +80,6 @@ namespace campvis {
*/
void deinit();
/**
* Slot to be called by the application when its collection of pipelines has changed.
*/
void onPipelinesChanged();
/**
* Size hint for the default window size
* \return QSize(800, 450)
......@@ -108,7 +103,8 @@ namespace campvis {
signals:
/// Qt signal for updating the PipelineWidget.
void updatePipelineWidget(const std::vector<AbstractPipeline*>&);
void updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&);
/// Qt signal for updating the PropertyCollectionWidget
void updatePropCollectionWidget(HasPropertyCollection*, DataContainer*);
......@@ -130,6 +126,18 @@ namespace campvis {
void onBtnShowDataContainerInspectorClicked();
private:
/**
* Slot to be called by the application when its collection of pipelines has changed.
*/
void onPipelinesChanged();
/**
* Slot to be called by the application when its collection of DataContainers has changed.
*/
void onDataContainersChanged();
/**
* Setup Qt GUI stuff
*/
......
......@@ -45,6 +45,38 @@ namespace campvis {
// = TreeModel items ==============================================================================
DataContainerTreeItem::DataContainerTreeItem(DataContainer* dc, TreeItem* parent)
: TreeItem(parent)
, _dataContainer(dc)
{
tgtAssert(_dataContainer != 0, "Pipeline must not be 0.");
}
QVariant DataContainerTreeItem::getData(int column, int role) const {
switch (role) {
case Qt::DisplayRole:
if (column == COLUMN_NAME)
return QVariant(QString::fromStdString(_dataContainer->getName()));
else
return QVariant();
case Qt::CheckStateRole:
return QVariant();
case Qt::UserRole:
return QVariant();
default:
return QVariant();
}
}
DataContainerTreeItem::~DataContainerTreeItem() {
}
bool DataContainerTreeItem::setData(int column, int role, const QVariant& value) const {
return false;
}
// ================================================================================================
PipelineTreeItem::PipelineTreeItem(AbstractPipeline* pipeline, TreeItem* parent)
: TreeItem(parent)
, _pipeline(pipeline)
......@@ -84,6 +116,7 @@ namespace campvis {
return false;
}
// ================================================================================================
ProcessorTreeItem::ProcessorTreeItem(AbstractProcessor* processor, TreeItem* parent)
: TreeItem(parent)
......@@ -258,15 +291,28 @@ namespace campvis {
return 4;
}
void PipelineTreeModel::setData(const std::vector<AbstractPipeline*>& pipelines) {
void PipelineTreeModel::setData(const std::vector<DataContainer*>& dataContainers, const std::vector<AbstractPipeline*>& pipelines) {
delete _rootItem;
_rootItem = new PipelineTreeRootItem();
std::map<DataContainer*, DataContainerTreeItem*> dcItemMap;
for (size_t i = 0; i < dataContainers.size(); ++i) {
DataContainerTreeItem* dcti = new DataContainerTreeItem(dataContainers[i], _rootItem);
dcItemMap[dataContainers[i]] = dcti;
}
for (std::vector<AbstractPipeline*>::const_iterator pipe = pipelines.begin(); pipe != pipelines.end(); ++pipe) {
PipelineTreeItem* pipeti = new PipelineTreeItem(*pipe, _rootItem);
std::map<DataContainer*, DataContainerTreeItem*>::iterator it = dcItemMap.find(&(*pipe)->getDataContainer());
if (it != dcItemMap.end()) {
PipelineTreeItem* pipeti = new PipelineTreeItem(*pipe, it->second);
for (std::vector<AbstractProcessor*>::const_iterator proc = (*pipe)->getProcessors().begin(); proc != (*pipe)->getProcessors().end(); ++proc) {
ProcessorTreeItem* procti = new ProcessorTreeItem(*proc, pipeti);
for (std::vector<AbstractProcessor*>::const_iterator proc = (*pipe)->getProcessors().begin(); proc != (*pipe)->getProcessors().end(); ++proc) {
ProcessorTreeItem* procti = new ProcessorTreeItem(*proc, pipeti);
}
}
else {
tgtAssert(false, "The DataContainer of this pipeline is not in the list of DataContainers, cannot add it to GUI!");
}
}
}
......@@ -292,23 +338,30 @@ namespace campvis {
height += sizeHintForRow(i);
if (model()->hasChildren(index)) {
height += model()->rowCount(index) * sizeHintForIndex(index.child(0, 0)).height();
for (int j = 0; j < model()->rowCount(index); ++j) {
QModelIndex cIndex = index.child(j, 0);
height += sizeHintForIndex(cIndex).height();
if (model()->hasChildren(cIndex)) {
height += model()->rowCount(cIndex) * sizeHintForIndex(cIndex.child(0, 0)).height();
}
}
}
}
// Next, add the heights of the horizontal scrollbar, header, and frame
height += horizontalScrollBar()->sizeHint().height();
height += header()->sizeHint().height();
height += 2 * header()->sizeHint().height();
height += 2 * frameWidth();
return QSize(QTreeView::sizeHint().width(), height);
}
void PipelineTreeWidget::update(const std::vector<AbstractPipeline*>& pipelines) {
void PipelineTreeWidget::update(const std::vector<DataContainer*>& dataContainers, const std::vector<AbstractPipeline*>& pipelines) {
// clear selection before setting the new data or we will encounter random crashes...
selectionModel()->clear();
_treeModel->setData(pipelines);
_treeModel->setData(dataContainers, pipelines);
expandAll();
resizeColumnToContents(0);
resizeColumnToContents(1);
......
......@@ -35,6 +35,7 @@
#include <QList>
#include <QVariant>
#include "core/datastructures/datacontainer.h"
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/abstractprocessor.h"
#include "application/tools/treeitem.h"
......@@ -56,6 +57,24 @@ namespace campvis {
virtual QVariant getData(int column, int role) const;
};
/**
* Specialization for TreeItems hosting an AbstracPipeline.
*/
class DataContainerTreeItem : public TreeItem {
public:
DataContainerTreeItem(DataContainer* dc, TreeItem* parent);
virtual ~DataContainerTreeItem();
/// \see TreeItem::getData()
virtual QVariant getData(int column, int role) const;
/// \see TreeItem::setData()
virtual bool setData(int column, int role, const QVariant& value) const;
private:
DataContainer* _dataContainer; ///< Base DataContainer
};
/**
* Specialization for TreeItems hosting an AbstracPipeline.
*/
......@@ -104,7 +123,7 @@ namespace campvis {
explicit PipelineTreeModel(QObject *parent = 0);
~PipelineTreeModel();
void setData(const std::vector<AbstractPipeline*>& pipelines);
void setData(const std::vector<DataContainer*>& dataContainers, const std::vector<AbstractPipeline*>& pipelines);
QVariant data(const QModelIndex &index, int role) const;
......@@ -162,7 +181,7 @@ namespace campvis {
* Updates the data in the tree view by the given collection of pipelines \a pipelines.
* \param pipelines
*/
void update(const std::vector<AbstractPipeline*>& pipelines);
void update(const std::vector<DataContainer*>& dataContainers, const std::vector<AbstractPipeline*>& pipelines);
private:
......
......@@ -35,7 +35,9 @@
namespace campvis {
const std::string DataContainer::loggerCat_ = "CAMPVis.core.datastructures.DataContainer";
DataContainer::DataContainer() {
DataContainer::DataContainer(const std::string& name)
: _name(name)
{
}
......@@ -110,4 +112,12 @@ namespace campvis {
_handles.clear();
}
const std::string& DataContainer::getName() const {
return _name;
}
void DataContainer::setName(const std::string& name) {
_name = name;
}
}
\ No newline at end of file
......@@ -59,8 +59,9 @@ namespace campvis {
public:
/**
* Creates a new empty DataContainer
* \param name The name of the new DataContainer
*/
DataContainer();
DataContainer(const std::string& name);
/**
* Destructor of the DataContainer. Will disconnect all DataHandles from this container.
......@@ -126,6 +127,18 @@ namespace campvis {
*/
std::vector< std::pair< std::string, DataHandle> > getDataHandlesCopy() const;
/**
* Returns the name of this DataContainer.
* \return _name
*/
const std::string& getName() const;
/**
* Sets the name of this DataContainer.
* \param name The new name of this DataContainer
*/
void setName(const std::string& name);
/**
* Returns a copy of the current map of DataHandles.
* \note Use with caution, this method is to be considered as slow, as it includes several
......@@ -150,6 +163,8 @@ namespace campvis {
tbb::concurrent_unordered_map<std::string, DataHandle> _handles;
std::string _name;
static const std::string loggerCat_;
};
......
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