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.2 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
        , _workflowWidget(nullptr)
65
    {
66
        cgtAssert(_application != 0, "Application must not be 0.");
67
        ui.setupUi(this);
68
69
70
71
        setup();
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

145
146
147
        _workflowWidget = new WorkflowControllerWidget(this);
        ui.workflowDock->setWidget(_workflowWidget);

148
        _dcInspectorWidget = new DataContainerInspectorWidget();
149
        this->populateMainMenu();
150

151
152
        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
153
        qRegisterMetaType< std::map<AbstractProperty*, QWidget*>::iterator >("PropertyWidgetMapIterator");
154
        connect(
155
156
            this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)), 
            _pipelineWidget, SLOT(update(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)));
157
158
159
160
        connect(
            _pipelineWidget, SIGNAL(clicked(const QModelIndex&)), 
            this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&)));
        connect(
161
162
            this, SIGNAL(updatePropCollectionWidget(HasPropertyCollection*, DataContainer*)),
            _propCollectionWidget, SLOT(updatePropCollection(HasPropertyCollection*, DataContainer*)));
163
164
165
166
167
168
        connect(
            _btnExecute, SIGNAL(clicked()), 
            this, SLOT(onBtnExecuteClicked()));
        connect(
            _btnShowDataContainerInspector, SIGNAL(clicked()), 
            this, SLOT(onBtnShowDataContainerInspectorClicked()));
169
170
171
172
        connect(
            _btnPipelineFactory, SIGNAL(clicked()), 
            this, SLOT(onBtnPipelineFactoryClicked()));

173
        _application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
174
        _application->s_DataContainersChanged.connect(this, &MainWindow::onDataContainersChanged);
175
176
    }

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

184
185
186
187
188
189
190
191
192
193
        // 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());
194
        toolsMenu->addAction(ui.workflowDock->toggleViewAction());
195
196
    }

197
198
199
200
201
202
203
204
205
    bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
        if (watched == _pipelinePropertiesWidget && event->type() == QEvent::Resize) {
            _pipelinePropertiesScrollArea->setMinimumWidth(_pipelinePropertiesWidget->minimumSizeHint().width() +
                                                           _pipelinePropertiesScrollArea->verticalScrollBar()->width());
        }

        return false;
    }

206
    void MainWindow::onPipelinesChanged() {
207
208
209
210
        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);
211
212
213
    }

    void MainWindow::onDataContainersChanged() {
214
215
216
217
        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);
218
219
    }

220
221
222
223
    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);
224
225
            if (item.isValid()) {
                HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>());
226

227
                if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(ptr)) {
228
                    _selectedPipeline = pipeline;
229
                    _selectedProcessor = 0;
230
                    _selectedDataContainer = &pipeline->getDataContainer();
231
232
233
234
235
236
237
238
                }
                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;
239
                        _selectedDataContainer = &pipeline->getDataContainer();
240
                    }
241
242
                }

243
244
245
246
                emit updatePropCollectionWidget(ptr, &_selectedPipeline->getDataContainer());
            }
            else {
                emit updatePropCollectionWidget(0, 0);
247
                _selectedDataContainer = 0;
248
            }
249
250
        }
        else {
251
            emit updatePropCollectionWidget(0, 0);
252
            _selectedDataContainer = 0;
253
254
255
        }
    }

256
    QSize MainWindow::sizeHint() const {
257
        return QSize(1000, 600);
258
259
    }

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

    void MainWindow::onBtnShowDataContainerInspectorClicked() {
        if (_selectedPipeline != 0) {
275
276
277
            if (_dcInspectorWindow == 0) {
                _dcInspectorWindow = _mdiArea->addWidget(_dcInspectorWidget);
                _dcInspectorWindow->setWindowTitle(tr("Data Container Inspector"));
278
279
            }

280
            _dcInspectorWidget->setDataContainer(&(_selectedPipeline->getDataContainer()));
281
282
            _dcInspectorWindow->show();
            _dcInspectorWindow->activateWindow();
283
284
285
        }
    }

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

290
        _logViewer->init();
291
292
293

        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->init();
294
295
296
    }

    void MainWindow::deinit() {
297
298
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->deinit();
299

300
        _logViewer->deinit();
301
302
303

        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->deinit();
304
305
    }

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

    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;
330
331
    }

332
333
334
335
336
337
338
339
340
341
    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);
    }

342
343
344
345
    void MainWindow::onRebuildShadersClicked() {
        _application->rebuildAllShadersFromFiles();
    }

346
    void MainWindow::onLuaCommandExecuted(const QString& cmd) {
347
348
#ifdef CAMPVIS_HAS_SCRIPTING
        if (_application->getLuaVmState() != nullptr) {
349
            cgt::OpenGLJobProcessor::ScopedSynchronousGlJobExecution jobGuard;
350
            _application->getLuaVmState()->execString(cmd.toStdString());
351
        }
352
#endif
353
354
    }

355
}