Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing 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 540783ad authored by schultezub's avatar schultezub
Browse files

* Started implementing a GUI: introducing MainWindow, PipelineTreeWidget

 * elaborated checks in TumVisApplication
 * added AbstractPipeline.getName() and AbstractProcessor.getName()

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@204 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent c32b41e0
......@@ -6,10 +6,12 @@ MESSAGE(STATUS "Configuring TUMVis Application")
FILE(GLOB TUMVIS_APPLICATION_SOURCES
*.cpp
gui/*.cpp
)
FILE(GLOB TUMVIS_APPLICATION_HEADERS
*.h
gui/*.h
)
#SET(TUMVIS_APPLICATION_SOURCES
......@@ -19,7 +21,8 @@ FILE(GLOB TUMVIS_APPLICATION_HEADERS
#)
SET(TUMVIS_APPLICATION_TO_BE_MOCCED
tumvisapplication.h
gui/mainwindow.h
gui/pipelinetreewidget.h
)
#
......
#include "mainwindow.h"
#include "tgt/assert.h"
#include "application/tumvisapplication.h"
namespace TUMVis {
MainWindow::MainWindow(TumVisApplication* application)
: QMainWindow()
, _application(application)
, _pipelineWidget(0)
{
tgtAssert(_application != 0, "Application must not be 0.");
setup();
}
MainWindow::~MainWindow() {
}
void MainWindow::setup() {
_pipelineWidget = new PipelineTreeWidget(this);
setCentralWidget(_pipelineWidget);
connect(this, SIGNAL(updatePipelineWidget(const std::vector<AbstractPipeline*>&)), _pipelineWidget, SLOT(update(const std::vector<AbstractPipeline*>&)));
_application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
}
void MainWindow::onPipelinesChanged() {
emit updatePipelineWidget(_application->_pipelines);
}
}
\ No newline at end of file
#ifndef TUMVISMAINWINDOW_H__
#define TUMVISMAINWINDOW_H__
#include "sigslot/sigslot.h"
#include "application/tumvisapplication.h"
#include "application/gui/pipelinetreewidget.h"
#include <QMainWindow>
#include <vector>
namespace TUMVis {
class MainWindow : public QMainWindow, public sigslot::has_slots<> {
Q_OBJECT;
public:
MainWindow(TumVisApplication* application);
~MainWindow();
void onPipelinesChanged();
signals:
void updatePipelineWidget(const std::vector<AbstractPipeline*>&);
private:
void setup();
TumVisApplication* _application; ///< Pointer to the application hosting the whole stuff
PipelineTreeWidget* _pipelineWidget; ///< Widget for browsing the active pipelines
};
}
#endif // TUMVISMAINWINDOW_H__
#include "pipelinetreewidget.h"
#include "tgt/assert.h"
#include <QHeaderView>
#include <QStringList>
namespace TUMVis {
// = TreeModel items ==============================================================================
TreeItem::TreeItem(TreeItem* parent /*= 0*/)
: _parent(parent)
{
if (_parent != 0)
_parent->_children.append(this);
}
TreeItem::~TreeItem() {
qDeleteAll(_children);
}
TreeItem* TreeItem::getParent() {
return _parent;
}
TreeItem* TreeItem::getChild(int row) {
return _children.value(row);
}
int TreeItem::getRow() {
if (_parent)
return _parent->_children.indexOf(const_cast<TreeItem*>(this));
return 0;
}
int TreeItem::getChildCount() {
return _children.count();
}
PipelineTreeItem::PipelineTreeItem(AbstractPipeline* pipeline, TreeItem* parent)
: TreeItem(parent)
, _pipeline(pipeline)
{
tgtAssert(_pipeline != 0, "Pipeline must not be 0.");
}
QVariant PipelineTreeItem::getData(int column) const {
if (column == 0)
return QVariant(QString::fromStdString(_pipeline->getName()));
return QVariant();
}
PipelineTreeItem::~PipelineTreeItem() {
}
ProcessorTreeItem::ProcessorTreeItem(AbstractProcessor* processor, TreeItem* parent)
: TreeItem(parent)
, _processor(processor)
{
tgtAssert(_processor != 0, "Processor must not be 0.");
}
QVariant ProcessorTreeItem::getData(int column) const {
if (column == 0)
return QVariant(QString::fromStdString(_processor->getName()));
return QVariant();
}
ProcessorTreeItem::~ProcessorTreeItem() {
}
RootTreeItem::RootTreeItem(TreeItem* parent /*= 0*/)
: TreeItem(parent)
{}
QVariant RootTreeItem::getData(int column) const {
if (column == 0)
return QVariant(QString("Pipeline/Processor"));
else if (column == 1)
return QVariant(QString("Description"));
return QVariant();
}
RootTreeItem::~RootTreeItem() {
}
// = PipelineTreeModel ============================================================================
PipelineTreeModel::PipelineTreeModel(QObject *parent /*= 0*/)
: QAbstractItemModel(parent)
, _rootItem(new RootTreeItem(0))
{
}
PipelineTreeModel::~PipelineTreeModel() {
delete _rootItem;
}
QVariant PipelineTreeModel::data(const QModelIndex &index, int role) const {
if (!index.isValid())
return QVariant();
if (role != Qt::DisplayRole)
return QVariant();
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
return item->getData(index.column());
}
Qt::ItemFlags PipelineTreeModel::flags(const QModelIndex &index) const {
if (!index.isValid())
return 0;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
QVariant PipelineTreeModel::headerData(int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/) const {
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
return _rootItem->getData(section);
return QVariant();
}
QModelIndex PipelineTreeModel::index(int row, int column, const QModelIndex &parent /*= QModelIndex()*/) const {
if (!hasIndex(row, column, parent))
return QModelIndex();
TreeItem* parentItem;
if (!parent.isValid())
parentItem = _rootItem;
else
parentItem = static_cast<TreeItem*>(parent.internalPointer());
TreeItem* childItem = parentItem->getChild(row);
if (childItem)
return createIndex(row, column, childItem);
else
return QModelIndex();
}
QModelIndex PipelineTreeModel::parent(const QModelIndex &index) const {
if (!index.isValid())
return QModelIndex();
TreeItem* childItem = static_cast<TreeItem*>(index.internalPointer());
TreeItem* parentItem = childItem->getParent();
if (parentItem == _rootItem)
return QModelIndex();
return createIndex(parentItem->getRow(), 0, parentItem);
}
int PipelineTreeModel::rowCount(const QModelIndex &parent /*= QModelIndex()*/) const {
TreeItem* parentItem;
if (parent.column() > 0)
return 0;
if (!parent.isValid())
parentItem = _rootItem;
else
parentItem = static_cast<TreeItem*>(parent.internalPointer());
return parentItem->getChildCount();
}
int PipelineTreeModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const {
return 2;
}
void PipelineTreeModel::setData(const std::vector<AbstractPipeline*>& pipelines) {
for (std::vector<AbstractPipeline*>::const_iterator pipe = pipelines.begin(); pipe != pipelines.end(); ++pipe) {
PipelineTreeItem* pipeti = new PipelineTreeItem(*pipe, _rootItem);
for (std::vector<AbstractProcessor*>::const_iterator proc = (*pipe)->getProcessors().begin(); proc != (*pipe)->getProcessors().end(); ++proc) {
ProcessorTreeItem* procti = new ProcessorTreeItem(*proc, pipeti);
}
}
}
// = PipelineTreeWidget ===========================================================================
PipelineTreeWidget::PipelineTreeWidget(QWidget* parent /*= 0*/)
: QTreeView(parent)
{
setupWidget();
}
PipelineTreeWidget::~PipelineTreeWidget() {
}
void PipelineTreeWidget::update(const std::vector<AbstractPipeline*>& pipelines) {
_treeModel->setData(pipelines);
}
void PipelineTreeWidget::setupWidget() {
_treeModel = new PipelineTreeModel(this);
tgtAssert(_treeModel != 0, "Failed creating TreeViewWidget model.");
setModel(_treeModel);
resizeColumnToContents(0);
}
}
\ No newline at end of file
#ifndef PIPELINETREEWIDGET_H__
#define PIPELINETREEWIDGET_H__
#include <QAbstractItemModel>
#include <QTreeWidget>
#include <QList>
#include <QVariant>
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/abstractprocessor.h"
#include <vector>
namespace TUMVis {
// = TreeModel items ==============================================================================
class TreeItem {
public:
TreeItem(TreeItem* parent = 0);
virtual ~TreeItem();
virtual QVariant getData(int column) const = 0;
TreeItem* getParent();
TreeItem* getChild(int row);
int getRow();
int getChildCount();
private:
TreeItem* _parent;
QList<TreeItem*> _children;
};
class RootTreeItem : public TreeItem {
public:
RootTreeItem(TreeItem* parent = 0);
virtual ~RootTreeItem();
virtual QVariant getData(int column) const;
};
class PipelineTreeItem : public TreeItem {
public:
PipelineTreeItem(AbstractPipeline* pipeline, TreeItem* parent);
virtual ~PipelineTreeItem();
virtual QVariant getData(int column) const;
private:
AbstractPipeline* _pipeline;
};
class ProcessorTreeItem : public TreeItem {
public:
ProcessorTreeItem(AbstractProcessor* processor, TreeItem* parent);
virtual ~ProcessorTreeItem();
virtual QVariant getData(int column) const;
private:
AbstractProcessor* _processor;
};
// = TreeModel ====================================================================================
class PipelineTreeModel : public QAbstractItemModel {
Q_OBJECT
public:
PipelineTreeModel(QObject *parent = 0);
~PipelineTreeModel();
void setData(const std::vector<AbstractPipeline*>& pipelines);
QVariant data(const QModelIndex &index, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
private:
TreeItem* _rootItem;
};
// = Widget =======================================================================================
class PipelineTreeWidget : public QTreeView {
Q_OBJECT;
public:
PipelineTreeWidget(QWidget* parent = 0);
virtual ~PipelineTreeWidget();
public slots:
void update(const std::vector<AbstractPipeline*>& pipelines);
private:
void setupWidget();
PipelineTreeModel* _treeModel;
};
}
#endif // PIPELINETREEWIDGET_H__
......@@ -3,10 +3,6 @@
using namespace TUMVis;
SliceVis* sliceVis = 0;
TumVisPainter* painter = 0;
PipelineEvaluator* pe;
/**
* TUMVis main function, application entry point
*
......
......@@ -3,6 +3,7 @@
#include "tgt/assert.h"
#include "tgt/exception.h"
#include "tgt/glcontext.h"
#include "tgt/gpucapabilities.h"
#include "tgt/shadermanager.h"
#include "tgt/qt/qtapplication.h"
#include "tgt/qt/qtthreadedcanvas.h"
......@@ -10,21 +11,28 @@
#include "tbb/include/tbb/compat/thread"
#include "application/tumvispainter.h"
#include "application/gui/mainwindow.h"
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/visualizationpipeline.h"
#include "core/pipeline/pipelineevaluator.h"
namespace TUMVis {
const std::string TumVisApplication::loggerCat_ = "TUMVis.application.TumVisApplication";
TumVisApplication::TumVisApplication(int argc, char** argv)
: QApplication(argc, argv)
, _localContext(0)
, _mainWindow(0)
, _initialized(false)
, _argc(argc)
, _argv(argv)
{
tgt::QtContextManager::init();
// Make Xlib and GLX thread safe under X11
QApplication::setAttribute(Qt::AA_X11InitThreads);
_mainWindow = new MainWindow(this);
tgt::QtContextManager::init();
}
TumVisApplication::~TumVisApplication() {
......@@ -41,6 +49,7 @@ namespace TUMVis {
delete *it;
}
// TODO: _mainWindow is a Qt pointer and does not need to be deleted - right?
}
void TumVisApplication::init() {
......@@ -57,6 +66,14 @@ namespace TUMVis {
tgt::initGL(featureset);
LGL_ERROR;
// ensure matching OpenGL specs
if (GpuCaps.getGlVersion() < tgt::GpuCapabilities::GlVersion::TGT_GL_VERSION_3_0) {
LERROR("Your system does not support OpenGL 3.0, which is mandatory. TUMVis will probably not work as intendet.");
}
if (GpuCaps.getShaderVersion() < tgt::GpuCapabilities::GlVersion::SHADER_VERSION_130) {
LERROR("Your system does not support GLSL Shader Version 1.30, which is mandatory. TUMVis will probably not work as intendet.");
}
if (_argc > 0) {
// ugly hack
std::string programPath(_argv[0]);
......@@ -105,6 +122,8 @@ namespace TUMVis {
// disconnect OpenGL context from this thread so that the other threads can acquire an OpenGL context.
CtxtMgr.releaseCurrentContext();
_mainWindow->show();
// Start evaluator/render threads
for (std::vector<PipelineEvaluator*>::iterator it = _pipelineEvaluators.begin(); it != _pipelineEvaluators.end(); ++it) {
(*it)->start();
......@@ -128,21 +147,20 @@ namespace TUMVis {
}
void TumVisApplication::addPipeline(AbstractPipeline* pipeline) {
tgtAssert(_initialized == false, "Adding pipelines after initialization is currently not supported.");
tgtAssert(pipeline != 0, "Pipeline must not be 0.");
_pipelines.push_back(pipeline);
PipelineEvaluator* pe = new PipelineEvaluator(pipeline);
_pipelineEvaluators.push_back(pe);
s_PipelinesChanged();
}
void TumVisApplication::addVisualizationPipeline(const std::string& name, VisualizationPipeline* vp) {
tgtAssert(_initialized == false, "Adding pipelines after initialization is currently not supported.");
tgtAssert(vp != 0, "Pipeline must not be 0.");
// TODO: is there a more leightweight method to create a context for the pipeline (just performing off-screen rendering)?
tgt::QtThreadedCanvas* evaluationContext = CtxtMgr.createContext(name + "_eval", "", tgt::ivec2(512, 512));
vp->setCanvas(evaluationContext);
addPipeline(vp);
// create canvas and painter for the VisPipeline and connect all together
tgt::QtThreadedCanvas* canvas = CtxtMgr.createContext(name, "TUMVis", tgt::ivec2(512, 512));
canvas->init();
......@@ -152,6 +170,11 @@ namespace TUMVis {
CtxtMgr.releaseCurrentContext();
_visualizations.push_back(std::make_pair(vp, painter));
// TODO: is there a more leightweight method to create a context for the pipeline (just performing off-screen rendering)?
tgt::QtThreadedCanvas* evaluationContext = CtxtMgr.createContext(name + "_eval", "", tgt::ivec2(512, 512));
vp->setCanvas(evaluationContext);
addPipeline(vp);
}
}
\ No newline at end of file
#ifndef TUMVISAPPLICATION_H__
#define TUMVISAPPLICATION_H__
#include "sigslot/sigslot.h"
#include <QApplication>
#include <utility>
#include <vector>
......@@ -11,6 +12,7 @@ namespace tgt {
namespace TUMVis {
class AbstractPipeline;
class MainWindow;
class PipelineEvaluator;
class TumVisPainter;
class VisualizationPipeline;
......@@ -28,6 +30,8 @@ namespace TUMVis {
* 6) You can now safely destroy your TumVisApplication
*/
class TumVisApplication : QApplication {
friend class MainWindow;
public:
/**
* Creates a new TumVisApplication.
......@@ -80,22 +84,28 @@ namespace TUMVis {
*/
int run();
sigslot::signal0<> s_PipelinesChanged;
private:
/// All pipelines (incuding VisualizationPipelines)
std::vector<AbstractPipeline*> _pipelines;
/// All pipeline evaluators
/// All pipeline evaluators (separated from _pipelines because we probably want multiple pipelines per evaluator later)
std::vector<PipelineEvaluator*> _pipelineEvaluators;
/// All visualisations (i.e. VisualizationPipelines with their corresponding painters/canvases)
std::vector< std::pair<VisualizationPipeline*, TumVisPainter*> > _visualizations;
/// A local OpenGL context used for initialization
tgt::QtThreadedCanvas* _localContext;
/// Main window hosting GUI stuff
MainWindow* _mainWindow;
/// Flag, whether TumVisApplication was correctly initialized
bool _initialized;
int _argc;
char** _argv;
static const std::string loggerCat_;
};
}
......
......@@ -60,4 +60,8 @@ namespace TUMVis {
return _invalidationLevel;
}
const std::vector<AbstractProcessor*>& AbstractPipeline::getProcessors() const {
return _processors;
}
}
......@@ -65,6 +65,18 @@ namespace TUMVis {
* \return _data
*/
const DataContainer& getDataContainer() const;
/**