/*========================================================================= medInria Copyright (c) INRIA 2013 - 2019. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. =========================================================================*/ #include "baseViewEvent.h" // medInria #include #include // Qt // vtk #include #include #include #include #include #include #include #include #include baseViewEvent::baseViewEvent(medAbstractImageView *iView, polygonRoiToolBox *toolBox) : medViewEventFilter(), currentLabel(nullptr), enableInterpolation(true), pToolBox(toolBox), cursorState(CURSORSTATE::CS_DEFAULT), isRepulsorActivated(false) { currentView = iView; vtkImageView2D *view2d = static_cast(currentView->backend())->view2D; globalVtkLeftButtonBehaviour = view2d->GetLeftButtonInteractionStyle(); crossPosition = new medMouseCrossPosition(iView); currentLabel = nullptr; // interactors interactorStyleRepulsor = vtkInriaInteractorStylePolygonRepulsor::New(); originalInteractor = view2d->GetInteractor(); } baseViewEvent::~baseViewEvent() { activateRepulsor(false); delete crossPosition; removeViewInteractor(); manageTickVisibility(false); for (polygonLabel *label: labelList) { delete label; } labelList.clear(); currentLabel = nullptr; currentView = nullptr; } bool baseViewEvent::eventFilter(QObject *obj, QEvent *event) { if (!currentView) return false; auto keyEvent = dynamic_cast(event); auto mouseEvent = dynamic_cast(event); if (mouseEvent) { return medViewEventFilter::eventFilter(obj,event); } if (!keyEvent) { return false; } if (keyEvent->key() == Qt::Key::Key_Up || keyEvent->key() == Qt::Key::Key_Down) { return false; } if ( keyEvent->type() == QEvent::ShortcutOverride ) { switch (keyEvent->key()) { case Qt::Key::Key_C: copyContours(); break; case Qt::Key::Key_V: pasteContours(); break; case Qt::Key::Key_Backspace: deleteNode(savedMousePosition); break; case Qt::Key::Key_A: activateContour(savedMousePosition); break; case Qt::Key::Key_S: switchContourColor(savedMousePosition); break; case Qt::Key::Key_E: pToolBox->eraseCross(); break; case Qt::Key::Key_H: pToolBox->showHelp(); break; default: event->ignore(); break; } } return event->isAccepted(); } bool baseViewEvent::mouseReleaseEvent(medAbstractView *view, QMouseEvent *mouseEvent) { if (crossPosition->isEnabled() && mouseEvent->button() == Qt::LeftButton && mouseEvent->modifiers() == Qt::AltModifier ) { setCustomCursor(view, Qt::green); double wPos[4]; crossPosition->getWorldPosition(savedMousePosition, wPos); pToolBox->drawCross(wPos); vtkImageView2D *view2d = static_cast(currentView->backend())->view2D; view2d->SetLeftButtonInteractionStyle(globalVtkLeftButtonBehaviour); } else if (isRepulsorActivated ) { if ( !isActiveContourInSlice() || (currentLabel && currentLabel->roiOpenInSlice())) { return false; } if (interactorStyleRepulsor != nullptr) { if (interactorStyleRepulsor->GetManager() != nullptr ) { interactorStyleRepulsor->GetManager()->SetMasterRoi(); interactorStyleRepulsor->GetManager()->interpolateIfNeeded(); } manageTickVisibility(true); } } return false; } bool baseViewEvent::mouseMoveEvent(medAbstractView *view, QMouseEvent *mouseEvent) { #if QT_VERSION > QT_VERSION_CHECK(5, 10, 0) qreal devicePixelRatio = QGuiApplication::screenAt(mouseEvent->globalPos())->devicePixelRatio(); #else int screenNumber = QApplication::desktop()->screenNumber(mouseEvent->globalPos()); int devicePixelRatio = QGuiApplication::screens().at(screenNumber)->devicePixelRatio(); #endif savedMousePosition[0] = mouseEvent->x()*devicePixelRatio; savedMousePosition[1] = (view->viewWidget()->height()-mouseEvent->y()-1)*devicePixelRatio; double *crossPos = crossPosition->getPosition(); double distToCross = sqrt( pow(crossPos[0] - savedMousePosition[0], 2) + pow(crossPos[1] - savedMousePosition[1], 2)); if (crossPosition->isEnabled() && distToCross < 10.) { setCustomCursor(view, Qt::green); if (mouseEvent->modifiers() == Qt::AltModifier) { double wPos[4]; crossPosition->getWorldPosition(savedMousePosition, wPos); pToolBox->drawCross(wPos); } } else if (currentLabel) { if (currentLabel->getMinimumDistanceFromNodesToMouse(savedMousePosition, false) < 20.) { setCustomCursor(view, Qt::red); } else { view->viewWidget()->setCursor(Qt::ArrowCursor); } } else { view->viewWidget()->setCursor(Qt::ArrowCursor); } return false; } bool baseViewEvent::mousePressEvent(medAbstractView * view, QMouseEvent *mouseEvent) { if (mouseEvent->button()==Qt::LeftButton) { for (polygonLabel *label : labelList) { polygonRoi *roi = label->roiOpenInSlice(); if (roi != nullptr) { roi->getContour()->SetWidgetState(vtkContourWidget::Manipulate); } } if (mouseEvent->modifiers() == Qt::AltModifier) { double wPos[4]; crossPosition->getWorldPosition(savedMousePosition, wPos); pToolBox->drawCross(wPos); vtkImageView2D *view2d = static_cast(currentView->backend())->view2D; globalVtkLeftButtonBehaviour = view2d->GetLeftButtonInteractionStyle(); view2d->SetLeftButtonInteractionStyle(vtkInteractorStyleImageView2D::InteractionTypeNull); } else if (mouseEvent->modifiers() == Qt::ShiftModifier) { for (polygonLabel *label : labelList) { polygonRoi *roi = label->roiOpenInSlice(); if (roi != nullptr) { if (roi->getContour()->GetWidgetState()==vtkContourWidget::Manipulate) roi->getContour()->SetWidgetState(vtkContourWidget::Define); } } leftButtonBehaviour(view); } else if (mouseEvent->modifiers()==Qt::NoModifier) { if (!isRepulsorActivated ) { vtkImageView2D *view2d = static_cast(currentView->backend())->view2D; int currentLeftButtonBehaviour = view2d->GetLeftButtonInteractionStyle(); if (currentLeftButtonBehaviour != globalVtkLeftButtonBehaviour && currentLeftButtonBehaviour != vtkInteractorStyleImageView2D::InteractionTypeNull) { globalVtkLeftButtonBehaviour = currentLeftButtonBehaviour; } view2d->SetLeftButtonInteractionStyle(globalVtkLeftButtonBehaviour); } } } else if (mouseEvent->button()==Qt::RightButton) { return rightButtonBehaviour(view, mouseEvent); } return false; } void baseViewEvent::leftButtonBehaviour(medAbstractView *view) { if (isRepulsorActivated) { if (isActiveContourInSlice()) { cursorState = CURSORSTATE::CS_REPULSOR; activateRepulsor(true); } else { activateRepulsor(false); isRepulsorActivated = true; } } switch (cursorState) { case CURSORSTATE::CS_DEFAULT: { addPointInContourWithLabel(); break; } case CURSORSTATE::CS_REPULSOR: { if (!currentLabel) { pToolBox->displayMessageError(QString("Select a label in list to be able to use repulsor tool.")); return; } if (!interactorStyleRepulsor) { pToolBox->displayMessageError(QString("Repulsor tool is not activated")); return; } interactorStyleRepulsor->SetManager(currentLabel); break; } case CURSORSTATE::CS_NONE: break; } } void baseViewEvent::setCustomCursor(medAbstractView *view, QColor color) { if (!view) return; auto imageView = dynamic_cast(view); if (!imageView) return; double radiusSize = 1.; // Adapt to scale of view (zoom, crop, etc) double radiusSizeDouble = radiusSize * imageView->scale(); int radiusSizeInt = (int)floor(radiusSizeDouble + 0.5); // Create shape of the new cursor QPixmap pix(radiusSizeInt, radiusSizeInt); pix.fill(Qt::transparent); QPainter painter(&pix); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.setRenderHint( QPainter::Antialiasing ); painter.setBackgroundMode(Qt::TransparentMode); painter.setBackground(QColor(255,255,255,255)); painter.setPen( color ); painter.drawEllipse( 0, 0, radiusSizeInt, radiusSizeInt ); painter.setPen( color ); painter.drawPoint(floor(radiusSizeDouble/2.0+0.5), floor(radiusSizeDouble/2.0+0.5)); painter.drawPoint(floor(radiusSizeDouble/2.0-1.0+0.5), floor(radiusSizeDouble/2.0+0.5)); painter.drawPoint(floor(radiusSizeDouble/2.0+1.0+0.5), floor(radiusSizeDouble/2.0+0.5)); painter.drawPoint(floor(radiusSizeDouble/2.0+0.5), floor(radiusSizeDouble/2.0-1.0+0.5)); painter.drawPoint(floor(radiusSizeDouble/2.0+0.5), floor(radiusSizeDouble/2.0+1.0+0.5)); // Update the cursor view->viewWidget()->setCursor(QCursor(pix, -1, -1)); } QLineEdit * baseViewEvent::changeManagerNameBase(polygonLabel* closestManager, QMenu *mainMenu) { auto renameManager = new QLineEdit(closestManager->getName()); renameManager->setContextMenuPolicy(Qt::ContextMenuPolicy::NoContextMenu); QFont font = renameManager->font(); font.setWeight(QFont::Black); font.setPointSize(15); font.setUnderline(true); renameManager->setFont(font); renameManager->setAlignment(Qt::AlignCenter); QColor color = closestManager->getColor(); QString style = "QLineEdit { color: rgb(%1, %2, %3); }"; renameManager->setStyleSheet(style.arg(color.red()).arg(color.green()).arg(color.blue())); connect(renameManager, &QLineEdit::returnPressed, [=](){ mainMenu->close(); }); return renameManager; } polygonLabel *baseViewEvent::getClosestPLabel(double *mousePos) { polygonLabel *closestManager = nullptr; double minDist = DBL_MAX; double dist = 0.; for (polygonLabel *manager : labelList) { if (manager->isRoiInSlice() ) { dist = manager->getMinimumDistanceFromNodesToMouse(mousePos); if ( dist < minDist ) { minDist = dist; closestManager = manager; } } } return closestManager; } QMenu *baseViewEvent::changeLabelActions(polygonLabel* closestLabel) { auto changeMenu = new QMenu("Change Label"); for (polygonLabel *manager : labelList) { if (manager != closestLabel && !manager->isRoiInSlice()) { QPixmap pixmap(20,20); pixmap.fill(manager->getColor()); auto action = new QAction(pixmap, manager->getName(), changeMenu); connect(action, &QAction::triggered, [=](){ polygonRoi *roi = closestLabel->getRoiInSlice(); QVector nodes = roi->copyContour(); polygonRoi *roiToAdd = manager->appendRoi(); roiToAdd->pasteContour(nodes); setLabelActivationState(); deleteContour(closestLabel); // Re-render the ROI roiToAdd->Off(); roiToAdd->On(); }); changeMenu->addAction(action); } } return changeMenu; } void baseViewEvent::setLabelActivationState() { for (polygonLabel *manager : labelList) { manager->setRoisSelectedState(); } } bool baseViewEvent::rightButtonBehaviour(medAbstractView *view, QMouseEvent *mouseEvent) { if (!view) return false; QMenu mainMenu(view->viewWidget()); #if QT_VERSION > QT_VERSION_CHECK(5, 10, 0) qreal devicePixelRatio = QGuiApplication::screenAt(mouseEvent->globalPos())->devicePixelRatio(); #else int screenNumber = QApplication::desktop()->screenNumber(mouseEvent->globalPos()); int devicePixelRatio = QGuiApplication::screens().at(screenNumber)->devicePixelRatio(); #endif double mousePos[2]; mousePos[0] = mouseEvent->x()*devicePixelRatio; mousePos[1] = (view->viewWidget()->height()-mouseEvent->y()-1)*devicePixelRatio; polygonLabel * closestManager = getClosestPLabel(mousePos); auto roiManagementMenu = new QMenu("Remove"); auto saveMenu = new QMenu("Save as"); QMenu *changeMenu = nullptr; auto renameManagerAction = new QWidgetAction(&mainMenu); auto copyContourAction = new QAction("Copy", &mainMenu); QAction *activationAction = nullptr; if (closestManager && (closestManager->getMinimumDistanceFromNodesToMouse(mousePos) < 10.)) { auto deleteOneNodeAction = new QAction("Node", roiManagementMenu); connect(deleteOneNodeAction, &QAction::triggered, [this, &closestManager, &mousePos](){ deleteNode(closestManager, mousePos); }); roiManagementMenu->addAction(deleteOneNodeAction); auto deleteContourAction = new QAction("Contour", roiManagementMenu); connect(deleteContourAction, &QAction::triggered, [=](){ deleteContour(closestManager); }); roiManagementMenu->addAction(deleteContourAction); auto deleteLabelAction = new QAction("Label", roiManagementMenu); connect(deleteLabelAction, &QAction::triggered, [=](){ deleteLabel(closestManager); }); roiManagementMenu->addAction(deleteLabelAction); auto saveMaskAction = new QAction("Mask", saveMenu); connect(saveMaskAction, &QAction::triggered, [=](){ medDataManager::instance().importData(saveMask(closestManager), false); }); saveMenu->addAction(saveMaskAction); auto saveContourAction = new QAction("Contour", saveMenu); connect(saveContourAction, &QAction::triggered, [=](){ saveContour(closestManager); }); saveMenu->addAction(saveContourAction); connect(copyContourAction, &QAction::triggered, [=](){ copyContour(closestManager); }); if (closestManager != currentLabel) { activationAction = new QAction("Activate", &mainMenu); connect(activationAction, &QAction::triggered, [=](){ currentLabel = closestManager; activateContour(savedMousePosition); }); } changeMenu = changeLabelActions(closestManager); renameManagerAction->setDefaultWidget(changeManagerName(closestManager, &mainMenu)); mainMenu.addAction(renameManagerAction); if (!closestManager->getOptName().isEmpty()) { auto name = new QLabel(closestManager->getOptName()); QFont font = name->font(); font.setWeight(QFont::Black); font.setPointSize(15); font.setUnderline(true); name->setFont(font); name->setAlignment(Qt::AlignCenter); QString style = "QLabel { color: rgb(%1, %2, %3); }"; name->setStyleSheet(style.arg(closestManager->getOptColor().red()). arg(closestManager->getOptColor().green()). arg(closestManager->getOptColor().blue())); auto widAct = new QWidgetAction(&mainMenu); widAct->setDefaultWidget(name); mainMenu.addAction(widAct); } if ( activationAction ) { mainMenu.addAction(activationAction); } auto scoreMenu = createScoreMenu(closestManager); if (scoreMenu) { mainMenu.addMenu(scoreMenu); } mainMenu.addMenu(roiManagementMenu); mainMenu.addMenu(saveMenu); if ( !changeMenu->actions().isEmpty() ) { mainMenu.addMenu(changeMenu); } mainMenu.addAction(copyContourAction); mainMenu.exec(mouseEvent->globalPos()); } delete roiManagementMenu; delete saveMenu; delete renameManagerAction; delete changeMenu; delete copyContourAction; delete activationAction; mainMenu.clear(); return true; } void baseViewEvent::addPointInContourWithLabel() { if (currentLabel) { if (!currentLabel->isRoiInSlice() && currentLabel->isSameSliceOrientation()) { currentLabel->appendRoi(); } } } void baseViewEvent::setEnableInterpolation(bool state) { enableInterpolation = state; for (polygonLabel *manager : labelList) { manager->setEnableInterpolation(state); } setLabelActivationState(); manageTickVisibility(true); } void baseViewEvent::copyContour(polygonLabel *manager) { copyNodesList.clear(); QVector coords = manager->copyContour(); if (!coords.empty()) { int label = labelList.indexOf(manager); medDisplayPosContours contours = medDisplayPosContours(label, coords); copyNodesList.append(contours); } } void baseViewEvent::copyContours() { copyNodesList.clear(); for (polygonLabel *manager : labelList) { if (manager->isRoiInSlice()) { QVector coords = manager->copyContour(); if (!coords.empty()) { int label = labelList.indexOf(manager);; medDisplayPosContours contours = medDisplayPosContours(label, coords); copyNodesList.append(contours); } } } } void baseViewEvent::pasteContours() { for (medDisplayPosContours &contours : copyNodesList) { polygonLabel *fromLabel = labelList.at(contours.getLabel()); auto label = findManager(fromLabel->getPosition()); if ( label ) { if ( !label->isRoiInSlice() ) { label->pasteContour(contours.getNodes()); } else { pToolBox->displayMessageError("contour " + label->getName() + " already exists in current slice "); } } setLabelActivationState(); } } polygonLabel *baseViewEvent::findManager(int position) { polygonLabel *label = nullptr; for (polygonLabel *label1 : labelList) { if (label1->getPosition() == position) { label = label1; } } return label; } void baseViewEvent::updateContourProperty(QString &name, QColor &color, int position, bool isSelected, bool hasScore, bool checkState, QString scoreName) { if (!currentView) return; // 1/ unselect all labels. only one can be selected and it will be set just after for (auto label : labelList) { label->getState().selected = false; label->setRoisSelectedState(); } currentLabel = findManager(position); if (currentLabel) { currentLabel->updateContourProperty(name, color, isSelected, hasScore, checkState); if (hasScore && currentLabel->getState().secondColor!=QColor::Invalid) //this label can have a score { QColor newColor = (checkState)?currentLabel->getState().secondColor:currentLabel->getState().mainColor; currentLabel->changeContoursColor(newColor); } } else { currentLabel = new polygonLabel(currentView, this, color, name, position, isSelected, enableInterpolation); currentLabel->setScoreState(hasScore); if (hasScore && !scoreName.isEmpty()) { setScoreNameAndColor(currentLabel, scoreName); } labelList.append(currentLabel); } currentLabel->setRoisSelectedState(); interactorStyleRepulsor->SetManager(currentLabel); currentView->render(); } void baseViewEvent::activateRepulsor(bool state) { if (!currentView || !interactorStyleRepulsor) return; vtkImageView2D *view2d = static_cast(currentView->backend())->view2D; isRepulsorActivated = state; if (state) { cursorState = CURSORSTATE::CS_REPULSOR; vtkInteractorStyleImageView2D *interactorStyle2D = vtkInteractorStyleImageView2D::SafeDownCast(view2d->GetInteractor()->GetInteractorStyle()); interactorStyleRepulsor->SetManager(currentLabel); interactorStyleRepulsor->SetLeftButtonInteraction(interactorStyle2D->GetLeftButtonInteraction()); view2d->SetInteractorStyle(interactorStyleRepulsor); view2d->SetupInteractor(view2d->GetInteractor()); // to reinstall vtkImageView2D pipeline for (auto label: labelList) { if (label != currentLabel) { label->setRoisSelectedState(); if (label->isRoiInSlice()) { polygonRoi *roi = label->getRoiInSlice(); if (roi) { if (!roi->isClosed()) { roi->getContour()->SetWidgetState(vtkContourWidget::Define); } } } } } } else if (cursorState == CURSORSTATE::CS_REPULSOR) { cursorState = CURSORSTATE::CS_DEFAULT; vtkInteractorStyleImageView2D *interactorStyle2D = vtkInteractorStyleImageView2D::New(); globalVtkLeftButtonBehaviour = view2d->GetLeftButtonInteractionStyle(); interactorStyle2D->SetLeftButtonInteraction(vtkInteractorStyleImageView2D::InteractionTypeNull); view2d->SetInteractorStyle(interactorStyle2D); view2d->SetupInteractor(originalInteractor); interactorStyle2D->Delete(); } } QList> baseViewEvent::saveMasks() { QList> outputMasks; for (polygonLabel *label : labelList) { if (!label->getRois().empty()) { outputMasks.append(saveMask(label)); } } return outputMasks; } void baseViewEvent::saveAllContours() { if (!currentView) return; contourOutput = medAbstractDataFactory::instance()->createSmartPointer("medContours"); QVector contoursData; vtkSmartPointer append = vtkSmartPointer::New(); append->SetUserManagedInputs(true); append->SetNumberOfInputs(labelList.size()); int num = 0; for (polygonLabel *pLabel : labelList) { if (!pLabel->getRois().empty()) { int position = pLabel->getPosition(); auto ctr = pLabel->getContoursAsNodes(); medTagContours contoursTag; contoursTag.setSpecialityIndex(speciality()); contoursTag.setLabelName(pLabel->getName()); contoursTag.setTarget(pLabel->hasScore()); if (pLabel->hasScore() && pLabel->getOptName() != QString()) { contoursTag.setScore(pLabel->getOptName()); } contoursTag.setContourNodes(ctr); contoursData.append(contoursTag); auto pd = pLabel->getContoursAsPolyData(position); append->SetInputDataByNumber(num, pd); num++; } } if (!contoursData.empty()) { append->Update(); vtkMetaDataSet *outputDataSet = vtkMetaSurfaceMesh::New(); outputDataSet->SetDataSet(append->GetOutput()); QString description; if (contoursData.size() == 1) { description = QString("contour %1").arg(contoursData[0].getLabelName()); } else { description = QString("%1 contours").arg(contoursData.size()); } medAbstractData * data = currentView->layerData(0); description += " (" + data->metadata(medMetaDataKeys::SeriesDescription.key()) + ")"; medUtilities::setDerivedMetaData(contourOutput, data, description, false, false); contourOutput->setData(outputDataSet); contourOutput->setData(&contoursData, 1); outputDataSet->Delete(); medDataManager::instance().importData(contourOutput, false); } } void baseViewEvent::manageTickVisibility(bool show) { medIntParameterL *slicingParameter = getSlicingParameter(currentView); if ( slicingParameter ) { slicingParameter->getSlider()->removeAllTicks(); if (show) { for (polygonLabel *label : labelList) { label->manageTick(slicingParameter->getSlider()); } } } } medIntParameterL *baseViewEvent::getSlicingParameter(medAbstractImageView *iView) { medIntParameterL *slicingParameter = nullptr; for( auto interactor : qobject_cast(iView)->layerInteractors(0)) { if ((interactor->identifier() == "medVtkViewItkDataImageInteractor") || (interactor->identifier() == "medVtkViewItkDataImage4DInteractor")) { for (auto parameter : interactor->linkableParameters()) { if (parameter->name() == "Slicing") { slicingParameter = qobject_cast(parameter); } } } } return slicingParameter; } void baseViewEvent::deleteNode(double *mousePosition) { polygonLabel *closestManager = getClosestPLabel(mousePosition); if (closestManager && closestManager->getMinimumDistanceFromNodesToMouse(mousePosition, false) < 10. ) { deleteNode(closestManager, mousePosition); } } int baseViewEvent::activateContourBase(double *mousePosition) { // 1/ unselect all labels. only one can be selected and it will be set just after unselectLabels(); int position = -1; polygonLabel *pLabel = getClosestPLabel(mousePosition); if (pLabel && pLabel->getMinimumDistanceFromNodesToMouse(mousePosition, true) < 10. ) { currentLabel = pLabel; interactorStyleRepulsor->SetManager(currentLabel); pLabel->getState().selected = true; pLabel->setRoisSelectedState(); position = pLabel->getPosition(); } return position; } void baseViewEvent::unselectLabels() { for (auto label : labelList) { label->getState().selected = false; label->setRoisSelectedState(); } } void baseViewEvent::deleteNode(polygonLabel *manager, const double *mousePos) { manager->deleteNode(mousePos[0], mousePos[1]); if (manager->getRois().isEmpty()) { deleteLabel(manager); } else if (!manager->isRoiInSlice()) { deleteContour(manager); } else { manageTickVisibility(true); } } void baseViewEvent::deleteContour(polygonLabel *manager) { manager->deleteContour(); if ( manager->getRois().empty() ) { deleteLabel(manager); } else { manageTickVisibility(true); } } void baseViewEvent::deleteLabel(int position) { polygonLabel *label = findManager(position); if (label) { deleteLabel(label); } } void baseViewEvent::updatePosition(QString name, int position) { for (auto label: labelList) { if (label->getName()==name) label->getState().position = position; } } int baseViewEvent::deleteLabelBase(polygonLabel *manager) { int position = -1; labelList.removeOne(manager); manager->removeAllTick(); if (currentLabel == manager && !labelList.empty()) { unselectLabels(); currentLabel = labelList.at(0); currentLabel->getState().selected = true; currentLabel->setRoisSelectedState(); position = currentLabel->getPosition(); if (isRepulsorActivated) { interactorStyleRepulsor->SetManager(currentLabel); } } delete manager; if (labelList.empty()) { currentLabel = nullptr; position = -1; if (pToolBox->repulsorTool->isChecked()) { pToolBox->repulsorTool->click(); } } manageTickVisibility(true); return position; } bool baseViewEvent::isActiveContourInSlice() { bool retVal = false; if (currentLabel && currentLabel->isRoiInSlice() ) { retVal = true; } return retVal; } dtkSmartPointer baseViewEvent::saveMask(polygonLabel *manager) { int label = labelList.indexOf(manager); QString desc = createMaskDescription(manager); auto outputMask = manager->createMask(label, desc); outputMask->setMetaData("LabelName", manager->getName()); return outputMask; } QString baseViewEvent::createMaskDescription(polygonLabel *label) { QString name = QString(label->getName()); medAbstractData * data = currentView->layerData(0); QString desc = QString("mask ") + name + " (" + data->metadata(medMetaDataKeys::SeriesDescription.key()) + ")"; return desc; } void baseViewEvent::saveContour(polygonLabel *label) { contourOutput = medAbstractDataFactory::instance()->createSmartPointer("medContours"); QVector contoursData; vtkSmartPointer append = vtkSmartPointer::New(); append->SetUserManagedInputs(true); append->SetNumberOfInputs(labelList.size()); int position = label->getPosition(); QVector contour = label->getContoursAsNodes(); medTagContours contoursTag; contoursTag.setSpecialityIndex(speciality()); contoursTag.setLabelName(label->getName()); contoursTag.setTarget(label->hasScore()); if (label->hasScore() && label->getOptName() != QString()) { contoursTag.setScore(label->getOptName()); } contoursTag.setContourNodes(contour); contoursData.append(contoursTag); auto pd = label->getContoursAsPolyData(position); append->SetInputDataByNumber(0, pd); append->Update(); vtkMetaDataSet *outputDataSet = vtkMetaSurfaceMesh::New(); outputDataSet->SetDataSet(append->GetOutput()); QString description; if (contoursData.size() == 1) { description = QString("contour %1 ").arg(contoursData[0].getLabelName()); } else { description = QString("%1 contours ").arg(contoursData.size()); } medAbstractData * data = currentView->layerData(0); description += " (" + data->metadata(medMetaDataKeys::SeriesDescription.key()) + ")"; medUtilities::setDerivedMetaData(contourOutput, data, description, false, false); contourOutput->setData(outputDataSet); contourOutput->setData(&contoursData, 1); outputDataSet->Delete(); medDataManager::instance().importData(contourOutput, false); } void baseViewEvent::onContourFinished(CURSORSTATE state) { cursorState = state; for (polygonLabel *label : labelList) { label->interpolateIfNeeded(); currentView->render(); } manageTickVisibility(true); } medAbstractView *baseViewEvent::getCurrentView() { return currentView; } void baseViewEvent::showOnDifferentOrientation() { auto view = dynamic_cast(sender()); for (polygonLabel *label : labelList) { label->updateRoiOnOrientedView(view, true); } } void baseViewEvent::removeViewFromList(medAbstractImageView *iView) { for (polygonLabel *label : labelList) { label->updateRoiOnOrientedView(iView, false); } } void baseViewEvent::rename(int position, QString newName) { polygonLabel *label = findManager(position); if (label) { label->setName(newName); } } void baseViewEvent::onSelectContainer() { updateLabelToolBoxState(identifier); installOnView(currentView); for (auto label : labelList) { label->addViewObservers(); } } void baseViewEvent::removeViewInteractor() { removeFromAllViews(); for (auto label : labelList) { polygonRoi *roi = label->roiOpenInSlice(); if (roi != nullptr) { roi->getContour()->SetWidgetState(vtkContourWidget::Manipulate); } label->removeViewObservers(); } } bool baseViewEvent::isContourLoadable(QString &labelName) { if (labelList.size() == 9) { // TODO : send message to toolbox (signal or return ?) qDebug()<<"isContourLoadable - unable to create new label (max size)"; return false; } for (polygonLabel *label : labelList) { // label is already created (click on label in tb) and segmentation has be done in view (create roi in view) if (label->getName() == labelName && !(label->getRois().empty())) { // TODO : send message to toolbox (signal or return ?) qDebug()<getName()); return false; } } return true; } void baseViewEvent::drawCross(double *position) { crossPosition->draw(position); currentView->render(); } void baseViewEvent::eraseCross() { crossPosition->erase(); currentView->render(); }