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.3 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-2014, 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 Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, 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
        QMenuBar* menuBar = this->menuBar();
        QMenu* fileMenu = menuBar->addMenu(tr("&File"));
163
        fileMenu->addAction(tr("&Rebuild all Shaders from File"), this, SLOT(onRebuildShadersClicked()), QKeySequence(Qt::CTRL + Qt::Key_F5));
164
165
        fileMenu->addAction(tr("&Quit"), qApp, SLOT(closeAllWindows()), QKeySequence(Qt::CTRL + Qt::Key_Q));

166
167
168
169
170
171
172
173
174
175
        // 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());
176
177
    }

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

        return false;
    }

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

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

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

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

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

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

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

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

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

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

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

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

272
        _logViewer->deinit();
273
274
    }

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

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

300
301
302
303
304
305
306
307
308
309
    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);
    }

310
311
312
313
    void MainWindow::onRebuildShadersClicked() {
        _application->rebuildAllShadersFromFiles();
    }

314
}