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 13 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-2013, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
//      Chair for Computer Aided Medical Procedures
8
9
//      Technische Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, Germany
10
// 
schultezub's avatar
schultezub committed
11
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
12
// 
13
14
15
16
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 
// except in compliance with the License. You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
17
// 
18
19
20
21
// Unless required by applicable law or agreed to in writing, software distributed under the 
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
// either express or implied. See the License for the specific language governing permissions 
// and limitations under the License.
22
23
24
// 
// ================================================================================================

25
26
27
#include "mainwindow.h"

#include "tgt/assert.h"
schultezub's avatar
schultezub committed
28
#include "application/campvisapplication.h"
29
#include "application/gui/datacontainerinspectorwidget.h"
30
#include "application/gui/datacontainerinspectorcanvas.h"
31
#include "application/gui/mdi/mdidockablewindow.h"
32
#include "application/gui/qtdatahandle.h"
33
#include "core/datastructures/datacontainer.h"
34
35
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/abstractprocessor.h"
36
37
#include "core/tools/stringutils.h"
#include "modules/pipelinefactory.h"
38

39
#include <QScrollBar>
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
40

41

schultezub's avatar
schultezub committed
42
namespace campvis {
43

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

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

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

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

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

83
        _mdiArea = new MdiDockArea();
84
85
86
        _mdiArea->tileSubWindows();
        setCentralWidget(_mdiArea);

87
88
89
90
91
92
93
94
95
96
97
98
        _containerWidget = new QWidget(this);
        QGridLayout* _cwLayout = new QGridLayout(_containerWidget);

        _cbPipelineFactory = new QComboBox(_containerWidget);
        std::vector<std::string> registeredPipelines = PipelineFactory::getRef().getRegisteredPipelines();
        for (std::vector<std::string>::const_iterator it = registeredPipelines.begin(); it != registeredPipelines.end(); ++it)
            _cbPipelineFactory->addItem(QString::fromStdString(*it));
        _cwLayout->addWidget(_cbPipelineFactory, 0, 0);

        _btnPipelineFactory = new QPushButton("Add Pipeline", _containerWidget);
        _cwLayout->addWidget(_btnPipelineFactory, 0, 1);

99
        _pipelineWidget = new PipelineTreeWidget(this);
100
101
102
103
104
        _containerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
        _cwLayout->addWidget(_pipelineWidget, 1, 0, 1, 2);

        _containerWidget->setLayout(_cwLayout);
        ui.pipelineTreeDock->setWidget(_containerWidget);
105

106
        _pipelinePropertiesScrollArea = new QScrollArea(this);
107
108
109
110
        _pipelinePropertiesScrollArea->setWidgetResizable(true);
        _pipelinePropertiesScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        _pipelinePropertiesScrollArea->setFrameStyle(QScrollArea::NoFrame);

111
        _pipelinePropertiesWidget = new QWidget(_pipelinePropertiesScrollArea);
112
113
114
        _pipelinePropertiesWidget->installEventFilter(this);
        _pipelinePropertiesScrollArea->setWidget(_pipelinePropertiesWidget);
        ui.pipelinePropertiesDock->setWidget(_pipelinePropertiesScrollArea);
115

116
        QVBoxLayout* rightLayout = new QVBoxLayout(_pipelinePropertiesWidget);
117
        rightLayout->setSpacing(4);
118
        _pipelinePropertiesWidget->setLayout(rightLayout);
119

120
        _btnExecute = new QPushButton("Execute Selected Pipeline/Processor", _pipelinePropertiesWidget);
121
122
        rightLayout->addWidget(_btnExecute);

123
        _btnShowDataContainerInspector = new QPushButton("Inspect DataContainer of Selected Pipeline", _pipelinePropertiesWidget);
124
        rightLayout->addWidget(_btnShowDataContainerInspector);
125

126
        _propCollectionWidget = new PropertyCollectionWidget(this);
127
        rightLayout->addWidget(_propCollectionWidget);
128
        rightLayout->addStretch();
129

130
        _logViewer = new LogViewerWidget(this);
131
        ui.logViewerDock->setWidget(_logViewer);
132

133
        _dcInspectorWidget = new DataContainerInspectorWidget();
134
        this->populateMainMenu();
135
136

        connect(
137
138
            this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)), 
            _pipelineWidget, SLOT(update(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)));
139
140
141
142
        connect(
            _pipelineWidget, SIGNAL(clicked(const QModelIndex&)), 
            this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&)));
        connect(
143
144
            this, SIGNAL(updatePropCollectionWidget(HasPropertyCollection*, DataContainer*)),
            _propCollectionWidget, SLOT(updatePropCollection(HasPropertyCollection*, DataContainer*)));
145
146
147
148
149
150
        connect(
            _btnExecute, SIGNAL(clicked()), 
            this, SLOT(onBtnExecuteClicked()));
        connect(
            _btnShowDataContainerInspector, SIGNAL(clicked()), 
            this, SLOT(onBtnShowDataContainerInspectorClicked()));
151
152
153
154
        connect(
            _btnPipelineFactory, SIGNAL(clicked()), 
            this, SLOT(onBtnPipelineFactoryClicked()));

