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

mainwindow.cpp 10.7 KB
Newer Older
1
2
// ================================================================================================
// 
schultezub's avatar
schultezub committed
3
// This file is part of the CAMPVis Software Framework.
4
5
// 
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
8
9
//      Chair for Computer Aided Medical Procedures
//      Technische Universitt Mnchen
//      Boltzmannstr. 3, 85748 Garching b. Mnchen, Germany
schultezub's avatar
schultezub committed
10
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
// 
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// 
// ================================================================================================

30
31
32
#include "mainwindow.h"

#include "tgt/assert.h"
schultezub's avatar
schultezub committed
33
#include "application/campvisapplication.h"
34
#include "application/gui/datacontainerinspectorwidget.h"
35
#include "application/gui/datacontainerinspectorcanvas.h"
36
#include "application/gui/qtdatahandle.h"
37
#include "application/gui/visualizationpipelinewrapper.h"
38
#include "core/datastructures/datacontainer.h"
39
40
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/abstractprocessor.h"
41

42
#include <QMdiSubWindow>
43
#include <QScrollBar>
44

schultezub's avatar
schultezub committed
45
namespace campvis {
46

47
    MainWindow::MainWindow(CampVisApplication* application)
48
49
        : QMainWindow()
        , _application(application)
50
        , _mdiArea(0)
51
        , _pipelineWidget(0)
52
53
        , _propCollectionWidget(0)
        , _dcInspectorWidget(0)
54
        , _dcInspectorDock(0)
55
56
57
58
        , _btnExecute(0)
        , _btnShowDataContainerInspector(0)
        , _selectedPipeline(0)
        , _selectedProcessor(0)
59
        , _logViewer(0)
60
61
    {
        tgtAssert(_application != 0, "Application must not be 0.");
62
        ui.setupUi(this);
63
64
65
66
        setup();
    }

    MainWindow::~MainWindow() {
schultezub's avatar
schultezub committed
67
        _application->s_PipelinesChanged.disconnect(this);
68
        _application->s_DataContainersChanged.disconnect(this);
69
        delete _dcInspectorWidget;
70
71
72
    }

    void MainWindow::setup() {
73
74
        qRegisterMetaType<QtDataHandle>("QtDataHandle");

75
        setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
76
        setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
77
        setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
78
        setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
79

80
        setTabPosition(Qt::TopDockWidgetArea, QTabWidget::North);
81

82
83
84
85
        _mdiArea = new QMdiArea();
        _mdiArea->tileSubWindows();
        setCentralWidget(_mdiArea);

86
        _pipelineWidget = new PipelineTreeWidget();
87
        _pipelineWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
88
        ui.pipelineTreeDock->setWidget(_pipelineWidget);
89

90
91
92
93
94
95
96
97
98
        _pipelinePropertiesScrollArea = new QScrollArea();
        _pipelinePropertiesScrollArea->setWidgetResizable(true);
        _pipelinePropertiesScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        _pipelinePropertiesScrollArea->setFrameStyle(QScrollArea::NoFrame);

        _pipelinePropertiesWidget = new QWidget();
        _pipelinePropertiesWidget->installEventFilter(this);
        _pipelinePropertiesScrollArea->setWidget(_pipelinePropertiesWidget);
        ui.pipelinePropertiesDock->setWidget(_pipelinePropertiesScrollArea);
99
100
101

        QVBoxLayout* rightLayout = new QVBoxLayout();
        rightLayout->setSpacing(4);
102
        _pipelinePropertiesWidget->setLayout(rightLayout);
103

104
        _btnExecute = new QPushButton("Execute Selected Pipeline/Processor");
105
106
        rightLayout->addWidget(_btnExecute);

107
        _btnShowDataContainerInspector = new QPushButton("Inspect DataContainer of Selected Pipeline");
108
        rightLayout->addWidget(_btnShowDataContainerInspector);
109

110
        _propCollectionWidget = new PropertyCollectionWidget();
111
        rightLayout->addWidget(_propCollectionWidget);
112
        rightLayout->addStretch();
113

114
        _logViewer = new LogViewerWidget();
115
        ui.logViewerDock->setWidget(_logViewer);
116

117
        _dcInspectorWidget = new DataContainerInspectorWidget();
118
119

        connect(
120
121
            this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)), 
            _pipelineWidget, SLOT(update(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)));
