diff --git a/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageTreeModel.h b/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageTreeModel.h index 7fafa6cd65..44a37fbf55 100644 --- a/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageTreeModel.h +++ b/Modules/RenderWindowManagerUI/include/QmitkRenderWindowDataStorageTreeModel.h @@ -1,116 +1,136 @@ /*=================================================================== 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 ... + * @brief Adjust the layer property according to the current tree. + * The function will set the "layer" property of each underlying data node so that it fits the + * the actual hierarchy represented by the current tree. + */ + void AdjustLayerProperty(); + /** + * @brief Fill a vector of tree items in a depth-first order (child-first). + */ + void TreeToVector(QmitkDataStorageTreeModelInternalItem* parent, std::vector& treeAsVector) const; + /** + * @brief Add the given data node to the tree of the given renderer. + * The given renderer specifies the "layer"-property that is used for adding the new tree item + * to the tree. The "layer"-property may be different for each renderer resulting in a + * different tree for each renderer. * * @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); + /** + * @brief Remove the tree item that contains the given data node. Removing an item may + * leave the child items of the removed item without a parent. In this case + * the children have to be moved inside the tree so the tree has to be rebuild + * according to the current status of the data storage. + * + * @param dataNode The data node that should be removed. + */ + void RemoveNodeInternal(const mitk::DataNode* dataNode); mitk::DataNode* GetParentNode(const mitk::DataNode* node) const; QmitkDataStorageTreeModelInternalItem* GetItemByIndex(const QModelIndex& index) const; - - std::list m_TreeItems; + QModelIndex GetIndexByItem(QmitkDataStorageTreeModelInternalItem* item) const; std::unique_ptr m_RenderWindowLayerController; mitk::RenderWindowLayerUtilities::RendererVector m_ControlledRenderer; - std::unique_ptr m_Root; + QmitkDataStorageTreeModelInternalItem* m_Root; mitk::WeakPointer m_BaseRenderer; }; #endif // QMITKDATASTORAGERENDERWINDOWTREEMODEL_H diff --git a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageTreeModel.cpp b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageTreeModel.cpp index c4e08c8912..87214ffa53 100644 --- a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageTreeModel.cpp +++ b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowDataStorageTreeModel.cpp @@ -1,545 +1,605 @@ /*=================================================================== 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_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 a node to each render window + // add the node to each render window mitk::RenderWindowLayerUtilities::SetRenderWindowProperties(const_cast(node), renderer); } - */ + if (!m_BaseRenderer.IsExpired()) { auto baseRenderer = m_BaseRenderer.Lock(); - AddNodeInternal(node, nullptr); + AddNodeInternal(node, baseRenderer); } } void QmitkRenderWindowDataStorageTreeModel::NodeChanged(const mitk::DataNode* node) { - auto treeItem = m_Root->Find(node); - if (nullptr != treeItem) + auto item = m_Root->Find(node); + if (nullptr != item) { - auto parentTreeItem = treeItem->GetParent(); + auto parentItem = item->GetParent(); // as the root node should not be removed one should always have a parent item - if (nullptr == parentTreeItem) + if (nullptr == parentItem) { return; } - QModelIndex index = this->createIndex(treeItem->GetIndex(), 0, treeItem); + auto index = createIndex(item->GetIndex(), 0, item); emit dataChanged(index, index); } } -void QmitkRenderWindowDataStorageTreeModel::NodeRemoved(const mitk::DataNode* /*node*/) +void QmitkRenderWindowDataStorageTreeModel::NodeRemoved(const mitk::DataNode* node) { - // #TODO - // update model data to create a new list without the removed data node - UpdateModelData(); + RemoveNodeInternal(node); } QModelIndex QmitkRenderWindowDataStorageTreeModel::index(int row, int column, const QModelIndex& parent) const { - if (!hasIndex(row, column, parent)) + auto item = GetItemByIndex(parent); + if (nullptr != item) { - return QModelIndex(); + item = item->GetChild(row); } - auto childItem = GetItemByIndex(parent)->GetChild(row); - if (nullptr != childItem) + if (nullptr == item) { - return createIndex(row, column, childItem); + return QModelIndex(); } - return QModelIndex(); + return createIndex(row, column, item); } QModelIndex QmitkRenderWindowDataStorageTreeModel::parent(const QModelIndex& parent) const { - if (!parent.isValid() || !m_Root) + auto item = GetItemByIndex(parent); + if (nullptr != item) { - return QModelIndex(); + item = item->GetParent(); } - auto parentItem = GetItemByIndex(parent)->GetParent(); - if(nullptr == parentItem) + if(nullptr == item) { return QModelIndex(); } - if (parentItem == m_Root.get()) + if (item == m_Root) { return QModelIndex(); } - return this->createIndex(parentItem->GetIndex(), 0, parentItem); + return createIndex(item->GetIndex(), 0, item); } int QmitkRenderWindowDataStorageTreeModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const { - return GetItemByIndex(parent)->GetChildCount(); + 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 { 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) + auto item = GetItemByIndex(index); + if (nullptr == item) { return QVariant(); } - auto dataNode = treeItem->GetDataNode(); + 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*/) { 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) + auto item = GetItemByIndex(index); + if (nullptr == item) { return false; } - auto dataNode = treeItem->GetDataNode(); + 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 treeItem = GetItemByIndex(index); - if (nullptr == treeItem) + auto item = GetItemByIndex(index); + if (nullptr == item) { return Qt::NoItemFlags; } - const auto dataNode = treeItem->GetDataNode(); + 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) +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) + if (!parent.isValid()) { return false; } - if (parent.isValid()) + int layer = -1; + auto dataNode = this->data(parent, QmitkDataNodeRawPointerRole).value(); + if (nullptr != dataNode) { - 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); - } + dataNode->GetIntProperty("layer", layer, baseRenderer); + } - UpdateModelData(); - return true; + auto dataNodeList = QmitkMimeTypes::ToDataNodePtrList(data); + for (const auto& dataNode : dataNodeList) + { + m_RenderWindowLayerController->MoveNodeToPosition(dataNode, layer, baseRenderer); } - return false; + ResetTree(); + UpdateModelData(); + AdjustLayerProperty(); + return true; } void QmitkRenderWindowDataStorageTreeModel::SetControlledRenderer(mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer) { m_RenderWindowLayerController->SetControlledRenderer(controlledRenderer); m_ControlledRenderer = controlledRenderer; - /* - if (!m_DataStorage.IsExpired()) + ResetTree(); + 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) + return; + } + + auto dataStorage = m_DataStorage.Lock(); + + for (const auto& renderer : controlledRenderer) + { + if (nullptr == renderer) { - mitk::DataNode::Pointer dataNode = it->Value(); - if (dataNode.IsNull()) - { - continue; - } + continue; + } - for (const auto& renderer : controlledRenderer) - { - if (nullptr != renderer) - { - AddNodeInternal(dataNode, renderer); - } - } + 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* QmitkRenderWindowDataStorageTreeModel::GetCurrentRenderer() const { if (m_BaseRenderer.IsExpired()) { return nullptr; } return m_BaseRenderer.Lock().GetPointer(); } void QmitkRenderWindowDataStorageTreeModel::ResetTree() { + beginResetModel(); + if (nullptr != m_Root) + { + m_Root->Delete(); + } + endResetModel(); + mitk::DataNode::Pointer rootDataNode = mitk::DataNode::New(); rootDataNode->SetName("Data Storage"); - m_Root.reset(new QmitkDataStorageTreeModelInternalItem(rootDataNode)); + m_Root = 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); + AddNodeInternal(dataNode, baseRenderer); } } } } -void QmitkRenderWindowDataStorageTreeModel::AddNodeInternal(const mitk::DataNode* dataNode, const mitk::BaseRenderer* renderer) +void QmitkRenderWindowDataStorageTreeModel::AdjustLayerProperty() { - if (nullptr == dataNode) + if (m_BaseRenderer.IsExpired()) { return; } - if (m_DataStorage.IsExpired()) + auto baseRenderer = m_BaseRenderer.Lock(); + + std::vector treeAsVector; + TreeToVector(m_Root, treeAsVector); + + int i = treeAsVector.size() - 1; + for (auto it = treeAsVector.begin(); it != treeAsVector.end(); ++it) { - return; + auto dataNode = (*it)->GetDataNode(); + dataNode->SetIntProperty("layer", i, baseRenderer); + --i; } +} - auto dataStorage = m_DataStorage.Lock(); +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); + } +} - if (m_Root->Find(dataNode) != 0) +void QmitkRenderWindowDataStorageTreeModel::AddNodeInternal(const mitk::DataNode* dataNode, const mitk::BaseRenderer* renderer) +{ + if (nullptr == dataNode + || m_DataStorage.IsExpired() + || nullptr != m_Root->Find(dataNode)) { - // node already contained in the tree return; } // find out if we have a root node - auto parentTreeItem = m_Root.get(); + auto parentItem = m_Root; QModelIndex index; - mitk::DataNode* parentDataNode = GetParentNode(dataNode); + auto parentDataNode = GetParentNode(dataNode); if (nullptr != parentDataNode) // no top level data node { - parentTreeItem = m_Root->Find(parentDataNode); // find the corresponding tree item - if (nullptr == parentTreeItem) + parentItem = m_Root->Find(parentDataNode); + if (nullptr == parentItem) { // parent node not contained in the tree; add it NodeAdded(parentDataNode); - parentTreeItem = m_Root->Find(parentDataNode); - if (nullptr == parentTreeItem) + 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 = this->createIndex(parentTreeItem->GetIndex(), 0, parentTreeItem); + index = createIndex(parentItem->GetIndex(), 0, parentItem); } int firstRowWithASiblingBelow = 0; int nodeLayer = -1; dataNode->GetIntProperty("layer", nodeLayer, renderer); - for (const auto& siblingTreeItem : parentTreeItem->GetChildren()) + for (const auto& siblingItem : parentItem->GetChildren()) { int siblingLayer = -1; - auto siblingNode = siblingTreeItem->GetDataNode(); + 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)); - parentTreeItem->InsertChild(newNode, firstRowWithASiblingBelow); - m_TreeItems.push_back(newNode); - + 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; 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 static_cast(index.internalPointer()); + } + + return m_Root; +} + +QModelIndex QmitkRenderWindowDataStorageTreeModel::GetIndexByItem(QmitkDataStorageTreeModelInternalItem* item) const +{ + if (item == m_Root) + { + return QModelIndex(); } - return m_Root.get(); + return createIndex(item->GetIndex(), 0, item); }