155
        _application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
156
        _application->s_DataContainersChanged.connect(this, &MainWindow::onDataContainersChanged);
157
158
    }

159
    void MainWindow::populateMainMenu() {
160
        // Populate the file menu
161
162
163
164
        QMenuBar* menuBar = this->menuBar();
        QMenu* fileMenu = menuBar->addMenu(tr("&File"));
        fileMenu->addAction(tr("&Quit"), qApp, SLOT(closeAllWindows()), QKeySequence(Qt::CTRL + Qt::Key_Q));

165
166
167
168
169
170
171
172
173
174
        // Populate the visualizations menu
        QMenu* visualizationsMenu = _mdiArea->menu();
        visualizationsMenu->setTitle(tr("&Visualizations"));
        menuBar->addMenu(visualizationsMenu);

        // Populate the tools menu
        QMenu* toolsMenu = menuBar->addMenu(tr("&Tools"));
        toolsMenu->addAction(ui.pipelineTreeDock->toggleViewAction());
        toolsMenu->addAction(ui.pipelinePropertiesDock->toggleViewAction());
        toolsMenu->addAction(ui.logViewerDock->toggleViewAction());
175
176
    }

177
178
179
180
181
182
183
184
185
    bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
        if (watched == _pipelinePropertiesWidget && event->type() == QEvent::Resize) {
            _pipelinePropertiesScrollArea->setMinimumWidth(_pipelinePropertiesWidget->minimumSizeHint().width() +
                                                           _pipelinePropertiesScrollArea->verticalScrollBar()->width());
        }

        return false;
    }

186
    void MainWindow::onPipelinesChanged() {
187
188
189
190
191
        emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
    }

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

194
195
196
197
    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);
198
199
            if (item.isValid()) {
                HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>());
200

201
                if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(ptr)) {
202
                    _selectedPipeline = pipeline;
203
                    _selectedProcessor = 0;
204
                    _selectedDataContainer = &pipeline->getDataContainer();
205
206
207
208
209
210
211
212
                }
                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;
213
                        _selectedDataContainer = &pipeline->getDataContainer();
214
                    }
215
216
                }

217
218
219
220
                emit updatePropCollectionWidget(ptr, &_selectedPipeline->getDataContainer());
            }
            else {
                emit updatePropCollectionWidget(0, 0);
221
                _selectedDataContainer = 0;
222
            }
223
224
        }
        else {
225
            emit updatePropCollectionWidget(0, 0);
226
            _selectedDataContainer = 0;
227
228
229
        }
    }

230
    QSize MainWindow::sizeHint() const {
231
        return QSize(1000, 600);
232
233
    }

234
235
236
237
    void MainWindow::onBtnExecuteClicked() {
        if (_selectedProcessor != 0 && _selectedPipeline != 0) {
            // this is not as trivial as it seems:
            // We need the pipeline, probably an OpenGL context...
238
            _selectedProcessor->invalidate(AbstractProcessor::INVALID_RESULT);
239
240
        }
        else if (_selectedPipeline != 0) {
241
242
243
            for (std::vector<AbstractProcessor*>::const_iterator it = _selectedPipeline->getProcessors().begin(); it != _selectedPipeline->getProcessors().end(); ++it) {
                (*it)->invalidate(AbstractProcessor::INVALID_RESULT);
            }
244
245
246
247
248
        }
    }

    void MainWindow::onBtnShowDataContainerInspectorClicked() {
        if (_selectedPipeline != 0) {
249
250
251
            if (_dcInspectorWindow == 0) {
                _dcInspectorWindow = _mdiArea->addWidget(_dcInspectorWidget);
                _dcInspectorWindow->setWindowTitle(tr("Data Container Inspector"));
252
253
            }

254
            _dcInspectorWidget->setDataContainer(&(_selectedPipeline->getDataContainer()));
255
256
            _dcInspectorWindow->show();
            _dcInspectorWindow->activateWindow();
257
258
259
        }
    }

260
    void MainWindow::init() {
261
262
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->init();
263

264
        _logViewer->init();
265
266
267
    }

    void MainWindow::deinit() {
268
269
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->deinit();
270

271
        _logViewer->deinit();
272
273
    }

274
    void MainWindow::addVisualizationPipelineWidget(const std::string& name, QWidget* canvas) {
275
        MdiDockableWindow* dockableWindow = _mdiArea->addWidget(canvas);
276
        QString windowTitle = QString::fromStdString(name);
277
278
        dockableWindow->setWindowTitle(windowTitle);
        dockableWindow->show();
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
    }

    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;
297
298
    }

299
300
301
302
303
304
305
306
307
308
    void MainWindow::onBtnPipelineFactoryClicked() {
        std::string name = this->_cbPipelineFactory->currentText().toStdString();
        DataContainer* dc = _selectedDataContainer;
        if (dc == 0) {
            dc = _application->createAndAddDataContainer("DataContainer #" + StringUtils::toString(_application->_dataContainers.size() + 1));
        }
        AbstractPipeline* p = PipelineFactory::getRef().createPipeline(name, dc);
        _application->addPipeline(name, p);
    }

309
}