mainwindow.cpp 20.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-2015, 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/pipeline/pipelinefactory.h"
#include "core/pipeline/processorfactory.h"
40
#include "core/tools/stringutils.h"
41

42
#include <QScrollBar>
Hossain Mahmud's avatar
Hossain Mahmud committed
43 44 45 46
#include <QFileDialog>

#include <fstream>

47 48
#ifdef CAMPVIS_HAS_SCRIPTING
#include "scripting/glue/globalluatable.h"
Hossain Mahmud's avatar
Hossain Mahmud committed
49
#include "scripting/luagen/properties/propertycollectionluascriptgenerator.h"
Hossain Mahmud's avatar
Hossain Mahmud committed
50
#include "scripting/luagen/properties/abstractpropertylua.h"
51
#include "application/gui/luatablewidget.h"
52
#include "application/gui/scriptingwidget.h"
53
#endif
54

schultezub's avatar
schultezub committed
55
namespace campvis {
56

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

    MainWindow::~MainWindow() {
schultezub's avatar
schultezub committed
84
        _application->s_PipelinesChanged.disconnect(this);
85
        _application->s_DataContainersChanged.disconnect(this);
86
        delete _dcInspectorWidget;
87 88 89
    }

    void MainWindow::setup() {
90 91
        qRegisterMetaType<QtDataHandle>("QtDataHandle");

92
        setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
93
        setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
94 95 96
#ifdef CAMPVIS_HAS_SCRIPTING
        setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
#else
97
        setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
98
#endif
99
        setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
100

101
        setTabPosition(Qt::TopDockWidgetArea, QTabWidget::North);
102

103
        _mdiArea = new MdiDockArea();
104 105 106
        _mdiArea->tileSubWindows();
        setCentralWidget(_mdiArea);

107 108 109
        _containerWidget = new QWidget(this);
        QGridLayout* _cwLayout = new QGridLayout(_containerWidget);

110
        int rowPosition = 0;
111 112 113 114
        _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));
115
        _cwLayout->addWidget(_cbPipelineFactory, rowPosition, 0);
116 117

        _btnPipelineFactory = new QPushButton("Add Pipeline", _containerWidget);
118
        _cwLayout->addWidget(_btnPipelineFactory, rowPosition++, 1);
119

120
        _pipelineWidget = new PipelineTreeWidget(this);
121
        _containerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
122
        _cwLayout->addWidget(_pipelineWidget, rowPosition++, 0, 1, 2);
123

124
        _btnExecute = new QPushButton("Execute Selected Pipeline/Processor", _containerWidget);
125 126 127 128 129 130 131 132 133 134
        _cwLayout->addWidget(_btnExecute, rowPosition++, 0, 1, 2);

        _cbProcessorFactory = new QComboBox(_containerWidget);
        std::vector<std::string> registeredProcessors = ProcessorFactory::getRef().getRegisteredProcessors();
        for (std::vector<std::string>::const_iterator it = registeredProcessors.begin(); it != registeredProcessors.end(); ++it)
            _cbProcessorFactory->addItem(QString::fromStdString(*it));
        _cwLayout->addWidget(_cbProcessorFactory, rowPosition, 0);

        _btnProcessorFactory = new QPushButton("Add Processor", _containerWidget);
        _cwLayout->addWidget(_btnProcessorFactory, rowPosition++, 1);
135 136

        _btnShowDataContainerInspector = new QPushButton("Inspect DataContainer of Selected Pipeline", _containerWidget);
137
        _cwLayout->addWidget(_btnShowDataContainerInspector, rowPosition++, 0, 1, 2);
138 139 140

#ifdef CAMPVIS_HAS_SCRIPTING
        _btnLuaLoad = new QPushButton("Load Script", _containerWidget);
141
        _cwLayout->addWidget(_btnLuaLoad, rowPosition++, 0, 1, 2);
142
        _btnLuaSave = new QPushButton("Save Script", _containerWidget);
143
        _cwLayout->addWidget(_btnLuaSave, rowPosition++, 0, 1, 2);
144 145 146 147 148 149 150 151 152
        connect(
            _btnLuaLoad, SIGNAL(clicked()), 
            this, SLOT(onBtnLuaLoadClicked()));
        connect(
            _btnLuaSave, SIGNAL(clicked()), 
            this, SLOT(onBtnLuaSaveClicked()));
#else
#endif

153 154
        _containerWidget->setLayout(_cwLayout);
        ui.pipelineTreeDock->setWidget(_containerWidget);
155

156
        _pipelinePropertiesScrollArea = new QScrollArea(this);
