diff --git a/Modules/ModuleList.cmake b/Modules/ModuleList.cmake index b9a9267a2a..68266fabfd 100644 --- a/Modules/ModuleList.cmake +++ b/Modules/ModuleList.cmake @@ -1,86 +1,86 @@ # The entries in the mitk_modules list must be # ordered according to their dependencies. set(MITK_MODULES Core CommandLine AppUtil RDF LegacyIO DataTypesExt Annotation LegacyGL AlgorithmsExt MapperExt DICOMReader DICOMReaderServices DICOMQI DICOMTesting SceneSerializationBase PlanarFigure ImageDenoising ImageExtraction SceneSerialization Gizmo GraphAlgorithms Multilabel ImageStatistics ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation QtWidgets QtWidgetsExt Chart SegmentationUI MatchPointRegistration MatchPointRegistrationUI Classification GPGPU OpenIGTLink IGTBase IGT CameraCalibration OpenCL OpenCVVideoSupport QtOverlays ToFHardware ToFProcessing ToFUI PhotoacousticsHardware PhotoacousticsAlgorithms PhotoacousticsLib US USUI DicomUI - RegistrationOntology Remeshing Python QtPython Persistence OpenIGTLinkUI IGTUI DicomRT RTUI IOExt XNAT TubeGraph BiophotonicsHardware DiffusionImaging TumorInvasionAnalysis BoundingShape RenderWindowManager RenderWindowManagerUI SemanticRelations SemanticRelationsUI + RegistrationOntology CEST BasicImageProcessing ModelFit ModelFitUI Pharmacokinetics PharmacokineticsUI ) if(MITK_ENABLE_PIC_READER) list(APPEND MITK_MODULES IpPicSupportIO) endif() diff --git a/Modules/RegistrationOntology/CMakeLists.txt b/Modules/RegistrationOntology/CMakeLists.txt index ad8b813481..c0ca9b3aa3 100644 --- a/Modules/RegistrationOntology/CMakeLists.txt +++ b/Modules/RegistrationOntology/CMakeLists.txt @@ -1,4 +1,4 @@ MITK_CREATE_MODULE( - DEPENDS MitkCore + DEPENDS MitkSemanticRelations PACKAGE_DEPENDS PUBLIC MatchPoint ) diff --git a/Modules/RegistrationOntology/include/mitkLesionPropagation.h b/Modules/RegistrationOntology/include/mitkLesionPropagation.h index ea2a7a7cd9..f1c042b4a7 100644 --- a/Modules/RegistrationOntology/include/mitkLesionPropagation.h +++ b/Modules/RegistrationOntology/include/mitkLesionPropagation.h @@ -1,35 +1,62 @@ /*=================================================================== 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 MITKLESIONPROPAGATION_H #define MITKLESIONPROPAGATION_H // registration ontology module #include "MitkRegistrationOntologyExports.h" // mitk core -#include +#include + +// semantic relations module +#include // matchpoint ontology #include #include namespace mitk { - MITKREGISTRATIONONTOLOGY_EXPORT void FindClosestSegmentationMask(); + /** + * @brief #TODO no need to use semantic relations; directly use relation storage if it is a namespace file + * + * + */ + class MITKREGISTRATIONONTOLOGY_EXPORT LesionPropagation + { + public: + + LesionPropagation(DataStorage* dataStorage); + + DataNode* FindClosestSegmentationMask(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& sourceLesion, DataNode* targetImage); + void PropagateSegmentationMask(const SemanticTypes::CaseID& caseID, DataNode* segmentationMask, DataNode* targetImage); + + private: + + bool LesionPropagation::CheckControlPoint(const DataNode* lesionImage, const DataNode* targetImage); + bool LesionPropagation::CheckInformationType(const DataNode* lesionImage, const DataNode* targetImage); + DataNode* LesionPropagation::GetSegmentationFromRelatedImage(const SemanticTypes::Lesion& sourceLesion, const DataNode* lesionImage); + bool LesionPropagation::CheckRegistration(const DataNode* lesionImage, const DataNode* targetImage); + + WeakPointer m_DataStorage; + std::unique_ptr m_SemanticRelations; + + }; } // namespace mitk #endif // MITKLESIONPROPAGATION_H diff --git a/Modules/RegistrationOntology/src/mitkLesionPropagation.cpp b/Modules/RegistrationOntology/src/mitkLesionPropagation.cpp index 7f73c07a76..d0234efdcc 100644 --- a/Modules/RegistrationOntology/src/mitkLesionPropagation.cpp +++ b/Modules/RegistrationOntology/src/mitkLesionPropagation.cpp @@ -1,22 +1,185 @@ /*=================================================================== 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. ===================================================================*/ #include "mitkLesionPropagation.h" -void mitk::FindClosestSegmentationMask() +// semantic relations module +#include "mitkSemanticRelationException.h" + +// multilabel module +#include "mitkLabelSetImage.h" + +mitk::LesionPropagation::LesionPropagation(DataStorage* dataStorage) + : m_DataStorage(dataStorage) + , m_SemanticRelations(std::make_unique(dataStorage)) +{ + // nothing here +} + +mitk::DataNode* mitk::LesionPropagation::FindClosestSegmentationMask(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& sourceLesion, DataNode* targetImage) +{ + auto allImagesOfLesion = m_SemanticRelations->GetAllImagesOfLesion(caseID, sourceLesion); + SemanticRelations::DataNodeVector sameControlPointImages; + SemanticRelations::DataNodeVector sameInformationTypeImages; + for (const auto& image : allImagesOfLesion) + { + bool sameControlPoint = CheckControlPoint(image, targetImage); + bool sameInformationType = CheckInformationType(image, targetImage); + if(sameControlPoint && !sameInformationType) + { + // lesion image and target image are in the same control point relation group + sameControlPointImages.push_back(image); + } + if (sameInformationType && !sameControlPoint) + { + // lesion image and target image are in the same information type group + sameInformationTypeImages.push_back(image); + } + } + + // sorted all lesion images according to the target image's relation group + for (const auto& image : sameControlPointImages) + { + // check if any image in the same control point relation group is registered to the target image + bool registered = CheckRegistration(image, targetImage); + if (registered) + { + auto segmentationNode = GetSegmentationFromRelatedImage(sourceLesion, image); + if (nullptr != segmentationNode) + { + return segmentationNode; + } + } + } + + for (const auto& image : sameInformationTypeImages) + { + bool registered = CheckRegistration(image, targetImage); + if (registered) + { + // check if any image in the same information type relation group is registered to the target image + auto segmentationNode = GetSegmentationFromRelatedImage(sourceLesion, image); + if (nullptr != segmentationNode) + { + return segmentationNode; + } + } + } + + return nullptr; +} + +void mitk::LesionPropagation::PropagateSegmentationMask(const SemanticTypes::CaseID& caseID, DataNode* segmentationMask, DataNode* targetImage) +{ + if (m_DataStorage.IsExpired()) + { + return; + } + + auto dataStorage = m_DataStorage.Lock(); + + // #TODO: check mitkTool::CreateSegmentationNode(...); + + std::cout << "Segmentation mask propagation for case " << caseID + << " segmentation node " << segmentationMask->GetName() + << " to target image " << targetImage->GetName() << std::endl; + + auto labelSetImage = LabelSetImage::New(); + mitk::Image::Pointer segmentation = dynamic_cast(segmentationMask->GetData()); + labelSetImage->Initialize(segmentation); + + auto newSegmentationNode = DataNode::New(); + newSegmentationNode->SetData(labelSetImage); + + dataStorage->Add(newSegmentationNode, targetImage); + + return; +} + +bool mitk::LesionPropagation::CheckControlPoint(const DataNode* lesionImage, const DataNode* targetImage) +{ + auto lesionImageControlPoint = m_SemanticRelations->GetControlPointOfData(lesionImage); + auto targetImageControlPoint = m_SemanticRelations->GetControlPointOfData(targetImage); + + if (lesionImageControlPoint.UID == targetImageControlPoint.UID) + { + return true; + } + + return false; +} + +bool mitk::LesionPropagation::CheckInformationType(const DataNode* lesionImage, const DataNode* targetImage) +{ + auto lesionImageInformationType = m_SemanticRelations->GetInformationTypeOfImage(lesionImage); + auto targetImageInformationType = m_SemanticRelations->GetInformationTypeOfImage(targetImage); + + if (lesionImageInformationType == targetImageInformationType) + { + return true; + } + + return false; +} + +mitk::DataNode* mitk::LesionPropagation::GetSegmentationFromRelatedImage(const SemanticTypes::Lesion& sourceLesion, const DataNode* lesionImage) +{ + // found an image of the source lesion that is registered to the target image + // could clone the mask and copy it to the target image + // need to find the correct segmentation amongst many segmentations of the source image + SemanticRelations::DataNodeVector allSpecificSegmentations; + try + { + allSpecificSegmentations = m_SemanticRelations->GetAllSpecificSegmentations(mitk::GetCaseIDFromDataNode(lesionImage), + m_SemanticRelations->GetControlPointOfData(lesionImage), + m_SemanticRelations->GetInformationTypeOfImage(lesionImage)); + } + catch (const SemanticRelationException&) + { + return nullptr; + } + + auto lambda = [this, &sourceLesion](const mitk::DataNode* specificSegmentation) + { + try + { + auto representedLesion = m_SemanticRelations->GetRepresentedLesion(specificSegmentation); + return sourceLesion.UID == representedLesion.UID; + } + catch (const SemanticRelationException&) + { + return false; + } + }; + + auto segmentation = std::find_if(allSpecificSegmentations.begin(), allSpecificSegmentations.end(), lambda); + + // return segmentation as image mask of source lesion + if (segmentation != allSpecificSegmentations.end()) + { + return *segmentation; + } + + return nullptr; +} + +bool mitk::LesionPropagation::CheckRegistration(const DataNode* lesionImage, const DataNode* targetImage) { - std::cout << "Lesion propagation works and can be called" << std::endl; + // #TODO + // for now we will always return true + // registration ontology is not fully implemented + return true; } 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 327874c39f..b2f4b7d0cf 100644 --- a/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.cpp +++ b/Plugins/org.mitk.gui.qt.semanticrelations/src/internal/QmitkLesionInfoWidget.cpp @@ -1,431 +1,440 @@ /*=================================================================== 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_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(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_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) { // only the UID is needed to identify a representing lesion QVariant data = m_StorageModel->data(current, Qt::UserRole); if (!data.canConvert()) { return; } 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 // hide "selected data nodes presence background highlighting" in the model if (!m_StorageModel->GetSelectedDataNodes().isEmpty()) { m_StorageModel->SetDataNodeSelection(QList()); } 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_DataStorage.IsExpired()) { return; } auto dataStorage = m_DataStorage.Lock(); QmitkSemanticRelationsNodeSelectionDialog* dialog = new QmitkSemanticRelationsNodeSelectionDialog(this, "Select segmentation to link to the selected lesion.", ""); dialog->setWindowTitle("Select segmentation node"); dialog->SetDataStorage(dataStorage); dialog->SetNodePredicate(mitk::NodePredicates::GetSegmentationPredicate()); dialog->SetSelectOnlyVisibleNodes(true); 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(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(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_SemanticRelationsIntegration->LinkSegmentationToLesion(selectedDataNode, selectedLesion); } catch (const mitk::SemanticRelationException& e) { - std::stringstream exceptionMessage; exceptionMessage << e; + + std::stringstream exceptionMessage; + exceptionMessage << e; 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.exec(); } } void QmitkLesionInfoWidget::OnSetLesionName(mitk::SemanticTypes::Lesion selectedLesion) { // 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; } selectedLesion.name = inputDialog->GetLineEditText().toStdString(); m_SemanticRelationsIntegration->OverwriteLesion(m_CaseID, selectedLesion); } void QmitkLesionInfoWidget::OnSetLesionClass(mitk::SemanticTypes::Lesion selectedLesion) { // 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 = 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_SemanticRelationsIntegration->OverwriteLesion(m_CaseID, selectedLesion); } void QmitkLesionInfoWidget::OnPropagateLesion(mitk::SemanticTypes::Lesion selectedLesion) { if (m_DataStorage.IsExpired()) { return; } auto dataStorage = m_DataStorage.Lock(); QmitkSemanticRelationsNodeSelectionDialog* dialog = new QmitkSemanticRelationsNodeSelectionDialog(this, "Select data node to propagate the selected lesion.", ""); dialog->setWindowTitle("Select image node"); dialog->SetDataStorage(dataStorage); dialog->SetNodePredicate(mitk::NodePredicates::GetImagePredicate()); dialog->SetSelectOnlyVisibleNodes(true); 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(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(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_SemanticRelationsDataStorageAccess->GetAllSegmentationsOfLesion(m_CaseID, selectedLesion); - mitk::LesionPropagation::FindClosestSegmentationMask(); + mitk::LesionPropagation lesionPropagation(dataStorage); + auto segmentationMask = lesionPropagation.FindClosestSegmentationMask(m_CaseID, selectedLesion, selectedDataNode); + if (nullptr != segmentationMask) + { + lesionPropagation.PropagateSegmentationMask(m_CaseID, segmentationMask, selectedDataNode); + } } catch (const mitk::SemanticRelationException& e) { - std::stringstream exceptionMessage; exceptionMessage << e; + std::stringstream exceptionMessage; + exceptionMessage << e; 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.exec(); } } void QmitkLesionInfoWidget::OnRemoveLesion(mitk::SemanticTypes::Lesion selectedLesion) { try { m_SemanticRelationsIntegration->RemoveLesion(m_CaseID, selectedLesion); } catch (const mitk::SemanticRelationException& e) { - std::stringstream exceptionMessage; exceptionMessage << e; + + std::stringstream exceptionMessage; + exceptionMessage << e; 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 15f3d95930..977fa7471f 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 -// mitk +// mitk core #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); 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::SemanticTypes::CaseID m_CaseID; mitk::WeakPointer m_DataStorage; std::unique_ptr m_SemanticRelationsDataStorageAccess; std::unique_ptr m_SemanticRelationsIntegration; }; #endif // QMITKLESIONINFOWIDGET_H