mainwindow.cpp 13.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
62
    {
        tgtAssert(_application != 0, "Application must not be 0.");
63
        ui.setupUi(this);
64
65
66
67
        setup();
    }

    MainWindow::~MainWindow() {
schultezub's avatar
schultezub committed
68
        _application->s_PipelinesChanged.disconnect(this);
69
        _application->s_DataContainersChanged.disconnect(this);
70
        delete _dcInspectorWidget;
71
72
73
    }

    void MainWindow::setup() {
74
75
        qRegisterMetaType<QtDataHandle>("QtDataHandle");

76
        setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
77
        setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
78
        setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
79
        setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
80

81
        setTabPosition(Qt::TopDockWidgetArea, QTabWidget::North);
82

83
        _mdiArea = new MdiDockArea();
84
85
86
        _mdiArea->tileSubWindows();
        setCentralWidget(_mdiArea);

87
88
89
90
91
92
93
94
95
96
97
98
        _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);

99
        _pipelineWidget = new PipelineTreeWidget(this);
100
101
102
103
104
        _containerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
        _cwLayout->addWidget(_pipelineWidget, 1, 0, 1, 2);

        _containerWidget->setLayout(_cwLayout);
        ui.pipelineTreeDock->setWidget(_containerWidget);
105

106
        _pipelinePropertiesScrollArea = new QScrollArea(this);
107
108
109
110
        _pipelinePropertiesScrollArea->setWidgetResizable(true);
        _pipelinePropertiesScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        _pipelinePropertiesScrollArea->setFrameStyle(QScrollArea::NoFrame);

111
        _pipelinePropertiesWidget = new QWidget(_pipelinePropertiesScrollArea);
112
113
114
        _pipelinePropertiesWidget->installEventFilter(this);
        _pipelinePropertiesScrollArea->setWidget(_pipelinePropertiesWidget);
        ui.pipelinePropertiesDock->setWidget(_pipelinePropertiesScrollArea);
115

116
        QVBoxLayout* rightLayout = new QVBoxLayout(_pipelinePropertiesWidget);
117
        rightLayout->setSpacing(4);
118
        _pipelinePropertiesWidget->setLayout(rightLayout);
119

120
        _btnExecute = new QPushButton("Execute Selected Pipeline/Processor", _pipelinePropertiesWidget);
121
122
        rightLayout->addWidget(_btnExecute);

123
        _btnShowDataContainerInspector = new QPushButton("Inspect DataContainer of Selected Pipeline", _pipelinePropertiesWidget);
124
        rightLayout->addWidget(_btnShowDataContainerInspector);
125

126
        _propCollectionWidget = new PropertyCollectionWidget(this);
127
        rightLayout->addWidget(_propCollectionWidget);
128
        rightLayout->addStretch();
129

130
        _logViewer = new LogViewerWidget(this);
131
        ui.logViewerDock->setWidget(_logViewer);
132

133
        _dcInspectorWidget = new DataContainerInspectorWidget();
134
        this->populateMainMenu();
135
136

        connect(
137
138
            this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)), 
            _pipelineWidget, SLOT(update(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)));
139
140
141
142
        connect(
            _pipelineWidget, SIGNAL(clicked(const QModelIndex&)), 
            this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&)));
        connect(
143
144
            this, SIGNAL(updatePropCollectionWidget(HasPropertyCollection*, DataContainer*)),
            _propCollectionWidget, SLOT(updatePropCollection(HasPropertyCollection*, DataContainer*)));
145
146
147
148
149
150
        connect(
            _btnExecute, SIGNAL(clicked()), 
            this, SLOT(onBtnExecuteClicked()));
        connect(
            _btnShowDataContainerInspector, SIGNAL(clicked()), 
            this, SLOT(onBtnShowDataContainerInspectorClicked()));
151
152
153
154
        connect(
            _btnPipelineFactory, SIGNAL(clicked()), 
            this, SLOT(onBtnPipelineFactoryClicked()));

155
        _application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
156
        _application->s_DataContainersChanged.connect(this, &MainWindow::onDataContainersChanged);
157
158
    }

