Medical Imaging Interaction Toolkit  2018.4.99-b7f3afaa
Medical Imaging Interaction Toolkit
berryViewTreeModel.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 #include "berryViewTreeModel.h"
14 
15 #include "berryIViewRegistry.h"
16 #include "berryIViewCategory.h"
17 #include "berryIWorkbench.h"
18 #include "berryIWorkbenchWindow.h"
19 #include "berryIWorkbenchPage.h"
20 
21 #include "internal/intro/berryIntroConstants.h"
22 #include "internal/berryKeywordRegistry.h"
23 
24 #include <QIcon>
25 #include <QBrush>
26 
27 namespace berry {
28 
29 // --------------------------- Tree Item Classes ---------------------------
30 
31 struct ViewTreeItem;
32 
33 bool CompareViewTreeItem(ViewTreeItem* item1, ViewTreeItem* item2);
34 
35 struct ViewTreeItem
36 {
37  ViewTreeItem(ViewTreeModel* model)
38  : m_parent(nullptr)
39  , m_model(model)
40  {}
41 
42  virtual ~ViewTreeItem()
43  {
44  QList<ViewTreeItem*> children = m_children;
45  if (m_parent) m_parent->removeChild(this);
46  qDeleteAll(children);
47  }
48 
49  virtual QVariant data(int role)
50  {
51  if (role == ViewTreeModel::Keywords)
52  {
53  if (m_keywordCache.isEmpty())
54  {
55  m_keywordCache = QStringList(keywordLabels().toList());
56  }
57  return m_keywordCache;
58  }
59  return QVariant();
60  }
61 
62  virtual Qt::ItemFlags flags() const
63  {
64  return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
65  }
66 
67  virtual QSet<QString> keywordLabels() const
68  {
69  return QSet<QString>();
70  }
71 
72  void appendChild(ViewTreeItem* child)
73  {
74  m_children.push_back(child);
75  child->m_parent = this;
76  qSort(m_children.begin(), m_children.end(), CompareViewTreeItem);
77  }
78 
79  void removeChild(ViewTreeItem* child)
80  {
81  m_children.removeAll(child);
82  }
83 
84  QList<ViewTreeItem*> takeChildren()
85  {
86  QList<ViewTreeItem*> children = m_children;
87  m_children.clear();
88  return children;
89  }
90 
91  ViewTreeItem* childItem(int row) const
92  {
93  if (row < 0 || row >= m_children.size()) return nullptr;
94  return m_children.at(row);
95  }
96 
97  ViewTreeItem* parentItem() const
98  {
99  return m_parent;
100  }
101 
102  int childCount() const
103  {
104  return m_children.size();
105  }
106 
107  int row() const
108  {
109  if (m_parent) return m_parent->rowIndex(this);
110  return 0;
111  }
112 
113  int rowIndex(const ViewTreeItem* child) const
114  {
115  return m_children.indexOf(const_cast<ViewTreeItem*>(child));
116  }
117 
118  QList<ViewTreeItem*> m_children;
119  ViewTreeItem* m_parent;
120  ViewTreeModel* m_model;
121 
122 private:
123 
124  QStringList m_keywordCache;
125 
126 };
127 
128 bool CompareViewTreeItem(ViewTreeItem* item1, ViewTreeItem* item2)
129 {
130  return item1->data(Qt::DisplayRole).toString() < item2->data(Qt::DisplayRole).toString();
131 }
132 
133 struct RootTreeItem : ViewTreeItem
134 {
135  RootTreeItem(ViewTreeModel* model) : ViewTreeItem(model) {}
136 
137  QVariant data(int /*role*/) override { return QVariant(); }
138 };
139 
140 struct DescriptorTreeItem : ViewTreeItem
141 {
142  DescriptorTreeItem(ViewTreeModel* model, IViewDescriptor::Pointer descriptor, ViewTreeItem* parent = nullptr);
143 
144  QVariant data(int role) override;
145 
146 protected:
147 
148  QSet<QString> keywordLabels() const override;
149 
150  IViewDescriptor::Pointer m_descriptor;
151 };
152 
153 struct CategoryTreeItem : ViewTreeItem
154 {
155  CategoryTreeItem(ViewTreeModel* model, IViewCategory::Pointer category, ViewTreeItem* parent = nullptr);
156 
157  QVariant data(int role) override;
158 
159  Qt::ItemFlags flags() const override;
160 
161 protected:
162 
163  QSet<QString> keywordLabels() const override;
164 
169  void RemoveIntroView(QList<IViewDescriptor::Pointer>& list);
170 
171 private:
172 
173  void CreateChildren();
174 
175  IViewCategory::Pointer m_category;
176 
177 };
178 
179 // --------------------------- Tree Model Classes ---------------------------
180 
181 struct ViewTreeModel::Impl
182 {
183  Impl(const IWorkbenchWindow* window)
184  : window(window)
185  , viewRegistry(*window->GetWorkbench()->GetViewRegistry())
186  {
187 
188  }
189 
190  const IWorkbenchWindow* window;
191  IViewRegistry& viewRegistry;
192 
193  QScopedPointer<RootTreeItem> rootItem;
194 };
195 
196 ViewTreeModel::ViewTreeModel(const IWorkbenchWindow* window, QObject* parent)
197  : QAbstractItemModel(parent)
198  , d(new Impl(window))
199 {
200  d->rootItem.reset(new RootTreeItem(this));
201 
202  QList<CategoryTreeItem*> categoryItems;
203 
204  QList<IViewCategory::Pointer> categories = d->viewRegistry.GetCategories();
205  for (auto category : categories)
206  {
207  if (category->GetViews().isEmpty()) continue;
208  CategoryTreeItem* categoryItem = new CategoryTreeItem(this, category);
209  if (categoryItem->childCount() == 0)
210  {
211  delete categoryItem;
212  }
213  else
214  {
215  categoryItems.push_back(categoryItem);
216  }
217  }
218 
219 
220  // if there is only one category, return it's children directly
221  if (categoryItems.size() == 1)
222  {
223  QList<ViewTreeItem*> items = categoryItems.front()->takeChildren();
224  for (auto item : items)
225  {
226  d->rootItem->appendChild(item);
227  }
228  qDeleteAll(categoryItems);
229  }
230  else
231  {
232  for (auto category : categoryItems)
233  {
234  d->rootItem->appendChild(category);
235  }
236  }
237 }
238 
240 {
241 
242 }
243 
244 QVariant ViewTreeModel::data(const QModelIndex& index, int role) const
245 {
246  if (!index.isValid()) return QVariant();
247 
248  return static_cast<ViewTreeItem*>(index.internalPointer())->data(role);
249 }
250 
251 Qt::ItemFlags ViewTreeModel::flags(const QModelIndex& index) const
252 {
253  if (!index.isValid()) return nullptr;
254 
255  return static_cast<ViewTreeItem*>(index.internalPointer())->flags();
256 }
257 
258 QVariant ViewTreeModel::headerData(int section, Qt::Orientation /*orientation*/, int role) const
259 {
260  if (role == Qt::DisplayRole && section == 0)
261  {
262  return "View";
263  }
264  return QVariant();
265 }
266 
267 QModelIndex ViewTreeModel::index(int row, int column, const QModelIndex& parent) const
268 {
269  if (!hasIndex(row, column, parent))
270  {
271  return QModelIndex();
272  }
273 
274  ViewTreeItem* parentItem = nullptr;
275  if (!parent.isValid())
276  {
277  parentItem = d->rootItem.data();
278  }
279  else
280  {
281  parentItem = static_cast<ViewTreeItem*>(parent.internalPointer());
282  }
283 
284  ViewTreeItem* childItem = parentItem->childItem(row);
285  if (childItem)
286  {
287  return createIndex(row, column, childItem);
288  }
289  return QModelIndex();
290 }
291 
292 QModelIndex ViewTreeModel::parent(const QModelIndex& child) const
293 {
294  if (!child.isValid())
295  {
296  return QModelIndex();
297  }
298 
299  ViewTreeItem* childItem = static_cast<ViewTreeItem*>(child.internalPointer());
300  ViewTreeItem* parentItem = childItem->parentItem();
301 
302  if (parentItem == d->rootItem.data())
303  {
304  return QModelIndex();
305  }
306  return createIndex(parentItem->row(), 0, parentItem);
307 }
308 
309 int ViewTreeModel::rowCount(const QModelIndex& parent) const
310 {
311  ViewTreeItem* parentItem = nullptr;
312  if (parent.column() > 0) return 0;
313 
314  if (!parent.isValid())
315  {
316  parentItem = d->rootItem.data();
317  }
318  else
319  {
320  parentItem = static_cast<ViewTreeItem*>(parent.internalPointer());
321  }
322  return parentItem->childCount();
323 }
324 
325 int ViewTreeModel::columnCount(const QModelIndex& /*parent*/) const
326 {
327  return 1;
328 }
329 
331 {
332  return d->window;
333 }
334 
335 // --------------------------- DescriptorTreeItem ---------------------------
336 
337 DescriptorTreeItem::DescriptorTreeItem(ViewTreeModel* model, IViewDescriptor::Pointer descriptor, ViewTreeItem* parent)
338  : ViewTreeItem(model)
339  , m_descriptor(descriptor)
340 {
341  if (parent) parent->appendChild(this);
342 }
343 
344 QVariant DescriptorTreeItem::data(int role)
345 {
346  if (role == Qt::DisplayRole)
347  {
348  return m_descriptor->GetLabel();
349  }
350  else if (role == Qt::DecorationRole)
351  {
352  return m_descriptor->GetImageDescriptor();
353  }
354  else if (role == Qt::ForegroundRole)
355  {
356  IWorkbenchPage::Pointer page = this->m_model->GetWorkbenchWindow()->GetActivePage();
357  if (page.IsNotNull())
358  {
359  if (page->FindViewReference(m_descriptor->GetId()).IsNotNull())
360  {
361  return QBrush(QColor(Qt::gray));
362  }
363  }
364  }
365  else if (role == ViewTreeModel::Description)
366  {
367  return m_descriptor->GetDescription();
368  }
369  else if (role == ViewTreeModel::Id)
370  {
371  return m_descriptor->GetId();
372  }
373  return ViewTreeItem::data(role);
374 }
375 
376 QSet<QString> DescriptorTreeItem::keywordLabels() const
377 {
378  KeywordRegistry* registry = KeywordRegistry::GetInstance();
379  QStringList ids = m_descriptor->GetKeywordReferences();
380  QSet<QString> keywords;
381  keywords.insert(m_descriptor->GetLabel());
382  for(auto id : ids)
383  {
384  QString label = registry->GetKeywordLabel(id);
385  for (auto keyword : label.split(' ', QString::SkipEmptyParts))
386  {
387  keywords.insert(keyword);
388  }
389  }
390  return keywords;
391 }
392 
393 // --------------------------- CategoryTreeItem ---------------------------
394 
395 CategoryTreeItem::CategoryTreeItem(ViewTreeModel* model, IViewCategory::Pointer category, ViewTreeItem* parent)
396  : ViewTreeItem(model)
397  , m_category(category)
398 {
399  if (parent) parent->appendChild(this);
400  this->CreateChildren();
401 }
402 
403 QVariant CategoryTreeItem::data(int role)
404 {
405  if (role == Qt::DisplayRole)
406  {
407  return m_category->GetLabel();
408  }
409  else if (role == Qt::DecorationRole)
410  {
411  return QIcon::fromTheme("folder");
412  }
413  else if (role == ViewTreeModel::Id)
414  {
415  return m_category->GetId();
416  }
417  return ViewTreeItem::data(role);
418 }
419 
420 Qt::ItemFlags CategoryTreeItem::flags() const
421 {
422  return Qt::ItemIsEnabled;
423 }
424 
425 QSet<QString> CategoryTreeItem::keywordLabels() const
426 {
427  QSet<QString> keywords;
428  for(auto child : this->m_children)
429  {
430  for (auto keyword : child->data(ViewTreeModel::Keywords).toStringList())
431  {
432  keywords.insert(keyword);
433  }
434  }
435  return keywords;
436 }
437 
438 void CategoryTreeItem::CreateChildren()
439 {
440  auto viewDescriptors = m_category->GetViews();
441  RemoveIntroView(viewDescriptors);
442  for(auto viewDescriptor : viewDescriptors)
443  {
444  new DescriptorTreeItem(this->m_model, viewDescriptor, this);
445  }
446 }
447 
448 void CategoryTreeItem::RemoveIntroView(QList<IViewDescriptor::Pointer>& list)
449 {
450  for (auto view = list.begin(); view != list.end();)
451  {
452  if ((*view)->GetId() == IntroConstants::INTRO_VIEW_ID)
453  {
454  view = list.erase(view);
455  }
456  else ++view;
457  }
458 }
459 
460 }
int rowCount(const QModelIndex &parent=QModelIndex()) const override
ViewTreeModel(const IWorkbenchWindow *window, QObject *parent=nullptr)
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
const IWorkbenchWindow * GetWorkbenchWindow() const
bool CompareViewTreeItem(ViewTreeItem *item1, ViewTreeItem *item2)
int columnCount(const QModelIndex &parent=QModelIndex()) const override
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
QModelIndex parent(const QModelIndex &child) const override
virtual IViewRegistry * GetViewRegistry() const =0
virtual IWorkbench * GetWorkbench() const =0