TreeNodeItemModel.hpp
1 #pragma once
2 #include <QAbstractItemModel>
3 
4 #include <score_lib_base_export.h>
5 
12 // TESTME
13 class TreePath;
14 class SCORE_LIB_BASE_EXPORT TreeModel : public QAbstractItemModel
15 {
16 public:
17  using QAbstractItemModel::QAbstractItemModel;
19  template <typename F>
20  void iterate(const QModelIndex& idx, const F& f)
21  {
22  if(idx.isValid())
23  f(idx);
24 
25  if(!hasChildren(idx))
26  return;
27 
28  const int rows = rowCount(idx);
29  for(int i = 0; i < rows; ++i)
30  iterate(this->index(i, 0, idx), f);
31  }
32 
33  QModelIndex convertPathToIndex(const TreePath& path) const;
34 };
35 
36 template <typename NodeType>
38 {
39 public:
40  using TreeModel::TreeModel;
41 
42  using node_type = NodeType;
43  virtual ~TreeNodeBasedItemModel() = default;
44  virtual NodeType& rootNode() = 0;
45  virtual const NodeType& rootNode() const = 0;
46 
47  NodeType& nodeFromModelIndex(const QModelIndex& index) const
48  {
49  auto n = index.isValid() ? static_cast<NodeType*>(index.internalPointer())
50  : const_cast<NodeType*>(&rootNode());
51 
52  SCORE_ASSERT(n);
53  return *n;
54  }
55 
56  QModelIndex parent(const QModelIndex& index) const final override
57  {
58  if(!index.isValid())
59  return QModelIndex();
60  if(index.model() != this)
61  return QModelIndex();
62 
63  const auto& node = nodeFromModelIndex(index);
64  auto parentNode = node.parent();
65 
66  if(!parentNode)
67  return QModelIndex();
68 
69  auto grandparentNode = parentNode->parent();
70 
71  if(!grandparentNode)
72  return QModelIndex();
73 
74  const int rowParent = grandparentNode->indexOfChild(parentNode);
75  if(rowParent == -1)
76  return QModelIndex();
77 
78  return createIndex(rowParent, 0, parentNode);
79  }
80 
81  QModelIndex index(int row, int column, const QModelIndex& parent) const final override
82  {
83  if(!hasIndex(row, column, parent))
84  return QModelIndex();
85 
86  auto& parentItem = nodeFromModelIndex(parent);
87 
88  if(parentItem.hasChild(row))
89  return createIndex(row, column, &parentItem.childAt(row));
90  else
91  return QModelIndex();
92  }
93 
94  int rowCount(const QModelIndex& parent) const final override
95  {
96  if(parent.column() > 0)
97  return 0;
98 
99  const auto& parentNode = nodeFromModelIndex(parent);
100  return parentNode.childCount();
101  }
102 
103  bool hasChildren(const QModelIndex& parent) const final override
104  {
105  const auto& parentNode = nodeFromModelIndex(parent);
106  return parentNode.childCount() > 0;
107  }
108 };
Definition: TreeNodeItemModel.hpp:15
void iterate(const QModelIndex &idx, const F &f)
idx: should be the root index of the view
Definition: TreeNodeItemModel.hpp:20
Definition: TreeNodeItemModel.hpp:38
Path in a tree of QAbstractItemModel objects.
Definition: TreePath.hpp:34