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.3 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
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&)));
#endif

140
        _dcInspectorWidget = new DataContainerInspectorWidget();
141
        this->populateMainMenu();
142
143

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

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

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

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

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

        return false;
    }

194
    void MainWindow::onPipelinesChanged() {
195
196
197
198
        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);
199
200
201
    }

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

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

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

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

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

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

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

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

278
        _logViewer->init();
279
280
281
    }

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

285
        _logViewer->deinit();
286
287
    }

288
    void MainWindow::addVisualizationPipelineWidget(const std::string& name, QWidget* canvas) {
289
        MdiDockableWindow* dockableWindow = _mdiArea->addWidget(canvas);
290
        QString windowTitle = QString::fromStdString(name);
291
292
        dockableWindow->setWindowTitle(windowTitle);
        dockableWindow->show();
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
    }

    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;
311
312
    }

313
314
315
316
317
318
319
320
321
322
    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);
    }

323
324
325
326
    void MainWindow::onRebuildShadersClicked() {
        _application->rebuildAllShadersFromFiles();
    }

327
328
329
330
331
332
333
    void MainWindow::onLuaCommandExecuted(const QString& cmd) {
        // FIXME: so far just a hack
        if (! _application->_pipelines.empty()){
            _application->_pipelines.front()._luaVmState->execString(cmd.toStdString());
        }
    }

334
}