Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
QmitkDataStorageTreeModel.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 #include <mitkNodePredicateAnd.h>
17 #include <mitkNodePredicateData.h>
19 #include <mitkNodePredicateNot.h>
20 #include <mitkNodePredicateOr.h>
22 #include <mitkPlanarFigure.h>
23 #include <mitkProperties.h>
24 #include <mitkRenderingManager.h>
25 #include <mitkStringProperty.h>
26 
27 #include <mitkPropertyNameHelper.h>
28 
31 #include <QmitkCustomVariants.h>
32 #include <QmitkEnums.h>
33 #include <QmitkMimeTypes.h>
34 
35 #include <QFile>
36 #include <QIcon>
37 #include <QMimeData>
38 #include <QTextStream>
39 
40 #include <map>
41 
42 #include <mitkCoreServices.h>
43 
45  bool _PlaceNewNodesOnTop,
46  QObject *parent)
47  : QAbstractItemModel(parent),
48  m_DataStorage(0),
49  m_PlaceNewNodesOnTop(_PlaceNewNodesOnTop),
50  m_Root(0),
51  m_BlockDataStorageEvents(false),
52  m_AllowHierarchyChange(false)
53 {
54  this->SetDataStorage(_DataStorage);
55 }
56 
58 {
59  // set data storage to 0 = remove all listeners
60  this->SetDataStorage(0);
61  m_Root->Delete();
62  m_Root = 0;
63 }
64 
66 {
67  return this->TreeItemFromIndex(index)->GetDataNode();
68 }
69 
71 {
72  return m_DataStorage.GetPointer();
73 }
74 
75 QModelIndex QmitkDataStorageTreeModel::index(int row, int column, const QModelIndex &parent) const
76 {
77  TreeItem *parentItem;
78 
79  if (!parent.isValid())
80  parentItem = m_Root;
81  else
82  parentItem = static_cast<TreeItem *>(parent.internalPointer());
83 
84  TreeItem *childItem = parentItem->GetChild(row);
85  if (childItem)
86  return createIndex(row, column, childItem);
87  else
88  return QModelIndex();
89 }
90 
91 int QmitkDataStorageTreeModel::rowCount(const QModelIndex &parent) const
92 {
93  TreeItem *parentTreeItem = this->TreeItemFromIndex(parent);
94  return parentTreeItem->GetChildCount();
95 }
96 
97 Qt::ItemFlags QmitkDataStorageTreeModel::flags(const QModelIndex &index) const
98 {
99  mitk::DataNode *dataNode = this->TreeItemFromIndex(index)->GetDataNode();
100  if (index.isValid())
101  {
102  if (DicomPropertiesExists(*dataNode))
103  {
104  return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled |
105  Qt::ItemIsDropEnabled;
106  }
107  return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable |
108  Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
109  }
110  else
111  {
112  return Qt::ItemIsDropEnabled;
113  }
114 }
115 
116 int QmitkDataStorageTreeModel::columnCount(const QModelIndex & /* parent = QModelIndex() */) const
117 {
118  return 1;
119 }
120 
121 QModelIndex QmitkDataStorageTreeModel::parent(const QModelIndex &index) const
122 {
123  if (!index.isValid())
124  return QModelIndex();
125 
126  TreeItem *childItem = this->TreeItemFromIndex(index);
127  TreeItem *parentItem = childItem->GetParent();
128 
129  if (parentItem == m_Root)
130  return QModelIndex();
131 
132  return this->createIndex(parentItem->GetIndex(), 0, parentItem);
133 }
134 
136 {
137  if (index.isValid())
138  return static_cast<TreeItem *>(index.internalPointer());
139  else
140  return m_Root;
141 }
143 {
144  return Qt::CopyAction | Qt::MoveAction;
145 }
146 
148 {
149  return Qt::CopyAction | Qt::MoveAction;
150 }
151 
153  const QMimeData *data, Qt::DropAction action, int row, int /*column*/, const QModelIndex &parent)
154 {
155  // Early exit, returning true, but not actually doing anything (ignoring data).
156  if (action == Qt::IgnoreAction)
157  {
158  return true;
159  }
160 
161  // Note, we are returning true if we handled it, and false otherwise
162  bool returnValue = false;
163 
164  if (data->hasFormat("application/x-qabstractitemmodeldatalist"))
165  {
166  returnValue = true;
167 
168  // First we extract a Qlist of TreeItem* pointers.
169  QList<TreeItem *> listOfItemsToDrop = ToTreeItemPtrList(data);
170  if (listOfItemsToDrop.empty())
171  {
172  return false;
173  }
174 
175  // Retrieve the TreeItem* where we are dropping stuff, and its parent.
176  TreeItem *dropItem = this->TreeItemFromIndex(parent);
177  TreeItem *parentItem = dropItem->GetParent();
178 
179  // If item was dropped onto empty space, we select the root node
180  if (dropItem == m_Root)
181  {
182  parentItem = m_Root;
183  }
184 
185  // Dragging and Dropping is only allowed within the same parent, so use the first item in list to validate.
186  // (otherwise, you could have a derived image such as a segmentation, and assign it to another image).
187  // NOTE: We are assuming the input list is valid... i.e. when it was dragged, all the items had the same parent.
188 
189  // Determine whether or not the drag and drop operation is a valid one.
190  // Examples of invalid operations include:
191  // - dragging nodes with different parents
192  // - dragging nodes from one parent to another parent, if m_AllowHierarchyChange is false
193  // - dragging a node on one of its child nodes (only relevant if m_AllowHierarchyChange is true)
194 
195  bool isValidDragAndDropOperation(true);
196 
197  // different parents
198  {
199  TreeItem *firstParent = listOfItemsToDrop[0]->GetParent();
200  QList<TreeItem *>::iterator diIter;
201  for (diIter = listOfItemsToDrop.begin() + 1; diIter != listOfItemsToDrop.end(); diIter++)
202  {
203  if (firstParent != (*diIter)->GetParent())
204  {
205  isValidDragAndDropOperation = false;
206  break;
207  }
208  }
209  }
210 
211  // dragging from one parent to another
212  if ((!m_AllowHierarchyChange) && isValidDragAndDropOperation)
213  {
214  if (row == -1) // drag onto a node
215  {
216  isValidDragAndDropOperation = listOfItemsToDrop[0]->GetParent() == parentItem;
217  }
218  else // drag between nodes
219  {
220  isValidDragAndDropOperation = listOfItemsToDrop[0]->GetParent() == dropItem;
221  }
222  }
223 
224  // dragging on a child node of one the dragged nodes
225  {
226  QList<TreeItem *>::iterator diIter;
227  for (diIter = listOfItemsToDrop.begin(); diIter != listOfItemsToDrop.end(); diIter++)
228  {
229  TreeItem *tempItem = dropItem;
230 
231  while (tempItem != m_Root)
232  {
233  tempItem = tempItem->GetParent();
234  if (tempItem == *diIter)
235  {
236  isValidDragAndDropOperation = false;
237  }
238  }
239  }
240  }
241 
242  if (!isValidDragAndDropOperation)
243  return isValidDragAndDropOperation;
244 
245  if (listOfItemsToDrop[0] != dropItem && isValidDragAndDropOperation)
246  {
247  // Retrieve the index of where we are dropping stuff.
248  QModelIndex parentModelIndex = this->IndexFromTreeItem(parentItem);
249 
250  int dragIndex = 0;
251 
252  // Iterate through the list of TreeItem (which may be at non-consecutive indexes).
253  QList<TreeItem *>::iterator diIter;
254  for (diIter = listOfItemsToDrop.begin(); diIter != listOfItemsToDrop.end(); diIter++)
255  {
256  TreeItem *itemToDrop = *diIter;
257 
258  // if the item is dragged down we have to compensate its final position for the
259  // fact it is deleted lateron, this only applies if it is dragged within the same level
260  if ((itemToDrop->GetIndex() < row) && (itemToDrop->GetParent() == dropItem))
261  {
262  dragIndex = 1;
263  }
264 
265  // Here we assume that as you remove items, one at a time, that GetIndex() will be valid.
266  this->beginRemoveRows(
267  this->IndexFromTreeItem(itemToDrop->GetParent()), itemToDrop->GetIndex(), itemToDrop->GetIndex());
268  itemToDrop->GetParent()->RemoveChild(itemToDrop);
269  this->endRemoveRows();
270  }
271 
272  // row = -1 dropped on an item, row != -1 dropped in between two items
273  // Select the target index position, or put it at the end of the list.
274  int dropIndex = 0;
275  if (row != -1)
276  {
277  if (dragIndex == 0)
278  dropIndex = std::min(row, parentItem->GetChildCount() - 1);
279  else
280  dropIndex = std::min(row - 1, parentItem->GetChildCount() - 1);
281  }
282  else
283  {
284  dropIndex = dropItem->GetIndex();
285  }
286 
287  QModelIndex dropItemModelIndex = this->IndexFromTreeItem(dropItem);
288  if ((row == -1 && dropItemModelIndex.row() == -1) || dropItemModelIndex.row() > parentItem->GetChildCount())
289  dropIndex = parentItem->GetChildCount() - 1;
290 
291  // Now insert items again at the drop item position
292 
294  {
295  this->beginInsertRows(dropItemModelIndex, dropIndex, dropIndex + listOfItemsToDrop.size() - 1);
296  }
297  else
298  {
299  this->beginInsertRows(parentModelIndex, dropIndex, dropIndex + listOfItemsToDrop.size() - 1);
300  }
301 
302  for (diIter = listOfItemsToDrop.begin(); diIter != listOfItemsToDrop.end(); diIter++)
303  {
304  // dropped on node, behaviour depends on preference setting
306  {
308  mitk::DataNode *droppedNode = (*diIter)->GetDataNode();
309  mitk::DataNode *dropOntoNode = dropItem->GetDataNode();
310  m_DataStorage->Remove(droppedNode);
311  m_DataStorage->Add(droppedNode, dropOntoNode);
312  m_BlockDataStorageEvents = false;
313 
314  dropItem->InsertChild((*diIter), dropIndex);
315  }
316  else
317  {
318  if (row == -1) // drag onto a node
319  {
320  parentItem->InsertChild((*diIter), dropIndex);
321  }
322  else // drag between nodes
323  {
324  dropItem->InsertChild((*diIter), dropIndex);
325  }
326  }
327 
328  dropIndex++;
329  }
330  this->endInsertRows();
331 
332  // Change Layers to match.
333  this->AdjustLayerProperty();
334  }
335  }
336  else if (data->hasFormat("application/x-mitk-datanodes"))
337  {
338  returnValue = true;
339 
340  int numberOfNodesDropped = 0;
341 
342  QList<mitk::DataNode *> dataNodeList = QmitkMimeTypes::ToDataNodePtrList(data);
343  mitk::DataNode *node = NULL;
344  foreach (node, dataNodeList)
345  {
346  if (node && m_DataStorage.IsNotNull() && !m_DataStorage->Exists(node))
347  {
348  m_DataStorage->Add(node);
349  mitk::BaseData::Pointer basedata = node->GetData();
350 
351  if (basedata.IsNotNull())
352  {
354  basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true);
355 
356  numberOfNodesDropped++;
357  }
358  }
359  }
360  // Only do a rendering update, if we actually dropped anything.
361  if (numberOfNodesDropped > 0)
362  {
364  }
365  }
366 
367  return returnValue;
368 }
369 
371 {
372  QStringList types = QAbstractItemModel::mimeTypes();
373  types << "application/x-qabstractitemmodeldatalist";
374  types << "application/x-mitk-datanodes";
375  return types;
376 }
377 
378 QMimeData *QmitkDataStorageTreeModel::mimeData(const QModelIndexList &indexes) const
379 {
380  return mimeDataFromModelIndexList(indexes);
381 }
382 
383 QMimeData *QmitkDataStorageTreeModel::mimeDataFromModelIndexList(const QModelIndexList &indexes)
384 {
385  QMimeData *ret = new QMimeData;
386 
387  QString treeItemAddresses("");
388  QString dataNodeAddresses("");
389 
390  QByteArray baTreeItemPtrs;
391  QByteArray baDataNodePtrs;
392 
393  QDataStream dsTreeItemPtrs(&baTreeItemPtrs, QIODevice::WriteOnly);
394  QDataStream dsDataNodePtrs(&baDataNodePtrs, QIODevice::WriteOnly);
395 
396  for (int i = 0; i < indexes.size(); i++)
397  {
398  TreeItem *treeItem = static_cast<TreeItem *>(indexes.at(i).internalPointer());
399 
400  dsTreeItemPtrs << reinterpret_cast<quintptr>(treeItem);
401  dsDataNodePtrs << reinterpret_cast<quintptr>(treeItem->GetDataNode().GetPointer());
402 
403  // --------------- deprecated -----------------
404  unsigned long long treeItemAddress = reinterpret_cast<unsigned long long>(treeItem);
405  unsigned long long dataNodeAddress = reinterpret_cast<unsigned long long>(treeItem->GetDataNode().GetPointer());
406  QTextStream(&treeItemAddresses) << treeItemAddress;
407  QTextStream(&dataNodeAddresses) << dataNodeAddress;
408 
409  if (i != indexes.size() - 1)
410  {
411  QTextStream(&treeItemAddresses) << ",";
412  QTextStream(&dataNodeAddresses) << ",";
413  }
414  // -------------- end deprecated -------------
415  }
416 
417  // ------------------ deprecated -----------------
418  ret->setData("application/x-qabstractitemmodeldatalist", QByteArray(treeItemAddresses.toLatin1()));
419  ret->setData("application/x-mitk-datanodes", QByteArray(dataNodeAddresses.toLatin1()));
420  // --------------- end deprecated -----------------
421 
422  ret->setData(QmitkMimeTypes::DataStorageTreeItemPtrs, baTreeItemPtrs);
423  ret->setData(QmitkMimeTypes::DataNodePtrs, baDataNodePtrs);
424 
425  return ret;
426 }
427 
428 QVariant QmitkDataStorageTreeModel::data(const QModelIndex &index, int role) const
429 {
430  mitk::DataNode *dataNode = this->TreeItemFromIndex(index)->GetDataNode();
431 
432  // get name of treeItem (may also be edited)
433  QString nodeName;
434  if (DicomPropertiesExists(*dataNode))
435  {
436  mitk::BaseProperty *seriesDescription =
437  (dataNode->GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0008, 0x103e).c_str()));
438  mitk::BaseProperty *studyDescription =
439  (dataNode->GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0008, 0x1030).c_str()));
440  mitk::BaseProperty *patientsName =
441  (dataNode->GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0010, 0x0010).c_str()));
442 
443  mitk::BaseProperty *seriesDescription_deprecated = (dataNode->GetProperty("dicom.series.SeriesDescription"));
444  mitk::BaseProperty *studyDescription_deprecated = (dataNode->GetProperty("dicom.study.StudyDescription"));
445  mitk::BaseProperty *patientsName_deprecated = (dataNode->GetProperty("dicom.patient.PatientsName"));
446 
447  if (patientsName)
448  {
449  nodeName += QFile::encodeName(patientsName->GetValueAsString().c_str()) + "\n";
450  nodeName += QFile::encodeName(studyDescription->GetValueAsString().c_str()) + "\n";
451  nodeName += QFile::encodeName(seriesDescription->GetValueAsString().c_str());
452  }
453  else
454  {
455  nodeName += QFile::encodeName(patientsName_deprecated->GetValueAsString().c_str()) + "\n";
456  nodeName += QFile::encodeName(studyDescription_deprecated->GetValueAsString().c_str()) + "\n";
457  nodeName += QFile::encodeName(seriesDescription_deprecated->GetValueAsString().c_str());
458  }
459  }
460  else
461  {
462  nodeName = QFile::encodeName(dataNode->GetName().c_str());
463  }
464  if (nodeName.isEmpty())
465  {
466  nodeName = "unnamed";
467  }
468 
469  if (role == Qt::DisplayRole)
470  return nodeName;
471  else if (role == Qt::ToolTipRole)
472  return nodeName;
473  else if (role == Qt::DecorationRole)
474  {
476  return nodeDescriptor->GetIcon();
477  }
478  else if (role == Qt::CheckStateRole)
479  {
480  return dataNode->IsVisible(0);
481  }
482  else if (role == QmitkDataNodeRole)
483  {
484  return QVariant::fromValue<mitk::DataNode::Pointer>(mitk::DataNode::Pointer(dataNode));
485  }
486  else if (role == QmitkDataNodeRawPointerRole)
487  {
488  return QVariant::fromValue<mitk::DataNode *>(dataNode);
489  }
490 
491  return QVariant();
492 }
493 
494 bool QmitkDataStorageTreeModel::DicomPropertiesExists(const mitk::DataNode &node) const
495 {
496  bool propertiesExists = false;
497 
498  mitk::BaseProperty *seriesDescription_deprecated = (node.GetProperty("dicom.series.SeriesDescription"));
499  mitk::BaseProperty *studyDescription_deprecated = (node.GetProperty("dicom.study.StudyDescription"));
500  mitk::BaseProperty *patientsName_deprecated = (node.GetProperty("dicom.patient.PatientsName"));
501  mitk::BaseProperty *seriesDescription =
502  (node.GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0008, 0x103e).c_str()));
503  mitk::BaseProperty *studyDescription =
504  (node.GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0008, 0x1030).c_str()));
505  mitk::BaseProperty *patientsName = (node.GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0010, 0x0010).c_str()));
506 
507  if (patientsName != NULL && studyDescription != NULL && seriesDescription != NULL)
508  {
509  if ((!patientsName->GetValueAsString().empty()) && (!studyDescription->GetValueAsString().empty()) &&
510  (!seriesDescription->GetValueAsString().empty()))
511  {
512  propertiesExists = true;
513  }
514  }
515 
517  if (patientsName_deprecated != NULL && studyDescription_deprecated != NULL && seriesDescription_deprecated != NULL)
518  {
519  if ((!patientsName_deprecated->GetValueAsString().empty()) &&
520  (!studyDescription_deprecated->GetValueAsString().empty()) &&
521  (!seriesDescription_deprecated->GetValueAsString().empty()))
522  {
523  propertiesExists = true;
524  }
525  }
526 
527  return propertiesExists;
528 }
529 
530 QVariant QmitkDataStorageTreeModel::headerData(int /*section*/, Qt::Orientation orientation, int role) const
531 {
532  if (orientation == Qt::Horizontal && role == Qt::DisplayRole && m_Root)
533  return QString::fromStdString(m_Root->GetDataNode()->GetName());
534 
535  return QVariant();
536 }
537 
539 {
540  if (m_DataStorage != _DataStorage) // dont take the same again
541  {
542  if (m_DataStorage.IsNotNull())
543  {
544  // remove Listener for the data storage itself
547 
548  // remove listeners for the nodes
552 
556 
560  }
561 
562  // take over the new data storage
563  m_DataStorage = _DataStorage;
564 
565  // delete the old root (if necessary, create new)
566  if (m_Root)
567  m_Root->Delete();
569  rootDataNode->SetName("Data Manager");
570  m_Root = new TreeItem(rootDataNode, 0);
571  this->beginResetModel();
572  this->endResetModel();
573 
574  if (m_DataStorage.IsNotNull())
575  {
576  // add Listener for the data storage itself
579 
580  // add listeners for the nodes
583 
587 
591 
593 
594  // finally add all nodes to the model
595  this->Update();
596  }
597  }
598 }
599 
600 void QmitkDataStorageTreeModel::SetDataStorageDeleted(const itk::Object * /*_DataStorage*/)
601 {
602  this->SetDataStorage(0);
603 }
604 
605 void QmitkDataStorageTreeModel::AddNodeInternal(const mitk::DataNode *node)
606 {
607  if (node == 0 || m_DataStorage.IsNull() || !m_DataStorage->Exists(node) || m_Root->Find(node) != 0)
608  return;
609 
610  // find out if we have a root node
611  TreeItem *parentTreeItem = m_Root;
612  QModelIndex index;
613  mitk::DataNode *parentDataNode = this->GetParentNode(node);
614 
615  if (parentDataNode) // no top level data node
616  {
617  parentTreeItem = m_Root->Find(parentDataNode); // find the corresponding tree item
618  if (!parentTreeItem)
619  {
620  this->AddNode(parentDataNode);
621  parentTreeItem = m_Root->Find(parentDataNode);
622  if (!parentTreeItem)
623  return;
624  }
625 
626  // get the index of this parent with the help of the grand parent
627  index = this->createIndex(parentTreeItem->GetIndex(), 0, parentTreeItem);
628  }
629 
630  // add node
632  {
633  // emit beginInsertRows event
634  beginInsertRows(index, 0, 0);
635  parentTreeItem->InsertChild(new TreeItem(const_cast<mitk::DataNode *>(node)), 0);
636  }
637  else
638  {
639  beginInsertRows(index, parentTreeItem->GetChildCount(), parentTreeItem->GetChildCount());
640  new TreeItem(const_cast<mitk::DataNode *>(node), parentTreeItem);
641  }
642 
643  // emit endInsertRows event
644  endInsertRows();
645 
646  this->AdjustLayerProperty();
647 }
648 
650 {
651  if (node == 0 || m_BlockDataStorageEvents || m_DataStorage.IsNull() || !m_DataStorage->Exists(node) ||
652  m_Root->Find(node) != 0)
653  return;
654 
655  this->AddNodeInternal(node);
656 }
657 
659 {
660  m_PlaceNewNodesOnTop = _PlaceNewNodesOnTop;
661 }
662 
663 void QmitkDataStorageTreeModel::RemoveNodeInternal(const mitk::DataNode *node)
664 {
665  if (!m_Root)
666  return;
667 
668  TreeItem *treeItem = m_Root->Find(node);
669  if (!treeItem)
670  return; // return because there is no treeitem containing this node
671 
672  TreeItem *parentTreeItem = treeItem->GetParent();
673  QModelIndex parentIndex = this->IndexFromTreeItem(parentTreeItem);
674 
675  // emit beginRemoveRows event (QModelIndex is empty because we dont have a tree model)
676  this->beginRemoveRows(parentIndex, treeItem->GetIndex(), treeItem->GetIndex());
677 
678  // remove node
679  std::vector<TreeItem *> children = treeItem->GetChildren();
680  delete treeItem;
681 
682  // emit endRemoveRows event
683  endRemoveRows();
684 
685  // move all children of deleted node into its parent
686  for (std::vector<TreeItem *>::iterator it = children.begin(); it != children.end(); it++)
687  {
688  // emit beginInsertRows event
689  beginInsertRows(parentIndex, parentTreeItem->GetChildCount(), parentTreeItem->GetChildCount());
690 
691  // add nodes again
692  parentTreeItem->AddChild(*it);
693 
694  // emit endInsertRows event
695  endInsertRows();
696  }
697 
698  this->AdjustLayerProperty();
699 }
700 
702 {
703  if (node == 0 || m_BlockDataStorageEvents)
704  return;
705 
706  this->RemoveNodeInternal(node);
707 }
708 
710 {
711  TreeItem *treeItem = m_Root->Find(node);
712  if (treeItem)
713  {
714  TreeItem *parentTreeItem = treeItem->GetParent();
715  // as the root node should not be removed one should always have a parent item
716  if (!parentTreeItem)
717  return;
718  QModelIndex index = this->createIndex(treeItem->GetIndex(), 0, treeItem);
719 
720  // now emit the dataChanged signal
721  emit dataChanged(index, index);
722  }
723 }
724 
726 {
727  mitk::DataNode *dataNode = 0;
728 
730 
731  if (_Sources->Size() > 0)
732  dataNode = _Sources->front();
733 
734  return dataNode;
735 }
736 
737 bool QmitkDataStorageTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
738 {
739  mitk::DataNode *dataNode = this->TreeItemFromIndex(index)->GetDataNode();
740  if (!dataNode)
741  return false;
742 
743  if (role == Qt::EditRole && !value.toString().isEmpty())
744  {
745  dataNode->SetStringProperty("name", value.toString().toStdString().c_str());
746 
747  mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>(dataNode->GetData());
748 
749  if (planarFigure != NULL)
751  }
752  else if (role == Qt::CheckStateRole)
753  {
754  // Please note: value.toInt() returns 2, independentely from the actual checkstate of the index element.
755  // Therefore the checkstate is being estimated again here.
756 
757  QVariant qcheckstate = index.data(Qt::CheckStateRole);
758  int checkstate = qcheckstate.toInt();
759  bool isVisible = bool(checkstate);
760  dataNode->SetVisibility(!isVisible);
762  }
763  // inform listeners about changes
764  emit dataChanged(index, index);
765  return true;
766 }
767 
769  Qt::Orientation /*orientation*/,
770  const QVariant & /* value */,
771  int /*role = Qt::EditRole*/)
772 {
773  return false;
774 }
775 
777 {
779  std::vector<TreeItem *> vec;
780  this->TreeToVector(m_Root, vec);
781 
782  int i = vec.size() - 1;
783  for (std::vector<TreeItem *>::const_iterator it = vec.begin(); it != vec.end(); ++it)
784  {
785  mitk::DataNode::Pointer dataNode = (*it)->GetDataNode();
786  bool fixedLayer = false;
787 
788  if (!(dataNode->GetBoolProperty("fixedLayer", fixedLayer) && fixedLayer))
789  dataNode->SetIntProperty("layer", i);
790 
791  --i;
792  }
794 }
795 
796 void QmitkDataStorageTreeModel::TreeToVector(TreeItem *parent, std::vector<TreeItem *> &vec) const
797 {
798  TreeItem *current;
799  for (int i = 0; i < parent->GetChildCount(); ++i)
800  {
801  current = parent->GetChild(i);
802  this->TreeToVector(current, vec);
803  vec.push_back(current);
804  }
805 }
806 
808 {
809  if (item == m_Root)
810  return QModelIndex();
811  else
812  return this->createIndex(item->GetIndex(), 0, item);
813 }
814 
815 QList<mitk::DataNode::Pointer> QmitkDataStorageTreeModel::GetNodeSet() const
816 {
817  QList<mitk::DataNode::Pointer> res;
818  if (m_Root)
819  this->TreeToNodeSet(m_Root, res);
820 
821  return res;
822 }
823 
824 void QmitkDataStorageTreeModel::TreeToNodeSet(TreeItem *parent, QList<mitk::DataNode::Pointer> &vec) const
825 {
826  TreeItem *current;
827  for (int i = 0; i < parent->GetChildCount(); ++i)
828  {
829  current = parent->GetChild(i);
830  vec.push_back(current->GetDataNode());
831  this->TreeToNodeSet(current, vec);
832  }
833 }
834 
836 {
837  if (m_Root)
838  {
839  TreeItem *item = m_Root->Find(node);
840  if (item)
841  return this->IndexFromTreeItem(item);
842  }
843  return QModelIndex();
844 }
845 
846 QList<QmitkDataStorageTreeModel::TreeItem *> QmitkDataStorageTreeModel::ToTreeItemPtrList(const QMimeData *mimeData)
847 {
848  if (mimeData == NULL || !mimeData->hasFormat(QmitkMimeTypes::DataStorageTreeItemPtrs))
849  {
850  return QList<TreeItem *>();
851  }
853 }
854 
855 QList<QmitkDataStorageTreeModel::TreeItem *> QmitkDataStorageTreeModel::ToTreeItemPtrList(const QByteArray &ba)
856 {
857  QList<TreeItem *> result;
858  QDataStream ds(ba);
859  while (!ds.atEnd())
860  {
861  quintptr treeItemPtr;
862  ds >> treeItemPtr;
863  result.push_back(reinterpret_cast<TreeItem *>(treeItemPtr));
864  }
865  return result;
866 }
867 
869  : m_Parent(_Parent), m_DataNode(_DataNode)
870 {
871  if (m_Parent)
872  m_Parent->AddChild(this);
873 }
874 
876 {
877  if (m_Parent)
878  m_Parent->RemoveChild(this);
879 }
880 
882 {
883  while (m_Children.size() > 0)
884  delete m_Children.back();
885 
886  delete this;
887 }
888 
890 {
892  if (_DataNode)
893  {
894  if (m_DataNode == _DataNode)
895  item = const_cast<TreeItem *>(this);
896  else
897  {
898  for (std::vector<TreeItem *>::const_iterator it = m_Children.begin(); it != m_Children.end(); ++it)
899  {
900  if (item)
901  break;
902  item = (*it)->Find(_DataNode);
903  }
904  }
905  }
906  return item;
907 }
908 
910 {
911  std::vector<TreeItem *>::const_iterator it = std::find(m_Children.begin(), m_Children.end(), item);
912  return it != m_Children.end() ? std::distance(m_Children.begin(), it) : -1;
913 }
914 
916 {
917  return (m_Children.size() > 0 && index >= 0 && index < (int)m_Children.size()) ? m_Children.at(index) : 0;
918 }
919 
921 {
922  this->InsertChild(item);
923 }
924 
926 {
927  std::vector<TreeItem *>::iterator it = std::find(m_Children.begin(), m_Children.end(), item);
928  if (it != m_Children.end())
929  {
930  m_Children.erase(it);
931  item->SetParent(0);
932  }
933 }
934 
936 {
937  return m_Children.size();
938 }
939 
941 {
942  if (m_Parent)
943  return m_Parent->IndexOfChild(this);
944 
945  return 0;
946 }
947 
949 {
950  return m_Parent;
951 }
952 
954 {
955  return m_DataNode;
956 }
957 
959 {
960  std::vector<TreeItem *>::iterator it = std::find(m_Children.begin(), m_Children.end(), item);
961  if (it == m_Children.end())
962  {
963  if (m_Children.size() > 0 && index >= 0 && index < (int)m_Children.size())
964  {
965  it = m_Children.begin();
966  std::advance(it, index);
967  m_Children.insert(it, item);
968  }
969  else
970  m_Children.push_back(item);
971 
972  // add parent if necessary
973  if (item->GetParent() != this)
974  item->SetParent(this);
975  }
976 }
977 
978 std::vector<QmitkDataStorageTreeModel::TreeItem *> QmitkDataStorageTreeModel::TreeItem::GetChildren() const
979 {
980  return m_Children;
981 }
982 
984 {
985  m_Parent = _Parent;
986  if (m_Parent)
987  m_Parent->AddChild(this);
988 }
989 
991 {
992  if (m_DataStorage.IsNotNull())
993  {
994  this->beginResetModel();
995  this->endResetModel();
996 
998 
999  for (mitk::DataStorage::SetOfObjects::const_iterator it = _NodeSet->begin(); it != _NodeSet->end(); it++)
1000  {
1001  // save node
1002  this->AddNodeInternal(*it);
1003  }
1004  }
1005 }
1006 
1008 {
1009  m_AllowHierarchyChange = allowHierarchyChange;
1010 }
static QMimeData * mimeDataFromModelIndexList(const QModelIndexList &indexes)
void RemoveListener(const AbstractDelegate &delegate) const
Definition: mitkMessage.h:397
virtual void Add(mitk::DataNode *node, const mitk::DataStorage::SetOfObjects *parents=nullptr)=0
Adds a DataNode containing a data object to its internal storage.
virtual bool InitializeViews(const BaseGeometry *geometry, RequestType type=REQUEST_UPDATE_ALL, bool preserveRoughOrientationInWorldSpace=false)
void AddListener(const AbstractDelegate &delegate) const
Definition: mitkMessage.h:378
void SetDataStorage(mitk::DataStorage *_DataStorage)
virtual void SetNodeModified(const mitk::DataNode *node)
int IndexOfChild(const TreeItem *item) const
Data management class that handles 'was created by' relations.
QmitkNodeQmitkNodeDescriptor is Decorator class for the mitk::DataNode which enhances certain mitk::D...
void SetVisibility(bool visible, const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="visible")
Convenience method for setting visibility properties (instances of BoolProperty)
QModelIndex parent(const QModelIndex &index) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
void SetAllowHierarchyChange(bool allowHierarchyChange)
Set whether to allow hierarchy changes by dragging and dropping.
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
itkObjectEvent ObjectDelete
AddEvent is emitted when the object pointed to gets deleted.
std::string MITKCORE_EXPORT GeneratePropertyNameForDICOMTag(unsigned int group, unsigned int element)
void TreeToNodeSet(TreeItem *parent, QList< mitk::DataNode::Pointer > &vec) const
Qt::DropActions supportedDropActions() const override
static QList< mitk::DataNode * > ToDataNodePtrList(const QByteArray &ba)
bool IsNotNull() const
bool m_BlockDataStorageEvents
Flag to block the data storage events if nodes are added/removed by this class.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
Qt::ItemFlags flags(const QModelIndex &index) const override
static const QString DataNodePtrs
mitk::BaseProperty * GetProperty(const char *propertyKey, const mitk::BaseRenderer *renderer=nullptr) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList of the rendere...
void InsertChild(TreeItem *item, int index=-1)
TreeItem * TreeItemFromIndex(const QModelIndex &index) const
void SetParent(TreeItem *_Parent)
Sets the parent on the treeitem.
virtual void AddNode(const mitk::DataNode *node)
itk::SmartPointer< const Self > ConstPointer
void SetPlaceNewNodesOnTop(bool _PlaceNewNodesOnTop)
virtual SetOfObjects::ConstPointer GetSources(const mitk::DataNode *node, const NodePredicateBase *condition=nullptr, bool onlyDirectSources=true) const =0
returns a set of source objects for a given node that meet the given condition(s).
ObjectType * GetPointer() const
bool IsVisible(const mitk::BaseRenderer *renderer, const char *propertyKey="visible", bool defaultIsOn=true) const
Convenience access method for visibility properties (instances of BoolProperty). Return value is the ...
Definition: mitkDataNode.h:453
itk::SmartPointer< Self > Pointer
Definition: mitkDataNode.h:81
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
virtual SetOfObjects::ConstPointer GetAll() const =0
returns a set of all data objects that are stored in the data storage
Abstract base class for properties.
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role=Qt::EditRole) override
mitk::DataStorage::Pointer m_DataStorage
QModelIndex IndexFromTreeItem(TreeItem *) const
SetOfObjects::ConstPointer GetSubset(const NodePredicateBase *condition) const
returns a set of data objects that meet the given condition(s)
static Pointer New()
static RenderingManager * GetInstance()
mitk::WeakPointer< mitk::DataStorage > m_DataStorage
TreeItem(mitk::DataNode *_DataNode, TreeItem *_Parent=0)
virtual QIcon GetIcon() const
virtual std::string GetValueAsString() const
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
DataStorageEvent AddNodeEvent
AddEvent is emitted whenever a new node has been added to the DataStorage.
mitk::DataNode::Pointer GetNode(const QModelIndex &index) const
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
mitk::DataNode::Pointer GetDataNode() const
bool IsNull() const
QmitkNodeDescriptor * GetDescriptor(const mitk::DataNode *_Node) const
void SetDataStorageDeleted(const itk::Object *_DataStorage)
static T min(T x, T y)
Definition: svm.cpp:67
DataStorageEvent RemoveNodeEvent
RemoveEvent is emitted directly before a node is removed from the DataStorage.
virtual QList< mitk::DataNode::Pointer > GetNodeSet() const
std::vector< TreeItem * > GetChildren() const
const mitk::DataStorage::Pointer GetDataStorage() const
Base-class for geometric planar (2D) figures, such as lines, circles, rectangles, polygons...
mitk::NodePredicateBase::Pointer m_Predicate
void SetStringProperty(const char *propertyKey, const char *string, const mitk::BaseRenderer *renderer=nullptr)
Convenience method for setting string properties (instances of StringProperty)
DataStorageEvent ChangedNodeEvent
ChangedEvent is emitted directly after a node was changed.
virtual void RemoveNode(const mitk::DataNode *node)
void TreeToVector(TreeItem *parent, std::vector< TreeItem * > &vec) const
Qt::DropActions supportedDragActions() const override
QModelIndex GetIndex(const mitk::DataNode *) const
QList< TreeItem * > ToTreeItemPtrList(const QMimeData *mimeData)
QStringList mimeTypes() const override
virtual bool Exists(const mitk::DataNode *node) const =0
Checks if a node exists in the DataStorage.
virtual void Remove(const mitk::DataNode *node)=0
Removes node from the DataStorage.
QMimeData * mimeData(const QModelIndexList &indexes) const override
TreeItem * Find(const mitk::DataNode *_DataNode) const
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
mitk::DataNode * GetParentNode(const mitk::DataNode *node) const
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
static QmitkNodeDescriptorManager * GetInstance()
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QmitkDataStorageTreeModel(mitk::DataStorage *_DataStorage, bool _PlaceNewNodesOnTop=false, QObject *parent=0)
static const QString DataStorageTreeItemPtrs