Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.