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 15 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
#include "mainwindow.h"

27
#include "cgt/assert.h"
28
29
#include "cgt/opengljobprocessor.h"

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

41
#include <QScrollBar>
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
42

43

schultezub's avatar
schultezub committed
44
namespace campvis {
45

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

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

    void MainWindow::setup() {
77
78
        qRegisterMetaType<QtDataHandle>("QtDataHandle");

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

84
        setTabPosition(Qt::TopDockWidgetArea, QTabWidget::North);
85

86
        _mdiArea = new MdiDockArea();
87
88
89
        _mdiArea->tileSubWindows();
        setCentralWidget(_mdiArea);

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

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

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

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

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

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

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

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

129
        _propCollectionWidget = new PropertyCollectionWidget(this);
130
        rightLayout->addWidget(_propCollectionWidget);
131
        rightLayout->addStretch();
132

133
        _logViewer = new LogViewerWidget(this);
134
        ui.logViewerDock->setWidget(_logViewer);
135

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

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

147
148
        qRegisterMetaType< std::vector<DataContainer*> >("std::vector<DataContainer*>");
        qRegisterMetaType< std::vector<AbstractPipeline*> >("std::vector<AbstractPipeline*>");
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
149
        qRegisterMetaType< std::map<AbstractProperty*, QWidget*>::iterator >("PropertyWidgetMapIterator");
150
        connect(
151
152
            this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)), 
            _pipelineWidget, SLOT(update(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)));
153
154
155
156
        connect(
            _pipelineWidget, SIGNAL(clicked(const QModelIndex&)), 
            this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&)));
        connect(
157
158
            this, SIGNAL(updatePropCollectionWidget(HasPropertyCollection*, DataContainer*)),
            _propCollectionWidget, SLOT(updatePropCollection(HasPropertyCollection*, DataContainer*)));
159
160
161
162
163
164
        connect(
            _btnExecute, SIGNAL(clicked()), 
            this, SLOT(onBtnExecuteClicked()));
        connect(
            _btnShowDataContainerInspector, SIGNAL(clicked()), 
            this, SLOT(onBtnShowDataContainerInspectorClicked()));
165
166
167
168
        connect(
            _btnPipelineFactory, SIGNAL(clicked()), 
            this, SLOT(onBtnPipelineFactoryClicked()));

169
        _application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
170
        _application->s_DataContainersChanged.connect(this, &MainWindow::onDataContainersChanged);
171
172
    }

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

180
181
182
183
184
185
186
187
188
189
        // 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());
190
191
    }

192
193
194
195
196
197
198
199
200
    bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
        if (watched == _pipelinePropertiesWidget && event->type() == QEvent::Resize) {
            _pipelinePropertiesScrollArea->setMinimumWidth(_pipelinePropertiesWidget->minimumSizeHint().width() +
                                                           _pipelinePropertiesScrollArea->verticalScrollBar()->width());
        }

        return false;
    }

201
    void MainWindow::onPipelinesChanged() {
202
203
204
205
        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);
206
207
208
    }

    void MainWindow::onDataContainersChanged() {
209
210
211
212
        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);
213
214
    }

215
216
217
218
    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);
219
220
            if (item.isValid()) {
                HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>());
221

222
                if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(ptr)) {
223
                    _selectedPipeline = pipeline;
224
                    _selectedProcessor = 0;
225
                    _selectedDataContainer = &pipeline->getDataContainer();
226
227
228
229
230
231
232
233
                }
                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;
234
                        _selectedDataContainer = &pipeline->getDataContainer();
235
                    }
236
237
                }

238
239
240
241
                emit updatePropCollectionWidget(ptr, &_selectedPipeline->getDataContainer());
            }
            else {
                emit updatePropCollectionWidget(0, 0);
242
                _selectedDataContainer = 0;
243
            }
244
245
        }
        else {
246
            emit updatePropCollectionWidget(0, 0);
247
            _selectedDataContainer = 0;
248
249
250
        }
    }

251
    QSize MainWindow::sizeHint() const {
252
        return QSize(1000, 600);
253
254
    }

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

    void MainWindow::onBtnShowDataContainerInspectorClicked() {
        if (_selectedPipeline != 0) {
270
271
272
            if (_dcInspectorWindow == 0) {
                _dcInspectorWindow = _mdiArea->addWidget(_dcInspectorWidget);
                _dcInspectorWindow->setWindowTitle(tr("Data Container Inspector"));
273
274
            }

275
            _dcInspectorWidget->setDataContainer(&(_selectedPipeline->getDataContainer()));
276
277
            _dcInspectorWindow->show();
            _dcInspectorWindow->activateWindow();
278
279
280
        }
    }

281
    void MainWindow::init() {
282
283
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->init();
284

285
        _logViewer->init();
286
287
288

        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->init();
289
290
291
    }

    void MainWindow::deinit() {
292
293
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->deinit();
294

295
        _logViewer->deinit();
296
297
298

        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->deinit();
299
300
    }

301
    MdiDockableWindow * MainWindow::addVisualizationPipelineWidget(const std::string& name, QWidget* canvas) {
302
        MdiDockableWindow* dockableWindow = _mdiArea->addWidget(canvas);
303
        QString windowTitle = QString::fromStdString(name);
304
305
        dockableWindow->setWindowTitle(windowTitle);
        dockableWindow->show();
306
        return dockableWindow;
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
    }

    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;
325
326
    }

327
328
329
330
331
332
333
334
335
336
    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);
    }

337
338
339
340
    void MainWindow::onRebuildShadersClicked() {
        _application->rebuildAllShadersFromFiles();
    }

341
    void MainWindow::onLuaCommandExecuted(const QString& cmd) {
342
343
#ifdef CAMPVIS_HAS_SCRIPTING
        if (_application->getLuaVmState() != nullptr) {
344
            cgt::OpenGLJobProcessor::ScopedSynchronousGlJobExecution jobGuard;
345
            _application->getLuaVmState()->execString(cmd.toStdString());
346
        }
347
#endif
348
349
    }

350
}