diff --git a/Modules/QtWidgets/src/QmitkDataStorageDefaultListModel.cpp b/Modules/QtWidgets/src/QmitkDataStorageDefaultListModel.cpp index 6cedc1e324..a27b5f1098 100644 --- a/Modules/QtWidgets/src/QmitkDataStorageDefaultListModel.cpp +++ b/Modules/QtWidgets/src/QmitkDataStorageDefaultListModel.cpp @@ -1,158 +1,172 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical Image Computing. 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. ===================================================================*/ #include // qt widgets module #include "QmitkCustomVariants.h" #include "QmitkEnums.h" +#include "QmitkNodeDescriptorManager.h" QmitkDataStorageDefaultListModel::QmitkDataStorageDefaultListModel(QObject *parent) : QmitkAbstractDataStorageModel(parent) { } void QmitkDataStorageDefaultListModel::DataStorageChanged() { UpdateModelData(); } void QmitkDataStorageDefaultListModel::NodePredicateChanged() { UpdateModelData(); } void QmitkDataStorageDefaultListModel::NodeAdded(const mitk::DataNode* node) { UpdateModelData(); } void QmitkDataStorageDefaultListModel::NodeChanged(const mitk::DataNode* node) { // nothing here, since the "'NodeChanged'-event is currently sent far too often //UpdateModelData(); } void QmitkDataStorageDefaultListModel::NodeRemoved(const mitk::DataNode* node) { UpdateModelData(); } QModelIndex QmitkDataStorageDefaultListModel::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 QmitkDataStorageDefaultListModel::parent(const QModelIndex &child) const { return QModelIndex(); } int QmitkDataStorageDefaultListModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return m_DataNodes.size(); } int QmitkDataStorageDefaultListModel::columnCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return 1; } QVariant QmitkDataStorageDefaultListModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.model() != this) { return QVariant(); } if(index.row() < 0 || index.row() >= m_DataNodes.size()) { return QVariant(); } mitk::DataNode::Pointer dataNode = m_DataNodes.at(index.row()); - if (Qt::DisplayRole == role) + QString nodeName = QString::fromStdString(dataNode->GetName()); + if (nodeName.isEmpty()) + nodeName = "unnamed"; + + if (role == Qt::DisplayRole) + return nodeName; + else if (role == Qt::ToolTipRole) + return nodeName; + else if (role == Qt::DecorationRole) { - return QVariant(QString::fromStdString(dataNode->GetName())); + QmitkNodeDescriptor *nodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor(dataNode); + return nodeDescriptor->GetIcon(dataNode); } - else if (QmitkDataNodeRole == role) + else if (role == QmitkDataNodeRole) { - return QVariant::fromValue(dataNode); + return QVariant::fromValue(mitk::DataNode::Pointer(dataNode)); + } + else if (role == QmitkDataNodeRawPointerRole) + { + return QVariant::fromValue(dataNode); } return QVariant(); } QVariant QmitkDataStorageDefaultListModel::headerData(int section, Qt::Orientation orientation, int role) const { return QVariant(tr("Nodes")); } Qt::ItemFlags QmitkDataStorageDefaultListModel::flags(const QModelIndex &index) const { if (index.isValid() && index.model() == this) { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } return Qt::NoItemFlags; } void QmitkDataStorageDefaultListModel::UpdateModelData() { mitk::DataStorage::SetOfObjects::ConstPointer dataNodes; if (!m_DataStorage.IsExpired()) { auto dataStorage = m_DataStorage.Lock(); if (m_NodePredicate.IsNotNull()) { dataNodes = dataStorage->GetSubset(m_NodePredicate); } else { dataNodes = dataStorage->GetAll(); } } // update the model, so that it will be filled with the nodes of the new data storage beginResetModel(); m_DataNodes.clear(); // add all (filtered) nodes to the vector of nodes if (dataNodes != nullptr) { for (auto& node : *dataNodes) { m_DataNodes.push_back(node); } } endResetModel(); } diff --git a/Modules/QtWidgets/src/QmitkDataStorageSimpleTreeModel.cpp b/Modules/QtWidgets/src/QmitkDataStorageSimpleTreeModel.cpp index a540a21a92..6b24c9d4a3 100644 --- a/Modules/QtWidgets/src/QmitkDataStorageSimpleTreeModel.cpp +++ b/Modules/QtWidgets/src/QmitkDataStorageSimpleTreeModel.cpp @@ -1,374 +1,370 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical Image Computing. 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. ===================================================================*/ #include #include #include // qt widgets module #include "QmitkCustomVariants.h" #include "QmitkEnums.h" QmitkDataStorageSimpleTreeModel::QmitkDataStorageSimpleTreeModel(QObject *parent) : QmitkAbstractDataStorageModel(parent), m_Root(nullptr) { ResetTree(); } QmitkDataStorageSimpleTreeModel::~QmitkDataStorageSimpleTreeModel() { m_Root->Delete(); m_Root = nullptr; }; void QmitkDataStorageSimpleTreeModel::ResetTree() { mitk::DataNode::Pointer rootDataNode = mitk::DataNode::New(); rootDataNode->SetName("Data Storage"); m_Root = new TreeItem(rootDataNode, 0); } void QmitkDataStorageSimpleTreeModel::DataStorageChanged() { if (m_Root) { m_Root->Delete(); } ResetTree(); UpdateModelData(); } void QmitkDataStorageSimpleTreeModel::NodePredicateChanged() { ResetTree(); UpdateModelData(); } void QmitkDataStorageSimpleTreeModel::NodeAdded(const mitk::DataNode *node) { if (node == nullptr || m_DataStorage.IsExpired() || !m_DataStorage.Lock()->Exists(node) || m_Root->Find(node) != nullptr) return; this->AddNodeInternal(node); } void QmitkDataStorageSimpleTreeModel::NodeChanged(const mitk::DataNode *node) { TreeItem *treeItem = m_Root->Find(node); if (treeItem) { TreeItem *parentTreeItem = treeItem->GetParent(); // as the root node should not be removed one should always have a parent item if (!parentTreeItem) return; QModelIndex index = this->createIndex(treeItem->GetIndex(), 0, treeItem); // now emit the dataChanged signal emit dataChanged(index, index); } } void QmitkDataStorageSimpleTreeModel::NodeRemoved(const mitk::DataNode *node) { if (node == nullptr || !m_Root) return; TreeItem *treeItem = m_Root->Find(node); if (!treeItem) return; // return because there is no treeitem containing this node TreeItem *parentTreeItem = treeItem->GetParent(); QModelIndex parentIndex = this->IndexFromTreeItem(parentTreeItem); // emit beginRemoveRows event (QModelIndex is empty because we dont have a tree model) this->beginRemoveRows(parentIndex, treeItem->GetIndex(), treeItem->GetIndex()); // remove node std::vector children = treeItem->GetChildren(); m_TreeItems.remove(treeItem); delete treeItem; //delete in tree if (!children.empty()) { //if not empty we have to rebuild the whole representation, //because the children could be now top level, or at another //source/parent. this->UpdateModelData(); } } QModelIndex QmitkDataStorageSimpleTreeModel::index(int row, int column, const QModelIndex &parent) const { TreeItem *parentItem; if (!parent.isValid() || parent.model() != this) parentItem = m_Root; else parentItem = static_cast(parent.internalPointer()); if (parentItem) { TreeItem *childItem = parentItem->GetChild(row); if (childItem) return createIndex(row, column, childItem); } return QModelIndex(); } QModelIndex QmitkDataStorageSimpleTreeModel::parent(const QModelIndex &child) const { if (!child.isValid() || !m_Root || child.model() != this) return QModelIndex(); TreeItem *childItem = this->TreeItemFromIndex(child); if (!childItem) return QModelIndex(); TreeItem *parentItem = childItem->GetParent(); if (parentItem == m_Root) return QModelIndex(); return this->createIndex(parentItem->GetIndex(), 0, parentItem); } QmitkDataStorageSimpleTreeModel::TreeItem *QmitkDataStorageSimpleTreeModel::TreeItemFromIndex( const QModelIndex &index) const { if (index.isValid() && index.model() == this) { auto item = static_cast(index.internalPointer()); auto finding = std::find(std::begin(m_TreeItems), std::end(m_TreeItems), item); if (finding == std::end(m_TreeItems)) { return nullptr; } return item; } else return m_Root; } int QmitkDataStorageSimpleTreeModel::rowCount(const QModelIndex &parent) const { TreeItem *parentTreeItem = this->TreeItemFromIndex(parent); if (parentTreeItem) return parentTreeItem->GetChildCount(); else return 0; } int QmitkDataStorageSimpleTreeModel::columnCount(const QModelIndex &parent) const { return 1; } QVariant QmitkDataStorageSimpleTreeModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.model() != this) { return QVariant(); } auto treeItem = this->TreeItemFromIndex(index); if (!treeItem) return QVariant(); mitk::DataNode *dataNode = treeItem->GetDataNode(); QString nodeName = QString::fromStdString(dataNode->GetName()); if (nodeName.isEmpty()) { nodeName = "unnamed"; } if (role == Qt::DisplayRole) return nodeName; else if (role == Qt::ToolTipRole) return nodeName; else if (role == Qt::DecorationRole) { QmitkNodeDescriptor *nodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor(dataNode); return nodeDescriptor->GetIcon(dataNode); } - else if (role == Qt::CheckStateRole) - { - return dataNode->IsVisible(0); - } else if (role == QmitkDataNodeRole) { return QVariant::fromValue(mitk::DataNode::Pointer(dataNode)); } else if (role == QmitkDataNodeRawPointerRole) { return QVariant::fromValue(dataNode); } return QVariant(); } bool QmitkDataStorageSimpleTreeModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid() || index.model() != this) return false; auto treeItem = this->TreeItemFromIndex(index); if (!treeItem) return false; mitk::DataNode *dataNode = treeItem->GetDataNode(); if (!dataNode) return false; if (role == Qt::EditRole && !value.toString().isEmpty()) { dataNode->SetName(value.toString().toStdString().c_str()); } else if (role == Qt::CheckStateRole) { // Please note: value.toInt() returns 2, independentely from the actual checkstate of the index element. // Therefore the checkstate is being estimated again here. QVariant qcheckstate = index.data(Qt::CheckStateRole); int checkstate = qcheckstate.toInt(); bool isVisible = bool(checkstate); dataNode->SetVisibility(!isVisible); } // inform listeners about changes emit dataChanged(index, index); return true; } QVariant QmitkDataStorageSimpleTreeModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole && m_Root) return QString::fromStdString(m_Root->GetDataNode()->GetName()); return QVariant(); } Qt::ItemFlags QmitkDataStorageSimpleTreeModel::flags(const QModelIndex &index) const { if (index.isValid() && index.model() == this) { auto treeItem = this->TreeItemFromIndex(index); if (!treeItem) return Qt::NoItemFlags; const auto dataNode = treeItem->GetDataNode(); if (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(dataNode)) { return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; } else { return Qt::NoItemFlags; } } return Qt::NoItemFlags; } mitk::DataNode *QmitkDataStorageSimpleTreeModel::GetParentNode(const mitk::DataNode *node) const { mitk::DataNode *dataNode = nullptr; mitk::DataStorage::SetOfObjects::ConstPointer _Sources = m_DataStorage.Lock()->GetSources(node); if (_Sources->Size() > 0) dataNode = _Sources->front(); return dataNode; } void QmitkDataStorageSimpleTreeModel::AddNodeInternal(const mitk::DataNode *node) { if (node == nullptr || m_DataStorage.IsExpired() || !m_DataStorage.Lock()->Exists(node) || m_Root->Find(node) != 0) return; // find out if we have a root node TreeItem *parentTreeItem = m_Root; QModelIndex index; mitk::DataNode *parentDataNode = this->GetParentNode(node); if (parentDataNode) // no top level data node { parentTreeItem = m_Root->Find(parentDataNode); // find the corresponding tree item if (!parentTreeItem) { this->NodeAdded(parentDataNode); parentTreeItem = m_Root->Find(parentDataNode); if (!parentTreeItem) 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; node->GetIntProperty("layer", nodeLayer); for (TreeItem *siblingTreeItem : parentTreeItem->GetChildren()) { int siblingLayer = -1; if (mitk::DataNode *siblingNode = siblingTreeItem->GetDataNode()) { siblingNode->GetIntProperty("layer", siblingLayer); } if (nodeLayer > siblingLayer) { break; } ++firstRowWithASiblingBelow; } beginInsertRows(index, firstRowWithASiblingBelow, firstRowWithASiblingBelow); auto newNode = new TreeItem(const_cast(node)); parentTreeItem->InsertChild(newNode, firstRowWithASiblingBelow); m_TreeItems.push_back(newNode); endInsertRows(); } QModelIndex QmitkDataStorageSimpleTreeModel::IndexFromTreeItem(TreeItem *item) const { if (item == m_Root) return QModelIndex(); else return this->createIndex(item->GetIndex(), 0, item); } void QmitkDataStorageSimpleTreeModel::UpdateModelData() { if (!m_DataStorage.IsExpired()) { auto nodeset = m_DataStorage.Lock()->GetAll(); if (m_NodePredicate != nullptr) { nodeset = m_DataStorage.Lock()->GetSubset(m_NodePredicate); } for (const auto& node : *nodeset) { this->AddNodeInternal(node); } } }