157 158 159 160
        _pipelinePropertiesScrollArea->setWidgetResizable(true);
        _pipelinePropertiesScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        _pipelinePropertiesScrollArea->setFrameStyle(QScrollArea::NoFrame);

161
        _pipelinePropertiesWidget = new QWidget(_pipelinePropertiesScrollArea);
162 163 164
        _pipelinePropertiesWidget->installEventFilter(this);
        _pipelinePropertiesScrollArea->setWidget(_pipelinePropertiesWidget);
        ui.pipelinePropertiesDock->setWidget(_pipelinePropertiesScrollArea);
165

166
        QVBoxLayout* rightLayout = new QVBoxLayout(_pipelinePropertiesWidget);
167
        rightLayout->setSpacing(4);
168
        _pipelinePropertiesWidget->setLayout(rightLayout);
169

170
        _propCollectionWidget = new PropertyCollectionWidget(this);
171
        rightLayout->addWidget(_propCollectionWidget);
172
        rightLayout->addStretch();
173

174
        _logViewer = new LogViewerWidget(this);
175
        ui.logViewerDock->setWidget(_logViewer);
176

177 178 179 180
#ifdef CAMPVIS_HAS_SCRIPTING
        _scriptingConsoleWidget = new ScriptingWidget(this);
        ui.scriptingConsoleDock->setWidget(_scriptingConsoleWidget);
        connect(_scriptingConsoleWidget, SIGNAL(s_commandExecuted(const QString&)), this, SLOT(onLuaCommandExecuted(const QString&)));
181 182 183 184

        _luaTreeWidget = new LuaTableTreeWidget(this);
        ui.scriptingInspectorDock->setWidget(_luaTreeWidget);

185 186
#else
        ui.scriptingConsoleDock->setVisible(false);
187
        ui.scriptingInspectorDock->setVisible(false);
188 189
#endif

190
        _workflowWidget = new WorkflowControllerWidget(_application, this);
191
        ui.workflowDock->setWidget(_workflowWidget);
192
        ui.workflowDock->setVisible(! _application->_workflows.empty());
193

194
        _dcInspectorWidget = new DataContainerInspectorWidget();
195
        this->populateMainMenu();
196

197 198
        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
199
        qRegisterMetaType< std::map<AbstractProperty*, QWidget*>::iterator >("PropertyWidgetMapIterator");
200
        connect(
201 202
            this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)), 
            _pipelineWidget, SLOT(update(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)));
203
        connect(
204 205
            _pipelineWidget, SIGNAL(itemChanged(const QModelIndex&)), 
            this, SLOT(onPipelineWidgetItemChanged(const QModelIndex&)));
206
        connect(
207 208
            this, SIGNAL(updatePropCollectionWidget(HasPropertyCollection*, DataContainer*)),
            _propCollectionWidget, SLOT(updatePropCollection(HasPropertyCollection*, DataContainer*)));
209 210 211 212 213 214
        connect(
            _btnExecute, SIGNAL(clicked()), 
            this, SLOT(onBtnExecuteClicked()));
        connect(
            _btnShowDataContainerInspector, SIGNAL(clicked()), 
            this, SLOT(onBtnShowDataContainerInspectorClicked()));
215 216 217
        connect(
            _btnPipelineFactory, SIGNAL(clicked()), 
            this, SLOT(onBtnPipelineFactoryClicked()));
218 219 220
        connect(
            _btnProcessorFactory, SIGNAL(clicked()), 
            this, SLOT(onBtnProcessorFactoryClicked()));
221

222
        _application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
223
        _application->s_DataContainersChanged.connect(this, &MainWindow::onDataContainersChanged);
Hossain Mahmud's avatar
Hossain Mahmud committed
224

225 226
    }

227
    void MainWindow::populateMainMenu() {
228
        // Populate the file menu
229 230
        QMenuBar* menuBar = this->menuBar();
        QMenu* fileMenu = menuBar->addMenu(tr("&File"));
231
        fileMenu->addAction(tr("&Rebuild all Shaders from File"), this, SLOT(onRebuildShadersClicked()), QKeySequence(Qt::CTRL + Qt::Key_F5));
232 233
        fileMenu->addAction(tr("&Quit"), qApp, SLOT(closeAllWindows()), QKeySequence(Qt::CTRL + Qt::Key_Q));

234 235 236 237 238 239 240 241 242 243
        // 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());
244
        toolsMenu->addAction(ui.workflowDock->toggleViewAction());
245 246
    }

