Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
QmitkRenderWindowDataStorageTreeModel.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 // render window manager UI module
15 
16 // mitk core
18 
19 // qt widgets module
20 #include "QmitkCustomVariants.h"
21 #include "QmitkEnums.h"
22 #include "QmitkMimeTypes.h"
24 
27  , m_Root(nullptr)
28 {
29  m_RenderWindowLayerController = std::make_unique<mitk::RenderWindowLayerController>();
30  ResetTree();
31 }
32 
34 {
35  m_RenderWindowLayerController->SetDataStorage(m_DataStorage.Lock());
36  ResetTree();
37  UpdateModelData();
38 }
39 
41 {
42  ResetTree();
43  UpdateModelData();
44 }
45 
47 {
48  for (const auto renderer : m_ControlledRenderer)
49  {
50  // add the node to each render window
51  mitk::RenderWindowLayerUtilities::SetRenderWindowProperties(const_cast<mitk::DataNode*>(node), renderer);
52  }
53 
54  if (!m_BaseRenderer.IsExpired())
55  {
56  auto baseRenderer = m_BaseRenderer.Lock();
57  AddNodeInternal(node, baseRenderer);
58  }
59 }
60 
62 {
63  auto item = m_Root->Find(node);
64  if (nullptr != item)
65  {
66  auto parentItem = item->GetParent();
67  // as the root node should not be removed one should always have a parent item
68  if (nullptr == parentItem)
69  {
70  return;
71  }
72 
73  auto index = createIndex(item->GetIndex(), 0, item);
74  emit dataChanged(index, index);
75  }
76 }
77 
79 {
80  RemoveNodeInternal(node);
81 }
82 
83 QModelIndex QmitkRenderWindowDataStorageTreeModel::index(int row, int column, const QModelIndex& parent) const
84 {
85  auto item = GetItemByIndex(parent);
86  if (nullptr != item)
87  {
88  item = item->GetChild(row);
89  }
90 
91  if (nullptr == item)
92  {
93  return QModelIndex();
94  }
95 
96  return createIndex(row, column, item);
97 }
98 
99 QModelIndex QmitkRenderWindowDataStorageTreeModel::parent(const QModelIndex& parent) const
100 {
101  auto item = GetItemByIndex(parent);
102  if (nullptr != item)
103  {
104  item = item->GetParent();
105  }
106 
107  if(nullptr == item)
108  {
109  return QModelIndex();
110  }
111 
112  if (item == m_Root)
113  {
114  return QModelIndex();
115  }
116 
117  return createIndex(item->GetIndex(), 0, item);
118 }
119 
120 int QmitkRenderWindowDataStorageTreeModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const
121 {
122  auto item = GetItemByIndex(parent);
123  if (nullptr == item)
124  {
125  return 0;
126  }
127 
128  return item->GetChildCount();
129 }
130 
131 int QmitkRenderWindowDataStorageTreeModel::columnCount(const QModelIndex&/* parent = QModelIndex()*/) const
132 {
133  if (0 == m_Root->GetChildCount())
134  {
135  // no items stored, no need to display columns
136  return 0;
137  }
138 
139  return 1;
140 }
141 
142 QVariant QmitkRenderWindowDataStorageTreeModel::data(const QModelIndex& index, int role) const
143 {
144  if (m_BaseRenderer.IsExpired())
145  {
146  return QVariant();
147  }
148 
149  auto baseRenderer = m_BaseRenderer.Lock();
150 
151  if (!index.isValid() || this != index.model())
152  {
153  return QVariant();
154  }
155 
156  auto item = GetItemByIndex(index);
157  if (nullptr == item)
158  {
159  return QVariant();
160  }
161 
162  auto dataNode = item->GetDataNode();
163  if (nullptr == dataNode)
164  {
165  return QVariant();
166  }
167 
168  if (Qt::CheckStateRole == role)
169  {
170  bool visibility = false;
171  dataNode->GetVisibility(visibility, baseRenderer);
172  if (visibility)
173  {
174  return Qt::Checked;
175  }
176  else
177  {
178  return Qt::Unchecked;
179  }
180  }
181  else if (Qt::DisplayRole == role)
182  {
183  return QVariant(QString::fromStdString(dataNode->GetName()));
184  }
185  else if (Qt::ToolTipRole == role)
186  {
187  return QVariant("Name of the data node.");
188  }
189  else if (Qt::DecorationRole == role)
190  {
192  return nodeDescriptor->GetIcon(dataNode);
193  }
194  else if (Qt::UserRole == role || QmitkDataNodeRawPointerRole == role)
195  {
196  // user role always returns a reference to the data node,
197  // which can be used to modify the data node in the data storage
198  return QVariant::fromValue<mitk::DataNode*>(dataNode);
199  }
200  else if (QmitkDataNodeRole == role)
201  {
202  return QVariant::fromValue<mitk::DataNode::Pointer>(mitk::DataNode::Pointer(dataNode));
203  }
204 
205  return QVariant();
206 }
207 
208 bool QmitkRenderWindowDataStorageTreeModel::setData(const QModelIndex& index, const QVariant& value, int role /*= Qt::EditRole*/)
209 {
210  if (m_BaseRenderer.IsExpired())
211  {
212  return false;
213  }
214 
215  auto baseRenderer = m_BaseRenderer.Lock();
216 
217  if (!index.isValid() || this != index.model())
218  {
219  return false;
220  }
221 
222  auto item = GetItemByIndex(index);
223  if (nullptr == item)
224  {
225  return false;
226  }
227 
228  auto dataNode = item->GetDataNode();
229  if (nullptr == dataNode)
230  {
231  return false;
232  }
233 
234  if (Qt::EditRole == role && !value.toString().isEmpty())
235  {
236  dataNode->SetName(value.toString().toStdString().c_str());
237  emit dataChanged(index, index);
238  return true;
239  }
240  if (Qt::CheckStateRole == role)
241  {
242  Qt::CheckState newCheckState = static_cast<Qt::CheckState>(value.toInt());
243  bool isVisible = newCheckState;
244  dataNode->SetVisibility(isVisible, baseRenderer);
245 
246  emit dataChanged(index, index);
247  mitk::RenderingManager::GetInstance()->RequestUpdate(baseRenderer->GetRenderWindow());
248  return true;
249  }
250  return false;
251 }
252 
253 Qt::ItemFlags QmitkRenderWindowDataStorageTreeModel::flags(const QModelIndex& index) const
254 {
255  if (this != index.model())
256  {
257  return Qt::NoItemFlags;
258  }
259 
260  if (!index.isValid())
261  {
262  return Qt::ItemIsDropEnabled;
263  }
264 
265  auto item = GetItemByIndex(index);
266  if (nullptr == item)
267  {
268  return Qt::NoItemFlags;
269  }
270 
271  const auto dataNode = item->GetDataNode();
272  if (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(dataNode))
273  {
274  return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
275  }
276 
277  return Qt::NoItemFlags;
278 }
279 
281 {
282  return Qt::CopyAction | Qt::MoveAction;
283 }
284 
286 {
287  return Qt::CopyAction | Qt::MoveAction;
288 }
289 
291 {
292  QStringList types = QAbstractItemModel::mimeTypes();
294  return types;
295 }
296 
297 QMimeData* QmitkRenderWindowDataStorageTreeModel::mimeData(const QModelIndexList& indexes) const
298 {
299  QMimeData* mimeData = new QMimeData();
300  QByteArray encodedData;
301 
302  QDataStream stream(&encodedData, QIODevice::WriteOnly);
303 
304  for (const auto& index : indexes)
305  {
306  if (index.isValid())
307  {
308  auto dataNode = data(index, QmitkDataNodeRawPointerRole).value<mitk::DataNode*>();
309  stream << reinterpret_cast<quintptr>(dataNode);
310  }
311  }
312 
313  mimeData->setData(QmitkMimeTypes::DataNodePtrs, encodedData);
314  return mimeData;
315 }
316 
317 bool QmitkRenderWindowDataStorageTreeModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int /*row*/, int /*column*/, const QModelIndex& parent)
318 {
319  if (m_BaseRenderer.IsExpired())
320  {
321  return false;
322  }
323 
324  auto baseRenderer = m_BaseRenderer.Lock();
325 
326  if (action == Qt::IgnoreAction)
327  {
328  return true;
329  }
330 
331  if (!data->hasFormat(QmitkMimeTypes::DataNodePtrs))
332  {
333  return false;
334  }
335 
336  if (!parent.isValid())
337  {
338  return false;
339  }
340 
341  int layer = -1;
342  auto dataNode = this->data(parent, QmitkDataNodeRawPointerRole).value<mitk::DataNode*>();
343  if (nullptr != dataNode)
344  {
345  dataNode->GetIntProperty("layer", layer, baseRenderer);
346  }
347 
348  auto dataNodeList = QmitkMimeTypes::ToDataNodePtrList(data);
349  for (const auto& dataNode : dataNodeList)
350  {
351  m_RenderWindowLayerController->MoveNodeToPosition(dataNode, layer, baseRenderer);
352  }
353 
354  ResetTree();
355  UpdateModelData();
356  AdjustLayerProperty();
357  return true;
358 }
359 
361 {
362  m_RenderWindowLayerController->SetControlledRenderer(controlledRenderer);
363  m_ControlledRenderer = controlledRenderer;
364 
365  ResetTree();
366  if (m_DataStorage.IsExpired())
367  {
368  return;
369  }
370 
371  auto dataStorage = m_DataStorage.Lock();
372 
373  for (const auto& renderer : controlledRenderer)
374  {
375  if (nullptr == renderer)
376  {
377  continue;
378  }
379 
380  auto allDataNodes = dataStorage->GetAll();
381  for (const auto& dataNode : *allDataNodes)
382  {
383  // add the node to each render window
385  }
386  }
387 }
388 
390 {
391  if (m_BaseRenderer == baseRenderer)
392  {
393  return;
394  }
395 
396  // base renderer changed
397  // reset tree to build a new renderer-specific item hierarchy
398  m_BaseRenderer = baseRenderer;
399  ResetTree();
400  UpdateModelData();
401 }
402 
404 {
405  if (m_BaseRenderer.IsExpired())
406  {
407  return nullptr;
408  }
409 
410  return m_BaseRenderer.Lock().GetPointer();
411 }
412 
413 void QmitkRenderWindowDataStorageTreeModel::ResetTree()
414 {
415  beginResetModel();
416  if (nullptr != m_Root)
417  {
418  m_Root->Delete();
419  }
420 
422  rootDataNode->SetName("Data Storage");
423  m_Root = new QmitkDataStorageTreeModelInternalItem(rootDataNode);
424  endResetModel();
425 }
426 
427 void QmitkRenderWindowDataStorageTreeModel::UpdateModelData()
428 {
429  if (!m_DataStorage.IsExpired())
430  {
431  auto dataStorage = m_DataStorage.Lock();
432  if (!m_BaseRenderer.IsExpired())
433  {
434  auto baseRenderer = m_BaseRenderer.Lock();
435 
437  auto filteredDataNodes = dataStorage->GetSubset(combinedNodePredicate);
438  for (const auto& dataNode : *filteredDataNodes)
439  {
440  AddNodeInternal(dataNode, baseRenderer);
441  }
442  }
443  }
444 }
445 
446 void QmitkRenderWindowDataStorageTreeModel::AdjustLayerProperty()
447 {
448  if (m_BaseRenderer.IsExpired())
449  {
450  return;
451  }
452 
453  auto baseRenderer = m_BaseRenderer.Lock();
454 
455  std::vector<QmitkDataStorageTreeModelInternalItem*> treeAsVector;
456  TreeToVector(m_Root, treeAsVector);
457 
458  int i = treeAsVector.size() - 1;
459  for (auto it = treeAsVector.begin(); it != treeAsVector.end(); ++it)
460  {
461  auto dataNode = (*it)->GetDataNode();
462  dataNode->SetIntProperty("layer", i, baseRenderer);
463  --i;
464  }
465 }
466 
467 void QmitkRenderWindowDataStorageTreeModel::TreeToVector(QmitkDataStorageTreeModelInternalItem* parent, std::vector<QmitkDataStorageTreeModelInternalItem*>& treeAsVector) const
468 {
470  for (int i = 0; i < parent->GetChildCount(); ++i)
471  {
472  item = parent->GetChild(i);
473  TreeToVector(item, treeAsVector);
474  treeAsVector.push_back(item);
475  }
476 }
477 
478 void QmitkRenderWindowDataStorageTreeModel::AddNodeInternal(const mitk::DataNode* dataNode, const mitk::BaseRenderer* renderer)
479 {
480  if (nullptr == dataNode
482  || nullptr != m_Root->Find(dataNode))
483  {
484  return;
485  }
486 
487  // find out if we have a root node
488  auto parentItem = m_Root;
489  QModelIndex index;
490  auto parentDataNode = GetParentNode(dataNode);
491 
492  if (nullptr != parentDataNode) // no top level data node
493  {
494  parentItem = m_Root->Find(parentDataNode);
495  if (nullptr == parentItem)
496  {
497  // parent node not contained in the tree; add it
498  NodeAdded(parentDataNode);
499  parentItem = m_Root->Find(parentDataNode);
500  if (nullptr == parentItem)
501  {
502  // could not find and add the parent tree; abort
503  return;
504  }
505  }
506 
507  // get the index of this parent with the help of the grand parent
508  index = createIndex(parentItem->GetIndex(), 0, parentItem);
509  }
510 
511  int firstRowWithASiblingBelow = 0;
512  int nodeLayer = -1;
513  dataNode->GetIntProperty("layer", nodeLayer, renderer);
514  for (const auto& siblingItem : parentItem->GetChildren())
515  {
516  int siblingLayer = -1;
517  auto siblingNode = siblingItem->GetDataNode();
518  if (nullptr != siblingNode)
519  {
520  siblingNode->GetIntProperty("layer", siblingLayer, renderer);
521  }
522  if (nodeLayer > siblingLayer)
523  {
524  break;
525  }
526  ++firstRowWithASiblingBelow;
527  }
528 
529  beginInsertRows(index, firstRowWithASiblingBelow, firstRowWithASiblingBelow);
530  auto newNode = new QmitkDataStorageTreeModelInternalItem(const_cast<mitk::DataNode*>(dataNode));
531  parentItem->InsertChild(newNode, firstRowWithASiblingBelow);
532  endInsertRows();
533 }
534 
535 void QmitkRenderWindowDataStorageTreeModel::RemoveNodeInternal(const mitk::DataNode* dataNode)
536 {
537  if (nullptr == dataNode
538  || nullptr == m_Root)
539  {
540  return;
541  }
542 
543  auto item = m_Root->Find(dataNode);
544  if (nullptr == item)
545  {
546  return;
547  }
548 
549  auto parentItem = item->GetParent();
550  auto parentIndex = GetIndexByItem(parentItem);
551 
552  auto children = item->GetChildren();
553  beginRemoveRows(parentIndex, item->GetIndex(), item->GetIndex());
554  parentItem->RemoveChild(item);
555  delete item;
556  endRemoveRows();
557 
558  if (!children.empty())
559  {
560  // rebuild tree because children could not be at the top level
561  ResetTree();
562  UpdateModelData();
563  }
564 }
565 
566 mitk::DataNode* QmitkRenderWindowDataStorageTreeModel::GetParentNode(const mitk::DataNode* node) const
567 {
568  mitk::DataNode* dataNode = nullptr;
569  if (m_DataStorage.IsExpired())
570  {
571  return dataNode;
572  }
573 
574  auto sources = m_DataStorage.Lock()->GetSources(node);
575  if (sources->empty())
576  {
577  return dataNode;
578  }
579 
580  return sources->front();
581 }
582 
583 QmitkDataStorageTreeModelInternalItem* QmitkRenderWindowDataStorageTreeModel::GetItemByIndex(const QModelIndex& index) const
584 {
585  if (index.isValid())
586  {
587  return static_cast<QmitkDataStorageTreeModelInternalItem*>(index.internalPointer());
588  }
589 
590  return m_Root;
591 }
592 
593 QModelIndex QmitkRenderWindowDataStorageTreeModel::GetIndexByItem(QmitkDataStorageTreeModelInternalItem* item) const
594 {
595  if (item == m_Root)
596  {
597  return QModelIndex();
598  }
599 
600  return createIndex(item->GetIndex(), 0, item);
601 }
itk::SmartPointer< T > Lock() const
MITKRENDERWINDOWMANAGER_EXPORT void SetRenderWindowProperties(mitk::DataNode *dataNode, const BaseRenderer *renderer)
Set renderer-specific properties to mark a data node as &#39;managed by the specific renderer&#39;. In order for a renderer to manage a data node, the &#39;fixedLayer&#39; property has to be set for the given renderer. Additionally, the &#39;visible&#39; and the &#39;layer&#39; property are set and allow to individually render a set of nodes with a specific renderer. The last two mentioned properties are set so that they initially have the same value as the corresponding global property.
Decorator class for mitk::DataNode.
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
Qt::ItemFlags flags(const QModelIndex &index) const override
Organizes the rendering process.
static QList< mitk::DataNode * > ToDataNodePtrList(const QByteArray &ba)
MITKRENDERWINDOWMANAGER_EXPORT NodePredicateAnd::Pointer GetRenderWindowPredicate(const BaseRenderer *renderer)
Helper function to get a node predicate that can be used to filter render window specific data nodes...
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
static const QString DataNodePtrs
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
bool GetIntProperty(const char *propertyKey, int &intValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for int properties (instances of IntProperty)
std::vector< BaseRenderer * > RendererVector
itk::SmartPointer< Self > Pointer
Definition: mitkDataNode.h:71
QmitkNodeDescriptor * GetDescriptor(const mitk::DataNode *node) const
QModelIndex parent(const QModelIndex &parent) const override
void NodeAdded(const mitk::DataNode *node) override
See &#39;QmitkAbstractDataStorageModel&#39;.
mitk::NodePredicateBase::ConstPointer m_NodePredicate
void SetCurrentRenderer(mitk::BaseRenderer *baseRenderer)
QmitkDataStorageTreeModelInternalItem * GetChild(int index) const
static Pointer New()
static RenderingManager * GetInstance()
QVariant data(const QModelIndex &index, int role) const override
bool IsExpired() const noexcept
int columnCount(const QModelIndex &parent=QModelIndex()) const override
void NodeRemoved(const mitk::DataNode *node) override
See &#39;QmitkAbstractDataStorageModel&#39;.
void NodePredicateChanged() override
See &#39;QmitkAbstractDataStorageModel&#39;.
void DataStorageChanged() override
See &#39;QmitkAbstractDataStorageModel&#39;.
QmitkDataStorageTreeModelInternalItem * GetParent() const
void NodeChanged(const mitk::DataNode *node) override
See &#39;QmitkAbstractDataStorageModel&#39;.
QMimeData * mimeData(const QModelIndexList &indexes) const override
void RequestUpdate(vtkRenderWindow *renderWindow)
void SetControlledRenderer(mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer)
QmitkDataStorageTreeModelInternalItem * Find(const mitk::DataNode *_DataNode) const
virtual QIcon GetIcon(const mitk::DataNode *node) const
static QmitkNodeDescriptorManager * GetInstance()
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57
int rowCount(const QModelIndex &parent=QModelIndex()) const override
mitk::WeakPointer< mitk::DataStorage > m_DataStorage