diff --git a/Modules/QtWidgets/include/QmitkRenderWindowContextDataStorageInspector.h b/Modules/QtWidgets/include/QmitkRenderWindowContextDataStorageInspector.h index 2434015247..f4d17a5f8d 100644 --- a/Modules/QtWidgets/include/QmitkRenderWindowContextDataStorageInspector.h +++ b/Modules/QtWidgets/include/QmitkRenderWindowContextDataStorageInspector.h @@ -1,90 +1,88 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef QmitkRenderWindowContextDataStorageInspector_h #define QmitkRenderWindowContextDataStorageInspector_h // qt widgets module #include "MitkQtWidgetsExports.h" #include "ui_QmitkRenderWindowContextDataStorageInspector.h" // render window manager module #include #include // qt widgets module #include // mitk core #include /** * The 'QmitkRenderWindowContextDataStorageInspector' 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 MITKQTWIDGETS_EXPORT QmitkRenderWindowContextDataStorageInspector : public QmitkAbstractDataStorageInspector { Q_OBJECT public: QmitkRenderWindowContextDataStorageInspector(QWidget* parent = nullptr, mitk::BaseRenderer* renderer = nullptr); // override from 'QmitkAbstractDataStorageInspector' /** * @brief See 'QmitkAbstractDataStorageInspector' */ QAbstractItemView* GetView() override; /** * @brief See 'QmitkAbstractDataStorageInspector' */ const QAbstractItemView* GetView() const override; /** * @brief See 'QmitkAbstractDataStorageInspector' */ void SetSelectionMode(SelectionMode mode) override; /** * @brief See 'QmitkAbstractDataStorageInspector' */ SelectionMode GetSelectionMode() const override; QItemSelectionModel* GetDataNodeSelectionModel() const; Q_SIGNALS: void ReinitAction(QList selectedNodes); void ResetAction(QList selectedNodes); private Q_SLOTS: void ModelRowsInserted(const QModelIndex& parent, int start, int end); - void ResetRenderer(); - void OnContextMenuRequested(const QPoint& pos); void OnReinit(); void OnReset(); private: void Initialize() override; void SetUpConnections(); Ui::QmitkRenderWindowContextDataStorageInspector m_Controls; std::unique_ptr m_StorageModel; std::unique_ptr m_RenderWindowLayerController; }; #endif diff --git a/Modules/QtWidgets/include/mitkRenderWindowLayerController.h b/Modules/QtWidgets/include/mitkRenderWindowLayerController.h index 86a48c5e75..c90a2c9b61 100644 --- a/Modules/QtWidgets/include/mitkRenderWindowLayerController.h +++ b/Modules/QtWidgets/include/mitkRenderWindowLayerController.h @@ -1,174 +1,115 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkRenderWindowLayerController_h #define mitkRenderWindowLayerController_h // qt widgets module #include "MitkQtWidgetsExports.h" #include "mitkRenderWindowLayerUtilities.h" // mitk core #include #include #include namespace mitk { /** * The RenderWindowLayerController is used to manipulate the 'layer', 'fixedLayer' and 'visible' property of a given data node. * The 'layer' property is used to denote the layer level of a data node. Data from nodes on higher layer level are rendered * on top of data from nodes on lower layer level. It can be changed using the 'MoveNode*'-functions. * * To view the data of a data node only in a specific renderer, the "InsertLayerNode'-function should be used. It inserts the * given node into the specified renderer and sets the corresponding properties. - * To hide the data in the common renderer view (all renderer), the 'HideDataNodeInAllRenderer'-function can be used. * Inserting and showing a data node in a specific renderer / render window, will overwrite the properties of the common renderer view. * * For more information about the data node properties for specific renderer, see mitk::DataNode- and mitk::PropertyList-classes. * * Functions with 'mitk::BaseRenderer* renderer' have 'nullptr' as their default argument. Using the nullptr - * these functions operate on all base renderer. Giving a specific base renderer will modify the node only for the given renderer. + * these functions operate on the general property list. + * Giving a specific base renderer will modify the property list of the given renderer. */ class MITKQTWIDGETS_EXPORT RenderWindowLayerController { public: RenderWindowLayerController(); /** * @brief Set the data storage on which to work. */ void SetDataStorage(DataStorage::Pointer dataStorage); - /** - * @brief Set the controlled base renderer. - */ - void SetControlledRenderer(RenderWindowLayerUtilities::RendererVector controlledRenderer); // wrapper functions to modify the layer order / visibility of render window data /** - * @brief Set the given node as the base node of the given renderer. - * - * @param dataNode The data node whose layer is to be modified. - * @param renderer Pointer to the renderer instance for which the data node property should be modified. - * If it is a nullptr (default) all controlled renderer will be affected. - */ - void SetBaseDataNode(DataNode* dataNode, const BaseRenderer* renderer = nullptr); - /** * @brief Insert the given data node at the specified layer for the given renderer. * * @param dataNode The data node that should be inserted. * @param layer The layer value for the "layer" property of the data node (insertion level). "layer = RenderWindowLayerUtilities::TOP_LAYER_INDEX" (default) inserts the given data node at the top of the node stack (topmost layer). * @param renderer Pointer to the renderer instance for which the data node should be inserted. * If it is a nullptr (default) all controlled renderer will be affected. * * @post After a successful call, the "fixedLayer" and "visibility" property will be true and the "layer" property will be set correctly. */ void InsertLayerNode(DataNode* dataNode, int layer = RenderWindowLayerUtilities::TOP_LAYER_INDEX, const BaseRenderer* renderer = nullptr); /** - * @brief Remove the given data node for the given renderer. - * - * @param dataNode The data node that should be removed. - * @param renderer Pointer to the renderer instance for which the data node should be removed. - * If it is a nullptr (default) all controlled renderer will be affected. - * - * @post After a successful call, the "fixedLayer" and "visibility" property will be false and the "layer" property will be deleted. - */ - void RemoveLayerNode(DataNode* dataNode, const BaseRenderer* renderer = nullptr); - /** * @brief Move the data node to the given layer. This will change only the "layer" property. * * @param dataNode The data node that should be moved. - * @param newLayer + * @param layer The layer to which the data node should be moved. * @param renderer Pointer to the renderer instance for which the data node should be moved. - * If it is a nullptr (default) all controlled renderer will be affected. + * If it is a nullptr (default) all controlled renderer will be affected and the + * common property list will be modified. */ - bool MoveNodeToPosition(DataNode* dataNode, int newLayer, const BaseRenderer* renderer = nullptr); + bool MoveNodeToPosition(DataNode* dataNode, int layer, const BaseRenderer* renderer = nullptr); /** * @brief Set the node in the given renderer as the topmost layer. This will change only the "layer" property. * * @param dataNode The data node that should be moved. * @param renderer Pointer to the renderer instance for which the data node should be moved. * If it is a nullptr (default) all controlled renderer will be affected. */ bool MoveNodeToFront(DataNode* dataNode, const BaseRenderer* renderer = nullptr); /** * @brief Set the node in the given renderer as the lowermost layer. This will change only the "layer" property. * * @param dataNode The data node that should be moved. * @param renderer Pointer to the renderer instance for which the data node should be moved. * If it is a nullptr (default) all controlled renderer will be affected. */ bool MoveNodeToBack(DataNode* dataNode, const BaseRenderer* renderer = nullptr); /** * @brief Move the node in the given renderer one layer down. This will change only the "layer" property. * * @param dataNode The data node that should be moved. * @param renderer Pointer to the renderer instance for which the data node should be moved. * If it is a nullptr (default) all controlled renderer will be affected. */ bool MoveNodeUp(DataNode* dataNode, const BaseRenderer* renderer = nullptr); /** * @brief Move the node in the given renderer one layer up. This will change only the "layer" property. * * @param dataNode The data node that should be moved. * @param renderer Pointer to the renderer instance for which the data node should be moved. * If it is a nullptr (default) all controlled renderer will be affected. */ bool MoveNodeDown(DataNode* dataNode, const BaseRenderer* renderer = nullptr); - /** - * @brief Set the visibility of the given data node for the given renderer. - * - * @param visibility Boolean to set the "visible" property of the given data node. - * @param dataNode The data node that should be moved. - * @param renderer Pointer to the renderer instance for which the data node should be modified. - * If it is a nullptr (default) all controlled renderer will be affected. - * - * @post After a successful call , the "visibility" property will be set to the "visibility" value. - */ - void SetVisibilityOfDataNode(bool visibility, DataNode* dataNode, const BaseRenderer* renderer = nullptr); - /** - * @brief Hide the given data node by setting the "visible" property of the data node for - * all controlled renderer to false. - * Later setting the "visible" property of the data node for a certain renderer will overwrite - * the same property of the common renderer. - * - * @param dataNode The data node that should be hid. - * - * @post After a successful call , the "visibility" property will be set to the false. - */ - void HideDataNodeInAllRenderer(const DataNode* dataNode); - /** - * @brief Reset the given render window: - * If "onlyVisibility = true": set all data nodes for the given render window to invisible, except for the base node. - * If "onlyVisibility = false": remove all data nodes from the render window, except for the base node. - * - * @param onlyVisibility Boolean to define the reset mode. - * @param renderer Pointer to the renderer instance for which the data node should be reset. - * If it is a nullptr (default) all controlled renderer will be affected. - * - * @post After a successful call , the "visibility" property will be set to the "false" value (except for the base node). - * If "onlyVisibility = false": additionally the "fixedLayer" property will be false and the "layer" property will be deleted. - */ - void ResetRenderer(bool onlyVisibility = true, const BaseRenderer* renderer = nullptr); private: - void InsertLayerNodeInternal(DataNode* dataNode, int layer, const BaseRenderer* renderer = nullptr); - DataStorage::Pointer m_DataStorage; - RenderWindowLayerUtilities::RendererVector m_ControlledRenderer; }; } // namespace mitk #endif diff --git a/Modules/QtWidgets/src/QmitkRenderWindowContextDataStorageInspector.cpp b/Modules/QtWidgets/src/QmitkRenderWindowContextDataStorageInspector.cpp index 664f99a2f6..cff14a7f17 100644 --- a/Modules/QtWidgets/src/QmitkRenderWindowContextDataStorageInspector.cpp +++ b/Modules/QtWidgets/src/QmitkRenderWindowContextDataStorageInspector.cpp @@ -1,144 +1,137 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // render window manager UI module #include "QmitkRenderWindowContextDataStorageInspector.h" #include #include #include #include #include // qt #include #include QmitkRenderWindowContextDataStorageInspector::QmitkRenderWindowContextDataStorageInspector( QWidget* parent /* =nullptr */, mitk::BaseRenderer* renderer /* = nullptr */) : QmitkAbstractDataStorageInspector(parent) { m_Controls.setupUi(this); mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer{ renderer }; m_RenderWindowLayerController = std::make_unique(); - m_RenderWindowLayerController->SetControlledRenderer(controlledRenderer); m_StorageModel = std::make_unique(this); m_StorageModel->SetControlledRenderer(controlledRenderer); 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); connect(m_Controls.renderWindowTreeView, &QTreeView::customContextMenuRequested, this, &QmitkRenderWindowContextDataStorageInspector::OnContextMenuRequested); SetUpConnections(); if (nullptr == renderer) { return; } m_StorageModel->SetCurrentRenderer(renderer); } QAbstractItemView* QmitkRenderWindowContextDataStorageInspector::GetView() { return m_Controls.renderWindowTreeView; } const QAbstractItemView* QmitkRenderWindowContextDataStorageInspector::GetView() const { return m_Controls.renderWindowTreeView; } void QmitkRenderWindowContextDataStorageInspector::SetSelectionMode(SelectionMode mode) { m_Controls.renderWindowTreeView->setSelectionMode(mode); } QmitkRenderWindowContextDataStorageInspector::SelectionMode QmitkRenderWindowContextDataStorageInspector::GetSelectionMode() const { return m_Controls.renderWindowTreeView->selectionMode(); } QItemSelectionModel* QmitkRenderWindowContextDataStorageInspector::GetDataNodeSelectionModel() const { return m_Controls.renderWindowTreeView->selectionModel(); } void QmitkRenderWindowContextDataStorageInspector::Initialize() { auto dataStorage = m_DataStorage.Lock(); if (dataStorage.IsNull()) return; m_StorageModel->SetDataStorage(dataStorage); mitk::NodePredicateAnd::Pointer noHelperObjects = mitk::NodePredicateAnd::New(); noHelperObjects->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))); noHelperObjects->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object"))); m_StorageModel->SetNodePredicate(noHelperObjects); m_RenderWindowLayerController->SetDataStorage(dataStorage); m_Connector->SetView(m_Controls.renderWindowTreeView); } void QmitkRenderWindowContextDataStorageInspector::SetUpConnections() { connect(m_StorageModel.get(), &QAbstractItemModel::rowsInserted, this, &QmitkRenderWindowContextDataStorageInspector::ModelRowsInserted); } void QmitkRenderWindowContextDataStorageInspector::ModelRowsInserted(const QModelIndex& parent, int /*start*/, int /*end*/) { m_Controls.renderWindowTreeView->setExpanded(parent, true); } -void QmitkRenderWindowContextDataStorageInspector::ResetRenderer() -{ - m_RenderWindowLayerController->ResetRenderer(true, m_StorageModel->GetCurrentRenderer()); - m_Controls.renderWindowTreeView->clearSelection(); -} - void QmitkRenderWindowContextDataStorageInspector::OnContextMenuRequested(const QPoint& pos) { QMenu contextMenu; contextMenu.addAction(tr("Reinit with node"), this, &QmitkRenderWindowContextDataStorageInspector::OnReinit); contextMenu.addAction(tr("Reset to node geometry"), this, &QmitkRenderWindowContextDataStorageInspector::OnReset); contextMenu.exec(this->mapToGlobal(pos)); } void QmitkRenderWindowContextDataStorageInspector::OnReinit() { auto nodes = this->GetSelectedNodes(); emit ReinitAction(nodes); } void QmitkRenderWindowContextDataStorageInspector::OnReset() { auto nodes = this->GetSelectedNodes(); emit ResetAction(nodes); } diff --git a/Modules/QtWidgets/src/QmitkRenderWindowDataStorageTreeModel.cpp b/Modules/QtWidgets/src/QmitkRenderWindowDataStorageTreeModel.cpp index 3d761af13c..8592a884a5 100644 --- a/Modules/QtWidgets/src/QmitkRenderWindowDataStorageTreeModel.cpp +++ b/Modules/QtWidgets/src/QmitkRenderWindowDataStorageTreeModel.cpp @@ -1,628 +1,627 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // render window manager UI module #include "QmitkRenderWindowDataStorageTreeModel.h" #include // 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_Root(nullptr) { 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 the node to each render window mitk::RenderWindowLayerUtilities::SetRenderWindowProperties(const_cast(node), renderer); } auto baseRenderer = m_BaseRenderer.Lock(); if (baseRenderer.IsNull()) { return; } mitk::NodePredicateBase::Pointer renderWindowPredicate = mitk::RenderWindowLayerUtilities::GetRenderWindowPredicate(baseRenderer); mitk::NodePredicateAnd::Pointer combinedNodePredicate = mitk::NodePredicateAnd::New(); combinedNodePredicate->AddPredicate(renderWindowPredicate); if (m_NodePredicate.IsNotNull()) { combinedNodePredicate->AddPredicate(m_NodePredicate); } if (combinedNodePredicate->CheckNode(node)) { AddNodeInternal(node, baseRenderer); } } void QmitkRenderWindowDataStorageTreeModel::NodeChanged(const mitk::DataNode* node) { auto item = m_Root->Find(node); if (nullptr != item) { auto parentItem = item->GetParent(); // as the root node should not be removed one should always have a parent item if (nullptr == parentItem) { return; } auto index = createIndex(item->GetIndex(), 0, item); emit dataChanged(index, index); } } void QmitkRenderWindowDataStorageTreeModel::NodeRemoved(const mitk::DataNode* node) { RemoveNodeInternal(node); } QModelIndex QmitkRenderWindowDataStorageTreeModel::index(int row, int column, const QModelIndex& parent) const { auto item = GetItemByIndex(parent); if (nullptr != item) { item = item->GetChild(row); } if (nullptr == item) { return QModelIndex(); } return createIndex(row, column, item); } QModelIndex QmitkRenderWindowDataStorageTreeModel::parent(const QModelIndex& parent) const { auto item = GetItemByIndex(parent); if (nullptr != item) { item = item->GetParent(); } if(nullptr == item) { return QModelIndex(); } if (item == m_Root) { return QModelIndex(); } return createIndex(item->GetIndex(), 0, item); } int QmitkRenderWindowDataStorageTreeModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const { auto item = GetItemByIndex(parent); if (nullptr == item) { return 0; } return item->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 { auto baseRenderer = m_BaseRenderer.Lock(); if (baseRenderer.IsNull()) { return QVariant(); } if (!index.isValid() || this != index.model()) { return QVariant(); } auto item = GetItemByIndex(index); if (nullptr == item) { return QVariant(); } auto dataNode = item->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*/) { auto baseRenderer = m_BaseRenderer.Lock(); if (baseRenderer.IsNull()) { return false; } if (!index.isValid() || this != index.model()) { return false; } auto item = GetItemByIndex(index); if (nullptr == item) { return false; } auto dataNode = item->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 item = GetItemByIndex(index); if (nullptr == item) { return Qt::NoItemFlags; } const auto dataNode = item->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) { auto baseRenderer = m_BaseRenderer.Lock(); if (baseRenderer.IsNull()) { return false; } if (action == Qt::IgnoreAction) { return true; } if (!data->hasFormat(QmitkMimeTypes::DataNodePtrs)) { return false; } if (!parent.isValid()) { return false; } 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 : qAsConst(dataNodeList)) { m_RenderWindowLayerController->MoveNodeToPosition(dataNode, layer, baseRenderer); } ResetTree(); UpdateModelData(); AdjustLayerProperty(); return true; } void QmitkRenderWindowDataStorageTreeModel::SetControlledRenderer(mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer) { - m_RenderWindowLayerController->SetControlledRenderer(controlledRenderer); m_ControlledRenderer = controlledRenderer; ResetTree(); auto dataStorage = m_DataStorage.Lock(); if (dataStorage.IsNull()) { return; } for (const auto& renderer : controlledRenderer) { if (nullptr == renderer) { continue; } auto allDataNodes = dataStorage->GetAll(); for (const auto& dataNode : *allDataNodes) { // add the node to each render window mitk::RenderWindowLayerUtilities::SetRenderWindowProperties(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::Pointer QmitkRenderWindowDataStorageTreeModel::GetCurrentRenderer() const { return m_BaseRenderer.Lock(); } void QmitkRenderWindowDataStorageTreeModel::ResetTree() { beginResetModel(); if (nullptr != m_Root) { m_Root->Delete(); } mitk::DataNode::Pointer rootDataNode = mitk::DataNode::New(); rootDataNode->SetName("Data Storage"); m_Root = new QmitkDataStorageTreeModelInternalItem(rootDataNode); endResetModel(); } void QmitkRenderWindowDataStorageTreeModel::UpdateModelData() { auto dataStorage = m_DataStorage.Lock(); if (dataStorage.IsNotNull()) { auto baseRenderer = m_BaseRenderer.Lock(); if (baseRenderer.IsNotNull()) { auto allDataNodes = dataStorage->GetAll(); for (const auto& dataNode : *allDataNodes) { // add the node to each render window mitk::RenderWindowLayerUtilities::SetRenderWindowProperties(dataNode, baseRenderer); } mitk::NodePredicateBase::Pointer renderWindowPredicate = mitk::RenderWindowLayerUtilities::GetRenderWindowPredicate(baseRenderer); mitk::NodePredicateAnd::Pointer combinedNodePredicate = mitk::NodePredicateAnd::New(); combinedNodePredicate->AddPredicate(renderWindowPredicate); if (m_NodePredicate.IsNotNull()) { combinedNodePredicate->AddPredicate(m_NodePredicate); } auto filteredDataNodes = dataStorage->GetSubset(combinedNodePredicate); for (const auto& dataNode : *filteredDataNodes) { AddNodeInternal(dataNode, baseRenderer); } } } } void QmitkRenderWindowDataStorageTreeModel::AdjustLayerProperty() { auto baseRenderer = m_BaseRenderer.Lock(); if (baseRenderer.IsNull()) { return; } std::vector treeAsVector; TreeToVector(m_Root, treeAsVector); int i = treeAsVector.size() - 1; for (auto it = treeAsVector.begin(); it != treeAsVector.end(); ++it) { auto dataNode = (*it)->GetDataNode(); dataNode->SetIntProperty("layer", i, baseRenderer); --i; } } void QmitkRenderWindowDataStorageTreeModel::TreeToVector(QmitkDataStorageTreeModelInternalItem* parent, std::vector& treeAsVector) const { QmitkDataStorageTreeModelInternalItem* item; for (int i = 0; i < parent->GetChildCount(); ++i) { item = parent->GetChild(i); TreeToVector(item, treeAsVector); treeAsVector.push_back(item); } } void QmitkRenderWindowDataStorageTreeModel::AddNodeInternal(const mitk::DataNode* dataNode, const mitk::BaseRenderer* renderer) { if (nullptr == dataNode || m_DataStorage.IsExpired() || nullptr != m_Root->Find(dataNode)) { return; } // find out if we have a root node auto parentItem = m_Root; QModelIndex index; auto parentDataNode = GetParentNode(dataNode); if (nullptr != parentDataNode) // no top level data node { parentItem = m_Root->Find(parentDataNode); if (nullptr == parentItem) { // parent node not contained in the tree; add it NodeAdded(parentDataNode); parentItem = m_Root->Find(parentDataNode); if (nullptr == parentItem) { // could not find and add the parent tree; abort return; } } // get the index of this parent with the help of the grand parent index = createIndex(parentItem->GetIndex(), 0, parentItem); } int firstRowWithASiblingBelow = 0; int nodeLayer = -1; dataNode->GetIntProperty("layer", nodeLayer, renderer); for (const auto& siblingItem : parentItem->GetChildren()) { int siblingLayer = -1; auto siblingNode = siblingItem->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)); parentItem->InsertChild(newNode, firstRowWithASiblingBelow); endInsertRows(); } void QmitkRenderWindowDataStorageTreeModel::RemoveNodeInternal(const mitk::DataNode* dataNode) { if (nullptr == dataNode || nullptr == m_Root) { return; } auto item = m_Root->Find(dataNode); if (nullptr == item) { return; } auto parentItem = item->GetParent(); auto parentIndex = GetIndexByItem(parentItem); auto children = item->GetChildren(); beginRemoveRows(parentIndex, item->GetIndex(), item->GetIndex()); parentItem->RemoveChild(item); delete item; endRemoveRows(); if (!children.empty()) { // rebuild tree because children could not be at the top level ResetTree(); UpdateModelData(); } } mitk::DataNode* QmitkRenderWindowDataStorageTreeModel::GetParentNode(const mitk::DataNode* node) const { mitk::DataNode* dataNode = nullptr; auto dataStorage = m_DataStorage.Lock(); if (dataStorage.IsNull()) { return dataNode; } auto sources = dataStorage->GetSources(node); if (sources->empty()) { return dataNode; } return sources->front(); } QmitkDataStorageTreeModelInternalItem* QmitkRenderWindowDataStorageTreeModel::GetItemByIndex(const QModelIndex& index) const { if (index.isValid()) { return static_cast(index.internalPointer()); } return m_Root; } QModelIndex QmitkRenderWindowDataStorageTreeModel::GetIndexByItem(QmitkDataStorageTreeModelInternalItem* item) const { if (item == m_Root) { return QModelIndex(); } return createIndex(item->GetIndex(), 0, item); } diff --git a/Modules/QtWidgets/src/mitkRenderWindowLayerController.cpp b/Modules/QtWidgets/src/mitkRenderWindowLayerController.cpp index 37cbe9cde5..4b8a8c91e3 100644 --- a/Modules/QtWidgets/src/mitkRenderWindowLayerController.cpp +++ b/Modules/QtWidgets/src/mitkRenderWindowLayerController.cpp @@ -1,563 +1,318 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // render window manager module #include "mitkRenderWindowLayerController.h" mitk::RenderWindowLayerController::RenderWindowLayerController() : m_DataStorage(nullptr) { // nothing here } void mitk::RenderWindowLayerController::SetDataStorage(DataStorage::Pointer dataStorage) { if (m_DataStorage != dataStorage) { // set the new data storage m_DataStorage = dataStorage; } } -void mitk::RenderWindowLayerController::SetControlledRenderer(RenderWindowLayerUtilities::RendererVector controlledRenderer) -{ - if (m_ControlledRenderer != controlledRenderer) - { - // set the new set of controlled renderer - m_ControlledRenderer = controlledRenderer; - } -} - -void mitk::RenderWindowLayerController::SetBaseDataNode(DataNode* dataNode, const BaseRenderer* renderer /*= nullptr*/) -{ - if (nullptr == dataNode) - { - return; - } - - if (nullptr == renderer) - { - // set the data node as base data node in all controlled renderer - for (const auto& renderer : m_ControlledRenderer) - { - if (nullptr != renderer) - { - SetBaseDataNode(dataNode, renderer); - } - } - } - else - { - // get the layer stack with the base data node of the current renderer - RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, true); - if (!stackedLayers.empty()) - { - // see if base layer exists - RenderWindowLayerUtilities::LayerStack::iterator layerStackIterator = stackedLayers.find(RenderWindowLayerUtilities::BASE_LAYER_INDEX); - if (layerStackIterator != stackedLayers.end()) - { - // remove the current base data node from the current renderer - layerStackIterator->second->GetPropertyList(renderer)->DeleteProperty("layer"); - layerStackIterator->second->SetBoolProperty("fixedLayer", false, renderer); - layerStackIterator->second->SetVisibility(false, renderer); - } - } - - // "RenderWindowLayerUtilities::BASE_LAYER_INDEX" indicates the base data node --> set as new background - dataNode->SetIntProperty("layer", RenderWindowLayerUtilities::BASE_LAYER_INDEX, renderer); - dataNode->SetBoolProperty("fixedLayer", true, renderer); - dataNode->SetVisibility(true, renderer); - dataNode->Modified(); - mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); - } -} - void mitk::RenderWindowLayerController::InsertLayerNode(DataNode* dataNode, int layer /*= RenderWindowLayerUtilities::TOP_LAYER_INDEX*/, const BaseRenderer* renderer /*= nullptr*/) { if (nullptr == dataNode) { return; } - if (nullptr == renderer) - { - // insert data node in all controlled renderer - for (const auto& renderer : m_ControlledRenderer) - { - if (nullptr != renderer) - { - InsertLayerNode(dataNode, layer, renderer); - } - } - } - else - { - if (RenderWindowLayerUtilities::BASE_LAYER_INDEX == layer) - { - // "RenderWindowLayerUtilities::BASE_LAYER_INDEX" indicates the base data node --> set as new background (overwrite current base node if needed) - SetBaseDataNode(dataNode, renderer); - } - else - { - InsertLayerNodeInternal(dataNode, layer, renderer); - } - } -} - -void mitk::RenderWindowLayerController::InsertLayerNodeInternal(DataNode* dataNode, int newLayer, const BaseRenderer* renderer /*= nullptr*/) -{ RenderWindowLayerUtilities::SetRenderWindowProperties(dataNode, renderer); - // get the layer stack without the base node of the current renderer - RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, false); + // get the layer stack of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer); if (stackedLayers.empty()) { // no layer stack for the current renderer - if (RenderWindowLayerUtilities::TOP_LAYER_INDEX == newLayer) + if (RenderWindowLayerUtilities::TOP_LAYER_INDEX == layer) { - // set given layer as first layer above base layer (= 1) - newLayer = 1; - // alternatively: no layer stack for the current renderer -> insert as background node - //SetBaseDataNode(dataNode, renderer); + // set given layer as first layer + layer = 0; } } else { - if (RenderWindowLayerUtilities::TOP_LAYER_INDEX == newLayer) + if (RenderWindowLayerUtilities::TOP_LAYER_INDEX == layer) { // get the first value (highest int-key -> topmost layer) // + 1 indicates inserting the node above the topmost layer - newLayer = stackedLayers.begin()->first + 1; + layer = stackedLayers.begin()->first + 1; } else { - MoveNodeToPosition(dataNode, newLayer, renderer); + MoveNodeToPosition(dataNode, layer, renderer); return; } } // update data storage (the "data node model") - dataNode->SetIntProperty("layer", newLayer, renderer); + dataNode->SetIntProperty("layer", layer, renderer); dataNode->Modified(); - mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); -} - -void mitk::RenderWindowLayerController::RemoveLayerNode(DataNode* dataNode, const BaseRenderer* renderer /*= nullptr*/) -{ - if (nullptr == dataNode) - { - return; - } - if (nullptr == renderer) { - // remove data node from all controlled renderer - for (const auto& renderer : m_ControlledRenderer) - { - if (nullptr != renderer) - { - RemoveLayerNode(dataNode, renderer); - } - } + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } else { - // "remove" node from the renderer list - dataNode->GetPropertyList(renderer)->DeleteProperty("layer"); - dataNode->SetBoolProperty("fixedLayer", false, renderer); - dataNode->SetVisibility(false, renderer); - dataNode->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); } } bool mitk::RenderWindowLayerController::MoveNodeToPosition(DataNode* dataNode, int newLayer, const BaseRenderer* renderer /*= nullptr*/) { if (nullptr == dataNode) { return false; } - if (nullptr == renderer) + // get the layer stack of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer); + if (!stackedLayers.empty()) { - // move data node to position in all controlled renderer - for (const auto& renderer : m_ControlledRenderer) + // get the current layer value of the given data node + int currentLayer; + bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); + if (wasFound && currentLayer != newLayer) { - if (nullptr != renderer) + // move the given data node to the specified layer + dataNode->SetIntProperty("layer", newLayer, renderer); + + int upperBound; + int lowerBound; + int step; + if (currentLayer < newLayer) { - MoveNodeToPosition(dataNode, newLayer, renderer); - // we don't store/need the returned boolean value - return false; + // move node up + upperBound = newLayer + 1; + lowerBound = currentLayer + 1; + step = -1; // move all other nodes one step down } - } - } - else - { - // get the layer stack without the base node of the current renderer - RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, false); - if (!stackedLayers.empty()) - { - // get the current layer value of the given data node - int currentLayer; - bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); - if (wasFound && currentLayer != newLayer) + else { - // move the given data node to the specified layer - dataNode->SetIntProperty("layer", newLayer, renderer); - - int upperBound; - int lowerBound; - int step; - if (currentLayer < newLayer) - { - // move node up - upperBound = newLayer + 1; - lowerBound = currentLayer + 1; - step = -1; // move all other nodes one step down - } - else - { - upperBound = currentLayer; - lowerBound = newLayer; - step = 1; // move all other nodes one step up - } + upperBound = currentLayer; + lowerBound = newLayer; + step = 1; // move all other nodes one step up + } - // move all other data nodes between the upper and the lower bound - for (auto& layer : stackedLayers) + // move all other data nodes between the upper and the lower bound + for (auto& layer : stackedLayers) + { + if (layer.second != dataNode && layer.first < upperBound && layer.first >= lowerBound) { - if (layer.second != dataNode && layer.first < upperBound && layer.first >= lowerBound) - { - layer.second->SetIntProperty("layer", layer.first + step, renderer); - } - // else: current data node is the selected data node or - // was previously already above the selected data node or - // was previously already below the new layer position + layer.second->SetIntProperty("layer", layer.first + step, renderer); } - dataNode->Modified(); + // else: current data node is the selected data node or + // was previously already above the selected data node or + // was previously already below the new layer position + } + dataNode->Modified(); + if (nullptr == renderer) + { + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } + else + { mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); - return true; } - // else: data node has no layer information or is already at the specified position + + return true; } - // else: do not work with empty layer stack + // else: data node has no layer information or is already at the specified position } + // else: do not work with empty layer stack return false; } bool mitk::RenderWindowLayerController::MoveNodeToFront(DataNode* dataNode, const BaseRenderer* renderer /*= nullptr*/) { if (nullptr == dataNode) { return false; } - if (nullptr == renderer) + // get the layer stack of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer); + if (!stackedLayers.empty()) { - // move data node to front in all controlled renderer - for (const auto& renderer : m_ControlledRenderer) + // get the first value (highest int-key -> topmost layer) + int topmostLayer = stackedLayers.begin()->first; + // get the current layer value of the given data node + int currentLayer; + bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); + if (wasFound && currentLayer < topmostLayer) { - if (nullptr != renderer) + // move the current data node above the current topmost layer + dataNode->SetIntProperty("layer", topmostLayer+1, renderer); + dataNode->Modified(); + if (nullptr == renderer) { - MoveNodeToFront(dataNode, renderer); - // we don't store/need the returned boolean value - return false; + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } - } - } - else - { - // get the layer stack without the base node of the current renderer - RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, false); - if (!stackedLayers.empty()) - { - // get the first value (highest int-key -> topmost layer) - int topmostLayer = stackedLayers.begin()->first; - // get the current layer value of the given data node - int currentLayer; - bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); - if (wasFound && currentLayer < topmostLayer) + else { - // move the current data node above the current topmost layer - dataNode->SetIntProperty("layer", topmostLayer+1, renderer); - dataNode->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); - return true; } - // else: data node has no layer information or is already the topmost layer node + return true; } - // else: do not work with empty layer stack + // else: data node has no layer information or is already the topmost layer node } + // else: do not work with empty layer stack return false; } bool mitk::RenderWindowLayerController::MoveNodeToBack(DataNode* dataNode, const BaseRenderer* renderer /*= nullptr*/) { if (nullptr == dataNode) { return false; } - if (nullptr == renderer) - { - // move data node to back in all controlled renderer - for (const auto& renderer : m_ControlledRenderer) - { - if (nullptr != renderer) - { - MoveNodeToBack(dataNode, renderer); - // we don't store/need the returned boolean value - return false; - } - } - } - else + // get the layer stack of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer); + if (!stackedLayers.empty()) { - // get the layer stack without the base node of the current renderer - RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, false); - if (!stackedLayers.empty()) + // get the last value (lowest int-key) + int lowermostLayer = stackedLayers.rbegin()->first; + // get the current layer value of the given data node + int currentLayer; + bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); + if (wasFound && currentLayer > lowermostLayer) { - // get the last value (lowest int-key) - // cannot be the base layer as the base node was excluded by the 'GetLayerStack'-function - int lowermostLayer = stackedLayers.rbegin()->first; - // get the current layer value of the given data node - int currentLayer; - bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); - if (wasFound && currentLayer > lowermostLayer) + // move the current data node to the current lowermost layer + dataNode->SetIntProperty("layer", lowermostLayer, renderer); + // move all other data nodes one layer up + for (auto& layer : stackedLayers) { - // move the current data node to the current lowermost layer - dataNode->SetIntProperty("layer", lowermostLayer, renderer); - // move all other data nodes one layer up - for (auto& layer : stackedLayers) + if (layer.second != dataNode && layer.first < currentLayer) { - if (layer.second != dataNode && layer.first < currentLayer) - { - layer.second->SetIntProperty("layer", layer.first + 1, renderer); - } - // else: current data node is the selected data node or - // was previously already above the selected data node + layer.second->SetIntProperty("layer", layer.first + 1, renderer); } - dataNode->Modified(); + // else: current data node is the selected data node or + // was previously already above the selected data node + } + dataNode->Modified(); + if (nullptr == renderer) + { + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + + } + else + { mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); - return true; } - // else: data node has no layer information or is already the lowermost layer node + return true; } - // else: do not work with empty layer stack + // else: data node has no layer information or is already the lowermost layer node } + // else: do not work with empty layer stack return false; } bool mitk::RenderWindowLayerController::MoveNodeUp(DataNode* dataNode, const BaseRenderer* renderer /*= nullptr*/) { if (nullptr == dataNode) { return false; } - if (nullptr == renderer) - { - // move data node down in all controlled renderer - for (const auto& renderer : m_ControlledRenderer) - { - if (nullptr != renderer) - { - MoveNodeUp(dataNode, renderer); - // we don't store/need the returned boolean value - return false; - } - } - } - else + // get the layer stack of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer); + if (!stackedLayers.empty()) { - // get the layer stack without the base node of the current renderer - RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, false); - if (!stackedLayers.empty()) + // get the current layer value of the given data node + int currentLayer; + bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); + if (wasFound) { - // get the current layer value of the given data node - int currentLayer; - bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); - if (wasFound) + // get the current layer in the map of stacked layers + RenderWindowLayerUtilities::LayerStack::const_iterator layerStackIterator = stackedLayers.find(currentLayer); + if (layerStackIterator != stackedLayers.end() && layerStackIterator != stackedLayers.begin()) { - // get the current layer in the map of stacked layers - RenderWindowLayerUtilities::LayerStack::const_iterator layerStackIterator = stackedLayers.find(currentLayer); - if (layerStackIterator != stackedLayers.end() && layerStackIterator != stackedLayers.begin()) + // found the element in the map, at different position than 'begin' -> + // current node is not on the topmost layer and therefore can be moved one layer up + // swap the layers of the dataNode and the dataNode on the next higher layer (previous map element) + RenderWindowLayerUtilities::LayerStack::const_iterator prevLayerStackIterator = std::prev(layerStackIterator); + dataNode->SetIntProperty("layer", prevLayerStackIterator->first, renderer); + prevLayerStackIterator->second->SetIntProperty("layer", currentLayer, renderer); + dataNode->Modified(); + if (nullptr == renderer) + { + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + + } + else { - // found the element in the map, at different position than 'begin' -> - // current node is not on the topmost layer and therefore can be moved one layer up - // swap the layers of the dataNode and the dataNode on the next higher layer (previous map element) - RenderWindowLayerUtilities::LayerStack::const_iterator prevLayerStackIterator = std::prev(layerStackIterator); - dataNode->SetIntProperty("layer", prevLayerStackIterator->first, renderer); - prevLayerStackIterator->second->SetIntProperty("layer", currentLayer, renderer); - dataNode->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); - return true; } - // else: layer stack does not contain a layer with the 'currentLayer'data node or - // layer is already the topmost layer node + return true; } - // else: data node has no layer information + // else: layer stack does not contain a layer with the 'currentLayer'data node or + // layer is already the topmost layer node } - // else: do not work with empty layer stack + // else: data node has no layer information } + // else: do not work with empty layer stack return false; } bool mitk::RenderWindowLayerController::MoveNodeDown(DataNode* dataNode, const BaseRenderer* renderer /*= nullptr*/) { if (nullptr == dataNode) { return false; } - if (nullptr == renderer) - { - // move data node up in all controlled renderer - for (const auto& renderer : m_ControlledRenderer) - { - if (nullptr != renderer) - { - MoveNodeDown(dataNode, renderer); - // we don't store/need the returned boolean value - return false; - } - } - } - else + // get the layer stack of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer); + if (!stackedLayers.empty()) { - // get the layer stack without the base node of the current renderer - RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, false); - if (!stackedLayers.empty()) + // get the current layer value of the given data node + int currentLayer; + bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); + if (wasFound) { - // get the current layer value of the given data node - int currentLayer; - bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); - if (wasFound) + // get the current layer in the map of stacked layers + RenderWindowLayerUtilities::LayerStack::const_iterator layerStackIterator = stackedLayers.find(currentLayer); + if (layerStackIterator != stackedLayers.end()) { - // get the current layer in the map of stacked layers - RenderWindowLayerUtilities::LayerStack::const_iterator layerStackIterator = stackedLayers.find(currentLayer); - if (layerStackIterator != stackedLayers.end()) + // found the element in the map ... + RenderWindowLayerUtilities::LayerStack::const_iterator nextLayerStackIterator = std::next(layerStackIterator); + if (nextLayerStackIterator != stackedLayers.end()) { - // found the element in the map ... - RenderWindowLayerUtilities::LayerStack::const_iterator nextLayerStackIterator = std::next(layerStackIterator); - if (nextLayerStackIterator != stackedLayers.end()) - { - // ... and found a successor -> - // current node is not on the lowermost layer and therefore can be moved one layer down - // swap the layers of the dataNode and the dataNode on the next lower layer (next map element) - dataNode->SetIntProperty("layer", nextLayerStackIterator->first, renderer); - nextLayerStackIterator->second->SetIntProperty("layer", currentLayer, renderer); - dataNode->Modified(); - mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); - return true; - } - // else: data node is already the lowermost layer node + // ... and found a successor -> + // current node is not on the lowermost layer and therefore can be moved one layer down + // swap the layers of the dataNode and the dataNode on the next lower layer (next map element) + dataNode->SetIntProperty("layer", nextLayerStackIterator->first, renderer); + nextLayerStackIterator->second->SetIntProperty("layer", currentLayer, renderer); + dataNode->Modified(); + mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); + return true; } - // else: layer stack does not contain a layer with the 'currentLayer' + // else: data node is already the lowermost layer node } - // else: data node has no layer information + // else: layer stack does not contain a layer with the 'currentLayer' } - // else: do not work with empty layer stack + // else: data node has no layer information } + // else: do not work with empty layer stack return false; } - -void mitk::RenderWindowLayerController::SetVisibilityOfDataNode(bool visibility, DataNode* dataNode, const BaseRenderer* renderer /*=nullptr*/) -{ - if (nullptr == dataNode) - { - return; - } - - if (nullptr == renderer) - { - // set visibility of data node in all controlled renderer - for (const auto& renderer : m_ControlledRenderer) - { - if (nullptr != renderer) - { - SetVisibilityOfDataNode(visibility, dataNode, renderer); - } - } - } - else - { - dataNode->SetVisibility(visibility, renderer); - dataNode->Modified(); - mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); - } -} - -void mitk::RenderWindowLayerController::HideDataNodeInAllRenderer(const DataNode* dataNode) -{ - if (nullptr == dataNode) - { - return; - } - - for (const auto& renderer : m_ControlledRenderer) - { - if (nullptr != renderer) - { - dataNode->GetPropertyList(renderer)->SetBoolProperty("visible", false); - } - } - - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); -} - -void mitk::RenderWindowLayerController::ResetRenderer(bool onlyVisibility /*= true*/, const BaseRenderer* renderer /*= nullptr*/) -{ - if (nullptr == renderer) - { - // reset all controlled renderer - for (const auto& renderer : m_ControlledRenderer) - { - if (nullptr != renderer) - { - ResetRenderer(onlyVisibility, renderer); - } - } - } - else - { - // get the layer stack with the base node of the current renderer - RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, true); - if (!stackedLayers.empty()) - { - for (const auto& layer : stackedLayers) - { - int layerLevel; - layer.second->GetIntProperty("layer", layerLevel, renderer); - if (RenderWindowLayerUtilities::BASE_LAYER_INDEX == layerLevel) - { - // set base data node visibility to true - layer.second->SetVisibility(true, renderer); - } - else - { - // set visibility of all other data nodes to false - layer.second->SetVisibility(false, renderer); - - // modify layer node - if (!onlyVisibility) - { - // clear mode: additionally remove layer node from current renderer - layer.second->GetPropertyList(renderer)->DeleteProperty("layer"); - layer.second->SetBoolProperty("fixedLayer", false, renderer); - } - } - layer.second->Modified(); - } - - mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); - } - } -} diff --git a/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageInspector.h b/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageInspector.h index 201f8cf854..ee454680c7 100644 --- a/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageInspector.h +++ b/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageInspector.h @@ -1,92 +1,88 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef QmitkRenderWindowDataStorageInspector_h #define QmitkRenderWindowDataStorageInspector_h // render window manager UI module #include "MitkRenderWindowManagerUIExports.h" #include "ui_QmitkRenderWindowDataStorageInspector.h" // render window manager module #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' */ QAbstractItemView* GetView() override; /** * @brief See 'QmitkAbstractDataStorageInspector' */ const QAbstractItemView* GetView() const override; /** * @brief See 'QmitkAbstractDataStorageInspector' */ void SetSelectionMode(SelectionMode mode) override; /** * @brief See 'QmitkAbstractDataStorageInspector' */ 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: void Initialize() override; void SetUpConnections(); Ui::QmitkRenderWindowDataStorageInspector m_Controls; std::unique_ptr m_StorageModel; std::unique_ptr m_RenderWindowLayerController; std::unique_ptr m_RenderWindowViewDirectionController; }; #endif diff --git a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.cpp b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.cpp index 8094567bc2..f489241706 100644 --- a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.cpp +++ b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.cpp @@ -1,167 +1,142 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // 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.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.renderWindowTreeView; } const QAbstractItemView* QmitkRenderWindowDataStorageInspector::GetView() const { return m_Controls.renderWindowTreeView; } void QmitkRenderWindowDataStorageInspector::SetSelectionMode(SelectionMode mode) { m_Controls.renderWindowTreeView->setSelectionMode(mode); } QmitkRenderWindowDataStorageInspector::SelectionMode QmitkRenderWindowDataStorageInspector::GetSelectionMode() const { return m_Controls.renderWindowTreeView->selectionMode(); } void QmitkRenderWindowDataStorageInspector::Initialize() { auto dataStorage = m_DataStorage.Lock(); if (dataStorage.IsNull()) return; m_StorageModel->SetDataStorage(dataStorage); m_StorageModel->SetNodePredicate(m_NodePredicate); m_RenderWindowLayerController->SetDataStorage(dataStorage); m_RenderWindowViewDirectionController->SetDataStorage(dataStorage); 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)); + connect(m_Controls.radioButtonAxial, &QRadioButton::clicked, changeViewDirectionSignalMapper, static_cast(&QSignalMapper::map)); + connect(m_Controls.radioButtonCoronal, &QRadioButton::clicked, changeViewDirectionSignalMapper, static_cast(&QSignalMapper::map)); + connect(m_Controls.radioButtonSagittal, &QRadioButton::clicked, changeViewDirectionSignalMapper, static_cast(&QSignalMapper::map)); + connect(m_Controls.radioButton3D, &QRadioButton::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::AnatomicalPlane viewDirection = selectedRenderer->GetSliceNavigationController()->GetDefaultViewDirection(); switch (viewDirection) { case mitk::AnatomicalPlane::Axial: m_Controls.radioButtonAxial->setChecked(true); break; case mitk::AnatomicalPlane::Coronal: m_Controls.radioButtonCoronal->setChecked(true); break; case mitk::AnatomicalPlane::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.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.renderWindowTreeView->clearSelection(); - } - } -} - -void QmitkRenderWindowDataStorageInspector::ResetRenderer() -{ - m_RenderWindowLayerController->ResetRenderer(true, m_StorageModel->GetCurrentRenderer()); - 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 785e20c50c..0ad31773e2 100644 --- a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.ui +++ b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageInspector.ui @@ -1,92 +1,78 @@ 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/QmitkRenderWindowDataStorageListModel.cpp b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageListModel.cpp index 9b6face241..812b6356e3 100644 --- a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageListModel.cpp +++ b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageListModel.cpp @@ -1,351 +1,350 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // render window manager UI module #include "QmitkRenderWindowDataStorageListModel.h" // qt widgets module #include "QmitkCustomVariants.h" #include "QmitkEnums.h" #include "QmitkMimeTypes.h" #include "QmitkNodeDescriptorManager.h" QmitkRenderWindowDataStorageListModel::QmitkRenderWindowDataStorageListModel(QObject* parent /*= nullptr*/) : QmitkAbstractDataStorageModel(parent) { m_RenderWindowLayerController = std::make_unique(); } void QmitkRenderWindowDataStorageListModel::DataStorageChanged() { m_RenderWindowLayerController->SetDataStorage(m_DataStorage.Lock()); UpdateModelData(); } void QmitkRenderWindowDataStorageListModel::NodePredicateChanged() { UpdateModelData(); } void QmitkRenderWindowDataStorageListModel::NodeAdded(const mitk::DataNode* node) { // add a node to each render window specific list (or to a global list initially) AddDataNodeToAllRenderer(const_cast(node)); UpdateModelData(); } void QmitkRenderWindowDataStorageListModel::NodeChanged(const mitk::DataNode* /*node*/) { // nothing here, since the "'NodeChanged'-event is currently sent far too often } void QmitkRenderWindowDataStorageListModel::NodeRemoved(const mitk::DataNode* /*node*/) { // update model data to create a new list without the removed data node UpdateModelData(); } QModelIndex QmitkRenderWindowDataStorageListModel::index(int row, int column, const QModelIndex& parent) const { bool hasIndex = this->hasIndex(row, column, parent); if (hasIndex) { return this->createIndex(row, column); } return QModelIndex(); } QModelIndex QmitkRenderWindowDataStorageListModel::parent(const QModelIndex& /*child*/) const { return QModelIndex(); } int QmitkRenderWindowDataStorageListModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const { if (parent.isValid()) { return 0; } return static_cast(m_LayerStack.size()); } int QmitkRenderWindowDataStorageListModel::columnCount(const QModelIndex& parent /*= QModelIndex()*/) const { if (parent.isValid()) { return 0; } return 1; } QVariant QmitkRenderWindowDataStorageListModel::data(const QModelIndex& index, int role) const { auto baseRenderer = m_BaseRenderer.Lock(); if (baseRenderer.IsNull()) { return QVariant(); } if (!index.isValid() || this != index.model()) { return QVariant(); } if (index.row() < 0 || index.row() >= static_cast(m_LayerStack.size())) { return QVariant(); } mitk::RenderWindowLayerUtilities::LayerStack::const_iterator layerStackIt = m_LayerStack.begin(); std::advance(layerStackIt, index.row()); mitk::DataNode* dataNode = layerStackIt->second; 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 QmitkRenderWindowDataStorageListModel::setData(const QModelIndex& index, const QVariant& value, int role /*= Qt::EditRole*/) { auto baseRenderer = m_BaseRenderer.Lock(); if (baseRenderer.IsNull()) { return false; } if (!index.isValid() || this != index.model()) { return false; } if (index.row() < 0 || index.row() >= static_cast(m_LayerStack.size())) { return false; } mitk::RenderWindowLayerUtilities::LayerStack::const_iterator layerStackIt = m_LayerStack.begin(); std::advance(layerStackIt, index.row()); mitk::DataNode* dataNode = layerStackIt->second; 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 QmitkRenderWindowDataStorageListModel::flags(const QModelIndex &index) const { if (this != index.model()) { return Qt::NoItemFlags; } if (!index.isValid()) { return Qt::ItemIsDropEnabled; } return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } Qt::DropActions QmitkRenderWindowDataStorageListModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } Qt::DropActions QmitkRenderWindowDataStorageListModel::supportedDragActions() const { return Qt::CopyAction | Qt::MoveAction; } QStringList QmitkRenderWindowDataStorageListModel::mimeTypes() const { QStringList types = QAbstractItemModel::mimeTypes(); types << QmitkMimeTypes::DataNodePtrs; return types; } QMimeData* QmitkRenderWindowDataStorageListModel::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 QmitkRenderWindowDataStorageListModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int /*row*/, int column, const QModelIndex& parent) { auto baseRenderer = m_BaseRenderer.Lock(); if (baseRenderer.IsNull()) { return false; } 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 : qAsConst(dataNodeList)) { m_RenderWindowLayerController->MoveNodeToPosition(dataNode, layer, baseRenderer); } UpdateModelData(); return true; } return false; } void QmitkRenderWindowDataStorageListModel::SetControlledRenderer(mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer) { - m_RenderWindowLayerController->SetControlledRenderer(controlledRenderer); auto dataStorage = m_DataStorage.Lock(); if (dataStorage.IsNotNull()) { 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; } AddDataNodeToAllRenderer(dataNode); } } } void QmitkRenderWindowDataStorageListModel::SetCurrentRenderer(mitk::BaseRenderer* baseRenderer) { if (m_BaseRenderer == baseRenderer) { return; } m_BaseRenderer = baseRenderer; if (!m_BaseRenderer.IsExpired()) { UpdateModelData(); } } mitk::BaseRenderer::Pointer QmitkRenderWindowDataStorageListModel::GetCurrentRenderer() const { return m_BaseRenderer.Lock(); } void QmitkRenderWindowDataStorageListModel::AddDataNodeToAllRenderer(mitk::DataNode* dataNode) { m_RenderWindowLayerController->InsertLayerNode(dataNode); } void QmitkRenderWindowDataStorageListModel::UpdateModelData() { auto dataStorage = m_DataStorage.Lock(); if (dataStorage.IsNotNull()) { auto baseRenderer = m_BaseRenderer.Lock(); if (baseRenderer.IsNotNull()) { // update the model, so that it will be filled with the nodes of the new data storage beginResetModel(); // get the current layer stack of the given base renderer m_LayerStack = mitk::RenderWindowLayerUtilities::GetLayerStack(dataStorage, baseRenderer, true); endResetModel(); } } }