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.7 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
46
47
#include <QFileDialog>

#include <fstream>

#include "scripting/luagen/properties/propertycollectionlua.h"
#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
    {
71
        cgtAssert(_application != 0, "Application must not be 0.");
72
        ui.setupUi(this);
73
74
75
76
        setup();
    }

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

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

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

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

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

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

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

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
        _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

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

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

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

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

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

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

156
157
158
159
#ifdef CAMPVIS_HAS_SCRIPTING
        _scriptingConsoleWidget = new ScriptingWidget(this);
        ui.scriptingConsoleDock->setWidget(_scriptingConsoleWidget);
        connect(_scriptingConsoleWidget, SIGNAL(s_commandExecuted(const QString&)), this, SLOT(onLuaCommandExecuted(const QString&)));
160
161
#else
        ui.scriptingConsoleDock->setVisible(false);
162
#endif
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
163

164
        _dcInspectorWidget = new DataContainerInspectorWidget();
165
        this->populateMainMenu();
166

167
168
        qRegisterMetaType< std::vector<DataContainer*> >("std::vector<DataContainer*>");
        qRegisterMetaType< std::vector<AbstractPipeline*> >("std::vector<AbstractPipeline*>");
169
        connect(
170
171
            this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)), 
            _pipelineWidget, SLOT(update(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)));
172
173
174
175
        connect(
            _pipelineWidget, SIGNAL(clicked(const QModelIndex&)), 
            this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&)));
        connect(
176
177
            this, SIGNAL(updatePropCollectionWidget(HasPropertyCollection*, DataContainer*)),
            _propCollectionWidget, SLOT(updatePropCollection(HasPropertyCollection*, DataContainer*)));
178
179
180
181
182
183
        connect(
            _btnExecute, SIGNAL(clicked()), 
            this, SLOT(onBtnExecuteClicked()));
        connect(
            _btnShowDataContainerInspector, SIGNAL(clicked()), 
            this, SLOT(onBtnShowDataContainerInspectorClicked()));
184
185
186
187
        connect(
            _btnPipelineFactory, SIGNAL(clicked()), 
            this, SLOT(onBtnPipelineFactoryClicked()));

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

191
192
    }

193
    void MainWindow::populateMainMenu() {
194
        // Populate the file menu
195
196
        QMenuBar* menuBar = this->menuBar();
        QMenu* fileMenu = menuBar->addMenu(tr("&File"));
197
        fileMenu->addAction(tr("&Rebuild all Shaders from File"), this, SLOT(onRebuildShadersClicked()), QKeySequence(Qt::CTRL + Qt::Key_F5));
198
199
        fileMenu->addAction(tr("&Quit"), qApp, SLOT(closeAllWindows()), QKeySequence(Qt::CTRL + Qt::Key_Q));

200
201
202
203
204
205
206
207
208
209
        // 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());
210
211
    }

212
213
214
215
216
217
218
219
220
    bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
        if (watched == _pipelinePropertiesWidget && event->type() == QEvent::Resize) {
            _pipelinePropertiesScrollArea->setMinimumWidth(_pipelinePropertiesWidget->minimumSizeHint().width() +
                                                           _pipelinePropertiesScrollArea->verticalScrollBar()->width());
        }

        return false;
    }

221
    void MainWindow::onPipelinesChanged() {
222
223
224
225
        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);
226
227
228
    }

    void MainWindow::onDataContainersChanged() {
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
236
237
238
    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);
239
240
            if (item.isValid()) {
                HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>());
241

242
                if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(ptr)) {
243
                    _selectedPipeline = pipeline;
244
                    _selectedProcessor = 0;
245
                    _selectedDataContainer = &pipeline->getDataContainer();
246
247
248
249
250
251
252
253
                }
                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;
254
                        _selectedDataContainer = &pipeline->getDataContainer();
255
                    }
256
257
                }

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

260
261
262
            }
            else {
                emit updatePropCollectionWidget(0, 0);
263
                _selectedDataContainer = 0;
264
            }
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
265

266
267
        }
        else {
268
            emit updatePropCollectionWidget(0, 0);
269
            _selectedDataContainer = 0;
270
271
272
        }
    }

