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