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
}