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.9 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*>");
149
        connect(
150
151
            this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)), 
            _pipelineWidget, SLOT(update(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)));
152
153
154
155
        connect(
            _pipelineWidget, SIGNAL(clicked(const QModelIndex&)), 
            this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&)));
        connect(
156
157
            this, SIGNAL(updatePropCollectionWidget(HasPropertyCollection*, DataContainer*)),
            _propCollectionWidget, SLOT(updatePropCollection(HasPropertyCollection*, DataContainer*)));
158
159
160
161
162
163
        connect(
            _btnExecute, SIGNAL(clicked()), 
            this, SLOT(onBtnExecuteClicked()));
        connect(
            _btnShowDataContainerInspector, SIGNAL(clicked()), 
            this, SLOT(onBtnShowDataContainerInspectorClicked()));
164
165
166
167
        connect(
            _btnPipelineFactory, SIGNAL(clicked()), 
            this, SLOT(onBtnPipelineFactoryClicked()));

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

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

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

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

        return false;
    }

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

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

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

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

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

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

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

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

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

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

284
        _logViewer->init();
285
286
287

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

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

294
        _logViewer->deinit();
295
296
297

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

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

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

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

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

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

349
}