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 18.4 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>
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
42
43
44
45
#include <QFileDialog>

#include <fstream>

Hossain Mahmud's avatar
Hossain Mahmud committed
46
#include "scripting/luagen/properties/propertycollectionluascriptgenerator.h"
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
47
#include "scripting/luagen/properties/abstractpropertylua.h"
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
48

49

schultezub's avatar
schultezub committed
50
namespace campvis {
51

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

    MainWindow::~MainWindow() {
schultezub's avatar
schultezub committed
78
        _application->s_PipelinesChanged.disconnect(this);
79
        _application->s_DataContainersChanged.disconnect(this);
80
        delete _dcInspectorWidget;
81
82
83
    }

    void MainWindow::setup() {
84
85
        qRegisterMetaType<QtDataHandle>("QtDataHandle");

86
        setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
87
        setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
88
        setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
89
        setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
90

91
        setTabPosition(Qt::TopDockWidgetArea, QTabWidget::North);
92

93
        _mdiArea = new MdiDockArea();
94
95
96
        _mdiArea->tileSubWindows();
        setCentralWidget(_mdiArea);

97
98
99
100
101
102
103
104
105
106
107
108
        _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);

109
        _pipelineWidget = new PipelineTreeWidget(this);
110
111
112
        _containerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
        _cwLayout->addWidget(_pipelineWidget, 1, 0, 1, 2);

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
        _btnExecute = new QPushButton("Execute Selected Pipeline/Processor", _containerWidget);
        _cwLayout->addWidget(_btnExecute, 2, 0, 1, 2);

        _btnShowDataContainerInspector = new QPushButton("Inspect DataContainer of Selected Pipeline", _containerWidget);
        _cwLayout->addWidget(_btnShowDataContainerInspector, 3, 0, 1, 2);

#ifdef CAMPVIS_HAS_SCRIPTING
        _btnLuaLoad = new QPushButton("Load Script", _containerWidget);
        _cwLayout->addWidget(_btnLuaLoad, 4, 0, 1, 2);
        _btnLuaSave = new QPushButton("Save Script", _containerWidget);
        _cwLayout->addWidget(_btnLuaSave, 5, 0, 1, 2);
        connect(
            _btnLuaLoad, SIGNAL(clicked()), 
            this, SLOT(onBtnLuaLoadClicked()));
        connect(
            _btnLuaSave, SIGNAL(clicked()), 
            this, SLOT(onBtnLuaSaveClicked()));
#else
#endif

133
134
        _containerWidget->setLayout(_cwLayout);
        ui.pipelineTreeDock->setWidget(_containerWidget);
135

136
        _pipelinePropertiesScrollArea = new QScrollArea(this);
137
138
139
140
        _pipelinePropertiesScrollArea->setWidgetResizable(true);
        _pipelinePropertiesScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        _pipelinePropertiesScrollArea->setFrameStyle(QScrollArea::NoFrame);

141
        _pipelinePropertiesWidget = new QWidget(_pipelinePropertiesScrollArea);
142
143
144
        _pipelinePropertiesWidget->installEventFilter(this);
        _pipelinePropertiesScrollArea->setWidget(_pipelinePropertiesWidget);
        ui.pipelinePropertiesDock->setWidget(_pipelinePropertiesScrollArea);
145

146
        QVBoxLayout* rightLayout = new QVBoxLayout(_pipelinePropertiesWidget);
147
        rightLayout->setSpacing(4);
148
        _pipelinePropertiesWidget->setLayout(rightLayout);
149

150
        _propCollectionWidget = new PropertyCollectionWidget(this);
151
        rightLayout->addWidget(_propCollectionWidget);
152
        rightLayout->addStretch();
153

154
        _logViewer = new LogViewerWidget(this);
155
        ui.logViewerDock->setWidget(_logViewer);
156

157
158
159
160
#ifdef CAMPVIS_HAS_SCRIPTING
        _scriptingConsoleWidget = new ScriptingWidget(this);
        ui.scriptingConsoleDock->setWidget(_scriptingConsoleWidget);
        connect(_scriptingConsoleWidget, SIGNAL(s_commandExecuted(const QString&)), this, SLOT(onLuaCommandExecuted(const QString&)));
161
162
#else
        ui.scriptingConsoleDock->setVisible(false);
163
164
#endif

165
        _workflowWidget = new WorkflowControllerWidget(_application, this);
166
        ui.workflowDock->setWidget(_workflowWidget);
167
        ui.workflowDock->setVisible(! _application->_workflows.empty());
168

169
        _dcInspectorWidget = new DataContainerInspectorWidget();
170
        this->populateMainMenu();
171

172
173
        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
174
        qRegisterMetaType< std::map<AbstractProperty*, QWidget*>::iterator >("PropertyWidgetMapIterator");
175
        connect(
176
177
            this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)), 
            _pipelineWidget, SLOT(update(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)));
