Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
QmitkDataStorageListModel.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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
18 
19 //# Own includes
20 // mitk
21 #include "mitkStringProperty.h"
22 
23 //# Toolkit includes
24 // itk
25 #include "itkCommand.h"
26 
29  QObject *parent)
30  : QAbstractListModel(parent), m_NodePredicate(nullptr), m_DataStorage(nullptr), m_BlockEvents(false)
31 {
32  this->SetPredicate(pred);
33  this->SetDataStorage(dataStorage);
34 }
35 
37 {
38  // set data storage to nullptr so that the event listener gets removed
39  this->SetDataStorage(nullptr);
40 }
41 
43 {
44  if (m_DataStorage == dataStorage)
45  {
46  return;
47  }
48 
49  // remove old listeners
50  if (m_DataStorage != nullptr)
51  {
52  m_DataStorage->AddNodeEvent.RemoveListener(
55 
56  m_DataStorage->RemoveNodeEvent.RemoveListener(
59 
60  m_DataStorage->RemoveObserver(m_DataStorageDeleteObserverTag);
61  m_DataStorageDeleteObserverTag = 0;
62  }
63 
64  m_DataStorage = dataStorage;
65 
66  if (m_DataStorage != nullptr)
67  {
68  // subscribe for node added/removed events
71 
72  m_DataStorage->RemoveNodeEvent.AddListener(
75 
76  // add ITK delete listener on data storage
79  deleteCommand->SetCallbackFunction(this, &QmitkDataStorageListModel::OnDataStorageDeleted);
80  m_DataStorageDeleteObserverTag = m_DataStorage->AddObserver(itk::DeleteEvent(), deleteCommand);
81  }
82 
83  // reset/rebuild model
84  reset();
85 }
86 
87 Qt::ItemFlags QmitkDataStorageListModel::flags(const QModelIndex &) const
88 {
89  return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
90 }
91 
92 QVariant QmitkDataStorageListModel::data(const QModelIndex &index, int role) const
93 {
94  if (role == Qt::DisplayRole && index.isValid())
95  {
96  const mitk::DataNode *node = std::get<NODE>(m_NodesAndObserverTags.at(index.row()));
97  return QVariant(QString::fromStdString(node->GetName()));
98  }
99  else
100  {
101  return QVariant();
102  }
103 }
104 
105 QVariant QmitkDataStorageListModel::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const
106 {
107  return QVariant(tr("Nodes"));
108 }
109 
110 int QmitkDataStorageListModel::rowCount(const QModelIndex & /*parent*/) const
111 {
112  return m_NodesAndObserverTags.size();
113 }
114 
115 std::vector<mitk::DataNode *> QmitkDataStorageListModel::GetDataNodes() const
116 {
117  auto size = m_NodesAndObserverTags.size();
118  std::vector<mitk::DataNode *> result(size);
119  for (int i = 0; i < size; ++i)
120  {
121  result[i] = std::get<NODE>(m_NodesAndObserverTags[i]);
122  }
123  return result;
124 }
125 
127 {
128  return m_DataStorage;
129 }
130 
132 {
133  m_NodePredicate = pred;
134 
135  // in a prior implementation the call to beginResetModel() been after reset().
136  // Should this actually be the better order of calls, please document!
137  QAbstractListModel::beginResetModel();
138  reset();
139  QAbstractListModel::endResetModel();
140 }
141 
143 {
144  return m_NodePredicate;
145 }
146 
148 {
150 
151  if (m_DataStorage != nullptr)
152  {
153  if (m_NodePredicate != nullptr)
154  {
155  modelNodes = m_DataStorage->GetSubset(m_NodePredicate);
156  }
157  else
158  {
159  modelNodes = m_DataStorage->GetAll();
160  }
161  }
162 
164 
165  // add all filtered nodes to our list
166  if (modelNodes != nullptr)
167  {
168  for (auto &node : *modelNodes)
169  {
170  AddNodeToInternalList(node);
171  }
172  }
173 }
174 
176 {
177  if (m_DataStorage != nullptr)
178  {
180  // add modified observer
182  nodeModifiedCommand->SetCallbackFunction(this, &QmitkDataStorageListModel::OnDataNodeModified);
183  unsigned long nodeObserverTag = node->AddObserver(itk::ModifiedEvent(), nodeModifiedCommand);
184 
186  unsigned long dataObserverTag = 0;
187  // add modified observer
188  if (node->GetData() != nullptr)
189  {
191  dataModifiedCommand->SetCallbackFunction(this, &QmitkDataStorageListModel::OnDataModified);
192  dataObserverTag = node->GetData()->AddObserver(itk::ModifiedEvent(), dataModifiedCommand);
193  }
194 
195  m_NodesAndObserverTags.push_back(std::make_tuple(node, nodeObserverTag, dataObserverTag));
196  }
197 }
198 
200 {
201  for (auto &iter : m_NodesAndObserverTags)
202  {
203  auto node = std::get<NODE>(iter);
204  if (node != nullptr)
205  {
206  node->RemoveObserver(std::get<NODE_OBSERVER>(iter));
207  if (node->GetData() != nullptr)
208  {
209  node->GetData()->RemoveObserver(std::get<DATA_OBSERVER>(iter));
210  }
211  }
212  }
213  m_NodesAndObserverTags.clear();
214 }
215 
217 {
218  for (auto iter = m_NodesAndObserverTags.begin(); iter != m_NodesAndObserverTags.end(); ++iter)
219  {
220  if (std::get<NODE>(*iter) == node)
221  {
222  node->RemoveObserver(std::get<NODE_OBSERVER>(*iter));
223  if (node->GetData() != nullptr)
224  {
225  node->GetData()->RemoveObserver(std::get<DATA_OBSERVER>(*iter));
226  }
227  m_NodesAndObserverTags.erase(iter); // invalidate iter
228  break;
229  }
230  }
231 }
232 
234 {
235  // guarantee no recursions when a new node event is thrown
236  if (!m_BlockEvents)
237  {
238  m_BlockEvents = true;
239 
240  // check if node should be added to the model
241  bool addNode = true;
242  if (m_NodePredicate && !m_NodePredicate->CheckNode(node))
243  addNode = false;
244 
245  if (addNode)
246  {
247  int newIndex = m_NodesAndObserverTags.size();
248  beginInsertRows(QModelIndex(), newIndex, newIndex);
249  AddNodeToInternalList(const_cast<mitk::DataNode *>(node));
250  endInsertRows();
251  }
252 
253  m_BlockEvents = false;
254  }
255 }
256 
258 {
259  // guarantee no recursions when a new node event is thrown
260  if (!m_BlockEvents)
261  {
262  m_BlockEvents = true;
263 
264  int row = 0;
265  for (auto iter = m_NodesAndObserverTags.begin(); iter != m_NodesAndObserverTags.end(); ++iter, ++row)
266  {
267  if (std::get<NODE>(*iter) == node)
268  {
269  // node found, remove it
270  beginRemoveRows(QModelIndex(), row, row);
271  RemoveNodeFromInternalList(std::get<NODE>(*iter));
272  endRemoveRows();
273  break;
274  }
275  }
276  }
277 
278  m_BlockEvents = false;
279 }
280 
281 void QmitkDataStorageListModel::OnDataNodeModified(const itk::Object *caller, const itk::EventObject & /*event*/)
282 {
283  if (m_BlockEvents)
284  return;
285 
286  const mitk::DataNode *modifiedNode = dynamic_cast<const mitk::DataNode *>(caller);
287  if (modifiedNode)
288  {
289  QModelIndex changedIndex = getIndex(modifiedNode);
290  if (changedIndex.isValid())
291  {
292  emit dataChanged(changedIndex, changedIndex);
293  }
294  }
295 }
296 
297 void QmitkDataStorageListModel::OnDataModified(const itk::Object *caller, const itk::EventObject &event)
298 {
299  OnDataNodeModified(caller, event); // until different implementation
300 }
301 
302 void QmitkDataStorageListModel::OnDataStorageDeleted(const itk::Object *caller, const itk::EventObject & /*event*/)
303 {
304  if (m_BlockEvents)
305  return;
306 
307  // set data storage to nullptr -> empty model
308  this->SetDataStorage(nullptr);
309 }
310 
312 {
313  if (index.isValid())
314  {
315  return std::get<NODE>(m_NodesAndObserverTags.at(index.row()));
316  }
317  else
318  {
319  return nullptr;
320  }
321 }
322 
324 {
325  int row = 0;
326  for (auto iter = m_NodesAndObserverTags.begin(); iter != m_NodesAndObserverTags.end(); ++iter, ++row)
327  {
328  if (std::get<NODE>(*iter) == node)
329  {
330  return index(row);
331  }
332  }
333  return QModelIndex();
334 }
void RemoveListener(const AbstractDelegate &delegate) const
Definition: mitkMessage.h:397
void AddListener(const AbstractDelegate &delegate) const
Definition: mitkMessage.h:378
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Implements QAbstractListModel.
void reset()
Resets the whole model. Get all nodes matching the predicate from the data storage.
Data management class that handles 'was created by' relations.
itk::SmartPointer< Self > Pointer
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Implements QAbstractListModel.
mitk::NodePredicateBase * GetPredicate() const
Get the filter predicate in use.
virtual void OnDataStorageDeleted(const itk::Object *caller, const itk::EventObject &event)
bool GetName(std::string &nodeName, const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="name") const
Convenience access method for accessing the name of an object (instance of StringProperty with proper...
Definition: mitkDataNode.h:366
QModelIndex getIndex(const mitk::DataNode *node) const
Return the model index of the given node.
void SetPredicate(mitk::NodePredicateBase *pred)
Change the filter predicate.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
void SetDataStorage(mitk::DataStorage::Pointer dataStorage)
Change the data storage to represent.
itk::SmartPointer< const Self > ConstPointer
mitk::DataStorage * GetDataStorage() const
Get the represented data storage.
virtual void OnDataNodeModified(const itk::Object *caller, const itk::EventObject &event)
void AddNodeToInternalList(mitk::DataNode *node)
Internal helper: adds given node to end of list.
virtual SetOfObjects::ConstPointer GetAll() const =0
returns a set of all data objects that are stored in the data storage
mitk::DataStorage::Pointer m_DataStorage
Qt::ItemFlags flags(const QModelIndex &index) const override
Implements QAbstractListModel.
SetOfObjects::ConstPointer GetSubset(const NodePredicateBase *condition) const
returns a set of data objects that meet the given condition(s)
QmitkDataStorageListModel(mitk::DataStorage *dataStorage=nullptr, mitk::NodePredicateBase::Pointer pred=nullptr, QObject *parent=nullptr)
void RemoveNodeFromInternalList(mitk::DataNode *node)
Internal helper: remove given node.
virtual void OnDataStorageNodeAdded(const mitk::DataNode *node)
DataStorageEvent AddNodeEvent
AddEvent is emitted whenever a new node has been added to the DataStorage.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Implements QAbstractListModel.
DataStorageEvent RemoveNodeEvent
RemoveEvent is emitted directly before a node is removed from the DataStorage.
mitk::DataNode::Pointer getNode(const QModelIndex &index) const
Return the node for given model index.
virtual void OnDataStorageNodeRemoved(const mitk::DataNode *node)
Interface for evaluation conditions used in the DataStorage class GetSubset() method.
void ClearInternalNodeList()
Internal helper: Clear complete model list.
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
virtual void OnDataModified(const itk::Object *caller, const itk::EventObject &event)
std::vector< mitk::DataNode * > GetDataNodes() const
Get all current data nodes.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.