diff --git a/Modules/SemanticRelationsUI/include/QmitkLesionTreeModel.h b/Modules/SemanticRelationsUI/include/QmitkLesionTreeModel.h index ff80a1b00e..cafc181553 100644 --- a/Modules/SemanticRelationsUI/include/QmitkLesionTreeModel.h +++ b/Modules/SemanticRelationsUI/include/QmitkLesionTreeModel.h @@ -1,87 +1,86 @@ /*=================================================================== 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; - //Qt::ItemFlags flags(const QModelIndex &index) 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; /** * @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); QmitkLesionTreeItem* GetItemByIndex(const QModelIndex& index) const; std::shared_ptr m_RootItem; std::vector m_ControlPoints; }; #endif // QMITKLESIONTREEMODEL_H diff --git a/Modules/SemanticRelationsUI/src/QmitkPatientTableModel.cpp b/Modules/SemanticRelationsUI/src/QmitkPatientTableModel.cpp index 95137b61dd..635f8eab62 100644 --- a/Modules/SemanticRelationsUI/src/QmitkPatientTableModel.cpp +++ b/Modules/SemanticRelationsUI/src/QmitkPatientTableModel.cpp @@ -1,354 +1,357 @@ /*=================================================================== 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 "QmitkSemanticRelationsUIHelper.h" // semantic relations module #include #include #include #include #include // qt #include QmitkPatientTableModel::QmitkPatientTableModel(QObject* parent /*= nullptr*/) : QmitkAbstractSemanticRelationsStorageModel(parent) , m_SelectedNodeType("Image") { // nothing here } 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 { 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 { 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); } } - else if (QmitkDataNodeRole == role) + + if (QmitkDataNodeRole == role) { return QVariant::fromValue(mitk::DataNode::Pointer(dataNode)); } - else if (QmitkDataNodeRawPointerRole == role) + + if (QmitkDataNodeRawPointerRole == role) { return QVariant::fromValue(dataNode); } - else if (Qt::BackgroundColorRole == role) + + if (Qt::BackgroundColorRole == role) { auto it = m_LesionPresence.find(dataNode); if (it != m_LesionPresence.end()) { return it->second ? QVariant(QColor(Qt::green)) : QVariant(QColor(Qt::transparent)); } return QVariant(QColor(Qt::transparent)); } return QVariant(); } QVariant QmitkPatientTableModel::headerData(int section, Qt::Orientation orientation, int role) const { if (Qt::Horizontal == orientation && Qt::DisplayRole == role) { if (m_ControlPoints.size() > section) { mitk::SemanticTypes::ControlPoint currentControlPoint = m_ControlPoints.at(section); // generate a string from the control point std::string currentControlPointAsString = mitk::GetControlPointAsString(currentControlPoint); return QVariant(QString::fromStdString(currentControlPointAsString)); } } if (Qt::Vertical == orientation && Qt::DisplayRole == role) { if (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::NodeAdded(const mitk::DataNode* node) { // does not react to data storage changes } void QmitkPatientTableModel::NodeChanged(const mitk::DataNode* node) { // nothing here, since the "'NodeChanged'-event is currently sent far too often //UpdateModelData(); } void QmitkPatientTableModel::NodeRemoved(const mitk::DataNode* node) { // does not react to data storage changes } 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::SetLesionPresence(const mitk::DataNode* dataNode, bool lesionPresence) { if (nullptr == dataNode) { return; } 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)); } } void QmitkPatientTableModel::SetData() { // get all control points of current case m_ControlPoints = m_SemanticRelations->GetAllControlPointsOfCase(m_CaseID); // sort the vector of control points for the timeline std::sort(m_ControlPoints.begin(), m_ControlPoints.end()); // get all information types points of current case m_InformationTypes = m_SemanticRelations->GetAllInformationTypesOfCase(m_CaseID); m_PixmapMap.clear(); m_LesionPresence.clear(); SetDataNodes(); } void QmitkPatientTableModel::SetDataNodes() { std::vector allDataNodes; if("Image" == m_SelectedNodeType) { allDataNodes = m_SemanticRelations->GetAllImagesOfCase(m_CaseID); } else if("Segmentation" == m_SelectedNodeType) { allDataNodes = m_SemanticRelations->GetAllSegmentationsOfCase(m_CaseID); } for (const auto& dataNode : allDataNodes) { // set the pixmap for the current node QPixmap pixmapFromImage = QmitkSemanticRelationsUIHelper::GetPixmapFromImageNode(dataNode); SetPixmapOfNode(dataNode, &pixmapFromImage); // set the lesion presence for the current node if (m_SemanticRelations->InstanceExists(m_CaseID, m_Lesion)) { bool lesionPresence = lesionPresence = IsLesionPresentOnDataNode(dataNode); SetLesionPresence(dataNode, lesionPresence); } else { m_LesionPresence.clear(); } } } bool QmitkPatientTableModel::IsLesionPresentOnDataNode(const mitk::DataNode* dataNode) const { if (m_DataStorage.IsExpired()) { return false; } auto dataStorage = m_DataStorage.Lock(); try { mitk::SemanticRelations::DataNodeVector allSegmentationsOfLesion = m_SemanticRelations->GetAllSegmentationsOfLesion(m_CaseID, m_Lesion); for (const auto& segmentation : allSegmentationsOfLesion) { if ("Segmentation" == m_SelectedNodeType) { if (dataNode == segmentation) { // found a segmentation of the node that is represented by the selected lesion return true; } } else if ("Image" == m_SelectedNodeType) { // get parent node of the current segmentation node with the node predicate mitk::DataStorage::SetOfObjects::ConstPointer parentNodes = dataStorage->GetSources(segmentation, mitk::NodePredicates::GetImagePredicate(), false); for (auto it = parentNodes->Begin(); it != parentNodes->End(); ++it) { if (dataNode == it.Value()) { // found a segmentation of the node that is represented by the selected lesion return true; } } } } } catch (const mitk::SemanticRelationException&) { return false; } return false; } mitk::DataNode* QmitkPatientTableModel::GetCurrentDataNode(const QModelIndex& index) const { 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_SemanticRelations->GetAllSpecificImages(m_CaseID, currentControlPoint, currentInformationType); } else if ("Segmentation" == m_SelectedNodeType) { filteredDataNodes = m_SemanticRelations->GetAllSpecificSegmentations(m_CaseID, currentControlPoint, currentInformationType); } if (filteredDataNodes.empty()) { return nullptr; } return filteredDataNodes.front(); } catch (const mitk::SemanticRelationException&) { return nullptr; } } diff --git a/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.cpp b/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.cpp index 1e4fe0fc80..837aaaf405 100644 --- a/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.cpp +++ b/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.cpp @@ -1,398 +1,391 @@ /*=================================================================== 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 plugin #include "QmitkLesionInfoWidget.h" #include "QmitkSemanticRelationsNodeSelectionDialog.h" // semantic relations UI module #include // semantic relations module #include #include #include // qt #include #include #include #include #include -const QBrush QmitkLesionInfoWidget::DEFAULT_BACKGROUND_COLOR = QBrush(Qt::transparent); -const QBrush QmitkLesionInfoWidget::SELECTED_BACKGROUND_COLOR = QBrush(Qt::green); -const QBrush QmitkLesionInfoWidget::CONNECTED_BACKGROUND_COLOR = QBrush(Qt::darkGreen); - QmitkLesionInfoWidget::QmitkLesionInfoWidget(mitk::DataStorage* dataStorage, QWidget* parent /*= nullptr*/) : QWidget(parent) , m_DataStorage(dataStorage) , m_SemanticRelations(std::make_unique(dataStorage)) { Initialize(); } QmitkLesionInfoWidget::~QmitkLesionInfoWidget() { // nothing here } void QmitkLesionInfoWidget::Initialize() { m_Controls.setupUi(this); m_Controls.lesionTreeView->setAlternatingRowColors(true); m_Controls.lesionTreeView->setSelectionMode(QAbstractItemView::SingleSelection); - m_Controls.lesionTreeView->setSelectionBehavior(QAbstractItemView::SelectItems); + m_Controls.lesionTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); m_Controls.lesionTreeView->setContextMenuPolicy(Qt::CustomContextMenu); m_StorageModel = new QmitkLesionTreeModel(this); if (m_DataStorage.IsExpired()) { return; } auto dataStorage = m_DataStorage.Lock(); m_StorageModel->SetDataStorage(dataStorage); m_Controls.lesionTreeView->setModel(m_StorageModel); SetUpConnections(); } void QmitkLesionInfoWidget::SetUpConnections() { connect(m_StorageModel, &QmitkLesionTreeModel::ModelUpdated, this, &QmitkLesionInfoWidget::OnModelUpdated); // connect buttons to modify semantic relations connect(m_Controls.addLesionPushButton, &QPushButton::clicked, this, &QmitkLesionInfoWidget::OnAddLesionButtonClicked); // connect each list widget with a custom slots - connect(m_Controls.lesionTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QmitkLesionInfoWidget::OnSelectionChanged); + connect(m_Controls.lesionTreeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &QmitkLesionInfoWidget::OnSelectionChanged); // connect context menu entries connect(m_Controls.lesionTreeView, &QTreeView::customContextMenuRequested, this, &QmitkLesionInfoWidget::OnLesionListContextMenuRequested); } void QmitkLesionInfoWidget::SetCaseID(const mitk::SemanticTypes::CaseID& caseID) { m_CaseID = caseID; m_StorageModel->SetCaseID(caseID); } ////////////////////////////////////////////////////////////////////////// // Implementation of the QT_SLOTS ////////////////////////////////////////////////////////////////////////// void QmitkLesionInfoWidget::OnModelUpdated() { m_Controls.lesionTreeView->expandAll(); int columns = m_Controls.lesionTreeView->model()->columnCount(); for (int i = 0; i < columns; ++i) { m_Controls.lesionTreeView->resizeColumnToContents(i); } } void QmitkLesionInfoWidget::OnAddLesionButtonClicked() { if (m_CaseID.empty()) { QMessageBox msgBox; msgBox.setWindowTitle("No case ID set."); msgBox.setText("In order to add a lesion, please specify the current case / patient."); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); return; } mitk::SemanticTypes::Lesion newLesion = mitk::GenerateNewLesion(); try { m_SemanticRelations->AddLesion(m_CaseID, newLesion); } catch (mitk::SemanticRelationException& e) { MITK_INFO << "Could not add a new lesion. " << e; } } -void QmitkLesionInfoWidget::OnSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) +void QmitkLesionInfoWidget::OnSelectionChanged(const QModelIndex& current, const QModelIndex& previous) { - if (nullptr == m_SemanticRelations) + if (nullptr == m_SemanticRelations && current.isValid()) { return; } - for (const auto& index : selected.indexes()) + // only the UID is needed to identify a representing lesion + QVariant data = m_StorageModel->data(current, Qt::UserRole); + if (data.canConvert()) + { + m_CurrentLesion = data.value()->GetData().GetLesion(); + } + else { - // only the UID is needed to identify a representing lesion - QVariant data = m_StorageModel->data(index, Qt::UserRole); - if (data.canConvert()) - { - m_CurrentLesion = data.value()->GetData().GetLesion(); - } - else - { - return; - } - - if (false == m_SemanticRelations->InstanceExists(m_CaseID, m_CurrentLesion)) - { - // no UID found; cannot create a lesion - continue; - } - - emit LesionChanged(m_CurrentLesion); + return; } + + if (false == m_SemanticRelations->InstanceExists(m_CaseID, m_CurrentLesion)) + { + // no UID of a existing lesion found; cannot create a lesion + return; + } + + emit LesionChanged(m_CurrentLesion); } void QmitkLesionInfoWidget::OnLesionListContextMenuRequested(const QPoint& pos) { QModelIndex index = m_Controls.lesionTreeView->indexAt(pos); if (!index.isValid()) { // no item clicked; cannot retrieve the current lesion return; } QVariant data = m_StorageModel->data(index, Qt::UserRole); mitk::SemanticTypes::Lesion selectedLesion; if (data.canConvert()) { selectedLesion = data.value()->GetData().GetLesion(); } else { return; } QMenu* menu = new QMenu(m_Controls.lesionTreeView); QAction* linkToSegmentation = new QAction("Link to segmentation", this); linkToSegmentation->setEnabled(true); connect(linkToSegmentation, &QAction::triggered, [this, selectedLesion] { OnLinkToSegmentation(selectedLesion); }); menu->addAction(linkToSegmentation); QAction* setLesionName = new QAction("Set lesion name", this); setLesionName->setEnabled(true); connect(setLesionName, &QAction::triggered, [this, selectedLesion] { OnSetLesionName(selectedLesion); }); menu->addAction(setLesionName); QAction* setLesionClass = new QAction("Set lesion class", this); setLesionClass->setEnabled(true); connect(setLesionClass, &QAction::triggered, [this, selectedLesion] { OnSetLesionClass(selectedLesion); }); menu->addAction(setLesionClass); QAction* removeLesion = new QAction("Remove lesion", this); removeLesion->setEnabled(true); connect(removeLesion, &QAction::triggered, [this, selectedLesion] { OnRemoveLesion(selectedLesion); }); menu->addAction(removeLesion); menu->popup(QCursor::pos()); } void QmitkLesionInfoWidget::OnLinkToSegmentation(mitk::SemanticTypes::Lesion selectedLesion) { if (m_CaseID.empty()) { QMessageBox msgBox; msgBox.setWindowTitle("No case ID set."); msgBox.setText("In order to link a lesion to a segmentation, please specify the current case / patient."); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); return; } if (m_DataStorage.IsExpired()) { return; } auto dataStorage = m_DataStorage.Lock(); QmitkSemanticRelationsNodeSelectionDialog* dialog = new QmitkSemanticRelationsNodeSelectionDialog(this, "Select segmentation to link to the selected lesion.", ""); dialog->SetDataStorage(dataStorage); dialog->setWindowTitle("Select segmentation node"); dialog->SetNodePredicate(mitk::NodePredicates::GetSegmentationPredicate()); dialog->SetSelectOnlyVisibleNodes(true); dialog->SetSelectionMode(QAbstractItemView::SingleSelection); dialog->SetCaseID(m_CaseID); int dialogReturnValue = dialog->exec(); if (QDialog::Rejected == dialogReturnValue) { return; } auto nodes = dialog->GetSelectedNodes(); mitk::DataNode::Pointer selectedDataNode = nullptr; if (!nodes.isEmpty()) { // only single selection allowed selectedDataNode = nodes.front(); } if (nullptr == selectedDataNode) { QMessageBox msgBox; msgBox.setWindowTitle("No valid segmentation node selected."); msgBox.setText("In order to link the selected lesion to a segmentation, please specify a valid segmentation node."); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); return; } if (false == mitk::NodePredicates::GetSegmentationPredicate()->CheckNode(selectedDataNode)) { QMessageBox msgBox; msgBox.setWindowTitle("No segmentation selected"); msgBox.setText("In order to link the selected lesion to a segmentation, please specify a valid segmentation node."); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); return; } mitk::BaseData* baseData = selectedDataNode->GetData(); if (nullptr == baseData) { QMessageBox msgBox; msgBox.setWindowTitle("No valid base data."); msgBox.setText("In order to link the selected lesion to a segmentation, please specify a valid segmentation node."); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); return; } try { m_SemanticRelations->LinkSegmentationToLesion(selectedDataNode, selectedLesion); } catch (const mitk::SemanticRelationException& e) { std::stringstream exceptionMessage; exceptionMessage << e; QMessageBox msgBox; msgBox.setWindowTitle("Could not link the selected lesion."); msgBox.setText("The program wasn't able to correctly link the selected lesion with the selected segmentation.\n" "Reason:\n" + QString::fromStdString(exceptionMessage.str())); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); } } void QmitkLesionInfoWidget::OnSetLesionName(mitk::SemanticTypes::Lesion selectedLesion) { if (m_CaseID.empty()) { QMessageBox msgBox; msgBox.setWindowTitle("No case ID set."); msgBox.setText("In order to set a lesion name, please specify the current case / patient."); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); return; } // use the lesion information to set the input text for the dialog QmitkLesionTextDialog* inputDialog = new QmitkLesionTextDialog(this); inputDialog->setWindowTitle("Set lesion name"); inputDialog->SetLineEditText(selectedLesion.name); int dialogReturnValue = inputDialog->exec(); if (QDialog::Rejected == dialogReturnValue) { return; } std::string newLesionName = inputDialog->GetLineEditText().toStdString(); selectedLesion.name = newLesionName; m_SemanticRelations->OverwriteLesion(m_CaseID, selectedLesion); } void QmitkLesionInfoWidget::OnSetLesionClass(mitk::SemanticTypes::Lesion selectedLesion) { if (m_CaseID.empty()) { QMessageBox msgBox; msgBox.setWindowTitle("No case ID set."); msgBox.setText("In order to set a lesion class, please specify the current case / patient."); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); return; } // use the lesion information to set the input text for the dialog QmitkLesionTextDialog* inputDialog = new QmitkLesionTextDialog(this); inputDialog->setWindowTitle("Set lesion class"); inputDialog->SetLineEditText(selectedLesion.lesionClass.classType); // prepare the completer for the dialogs input text field mitk::LesionClassVector allLesionClasses = m_SemanticRelations->GetAllLesionClassesOfCase(m_CaseID); QStringList wordList; for (const auto& lesionClass : allLesionClasses) { wordList << QString::fromStdString(lesionClass.classType); } QCompleter* completer = new QCompleter(wordList, this); completer->setCaseSensitivity(Qt::CaseInsensitive); inputDialog->GetLineEdit()->setCompleter(completer); int dialogReturnValue = inputDialog->exec(); if (QDialog::Rejected == dialogReturnValue) { return; } // retrieve the new input lesion class type and check for an already existing lesion class types std::string newLesionClassType = inputDialog->GetLineEditText().toStdString(); mitk::SemanticTypes::LesionClass existingLesionClass = mitk::FindExistingLesionClass(newLesionClassType, allLesionClasses); if (existingLesionClass.UID.empty()) { // could not find lesion class information for the new lesion class type // create a new lesion class for the selected lesion existingLesionClass = mitk::GenerateNewLesionClass(newLesionClassType); } selectedLesion.lesionClass = existingLesionClass; m_SemanticRelations->OverwriteLesion(m_CaseID, selectedLesion); } void QmitkLesionInfoWidget::OnRemoveLesion(mitk::SemanticTypes::Lesion selectedLesion) { if (m_CaseID.empty()) { QMessageBox msgBox; msgBox.setWindowTitle("No case ID set."); msgBox.setText("In order to remove a lesion, please specify the current case / patient."); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); return; } try { m_SemanticRelations->RemoveLesion(m_CaseID, selectedLesion); } catch (const mitk::SemanticRelationException& e) { std::stringstream exceptionMessage; exceptionMessage << e; QMessageBox msgBox; msgBox.setWindowTitle("Could not remove the selected lesion."); msgBox.setText("The program wasn't able to correctly remove the selected lesion from the semantic relations model.\n" "Reason:\n" + QString::fromStdString(exceptionMessage.str())); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); } } diff --git a/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.h b/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.h index f85fc97835..5596a18cc2 100644 --- a/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.h +++ b/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.h @@ -1,100 +1,99 @@ /*=================================================================== 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 QMITKLESIONINFOWIDGET_H #define QMITKLESIONINFOWIDGET_H // semantic relations plugin #include // semantic relations UI module #include // semantic relations module #include // mitk #include // qt #include /* * @brief The QmitkLesionInfoWidget is a widget that shows and modifies the currently available lesion data of the semantic relations model. * * The widget provides a dialogs to add nodes from the data storage to the semantic relations model. * It provides functionality to create new lesions and link them with segmentation nodes. * * The QmitkLesionInfoWidget provides three QListWidgets, that show the lesion data and the referenced segmentation data, as * well as the connected image data, depending on the selected lesion. */ class QmitkLesionInfoWidget : public QWidget { Q_OBJECT public: static const QBrush DEFAULT_BACKGROUND_COLOR; static const QBrush SELECTED_BACKGROUND_COLOR; static const QBrush CONNECTED_BACKGROUND_COLOR; QmitkLesionInfoWidget::QmitkLesionInfoWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr); ~QmitkLesionInfoWidget(); void SetCaseID(const mitk::SemanticTypes::CaseID& caseID); const mitk::SemanticTypes::Lesion& GetSelectedLesion() const { return m_CurrentLesion; } Q_SIGNALS: void LesionChanged(const mitk::SemanticTypes::Lesion&); private Q_SLOTS: void OnModelUpdated(); /* * @brief Generates a new, empty lesion to add to the semantic relations model for the current case ID. */ void OnAddLesionButtonClicked(); - // slots for the mouse click events of the list widgets - void OnSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); - //void OnLesionItemDoubleClicked(QListWidgetItem*); + // slots for the mouse click events of tree view's selection model + void OnSelectionChanged(const QModelIndex& current, const QModelIndex& previous); void OnLesionListContextMenuRequested(const QPoint&); // slots for the context menu actions of the lesion list widget void OnLinkToSegmentation(mitk::SemanticTypes::Lesion); void OnSetLesionName(mitk::SemanticTypes::Lesion); void OnSetLesionClass(mitk::SemanticTypes::Lesion); void OnRemoveLesion(mitk::SemanticTypes::Lesion); private: void Initialize(); void SetUpConnections(); Ui::QmitkLesionInfoWidgetControls m_Controls; QmitkLesionTreeModel* m_StorageModel; mitk::WeakPointer m_DataStorage; std::unique_ptr m_SemanticRelations; mitk::SemanticTypes::CaseID m_CaseID; mitk::SemanticTypes::Lesion m_CurrentLesion; }; #endif // QMITKLESIONINFOWIDGET_H