178
179
180
181
        connect(
            _pipelineWidget, SIGNAL(clicked(const QModelIndex&)), 
            this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&)));
        connect(
182
183
            this, SIGNAL(updatePropCollectionWidget(HasPropertyCollection*, DataContainer*)),
            _propCollectionWidget, SLOT(updatePropCollection(HasPropertyCollection*, DataContainer*)));
184
185
186
187
188
189
        connect(
            _btnExecute, SIGNAL(clicked()), 
            this, SLOT(onBtnExecuteClicked()));
        connect(
            _btnShowDataContainerInspector, SIGNAL(clicked()), 
            this, SLOT(onBtnShowDataContainerInspectorClicked()));
190
191
192
193
        connect(
            _btnPipelineFactory, SIGNAL(clicked()), 
            this, SLOT(onBtnPipelineFactoryClicked()));

194
        _application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
195
        _application->s_DataContainersChanged.connect(this, &MainWindow::onDataContainersChanged);
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
196

197
198
    }

199
    void MainWindow::populateMainMenu() {
200
        // Populate the file menu
201
202
        QMenuBar* menuBar = this->menuBar();
        QMenu* fileMenu = menuBar->addMenu(tr("&File"));
203
        fileMenu->addAction(tr("&Rebuild all Shaders from File"), this, SLOT(onRebuildShadersClicked()), QKeySequence(Qt::CTRL + Qt::Key_F5));
204
205
        fileMenu->addAction(tr("&Quit"), qApp, SLOT(closeAllWindows()), QKeySequence(Qt::CTRL + Qt::Key_Q));

206
207
208
209
210
211
212
213
214
215
        // 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());
216
        toolsMenu->addAction(ui.workflowDock->toggleViewAction());
217
218
    }

219
220
221
222
223
224
225
226
227
    bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
        if (watched == _pipelinePropertiesWidget && event->type() == QEvent::Resize) {
            _pipelinePropertiesScrollArea->setMinimumWidth(_pipelinePropertiesWidget->minimumSizeHint().width() +
                                                           _pipelinePropertiesScrollArea->verticalScrollBar()->width());
        }

        return false;
    }

228
    void MainWindow::onPipelinesChanged() {
229
230
231
232
        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);
233
234
235
    }

    void MainWindow::onDataContainersChanged() {
236
237
238
239
        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);
240
241
    }

242
243
244
245
    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);
246
247
            if (item.isValid()) {
                HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>());
248

249
                if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(ptr)) {
250
                    _selectedPipeline = pipeline;
251
                    _selectedProcessor = 0;
252
                    _selectedDataContainer = &pipeline->getDataContainer();
253
254
255
256
257
258
259
260
                }
                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;
261
                        _selectedDataContainer = &pipeline->getDataContainer();
262
                    }
263
264
                }

265
                emit updatePropCollectionWidget(ptr, &_selectedPipeline->getDataContainer());
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
266

267
268
269
            }
            else {
                emit updatePropCollectionWidget(0, 0);
270
                _selectedDataContainer = 0;
271
            }
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
272

273
274
        }
        else {
275
            emit updatePropCollectionWidget(0, 0);
276
            _selectedDataContainer = 0;
277
278
279
        }
    }

280
    QSize MainWindow::sizeHint() const {
281
        return QSize(1000, 600);
282
283
    }

