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

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

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

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

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

        return false;
    }

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

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

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

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

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

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

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

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

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

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

282
        _logViewer->init();
283
284
285

        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->init();
286
287
288
    }

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

292
        _logViewer->deinit();
293
294
295

        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->deinit();
296
297
    }

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

    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;
322
323
    }

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

334
335
336
337
    void MainWindow::onRebuildShadersClicked() {
        _application->rebuildAllShadersFromFiles();
    }

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

346
}