pipelinetreewidget.cpp 14.6 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 "pipelinetreewidget.h"

27
#include "cgt/assert.h"
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
28
#include <QApplication>
29
#include <QHeaderView>
30
#include <QScrollBar>
31
32
#include <QStringList>

schultezub's avatar
schultezub committed
33
namespace campvis {
34

35
36
37
    namespace {
        const int COLUMN_NAME = 0;
        const int COLUMN_ENABLED_STATE = 1;
38
        const int COLUMN_CLOCK_STATE = 2;
39
40
    }

41
42
// = TreeModel items ==============================================================================

43
44
45
46
    DataContainerTreeItem::DataContainerTreeItem(DataContainer* dc, TreeItem* parent)
        : TreeItem(parent)
        , _dataContainer(dc)
    {
47
        cgtAssert(_dataContainer != 0, "Pipeline must not be 0.");
48
49
50
51
52
53
54
55
56
57
58
59
60
    }

    QVariant DataContainerTreeItem::getData(int column, int role) const {
        switch (role) {
        case Qt::DisplayRole:
            if (column == COLUMN_NAME)
                return QVariant(QString::fromStdString(_dataContainer->getName()));
            else
                return QVariant();
        case Qt::CheckStateRole:
            return QVariant();
        case Qt::UserRole:
            return QVariant();
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
61
62
        case Qt::BackgroundRole:
            return QVariant(QApplication::palette().alternateBase());
63
64
65
66
67
68
69
70
71
72
73
74
75
76
        default:
            return QVariant();
        }
    }

    DataContainerTreeItem::~DataContainerTreeItem() {
    }

    bool DataContainerTreeItem::setData(int column, int role, const QVariant& value) const {
        return false;
    }

    // ================================================================================================

77
78
79
80
    PipelineTreeItem::PipelineTreeItem(AbstractPipeline* pipeline, TreeItem* parent)
        : TreeItem(parent)
        , _pipeline(pipeline)
    {
81
        cgtAssert(_pipeline != 0, "Pipeline must not be 0.");
82
83
    }

84
85
86
    QVariant PipelineTreeItem::getData(int column, int role) const {
        switch (role) {
            case Qt::DisplayRole:
87
                if (column == COLUMN_NAME)
88
                    return QVariant(QString::fromStdString(_pipeline->getName()));
89
90
91
92
93
94
95
                else
                    return QVariant();
            case Qt::CheckStateRole:
                if (column == COLUMN_ENABLED_STATE)
                    return _pipeline->getEnabled() ? QVariant(Qt::Checked) : QVariant(Qt::Unchecked);
                else
                    return QVariant();
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
96
97
98
99
100
101
102
            case Qt::SizeHintRole:
                if (column == COLUMN_ENABLED_STATE || column == COLUMN_CLOCK_STATE)
                    return QVariant(QSize());
                else
                    return QVariant();
            case Qt::BackgroundRole:
                return QVariant(QApplication::palette().alternateBase());
103
104
105
106
107
            case Qt::UserRole:
                return qVariantFromValue(static_cast<void*>(_pipeline));
            default:
                return QVariant();
        }
108
109
110
111
112
    }

    PipelineTreeItem::~PipelineTreeItem() {
    }

113
114
115
116
117
118
119
120
121
122
    bool PipelineTreeItem::setData(int column, int role, const QVariant& value) const {
        if (column == COLUMN_ENABLED_STATE) {
            if (role == Qt::CheckStateRole) {
                _pipeline->setEnabled(value == Qt::Checked ? true : false);
                return true;
            }
        }
        return false;
    }

123
// ================================================================================================
124
125
126
127
128

    ProcessorTreeItem::ProcessorTreeItem(AbstractProcessor* processor, TreeItem* parent)
        : TreeItem(parent)
        , _processor(processor)
    {
129
        cgtAssert(_processor != 0, "Processor must not be 0.");
130
131
    }

132
133
134
    QVariant ProcessorTreeItem::getData(int column, int role) const {
        switch (role) {
            case Qt::DisplayRole:
135
                if (column == COLUMN_NAME)
136
                    return QVariant(QString::fromStdString(_processor->getInstanceName()));
137
138
139
140
141
                else
                    return QVariant();
            case Qt::CheckStateRole:
                if (column == COLUMN_ENABLED_STATE)
                    return _processor->getEnabled() ? QVariant(Qt::Checked) : QVariant(Qt::Unchecked);
142
143
                else if (column == COLUMN_CLOCK_STATE)
                    return _processor->getClockExecutionTime() ? QVariant(Qt::Checked) : QVariant(Qt::Unchecked);
144
145
                else
                    return QVariant();
146
147
            case Qt::UserRole:
                return qVariantFromValue(static_cast<void*>(_processor));
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
148
149
            case Qt::ToolTipRole:
                return QVariant(QString::fromStdString(_processor->getDescription()));
150
151
152
            default:
                return QVariant();
        }
153
154
155
156
157
    }

