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
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