Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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