    ProcessorTreeItem::~ProcessorTreeItem() {
    }

158
159
160
161
162
163
164
    bool ProcessorTreeItem::setData(int column, int role, const QVariant& value) const {
        if (column == COLUMN_ENABLED_STATE) {
            if (role == Qt::CheckStateRole) {
                _processor->setEnabled(value == Qt::Checked ? true : false);
                return true;
            }
        }
165
166
167
168
169
170
        else if (column == COLUMN_CLOCK_STATE) {
            if (role == Qt::CheckStateRole) {
                _processor->setClockExecutionTime(value == Qt::Checked ? true : false);
                return true;
            }
        }
171
172
173
        return false;
    }

174
    PipelineTreeRootItem::PipelineTreeRootItem(TreeItem* parent /*= 0*/)
175
176
177
        : TreeItem(parent)
    {}

178
    QVariant PipelineTreeRootItem::getData(int column, int role) const {
179
        if (role == Qt::DisplayRole) {
180
            if (column == COLUMN_NAME)
181
                return QVariant(QString("Pipeline/Processor"));
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
182
183
184
185
186
187
188
189
            else if (column == COLUMN_ENABLED_STATE)
                return QVariant(QString("E"));
            else if (column == COLUMN_CLOCK_STATE)
                return QVariant(QString("P"));
        }
        else if (role == Qt::ToolTipRole) {
            if (column == COLUMN_NAME)
                return QVariant(QString("Name of Pipeline/Processor"));
190
191
            else if (column == COLUMN_ENABLED_STATE)
                return QVariant(QString("Enabled"));
192
            else if (column == COLUMN_CLOCK_STATE)
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
193
                return QVariant(QString("Profile Processor's execution time"));
194
        }
195
196
197
198

        return QVariant();
    }

199
    PipelineTreeRootItem::~PipelineTreeRootItem() {
200
201
202
203
204
205
206

    }

// = PipelineTreeModel ============================================================================

    PipelineTreeModel::PipelineTreeModel(QObject *parent /*= 0*/)
        : QAbstractItemModel(parent)
207
        , _rootItem(new PipelineTreeRootItem(0))
208
209
210
211
212
213
214
215
216
217
218
219
    {
    }

    PipelineTreeModel::~PipelineTreeModel() {
        delete _rootItem;
    }

    QVariant PipelineTreeModel::data(const QModelIndex &index, int role) const {
        if (!index.isValid())
            return QVariant();

        TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
220
        return item->getData(index.column(), role);
221
222
    }

223
224
225
226
227
228
229
230
    bool PipelineTreeModel::setData(const QModelIndex& index, const QVariant& value, int role) {
        if (!index.isValid())
            return false;

        TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
        return item->setData(index.column(), role, value);
    }

231
232
233
234
    Qt::ItemFlags PipelineTreeModel::flags(const QModelIndex &index) const {
        if (!index.isValid())
            return 0;

235
236
237
238
239
        switch (index.column()) {
            case COLUMN_NAME:
                return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
            case COLUMN_ENABLED_STATE:
                return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
240
241
            case COLUMN_CLOCK_STATE:
                return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
242
243
244
        }

        return 0;
245
246
247
248
    }

    QVariant PipelineTreeModel::headerData(int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/) const {
        if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
249
            return _rootItem->getData(section, role);
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

        return QVariant();
    }

    QModelIndex PipelineTreeModel::index(int row, int column, const QModelIndex &parent /*= QModelIndex()*/) const {
        if (!hasIndex(row, column, parent))
            return QModelIndex();

        TreeItem* parentItem;

        if (!parent.isValid())
            parentItem = _rootItem;
        else
            parentItem = static_cast<TreeItem*>(parent.internalPointer());

        TreeItem* childItem = parentItem->getChild(row);
        if (childItem)
            return createIndex(row, column, childItem);
        else
            return QModelIndex();
    }

    QModelIndex PipelineTreeModel::parent(const QModelIndex &index) const {
        if (!index.isValid())
            return QModelIndex();

        TreeItem* childItem = static_cast<TreeItem*>(index.internalPointer());
        TreeItem* parentItem = childItem->getParent();

        if (parentItem == _rootItem)
            return QModelIndex();

        return createIndex(parentItem->getRow(), 0, parentItem);
    }

