Loading...
Searching...
No Matches
RecursiveFilterProxy.hpp
1#pragma once
2#include <score/tools/Debug.hpp>
3
4#include <QFileSystemModel>
5#include <QSortFilterProxyModel>
6
7namespace Library
8{
9class RecursiveFilterProxy : public QSortFilterProxyModel
10{
11public:
12 using QSortFilterProxyModel::QSortFilterProxyModel;
13
14 const QString& pattern() const noexcept { return m_textPattern; }
15 void setPattern(const QString& p)
16 {
17 beginResetModel();
18 // auto old = m_textPattern;
19 m_textPattern = p;
20 endResetModel();
21 // if(!p.contains(old))
22 // invalidateFilter();
23 }
24
25protected:
26 QString m_textPattern;
27
28 int columnCount(const QModelIndex& parent = QModelIndex()) const override { return 1; }
29 bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const override
30 {
31 if(filterAcceptsRowItself(srcRow, srcParent))
32 {
33 return true;
34 }
35
36 // Accept if any of the parents is accepted on its own
37 for(QModelIndex parent = srcParent; parent.isValid(); parent = parent.parent())
38 if(filterAcceptsRowItself(parent.row(), parent.parent()))
39 {
40 return true;
41 }
42
43 // Accept if any of the children is accepted on its own
44 return hasAcceptedChildren(srcRow, srcParent);
45 }
46
47 bool filterAcceptsRowItself(int srcRow, const QModelIndex& srcParent) const
48 {
49 QModelIndex index = sourceModel()->index(srcRow, 0, srcParent);
50 const QVariant& data = sourceModel()->data(index);
51
52 return data.toString().contains(m_textPattern, Qt::CaseInsensitive);
53 }
54
55 bool hasAcceptedChildren(int srcRow, const QModelIndex& srcParent) const
56 {
57 QModelIndex index = sourceModel()->index(srcRow, 0, srcParent);
58
59 if(!index.isValid())
60 return false;
61
62 SCORE_ASSERT(index.model());
63 const int childCount = index.model()->rowCount(index);
64
65 if(childCount == 0)
66 return false;
67
68 for(int i = 0; i < childCount; ++i)
69 {
70 if(filterAcceptsRowItself(i, index))
71 return true;
72
73 if(hasAcceptedChildren(i, index))
74 return true;
75 }
76
77 return false;
78 }
79};
80
82{
83public:
84 using RecursiveFilterProxy::RecursiveFilterProxy;
85
86 QModelIndex fixedRootIndex{};
87
88private:
89 bool isChildOfRoot(const QModelIndex& m) const noexcept
90 {
91 if(!m.isValid())
92 {
93 return false;
94 }
95 if(m == fixedRootIndex)
96 return true;
97 if(auto parent = m.parent(); parent == fixedRootIndex)
98 {
99 return true;
100 }
101 else
102 {
103 return isChildOfRoot(parent);
104 }
105 }
106
107 QFileSystemModel* sourceModel() const noexcept
108 {
109 return static_cast<QFileSystemModel*>(QSortFilterProxyModel::sourceModel());
110 }
111 bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const override
112 {
113 const QModelIndex index = sourceModel()->index(srcRow, 0, srcParent);
114 if(!isChildOfRoot(index))
115 {
116 return false;
117 }
118
119 if(filterAcceptsRowItself(srcRow, srcParent))
120 {
121 return true;
122 }
123
124 // Accept if any of the parents is accepted on its own
125 for(QModelIndex parent = srcParent; parent.isValid(); parent = parent.parent())
126 {
127 // We went up to the root. We know that we are a child due to the startsWith.
128 if(parent == fixedRootIndex)
129 return false;
130
131 if(filterAcceptsRowItself(parent.row(), parent.parent()))
132 {
133 return true;
134 }
135 }
136
137 // Accept if any of the children is accepted on its own
138 return hasAcceptedChildren(srcRow, srcParent);
139 }
140};
141}
Definition RecursiveFilterProxy.hpp:82
Definition RecursiveFilterProxy.hpp:10