diff --git a/Modules/QmitkExt/QmitkPointListView.cpp b/Modules/QmitkExt/QmitkPointListView.cpp index fb35fe6376..6085eb1b95 100644 --- a/Modules/QmitkExt/QmitkPointListView.cpp +++ b/Modules/QmitkExt/QmitkPointListView.cpp @@ -1,443 +1,470 @@ /*=================================================================== 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 "QmitkPointListView.h" #include "QmitkPointListModel.h" #include "QmitkStdMultiWidget.h" #include "QmitkEditPointDialog.h" #include "mitkRenderingManager.h" #include #include #include #include #include QmitkPointListView::QmitkPointListView( QWidget* parent ) - :QListView( parent ), - m_PointListModel( new QmitkPointListModel() ), - m_SelfCall( false ), - m_showFading(false), - m_MultiWidget( NULL), - m_Snc1(NULL), - m_Snc2(NULL), - m_Snc3(NULL) + : QListView( parent ), + m_Snc1(NULL), + m_Snc2(NULL), + m_Snc3(NULL), + m_PointListModel( new QmitkPointListModel() ), + m_SelfCall( false ), + m_showFading(false), + m_MultiWidget( NULL) { QListView::setAlternatingRowColors( true ); // logic QListView::setSelectionBehavior( QAbstractItemView::SelectRows ); QListView::setSelectionMode( QAbstractItemView::SingleSelection ); QListView::setModel( m_PointListModel ); QString tooltip = QString("Use the F2/F3 keys to move a point up/down, the Del key to remove a point\nand the mouse wheel to change the timestep.\n\nTimeStep:\t%1").arg(0); QListView::setToolTip(tooltip); //m_FadeTimer = new QTimer(); this->setContextMenuPolicy(Qt::CustomContextMenu); m_TimeStepFaderLabel = new QLabel(this); QFont font("Arial", 17); m_TimeStepFaderLabel->setFont(font); //Define Size this->setMinimumHeight(40); //horizontal, vertical this->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); //connect connect( m_PointListModel, SIGNAL(SignalUpdateSelection()), this, SLOT(OnPointSetSelectionChanged()) ); connect( this, SIGNAL(doubleClicked ( const QModelIndex & )), this, SLOT(OnPointDoubleClicked( const QModelIndex & )) ); connect( QListView::selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(OnListViewSelectionChanged(const QItemSelection& , const QItemSelection&)) ); connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(ctxMenu(const QPoint &))); } QmitkPointListView::~QmitkPointListView() { delete m_PointListModel; } void QmitkPointListView::SetPointSetNode( mitk::DataNode* pointSetNode ) { m_PointListModel->SetPointSetNode( pointSetNode); } const mitk::PointSet* QmitkPointListView::GetPointSet() const { return m_PointListModel->GetPointSet(); } void QmitkPointListView::SetMultiWidget( QmitkStdMultiWidget* multiWidget ) { m_MultiWidget = multiWidget; } QmitkStdMultiWidget* QmitkPointListView::GetMultiWidget() const { return m_MultiWidget; } void QmitkPointListView::OnPointDoubleClicked(const QModelIndex & index) { mitk::PointSet::PointType p; mitk::PointSet::PointIdentifier id; m_PointListModel->GetPointForModelIndex(index, p, id); QmitkEditPointDialog _EditPointDialog(this); _EditPointDialog.SetPoint(m_PointListModel->GetPointSet(), id, m_PointListModel->GetTimeStep()); _EditPointDialog.exec(); } void QmitkPointListView::OnPointSetSelectionChanged() { const mitk::PointSet* pointSet = m_PointListModel->GetPointSet(); if (pointSet == NULL) return; // update this view's selection status as a result to changes in the point set data structure m_SelfCall = true; int timeStep = m_PointListModel->GetTimeStep(); if ( pointSet->GetNumberOfSelected( timeStep ) > 1 ) { MITK_ERROR << "Point set has multiple selected points. This view is not designed for more than one selected point."; } int selectedIndex = pointSet->SearchSelectedPoint( timeStep ); if (selectedIndex == -1) // no selected point is found { m_SelfCall = false; return; } QModelIndex index; bool modelIndexOkay = m_PointListModel->GetModelIndexForPointID(selectedIndex, index); if (modelIndexOkay == true) QListView::selectionModel()->select( index , QItemSelectionModel::ClearAndSelect ); emit SignalPointSelectionChanged(); m_SelfCall = false; } void QmitkPointListView::OnListViewSelectionChanged(const QItemSelection& selected, const QItemSelection& /*deselected*/) { if (m_SelfCall) return; mitk::PointSet* pointSet = const_cast( m_PointListModel->GetPointSet() ); if (pointSet == NULL) return; // (take care that this widget doesn't react to self-induced changes by setting m_SelfCall) m_SelfCall = true; // update selection of all points in pointset: select the one(s) that are selected in the view, deselect all others QModelIndexList selectedIndexes = selected.indexes(); for (mitk::PointSet::PointsContainer::Iterator it = pointSet->GetPointSet(m_PointListModel->GetTimeStep())->GetPoints()->Begin(); it != pointSet->GetPointSet(m_PointListModel->GetTimeStep())->GetPoints()->End(); ++it) { QModelIndex index; if (m_PointListModel->GetModelIndexForPointID(it->Index(), index)) { if (selectedIndexes.indexOf(index) != -1) // index is found in the selected indices list { pointSet->SetSelectInfo(it->Index(), true, m_PointListModel->GetTimeStep()); // Use Multiwidget or SliceNavigationControllers to set crosshair to selected point if ( m_MultiWidget != NULL) { m_MultiWidget->MoveCrossToPosition(pointSet->GetPoint(it->Index(), m_PointListModel->GetTimeStep())); } - else if ( (m_Snc1 != NULL) && (m_Snc2 != NULL) && (m_Snc3 != NULL) ) + + mitk::Point3D p = pointSet->GetPoint(it->Index(), m_PointListModel->GetTimeStep()); + + // remove the three ifs below after the SetSnc* methods have been removed + if (m_Snc1 != NULL) { - mitk::Point3D p = pointSet->GetPoint(it->Index(), m_PointListModel->GetTimeStep()); m_Snc1->SelectSliceByPoint(p); + } + if (m_Snc2 != NULL) + { m_Snc2->SelectSliceByPoint(p); + } + if (m_Snc3 != NULL) + { m_Snc3->SelectSliceByPoint(p); } + + for (std::set::const_iterator i = m_Sncs.begin(); + i != m_Sncs.end(); ++i) + { + (*i)->SelectSliceByPoint(p); + } } else { pointSet->SetSelectInfo(it->Index(), false, m_PointListModel->GetTimeStep()); } } } m_SelfCall = false; emit SignalPointSelectionChanged(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPointListView::keyPressEvent( QKeyEvent * e ) { if (m_PointListModel == NULL) return; int key = e->key(); switch (key) { case Qt::Key_F2: m_PointListModel->MoveSelectedPointUp(); break; case Qt::Key_F3: m_PointListModel->MoveSelectedPointDown(); break; case Qt::Key_Delete: m_PointListModel->RemoveSelectedPoint(); break; default: break; } } void QmitkPointListView::wheelEvent(QWheelEvent *event) { if (!m_PointListModel || !m_PointListModel->GetPointSet() || (int)(m_PointListModel->GetPointSet()->GetTimeSteps()) == 1 /*|| !m_4DPointSet*/) return; int whe = event->delta(); mitk::PointSet::Pointer ps = dynamic_cast(m_PointListModel->GetPointSet()); unsigned int numberOfTS = ps->GetTimeSteps(); if(numberOfTS == 1) return; int currentTS = this->m_PointListModel->GetTimeStep(); if(whe > 0) { if((currentTS >= (int)(m_PointListModel->GetPointSet()->GetTimeSteps()))) return; this->m_PointListModel->SetTimeStep(++currentTS); } else { if((currentTS <= 0)) return; this->m_PointListModel->SetTimeStep(--currentTS); } QString tooltip = QString("Use the F2/F3 keys to move a point up/down, the Del key to remove a point\nand the mouse wheel to change the timestep.\n\nTimeStep:\t%1").arg(currentTS); this->setToolTip(tooltip); fadeTimeStepIn(); } void QmitkPointListView::fadeTimeStepIn() { //Setup Widget QWidget *m_TimeStepFader = new QWidget(this); QHBoxLayout *layout = new QHBoxLayout(m_TimeStepFader); int x = (int)(this->geometry().x()+this->width()*0.6); int y = (int)(this->geometry().y()+this->height()*0.8); m_TimeStepFader->move(x,y); m_TimeStepFader->resize(60, 55); m_TimeStepFader->setLayout(layout); m_TimeStepFader->setAttribute(Qt::WA_DeleteOnClose); //setup Label // QLabel *label = new QLabel(QString("%1").arg(this->m_PointListModel->GetTimeStep())); layout->addWidget(m_TimeStepFaderLabel); m_TimeStepFaderLabel->setAlignment(Qt::AlignCenter); m_TimeStepFaderLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Raised); m_TimeStepFaderLabel->setLineWidth(2); m_TimeStepFaderLabel->setText(QString("%1").arg(this->m_PointListModel->GetTimeStep())); //give the widget opacity and some colour QPalette pal = m_TimeStepFaderLabel->palette(); QColor semiTransparentColor(139, 192, 223, 50); QColor labelTransparentColor(0,0,0,200); pal.setColor(m_TimeStepFaderLabel->backgroundRole(), semiTransparentColor); pal.setColor(m_TimeStepFaderLabel->foregroundRole(), labelTransparentColor); m_TimeStepFaderLabel->setAutoFillBackground(true); m_TimeStepFaderLabel->setPalette(pal); //show the widget m_TimeStepFader->show(); //and start the timer m_TimeStepFaderLabel->setVisible(true); QTimer::singleShot(2000, this, SLOT(fadeTimeStepOut())); } void QmitkPointListView::fadeTimeStepOut() { m_TimeStepFaderLabel->hide(); } void QmitkPointListView::ctxMenu(const QPoint &pos) { QMenu *menu = new QMenu; // menu->setStyle(); // menu->addAction(tr("Test Item"), this, SLOT(test_slot())); //add Fading check QAction *showFading = new QAction(this); showFading->setCheckable(false); //TODO: reset when fading is working showFading->setEnabled(false); //TODO: reset when fading is working showFading->setText("Fade TimeStep"); connect(showFading, SIGNAL(triggered(bool)), this, SLOT(SetFading(bool))); menu->addAction(showFading); //add Clear action QAction *clearList = new QAction(this); clearList->setText("Clear List"); connect(clearList, SIGNAL(triggered()), this, SLOT(ClearPointList())); menu->addAction(clearList); //add Clear TimeStep action QAction *clearTS = new QAction(this); clearTS->setText("Clear current time step"); connect(clearTS, SIGNAL(triggered()), this, SLOT(ClearPointListTS())); menu->addAction(clearTS); // //add "show time step in list" option // QAction *viewTS = new QAction(this); // viewTS->setText("Show time step in list"); // viewTS->setCheckable(true); // viewTS->setChecked(false); // connect(viewTS, SIGNAL(triggered(bool)), this, SLOT(ClearPointList(bool))); // menu->addAction(viewTS); menu->exec(this->mapToGlobal(pos)); } void QmitkPointListView::SetFading(bool onOff) { m_showFading = onOff; } void QmitkPointListView::ClearPointList() { if(!m_PointListModel->GetPointSet()) return; mitk::PointSet::Pointer curPS = m_PointListModel->GetPointSet(); if ( curPS->GetSize() == 0) return; switch( QMessageBox::question( this, tr("Clear Points"), tr("Remove all points from the displayed list?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No)) { case QMessageBox::Yes: { // m_PointListModel->ClearList(); // /* // if (curPS) // { // curPS->Clear(); // } // */ // mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // break; mitk::PointSet::PointsIterator it; mitk::PointSet::PointsContainer *curPsPoints; while( !curPS->IsEmptyTimeStep(0)) { curPsPoints = curPS->GetPointSet()->GetPoints(); it = curPsPoints->Begin(); curPS->SetSelectInfo(it->Index(),true); m_PointListModel->RemoveSelectedPoint(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case QMessageBox::No: default: break; } // emit PointListChanged(); } void QmitkPointListView::ClearPointListTS() { // mitk::PointSet* /*::Pointer*/ curPS = m_PointListModel->GetPointSet(); // if ( curPS->GetSize() == 0) // return; // int ts = this->m_PointListModel->GetTimeStep(); // switch( QMessageBox::question( this, tr("Clear Points in Timestep"), // tr("Remove all points from the list with the timestep %1?").arg(ts), // QMessageBox::Yes | QMessageBox::No, QMessageBox::No)) // { // case QMessageBox::Yes: // if (curPS) // { // mitk::PointSet::DataType::Pointer curPSwithTS = curPS->GetPointSet(ts); // //curPSwithTS->Clear(); // } // mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // break; // case QMessageBox::No: // default: // break; // } // // emit PointListChanged(); } void QmitkPointListView::SetSnc1(mitk::SliceNavigationController* snc) { m_Snc1 = snc; } void QmitkPointListView::SetSnc2(mitk::SliceNavigationController* snc) { m_Snc2 = snc; } void QmitkPointListView::SetSnc3(mitk::SliceNavigationController* snc) { m_Snc3 = snc; -} \ No newline at end of file +} + +void QmitkPointListView::AddSliceNavigationController(mitk::SliceNavigationController* snc) +{ + if (snc == NULL) return; + m_Sncs.insert(snc); +} + +void QmitkPointListView::RemoveSliceNavigationController(mitk::SliceNavigationController* snc) +{ + if (snc == NULL) return; + m_Sncs.erase(snc); +} diff --git a/Modules/QmitkExt/QmitkPointListView.h b/Modules/QmitkExt/QmitkPointListView.h index 6c142c380f..68f5c4a2e3 100644 --- a/Modules/QmitkExt/QmitkPointListView.h +++ b/Modules/QmitkExt/QmitkPointListView.h @@ -1,131 +1,153 @@ /*=================================================================== 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 QMITK_POINTLIST_VIEW_H_INCLUDED #define QMITK_POINTLIST_VIEW_H_INCLUDED #include #include #include "QmitkExtExports.h" #include #include "QmitkPointListModel.h" class QmitkStdMultiWidget; /*! * \brief GUI widget for handling mitk::PointSet * * Displays all the points in a mitk::PointSet graphically. * Reacts automatically to changes in the PointSet's selection status. * Updates PointSet's selection status when this list's selection changes. * * If a QmitkStdMultiWidget is assigned via SetMultiWidget(), the * crosshair of the QmitkStdMultiWidget is moved to the currently selected * point. * */ class QmitkExt_EXPORT QmitkPointListView : public QListView { Q_OBJECT public: QmitkPointListView( QWidget* parent = 0 ); ~QmitkPointListView(); /// assign a point set for observation void SetPointSetNode( mitk::DataNode* pointSetNode ); /// which point set to work on const mitk::PointSet* GetPointSet() const; /** * \brief If Multiwidget is set, the crosshair is automatically centering to the selected point * As an alternative, if you dont have a multiwidget, you can call SetSnc1, SetSnc2, SetSnc3 to set the * SliceNavigationControllers directly to enable the focussing feature. */ void SetMultiWidget( QmitkStdMultiWidget* multiWidget ); QmitkStdMultiWidget* GetMultiWidget() const; ///< return the QmitkStdMultiWidget that is used for updating render window crosshair void SetTimesStep(int i); ///< which time step to display/model ///@{ /** * \brief Sets the SliceNavigationController of the three 2D Renderwindows. * If they are defined, they can be used to automatically set the crosshair to the selected point + * + * \deprecatedSince{2013_03} Use AddSliceNavigationController and RemoveSliceNavigationController instead. */ - void SetSnc1(mitk::SliceNavigationController* snc); - void SetSnc2(mitk::SliceNavigationController* snc); - void SetSnc3(mitk::SliceNavigationController* snc); + DEPRECATED( void SetSnc1(mitk::SliceNavigationController* snc) ); + DEPRECATED( void SetSnc2(mitk::SliceNavigationController* snc) ); + DEPRECATED( void SetSnc3(mitk::SliceNavigationController* snc) ); ///@} + /** + * @brief Add a mitk::SliceNavigationController instance. + * @param snc The mitk::SliceNavigationController instance. + * + * This method adds \c snc to the set of slice navigation controllers which are + * used to navigate to the selected point. + */ + void AddSliceNavigationController(mitk::SliceNavigationController* snc); + + /** + * @brief Remove a mitk::SliceNavigationController instance. + * @param snc The mitk::SliceNavigationController instance. + * + * This method removes \c snc from the set of slice navigation controllers which are + * used to navigate to the selected point. + */ + void RemoveSliceNavigationController(mitk::SliceNavigationController* snc); + signals: void SignalPointSelectionChanged(); ///< this signal is emmitted, if the selection of a point in the pointset is changed protected slots: /// Filtering double click event for editing point coordinates via a dialog void OnPointDoubleClicked(const QModelIndex & index); /// called when the point set data structure changes void OnPointSetSelectionChanged(); /// called when the selection of the view widget changes void OnListViewSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); /// fade the shown timestep out void fadeTimeStepOut(); /// open ContextMenu void ctxMenu(const QPoint &pos); /// Turn TimeStep Fading On/Off void SetFading(bool onOff); /// Delete all points in the list void ClearPointList(); /// delete all points in the list in the current timestep void ClearPointListTS(); protected: void keyPressEvent( QKeyEvent * e ); ///< react to F2, F3 and DEL keys void wheelEvent( QWheelEvent* event); ///< change timestep of the current pointset by mouse wheel void fadeTimeStepIn(); ///< fade a label with the currently shown timestep in mitk::SliceNavigationController* m_Snc1; mitk::SliceNavigationController* m_Snc2; mitk::SliceNavigationController* m_Snc3; + std::set m_Sncs; + QmitkPointListModel* m_PointListModel; bool m_SelfCall; bool m_showFading; /// used to position the planes on a selected point QmitkStdMultiWidget* m_MultiWidget; QLabel* m_TimeStepFaderLabel; }; #endif diff --git a/Modules/QmitkExt/QmitkPointListWidget.cpp b/Modules/QmitkExt/QmitkPointListWidget.cpp index 8b07f95800..ff6e60b88e 100644 --- a/Modules/QmitkExt/QmitkPointListWidget.cpp +++ b/Modules/QmitkExt/QmitkPointListWidget.cpp @@ -1,471 +1,506 @@ /*=================================================================== 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 "QmitkPointListWidget.h" #include #include #include #include #include #include #include #include #include "btnLoad.xpm" #include "btnSave.xpm" #include "btnClear.xpm" #include "btnSetPoints.xpm" #include "btnSetPointsManually.xpm" #include "btnUp.xpm" #include "btnDown.xpm" QmitkPointListWidget::QmitkPointListWidget(QWidget *parent, int orientation): QWidget(parent), m_PointListView(NULL), m_MultiWidget(NULL), m_PointSetNode(NULL), m_Orientation(0), m_MovePointUpBtn(NULL), m_MovePointDownBtn(NULL), m_RemovePointBtn(NULL), m_SavePointsBtn(NULL), m_LoadPointsBtn(NULL), m_ToggleAddPoint(NULL), - m_AddPoint(NULL), m_Interactor(NULL), m_TimeStep(0), m_EditAllowed(true), m_NodeObserverTag(0), + m_AddPoint(NULL), m_Snc1(NULL), m_Snc2(NULL), - m_Snc3(NULL) + m_Snc3(NULL), + m_Interactor(NULL), + m_TimeStep(0), + m_EditAllowed(true), + m_NodeObserverTag(0) { m_PointListView = new QmitkPointListView(); if(orientation != 0) m_Orientation = orientation; SetupUi(); SetupConnections(); ObserveNewNode(NULL); } QmitkPointListWidget::~QmitkPointListWidget() { if (m_Interactor) mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; if(m_PointSetNode && m_NodeObserverTag) { m_PointSetNode->RemoveObserver(m_NodeObserverTag); m_NodeObserverTag = 0; } m_MultiWidget = NULL; delete m_PointListView; } void QmitkPointListWidget::SetupConnections() { //m_PointListView->setModel(m_PointListModel); connect(this->m_LoadPointsBtn, SIGNAL(clicked()), this, SLOT(OnBtnLoadPoints())); connect(this->m_SavePointsBtn, SIGNAL(clicked()), this, SLOT(OnBtnSavePoints())); connect(this->m_MovePointUpBtn, SIGNAL(clicked()), this, SLOT(MoveSelectedPointUp())); connect(this->m_MovePointDownBtn, SIGNAL(clicked()), this, SLOT(MoveSelectedPointDown())); connect(this->m_RemovePointBtn, SIGNAL(clicked()), this, SLOT(RemoveSelectedPoint())); connect(this->m_ToggleAddPoint, SIGNAL(toggled(bool)), this, SLOT(OnBtnAddPoint(bool))); connect(this->m_AddPoint, SIGNAL(clicked()), this, SLOT(OnBtnAddPointManually())); connect(this->m_PointListView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnListDoubleClick())); connect(this->m_PointListView, SIGNAL(SignalPointSelectionChanged()), this, SLOT(OnPointSelectionChanged())); } void QmitkPointListWidget::SetupUi() { //Setup the buttons m_ToggleAddPoint = new QPushButton();//iconSetPoints, "", this); m_ToggleAddPoint->setMaximumSize(25,25); m_ToggleAddPoint->setCheckable(true); m_ToggleAddPoint->setToolTip("Toggle point editing (use SHIFT + Left Mouse Button to add Points)"); QIcon iconAdd(btnSetPoints_xpm); m_ToggleAddPoint->setIcon(iconAdd); m_AddPoint = new QPushButton();//iconSetPoints, "", this); m_AddPoint->setMaximumSize(25,25); m_AddPoint->setToolTip("Manually add point"); QIcon iconAddManually(btnSetPointsManually_xpm); m_AddPoint->setIcon(iconAddManually); m_RemovePointBtn = new QPushButton(); m_RemovePointBtn->setMaximumSize(25, 25); const QIcon iconDel(btnClear_xpm); m_RemovePointBtn->setIcon(iconDel); m_RemovePointBtn->setToolTip("Erase one point from list (Hotkey: DEL)"); m_MovePointUpBtn = new QPushButton(); m_MovePointUpBtn->setMaximumSize(25, 25); const QIcon iconUp(btnUp_xpm); m_MovePointUpBtn->setIcon(iconUp); m_MovePointUpBtn->setToolTip("Swap selected point upwards (Hotkey: F2)"); m_MovePointDownBtn = new QPushButton(); m_MovePointDownBtn->setMaximumSize(25, 25); const QIcon iconDown(btnDown_xpm); m_MovePointDownBtn->setIcon(iconDown); m_MovePointDownBtn->setToolTip("Swap selected point downwards (Hotkey: F3)"); m_SavePointsBtn = new QPushButton(); m_SavePointsBtn->setMaximumSize(25, 25); QIcon iconSave(btnSave_xpm); m_SavePointsBtn->setIcon(iconSave); m_SavePointsBtn->setToolTip("Save points to file"); m_LoadPointsBtn = new QPushButton(); m_LoadPointsBtn->setMaximumSize(25, 25); QIcon iconLoad(btnLoad_xpm); m_LoadPointsBtn->setIcon(iconLoad); m_LoadPointsBtn->setToolTip("Load list of points from file (REPLACES current content)"); int i; QBoxLayout* lay1; QBoxLayout* lay2; switch (m_Orientation) { case 0: lay1 = new QVBoxLayout(this); lay2 = new QHBoxLayout(); i = 0; break; case 1: lay1 = new QHBoxLayout(this); lay2 = new QVBoxLayout(); i=-1; break; case 2: lay1 = new QHBoxLayout(this); lay2 = new QVBoxLayout(); i=0; break; default: lay1 = new QVBoxLayout(this); lay2 = new QHBoxLayout(); i=-1; break; } //setup Layouts this->setLayout(lay1); lay1->addLayout(lay2); lay2->stretch(true); lay2->addWidget(m_ToggleAddPoint); lay2->addWidget(m_AddPoint); lay2->addWidget(m_RemovePointBtn); lay2->addWidget(m_MovePointUpBtn); lay2->addWidget(m_MovePointDownBtn); lay2->addWidget(m_SavePointsBtn); lay2->addWidget(m_LoadPointsBtn); //lay2->addSpacing();; lay1->insertWidget(i,m_PointListView); this->setLayout(lay1); } void QmitkPointListWidget::SetPointSet(mitk::PointSet* newPs) { if(newPs == NULL) return; this->m_PointSetNode->SetData(newPs); dynamic_cast(this->m_PointListView->model())->SetPointSetNode(m_PointSetNode); ObserveNewNode(m_PointSetNode); } void QmitkPointListWidget::SetPointSetNode(mitk::DataNode *newNode) { ObserveNewNode(newNode); dynamic_cast(this->m_PointListView->model())->SetPointSetNode(newNode); } void QmitkPointListWidget::OnBtnSavePoints() { if ((dynamic_cast(m_PointSetNode->GetData())) == NULL) return; // don't write empty point sets. If application logic requires something else then do something else. if ((dynamic_cast(m_PointSetNode->GetData()))->GetSize() == 0) return; // let the user choose a file std::string name(""); QString fileNameProposal = QString("/PointSet.mps");//.arg(m_PointSetNode->GetName().c_str()); //"PointSet.mps"; QString aFilename = QFileDialog::getSaveFileName( NULL, "Save point set", QDir::currentPath() + fileNameProposal, "MITK Pointset (*.mps)" ); if ( aFilename.isEmpty() ) return; try { // instantiate the writer and add the point-sets to write mitk::PointSetWriter::Pointer writer = mitk::PointSetWriter::New(); writer->SetInput( dynamic_cast(m_PointSetNode->GetData()) ); writer->SetFileName( aFilename.toLatin1() ); writer->Update(); } catch(...) { QMessageBox::warning( this, "Save point set", QString("File writer reported problems writing %1\n\n" "PLEASE CHECK output file!").arg(aFilename) ); } } void QmitkPointListWidget::OnBtnLoadPoints() { // get the name of the file to load QString filename = QFileDialog::getOpenFileName( NULL, "Open MITK Pointset", "", "MITK Point Sets (*.mps)"); if ( filename.isEmpty() ) return; // attempt to load file try { mitk::PointSetReader::Pointer reader = mitk::PointSetReader::New(); reader->SetFileName( filename.toLatin1() ); reader->Update(); mitk::PointSet::Pointer pointSet = reader->GetOutput(); if ( pointSet.IsNull() ) { QMessageBox::warning( this, "Load point set", QString("File reader could not read %1").arg(filename) ); return; } // loading successful // bool interactionOn( m_Interactor.IsNotNull() ); // if (interactionOn) // { // OnEditPointSetButtonToggled(false); // } // this->SetPointSet(pointSet); // if (interactionOn) // { // OnEditPointSetButtonToggled(true); // } } catch(...) { QMessageBox::warning( this, "Load point set", QString("File reader collapsed while reading %1").arg(filename) ); } emit PointListChanged(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } mitk::PointSet* QmitkPointListWidget::GetPointSet() { return dynamic_cast(m_PointSetNode->GetData()); } mitk::DataNode* QmitkPointListWidget::GetPointSetNode() { return m_PointSetNode; } void QmitkPointListWidget::SetMultiWidget(QmitkStdMultiWidget *multiWidget) { this->m_MultiWidget = multiWidget; m_PointListView->SetMultiWidget(multiWidget); } void QmitkPointListWidget::RemoveSelectedPoint() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; QmitkPointListModel* pointListModel = dynamic_cast( m_PointListView->model() ); pointListModel->RemoveSelectedPoint(); emit PointListChanged(); } void QmitkPointListWidget::MoveSelectedPointDown() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; QmitkPointListModel* pointListModel = dynamic_cast( m_PointListView->model() ); pointListModel->MoveSelectedPointDown(); emit PointListChanged(); } void QmitkPointListWidget::MoveSelectedPointUp() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; QmitkPointListModel* pointListModel = dynamic_cast( m_PointListView->model() ); pointListModel->MoveSelectedPointUp(); emit PointListChanged(); } void QmitkPointListWidget::OnBtnAddPoint(bool checked) { if (m_PointSetNode) { if (checked) { m_Interactor = dynamic_cast(m_PointSetNode->GetInteractor()); if (m_Interactor.IsNull())//if not present, instanciate one m_Interactor = mitk::PointSetInteractor::New("pointsetinteractor", m_PointSetNode); //add it to global interaction to activate it mitk::GlobalInteraction::GetInstance()->AddInteractor( m_Interactor ); } else if ( m_Interactor ) { mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; } emit EditPointSets(checked); } } void QmitkPointListWidget::OnBtnAddPointManually() { mitk::PointSet* pointSet = this->GetPointSet(); int currentPosition = pointSet->GetSize(); QmitkEditPointDialog editPointDialog(this); editPointDialog.SetPoint(pointSet, currentPosition, m_TimeStep); editPointDialog.exec(); } void QmitkPointListWidget::OnListDoubleClick() { ; } void QmitkPointListWidget::OnPointSelectionChanged() { emit this->PointSelectionChanged(); } void QmitkPointListWidget::DeactivateInteractor(bool /*deactivate*/) { ; } void QmitkPointListWidget::EnableEditButton( bool enabled ) { m_EditAllowed = enabled; if (enabled == false) m_ToggleAddPoint->setEnabled(false); else m_ToggleAddPoint->setEnabled(true); OnBtnAddPoint(enabled); } void QmitkPointListWidget::ObserveNewNode( mitk::DataNode* node ) { // remove old observer if ( m_PointSetNode ) { if (m_Interactor) { mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; m_ToggleAddPoint->setChecked( false ); } m_PointSetNode->RemoveObserver( m_NodeObserverTag ); m_NodeObserverTag = 0; } m_PointSetNode = node; // add new observer if necessary if ( m_PointSetNode ) { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkPointListWidget::OnNodeDeleted ); m_NodeObserverTag = m_PointSetNode->AddObserver( itk::DeleteEvent(), command ); } else { m_NodeObserverTag = 0; } if (m_EditAllowed == true) m_ToggleAddPoint->setEnabled( m_PointSetNode ); else m_ToggleAddPoint->setEnabled( false ); m_RemovePointBtn->setEnabled( m_PointSetNode ); m_LoadPointsBtn->setEnabled( m_PointSetNode ); m_SavePointsBtn->setEnabled(m_PointSetNode); m_AddPoint->setEnabled(m_PointSetNode); } void QmitkPointListWidget::OnNodeDeleted( const itk::EventObject & /*e*/ ) { if(m_PointSetNode.IsNotNull() && ! m_NodeObserverTag) m_PointSetNode->RemoveObserver( m_NodeObserverTag ); m_NodeObserverTag = 0; m_PointSetNode = NULL; m_PointListView->SetPointSetNode(NULL); m_ToggleAddPoint->setEnabled(false); m_RemovePointBtn->setEnabled( false ); m_LoadPointsBtn->setEnabled( false ); m_SavePointsBtn->setEnabled(false); m_AddPoint->setEnabled(false); } void QmitkPointListWidget::SetSnc1(mitk::SliceNavigationController* snc) { - m_Snc1 = snc; - m_PointListView->SetSnc1(snc); + if (snc == NULL) + { + m_PointListView->RemoveSliceNavigationController(m_Snc1); + } + else + { + m_PointListView->AddSliceNavigationController(snc); + } + m_Snc1 = snc; } void QmitkPointListWidget::SetSnc2(mitk::SliceNavigationController* snc) { - m_Snc2 = snc; - m_PointListView->SetSnc2(snc); + if (snc == NULL) + { + m_PointListView->RemoveSliceNavigationController(m_Snc2); + } + else + { + m_PointListView->AddSliceNavigationController(snc); + } + m_Snc2 = snc; } void QmitkPointListWidget::SetSnc3(mitk::SliceNavigationController* snc) { - m_Snc3 = snc; - m_PointListView->SetSnc3(snc); + if (snc == NULL) + { + m_PointListView->RemoveSliceNavigationController(m_Snc3); + } + else + { + m_PointListView->AddSliceNavigationController(snc); + } + m_Snc3 = snc; +} + +void QmitkPointListWidget::AddSliceNavigationController(mitk::SliceNavigationController* snc) +{ + m_PointListView->AddSliceNavigationController(snc); +} + +void QmitkPointListWidget::RemoveSliceNavigationController(mitk::SliceNavigationController* snc) +{ + m_PointListView->RemoveSliceNavigationController(snc); } void QmitkPointListWidget::UnselectEditButton() { m_ToggleAddPoint->setChecked(false); -} \ No newline at end of file +} diff --git a/Modules/QmitkExt/QmitkPointListWidget.h b/Modules/QmitkExt/QmitkPointListWidget.h index e63094a587..67ef291627 100644 --- a/Modules/QmitkExt/QmitkPointListWidget.h +++ b/Modules/QmitkExt/QmitkPointListWidget.h @@ -1,153 +1,171 @@ /*=================================================================== 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 QmitkPointListWidget_H #define QmitkPointListWidget_H #include #include #include "QmitkExtExports.h" #include #include #include #include #include #include /*! * \brief Widget for regular operations on point sets * * Displays a list of point coordinates and a couple of * buttons which * * \li enable point set interaction * \li clear all points from a set * \li load points from file * \li save points to file * * The user/application module of this widget needs to * assign a mitk::PointSet object to this widget. The user * also has to decide whether it wants to put the point set * into (a) DataStorage. This widget will not add/remove * point sets to DataStorage. * * If the render window crosshair should be moved to the * currently selected point, the widget user has to provide * a QmitkStdMultiWidget object. */ class QmitkExt_EXPORT QmitkPointListWidget : public QWidget { Q_OBJECT public: QmitkPointListWidget(QWidget *parent = 0, int orientation = 0); ~QmitkPointListWidget(); void SetupConnections(); ///@{ /** * \brief Sets the SliceNavigationController of the three 2D Renderwindows. * If they are defined, they can be used to automatically set the crosshair to the selected point + * \deprecatedSince{2013_03} Use AddSliceNavigationController and RemoveSliceNavigationController instead. */ - void SetSnc1(mitk::SliceNavigationController* snc); - void SetSnc2(mitk::SliceNavigationController* snc); - void SetSnc3(mitk::SliceNavigationController* snc); + DEPRECATED( void SetSnc1(mitk::SliceNavigationController* snc) ); + DEPRECATED( void SetSnc2(mitk::SliceNavigationController* snc) ); + DEPRECATED( void SetSnc3(mitk::SliceNavigationController* snc) ); ///@} + /** + * @brief Add a mitk::SliceNavigationController instance. + * @param snc The mitk::SliceNavigationController instance. + * + * This method adds \c snc to the set of slice navigation controllers which are + * used to navigate to the selected point. + */ + void AddSliceNavigationController(mitk::SliceNavigationController* snc); + + /** + * @brief Remove a mitk::SliceNavigationController instance. + * @param snc The mitk::SliceNavigationController instance. + * + * This method removes \c snc from the set of slice navigation controllers which are + * used to navigate to the selected point. + */ + void RemoveSliceNavigationController(mitk::SliceNavigationController* snc); /** @brief assign a point set (contained in a node of DataStorage) for observation */ void SetPointSet(mitk::PointSet* newPs); mitk::PointSet* GetPointSet(); /** @brief assign a point set (contained in a node of DataStorage) for observation */ void SetPointSetNode(mitk::DataNode* newNode); mitk::DataNode* GetPointSetNode(); /** @brief assign a QmitkStdMultiWidget for updating render window crosshair */ void SetMultiWidget(QmitkStdMultiWidget* multiWidget); /** @brief itk observer for node "delete" events */ void OnNodeDeleted( const itk::EventObject & e ); /** @brief Unselects the edit button if it is selected. */ void UnselectEditButton(); public slots: void DeactivateInteractor(bool deactivate); void EnableEditButton(bool enabled); signals: /** @brief signal to inform about the state of the EditPointSetButton, whether an interactor for setting points is active or not */ void EditPointSets(bool active); /// signal to inform that the selection of a point in the pointset has changed void PointSelectionChanged(); /// signal to inform about cleared or loaded point sets void PointListChanged(); protected slots: void OnBtnSavePoints(); void OnBtnLoadPoints(); void RemoveSelectedPoint(); void MoveSelectedPointDown(); void MoveSelectedPointUp(); void OnBtnAddPoint(bool checked); void OnBtnAddPointManually(); //void OnBtnSetPointsMode(bool checked); /*! \brief pass through signal from PointListView that point selection has changed */ void OnPointSelectionChanged(); void OnListDoubleClick(); protected: void SetupUi(); void ObserveNewNode(mitk::DataNode* node); QmitkPointListView* m_PointListView; QmitkStdMultiWidget* m_MultiWidget; mitk::DataNode::Pointer m_PointSetNode; int m_Orientation; QPushButton* m_MovePointUpBtn; QPushButton* m_MovePointDownBtn; QPushButton* m_RemovePointBtn; QPushButton* m_SavePointsBtn; QPushButton* m_LoadPointsBtn; QPushButton* m_ToggleAddPoint; QPushButton* m_AddPoint; mitk::SliceNavigationController* m_Snc1; mitk::SliceNavigationController* m_Snc2; mitk::SliceNavigationController* m_Snc3; mitk::PointSetInteractor::Pointer m_Interactor; int m_TimeStep; bool m_EditAllowed; unsigned long m_NodeObserverTag; }; #endif