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 3b20caedf4..327874c39f 100644 --- a/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.cpp +++ b/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.cpp @@ -1,483 +1,431 @@ /*=================================================================== 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 +#include +#include // registration ontology module #include // qt #include #include #include #include #include QmitkLesionInfoWidget::QmitkLesionInfoWidget(mitk::DataStorage* dataStorage, QWidget* parent /*= nullptr*/) : QWidget(parent) , m_DataStorage(dataStorage) - , m_SemanticRelations(std::make_unique(dataStorage)) + , m_SemanticRelationsDataStorageAccess(std::make_unique(dataStorage)) + , m_SemanticRelationsIntegration(std::make_unique()) { 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::SelectRows); m_Controls.lesionTreeView->setContextMenuPolicy(Qt::CustomContextMenu); - m_StorageModel = new QmitkLesionTreeModel(this); + m_StorageModel = new QmitkLesionTreeModel(m_Controls.lesionTreeView); 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::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); } void QmitkLesionInfoWidget::SetDataNodeSelection(const QList& dataNodeSelection) { m_StorageModel->SetDataNodeSelection(dataNodeSelection); } ////////////////////////////////////////////////////////////////////////// // 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); + m_SemanticRelationsIntegration->AddLesion(m_CaseID, newLesion); } catch (mitk::SemanticRelationException& e) { MITK_INFO << "Could not add a new lesion. " << e; } } void QmitkLesionInfoWidget::OnSelectionChanged(const QModelIndex& current, const QModelIndex& previous) { - if (nullptr == m_SemanticRelations && current.isValid()) - { - return; - } - // 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 + if (!data.canConvert()) { return; } - if (false == m_SemanticRelations->InstanceExists(m_CaseID, m_CurrentLesion)) + auto lesion = data.value()->GetData().GetLesion(); + if (false == mitk::SemanticRelationsInference::InstanceExists(m_CaseID, lesion)) { // no UID of a existing lesion found; cannot create a lesion return; } // if selected data nodes are set, reset to empty list to - // the "selected data nodes presence background highlighting" in the model + // hide "selected data nodes presence background highlighting" in the model if (!m_StorageModel->GetSelectedDataNodes().isEmpty()) { m_StorageModel->SetDataNodeSelection(QList()); } - emit LesionSelectionChanged(m_CurrentLesion); + emit LesionSelectionChanged(lesion); } void QmitkLesionInfoWidget::OnLesionListContextMenuRequested(const QPoint& pos) { + if (nullptr == m_SemanticRelationsIntegration) + { + return; + } + + if (m_CaseID.empty()) + { + QMessageBox msgBox(QMessageBox::Warning, + "No case ID set.", + "In order to access the context menu entries a case ID has to be set."); + msgBox.exec(); + return; + } + 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* propageLesionToImage = new QAction("Propagate lesion to image", this); propageLesionToImage->setEnabled(true); connect(propageLesionToImage, &QAction::triggered, [this, selectedLesion] { OnPropagateLesion(selectedLesion); }); menu->addAction(propageLesionToImage); 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->SetDataStorage(dataStorage); 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 || false == mitk::NodePredicates::GetSegmentationPredicate()->CheckNode(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); + QMessageBox msgBox(QMessageBox::Warning, + "No valid segmentation node selected.", + "In order to link the selected lesion to a segmentation, please specify a valid segmentation node."); 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); + QMessageBox msgBox(QMessageBox::Warning, + "No valid base data.", + "In order to link the selected lesion to a segmentation, please specify a valid segmentation node."); msgBox.exec(); return; } try { - m_SemanticRelations->LinkSegmentationToLesion(selectedDataNode, selectedLesion); + m_SemanticRelationsIntegration->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" + QMessageBox msgBox(QMessageBox::Warning, + "Could not link the selected lesion.", + "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); + selectedLesion.name = inputDialog->GetLineEditText().toStdString(); + m_SemanticRelationsIntegration->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); + mitk::LesionClassVector allLesionClasses = mitk::SemanticRelationsInference::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); + m_SemanticRelationsIntegration->OverwriteLesion(m_CaseID, selectedLesion); } void QmitkLesionInfoWidget::OnPropagateLesion(mitk::SemanticTypes::Lesion selectedLesion) { - if (m_CaseID.empty()) - { - QMessageBox msgBox; - msgBox.setWindowTitle("No case ID set."); - msgBox.setText("In order to propagate a lesion to an image, 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 data node to propagate the selected lesion.", ""); - dialog->SetDataStorage(dataStorage); dialog->setWindowTitle("Select image node"); + dialog->SetDataStorage(dataStorage); dialog->SetNodePredicate(mitk::NodePredicates::GetImagePredicate()); dialog->SetSelectOnlyVisibleNodes(true); - dialog->SetSelectionMode(QAbstractItemView::SingleSelection); dialog->SetCaseID(m_CaseID); dialog->SetLesion(selectedLesion); 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 || false == mitk::NodePredicates::GetImagePredicate()->CheckNode(selectedDataNode)) { - QMessageBox msgBox; - msgBox.setWindowTitle("No valid image node selected."); - msgBox.setText("In order to propagate the selected lesion to an image, please specify a valid image node."); - msgBox.setIcon(QMessageBox::Warning); + QMessageBox msgBox(QMessageBox::Warning, + "No valid image node selected.", + "In order to propagate the selected lesion to an image, please specify a valid image node."); msgBox.exec(); return; } mitk::BaseData* baseData = selectedDataNode->GetData(); if (nullptr == baseData) { - QMessageBox msgBox; - msgBox.setWindowTitle("No valid base data."); - msgBox.setText("In order to propagate the selected lesion to an image, please specify a valid image node."); - msgBox.setIcon(QMessageBox::Warning); + QMessageBox msgBox(QMessageBox::Warning, + "No valid base data.", + "In order to propagate the selected lesion to an image, please specify a valid image node."); msgBox.exec(); return; } try { - auto allSegmentationsOfLesion = m_SemanticRelations->GetAllSegmentationsOfLesion(m_CaseID, selectedLesion); - mitk::FindClosestSegmentationMask(); + auto allSegmentationsOfLesion = m_SemanticRelationsDataStorageAccess->GetAllSegmentationsOfLesion(m_CaseID, selectedLesion); + mitk::LesionPropagation::FindClosestSegmentationMask(); } catch (const mitk::SemanticRelationException& e) { std::stringstream exceptionMessage; exceptionMessage << e; - QMessageBox msgBox; - msgBox.setWindowTitle("Could not propagate the selected lesion."); - msgBox.setText("The program wasn't able to correctly propagate the selected lesion to the selected image.\n" + QMessageBox msgBox(QMessageBox::Warning, + "Could not propagate the selected lesion.", + "The program wasn't able to correctly propagate the selected lesion to the selected image.\n" "Reason:\n" + QString::fromStdString(exceptionMessage.str())); - msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); } } 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); + m_SemanticRelationsIntegration->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); + QMessageBox msgBox(QMessageBox::Warning, + "Could not remove the selected lesion.", + "The program wasn't able to correctly remove the selected lesion from the semantic relations model.\n" + "Reason:\n" + QString::fromStdString(exceptionMessage.str())); 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 a26a97569b..15f3d95930 100644 --- a/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.h +++ b/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.h @@ -1,102 +1,102 @@ /*=================================================================== 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 +#include +#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); void SetDataNodeSelection(const QList& dataNodeSelection); - const mitk::SemanticTypes::Lesion& GetSelectedLesion() const { return m_CurrentLesion; } - Q_SIGNALS: void LesionSelectionChanged(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 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 OnPropagateLesion(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; + mitk::WeakPointer m_DataStorage; + std::unique_ptr m_SemanticRelationsDataStorageAccess; + std::unique_ptr m_SemanticRelationsIntegration; + }; #endif // QMITKLESIONINFOWIDGET_H diff --git a/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkSemanticRelationsView.cpp b/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkSemanticRelationsView.cpp index 64bc9c6194..8166a94d17 100644 --- a/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkSemanticRelationsView.cpp +++ b/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkSemanticRelationsView.cpp @@ -1,276 +1,280 @@ /*=================================================================== 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 "QmitkSemanticRelationsView.h" #include "QmitkDataNodeAddToSemanticRelationsAction.h" #include "QmitkDataNodeRemoveFromSemanticRelationsAction.h" // semantic relations module +#include #include #include +#include +#include // mitk qt widgets module #include #include // mitk multi label module #include // berry #include #include // qt #include #include const std::string QmitkSemanticRelationsView::VIEW_ID = "org.mitk.views.semanticrelations"; void QmitkSemanticRelationsView::SetFocus() { // nothing here } void QmitkSemanticRelationsView::CreateQtPartControl(QWidget* parent) { // create GUI widgets m_Controls.setupUi(parent); - // initialize the semantic relations - m_SemanticRelations = std::make_unique(GetDataStorage()); - m_LesionInfoWidget = new QmitkLesionInfoWidget(GetDataStorage(), parent); m_Controls.gridLayout->addWidget(m_LesionInfoWidget); m_PatientTableInspector = new QmitkPatientTableInspector(parent); m_PatientTableInspector->SetDataStorage(GetDataStorage()); m_Controls.gridLayout->addWidget(m_PatientTableInspector); QGridLayout* dndDataNodeWidgetLayout = new QGridLayout; dndDataNodeWidgetLayout->addWidget(m_PatientTableInspector, 0, 0); dndDataNodeWidgetLayout->setContentsMargins(0, 0, 0, 0); m_DnDDataNodeWidget = new QmitkDnDDataNodeWidget(parent); m_DnDDataNodeWidget->setLayout(dndDataNodeWidgetLayout); m_Controls.gridLayout->addWidget(m_DnDDataNodeWidget); m_ContextMenu = new QmitkSemanticRelationsContextMenu(GetSite(), m_PatientTableInspector); m_ContextMenu->SetDataStorage(GetDataStorage()); mitk::IRenderWindowPart* renderWindowPart = GetRenderWindowPart(); if (nullptr != renderWindowPart) { RenderWindowPartActivated(renderWindowPart); } SetUpConnections(); - const auto& allCaseIDs = m_SemanticRelations->GetAllCaseIDs(); + const auto& allCaseIDs = mitk::RelationStorage::GetAllCaseIDs(); for (const auto& caseID : allCaseIDs) { AddToComboBox(caseID); } } void QmitkSemanticRelationsView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) { // connect QmitkRenderWindows - underlying vtkRenderWindow is the same as "mitk::RenderingManager::GetInstance()->GetAllRegisteredRenderWindows()" QHash windowMap = renderWindowPart->GetQmitkRenderWindows(); QHash::Iterator it; mitk::BaseRenderer* baseRenderer = nullptr; RenderWindowLayerUtilities::RendererVector controlledRenderer; for (it = windowMap.begin(); it != windowMap.end(); ++it) { baseRenderer = mitk::BaseRenderer::GetInstance(it.value()->GetVtkRenderWindow()); if (nullptr != baseRenderer) { controlledRenderer.push_back(baseRenderer); } } m_ContextMenu->SetControlledRenderer(controlledRenderer); } void QmitkSemanticRelationsView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart) { // nothing here } void QmitkSemanticRelationsView::SetUpConnections() { connect(m_Controls.caseIDComboBox, static_cast(&QComboBox::currentIndexChanged), this, &QmitkSemanticRelationsView::OnCaseIDSelectionChanged); connect(m_LesionInfoWidget, &QmitkLesionInfoWidget::LesionSelectionChanged, this, &QmitkSemanticRelationsView::OnLesionSelectionChanged); connect(m_PatientTableInspector, &QmitkPatientTableInspector::CurrentSelectionChanged, this, &QmitkSemanticRelationsView::OnDataNodeSelectionChanged); connect(m_PatientTableInspector, &QmitkPatientTableInspector::DataNodeDoubleClicked, this, &QmitkSemanticRelationsView::OnDataNodeDoubleClicked); connect(m_DnDDataNodeWidget, &QmitkDnDDataNodeWidget::NodesDropped, this, &QmitkSemanticRelationsView::OnNodesAdded); connect(m_PatientTableInspector, &QmitkPatientTableInspector::OnContextMenuRequested, m_ContextMenu, &QmitkSemanticRelationsContextMenu::OnContextMenuRequested); connect(m_PatientTableInspector, &QmitkPatientTableInspector::OnNodeRemoved, this, &QmitkSemanticRelationsView::NodeRemoved); } QItemSelectionModel* QmitkSemanticRelationsView::GetDataNodeSelectionModel() const { return m_PatientTableInspector->GetSelectionModel(); } void QmitkSemanticRelationsView::NodeRemoved(const mitk::DataNode* dataNode) { if (nullptr == dataNode) { return; } - if (m_SemanticRelations->InstanceExists(dataNode)) + if (mitk::SemanticRelationsInference::InstanceExists(dataNode)) { - RemoveFromSemanticRelationsAction::Run(m_SemanticRelations.get(), dataNode); + // no observer needed for the integration; simply use a temporary instance for removing + mitk::SemanticRelationsIntegration semanticRelationsIntegration; + RemoveFromSemanticRelationsAction::Run(&semanticRelationsIntegration, dataNode); mitk::SemanticTypes::CaseID caseID = mitk::GetCaseIDFromDataNode(dataNode); RemoveFromComboBox(caseID); } } void QmitkSemanticRelationsView::OnLesionSelectionChanged(const mitk::SemanticTypes::Lesion& lesion) { m_PatientTableInspector->SetLesion(lesion); } void QmitkSemanticRelationsView::OnDataNodeSelectionChanged(const QList& dataNodeSelection) { m_LesionInfoWidget->SetDataNodeSelection(dataNodeSelection); } void QmitkSemanticRelationsView::OnDataNodeDoubleClicked(const mitk::DataNode* dataNode) { if (nullptr == dataNode) { return; } if (mitk::NodePredicates::GetImagePredicate()->CheckNode(dataNode)) { OpenInEditor(dataNode); } else if (mitk::NodePredicates::GetSegmentationPredicate()->CheckNode(dataNode)) { JumpToPosition(dataNode); } } void QmitkSemanticRelationsView::OnCaseIDSelectionChanged(const QString& caseID) { m_LesionInfoWidget->SetCaseID(caseID.toStdString()); m_PatientTableInspector->SetCaseID(caseID.toStdString()); } void QmitkSemanticRelationsView::OnNodesAdded(QmitkDnDDataNodeWidget* dnDDataNodeWidget, std::vector nodes) { mitk::SemanticTypes::CaseID caseID = ""; for (mitk::DataNode* dataNode : nodes) { - AddToSemanticRelationsAction::Run(m_SemanticRelations.get(), GetDataStorage(), dataNode); + // no observer needed for the integration; simply use a temporary instance for adding + mitk::SemanticRelationsIntegration semanticRelationsIntegration; + AddToSemanticRelationsAction::Run(&semanticRelationsIntegration, GetDataStorage(), dataNode); caseID = mitk::GetCaseIDFromDataNode(dataNode); AddToComboBox(caseID); } } void QmitkSemanticRelationsView::OnNodeRemoved(const mitk::DataNode* dataNode) { NodeRemoved(dataNode); } void QmitkSemanticRelationsView::AddToComboBox(const mitk::SemanticTypes::CaseID& caseID) { int foundIndex = m_Controls.caseIDComboBox->findText(QString::fromStdString(caseID)); if (-1 == foundIndex) { // add the caseID to the combo box, as it is not already contained m_Controls.caseIDComboBox->addItem(QString::fromStdString(caseID)); } } void QmitkSemanticRelationsView::RemoveFromComboBox(const mitk::SemanticTypes::CaseID& caseID) { - std::vector allControlPoints = m_SemanticRelations->GetAllControlPointsOfCase(caseID); + std::vector allControlPoints = mitk::RelationStorage::GetAllControlPointsOfCase(caseID); int foundIndex = m_Controls.caseIDComboBox->findText(QString::fromStdString(caseID)); if (allControlPoints.empty() && -1 != foundIndex) { // TODO: find new way to check for empty case id // caseID does not contain any control points and therefore no data // remove the caseID, if it is still contained m_Controls.caseIDComboBox->removeItem(foundIndex); } } void QmitkSemanticRelationsView::OpenInEditor(const mitk::DataNode* dataNode) { auto renderWindowPart = GetRenderWindowPart(); if (nullptr == renderWindowPart) { renderWindowPart = GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategy::BRING_TO_FRONT | mitk::WorkbenchUtil::IRenderWindowPartStrategy::OPEN); if (nullptr == renderWindowPart) { // no render window available return; } } auto image = dynamic_cast(dataNode->GetData()); if (nullptr != image) { mitk::RenderingManager::GetInstance()->InitializeViews(image->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); } } void QmitkSemanticRelationsView::JumpToPosition(const mitk::DataNode* dataNode) { if (nullptr == dataNode) { return; } mitk::LabelSetImage* labelSetImage = dynamic_cast(dataNode->GetData()); if (nullptr == labelSetImage) { return; } int activeLayer = labelSetImage->GetActiveLayer(); mitk::Label* activeLabel = labelSetImage->GetActiveLabel(activeLayer); labelSetImage->UpdateCenterOfMass(activeLabel->GetValue(), activeLayer); const mitk::Point3D& centerPosition = activeLabel->GetCenterOfMassCoordinates(); if (centerPosition.GetVnlVector().max_value() > 0.0) { auto renderWindowPart = GetRenderWindowPart(); if (nullptr == renderWindowPart) { renderWindowPart = GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategy::BRING_TO_FRONT | mitk::WorkbenchUtil::IRenderWindowPartStrategy::OPEN); if (nullptr == renderWindowPart) { // no render window available return; } } auto segmentation = dynamic_cast(dataNode->GetData()); if (nullptr != segmentation) { renderWindowPart->SetSelectedPosition(centerPosition); mitk::RenderingManager::GetInstance()->InitializeViews(segmentation->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); } } } diff --git a/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkSemanticRelationsView.h b/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkSemanticRelationsView.h index 805dc045bf..68341a9722 100644 --- a/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkSemanticRelationsView.h +++ b/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkSemanticRelationsView.h @@ -1,108 +1,105 @@ /*=================================================================== 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 QMITKSEMANTICRELATIONSVIEW_H #define QMITKSEMANTICRELATIONSVIEW_H // semantic relations plugin #include "ui_QmitkSemanticRelationsControls.h" #include "QmitkLesionInfoWidget.h" #include "QmitkSemanticRelationsContextMenu.h" // semantic relations module -#include #include // semantic relations UI module #include // mitk gui common plugin #include // berry #include // mitk qt #include class QmitkDnDDataNodeWidget; class QMenu; /* * @brief The QmitkSemanticRelationsView is an MITK view to combine and show the widgets of the 'SemanticRelationsUI'-module and this semantic relations plugin. * * It allows the MITK user to see and modify the content of the SemanticRelations-session. * A combo box is used to select and show the current patient. */ class QmitkSemanticRelationsView : public QmitkAbstractView, public mitk::IRenderWindowPartListener { Q_OBJECT public: static const std::string VIEW_ID; protected: virtual void SetFocus() override; virtual void CreateQtPartControl(QWidget* parent) override; virtual void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) override; virtual void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart) override; private Q_SLOTS: void OnLesionSelectionChanged(const mitk::SemanticTypes::Lesion&); void OnDataNodeSelectionChanged(const QList&); void OnDataNodeDoubleClicked(const mitk::DataNode*); void OnCaseIDSelectionChanged(const QString&); void OnNodesAdded(QmitkDnDDataNodeWidget*, std::vector); void OnNodeRemoved(const mitk::DataNode*); private: void SetUpConnections(); /** * @brief Provide a QItemSelectionModel, which supports the data role 'QmitkDataNodeRole' (\see QmitkRenderWindowDataModel). * * The provided QItemSelectionModel is used in the QmitkAbstractView-base class as the selection model of * the selection provider (\see QmitkAbstractView::SetSelectionProvider()). * The default selection provider is a QmitkDataNodeSelectionProvider. Each time a selection in the provided * QItemSeletionModel is changed, a selection changed event is fired. All plugins (views), that subclass the * QmitkAbstractView will be informed about the selection changed via the OnSelectionChanged-function. */ virtual QItemSelectionModel* GetDataNodeSelectionModel() const override; virtual void NodeRemoved(const mitk::DataNode* dataNode) override; void AddToComboBox(const mitk::SemanticTypes::CaseID& caseID); void RemoveFromComboBox(const mitk::SemanticTypes::CaseID& caseID); void OpenInEditor(const mitk::DataNode* dataNode); void JumpToPosition(const mitk::DataNode* dataNode); Ui::QmitkSemanticRelationsControls m_Controls; QmitkLesionInfoWidget* m_LesionInfoWidget; QmitkPatientTableInspector* m_PatientTableInspector; QmitkDnDDataNodeWidget* m_DnDDataNodeWidget; QmitkSemanticRelationsContextMenu* m_ContextMenu; - - std::unique_ptr m_SemanticRelations; }; #endif // QMITKSEMANTICRELATIONSVIEW_H