diff --git a/Modules/RenderWindowManagerUI/files.cmake b/Modules/RenderWindowManagerUI/files.cmake index 1637b1a861..bb0d58e96c 100644 --- a/Modules/RenderWindowManagerUI/files.cmake +++ b/Modules/RenderWindowManagerUI/files.cmake @@ -1,18 +1,21 @@ set(H_FILES include/QmitkRenderWindowDataStorageInspector.h include/QmitkRenderWindowDataStorageListModel.h + include/QmitkRenderWindowDataStorageTreeModel.h ) set(CPP_FILES QmitkRenderWindowDataStorageInspector.cpp QmitkRenderWindowDataStorageListModel.cpp + QmitkRenderWindowDataStorageTreeModel.cpp ) set(MOC_H_FILES include/QmitkRenderWindowDataStorageInspector.h include/QmitkRenderWindowDataStorageListModel.h + include/QmitkRenderWindowDataStorageTreeModel.h ) set(UI_FILES src/QmitkRenderWindowDataStorageInspector.ui ) diff --git a/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageInspector.h b/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageInspector.h index d0078bb2dc..03e54c8a8e 100644 --- a/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageInspector.h +++ b/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageInspector.h @@ -1,94 +1,96 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKRENDERWINDOWDATASTORAGEINSPECTOR_H -#define QMITKRENDERWINDOWDATASTORAGEWINSPECTOR_H +#define QMITKRENDERWINDOWDATASTORAGEINSPECTOR_H // render window manager UI module #include "MitkRenderWindowManagerUIExports.h" #include "ui_QmitkRenderWindowDataStorageInspector.h" // render window manager module #include #include -#include +#include // qt widgets module #include /** * The 'QmitkRenderWindowDataStorageInspector' offers a GUI to manipulate the base renderer / render windows of the MITK workbench. * * In order to use this widget, a (e.g.) plugin has to set the controlled renderer, which will be forwarded to * a render window view direction controller. */ class MITKRENDERWINDOWMANAGERUI_EXPORT QmitkRenderWindowDataStorageInspector : public QmitkAbstractDataStorageInspector { Q_OBJECT public: QmitkRenderWindowDataStorageInspector(QWidget* parent = nullptr); // override from 'QmitkAbstractDataStorageInspector' /** * @brief See 'QmitkAbstractDataStorageInspector' */ virtual QAbstractItemView* GetView() override; /** * @brief See 'QmitkAbstractDataStorageInspector' */ virtual const QAbstractItemView* GetView() const override; /** * @brief See 'QmitkAbstractDataStorageInspector' */ virtual void SetSelectionMode(SelectionMode mode) override; /** * @brief See 'QmitkAbstractDataStorageInspector' */ virtual SelectionMode GetSelectionMode() const override; /** * @brief Set the controlled base renderer. */ void SetControlledRenderer(mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer); /** * @brief Set the currently selected render window. * * @param renderWindowId the text inside the combo box */ void SetActiveRenderWindow(const QString& renderWindowId); private Q_SLOTS: + void ModelRowsInserted(const QModelIndex& parent, int start, int end); + void SetAsBaseLayer(); void ResetRenderer(); void ChangeViewDirection(const QString& viewDirection); private: virtual void Initialize() override; void SetUpConnections(); Ui::QmitkRenderWindowDataStorageInspector m_Controls; - std::unique_ptr m_StorageModel; + std::unique_ptr m_StorageModel; std::unique_ptr m_RenderWindowLayerController; std::unique_ptr m_RenderWindowViewDirectionController; }; #endif // QMITKRENDERWINDOWDATASTORAGEINSPECTOR_H diff --git a/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageTreeModel.h b/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageTreeModel.h new file mode 100644 index 0000000000..7fafa6cd65 --- /dev/null +++ b/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageTreeModel.h @@ -0,0 +1,116 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QMITKDATASTORAGERENDERWINDOWTREEMODEL_H +#define QMITKDATASTORAGERENDERWINDOWTREEMODEL_H + +// render window manager UI model +#include "MitkRenderWindowManagerUIExports.h" + +// render window manager module +#include "mitkRenderWindowLayerController.h" +#include "mitkRenderWindowLayerUtilities.h" + +//mitk core +#include + +// qt widgets module +#include +#include + +/* +* @brief The 'QmitkRenderWindowDataStorageTreeModel' is a tree model derived from the 'QmitkAbstractDataStorageModel'. +*/ +class MITKRENDERWINDOWMANAGERUI_EXPORT QmitkRenderWindowDataStorageTreeModel : public QmitkAbstractDataStorageModel +{ + Q_OBJECT + +public: + + QmitkRenderWindowDataStorageTreeModel(QObject* parent = nullptr); + + // override from 'QmitkAbstractDataStorageModel' + /** + * @brief See 'QmitkAbstractDataStorageModel' + */ + void DataStorageChanged() override; + /** + * @brief See 'QmitkAbstractDataStorageModel' + */ + void NodePredicateChanged() override; + /** + * @brief See 'QmitkAbstractDataStorageModel' + */ + void NodeAdded(const mitk::DataNode* node) override; + /** + * @brief See 'QmitkAbstractDataStorageModel' + */ + void NodeChanged(const mitk::DataNode* node) override; + /** + * @brief See 'QmitkAbstractDataStorageModel' + */ + void NodeRemoved(const mitk::DataNode* node) override; + + // override from 'QAbstractItemModel' + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& parent) const override; + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + + QVariant data(const QModelIndex& index, int role) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + + Qt::DropActions supportedDropActions() const override; + Qt::DropActions supportedDragActions() const override; + QStringList mimeTypes() const override; + QMimeData* mimeData(const QModelIndexList& indexes) const override; + + bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; + + void SetControlledRenderer(mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer); + + void SetCurrentRenderer(mitk::BaseRenderer* baseRenderer); + mitk::BaseRenderer* GetCurrentRenderer() const; + +private: + + void ResetTree(); + void UpdateModelData(); + + /** + * @brief ... + * + * @param dataNode The data node that should be added. + * @param renderer The base renderer to which the data node should be added. + */ + void AddNodeInternal(const mitk::DataNode* dataNode, const mitk::BaseRenderer* renderer); + + mitk::DataNode* GetParentNode(const mitk::DataNode* node) const; + QmitkDataStorageTreeModelInternalItem* GetItemByIndex(const QModelIndex& index) const; + + std::list m_TreeItems; + + std::unique_ptr m_RenderWindowLayerController; + mitk::RenderWindowLayerUtilities::RendererVector m_ControlledRenderer; + std::unique_ptr m_Root; + mitk::WeakPointer m_BaseRenderer; + +}; + +#endif // QMITKDATASTORAGERENDERWINDOWTREEMODEL_H diff --git a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.cpp b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.cpp index 018d3441f0..152497dc09 100644 --- a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.cpp +++ b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.cpp @@ -1,165 +1,173 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // render window manager UI module #include "QmitkRenderWindowDataStorageInspector.h" #include "QmitkCustomVariants.h" // mitk core #include // qt #include QmitkRenderWindowDataStorageInspector::QmitkRenderWindowDataStorageInspector(QWidget* parent /*=nullptr*/) : QmitkAbstractDataStorageInspector(parent) { m_Controls.setupUi(this); // initialize the render window layer controller and the render window view direction controller m_RenderWindowLayerController = std::make_unique(); m_RenderWindowViewDirectionController = std::make_unique(); - m_StorageModel = std::make_unique(this); - - m_Controls.renderWindowListView->setModel(m_StorageModel.get()); - m_Controls.renderWindowListView->setEditTriggers(QAbstractItemView::NoEditTriggers); - m_Controls.renderWindowListView->setSelectionBehavior(QAbstractItemView::SelectRows); - m_Controls.renderWindowListView->setSelectionMode(QAbstractItemView::ExtendedSelection); - m_Controls.renderWindowListView->setAlternatingRowColors(true); - m_Controls.renderWindowListView->setDragEnabled(true); - m_Controls.renderWindowListView->setDropIndicatorShown(true); - m_Controls.renderWindowListView->setAcceptDrops(true); - m_Controls.renderWindowListView->setContextMenuPolicy(Qt::CustomContextMenu); + m_StorageModel = std::make_unique(this); + + m_Controls.renderWindowTreeView->setModel(m_StorageModel.get()); + m_Controls.renderWindowTreeView->setHeaderHidden(true); + m_Controls.renderWindowTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_Controls.renderWindowTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); + m_Controls.renderWindowTreeView->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_Controls.renderWindowTreeView->setAlternatingRowColors(true); + m_Controls.renderWindowTreeView->setDragEnabled(true); + m_Controls.renderWindowTreeView->setDropIndicatorShown(true); + m_Controls.renderWindowTreeView->setAcceptDrops(true); + m_Controls.renderWindowTreeView->setContextMenuPolicy(Qt::CustomContextMenu); SetUpConnections(); } QAbstractItemView* QmitkRenderWindowDataStorageInspector::GetView() { - return m_Controls.renderWindowListView; + return m_Controls.renderWindowTreeView; } const QAbstractItemView* QmitkRenderWindowDataStorageInspector::GetView() const { - return m_Controls.renderWindowListView; + return m_Controls.renderWindowTreeView; } void QmitkRenderWindowDataStorageInspector::SetSelectionMode(SelectionMode mode) { - m_Controls.renderWindowListView->setSelectionMode(mode); + m_Controls.renderWindowTreeView->setSelectionMode(mode); } QmitkRenderWindowDataStorageInspector::SelectionMode QmitkRenderWindowDataStorageInspector::GetSelectionMode() const { - return m_Controls.renderWindowListView->selectionMode(); + return m_Controls.renderWindowTreeView->selectionMode(); } void QmitkRenderWindowDataStorageInspector::Initialize() { if (m_DataStorage.IsExpired()) { return; } auto dataStorage = m_DataStorage.Lock(); m_StorageModel->SetDataStorage(dataStorage); m_StorageModel->SetNodePredicate(m_NodePredicate); m_RenderWindowLayerController->SetDataStorage(dataStorage); m_RenderWindowViewDirectionController->SetDataStorage(dataStorage); - m_Connector->SetView(m_Controls.renderWindowListView); + m_Connector->SetView(m_Controls.renderWindowTreeView); } void QmitkRenderWindowDataStorageInspector::SetUpConnections() { + connect(m_StorageModel.get(), &QAbstractItemModel::rowsInserted, this, &QmitkRenderWindowDataStorageInspector::ModelRowsInserted); + connect(m_Controls.pushButtonSetAsBaseLayer, &QPushButton::clicked, this, &QmitkRenderWindowDataStorageInspector::SetAsBaseLayer); connect(m_Controls.pushButtonResetRenderer, &QPushButton::clicked, this, &QmitkRenderWindowDataStorageInspector::ResetRenderer); QSignalMapper* changeViewDirectionSignalMapper = new QSignalMapper(this); changeViewDirectionSignalMapper->setMapping(m_Controls.radioButtonAxial, QString("axial")); changeViewDirectionSignalMapper->setMapping(m_Controls.radioButtonCoronal, QString("coronal")); changeViewDirectionSignalMapper->setMapping(m_Controls.radioButtonSagittal, QString("sagittal")); changeViewDirectionSignalMapper->setMapping(m_Controls.radioButton3D, QString("3D")); connect(changeViewDirectionSignalMapper, static_cast(&QSignalMapper::mapped), this, &QmitkRenderWindowDataStorageInspector::ChangeViewDirection); connect(m_Controls.radioButtonAxial, &QPushButton::clicked, changeViewDirectionSignalMapper, static_cast(&QSignalMapper::map)); connect(m_Controls.radioButtonCoronal, &QPushButton::clicked, changeViewDirectionSignalMapper, static_cast(&QSignalMapper::map)); connect(m_Controls.radioButtonSagittal, &QPushButton::clicked, changeViewDirectionSignalMapper, static_cast(&QSignalMapper::map)); connect(m_Controls.radioButton3D, &QPushButton::clicked, changeViewDirectionSignalMapper, static_cast(&QSignalMapper::map)); } void QmitkRenderWindowDataStorageInspector::SetControlledRenderer(mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer) { m_StorageModel->SetControlledRenderer(controlledRenderer); m_RenderWindowLayerController->SetControlledRenderer(controlledRenderer); m_RenderWindowViewDirectionController->SetControlledRenderer(controlledRenderer); } void QmitkRenderWindowDataStorageInspector::SetActiveRenderWindow(const QString& renderWindowId) { mitk::BaseRenderer* selectedRenderer = mitk::BaseRenderer::GetByName(renderWindowId.toStdString()); if (nullptr == selectedRenderer) { return; } m_StorageModel->SetCurrentRenderer(selectedRenderer); mitk::SliceNavigationController::ViewDirection viewDirection = selectedRenderer->GetSliceNavigationController()->GetDefaultViewDirection(); switch (viewDirection) { case mitk::SliceNavigationController::Axial: m_Controls.radioButtonAxial->setChecked(true); break; case mitk::SliceNavigationController::Frontal: m_Controls.radioButtonCoronal->setChecked(true); break; case mitk::SliceNavigationController::Sagittal: m_Controls.radioButtonSagittal->setChecked(true); break; default: break; } } +void QmitkRenderWindowDataStorageInspector::ModelRowsInserted(const QModelIndex& parent, int start, int end) +{ + m_Controls.renderWindowTreeView->setExpanded(parent, true); +} + void QmitkRenderWindowDataStorageInspector::SetAsBaseLayer() { - QModelIndex selectedIndex = m_Controls.renderWindowListView->currentIndex(); + QModelIndex selectedIndex = m_Controls.renderWindowTreeView->currentIndex(); if (selectedIndex.isValid()) { QVariant qvariantDataNode = m_StorageModel->data(selectedIndex, Qt::UserRole); if (qvariantDataNode.canConvert()) { mitk::DataNode* dataNode = qvariantDataNode.value(); m_RenderWindowLayerController->SetBaseDataNode(dataNode, m_StorageModel->GetCurrentRenderer()); - m_Controls.renderWindowListView->clearSelection(); + m_Controls.renderWindowTreeView->clearSelection(); } } } void QmitkRenderWindowDataStorageInspector::ResetRenderer() { m_RenderWindowLayerController->ResetRenderer(true, m_StorageModel->GetCurrentRenderer()); - m_Controls.renderWindowListView->clearSelection(); + m_Controls.renderWindowTreeView->clearSelection(); } void QmitkRenderWindowDataStorageInspector::ChangeViewDirection(const QString& viewDirection) { m_RenderWindowViewDirectionController->SetViewDirectionOfRenderer(viewDirection.toStdString(), m_StorageModel->GetCurrentRenderer()); } diff --git a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.ui b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.ui index 64c507a340..785e20c50c 100644 --- a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.ui +++ b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.ui @@ -1,92 +1,92 @@ QmitkRenderWindowDataStorageInspector 0 0 340 246 0 0 0 0 Render window manager Render window overview - + Reset render window - + Set as base layer - + Axial true - + Coronal Sagittal 3D diff --git a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageTreeModel.cpp b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageTreeModel.cpp new file mode 100644 index 0000000000..c4e08c8912 --- /dev/null +++ b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageTreeModel.cpp @@ -0,0 +1,545 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// render window manager UI module +#include "QmitkRenderWindowDataStorageTreeModel.h" + +// mitk core +#include + +// qt widgets module +#include "QmitkCustomVariants.h" +#include "QmitkEnums.h" +#include "QmitkMimeTypes.h" +#include "QmitkNodeDescriptorManager.h" + +QmitkRenderWindowDataStorageTreeModel::QmitkRenderWindowDataStorageTreeModel(QObject* parent /*= nullptr*/) + : QmitkAbstractDataStorageModel(parent) +{ + m_RenderWindowLayerController = std::make_unique(); + ResetTree(); +} + +void QmitkRenderWindowDataStorageTreeModel::DataStorageChanged() +{ + m_RenderWindowLayerController->SetDataStorage(m_DataStorage.Lock()); + ResetTree(); + UpdateModelData(); +} + +void QmitkRenderWindowDataStorageTreeModel::NodePredicateChanged() +{ + ResetTree(); + UpdateModelData(); +} + +void QmitkRenderWindowDataStorageTreeModel::NodeAdded(const mitk::DataNode* node) +{ + /* + for (const auto renderer : m_ControlledRenderer) + { + // add a node to each render window + mitk::RenderWindowLayerUtilities::SetRenderWindowProperties(const_cast(node), renderer); + } + */ + if (!m_BaseRenderer.IsExpired()) + { + auto baseRenderer = m_BaseRenderer.Lock(); + AddNodeInternal(node, nullptr); + } +} + +void QmitkRenderWindowDataStorageTreeModel::NodeChanged(const mitk::DataNode* node) +{ + auto treeItem = m_Root->Find(node); + if (nullptr != treeItem) + { + auto parentTreeItem = treeItem->GetParent(); + // as the root node should not be removed one should always have a parent item + if (nullptr == parentTreeItem) + { + return; + } + + QModelIndex index = this->createIndex(treeItem->GetIndex(), 0, treeItem); + emit dataChanged(index, index); + } +} + +void QmitkRenderWindowDataStorageTreeModel::NodeRemoved(const mitk::DataNode* /*node*/) +{ + // #TODO + // update model data to create a new list without the removed data node + UpdateModelData(); +} + +QModelIndex QmitkRenderWindowDataStorageTreeModel::index(int row, int column, const QModelIndex& parent) const +{ + if (!hasIndex(row, column, parent)) + { + return QModelIndex(); + } + + auto childItem = GetItemByIndex(parent)->GetChild(row); + if (nullptr != childItem) + { + return createIndex(row, column, childItem); + } + + return QModelIndex(); +} + +QModelIndex QmitkRenderWindowDataStorageTreeModel::parent(const QModelIndex& parent) const +{ + if (!parent.isValid() || !m_Root) + { + return QModelIndex(); + } + + auto parentItem = GetItemByIndex(parent)->GetParent(); + if(nullptr == parentItem) + { + return QModelIndex(); + } + + if (parentItem == m_Root.get()) + { + return QModelIndex(); + } + + return this->createIndex(parentItem->GetIndex(), 0, parentItem); +} + +int QmitkRenderWindowDataStorageTreeModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const +{ + return GetItemByIndex(parent)->GetChildCount(); +} + +int QmitkRenderWindowDataStorageTreeModel::columnCount(const QModelIndex&/* parent = QModelIndex()*/) const +{ + if (0 == m_Root->GetChildCount()) + { + // no items stored, no need to display columns + return 0; + } + + return 1; +} + +QVariant QmitkRenderWindowDataStorageTreeModel::data(const QModelIndex& index, int role) const +{ + if (m_BaseRenderer.IsExpired()) + { + return QVariant(); + } + + auto baseRenderer = m_BaseRenderer.Lock(); + + if (!index.isValid() || this != index.model()) + { + return QVariant(); + } + + auto treeItem = GetItemByIndex(index); + if (nullptr == treeItem) + { + return QVariant(); + } + + auto dataNode = treeItem->GetDataNode(); + if (nullptr == dataNode) + { + return QVariant(); + } + + if (Qt::CheckStateRole == role) + { + bool visibility = false; + dataNode->GetVisibility(visibility, baseRenderer); + if (visibility) + { + return Qt::Checked; + } + else + { + return Qt::Unchecked; + } + } + else if (Qt::DisplayRole == role) + { + return QVariant(QString::fromStdString(dataNode->GetName())); + } + else if (Qt::ToolTipRole == role) + { + return QVariant("Name of the data node."); + } + else if (Qt::DecorationRole == role) + { + QmitkNodeDescriptor* nodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor(dataNode); + return nodeDescriptor->GetIcon(dataNode); + } + else if (Qt::UserRole == role || QmitkDataNodeRawPointerRole == role) + { + // user role always returns a reference to the data node, + // which can be used to modify the data node in the data storage + return QVariant::fromValue(dataNode); + } + else if (QmitkDataNodeRole == role) + { + return QVariant::fromValue(mitk::DataNode::Pointer(dataNode)); + } + + return QVariant(); +} + +bool QmitkRenderWindowDataStorageTreeModel::setData(const QModelIndex& index, const QVariant& value, int role /*= Qt::EditRole*/) +{ + if (m_BaseRenderer.IsExpired()) + { + return false; + } + + auto baseRenderer = m_BaseRenderer.Lock(); + + if (!index.isValid() || this != index.model()) + { + return false; + } + + auto treeItem = GetItemByIndex(index); + if (nullptr == treeItem) + { + return false; + } + + auto dataNode = treeItem->GetDataNode(); + if (nullptr == dataNode) + { + return false; + } + + if (Qt::EditRole == role && !value.toString().isEmpty()) + { + dataNode->SetName(value.toString().toStdString().c_str()); + emit dataChanged(index, index); + return true; + } + if (Qt::CheckStateRole == role) + { + Qt::CheckState newCheckState = static_cast(value.toInt()); + bool isVisible = newCheckState; + dataNode->SetVisibility(isVisible, baseRenderer); + + emit dataChanged(index, index); + mitk::RenderingManager::GetInstance()->RequestUpdate(baseRenderer->GetRenderWindow()); + return true; + } + return false; +} + +Qt::ItemFlags QmitkRenderWindowDataStorageTreeModel::flags(const QModelIndex& index) const +{ + if (this != index.model()) + { + return Qt::NoItemFlags; + } + + if (!index.isValid()) + { + return Qt::ItemIsDropEnabled; + } + + auto treeItem = GetItemByIndex(index); + if (nullptr == treeItem) + { + return Qt::NoItemFlags; + } + + const auto dataNode = treeItem->GetDataNode(); + if (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(dataNode)) + { + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; + } + + return Qt::NoItemFlags; +} + +Qt::DropActions QmitkRenderWindowDataStorageTreeModel::supportedDropActions() const +{ + return Qt::CopyAction | Qt::MoveAction; +} + +Qt::DropActions QmitkRenderWindowDataStorageTreeModel::supportedDragActions() const +{ + return Qt::CopyAction | Qt::MoveAction; +} + +QStringList QmitkRenderWindowDataStorageTreeModel::mimeTypes() const +{ + QStringList types = QAbstractItemModel::mimeTypes(); + types << QmitkMimeTypes::DataNodePtrs; + return types; +} + +QMimeData* QmitkRenderWindowDataStorageTreeModel::mimeData(const QModelIndexList& indexes) const +{ + QMimeData* mimeData = new QMimeData(); + QByteArray encodedData; + + QDataStream stream(&encodedData, QIODevice::WriteOnly); + + for (const auto& index : indexes) + { + if (index.isValid()) + { + auto dataNode = data(index, QmitkDataNodeRawPointerRole).value(); + stream << reinterpret_cast(dataNode); + } + } + + mimeData->setData(QmitkMimeTypes::DataNodePtrs, encodedData); + return mimeData; +} + +bool QmitkRenderWindowDataStorageTreeModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int /*row*/, int column, const QModelIndex& parent) +{ + if (m_BaseRenderer.IsExpired()) + { + return false; + } + + auto baseRenderer = m_BaseRenderer.Lock(); + + if (action == Qt::IgnoreAction) + { + return true; + } + + if (!data->hasFormat(QmitkMimeTypes::DataNodePtrs)) + { + return false; + } + + if (column > 0) + { + return false; + } + + if (parent.isValid()) + { + int layer = -1; + auto dataNode = this->data(parent, QmitkDataNodeRawPointerRole).value(); + if (nullptr != dataNode) + { + dataNode->GetIntProperty("layer", layer, baseRenderer); + } + + auto dataNodeList = QmitkMimeTypes::ToDataNodePtrList(data); + for (const auto& dataNode : dataNodeList) + { + m_RenderWindowLayerController->MoveNodeToPosition(dataNode, layer, baseRenderer); + } + + UpdateModelData(); + return true; + } + + return false; +} + +void QmitkRenderWindowDataStorageTreeModel::SetControlledRenderer(mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer) +{ + m_RenderWindowLayerController->SetControlledRenderer(controlledRenderer); + m_ControlledRenderer = controlledRenderer; + + /* + if (!m_DataStorage.IsExpired()) + { + auto dataStorage = m_DataStorage.Lock(); + mitk::DataStorage::SetOfObjects::ConstPointer allDataNodes = dataStorage->GetAll(); + for (mitk::DataStorage::SetOfObjects::ConstIterator it = allDataNodes->Begin(); it != allDataNodes->End(); ++it) + { + mitk::DataNode::Pointer dataNode = it->Value(); + if (dataNode.IsNull()) + { + continue; + } + + for (const auto& renderer : controlledRenderer) + { + if (nullptr != renderer) + { + AddNodeInternal(dataNode, renderer); + } + } + } + } + */ +} + +void QmitkRenderWindowDataStorageTreeModel::SetCurrentRenderer(mitk::BaseRenderer* baseRenderer) +{ + if (m_BaseRenderer == baseRenderer) + { + return; + } + + // base renderer changed + // reset tree to build a new renderer-specific item hierarchy + m_BaseRenderer = baseRenderer; + ResetTree(); + UpdateModelData(); +} + +mitk::BaseRenderer* QmitkRenderWindowDataStorageTreeModel::GetCurrentRenderer() const +{ + if (m_BaseRenderer.IsExpired()) + { + return nullptr; + } + + return m_BaseRenderer.Lock().GetPointer(); +} + +void QmitkRenderWindowDataStorageTreeModel::ResetTree() +{ + mitk::DataNode::Pointer rootDataNode = mitk::DataNode::New(); + rootDataNode->SetName("Data Storage"); + m_Root.reset(new QmitkDataStorageTreeModelInternalItem(rootDataNode)); +} + +void QmitkRenderWindowDataStorageTreeModel::UpdateModelData() +{ + if (!m_DataStorage.IsExpired()) + { + auto dataStorage = m_DataStorage.Lock(); + if (!m_BaseRenderer.IsExpired()) + { + auto baseRenderer = m_BaseRenderer.Lock(); + + /* + mitk::NodePredicateAnd::Pointer combinedNodePredicate = mitk::RenderWindowLayerUtilities::GetRenderWindowPredicate(baseRenderer); + auto filteredDataNodes = dataStorage->GetSubset(combinedNodePredicate); + */ + auto filteredDataNodes = dataStorage->GetAll(); + for (const auto& dataNode : *filteredDataNodes) + { + AddNodeInternal(dataNode, nullptr); + } + } + } +} + +void QmitkRenderWindowDataStorageTreeModel::AddNodeInternal(const mitk::DataNode* dataNode, const mitk::BaseRenderer* renderer) +{ + if (nullptr == dataNode) + { + return; + } + + if (m_DataStorage.IsExpired()) + { + return; + } + + auto dataStorage = m_DataStorage.Lock(); + + if (m_Root->Find(dataNode) != 0) + { + // node already contained in the tree + return; + } + + // find out if we have a root node + auto parentTreeItem = m_Root.get(); + QModelIndex index; + mitk::DataNode* parentDataNode = GetParentNode(dataNode); + + if (nullptr != parentDataNode) // no top level data node + { + parentTreeItem = m_Root->Find(parentDataNode); // find the corresponding tree item + if (nullptr == parentTreeItem) + { + // parent node not contained in the tree; add it + NodeAdded(parentDataNode); + parentTreeItem = m_Root->Find(parentDataNode); + if (nullptr == parentTreeItem) + { + // could not find and add the parent tree; abort + return; + } + } + + // get the index of this parent with the help of the grand parent + index = this->createIndex(parentTreeItem->GetIndex(), 0, parentTreeItem); + } + + int firstRowWithASiblingBelow = 0; + int nodeLayer = -1; + dataNode->GetIntProperty("layer", nodeLayer, renderer); + for (const auto& siblingTreeItem : parentTreeItem->GetChildren()) + { + int siblingLayer = -1; + auto siblingNode = siblingTreeItem->GetDataNode(); + if (nullptr != siblingNode) + { + siblingNode->GetIntProperty("layer", siblingLayer, renderer); + } + if (nodeLayer > siblingLayer) + { + break; + } + ++firstRowWithASiblingBelow; + } + + beginInsertRows(index, firstRowWithASiblingBelow, firstRowWithASiblingBelow); + auto newNode = new QmitkDataStorageTreeModelInternalItem(const_cast(dataNode)); + parentTreeItem->InsertChild(newNode, firstRowWithASiblingBelow); + m_TreeItems.push_back(newNode); + + endInsertRows(); +} + +mitk::DataNode* QmitkRenderWindowDataStorageTreeModel::GetParentNode(const mitk::DataNode* node) const +{ + mitk::DataNode* dataNode = nullptr; + if (m_DataStorage.IsExpired()) + { + return dataNode; + } + + auto sources = m_DataStorage.Lock()->GetSources(node); + if (sources->empty()) + { + return dataNode; + } + + return sources->front(); +} + +QmitkDataStorageTreeModelInternalItem* QmitkRenderWindowDataStorageTreeModel::GetItemByIndex(const QModelIndex& index) const +{ + if (index.isValid()) + { + auto item = static_cast(index.internalPointer()); + if (nullptr != item) + { + return item; + } + } + + return m_Root.get(); +}