    int PipelineTreeModel::rowCount(const QModelIndex &parent /*= QModelIndex()*/) const {
        TreeItem* parentItem;
        if (parent.column() > 0)
            return 0;

        if (!parent.isValid())
            parentItem = _rootItem;
        else
            parentItem = static_cast<TreeItem*>(parent.internalPointer());

        return parentItem->getChildCount();
    }

    int PipelineTreeModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const {
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
299
        return 3;
300
301
    }

302
    void PipelineTreeModel::setData(const std::vector<DataContainer*>& dataContainers, const std::vector<AbstractPipeline*>& pipelines) {
303
        delete _rootItem;
304
        _rootItem = new PipelineTreeRootItem();
305

306
307
308
309
310
311
        std::map<DataContainer*, DataContainerTreeItem*> dcItemMap;
        for (size_t i = 0; i < dataContainers.size(); ++i) {
            DataContainerTreeItem* dcti = new DataContainerTreeItem(dataContainers[i], _rootItem);
            dcItemMap[dataContainers[i]] = dcti;
        }

312
        for (std::vector<AbstractPipeline*>::const_iterator pipe = pipelines.begin(); pipe != pipelines.end(); ++pipe) {
313
314
315
316
            std::map<DataContainer*, DataContainerTreeItem*>::iterator it = dcItemMap.find(&(*pipe)->getDataContainer());

            if (it != dcItemMap.end()) {
                PipelineTreeItem* pipeti = new PipelineTreeItem(*pipe, it->second);
317

318
                for (std::vector<AbstractProcessor*>::const_iterator proc = (*pipe)->getProcessors().begin(); proc != (*pipe)->getProcessors().end(); ++proc) {
319
                    new ProcessorTreeItem(*proc, pipeti);
320
321
322
                }
            }
            else {
323
                cgtAssert(false, "The DataContainer of this pipeline is not in the list of DataContainers, cannot add it to GUI!");
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
            }
        }
    }

// = PipelineTreeWidget ===========================================================================

    PipelineTreeWidget::PipelineTreeWidget(QWidget* parent /*= 0*/)
        : QTreeView(parent)
    {
        setupWidget();
    }

    PipelineTreeWidget::~PipelineTreeWidget() {

    }

340
341
342
343
344
345
346
347
348
    QSize PipelineTreeWidget::sizeHint() const {
        int height = 0;

        // First of all, sum up the heights of top-level items and their children
        for (int i = 0; i < model()->rowCount(); i++) {
            QModelIndex index = model()->index(i, 0);
            height += sizeHintForRow(i);

            if (model()->hasChildren(index)) {
349
350
351
352
353
354
355
356
                for (int j = 0; j < model()->rowCount(index); ++j) {
                    QModelIndex cIndex = index.child(j, 0);
                    height += sizeHintForIndex(cIndex).height();

                    if (model()->hasChildren(cIndex)) {
                        height += model()->rowCount(cIndex) * sizeHintForIndex(cIndex.child(0, 0)).height();
                    }
                }                
357
358
359
360
361
            }
        }

        // Next, add the heights of the horizontal scrollbar, header, and frame
        height += horizontalScrollBar()->sizeHint().height();
362
        height += 2 * header()->sizeHint().height();
363
364
        height += 2 * frameWidth();

Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
365
        return QSize(QTreeView::sizeHint().width(), std::max(height, 200));
366
367
    }

368
    void PipelineTreeWidget::update(const std::vector<DataContainer*>& dataContainers, const std::vector<AbstractPipeline*>& pipelines) {
schultezub's avatar
schultezub committed
369
370
371
        // clear selection before setting the new data or we will encounter random crashes...
        selectionModel()->clear();

372
        _treeModel->setData(dataContainers, pipelines);
373
        expandAll();
374
375
        resizeColumnToContents(0);
        resizeColumnToContents(1);
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
376
        resizeColumnToContents(2);
377
378
379

        // The widget's size hint might have changed, notify the layout
        updateGeometry();
380
381
    }

382
383
384
    void PipelineTreeWidget::selectionChanged(const QItemSelection& selected, const QItemSelection &deselected) {
        QTreeView::selectionChanged(selected, deselected);
        QModelIndexList selection = this->selectedIndexes();
Declara Denis's avatar
Declara Denis committed
385
386
        if (!selection.isEmpty())
            emit itemChanged(selection.first());
387
388
    }

389
390
    void PipelineTreeWidget::setupWidget() {
        _treeModel = new PipelineTreeModel(this);
391
        cgtAssert(_treeModel != 0, "Failed creating TreeViewWidget model.");
392
393

        setModel(_treeModel);
394
    }
395

396
}