247 248 249 250 251 252 253 254 255
    bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
        if (watched == _pipelinePropertiesWidget && event->type() == QEvent::Resize) {
            _pipelinePropertiesScrollArea->setMinimumWidth(_pipelinePropertiesWidget->minimumSizeHint().width() +
                                                           _pipelinePropertiesScrollArea->verticalScrollBar()->width());
        }

        return false;
    }

256
    void MainWindow::onPipelinesChanged() {
257
        emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
258 259 260
    }

    void MainWindow::onDataContainersChanged() {
261
        emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
262 263
    }

264
    void MainWindow::onPipelineWidgetItemChanged(const QModelIndex& index) {
265 266 267
        if (index.isValid()) {
            // Yak, this is so ugly - another reason why GUI programming sucks...
            QVariant item = index.data(Qt::UserRole);
268 269
            if (item.isValid()) {
                HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>());
270

271
                if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(ptr)) {
272
                    _selectedPipeline = pipeline;
273
                    _selectedProcessor = 0;
274
                    _selectedDataContainer = &pipeline->getDataContainer();
275 276 277 278 279 280 281 282
                }
                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;
283
                        _selectedDataContainer = &pipeline->getDataContainer();
284
                    }
285 286
                }

287
                emit updatePropCollectionWidget(ptr, &_selectedPipeline->getDataContainer());
Hossain Mahmud's avatar
Hossain Mahmud committed
288

289 290 291
            }
            else {
                emit updatePropCollectionWidget(0, 0);
292
                _selectedDataContainer = 0;
293
            }
Hossain Mahmud's avatar
Hossain Mahmud committed
294

295 296
        }
        else {
297
            emit updatePropCollectionWidget(0, 0);
298
            _selectedDataContainer = 0;
299 300 301
        }
    }

302
    QSize MainWindow::sizeHint() const {
303
        return QSize(1000, 600);
304 305
    }

306 307 308 309
    void MainWindow::onBtnExecuteClicked() {
        if (_selectedProcessor != 0 && _selectedPipeline != 0) {
            // this is not as trivial as it seems:
            // We need the pipeline, probably an OpenGL context...
310
            _selectedProcessor->invalidate(AbstractProcessor::INVALID_RESULT);
311 312
        }
        else if (_selectedPipeline != 0) {
313 314 315
            for (std::vector<AbstractProcessor*>::const_iterator it = _selectedPipeline->getProcessors().begin(); it != _selectedPipeline->getProcessors().end(); ++it) {
                (*it)->invalidate(AbstractProcessor::INVALID_RESULT);
            }
316 317 318
        }
    }

Hossain Mahmud's avatar
Hossain Mahmud committed
319 320 321 322
    void MainWindow::onBtnLuaLoadClicked() {
#ifdef CAMPVIS_HAS_SCRIPTING
        const QString dialogCaption = QString::fromStdString("Select File");
        const QString directory = QString::fromStdString(".");
323
        const QString fileFilter = tr("Lua Scripts (*.lua)");
Hossain Mahmud's avatar
Hossain Mahmud committed
324 325 326

        QString filename = QFileDialog::getOpenFileName(QWidget::parentWidget(), dialogCaption, directory, fileFilter);
        if (filename != nullptr && _application->getLuaVmState() != nullptr) {
327
            _application->getLuaVmState()->execFile(filename.toStdString());
Hossain Mahmud's avatar
Hossain Mahmud committed
328 329 330 331 332 333 334 335
        }
#endif
    }

    void MainWindow::onBtnLuaSaveClicked() {
#ifdef CAMPVIS_HAS_SCRIPTING
        const QString dialogCaption = QString::fromStdString("Save File as");
        const QString directory = QString::fromStdString(".");
336
        const QString fileFilter = tr("Lua Scripts (*.lua)");
Hossain Mahmud's avatar
Hossain Mahmud committed
337 338 339 340 341

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

        if (filename != nullptr) {
            if (_selectedProcessor != 0 && _selectedPipeline != 0) {
342
                PropertyCollectionLuaScriptGenerator pcLua;
343
                
344
                std::string pipeScript = "pipeline = pipelines[\"" + _selectedPipeline->getName()+"\"]\n";
345
                for (size_t i = 0; i < _selectedPipeline->getProcessors().size(); i++) {
346
                    pipeScript += "\n-- Restoring property state for " + _selectedPipeline->getProcessor(i)->getName() + " processor\n";
347
                    pipeScript += "proc = pipeline:getProcessor(" + StringUtils::toString(i) + ")\n";
348
                    AbstractProcessor* proc = _selectedPipeline->getProcessor(i);
349

350 351
                    pcLua.updatePropCollection(proc, &_selectedPipeline->getDataContainer());
                    std::string res = pcLua.getLuaScript(std::string(""), std::string("proc:"));
352
                    pipeScript += res;
353
                }
354 355 356 357 358

                std::ofstream file;
                file.open(filename.toStdString(), std::ofstream::out |std::ofstream::trunc);
                file << pipeScript.c_str();
                file.close();
Hossain Mahmud's avatar
Hossain Mahmud committed
359 360 361 362 363
            }
        }
#endif
    }

