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 14.5 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
        , _scriptingConsoleWidget(nullptr)
62
63
    {
        tgtAssert(_application != 0, "Application must not be 0.");
64
        ui.setupUi(this);
65
66
67
68
        setup();
    }

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

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

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

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

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

88
89
90
91
92
93
94
95
96
97
98
99
        _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);

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

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

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

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

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

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

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

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

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

134
135
136
137
#ifdef CAMPVIS_HAS_SCRIPTING
        _scriptingConsoleWidget = new ScriptingWidget(this);
        ui.scriptingConsoleDock->setWidget(_scriptingConsoleWidget);
        connect(_scriptingConsoleWidget, SIGNAL(s_commandExecuted(const QString&)), this, SLOT(onLuaCommandExecuted(const QString&)));
138
139
#else
        ui.scriptingConsoleDock->setVisible(false);
140
141
#endif

142
        _dcInspectorWidget = new DataContainerInspectorWidget();
143
        this->populateMainMenu();
144
145

        connect(
146
147
            this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)), 
            _pipelineWidget, SLOT(update(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)));
148
149
150
151
        connect(
            _pipelineWidget, SIGNAL(clicked(const QModelIndex&)), 
            this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&)));
        connect(
152
153
            this, SIGNAL(updatePropCollectionWidget(HasPropertyCollection*, DataContainer*)),
            _propCollectionWidget, SLOT(updatePropCollection(HasPropertyCollection*, DataContainer*)));
154
155
156
157
158
159
        connect(
            _btnExecute, SIGNAL(clicked()), 
            this, SLOT(onBtnExecuteClicked()));
        connect(
            _btnShowDataContainerInspector, SIGNAL(clicked()), 
            this, SLOT(onBtnShowDataContainerInspectorClicked()));
160
161
162
163
        connect(
            _btnPipelineFactory, SIGNAL(clicked()), 
            this, SLOT(onBtnPipelineFactoryClicked()));

164
        _application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
165
        _application->s_DataContainersChanged.connect(this, &MainWindow::onDataContainersChanged);
166
167
    }

168
    void MainWindow::populateMainMenu() {
169
        // Populate the file menu
170
171
        QMenuBar* menuBar = this->menuBar();
        QMenu* fileMenu = menuBar->addMenu(tr("&File"));
172
        fileMenu->addAction(tr("&Rebuild all Shaders from File"), this, SLOT(onRebuildShadersClicked()), QKeySequence(Qt::CTRL + Qt::Key_F5));
173
174
        fileMenu->addAction(tr("&Quit"), qApp, SLOT(closeAllWindows()), QKeySequence(Qt::CTRL + Qt::Key_Q));

175
176
177
178
179
180
181
182
183
184
        // 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());
185
186
    }

187
188
189
190
191
192
193
194
195
    bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
        if (watched == _pipelinePropertiesWidget && event->type() == QEvent::Resize) {
            _pipelinePropertiesScrollArea->setMinimumWidth(_pipelinePropertiesWidget->minimumSizeHint().width() +
                                                           _pipelinePropertiesScrollArea->verticalScrollBar()->width());
        }

        return false;
    }

196
    void MainWindow::onPipelinesChanged() {
197
198
199
200
        std::vector<AbstractPipeline*> pipelines;
        std::for_each(_application->_pipelines.begin(), _application->_pipelines.end(), [&] (const CampVisApplication::PipelineRecord& pr) { pipelines.push_back(pr._pipeline); });

        emit updatePipelineWidget(_application->_dataContainers, pipelines);
201
202
203
    }

    void MainWindow::onDataContainersChanged() {
204
205
206
207
        std::vector<AbstractPipeline*> pipelines;
        std::for_each(_application->_pipelines.begin(), _application->_pipelines.end(), [&] (const CampVisApplication::PipelineRecord& pr) { pipelines.push_back(pr._pipeline); });

        emit updatePipelineWidget(_application->_dataContainers, pipelines);
208
209
    }

210
211
212
213
    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);
214
215
            if (item.isValid()) {
                HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>());
216

217
                if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(ptr)) {
218
                    _selectedPipeline = pipeline;
219
                    _selectedProcessor = 0;
220
                    _selectedDataContainer = &pipeline->getDataContainer();
221
222
223
224
225
226
227
228
                }
                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;
229
                        _selectedDataContainer = &pipeline->getDataContainer();
230
                    }
231
232
                }

233
234
235
236
                emit updatePropCollectionWidget(ptr, &_selectedPipeline->getDataContainer());
            }
            else {
                emit updatePropCollectionWidget(0, 0);
237
                _selectedDataContainer = 0;
238
            }
239
240
        }
        else {
241
            emit updatePropCollectionWidget(0, 0);
242
            _selectedDataContainer = 0;
243
244
245
        }
    }

246
    QSize MainWindow::sizeHint() const {
247
        return QSize(1000, 600);
248
249
    }

250
251
252
253
    void MainWindow::onBtnExecuteClicked() {
        if (_selectedProcessor != 0 && _selectedPipeline != 0) {
            // this is not as trivial as it seems:
            // We need the pipeline, probably an OpenGL context...
254
            _selectedProcessor->invalidate(AbstractProcessor::INVALID_RESULT);
255
256
        }
        else if (_selectedPipeline != 0) {
257
258
259
            for (std::vector<AbstractProcessor*>::const_iterator it = _selectedPipeline->getProcessors().begin(); it != _selectedPipeline->getProcessors().end(); ++it) {
                (*it)->invalidate(AbstractProcessor::INVALID_RESULT);
            }
260
261
262
263
264
        }
    }

    void MainWindow::onBtnShowDataContainerInspectorClicked() {
        if (_selectedPipeline != 0) {
265
266
267
            if (_dcInspectorWindow == 0) {
                _dcInspectorWindow = _mdiArea->addWidget(_dcInspectorWidget);
                _dcInspectorWindow->setWindowTitle(tr("Data Container Inspector"));
268
269
            }

270
            _dcInspectorWidget->setDataContainer(&(_selectedPipeline->getDataContainer()));
271
272
            _dcInspectorWindow->show();
            _dcInspectorWindow->activateWindow();
273
274
275
        }
    }

276
    void MainWindow::init() {
277
278
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->init();
279

280
        _logViewer->init();
281
282
283

        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->init();
284
285
286
    }

    void MainWindow::deinit() {
287
288
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->deinit();
289

290
        _logViewer->deinit();
291
292
293

        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->deinit();
294
295
    }

296
    void MainWindow::addVisualizationPipelineWidget(const std::string& name, QWidget* canvas) {
297
        MdiDockableWindow* dockableWindow = _mdiArea->addWidget(canvas);
298
        QString windowTitle = QString::fromStdString(name);
299
300
        dockableWindow->setWindowTitle(windowTitle);
        dockableWindow->show();
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
    }

    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;
319
320
    }

321
322
323
324
325
326
327
328
329
330
    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);
    }

331
332
333
334
    void MainWindow::onRebuildShadersClicked() {
        _application->rebuildAllShadersFromFiles();
    }

335
    void MainWindow::onLuaCommandExecuted(const QString& cmd) {
336
337
338
#ifdef CAMPVIS_HAS_SCRIPTING
        if (_application->getLuaVmState() != nullptr) {
            _application->getLuaVmState()->execString(cmd.toStdString());
339
        }
340
#endif
341
342
    }

343
}