159
    void MainWindow::populateMainMenu() {
160
        // Populate the file menu
161
162
        QMenuBar* menuBar = this->menuBar();
        QMenu* fileMenu = menuBar->addMenu(tr("&File"));
163
        fileMenu->addAction(tr("&Rebuild all Shaders from File"), this, SLOT(onRebuildShadersClicked()), QKeySequence(Qt::CTRL + Qt::Key_F5));
164
165
        fileMenu->addAction(tr("&Quit"), qApp, SLOT(closeAllWindows()), QKeySequence(Qt::CTRL + Qt::Key_Q));

166
167
168
169
170
171
172
173
174
175
        // 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());
176
177
    }

178
179
180
181
182
183
184
185
186
    bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
        if (watched == _pipelinePropertiesWidget && event->type() == QEvent::Resize) {
            _pipelinePropertiesScrollArea->setMinimumWidth(_pipelinePropertiesWidget->minimumSizeHint().width() +
                                                           _pipelinePropertiesScrollArea->verticalScrollBar()->width());
        }

        return false;
    }

187
    void MainWindow::onPipelinesChanged() {
188
189
190
191
192
        emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
    }

    void MainWindow::onDataContainersChanged() {
        emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
193
194
    }

195
196
197
198
    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);
199
200
            if (item.isValid()) {
                HasPropertyCollection* ptr = static_cast<HasPropertyCollection*>(item.value<void*>());
201

202
                if (AbstractPipeline* pipeline = dynamic_cast<AbstractPipeline*>(ptr)) {
203
                    _selectedPipeline = pipeline;
204
                    _selectedProcessor = 0;
205
                    _selectedDataContainer = &pipeline->getDataContainer();
206
207
208
209
210
211
212
213
                }
                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;
214
                        _selectedDataContainer = &pipeline->getDataContainer();
215
                    }
216
217
                }

218
219
220
221
                emit updatePropCollectionWidget(ptr, &_selectedPipeline->getDataContainer());
            }
            else {
                emit updatePropCollectionWidget(0, 0);
222
                _selectedDataContainer = 0;
223
            }
224
225
        }
        else {
226
            emit updatePropCollectionWidget(0, 0);
227
            _selectedDataContainer = 0;
228
229
230
        }
    }

231
    QSize MainWindow::sizeHint() const {
232
        return QSize(1000, 600);
233
234
    }

235
236
237
238
    void MainWindow::onBtnExecuteClicked() {
        if (_selectedProcessor != 0 && _selectedPipeline != 0) {
            // this is not as trivial as it seems:
            // We need the pipeline, probably an OpenGL context...
239
            _selectedProcessor->invalidate(AbstractProcessor::INVALID_RESULT);
240
241
        }
        else if (_selectedPipeline != 0) {
242
243
244
            for (std::vector<AbstractProcessor*>::const_iterator it = _selectedPipeline->getProcessors().begin(); it != _selectedPipeline->getProcessors().end(); ++it) {
                (*it)->invalidate(AbstractProcessor::INVALID_RESULT);
            }
245
246
247
248
249
        }
    }

    void MainWindow::onBtnShowDataContainerInspectorClicked() {
        if (_selectedPipeline != 0) {
250
251
252
            if (_dcInspectorWindow == 0) {
                _dcInspectorWindow = _mdiArea->addWidget(_dcInspectorWidget);
                _dcInspectorWindow->setWindowTitle(tr("Data Container Inspector"));
253
254
            }

255
            _dcInspectorWidget->setDataContainer(&(_selectedPipeline->getDataContainer()));
256
257
            _dcInspectorWindow->show();
            _dcInspectorWindow->activateWindow();
258
259
260
        }
    }

261
    void MainWindow::init() {
262
263
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->init();
264

265
        _logViewer->init();
266
267
268
    }

    void MainWindow::deinit() {
269
270
        if (_dcInspectorWidget != 0)
            _dcInspectorWidget->deinit();
271

272
        _logViewer->deinit();
273
274
    }

275
    void MainWindow::addVisualizationPipelineWidget(const std::string& name, QWidget* canvas) {
276
        MdiDockableWindow* dockableWindow = _mdiArea->addWidget(canvas);
277
        QString windowTitle = QString::fromStdString(name);
278
279
        dockableWindow->setWindowTitle(windowTitle);
        dockableWindow->show();
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
    }

    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;
298
299
    }

300
301
302
303
304
305
306
307
308
309
    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);
    }

310
311
312
313
    void MainWindow::onRebuildShadersClicked() {
        _application->rebuildAllShadersFromFiles();
    }

314
}