364 365
    void MainWindow::onBtnShowDataContainerInspectorClicked() {
        if (_selectedPipeline != 0) {
366
            // if there is no existing inspector window, create one
367 368 369
            if (_dcInspectorWindow == 0) {
                _dcInspectorWindow = _mdiArea->addWidget(_dcInspectorWidget);
                _dcInspectorWindow->setWindowTitle(tr("Data Container Inspector"));
370 371
            }

372
            _dcInspectorWidget->setDataContainer(&(_selectedPipeline->getDataContainer()));
373 374
            _dcInspectorWindow->show();
            _dcInspectorWindow->activateWindow();
375

376
            //_dcInspectorWindow->detachDockedWindow();
377 378 379
        }
    }

380
    void MainWindow::init() {
381 382
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->init();
383

384
        _logViewer->init();
385

386
#ifdef CAMPVIS_HAS_SCRIPTING
387 388
        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->init();
389
#endif
390 391 392
    }

    void MainWindow::deinit() {
393 394
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->deinit();
395

396
        _logViewer->deinit();
397

398
#ifdef CAMPVIS_HAS_SCRIPTING
399 400
        if (_scriptingConsoleWidget)
            _scriptingConsoleWidget->deinit();
401
#endif
402 403
    }

404
    MdiDockableWindow * MainWindow::addVisualizationPipelineWidget(const std::string& name, QWidget* canvas) {
405
        MdiDockableWindow* dockableWindow = _mdiArea->addWidget(canvas);
406
        QString windowTitle = QString::fromStdString(name);
407 408
        dockableWindow->setWindowTitle(windowTitle);
        dockableWindow->show();
409
        return dockableWindow;
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
    }

    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;
428 429
    }

430 431 432 433 434 435
    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));
        }
436
        AbstractPipeline* p = PipelineFactory::getRef().createPipeline(name, *dc);
437
        _application->addPipeline(p);
438 439
    }

440 441 442 443 444
    void MainWindow::onBtnProcessorFactoryClicked() {
        std::string name = this->_cbProcessorFactory->currentText().toStdString();
        if (_selectedPipeline == nullptr) 
            return;

Hossain Mahmud's avatar
Hossain Mahmud committed
445 446 447
        IVec2Property temp = _selectedPipeline->getCanvasSize();
        IVec2Property *viewPort = new IVec2Property(temp.getName(), temp.getTitle(), temp.getValue(), temp.getMinValue(), temp.getMaxValue(), temp.getStepValue());
        AbstractProcessor* p = ProcessorFactory::getRef().createProcessor(name, viewPort);
448 449
        if (p == nullptr)
            return;
450
        
451 452 453
        GLJobProc.enqueueJobBlocking([&]() {
            p->init();
        });
454

455
        _selectedPipeline->addProcessor(p);
456
        emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
457 458
    }

459 460 461 462
    void MainWindow::onRebuildShadersClicked() {
        _application->rebuildAllShadersFromFiles();
    }

463
    void MainWindow::onLuaCommandExecuted(const QString& cmd) {
464 465
#ifdef CAMPVIS_HAS_SCRIPTING
        if (_application->getLuaVmState() != nullptr) {
466 467 468
            GLJobProc.enqueueJobBlocking([&]() {
                _application->getLuaVmState()->execString(cmd.toStdString());
            });
469 470 471

            _application->getLuaVmState()->getGlobalTable()->updateValueMap();
            _scriptingConsoleWidget->_editCommand->setCompleter(new LuaCompleter(_application->getLuaVmState(), _scriptingConsoleWidget->_editCommand));
472
            _luaTreeWidget->update(_application->getLuaVmState(), LuaTreeItem::FULL_MODEL);
473
        }
474
#endif
475 476
    }

477 478 479 480 481
    void MainWindow::setWorkflow(AbstractWorkflow* w) {
        ui.workflowDock->setVisible(true);
        _workflowWidget->setWorkflow(w);
    }

482 483 484 485 486 487 488 489 490
    void MainWindow::enableKioskMode() {
        ui.logViewerDock->hide();
        ui.pipelineTreeDock->hide();
        ui.pipelinePropertiesDock->hide();
        ui.scriptingConsoleDock->hide();
        ui.workflowDock->show();

    }

491
}