diff --git a/Modules/QmitkExt/QmitkPointListModel.cpp b/Modules/QmitkExt/QmitkPointListModel.cpp index 76f06ec1d1..20fdca503e 100644 --- a/Modules/QmitkExt/QmitkPointListModel.cpp +++ b/Modules/QmitkExt/QmitkPointListModel.cpp @@ -1,202 +1,277 @@ /*========================================================================= - + Program: Medical Imaging & Interaction Toolkit Module: $RCSfile: mitkPropertyManager.cpp,v $ Language: C++ Date: $Date$ Version: $Revision: 1.12 $ - + Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - + This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. - + =========================================================================*/ #include "QmitkPointListModel.h" #include - -QmitkPointListModel::QmitkPointListModel( const mitk::PointSet* pointSet, int t, QObject* parent ) +#include "mitkInteractionConst.h" +#include "mitkPointOperation.h" + +QmitkPointListModel::QmitkPointListModel( mitk::PointSet* pointSet, int t, QObject* parent ) :QAbstractListModel(parent), - m_PointSet(NULL), - m_PointSetModifiedObserverTag(0), - m_PointSetDeletedObserverTag(0), - m_TimeStep(t) +m_PointSet(NULL), +m_PointSetModifiedObserverTag(0), +m_PointSetDeletedObserverTag(0), +m_TimeStep(t) { ObserveNewPointset( pointSet ); } + QmitkPointListModel::~QmitkPointListModel() { ObserveNewPointset( NULL ); } - -void QmitkPointListModel::SetPointSet( const mitk::PointSet* pointSet ) + + +void QmitkPointListModel::SetPointSet( mitk::PointSet* pointSet ) { ObserveNewPointset( pointSet ); emit QAbstractListModel::layoutChanged(); emit UpdateSelection(); } - -const mitk::PointSet* QmitkPointListModel::GetPointSet() + + +mitk::PointSet* QmitkPointListModel::GetPointSet() const { return m_PointSet; } - + + void QmitkPointListModel::SetTimeStep(int t) { m_TimeStep = t; emit QAbstractListModel::layoutChanged(); emit UpdateSelection(); } - + + int QmitkPointListModel::GetTimeStep() { return m_TimeStep; } -void QmitkPointListModel::ObserveNewPointset( const mitk::PointSet* pointSet ) + +void QmitkPointListModel::ObserveNewPointset( mitk::PointSet* pointSet ) { // remove old observer if ( m_PointSet != NULL ) { - const_cast(m_PointSet)->RemoveObserver( m_PointSetModifiedObserverTag ); - const_cast(m_PointSet)->RemoveObserver( m_PointSetDeletedObserverTag ); + m_PointSet->RemoveObserver( m_PointSetModifiedObserverTag ); + m_PointSet->RemoveObserver( m_PointSetDeletedObserverTag ); } m_PointSet = pointSet; - // add new observer for modified if neccessary + // add new observer for modified if necessary if ( m_PointSet != NULL ) { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkPointListModel::OnPointSetChanged ); - m_PointSetModifiedObserverTag = const_cast(m_PointSet)->AddObserver( itk::ModifiedEvent(), command ); + m_PointSetModifiedObserverTag = m_PointSet->AddObserver( itk::ModifiedEvent(), command ); } else { m_PointSetModifiedObserverTag = 0; } - // add new observer for modified if neccessary + // add new observer for modified if necessary if ( m_PointSet != NULL ) { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkPointListModel::OnPointSetDeleted ); - m_PointSetDeletedObserverTag = const_cast(m_PointSet)->AddObserver( itk::DeleteEvent(), command ); + m_PointSetDeletedObserverTag = m_PointSet->AddObserver( itk::DeleteEvent(), command ); } else { m_PointSetDeletedObserverTag = 0; } } - + + void QmitkPointListModel::OnPointSetChanged( const itk::EventObject & e ) { - //std::cout << "point set changed" << std::endl; - //emit QAbstractListModel::dataChanged(); this->reset(); emit QAbstractListModel::layoutChanged(); emit UpdateSelection(); } + void QmitkPointListModel::OnPointSetDeleted( const itk::EventObject & e ) { m_PointSet = NULL; m_PointSetModifiedObserverTag = 0; m_PointSetDeletedObserverTag = 0; - - //std::cout << "point set deleted" << std::endl; emit QAbstractListModel::layoutChanged(); } int QmitkPointListModel::rowCount( const QModelIndex& parent ) const { if ( m_PointSet != NULL ) { return m_PointSet->GetSize(m_TimeStep); } else { return 0; } } + QVariant QmitkPointListModel::data(const QModelIndex& index, int role) const { if ( m_PointSet == NULL ) { return QVariant(); } if ( !index.isValid() ) { return QVariant(); } if ( index.row() >= m_PointSet->GetSize(m_TimeStep) ) { return QVariant(); } if (role == Qt::DisplayRole) { - //mitk::Point3D p; - //bool exists = m_PointSet->GetPointIfExists( index.row(), &p, m_TimeStep ); - //if (exists == false) - // return QVariant(); - - // get the nth. element, we can not use the index directly, because PointSet uses a map container, where the index is not necessarily the same as the key. - mitk::PointSet::PointsContainer::Iterator it = m_PointSet->GetPointSet()->GetPoints()->Begin(); - for (unsigned int i = 0; i < index.row(); ++i) - { - ++it; - if (it == m_PointSet->GetPointSet()->GetPoints()->End()) - break; - } - if (it != m_PointSet->GetPointSet()->GetPoints()->End()) - { - mitk::Point3D p = it->Value(); - mitk::PointSet::PointsContainer::ElementIdentifier id = it->Index(); - QString s = QString("%0: (%1, %2, %3)") - .arg( id, 3) - .arg( p[0], 0, 'f', 3 ) - .arg( p[1], 0, 'f', 3 ) - .arg( p[2], 0, 'f', 3 ); - return QVariant(s); - } - else - { - // corresponding point for index not found. should we report this as an error? + mitk::PointSet::PointsContainer::ElementIdentifier id; + mitk::PointSet::PointType p; + bool pointFound = this->GetPointForModelIndex(index, p, id); + if (pointFound == false) return QVariant(); - } - + QString s = QString("%0: (%1, %2, %3)") + .arg( id, 3) + .arg( p[0], 0, 'f', 3 ) + .arg( p[1], 0, 'f', 3 ) + .arg( p[2], 0, 'f', 3 ); + return QVariant(s); } else { return QVariant(); } } - + + QVariant QmitkPointListModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole) { return QVariant(); } if (orientation == Qt::Horizontal) { return QString("Coordinates").arg(section); } else { return QString("Row %1").arg(section); } } + +bool QmitkPointListModel::GetPointForModelIndex( const QModelIndex &index, mitk::PointSet::PointType& p, mitk::PointSet::PointIdentifier& id) const +{ + if (m_PointSet == NULL) + return false; + + if ((index.row() < 0) || (index.row() >= m_PointSet->GetPointSet(m_TimeStep)->GetPoints()->Size())) + return false; + + // get the nth. element, if it exists. + // we can not use the index directly, because PointSet uses a map container, + // where the index is not necessarily the same as the key. + // Therefore we have to count the elements + mitk::PointSet::PointsContainer::Iterator it = m_PointSet->GetPointSet(m_TimeStep)->GetPoints()->Begin(); + for (unsigned int i = 0; i < index.row(); ++i) + { + ++it; + if (it == m_PointSet->GetPointSet(m_TimeStep)->GetPoints()->End()) + return false; + } + if (it != m_PointSet->GetPointSet(m_TimeStep)->GetPoints()->End()) // not at the end, + { + p = it->Value(); + id = it->Index(); + return true; + } + return false; +} + + +bool QmitkPointListModel::GetModelIndexForPointID(mitk::PointSet::PointIdentifier id, QModelIndex& index) const +{ + if (m_PointSet == NULL) + return false; + + if (m_PointSet->GetPointSet(m_TimeStep)->GetPoints()->IndexExists(id) == false) + return false; + + unsigned int idx = 0; + for (mitk::PointSet::PointsContainer::Iterator it = m_PointSet->GetPointSet(m_TimeStep)->GetPoints()->Begin(); it != m_PointSet->GetPointSet(m_TimeStep)->GetPoints()->End(); ++it) + { + if (it->Index() == id) // we found the correct element + { + index = this->index(idx); + return true; + } + idx++; + } + return false; // nothing found +} + + +void QmitkPointListModel::MoveSelectedPointUp() +{ + if (m_PointSet == NULL) + return; + + mitk::PointSet::PointIdentifier selectedID; + selectedID = m_PointSet->SearchSelectedPoint(m_TimeStep); + mitk::PointOperation* doOp = new mitk::PointOperation(mitk::OpMOVEPOINTUP, m_PointSet->GetPoint(selectedID, m_TimeStep), selectedID, true); + m_PointSet->ExecuteOperation(doOp); +} + + +void QmitkPointListModel::MoveSelectedPointDown() +{ + if (m_PointSet == NULL) + return; + + mitk::PointSet::PointIdentifier selectedID; + selectedID = m_PointSet->SearchSelectedPoint(m_TimeStep); + mitk::PointOperation* doOp = new mitk::PointOperation(mitk::OpMOVEPOINTDOWN, m_PointSet->GetPoint(selectedID, m_TimeStep), selectedID, true); + m_PointSet->ExecuteOperation(doOp); +} + + +void QmitkPointListModel::RemoveSelectedPoint() +{ + if (m_PointSet == NULL) + return; + + mitk::PointSet::PointIdentifier selectedID; + selectedID = m_PointSet->SearchSelectedPoint(m_TimeStep); + mitk::PointOperation* doOp = new mitk::PointOperation(mitk::OpREMOVE, m_PointSet->GetPoint(selectedID, m_TimeStep), selectedID, true); + m_PointSet->ExecuteOperation(doOp); +} diff --git a/Modules/QmitkExt/QmitkPointListModel.h b/Modules/QmitkExt/QmitkPointListModel.h index 9585b15cac..a4e9c90fb2 100644 --- a/Modules/QmitkExt/QmitkPointListModel.h +++ b/Modules/QmitkExt/QmitkPointListModel.h @@ -1,84 +1,115 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile: mitkPropertyManager.cpp,v $ Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef QMITK_POINTLIST_MODEL_H_INCLUDED #define QMITK_POINTLIST_MODEL_H_INCLUDED #include #include "mitkPointSet.h" class QMITKEXT_EXPORT QmitkPointListModel : public QAbstractListModel { Q_OBJECT public: - QmitkPointListModel( const mitk::PointSet* = NULL, int t = 0, QObject* parent = 0 ); + QmitkPointListModel( mitk::PointSet* = NULL, int t = 0, QObject* parent = 0 ); ~QmitkPointListModel(); // interface of QAbstractListModel int rowCount( const QModelIndex& parent = QModelIndex() ) const; // interface of QAbstractListModel QVariant data(const QModelIndex& index, int role) const; - + // interface of QAbstractListModel QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; /// which point set to work on - void SetPointSet( const mitk::PointSet* pointSet ); + void SetPointSet( mitk::PointSet* pointSet ); /// which point set to work on - const mitk::PointSet* GetPointSet(); + mitk::PointSet* GetPointSet() const; /// which time step to display/model void SetTimeStep(int t); /// which time step to display/model int GetTimeStep(); /// itk observer for point set "modified" events void OnPointSetChanged( const itk::EventObject & e ); /// itk observer for point set "delete" events void OnPointSetDeleted( const itk::EventObject & e ); + /** + * \brief get point and point ID that correspond to a given QModelIndex + * + * The mitk::PointSet uses a map to store points in an ID<-->Point relation. + * The IDs are not neccesarily continuously numbered, therefore, we can not + * directly use the QModelIndex as point ID. This method returns the point and + * the corresponding point id for a given QModelIndex. The point and the point ID + * are returned in the outgoing parameters p and id. If a valid point and ID were + * found, the method returns true, otherwise it returns false + * \param[in] QModelIndex &index the index for which a point is requested. + The row() part of the index is used to find a corresponding point + * \param[out] mitk::Point3D& p If a valid point is found, it will be stored in the p parameter + * \param[out] mitk::PointSet::PointIdentifier& id If a valid point is found, the corresponding ID will be stored in id + * \return Returns true, if a valid point was found, false otherwise + */ + bool QmitkPointListModel::GetPointForModelIndex( const QModelIndex &index, mitk::PointSet::PointType& p, mitk::PointSet::PointIdentifier& id) const; + + /**Documentation + * \brief returns a QModelIndex for a given point ID + * + * The mitk::PointSet uses a map to store points in an ID<-->Point relation. + * The IDs are not neccesarily continuously numbered, therefore, we can not + * directly use the point ID as a QModelIndex. This method returns a QModelIndex + * for a given point ID in the outgoing parameter index. + * \param[in] mitk::PointSet::PointIdentifier id The point ID for which the QModelIndex will be created + * \param[out] QModelIndex& index if a point with the ID id was found, index will contain a corresponding QModelIndex for that point + * \return returns true, if a valid QModelIndex was created, false otherwise + */ + bool GetModelIndexForPointID(mitk::PointSet::PointIdentifier id, QModelIndex& index) const; + + public slots: + void MoveSelectedPointUp(); + void MoveSelectedPointDown(); + void RemoveSelectedPoint(); signals: /// emitted, when views should update their selection status /// (because mouse interactions in render windows can change /// the selection status of points) void UpdateSelection(); protected: /// internally observe different point set - void ObserveNewPointset( const mitk::PointSet* pointSet ); - - const mitk::PointSet* m_PointSet; + void ObserveNewPointset( mitk::PointSet* pointSet ); + + mitk::PointSet* m_PointSet; unsigned int m_PointSetModifiedObserverTag; unsigned int m_PointSetDeletedObserverTag; - int m_TimeStep; }; - #endif - diff --git a/Modules/QmitkExt/QmitkPointListView.cpp b/Modules/QmitkExt/QmitkPointListView.cpp index ec3c1f5f53..00cf41082a 100644 --- a/Modules/QmitkExt/QmitkPointListView.cpp +++ b/Modules/QmitkExt/QmitkPointListView.cpp @@ -1,146 +1,164 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile: mitkPropertyManager.cpp,v $ Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkPointListView.h" #include "QmitkPointListModel.h" #include "QmitkStdMultiWidget.h" #include "mitkRenderingManager.h" +#include + QmitkPointListView::QmitkPointListView( QWidget* parent ) :QListView( parent ), m_PointListModel( new QmitkPointListModel() ), m_SelfCall( false ), m_MultiWidget( NULL) { // cosmetics QListView::setAlternatingRowColors( true ); // logic QListView::setModel( m_PointListModel ); QListView::setSelectionBehavior( QAbstractItemView::SelectRows ); QListView::setSelectionMode( QAbstractItemView::SingleSelection ); connect( m_PointListModel, SIGNAL(UpdateSelection()), this, SLOT(OnPointSetSelectionChanged()) ); connect( QListView::selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(OnListViewSelectionChanged(const QItemSelection& , const QItemSelection&)) ); } QmitkPointListView::~QmitkPointListView() { delete m_PointListModel; } void QmitkPointListView::SetPointSet( mitk::PointSet* pointSet ) { m_PointListModel->SetPointSet( pointSet ); } 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::OnPointSetSelectionChanged() { - if (m_SelfCall) return; + if (m_SelfCall) + return; - m_SelfCall = true; - // update this view's selection status as a result to changes in the point set data structure - //std::cout << "update view selection from point set" << std::endl; const mitk::PointSet* pointSet = m_PointListModel->GetPointSet(); - if (pointSet) - { - int timeStep = m_PointListModel->GetTimeStep(); + if (pointSet == NULL) + return; - if ( pointSet->GetNumberOfSelected( timeStep ) > 1 ) - { - /// @TODO use logging as soon as available - std::cerr << "Point set has multiple selected points. This view is not designed for more than one selected point." << std::endl; - } + // 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(); - int selectedIndex = pointSet->SearchSelectedPoint( timeStep ); + if ( pointSet->GetNumberOfSelected( timeStep ) > 1 ) + { + /// @TODO use logging as soon as available + std::cerr << "Point set has multiple selected points. This view is not designed for more than one selected point." << std::endl; + } - QListView::selectionModel()->select( m_PointListModel->index( selectedIndex ), - QItemSelectionModel::SelectCurrent ); + 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( m_PointListModel->index( selectedIndex ), QItemSelectionModel::SelectCurrent ); m_SelfCall = false; } + void QmitkPointListView::OnListViewSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) { - if (m_SelfCall) return; + if (m_SelfCall) + return; mitk::PointSet* pointSet = const_cast( m_PointListModel->GetPointSet() ); int timeStep = m_PointListModel->GetTimeStep(); - if (!pointSet) return; + if (pointSet == NULL) + return; - // select point in point set // (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 (int i = 0; i < selectedIndexes.size(); ++i) + for (mitk::PointSet::PointsContainer::Iterator it = pointSet->GetPointSet(m_PointListModel->GetTimeStep())->GetPoints()->Begin(); it != pointSet->GetPointSet(m_PointListModel->GetTimeStep())->GetPoints()->End(); ++it) { - QModelIndex index = selectedIndexes.at(i); - if ( index.isValid() ) + QModelIndex index; + m_PointListModel->GetModelIndexForPointID(it->Index(), index); + if (selectedIndexes.indexOf(index) != -1) // index is found in the selected indices list { - int selectedIndex = index.row(); - pointSet->SetSelectInfo( selectedIndex, true, timeStep ); - //std::cout << " select row " << selectedIndex << std::endl; - - // move crosshair to selected point - if ( m_MultiWidget ) - { - m_MultiWidget->MoveCrossToPosition( pointSet->GetPoint( selectedIndex, timeStep ) ); - } + pointSet->SetSelectInfo(it->Index(), true, m_PointListModel->GetTimeStep()); + if ( m_MultiWidget != NULL) + m_MultiWidget->MoveCrossToPosition(pointSet->GetPoint(it->Index(), m_PointListModel->GetTimeStep())); } + else + pointSet->SetSelectInfo(it->Index(), false, m_PointListModel->GetTimeStep()); } + m_SelfCall = false; + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + + +void QmitkPointListView::keyPressEvent( QKeyEvent * e ) +{ + if (m_PointListModel == NULL) + return; - QModelIndexList deselectedIndexes = deselected.indexes(); - for (int i = 0; i < deselectedIndexes.size(); ++i) + int key = e->key(); + switch (key) { - QModelIndex index = deselectedIndexes.at(i); - if ( index.isValid() ) - { - int selectedIndex = index.row(); - pointSet->SetSelectInfo( selectedIndex, false, timeStep ); - //std::cout << " deselect row " << selectedIndex << std::endl; - } + 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; } - m_SelfCall = false; - - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } diff --git a/Modules/QmitkExt/QmitkPointListView.h b/Modules/QmitkExt/QmitkPointListView.h index 29b2821224..ebb2c33ad6 100644 --- a/Modules/QmitkExt/QmitkPointListView.h +++ b/Modules/QmitkExt/QmitkPointListView.h @@ -1,77 +1,77 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile: mitkPropertyManager.cpp,v $ Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef QMITK_POINTLIST_VIEW_H_INCLUDED #define QMITK_POINTLIST_VIEW_H_INCLUDED #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 SetPointSet( mitk::PointSet* pointSet ); /// which point set to work on const mitk::PointSet* GetPointSet() const; - /// assign a QmitkStdMultiWidget for updating render window crosshair - void SetMultiWidget( QmitkStdMultiWidget* multiWidget ); - QmitkStdMultiWidget* GetMultiWidget() const; + + void SetMultiWidget( QmitkStdMultiWidget* multiWidget ); ///< assign a QmitkStdMultiWidget for updating render window crosshair + + QmitkStdMultiWidget* GetMultiWidget() const; ///< return the QmitkStdMultiWidget that is used for updating render window crosshair protected slots: /// 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); - + protected: + void keyPressEvent( QKeyEvent * e ); ///< react to F2, F3 and DEL keys QmitkPointListModel* m_PointListModel; bool m_SelfCall; /// used to position the planes on a selected point QmitkStdMultiWidget* m_MultiWidget; }; - #endif - diff --git a/Modules/QmitkExt/QmitkPointListWidget.cpp b/Modules/QmitkExt/QmitkPointListWidget.cpp index deaedd3c36..92963ba382 100644 --- a/Modules/QmitkExt/QmitkPointListWidget.cpp +++ b/Modules/QmitkExt/QmitkPointListWidget.cpp @@ -1,305 +1,309 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile: mitkPropertyManager.cpp,v $ Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkPointListWidget.h" #include "mitkGlobalInteraction.h" #include "mitkPointSetReader.h" #include "mitkPointSetWriter.h" #include #include #include #include +#include #include "btnSetPoints.xpm" #include "btnClear.xpm" #include "btnLoad.xpm" #include "btnSave.xpm" QmitkPointListWidget::QmitkPointListWidget( QWidget* parent, Qt::WindowFlags f ) :QWidget( parent, f ), m_ListView(NULL), m_BtnEdit(NULL), m_BtnClear(NULL), m_BtnLoad(NULL), m_BtnSave(NULL), m_PointSetNode(NULL), m_Interactor(NULL), m_EditAllowed(true), m_NodeObserverTag(0) { QGridLayout* layout = new QGridLayout; layout->setContentsMargins( 0, 0, 0, 0 ); this->setLayout( layout ); this->setContentsMargins( 0, 0, 0, 0 ); m_ListView = new QmitkPointListView( this ); layout->addWidget( m_ListView, 0, 0, 1, 4 ); // span 4 cols - + m_ListView->setToolTip("Use F2 to move the selected point up, use F3 to move the selected point down"); const QIcon iconEdit( btnSetPoints_xpm ); // installs/removes pointset interactor m_BtnEdit = new QPushButton( iconEdit, "", this ); m_BtnEdit->setToolTip("Toggle point editing (use SHIFT + Left Mouse Button to add Points)"); connect( m_BtnEdit, SIGNAL(toggled(bool)), this, SLOT(OnEditPointSetButtonToggled(bool)) ); m_BtnEdit->setCheckable( true ); layout->addWidget( m_BtnEdit, 1, 0 ); const QIcon iconClear( btnClear_xpm ); // clears whole point set m_BtnClear = new QPushButton( iconClear, "", this ); - m_BtnClear->setToolTip("Erase all points from list"); + m_BtnClear->setToolTip("Erase all points from list. Use the delete key to delete the selected point."); connect( m_BtnClear, SIGNAL(clicked()), this, SLOT(OnClearPointSetButtonClicked()) ); layout->addWidget( m_BtnClear, 1, 1 ); const QIcon iconLoad( btnLoad_xpm ); // loads a point set from file m_BtnLoad = new QPushButton( iconLoad, "", this ); m_BtnLoad->setToolTip("Load list of points from file (REPLACES current content)"); connect( m_BtnLoad, SIGNAL(clicked()), this, SLOT(OnLoadPointSetButtonClicked()) ); layout->addWidget( m_BtnLoad, 1, 2 ); const QIcon iconSave( btnSave_xpm ); // saves point set to file m_BtnSave = new QPushButton( iconSave, "", this ); m_BtnSave->setToolTip("Save points to file"); connect( m_BtnSave, SIGNAL(clicked()), this, SLOT(OnSavePointSetButtonClicked()) ); layout->addWidget( m_BtnSave, 1, 3 ); ObserveNewNode(NULL); } QmitkPointListWidget::~QmitkPointListWidget() { if (m_Interactor) mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; if (m_PointSetNode != NULL) m_PointSetNode->RemoveObserver( m_NodeObserverTag ); m_PointSetNode = NULL; } void QmitkPointListWidget::SetPointSetNode( mitk::DataTreeNode* node ) { ObserveNewNode(node); if (node) { mitk::PointSet* pointSet = dynamic_cast( node->GetData() ); m_ListView->SetPointSet( pointSet ); } else { m_ListView->SetPointSet( NULL ); } } void QmitkPointListWidget::SetMultiWidget( QmitkStdMultiWidget* multiWidget ) { m_ListView->SetMultiWidget( multiWidget ); } void QmitkPointListWidget::DeactivateInteractor(bool deactivate) { if (deactivate) { if (m_Interactor) { mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; m_BtnEdit->setChecked( false ); } } } void QmitkPointListWidget::ObserveNewNode( mitk::DataTreeNode* node ) { // remove old observer if ( m_PointSetNode != NULL ) { if (m_Interactor) { mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; m_BtnEdit->setChecked( false ); } m_PointSetNode->RemoveObserver( m_NodeObserverTag ); } m_PointSetNode = node; // add new observer if necessary if ( m_PointSetNode != NULL ) { 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_BtnEdit->setEnabled( m_PointSetNode != NULL ); else m_BtnEdit->setEnabled( false ); m_BtnClear->setEnabled( m_PointSetNode != NULL ); m_BtnLoad->setEnabled( m_PointSetNode != NULL ); m_BtnSave->setEnabled( m_PointSetNode != NULL ); } void QmitkPointListWidget::OnNodeDeleted( const itk::EventObject & e ) { m_PointSetNode = NULL; m_NodeObserverTag = 0; m_ListView->SetPointSet( NULL ); } void QmitkPointListWidget::OnEditPointSetButtonToggled(bool checked) { if (m_PointSetNode) { if (checked) { m_Interactor = mitk::PointSetInteractor::New("pointsetinteractor", m_PointSetNode); mitk::GlobalInteraction::GetInstance()->AddInteractor( m_Interactor ); } else if ( m_Interactor ) { mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; } emit EditPointSets(checked); } } void QmitkPointListWidget::OnClearPointSetButtonClicked() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; // we don't have to disturb by asking silly questions switch( QMessageBox::question( this, tr("Clear Points"), tr("Remove all points from the displayed list?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No)) { case QMessageBox::Yes: if (pointSet) { mitk::PointSet::DataType::PointsContainer::Pointer pointsContainer = pointSet->GetPointSet()->GetPoints(); pointsContainer->Initialize(); // a call to initialize results in clearing the points container } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; case QMessageBox::No: default: break; } emit PointListChanged(); } void QmitkPointListWidget::OnLoadPointSetButtonClicked() { if (!m_PointSetNode) return; // 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); } m_PointSetNode->SetData( pointSet ); m_ListView->SetPointSet( pointSet ); if (interactionOn) { OnEditPointSetButtonToggled(true); } } catch(...) { QMessageBox::warning( this, "Load point set", QString("File reader collapsed while reading %1").arg(filename) ); } emit PointListChanged(); } void QmitkPointListWidget::OnSavePointSetButtonClicked() { - if (!m_PointSetNode) return; + if (!m_PointSetNode) + return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); - if (!pointSet) return; // don't write empty point sets. If application logic requires something else then do something else. - if (pointSet->GetSize() == 0) return; + if (!pointSet) + return; // don't write empty point sets. If application logic requires something else then do something else. + if (pointSet->GetSize() == 0) + return; // let the user choose a file std::string name(""); - QString fileNameProposal = "PointSet.mps"; - QString aFilename = QFileDialog::getSaveFileName( NULL, "Save point set", fileNameProposal, "MITK Pointset (*.mps)" ); + QString fileNameProposal = QString("/%1.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( pointSet ); 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::EnableEditButton( bool enabled ) { m_EditAllowed = enabled; if (enabled == false) m_BtnEdit->setEnabled(false); else m_BtnEdit->setEnabled(true); OnEditPointSetButtonToggled(enabled); }