273
    QSize MainWindow::sizeHint() const {
274
        return QSize(1000, 600);
275
276
    }

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

Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
290
291
292
293
294
295
296
297
    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) {
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
            _application->getLuaVmState()->execFile(filename.toStdString());
            //std::ifstream file;
            //file.open(filename.toStdString());
            //if (!file.fail()) {
            //    _application->getLuaVmState()->execString("proc = pipelines[\"" +_selectedPipeline->getName()+"\"]");
            //
            //    std::string script;
            //    while (!file.eof()) {
            //        script = "";
            //        std::getline(file, script);
            //        if (script == "")
            //            continue;
            //
            //        printf("%s\n", script.c_str());
            //        //if (_application->getLuaVmState() != nullptr) {
            //        _application->getLuaVmState()->execString(script.c_str());
            //        //}
            //    }
            //    printf("Load lua script");
            //}
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
318
319
320
321
322
323
324
325
326
327
328
329
330
331
        }
#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) {
332
333
334
                PropertyCollectionLua *_pcLua = new PropertyCollectionLua();
                
                std::string pipeScript = "pipeline = pipelines[\"" + _selectedPipeline->getName()+"\"]\n\n";
335
                for (int i = 1; i < _selectedPipeline->getProcessors().size(); i++) {
336
337
338
339
                    pipeScript += "proc = pipeline:getProcessor(" + StringUtils::toString(i) + ")\n";
                    AbstractProcessor *proc = _selectedPipeline->getProcessor(i);

                    _pcLua->updatePropCollection(proc, &_selectedPipeline->getDataContainer());
340
                    std::string res = _pcLua->getLuaScript("", "proc:");
341
342
                    pipeScript += res;
                    std::cout << "\n\n" + pipeScript + "\n\n";
343
344
                }
                if (pipeScript != "pipeline = pipelines[\"" + _selectedPipeline->getName()+"\"]\n\n") {
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
345
346
                    std::ofstream file;
                    file.open(filename.toStdString());
347
                    file << pipeScript.c_str();
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
348
349
350
                    file.close();
                    printf("Saved Lua script");
                }
351
352
                
                delete _pcLua;
Hossain Mahmud's avatar
stuck!    
Hossain Mahmud committed
353
354
355
356
357
            }
        }
#endif
    }

358
359
    void MainWindow::onBtnShowDataContainerInspectorClicked() {
        if (_selectedPipeline != 0) {
360
361
362
            if (_dcInspectorWindow == 0) {
                _dcInspectorWindow = _mdiArea->addWidget(_dcInspectorWidget);
                _dcInspectorWindow->setWindowTitle(tr("Data Container Inspector"));
363
364
            }

365
            _dcInspectorWidget->setDataContainer(&(_selectedPipeline->getDataContainer()));
366
367
            _dcInspectorWindow->show();
            _dcInspectorWindow->activateWindow();
368
369
370
        }
    }

371
    void MainWindow::init() {
372
373
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->init();
374

375
        _logViewer->init();
376
377
378

        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->init();
379
380
381
    }

    void MainWindow::deinit() {
382
383
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->deinit();
384

385
        _logViewer->deinit();
386
387
388

        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->deinit();
389
390
    }

391
    MdiDockableWindow * MainWindow::addVisualizationPipelineWidget(const std::string& name, QWidget* canvas) {
392
        MdiDockableWindow* dockableWindow = _mdiArea->addWidget(canvas);
393
        QString windowTitle = QString::fromStdString(name);
394
395
        dockableWindow->setWindowTitle(windowTitle);
        dockableWindow->show();
396
        return dockableWindow;
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
    }

    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;
415
416
    }

417
418
419
420
421
422
423
424
425
426
    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);
    }

427
428
429
430
    void MainWindow::onRebuildShadersClicked() {
        _application->rebuildAllShadersFromFiles();
    }

431
    void MainWindow::onLuaCommandExecuted(const QString& cmd) {
432
433
#ifdef CAMPVIS_HAS_SCRIPTING
        if (_application->getLuaVmState() != nullptr) {
434
            cgt::OpenGLJobProcessor::ScopedSynchronousGlJobExecution jobGuard;
435
            _application->getLuaVmState()->execString(cmd.toStdString());
436
        }
437
#endif
438
439
    }

440
}