Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
QmitkDataStorageSimpleTreeModel.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 
16 
17 // qt widgets module
18 #include "QmitkCustomVariants.h"
19 #include "QmitkEnums.h"
20 
22  : QmitkAbstractDataStorageModel(parent), m_Root(nullptr)
23 {
24  ResetTree();
25 }
26 
28 {
29  m_Root->Delete();
30  m_Root = nullptr;
31 };
32 
33 void QmitkDataStorageSimpleTreeModel::ResetTree()
34 {
36  rootDataNode->SetName("Data Storage");
37  m_Root = new TreeItem(rootDataNode, nullptr);
38 }
39 
41 {
42  if (m_Root)
43  {
44  m_Root->Delete();
45  }
46 
47  beginResetModel();
48  ResetTree();
49  UpdateModelData();
50  endResetModel();
51 }
52 
54 {
55  beginResetModel();
56  ResetTree();
57  UpdateModelData();
58  endResetModel();
59 }
60 
62 {
63  if (node == nullptr || m_DataStorage.IsExpired() || !m_DataStorage.Lock()->Exists(node) ||
64  m_Root->Find(node) != nullptr)
65  return;
66 
67  this->AddNodeInternal(node);
68 }
69 
71 {
72  TreeItem *treeItem = m_Root->Find(node);
73  if (treeItem)
74  {
75  TreeItem *parentTreeItem = treeItem->GetParent();
76  // as the root node should not be removed one should always have a parent item
77  if (!parentTreeItem)
78  return;
79  QModelIndex index = this->createIndex(treeItem->GetIndex(), 0, treeItem);
80 
81  // now emit the dataChanged signal
82  emit dataChanged(index, index);
83  }
84 }
85 
87 {
88  if (node == nullptr || !m_Root)
89  return;
90 
91  TreeItem *treeItem = m_Root->Find(node);
92  if (!treeItem)
93  return; // return because there is no treeitem containing this node
94 
95  TreeItem *parentTreeItem = treeItem->GetParent();
96  QModelIndex parentIndex = this->IndexFromTreeItem(parentTreeItem);
97 
98  // emit beginRemoveRows event (QModelIndex is empty because we dont have a tree model)
99  this->beginRemoveRows(parentIndex, treeItem->GetIndex(), treeItem->GetIndex());
100 
101  // remove node
102  std::vector<TreeItem *> children = treeItem->GetChildren();
103  m_TreeItems.remove(treeItem);
104  delete treeItem; //delete in tree
105 
106  if (!children.empty())
107  {
108  //if not empty we have to rebuild the whole representation,
109  //because the children could be now top level, or at another
110  //source/parent.
111  this->UpdateModelData();
112  }
113 }
114 
115 QModelIndex QmitkDataStorageSimpleTreeModel::index(int row, int column, const QModelIndex &parent) const
116 {
117  TreeItem *parentItem;
118 
119  if (!parent.isValid() || parent.model() != this)
120  parentItem = m_Root;
121  else
122  parentItem = static_cast<TreeItem *>(parent.internalPointer());
123 
124  if (parentItem)
125  {
126  TreeItem *childItem = parentItem->GetChild(row);
127  if (childItem)
128  return createIndex(row, column, childItem);
129  }
130 
131  return QModelIndex();
132 }
133 
134 QModelIndex QmitkDataStorageSimpleTreeModel::parent(const QModelIndex &child) const
135 {
136  if (!child.isValid() || !m_Root || child.model() != this)
137  return QModelIndex();
138 
139  TreeItem *childItem = this->TreeItemFromIndex(child);
140 
141  if (!childItem)
142  return QModelIndex();
143 
144  TreeItem *parentItem = childItem->GetParent();
145 
146  if (parentItem == m_Root)
147  return QModelIndex();
148 
149  return this->createIndex(parentItem->GetIndex(), 0, parentItem);
150 }
151 
152 QmitkDataStorageSimpleTreeModel::TreeItem *QmitkDataStorageSimpleTreeModel::TreeItemFromIndex(
153  const QModelIndex &index) const
154 {
155  if (index.isValid() && index.model() == this)
156  {
157  auto item = static_cast<TreeItem *>(index.internalPointer());
158  auto finding = std::find(std::begin(m_TreeItems), std::end(m_TreeItems), item);
159  if (finding == std::end(m_TreeItems))
160  {
161  return nullptr;
162  }
163  return item;
164  }
165  else
166  return m_Root;
167 }
168 
170 {
171  TreeItem *parentTreeItem = this->TreeItemFromIndex(parent);
172  if (parentTreeItem)
173  return parentTreeItem->GetChildCount();
174  else
175  return 0;
176 }
177 
178 int QmitkDataStorageSimpleTreeModel::columnCount(const QModelIndex &/*parent*/) const
179 {
180  return 1;
181 }
182 
183 QVariant QmitkDataStorageSimpleTreeModel::data(const QModelIndex &index, int role) const
184 {
185  if (!index.isValid() || index.model() != this)
186  {
187  return QVariant();
188  }
189 
190  auto treeItem = this->TreeItemFromIndex(index);
191  if (!treeItem)
192  return QVariant();
193 
194  mitk::DataNode *dataNode = treeItem->GetDataNode();
195 
196  QString nodeName = QString::fromStdString(dataNode->GetName());
197  if (nodeName.isEmpty())
198  {
199  nodeName = "unnamed";
200  }
201 
202  if (role == Qt::DisplayRole)
203  return nodeName;
204  else if (role == Qt::ToolTipRole)
205  return nodeName;
206  else if (role == Qt::DecorationRole)
207  {
209  return nodeDescriptor->GetIcon(dataNode);
210  }
211  else if (role == QmitkDataNodeRole)
212  {
213  return QVariant::fromValue<mitk::DataNode::Pointer>(mitk::DataNode::Pointer(dataNode));
214  }
215  else if (role == QmitkDataNodeRawPointerRole)
216  {
217  return QVariant::fromValue<mitk::DataNode *>(dataNode);
218  }
219 
220  return QVariant();
221 }
222 
223 bool QmitkDataStorageSimpleTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
224 {
225  if (!index.isValid() || index.model() != this)
226  return false;
227 
228  auto treeItem = this->TreeItemFromIndex(index);
229  if (!treeItem)
230  return false;
231 
232  mitk::DataNode *dataNode = treeItem->GetDataNode();
233  if (!dataNode)
234  return false;
235 
236  if (role == Qt::EditRole && !value.toString().isEmpty())
237  {
238  dataNode->SetName(value.toString().toStdString().c_str());
239  }
240  else if (role == Qt::CheckStateRole)
241  {
242  // Please note: value.toInt() returns 2, independentely from the actual checkstate of the index element.
243  // Therefore the checkstate is being estimated again here.
244 
245  QVariant qcheckstate = index.data(Qt::CheckStateRole);
246  int checkstate = qcheckstate.toInt();
247  bool isVisible = bool(checkstate);
248  dataNode->SetVisibility(!isVisible);
249  }
250  // inform listeners about changes
251  emit dataChanged(index, index);
252  return true;
253 }
254 
255 QVariant QmitkDataStorageSimpleTreeModel::headerData(int /*section*/, Qt::Orientation orientation, int role) const
256 {
257  if (orientation == Qt::Horizontal && role == Qt::DisplayRole && m_Root)
258  return QString::fromStdString(m_Root->GetDataNode()->GetName());
259 
260  return QVariant();
261 }
262 
263 Qt::ItemFlags QmitkDataStorageSimpleTreeModel::flags(const QModelIndex &index) const
264 {
265  if (index.isValid() && index.model() == this)
266  {
267  auto treeItem = this->TreeItemFromIndex(index);
268  if (!treeItem)
269  return Qt::NoItemFlags;
270 
271  const auto dataNode = treeItem->GetDataNode();
272  if (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(dataNode))
273  {
274  return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
275  }
276  else
277  {
278  return Qt::NoItemFlags;
279  }
280 
281  }
282 
283  return Qt::NoItemFlags;
284 }
285 
286 mitk::DataNode *QmitkDataStorageSimpleTreeModel::GetParentNode(const mitk::DataNode *node) const
287 {
288  mitk::DataNode *dataNode = nullptr;
289 
290  mitk::DataStorage::SetOfObjects::ConstPointer _Sources = m_DataStorage.Lock()->GetSources(node);
291 
292  if (_Sources->Size() > 0)
293  dataNode = _Sources->front();
294 
295  return dataNode;
296 }
297 
298 void QmitkDataStorageSimpleTreeModel::AddNodeInternal(const mitk::DataNode *node)
299 {
300  if (node == nullptr || m_DataStorage.IsExpired() || !m_DataStorage.Lock()->Exists(node) || m_Root->Find(node) != nullptr)
301  return;
302 
303  // find out if we have a root node
304  TreeItem *parentTreeItem = m_Root;
305  QModelIndex index;
306  mitk::DataNode *parentDataNode = this->GetParentNode(node);
307 
308  if (parentDataNode) // no top level data node
309  {
310  parentTreeItem = m_Root->Find(parentDataNode); // find the corresponding tree item
311  if (!parentTreeItem)
312  {
313  this->NodeAdded(parentDataNode);
314  parentTreeItem = m_Root->Find(parentDataNode);
315  if (!parentTreeItem)
316  return;
317  }
318 
319  // get the index of this parent with the help of the grand parent
320  index = this->createIndex(parentTreeItem->GetIndex(), 0, parentTreeItem);
321  }
322 
323  int firstRowWithASiblingBelow = 0;
324  int nodeLayer = -1;
325  node->GetIntProperty("layer", nodeLayer);
326  for (TreeItem *siblingTreeItem : parentTreeItem->GetChildren())
327  {
328  int siblingLayer = -1;
329  if (mitk::DataNode *siblingNode = siblingTreeItem->GetDataNode())
330  {
331  siblingNode->GetIntProperty("layer", siblingLayer);
332  }
333  if (nodeLayer > siblingLayer)
334  {
335  break;
336  }
337  ++firstRowWithASiblingBelow;
338  }
339  beginInsertRows(index, firstRowWithASiblingBelow, firstRowWithASiblingBelow);
340  auto newNode = new TreeItem(const_cast<mitk::DataNode *>(node));
341  parentTreeItem->InsertChild(newNode, firstRowWithASiblingBelow);
342  m_TreeItems.push_back(newNode);
343 
344  endInsertRows();
345 }
346 
347 QModelIndex QmitkDataStorageSimpleTreeModel::IndexFromTreeItem(TreeItem *item) const
348 {
349  if (item == m_Root)
350  return QModelIndex();
351  else
352  return this->createIndex(item->GetIndex(), 0, item);
353 }
354 
355 void QmitkDataStorageSimpleTreeModel::UpdateModelData()
356 {
357  if (!m_DataStorage.IsExpired())
358  {
359  auto nodeset = m_DataStorage.Lock()->GetAll();
360  if (m_NodePredicate != nullptr)
361  {
362  nodeset = m_DataStorage.Lock()->GetSubset(m_NodePredicate);
363  }
364 
365  for (const auto& node : *nodeset)
366  {
367  this->AddNodeInternal(node);
368  }
369  }
370 }
int columnCount(const QModelIndex &parent=QModelIndex()) const override
itk::SmartPointer< T > Lock() const
Decorator class for mitk::DataNode.
void SetVisibility(bool visible, const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="visible")
Convenience method for setting visibility properties (instances of BoolProperty)
QmitkDataStorageTreeModelInternalItem TreeItem
bool GetIntProperty(const char *propertyKey, int &intValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for int properties (instances of IntProperty)
itk::SmartPointer< Self > Pointer
Definition: mitkDataNode.h:71
QmitkNodeDescriptor * GetDescriptor(const mitk::DataNode *node) const
void NodeAdded(const mitk::DataNode *node) override
mitk::NodePredicateBase::ConstPointer m_NodePredicate
QmitkDataStorageTreeModelInternalItem * GetChild(int index) const
static Pointer New()
bool IsExpired() const noexcept
virtual void SetName(const char *name)
Extra convenience access method to set the name of an object.
Definition: mitkDataNode.h:404
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
QmitkDataStorageTreeModelInternalItem * GetParent() const
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QModelIndex parent(const QModelIndex &child) const override
void NodeChanged(const mitk::DataNode *node) override
QmitkDataStorageTreeModelInternalItem * Find(const mitk::DataNode *_DataNode) const
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
std::vector< QmitkDataStorageTreeModelInternalItem * > GetChildren() const
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
virtual QIcon GetIcon(const mitk::DataNode *node) const
void NodeRemoved(const mitk::DataNode *node) override
Qt::ItemFlags flags(const QModelIndex &index) const override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
static QmitkNodeDescriptorManager * GetInstance()
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57
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:369
mitk::WeakPointer< mitk::DataStorage > m_DataStorage
void InsertChild(QmitkDataStorageTreeModelInternalItem *item, int index=-1)