284
285
286
287
    void MainWindow::onBtnExecuteClicked() {
        if (_selectedProcessor != 0 && _selectedPipeline != 0) {
            // this is not as trivial as it seems:
            // We need the pipeline, probably an OpenGL context...
288
            _selectedProcessor->invalidate(AbstractProcessor::INVALID_RESULT);
289
290
        }
        else if (_selectedPipeline != 0) {
291
292
293
            for (std::vector<AbstractProcessor*>::const_iterator it = _selectedPipeline->getProcessors().begin(); it != _selectedPipeline->getProcessors().end(); ++it) {
                (*it)->invalidate(AbstractProcessor::INVALID_RESULT);
            }
294
295
296
        }
    }

Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
297
298
299
300
301
302
303
304
    void MainWindow::onBtnLuaLoadClicked() {
#ifdef CAMPVIS_HAS_SCRIPTING
        const QString dialogCaption = QString::fromStdString("Select File");
        const QString directory = QString::fromStdString(".");
        const QString fileFilter = tr("All files (*)");

        QString filename = QFileDialog::getOpenFileName(QWidget::parentWidget(), dialogCaption, directory, fileFilter);
        if (filename != nullptr && _application->getLuaVmState() != nullptr) {
305
            _application->getLuaVmState()->execFile(filename.toStdString());
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
306
307
308
309
310
311
312
313
314
315
316
317
318
319
        }
#endif
    }

    void MainWindow::onBtnLuaSaveClicked() {
#ifdef CAMPVIS_HAS_SCRIPTING
        const QString dialogCaption = QString::fromStdString("Save File as");
        const QString directory = QString::fromStdString(".");
        const QString fileFilter = tr("All files (*)");

        QString filename = QFileDialog::getSaveFileName(QWidget::parentWidget(), dialogCaption, directory, fileFilter);

        if (filename != nullptr) {
            if (_selectedProcessor != 0 && _selectedPipeline != 0) {
Hossain Mahmud's avatar
Hossain Mahmud committed
320
                PropertyCollectionLuaScriptGenerator* _pcLua = new PropertyCollectionLuaScriptGenerator();
321
322
                
                std::string pipeScript = "pipeline = pipelines[\"" + _selectedPipeline->getName()+"\"]\n\n";
323
                for (size_t i = 0; i < _selectedPipeline->getProcessors().size(); i++) {
324
                    pipeScript += "proc = pipeline:getProcessor(" + StringUtils::toString(i) + ")\n";
325
                    AbstractProcessor* proc = _selectedPipeline->getProcessor(int(i));
326
327

                    _pcLua->updatePropCollection(proc, &_selectedPipeline->getDataContainer());
Hossain Mahmud's avatar
Hossain Mahmud committed
328
                    std::string res = _pcLua->getLuaScript(std::string(""), std::string("proc:"));
329
                    pipeScript += res;
330
331
                }
                if (pipeScript != "pipeline = pipelines[\"" + _selectedPipeline->getName()+"\"]\n\n") {
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
332
333
                    std::ofstream file;
                    file.open(filename.toStdString());
334
                    file << pipeScript.c_str();
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
335
336
                    file.close();
                }
337
338
                
                delete _pcLua;
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
339
340
341
342
343
            }
        }
#endif
    }

344
345
    void MainWindow::onBtnShowDataContainerInspectorClicked() {
        if (_selectedPipeline != 0) {
346
347
348
            if (_dcInspectorWindow == 0) {
                _dcInspectorWindow = _mdiArea->addWidget(_dcInspectorWidget);
                _dcInspectorWindow->setWindowTitle(tr("Data Container Inspector"));
349
350
            }

351
            _dcInspectorWidget->setDataContainer(&(_selectedPipeline->getDataContainer()));
352
353
            _dcInspectorWindow->show();
            _dcInspectorWindow->activateWindow();
354
355
356
        }
    }

357
    void MainWindow::init() {
358
359
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->init();
360

361
        _logViewer->init();
362
363
364

        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->init();
365
366
367
    }

    void MainWindow::deinit() {
368
369
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->deinit();
370

371
        _logViewer->deinit();
372
373
374

        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->deinit();
375
376
    }

377
    MdiDockableWindow * MainWindow::addVisualizationPipelineWidget(const std::string& name, QWidget* canvas) {
378
        MdiDockableWindow* dockableWindow = _mdiArea->addWidget(canvas);
379
        QString windowTitle = QString::fromStdString(name);
380
381
        dockableWindow->setWindowTitle(windowTitle);
        dockableWindow->show();
382
        return dockableWindow;
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
    }

    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;
401
402
    }

403
404
405
406
407
408
409
410
411
412
    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);
    }

413
414
415
416
    void MainWindow::onRebuildShadersClicked() {
        _application->rebuildAllShadersFromFiles();
    }

417
    void MainWindow::onLuaCommandExecuted(const QString& cmd) {
418
419
#ifdef CAMPVIS_HAS_SCRIPTING
        if (_application->getLuaVmState() != nullptr) {
420
            cgt::OpenGLJobProcessor::ScopedSynchronousGlJobExecution jobGuard;
421
            _application->getLuaVmState()->execString(cmd.toStdString());
422
        }
423
#endif
424
425
    }

426
427
428
429
430
    void MainWindow::setWorkflow(AbstractWorkflow* w) {
        ui.workflowDock->setVisible(true);
        _workflowWidget->setWorkflow(w);
    }

431
}