diff --git a/Modules/SemanticRelationsUI/files.cmake b/Modules/SemanticRelationsUI/files.cmake index e9fc94045d..8208ef2d16 100644 --- a/Modules/SemanticRelationsUI/files.cmake +++ b/Modules/SemanticRelationsUI/files.cmake @@ -1,31 +1,32 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkModuleActivator.cpp + QmitkAbstractSemanticRelationsStorageInspector.cpp QmitkAbstractSemanticRelationsStorageModel.cpp QmitkControlPointDialog.cpp QmitkLesionTextDialog.cpp QmitkLesionTreeItem.cpp QmitkLesionTreeModel.cpp QmitkPatientTableHeaderView.cpp QmitkPatientTableInspector.cpp QmitkPatientTableModel.cpp QmitkSemanticRelationsUIHelper.cpp QmitkTableItemThumbnailDelegate.cpp ) set(MOC_H_FILES include/QmitkAbstractSemanticRelationsStorageInspector.h include/QmitkAbstractSemanticRelationsStorageModel.h include/QmitkControlPointDialog.h include/QmitkLesionTextDialog.h include/QmitkLesionTreeModel.h include/QmitkPatientTableHeaderView.h include/QmitkPatientTableInspector.h include/QmitkPatientTableModel.h include/QmitkTableItemThumbnailDelegate.h ) set(UI_FILES src/QmitkPatientTableInspector.ui ) diff --git a/Modules/SemanticRelationsUI/include/QmitkAbstractSemanticRelationsStorageInspector.h b/Modules/SemanticRelationsUI/include/QmitkAbstractSemanticRelationsStorageInspector.h index 15a06ca2ea..1bd7d46a0c 100644 --- a/Modules/SemanticRelationsUI/include/QmitkAbstractSemanticRelationsStorageInspector.h +++ b/Modules/SemanticRelationsUI/include/QmitkAbstractSemanticRelationsStorageInspector.h @@ -1,55 +1,61 @@ /*=================================================================== 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 QMITKABSTRACTSEMANTICRELATIONSSTORAGEINSPECTOR_H #define QMITKABSTRACTSEMANTICRELATIONSSTORAGEINSPECTOR_H // semantic relations UI module #include "MitkSemanticRelationsUIExports.h" // semantic relations module #include "mitkSemanticTypes.h" // qt widgets module #include "QmitkAbstractDataStorageInspector.h" /* * @brief The QmitkAbstractSemanticRelationsStorageInspector is a QmitkAbstractDataStorageInspector that can be used to * show the currently available data of an (abstract) semantic relations storage model. */ class MITKSEMANTICRELATIONSUI_EXPORT QmitkAbstractSemanticRelationsStorageInspector : public QmitkAbstractDataStorageInspector { Q_OBJECT public: + + virtual ~QmitkAbstractSemanticRelationsStorageInspector(); + /** * @brief Extends the abstract base class to allow setting the current case ID which is needed to access the * semantic relations storage. The function sets the case ID in the storage model. * * @param caseID A case ID as string */ virtual void SetCaseID(const mitk::SemanticTypes::CaseID& caseID) = 0; /** * @brief Extends the abstract base class to allow setting the current lesion. * The function sets the lesion in the storage model. * *@param lesion The selected lesion */ virtual void SetLesion(const mitk::SemanticTypes::Lesion& lesion) = 0; +protected: + + QmitkAbstractSemanticRelationsStorageInspector(QWidget* parent = nullptr); }; #endif // QMITKABSTRACTSEMANTICRELATIONSSTORAGEINSPECTOR_H diff --git a/Modules/SemanticRelationsUI/include/QmitkLesionTreeModel.h b/Modules/SemanticRelationsUI/include/QmitkLesionTreeModel.h index d130c4d94f..899d912e61 100644 --- a/Modules/SemanticRelationsUI/include/QmitkLesionTreeModel.h +++ b/Modules/SemanticRelationsUI/include/QmitkLesionTreeModel.h @@ -1,98 +1,98 @@ /*=================================================================== 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 QMITKLESIONTREEMODEL_H #define QMITKLESIONTREEMODEL_H // mitk semantic relations UI #include "MitkSemanticRelationsUIExports.h" #include "QmitkAbstractSemanticRelationsStorageModel.h" #include "QmitkLesionTreeItem.h" // c++ #include /* * @brief */ class MITKSEMANTICRELATIONSUI_EXPORT QmitkLesionTreeModel : public QmitkAbstractSemanticRelationsStorageModel { Q_OBJECT public: /** * @brief Initialize the root item of the model. The root item does not have a parent item. */ QmitkLesionTreeModel(QObject* parent = nullptr); ~QmitkLesionTreeModel(); ////////////////////////////////////////////////////////////////////////// // overridden virtual functions from QAbstractItemModel ////////////////////////////////////////////////////////////////////////// virtual QModelIndex index(int row, int column, const QModelIndex& itemIndex = QModelIndex()) const override; virtual QModelIndex parent(const QModelIndex& itemIndex) const override; virtual int rowCount(const QModelIndex& itemIndex = QModelIndex()) const override; virtual int columnCount(const QModelIndex& itemIndex = QModelIndex()) const override; virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; ////////////////////////////////////////////////////////////////////////// // end override ////////////////////////////////////////////////////////////////////////// protected: // the following functions have to be overridden but are not implemented in this model virtual void NodePredicateChanged() override { } - virtual void NodeAdded(const mitk::DataNode* node) override { } - virtual void NodeChanged(const mitk::DataNode* node) override { } - virtual void NodeRemoved(const mitk::DataNode* node) override { } + virtual void NodeAdded(const mitk::DataNode*) override { } + virtual void NodeChanged(const mitk::DataNode*) override { } + virtual void NodeRemoved(const mitk::DataNode*) override { } /** * @brief Overridden from 'QmitkAbstractSemanticRelationsStorageModel': This function retrieves all control points * of the current case and stores them to define the header of the tree. * Furthermore all lesions are retrieved and the lesion data is stored and show in the tree view. */ virtual void SetData() override; private: void SetLesionData(); void AddLesion(const mitk::SemanticTypes::Lesion& lesion); void SetSelectedDataNodesPresence(); /** * @brief The function uses the ID of the lesion to see if a data node presence was already set. * If not, the given bool value is used and stored inside a member variable. If the lesion presence * was already set, it will be overwritten. * The function is used by the 'SetSelectedDataNodesPresence' function. * * @param lesion The lesion whose data node presence should be set * @param dataNodePresence The bool value that defines the data node presence of the given lesion */ void SetDataNodePresenceOfLesion(const mitk::SemanticTypes::Lesion* lesion, bool dataNodePresence); QmitkLesionTreeItem* GetItemByIndex(const QModelIndex& index) const; std::map m_DataNodePresence; std::shared_ptr m_RootItem; mitk::SemanticTypes::ControlPointVector m_ControlPoints; mitk::SemanticTypes::LesionVector m_CurrentLesions; }; #endif // QMITKLESIONTREEMODEL_H diff --git a/Modules/SemanticRelationsUI/include/QmitkPatientTableModel.h b/Modules/SemanticRelationsUI/include/QmitkPatientTableModel.h index b32290bf37..16a38ef02b 100644 --- a/Modules/SemanticRelationsUI/include/QmitkPatientTableModel.h +++ b/Modules/SemanticRelationsUI/include/QmitkPatientTableModel.h @@ -1,134 +1,134 @@ /*=================================================================== 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 QMITKPATIENTTABLEMODEL_H #define QMITKPATIENTTABLEMODEL_H // semantic relations UI module #include "QmitkAbstractSemanticRelationsStorageModel.h" // semantic relations module #include #include // mitk core #include // qt #include #include /** * @brief The QmitkPatientTableModel is a subclass of the QmitkAbstractSemanticRelationsStorageModel and holds the semantic relations data of the currently selected case. * * The QmitkPatientTableModel uses the 'data' function to return either the data node of a table cell or the thumbnail of the underlying image. * The horizontal header of the table shows the control points of the current case and the vertical header of the table shows the information types of the current case. * Using the 'GetFilteredData'-function of the SemanticRelations-class the model is able to retrieve the correct data node for each table entry. * * Additionally the model creates and holds the QPixmaps of the known data nodes in order to return a thumbnail, if needed. */ class QmitkPatientTableModel : public QmitkAbstractSemanticRelationsStorageModel { Q_OBJECT public: QmitkPatientTableModel(QObject* parent = nullptr); ~QmitkPatientTableModel(); ////////////////////////////////////////////////////////////////////////// // overridden functions from QAbstractItemModel ////////////////////////////////////////////////////////////////////////// virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; virtual QModelIndex parent(const QModelIndex& child) const override; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; virtual Qt::ItemFlags flags(const QModelIndex& index) const override; ////////////////////////////////////////////////////////////////////////// /// end override ///////////////////////////////////////////////////////////////////////// void SetNodeType(const std::string& nodeType); protected: // the following functions have to be overridden... virtual void NodePredicateChanged() override; // but are not implemented in this model - virtual void NodeAdded(const mitk::DataNode* node) override { } - virtual void NodeChanged(const mitk::DataNode* node) override { } - virtual void NodeRemoved(const mitk::DataNode* node) override { } + virtual void NodeAdded(const mitk::DataNode*) override { } + virtual void NodeChanged(const mitk::DataNode*) override { } + virtual void NodeRemoved(const mitk::DataNode*) override { } /** * @brief Overridden from 'QmitkAbstractSemanticRelationsStorageModel': This function retrieves all control points * and information types of the current case and stores them to define the header of the table. * Furthermore all images are retrieved and the pixmap of the images are generated and stored. */ virtual void SetData() override; private: void SetHeaderModel(); void SetPixmaps(); void SetLesionPresences(); /** * @brief The function uses the ID of the node to see if a pixmap was already set. If not, the given pixmap * is used and stored inside a member variable. If the pixmap was already set, it will be overwritten. * Using 'nullptr' as a pixmap will erase the entry for the given data node. * * @param dataNode The data node whose pixmap should be set * @param pixmapFromImage The pixmap that shows an image of the content of the data node */ void SetPixmapOfNode(const mitk::DataNode* dataNode, QPixmap* pixmapFromImage); /** * @brief The function uses the ID of the node to see if a lesion presence was already set. If not, the given * bool value is used and stored inside a member variable. If the lesion presence was already set, it * will be overwritten. * The function is used by the 'SetLesionPresences' function. * * @param dataNode The data node whose lesion presence should be set * @param lesionPresence The bool value that defines the lesion presence of the given data node */ void SetLesionPresenceOfNode(const mitk::DataNode* dataNode, bool lesionPresence); /** * @brief Returns the data node that is associated with the given table entry (index). * * The function uses the SemanticRelations-class and the current control point data and information type data to * filter the nodes of the current case. * The index is used to access the correct row in the table (information type) and the correct column in the table (control point). * * @par index The QModelIndex of the table entry */ mitk::DataNode* GetCurrentDataNode(const QModelIndex &index) const; std::map m_PixmapMap; std::map m_LesionPresence; mitk::SemanticTypes::InformationTypeVector m_InformationTypes; mitk::SemanticTypes::ControlPointVector m_ControlPoints; mitk::SemanticTypes::ExaminationPeriodVector m_ExaminationPeriods; mitk::SemanticRelationsDataStorageAccess::DataNodeVector m_CurrentDataNodes; std::string m_SelectedNodeType; QStandardItemModel* m_HeaderModel; }; #endif // QMITKPATIENTTABLEMODEL_H diff --git a/Modules/SemanticRelationsUI/src/QmitkAbstractSemanticRelationsStorageInspector.cpp b/Modules/SemanticRelationsUI/src/QmitkAbstractSemanticRelationsStorageInspector.cpp new file mode 100644 index 0000000000..2f6013c589 --- /dev/null +++ b/Modules/SemanticRelationsUI/src/QmitkAbstractSemanticRelationsStorageInspector.cpp @@ -0,0 +1,29 @@ +/*=================================================================== + +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. + +===================================================================*/ + +// semantic relations UI module +#include "QmitkAbstractSemanticRelationsStorageInspector.h" + +QmitkAbstractSemanticRelationsStorageInspector::QmitkAbstractSemanticRelationsStorageInspector(QWidget* parent /*= nullptr*/) + : QmitkAbstractDataStorageInspector(parent) +{ + // nothing here +} + +QmitkAbstractSemanticRelationsStorageInspector::~QmitkAbstractSemanticRelationsStorageInspector() +{ + // nothing here +} diff --git a/Modules/SemanticRelationsUI/src/QmitkLesionTreeModel.cpp b/Modules/SemanticRelationsUI/src/QmitkLesionTreeModel.cpp index d1a23715e0..07c1071fc3 100644 --- a/Modules/SemanticRelationsUI/src/QmitkLesionTreeModel.cpp +++ b/Modules/SemanticRelationsUI/src/QmitkLesionTreeModel.cpp @@ -1,303 +1,303 @@ /*=================================================================== 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. ===================================================================*/ // semantic relations UI module #include "QmitkLesionTreeModel.h" // semantic relations module #include #include #include #include #include // qt #include QmitkLesionTreeModel::QmitkLesionTreeModel(QObject* parent/* = nullptr*/) : QmitkAbstractSemanticRelationsStorageModel(parent) , m_RootItem(std::make_shared(mitk::LesionData())) { // nothing here } QmitkLesionTreeModel::~QmitkLesionTreeModel() { // nothing here } ////////////////////////////////////////////////////////////////////////// // overridden virtual functions from QAbstractItemModel ////////////////////////////////////////////////////////////////////////// QModelIndex QmitkLesionTreeModel::index(int row, int column, const QModelIndex& itemIndex) const { if (!hasIndex(row, column, itemIndex)) { return QModelIndex(); } auto childItem = GetItemByIndex(itemIndex)->GetChildInRow(row); if (nullptr == childItem) { return QModelIndex(); } return createIndex(row, column, childItem.get()); } QModelIndex QmitkLesionTreeModel::parent(const QModelIndex& itemIndex) const { if (!itemIndex.isValid()) { return QModelIndex(); } auto parentItem = GetItemByIndex(itemIndex)->GetParent(); if (parentItem.expired()) { return QModelIndex(); } auto sharedParent = parentItem.lock(); if (sharedParent == m_RootItem) { return QModelIndex(); } return createIndex(sharedParent->GetRow(), 0, sharedParent.get()); } int QmitkLesionTreeModel::rowCount(const QModelIndex& itemIndex/* = QModelIndex()*/) const { return GetItemByIndex(itemIndex)->ChildCount(); } int QmitkLesionTreeModel::columnCount(const QModelIndex&/* itemIndex = QModelIndex() */) const { if (0 == m_RootItem->ChildCount()) { // no lesion items stored, no need to display columns return 0; } return m_ControlPoints.size() + 1; } QVariant QmitkLesionTreeModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) { return QVariant(); } if (index.column() < 0 || index.column() > static_cast(m_ControlPoints.size())) { return QVariant(); } QmitkLesionTreeItem* currentItem = GetItemByIndex(index); if (Qt::DisplayRole == role) { if (currentItem->GetParent().expired()) { return QVariant(); } auto parentItem = currentItem->GetParent().lock(); // parent exists and is the root item -> 1. item of a lesion entry if (m_RootItem == parentItem) { // display role fills the first columns with the lesion UID / name if (0 == index.column()) { std::string itemString = currentItem->GetData().GetLesionName(); if (itemString.empty()) { itemString = currentItem->GetData().GetLesionUID(); } return QString::fromStdString(itemString); } else { // display role fills other columns with the lesion presence info const auto lesionPresence = currentItem->GetData().GetLesionPresence(); if (index.column() - 1 > static_cast(lesionPresence.size())) { return ""; } return QVariant(lesionPresence.at(index.column() - 1)); } } // parent is not the root item -> 2. item of a lesion entry else { // display role fills the first columns with the property name "Volume" if (0 == index.column()) { return "Volume"; } else { // display role fills other columns with the lesion volume info const auto lesionVolume= currentItem->GetData().GetLesionVolume(); if (index.column() - 1 > static_cast(lesionVolume.size())) { return ""; } return QVariant(lesionVolume.at(index.column() - 1)); } } } if (Qt::BackgroundColorRole == role) { auto it = m_DataNodePresence.find(currentItem->GetData().GetLesion().UID); if (it != m_DataNodePresence.end()) { return it->second ? QVariant(QColor(Qt::darkGreen)) : QVariant(QColor(Qt::transparent)); } return QVariant(QColor(Qt::transparent)); } if (Qt::UserRole == role) { return QVariant::fromValue(currentItem); } return QVariant(); } QVariant QmitkLesionTreeModel::headerData(int section, Qt::Orientation orientation, int role) const { if (0 == m_RootItem->ChildCount()) { // no lesion items stored, no need to display the header return QVariant(); } if (Qt::Horizontal == orientation && Qt::DisplayRole == role) { if (0 == section) { return QVariant("Lesion"); } - if (m_ControlPoints.size() >= section) + if (static_cast(m_ControlPoints.size()) >= section) { mitk::SemanticTypes::ControlPoint currentControlPoint = m_ControlPoints.at(section-1); return QVariant(QString::fromStdString(currentControlPoint.ToString())); } } return QVariant(); } void QmitkLesionTreeModel::SetData() { m_RootItem = std::make_shared(mitk::LesionData()); // get all control points of current case m_ControlPoints = mitk::RelationStorage::GetAllControlPointsOfCase(m_CaseID); // sort the vector of control points for the timeline std::sort(m_ControlPoints.begin(), m_ControlPoints.end()); SetLesionData(); SetSelectedDataNodesPresence(); } void QmitkLesionTreeModel::SetLesionData() { m_CurrentLesions = mitk::RelationStorage::GetAllLesionsOfCase(m_CaseID); for (auto& lesion : m_CurrentLesions) { AddLesion(lesion); } } void QmitkLesionTreeModel::AddLesion(const mitk::SemanticTypes::Lesion& lesion) { // create new lesion tree item data and modify it according to the control point data mitk::LesionData lesionData(lesion); mitk::GenerateAdditionalLesionData(lesionData, m_CaseID); // add the 1. level lesion item to the root item std::shared_ptr newLesionTreeItem = std::make_shared(lesionData); m_RootItem->AddChild(newLesionTreeItem); // add the 2. level lesion item to the 1. level lesion item std::shared_ptr newChildItem = std::make_shared(lesionData); newLesionTreeItem->AddChild(newChildItem); } void QmitkLesionTreeModel::SetSelectedDataNodesPresence() { m_DataNodePresence.clear(); for (const auto& dataNode : m_SelectedDataNodes) { if (!mitk::SemanticRelationsInference::InstanceExists(dataNode)) { continue; } for (const auto& lesion : m_CurrentLesions) { if (!mitk::SemanticRelationsInference::InstanceExists(m_CaseID, lesion)) { continue; } try { // set the lesion presence for the current node bool dataNodePresence = mitk::SemanticRelationsInference::IsLesionPresent(lesion, dataNode); SetDataNodePresenceOfLesion(&lesion, dataNodePresence); } catch (const mitk::SemanticRelationException&) { continue; } } } } void QmitkLesionTreeModel::SetDataNodePresenceOfLesion(const mitk::SemanticTypes::Lesion* lesion, bool dataNodePresence) { std::map::iterator iter = m_DataNodePresence.find(lesion->UID); if (iter != m_DataNodePresence.end()) { // key already existing, overwrite already stored bool value iter->second = dataNodePresence; } else { m_DataNodePresence.insert(std::make_pair(lesion->UID, dataNodePresence)); } } QmitkLesionTreeItem* QmitkLesionTreeModel::GetItemByIndex(const QModelIndex& index) const { if (index.isValid()) { auto item = static_cast(index.internalPointer()); if (nullptr != item) { return item; } } return m_RootItem.get(); } diff --git a/Modules/SemanticRelationsUI/src/QmitkPatientTableInspector.cpp b/Modules/SemanticRelationsUI/src/QmitkPatientTableInspector.cpp index 7b02bd0e59..9f8f4d3ca8 100644 --- a/Modules/SemanticRelationsUI/src/QmitkPatientTableInspector.cpp +++ b/Modules/SemanticRelationsUI/src/QmitkPatientTableInspector.cpp @@ -1,182 +1,183 @@ /*=================================================================== 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. ===================================================================*/ // semantic relations UI module #include "QmitkPatientTableInspector.h" #include "QmitkPatientTableHeaderView.h" // mitk qt widgets module #include "QmitkCustomVariants.h" #include "QmitkEnums.h" // qt #include #include QmitkPatientTableInspector::QmitkPatientTableInspector(QWidget* parent/* =nullptr*/) + : QmitkAbstractSemanticRelationsStorageInspector(parent) { m_Controls.setupUi(this); QmitkPatientTableHeaderView* patientTableHeaderView = new QmitkPatientTableHeaderView(m_Controls.tableView); m_Controls.tableView->setHorizontalHeader(patientTableHeaderView); m_Controls.tableView->horizontalHeader()->setHighlightSections(false); m_Controls.tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed); m_Controls.tableView->verticalHeader()->setHighlightSections(false); m_Controls.tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); m_Controls.tableView->setSelectionMode(QAbstractItemView::SingleSelection); m_Controls.tableView->setSelectionBehavior(QAbstractItemView::SelectItems); m_Controls.tableView->setContextMenuPolicy(Qt::CustomContextMenu); m_StorageModel = new QmitkPatientTableModel(m_Controls.tableView); m_Controls.tableView->setModel(m_StorageModel); m_ItemDelegate = new QmitkTableItemThumbnailDelegate(m_Controls.tableView); //m_Controls.tableView->setItemDelegate(m_ItemDelegate); SetUpConnections(); } QAbstractItemView* QmitkPatientTableInspector::GetView() { return m_Controls.tableView; } const QAbstractItemView* QmitkPatientTableInspector::GetView() const { return m_Controls.tableView; } void QmitkPatientTableInspector::SetSelectionMode(SelectionMode mode) { m_Controls.tableView->setSelectionMode(mode); } QmitkPatientTableInspector::SelectionMode QmitkPatientTableInspector::GetSelectionMode() const { return m_Controls.tableView->selectionMode(); } void QmitkPatientTableInspector::SetCaseID(const mitk::SemanticTypes::CaseID& caseID) { m_StorageModel->SetCaseID(caseID); } void QmitkPatientTableInspector::SetLesion(const mitk::SemanticTypes::Lesion& lesion) { m_StorageModel->SetLesion(lesion); } QItemSelectionModel* QmitkPatientTableInspector::GetSelectionModel() { return m_Controls.tableView->selectionModel(); } void QmitkPatientTableInspector::Initialize() { if (m_DataStorage.IsExpired()) { return; } auto dataStorage = m_DataStorage.Lock(); m_StorageModel->SetDataStorage(dataStorage); m_StorageModel->SetNodePredicate(m_NodePredicate); m_Connector->SetView(m_Controls.tableView); } void QmitkPatientTableInspector::OnModelUpdated() { m_Controls.tableView->resizeRowsToContents(); m_Controls.tableView->resizeColumnsToContents(); } void QmitkPatientTableInspector::OnNodeButtonClicked(const QString& nodeType) { m_StorageModel->SetNodeType(nodeType.toStdString()); } void QmitkPatientTableInspector::OnDataNodeSelectionChanged(const QList& dataNodeSelection) { if (m_StorageModel->GetLesion().UID.empty()) { return; } // if lesion is set, reset to empty lesion to hide the "lesion presence background highlighting" in the model m_StorageModel->SetLesion(mitk::SemanticTypes::Lesion()); // need to explicitly set the data node selection SetCurrentSelection(dataNodeSelection); } void QmitkPatientTableInspector::OnItemDoubleClicked(const QModelIndex& itemIndex) { if (itemIndex.isValid()) { QVariant qvariantDataNode = m_StorageModel->data(itemIndex, QmitkDataNodeRawPointerRole); if (qvariantDataNode.canConvert()) { mitk::DataNode* dataNode = qvariantDataNode.value(); emit DataNodeDoubleClicked(dataNode); } } } void QmitkPatientTableInspector::SetUpConnections() { connect(m_StorageModel, &QmitkPatientTableModel::ModelUpdated, this, &QmitkPatientTableInspector::OnModelUpdated); connect(m_Controls.tableView, &QTableView::customContextMenuRequested, this, &QmitkPatientTableInspector::OnContextMenuRequested); QSignalMapper* nodeButtonSignalMapper = new QSignalMapper(this); nodeButtonSignalMapper->setMapping(m_Controls.imageNodeButton, QString("Image")); nodeButtonSignalMapper->setMapping(m_Controls.segmentationNodeButton, QString("Segmentation")); connect(nodeButtonSignalMapper, static_cast(&QSignalMapper::mapped), this, &QmitkPatientTableInspector::OnNodeButtonClicked); connect(m_Controls.imageNodeButton, &QRadioButton::clicked, nodeButtonSignalMapper, static_cast(&QSignalMapper::map)); connect(m_Controls.segmentationNodeButton, &QRadioButton::clicked, nodeButtonSignalMapper, static_cast(&QSignalMapper::map)); m_Controls.imageNodeButton->setChecked(true); connect(this, &QmitkPatientTableInspector::CurrentSelectionChanged, this, &QmitkPatientTableInspector::OnDataNodeSelectionChanged); connect(m_Controls.tableView, &QTableView::doubleClicked, this, &QmitkPatientTableInspector::OnItemDoubleClicked); } void QmitkPatientTableInspector::keyPressEvent(QKeyEvent* e) { mitk::DataNode* dataNode = nullptr; QModelIndex selectedIndex = m_Controls.tableView->currentIndex(); if (selectedIndex.isValid()) { QVariant qvariantDataNode = m_StorageModel->data(selectedIndex, QmitkDataNodeRawPointerRole); if (qvariantDataNode.canConvert()) { dataNode = qvariantDataNode.value(); } } if (nullptr == dataNode) { return; } int key = e->key(); switch (key) { case Qt::Key_Delete: emit OnNodeRemoved(dataNode); break; default: break; } } diff --git a/Modules/SemanticRelationsUI/src/QmitkPatientTableModel.cpp b/Modules/SemanticRelationsUI/src/QmitkPatientTableModel.cpp index 1134f56d5d..17069bfe7f 100644 --- a/Modules/SemanticRelationsUI/src/QmitkPatientTableModel.cpp +++ b/Modules/SemanticRelationsUI/src/QmitkPatientTableModel.cpp @@ -1,344 +1,349 @@ /*=================================================================== 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. ===================================================================*/ // semantic relations UI module #include "QmitkPatientTableModel.h" #include "QmitkPatientTableHeaderView.h" #include "QmitkSemanticRelationsUIHelper.h" // semantic relations module #include #include #include #include #include #include #include // qt #include // c++ #include #include QmitkPatientTableModel::QmitkPatientTableModel(QObject* parent /*= nullptr*/) : QmitkAbstractSemanticRelationsStorageModel(parent) , m_SelectedNodeType("Image") { m_HeaderModel = new QStandardItemModel(this); } QmitkPatientTableModel::~QmitkPatientTableModel() { // nothing here } QModelIndex QmitkPatientTableModel::index(int row, int column, const QModelIndex& parent/* = QModelIndex()*/) const { if (hasIndex(row, column, parent)) { return createIndex(row, column); } return QModelIndex(); } -QModelIndex QmitkPatientTableModel::parent(const QModelIndex& child) const +QModelIndex QmitkPatientTableModel::parent(const QModelIndex& /*child*/) const { return QModelIndex(); } int QmitkPatientTableModel::rowCount(const QModelIndex& parent/* = QModelIndex()*/) const { if (parent.isValid()) { return 0; } return m_InformationTypes.size(); } int QmitkPatientTableModel::columnCount(const QModelIndex& parent/* = QModelIndex()*/) const { + if (parent.isValid()) + { + return 0; + } + return m_ControlPoints.size(); } QVariant QmitkPatientTableModel::data(const QModelIndex& index, int role/* = Qt::DisplayRole*/) const { // special role for returning the horizontal header if (QmitkPatientTableHeaderView::HorizontalHeaderDataRole == role) { return QVariant::fromValue(m_HeaderModel); } if (!index.isValid()) { return QVariant(); } if (index.row() < 0 || index.row() >= static_cast(m_InformationTypes.size()) || index.column() < 0 || index.column() >= static_cast(m_ControlPoints.size())) { return QVariant(); } mitk::DataNode* dataNode = GetCurrentDataNode(index); if (nullptr == dataNode) { return QVariant(); } if (Qt::DecorationRole == role) { auto it = m_PixmapMap.find(dataNode); if (it != m_PixmapMap.end()) { return QVariant(it->second); } } if (QmitkDataNodeRole == role) { return QVariant::fromValue(mitk::DataNode::Pointer(dataNode)); } if (QmitkDataNodeRawPointerRole == role) { return QVariant::fromValue(dataNode); } if (Qt::BackgroundColorRole == role) { auto it = m_LesionPresence.find(dataNode); if (it != m_LesionPresence.end()) { return it->second ? QVariant(QColor(Qt::darkGreen)) : QVariant(QColor(Qt::transparent)); } return QVariant(QColor(Qt::transparent)); } return QVariant(); } QVariant QmitkPatientTableModel::headerData(int section, Qt::Orientation orientation, int role) const { if (Qt::Vertical == orientation && Qt::DisplayRole == role) { - if (m_InformationTypes.size() > section) + if (static_cast(m_InformationTypes.size()) > section) { mitk::SemanticTypes::InformationType currentInformationType = m_InformationTypes.at(section); return QVariant(QString::fromStdString(currentInformationType)); } } return QVariant(); } Qt::ItemFlags QmitkPatientTableModel::flags(const QModelIndex& index) const { Qt::ItemFlags flags; mitk::DataNode* dataNode = GetCurrentDataNode(index); if (nullptr != dataNode) { flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; } return flags; } void QmitkPatientTableModel::SetNodeType(const std::string& nodeType) { m_SelectedNodeType = nodeType; UpdateModelData(); } void QmitkPatientTableModel::NodePredicateChanged() { UpdateModelData(); } void QmitkPatientTableModel::SetData() { // get all control points of current case m_ControlPoints = mitk::RelationStorage::GetAllControlPointsOfCase(m_CaseID); // sort the vector of control points for the timeline std::sort(m_ControlPoints.begin(), m_ControlPoints.end()); // get all examination periods of current case m_ExaminationPeriods = mitk::RelationStorage::GetAllExaminationPeriodsOfCase(m_CaseID); // sort the vector of examination periods for the timeline mitk::SortExaminationPeriods(m_ExaminationPeriods, m_ControlPoints); // get all information types points of current case m_InformationTypes = mitk::RelationStorage::GetAllInformationTypesOfCase(m_CaseID); if ("Image" == m_SelectedNodeType) { m_CurrentDataNodes = m_SemanticRelationsDataStorageAccess->GetAllImagesOfCase(m_CaseID); } else if ("Segmentation" == m_SelectedNodeType) { m_CurrentDataNodes = m_SemanticRelationsDataStorageAccess->GetAllSegmentationsOfCase(m_CaseID); } SetHeaderModel(); SetPixmaps(); SetLesionPresences(); } void QmitkPatientTableModel::SetHeaderModel() { m_HeaderModel->clear(); QStandardItem* rootItem = new QStandardItem("Timeline"); QList standardItems; for (const auto& examinationPeriod : m_ExaminationPeriods) { QStandardItem* examinationPeriodItem = new QStandardItem(QString::fromStdString(examinationPeriod.name)); standardItems.push_back(examinationPeriodItem); rootItem->appendColumn(standardItems); standardItems.clear(); const auto& currentControlPoints = examinationPeriod.controlPointUIDs; for (const auto& controlPointUID : currentControlPoints) { const auto& controlPoint = mitk::GetControlPointByUID(controlPointUID, m_ControlPoints); QStandardItem* controlPointItem = new QStandardItem(QString::fromStdString(controlPoint.ToString())); standardItems.push_back(controlPointItem); examinationPeriodItem->appendColumn(standardItems); standardItems.clear(); } } m_HeaderModel->setItem(0, 0, rootItem); } void QmitkPatientTableModel::SetPixmaps() { m_PixmapMap.clear(); for (const auto& dataNode : m_CurrentDataNodes) { // set the pixmap for the current node QPixmap pixmapFromImage = QmitkSemanticRelationsUIHelper::GetPixmapFromImageNode(dataNode); SetPixmapOfNode(dataNode, &pixmapFromImage); } } void QmitkPatientTableModel::SetPixmapOfNode(const mitk::DataNode* dataNode, QPixmap* pixmapFromImage) { if (nullptr == dataNode) { return; } std::map::iterator iter = m_PixmapMap.find(dataNode); if (iter != m_PixmapMap.end()) { // key already existing if (nullptr != pixmapFromImage) { // overwrite already stored pixmap iter->second = pixmapFromImage->scaled(120, 120, Qt::IgnoreAspectRatio); } else { // remove key if no pixmap is given m_PixmapMap.erase(iter); } } else { m_PixmapMap.insert(std::make_pair(dataNode, pixmapFromImage->scaled(120, 120, Qt::IgnoreAspectRatio))); } } void QmitkPatientTableModel::SetLesionPresences() { m_LesionPresence.clear(); if (!mitk::SemanticRelationsInference::InstanceExists(m_CaseID, m_Lesion)) { return; } for (const auto& dataNode : m_CurrentDataNodes) { if (!mitk::SemanticRelationsInference::InstanceExists(dataNode)) { continue; } try { // set the lesion presence for the current node bool lesionPresence = mitk::SemanticRelationsInference::IsLesionPresent(m_Lesion, dataNode); SetLesionPresenceOfNode(dataNode, lesionPresence); } catch (const mitk::SemanticRelationException&) { continue; } } } void QmitkPatientTableModel::SetLesionPresenceOfNode(const mitk::DataNode* dataNode, bool lesionPresence) { std::map::iterator iter = m_LesionPresence.find(dataNode); if (iter != m_LesionPresence.end()) { // key already existing, overwrite already stored bool value iter->second = lesionPresence; } else { m_LesionPresence.insert(std::make_pair(dataNode, lesionPresence)); } } mitk::DataNode* QmitkPatientTableModel::GetCurrentDataNode(const QModelIndex& index) const { if (!index.isValid()) { return nullptr; } mitk::SemanticTypes::ControlPoint currentControlPoint = m_ControlPoints.at(index.column()); mitk::SemanticTypes::InformationType currentInformationType = m_InformationTypes.at(index.row()); try { std::vector filteredDataNodes; if ("Image" == m_SelectedNodeType) { filteredDataNodes = m_SemanticRelationsDataStorageAccess->GetAllSpecificImages(m_CaseID, currentControlPoint, currentInformationType); } else if ("Segmentation" == m_SelectedNodeType) { filteredDataNodes = m_SemanticRelationsDataStorageAccess->GetAllSpecificSegmentations(m_CaseID, currentControlPoint, currentInformationType); } if (filteredDataNodes.empty()) { return nullptr; } return filteredDataNodes.front(); } catch (const mitk::SemanticRelationException&) { return nullptr; } } diff --git a/Modules/SemanticRelationsUI/src/QmitkTableItemThumbnailDelegate.cpp b/Modules/SemanticRelationsUI/src/QmitkTableItemThumbnailDelegate.cpp index f0ea252f5c..02091ed14d 100644 --- a/Modules/SemanticRelationsUI/src/QmitkTableItemThumbnailDelegate.cpp +++ b/Modules/SemanticRelationsUI/src/QmitkTableItemThumbnailDelegate.cpp @@ -1,47 +1,46 @@ /*=================================================================== 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. ===================================================================*/ // semantic relations UI module #include "QmitkTableItemThumbnailDelegate.h" // qt #include #include #include QmitkTableItemThumbnailDelegate::QmitkTableItemThumbnailDelegate(QObject* parent /*= nullptr*/) : QStyledItemDelegate(parent) { // nothing here } void QmitkTableItemThumbnailDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QPixmap pixmap = index.data(Qt::DecorationRole).value(); - QRect rect = option.rect; QPoint point = option.rect.center() - pixmap.rect().center(); painter->save(); if (option.state & QStyle::State_Selected) { painter->setBrush(option.palette.highlightedText()); const QWidget* widget = option.widget; QStyle* style = widget ? widget->style() : QApplication::style(); style->drawControl(QStyle::CE_ItemViewItem, &option, painter, widget); } painter->drawPixmap(point, pixmap); painter->restore(); }