Medical Imaging Interaction Toolkit  2018.4.99-f51274ea
Medical Imaging Interaction Toolkit
QmitkPointListModel.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "QmitkPointListModel.h"
14 #include "mitkInteractionConst.h"
15 #include "mitkPointOperation.h"
16 #include "mitkRenderingManager.h"
17 #include <itkCommand.h>
18 #include <mitkInteractionConst.h>
19 #include <mitkInternalEvent.h>
21 
22 QmitkPointListModel::QmitkPointListModel(mitk::DataNode *pointSetNode, int t, QObject *parent)
23  : QAbstractListModel(parent),
24  m_PointSetNode(nullptr),
25  m_PointSetModifiedObserverTag(0),
26  m_PointSetDeletedObserverTag(0),
27  m_TimeStep(t)
28 {
29  ObserveNewPointSet(pointSetNode);
30 }
31 
32 Qt::ItemFlags QmitkPointListModel::flags(const QModelIndex & /*index*/) const
33 {
34  // no editing so far, return default (enabled, selectable)
35  return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
36 }
37 
39 {
40  this->ObserveNewPointSet(nullptr);
41 }
42 
44 {
45  this->ObserveNewPointSet(pointSetNode);
46  QAbstractListModel::beginResetModel();
47  QAbstractListModel::endResetModel();
48  emit SignalUpdateSelection();
49 }
50 
52 {
54 }
55 
57 {
58  m_TimeStep = t;
59  QAbstractListModel::beginResetModel();
60  QAbstractListModel::endResetModel();
61  emit SignalUpdateSelection();
62 }
63 
65 {
66  return m_TimeStep;
67 }
68 
70 {
71  // remove old observers
72  if (m_PointSetNode != nullptr)
73  {
74  try // here sometimes an exception is thrown which leads to a crash. So catch this exception but give an error
75  // message. See bug 18316 for details.
76  {
77  mitk::PointSet::Pointer oldPointSet = dynamic_cast<mitk::PointSet *>(m_PointSetNode->GetData());
78  if (oldPointSet.IsNotNull())
79  {
80  oldPointSet->RemoveObserver(m_PointSetModifiedObserverTag);
81  oldPointSet->RemoveObserver(m_PointSetDeletedObserverTag);
82  }
83  }
84  catch (std::exception &e)
85  {
86  MITK_ERROR << "Exception while removing observer from old point set node: " << e.what();
87  }
88  }
89 
90  // get the new pointset
91  mitk::PointSet::Pointer pointSet = this->CheckForPointSetInNode(pointSetNode);
92 
93  m_PointSetNode = pointSetNode;
94 
95  if (pointSet.IsNotNull())
96  {
97  // add new observer for modified if necessary
98  itk::ReceptorMemberCommand<QmitkPointListModel>::Pointer modCommand =
99  itk::ReceptorMemberCommand<QmitkPointListModel>::New();
100  modCommand->SetCallbackFunction(this, &QmitkPointListModel::OnPointSetChanged);
101  m_PointSetModifiedObserverTag = pointSet->AddObserver(itk::ModifiedEvent(), modCommand);
102 
103  // add new observer for detele if necessary
104  itk::ReceptorMemberCommand<QmitkPointListModel>::Pointer delCommand =
105  itk::ReceptorMemberCommand<QmitkPointListModel>::New();
106  delCommand->SetCallbackFunction(this, &QmitkPointListModel::OnPointSetDeleted);
107  m_PointSetDeletedObserverTag = pointSet->AddObserver(itk::DeleteEvent(), delCommand);
108  }
109  else
110  {
113  }
114 }
115 
116 void QmitkPointListModel::OnPointSetChanged(const itk::EventObject &)
117 {
118  QAbstractListModel::beginResetModel();
119  QAbstractListModel::endResetModel();
120  emit SignalUpdateSelection();
121 }
122 
123 void QmitkPointListModel::OnPointSetDeleted(const itk::EventObject &)
124 {
126  if (ps)
127  {
128  ps->RemoveObserver(m_PointSetModifiedObserverTag);
129  ps->RemoveObserver(m_PointSetDeletedObserverTag);
130  }
131 
134  QAbstractListModel::beginResetModel();
135  QAbstractListModel::endResetModel();
136 }
137 
138 int QmitkPointListModel::rowCount(const QModelIndex &) const
139 {
141  if (pointSet.IsNotNull())
142  {
143  return pointSet->GetSize(m_TimeStep);
144  }
145  else
146  {
147  return 0;
148  }
149 }
150 
151 QVariant QmitkPointListModel::data(const QModelIndex &index, int role) const
152 {
154 
155  if (pointSet.IsNull())
156  {
157  return QVariant();
158  }
159 
160  if (!index.isValid())
161  {
162  return QVariant();
163  }
164 
165  if (index.row() >= pointSet->GetSize(m_TimeStep))
166  {
167  return QVariant();
168  }
169 
170  if (role == Qt::DisplayRole)
171  {
172  mitk::PointSet::PointsContainer::ElementIdentifier id;
174  bool pointFound = this->GetPointForModelIndex(index, p, id);
175  if (pointFound == false)
176  return QVariant();
177 
178  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);
179  return QVariant(s);
180  }
181  else
182  {
183  return QVariant();
184  }
185 }
186 
187 QVariant QmitkPointListModel::headerData(int section, Qt::Orientation orientation, int role) const
188 {
189  if (role != Qt::DisplayRole)
190  {
191  return QVariant();
192  }
193 
194  if (orientation == Qt::Horizontal)
195  {
196  return QString("Coordinates").arg(section);
197  }
198  else
199  {
200  return QString("Row %1").arg(section);
201  }
202 }
203 
204 bool QmitkPointListModel::GetPointForModelIndex(const QModelIndex &index,
207 {
209  if (pointSet.IsNull())
210  return false;
211 
212  if ((index.row() < 0) || (index.row() >= (int)pointSet->GetPointSet(m_TimeStep)->GetPoints()->Size()))
213  return false;
214 
215  // get the nth. element, if it exists.
216  // we can not use the index directly, because PointSet uses a map container,
217  // where the index is not necessarily the same as the key.
218  // Therefore we have to count the elements
219  mitk::PointSet::PointsContainer::Iterator it = pointSet->GetPointSet(m_TimeStep)->GetPoints()->Begin();
220  for (int i = 0; i < index.row(); ++i)
221  {
222  ++it;
223 
224  if (it == pointSet->GetPointSet(m_TimeStep)->GetPoints()->End())
225  return false;
226  }
227 
228  if (it != pointSet->GetPointSet(m_TimeStep)->GetPoints()->End()) // not at the end,
229  {
230  p = it->Value();
231  id = it->Index();
232  return true;
233  }
234 
235  return false;
236 }
237 
239 {
241  if (pointSet.IsNull())
242  return false;
243 
244  mitk::PointSet::PointsContainer::Pointer points = pointSet->GetPointSet(m_TimeStep)->GetPoints();
245 
246  if (points->IndexExists(id) == false)
247  return false;
248 
249  unsigned int idx = 0;
250  for (mitk::PointSet::PointsContainer::Iterator it = points->Begin(); it != points->End(); ++it)
251  {
252  if (it->Index() == id) // we found the correct element
253  {
254  index = this->index(idx);
255  return true;
256  }
257 
258  idx++;
259  }
260 
261  return false; // nothing found
262 }
263 
265 {
267  if (pointSet.IsNull())
268  return;
269 
271  selectedID = pointSet->SearchSelectedPoint(m_TimeStep);
272  mitk::ScalarType tsInMS = pointSet->GetTimeGeometry()->TimeStepToTimePoint(m_TimeStep);
273  mitk::PointOperation *doOp =
274  new mitk::PointOperation(mitk::OpMOVEPOINTUP, tsInMS, pointSet->GetPoint(selectedID, m_TimeStep), selectedID, true);
275  pointSet->ExecuteOperation(doOp);
276  mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // Workaround for update problem in Pointset/Mapper
277 }
278 
280 {
282  if (pointSet.IsNull())
283  return;
284 
286  selectedID = pointSet->SearchSelectedPoint(m_TimeStep);
287  mitk::ScalarType tsInMS = pointSet->GetTimeGeometry()->TimeStepToTimePoint(m_TimeStep);
289  mitk::OpMOVEPOINTDOWN, tsInMS, pointSet->GetPoint(selectedID, m_TimeStep), selectedID, true);
290  pointSet->ExecuteOperation(doOp);
291  mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // Workaround for update problem in Pointset/Mapper
292 }
293 
295 {
297  if (pointSet.IsNull())
298  return;
299 
301  selectedID = pointSet->SearchSelectedPoint(m_TimeStep);
302  mitk::ScalarType tsInMS = pointSet->GetTimeGeometry()->TimeStepToTimePoint(m_TimeStep);
303  mitk::PointOperation *doOp =
304  new mitk::PointOperation(mitk::OpREMOVE, tsInMS, pointSet->GetPoint(selectedID, m_TimeStep), selectedID, true);
305  pointSet->ExecuteOperation(doOp);
306  mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // Workaround for update problem in Pointset/Mapper
307 }
308 
310 {
311  if (node != nullptr)
312  {
313  mitk::PointSet::Pointer pointSet = dynamic_cast<mitk::PointSet *>(node->GetData());
314  if (pointSet.IsNotNull())
315  return pointSet;
316  }
317  return nullptr;
318 }
QVariant data(const QModelIndex &index, int role) const override
interface of QAbstractListModel
mitk::PointSet * CheckForPointSetInNode(mitk::DataNode *node) const
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
interface of QAbstractListModel
#define MITK_ERROR
Definition: mitkLogMacros.h:20
double ScalarType
int rowCount(const QModelIndex &parent=QModelIndex()) const override
interface of QAbstractListModel
mitk::PointSet * GetPointSet() const
which point set to work on
Constants for most interaction classes, due to the generic StateMachines.
QmitkPointListModel(mitk::DataNode *=nullptr, int t=0, QObject *parent=nullptr)
void SetTimeStep(int t)
which time step to display/model
unsigned int m_PointSetDeletedObserverTag
void SetPointSetNode(mitk::DataNode *pointSetNode)
which point set to work on
void ObserveNewPointSet(mitk::DataNode *pointSetNode)
internally observe different point set
DataType::PointIdentifier PointIdentifier
Definition: mitkPointSet.h:133
void OnPointSetChanged(const itk::EventObject &e)
itk observer for point set "modified" events
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
Data structure which stores a set of points. Superclass of mitk::Mesh.
Definition: mitkPointSet.h:75
static RenderingManager * GetInstance()
int GetTimeStep() const
which time step to display/model
Operation that handles all actions on one Point.
bool GetPointForModelIndex(const QModelIndex &index, mitk::PointSet::PointType &p, mitk::PointSet::PointIdentifier &id) const
get point and point ID that correspond to a given QModelIndex
bool GetModelIndexForPointID(mitk::PointSet::PointIdentifier id, QModelIndex &index) const
returns a QModelIndex for a given point ID
Qt::ItemFlags flags(const QModelIndex &) const override
unsigned int m_PointSetModifiedObserverTag
mitk::DataNode * m_PointSetNode
void OnPointSetDeleted(const itk::EventObject &e)
itk observer for point set "delete" events
void SignalUpdateSelection()
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57