122
123
124
125
        connect(
            _pipelineWidget, SIGNAL(clicked(const QModelIndex&)), 
            this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&)));
        connect(
126
127
            this, SIGNAL(updatePropCollectionWidget(HasPropertyCollection*, DataContainer*)),
            _propCollectionWidget, SLOT(updatePropCollection(HasPropertyCollection*, DataContainer*)));
128
129
130
131
132
133
        connect(
            _btnExecute, SIGNAL(clicked()), 
            this, SLOT(onBtnExecuteClicked()));
        connect(
            _btnShowDataContainerInspector, SIGNAL(clicked()), 
            this, SLOT(onBtnShowDataContainerInspectorClicked()));
134
        _application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
135
        _application->s_DataContainersChanged.connect(this, &MainWindow::onDataContainersChanged);
136
137
    }

138
139
140
141
142
143
144
145
146
    bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
        if (watched == _pipelinePropertiesWidget && event->type() == QEvent::Resize) {
            _pipelinePropertiesScrollArea->setMinimumWidth(_pipelinePropertiesWidget->minimumSizeHint().width() +
                                                           _pipelinePropertiesScrollArea->verticalScrollBar()->width());
        }

        return false;
    }

147
    void MainWindow::onPipelinesChanged() {
148
149
150
151
152
        emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
    }

    void MainWindow::onDataContainersChanged() {
        emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
153
154
    }

155
156
157
158
    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);
159
160
            if (item.isValid()) {
                HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>());
161

162
                if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(ptr)) {
163
                    _selectedPipeline = pipeline;
164
165
166
167
168
169
170
171
172
173
                    _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;
                    }
174
175
                }

176
177
178
179
180
                emit updatePropCollectionWidget(ptr, &_selectedPipeline->getDataContainer());
            }
            else {
                emit updatePropCollectionWidget(0, 0);
            }
181
182
        }
        else {
183
            emit updatePropCollectionWidget(0, 0);
184
185
186
        }
    }

187
188
189
190
    QSize MainWindow::sizeHint() const {
        return QSize(800, 450);
    }

191
192
193
194
    void MainWindow::onBtnExecuteClicked() {
        if (_selectedProcessor != 0 && _selectedPipeline != 0) {
            // this is not as trivial as it seems:
            // We need the pipeline, probably an OpenGL context...
195
            _selectedProcessor->invalidate(AbstractProcessor::INVALID_RESULT);
196
197
        }
        else if (_selectedPipeline != 0) {
198
199
200
            for (std::vector<AbstractProcessor*>::const_iterator it = _selectedPipeline->getProcessors().begin(); it != _selectedPipeline->getProcessors().end(); ++it) {
                (*it)->invalidate(AbstractProcessor::INVALID_RESULT);
            }
201
202
203
204
205
        }
    }

    void MainWindow::onBtnShowDataContainerInspectorClicked() {
        if (_selectedPipeline != 0) {
206
207
208
209
210
211
212
213
            if (_dcInspectorDock == 0) {
                _dcInspectorDock = dockPrimaryWidget("Data Container inspector", _dcInspectorWidget);
            } else {
                // Activate the dock's tab
                _dcInspectorDock->setVisible(true);
                _dcInspectorDock->raise();
            }

214
215
216
217
            _dcInspectorWidget->setDataContainer(&(_selectedPipeline->getDataContainer()));
        }
    }

218
    void MainWindow::init() {
219
220
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->init();
221

222
        _logViewer->init();
223
224
225
    }

    void MainWindow::deinit() {
226
227
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->deinit();
228

229
        _logViewer->deinit();
230
231
    }

232
233
    void MainWindow::addVisualizationPipelineWidget(const std::string& name, QWidget* canvas) {
        VisualizationPipelineWrapper* widget = new VisualizationPipelineWrapper(name, canvas, _mdiArea, this);
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
    }

    QDockWidget* MainWindow::dockPrimaryWidget(const std::string& name, QWidget* widget) {
        QDockWidget* dockWidget = new QDockWidget(QString::fromStdString(name));
        dockWidget->setWidget(widget);
        dockWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);

        if (_primaryDocks.empty()) {
            addDockWidget(Qt::TopDockWidgetArea, dockWidget);
        } else {
            tabifyDockWidget(_primaryDocks.back(), dockWidget);
            // Activate the dock's tab
            dockWidget->setVisible(true);
            dockWidget->raise();
        }

        _primaryDocks.push_back(dockWidget);
        return dockWidget;
252
253
    }

254
}