1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3#include "bookmarkfiltermodel.h"
4
5#include "bookmarkitem.h"
6#include "bookmarkmodel.h"
7
8BookmarkFilterModel::BookmarkFilterModel(QObject *parent)
9 : QAbstractProxyModel(parent)
10{
11}
12
13void BookmarkFilterModel::setSourceModel(QAbstractItemModel *_sourceModel)
14{
15 beginResetModel();
16
17 if (sourceModel) {
18 disconnect(sender: sourceModel, signal: &QAbstractItemModel::dataChanged,
19 receiver: this, slot: &BookmarkFilterModel::changed);
20 disconnect(sender: sourceModel, signal: &QAbstractItemModel::rowsInserted,
21 receiver: this, slot: &BookmarkFilterModel::rowsInserted);
22 disconnect(sender: sourceModel, signal: &QAbstractItemModel::rowsAboutToBeRemoved,
23 receiver: this, slot: &BookmarkFilterModel::rowsAboutToBeRemoved);
24 disconnect(sender: sourceModel, signal: &QAbstractItemModel::rowsRemoved,
25 receiver: this, slot: &BookmarkFilterModel::rowsRemoved);
26 disconnect(sender: sourceModel, signal: &QAbstractItemModel::layoutAboutToBeChanged,
27 receiver: this, slot: &BookmarkFilterModel::layoutAboutToBeChanged);
28 disconnect(sender: sourceModel, signal: &QAbstractItemModel::layoutChanged,
29 receiver: this, slot: &BookmarkFilterModel::layoutChanged);
30 disconnect(sender: sourceModel, signal: &QAbstractItemModel::modelAboutToBeReset,
31 receiver: this, slot: &BookmarkFilterModel::modelAboutToBeReset);
32 disconnect(sender: sourceModel, signal: &QAbstractItemModel::modelReset,
33 receiver: this, slot: &BookmarkFilterModel::modelReset);
34 }
35
36 sourceModel = qobject_cast<BookmarkModel*> (object: _sourceModel);
37 QAbstractProxyModel::setSourceModel(sourceModel);
38
39 if (sourceModel) {
40 connect(sender: sourceModel, signal: &QAbstractItemModel::dataChanged,
41 context: this, slot: &BookmarkFilterModel::changed);
42 connect(sender: sourceModel, signal: &QAbstractItemModel::rowsInserted,
43 context: this, slot: &BookmarkFilterModel::rowsInserted);
44 connect(sender: sourceModel, signal: &QAbstractItemModel::rowsAboutToBeRemoved,
45 context: this, slot: &BookmarkFilterModel::rowsAboutToBeRemoved);
46 connect(sender: sourceModel, signal: &QAbstractItemModel::rowsRemoved,
47 context: this, slot: &BookmarkFilterModel::rowsRemoved);
48 connect(sender: sourceModel, signal: &QAbstractItemModel::layoutAboutToBeChanged,
49 context: this, slot: &BookmarkFilterModel::layoutAboutToBeChanged);
50 connect(sender: sourceModel, signal: &QAbstractItemModel::layoutChanged,
51 context: this, slot: &BookmarkFilterModel::layoutChanged);
52 connect(sender: sourceModel, signal: &QAbstractItemModel::modelAboutToBeReset,
53 context: this, slot: &BookmarkFilterModel::modelAboutToBeReset);
54 connect(sender: sourceModel, signal: &QAbstractItemModel::modelReset,
55 context: this, slot: &BookmarkFilterModel::modelReset);
56
57 setupCache(sourceModel->index(row: 0, column: 0, index: QModelIndex()).parent());
58 }
59 endResetModel();
60}
61
62int BookmarkFilterModel::rowCount(const QModelIndex &index) const
63{
64 Q_UNUSED(index);
65 return cache.size();
66}
67
68int BookmarkFilterModel::columnCount(const QModelIndex &index) const
69{
70 Q_UNUSED(index);
71 if (sourceModel)
72 return sourceModel->columnCount();
73 return 0;
74}
75
76QModelIndex BookmarkFilterModel::mapToSource(const QModelIndex &proxyIndex) const
77{
78 const int row = proxyIndex.row();
79 if (proxyIndex.isValid() && row >= 0 && row < cache.size())
80 return cache[row];
81 return QModelIndex();
82}
83
84QModelIndex BookmarkFilterModel::mapFromSource(const QModelIndex &sourceIndex) const
85{
86 return index(row: cache.indexOf(t: sourceIndex), column: 0, parent: QModelIndex());
87}
88
89QModelIndex BookmarkFilterModel::parent(const QModelIndex &child) const
90{
91 Q_UNUSED(child);
92 return QModelIndex();
93}
94
95QModelIndex BookmarkFilterModel::index(int row, int column,
96 const QModelIndex &index) const
97{
98 Q_UNUSED(index);
99 if (row < 0 || column < 0 || cache.size() <= row
100 || !sourceModel || sourceModel->columnCount() <= column) {
101 return QModelIndex();
102 }
103 return createIndex(arow: row, acolumn: 0);
104}
105
106Qt::DropActions BookmarkFilterModel::supportedDropActions () const
107{
108 if (sourceModel)
109 return sourceModel->supportedDropActions();
110 return Qt::IgnoreAction;
111}
112
113Qt::ItemFlags BookmarkFilterModel::flags(const QModelIndex &index) const
114{
115 if (sourceModel)
116 return sourceModel->flags(index);
117 return Qt::NoItemFlags;
118}
119
120QVariant BookmarkFilterModel::data(const QModelIndex &index, int role) const
121{
122 if (sourceModel)
123 return sourceModel->data(index: mapToSource(proxyIndex: index), role);
124 return QVariant();
125}
126
127bool BookmarkFilterModel::setData(const QModelIndex &index, const QVariant &value,
128 int role)
129{
130 if (sourceModel)
131 return sourceModel->setData(index: mapToSource(proxyIndex: index), value, role);
132 return false;
133}
134
135void BookmarkFilterModel::filterBookmarks()
136{
137 if (sourceModel) {
138 beginResetModel();
139 hideBookmarks = true;
140 setupCache(sourceModel->index(row: 0, column: 0, index: QModelIndex()).parent());
141 endResetModel();
142 }
143}
144
145void BookmarkFilterModel::filterBookmarkFolders()
146{
147 if (sourceModel) {
148 beginResetModel();
149 hideBookmarks = false;
150 setupCache(sourceModel->index(row: 0, column: 0, index: QModelIndex()).parent());
151 endResetModel();
152 }
153}
154
155void BookmarkFilterModel::changed(const QModelIndex &topLeft,
156 const QModelIndex &bottomRight)
157{
158 emit dataChanged(topLeft: mapFromSource(sourceIndex: topLeft), bottomRight: mapFromSource(sourceIndex: bottomRight));
159}
160
161void BookmarkFilterModel::rowsInserted(const QModelIndex &parent, int start,
162 int end)
163{
164 if (!sourceModel)
165 return;
166
167 QModelIndex cachePrevious = parent;
168 if (BookmarkItem *parentItem = sourceModel->itemFromIndex(index: parent)) {
169 BookmarkItem *newItem = parentItem->child(number: start);
170
171 // iterate over tree hirarchie to find the previous folder
172 for (int i = 0; i < parentItem->childCount(); ++i) {
173 if (BookmarkItem *child = parentItem->child(number: i)) {
174 const QModelIndex &tmp = sourceModel->indexFromItem(item: child);
175 if (tmp.data(arole: UserRoleFolder).toBool() && child != newItem)
176 cachePrevious = tmp;
177 }
178 }
179
180 const QModelIndex &newIndex = sourceModel->indexFromItem(item: newItem);
181 const bool isFolder = newIndex.data(arole: UserRoleFolder).toBool();
182 if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks)) {
183 beginInsertRows(parent: mapFromSource(sourceIndex: parent), first: start, last: end);
184 const int index = cache.indexOf(t: cachePrevious) + 1;
185 if (cache.value(i: index, defaultValue: QPersistentModelIndex()) != newIndex)
186 cache.insert(i: index, t: newIndex);
187 endInsertRows();
188 }
189 }
190}
191
192void BookmarkFilterModel::rowsAboutToBeRemoved(const QModelIndex &parent,
193 int start, int end)
194{
195 if (!sourceModel)
196 return;
197
198 if (BookmarkItem *parentItem = sourceModel->itemFromIndex(index: parent)) {
199 if (BookmarkItem *child = parentItem->child(number: start)) {
200 indexToRemove = sourceModel->indexFromItem(item: child);
201 if (cache.contains(t: indexToRemove))
202 beginRemoveRows(parent: mapFromSource(sourceIndex: parent), first: start, last: end);
203 }
204 }
205}
206
207void BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int)
208{
209 if (cache.contains(t: indexToRemove)) {
210 cache.removeAll(t: indexToRemove);
211 endRemoveRows();
212 }
213}
214
215void BookmarkFilterModel::layoutAboutToBeChanged()
216{
217 // TODO: ???
218}
219
220void BookmarkFilterModel::layoutChanged()
221{
222 // TODO: ???
223}
224
225void BookmarkFilterModel::modelAboutToBeReset()
226{
227 beginResetModel();
228}
229
230void BookmarkFilterModel::modelReset()
231{
232 if (sourceModel)
233 setupCache(sourceModel->index(row: 0, column: 0, index: QModelIndex()).parent());
234 endResetModel();
235}
236
237void BookmarkFilterModel::setupCache(const QModelIndex &parent)
238{
239 cache.clear();
240 for (int i = 0; i < sourceModel->rowCount(index: parent); ++i)
241 collectItems(parent: sourceModel->index(row: i, column: 0, index: parent));
242}
243
244void BookmarkFilterModel::collectItems(const QModelIndex &parent)
245{
246 if (parent.isValid()) {
247 bool isFolder = sourceModel->data(index: parent, role: UserRoleFolder).toBool();
248 if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks))
249 cache.append(t: parent);
250
251 if (sourceModel->hasChildren(parent)) {
252 for (int i = 0; i < sourceModel->rowCount(index: parent); ++i)
253 collectItems(parent: sourceModel->index(row: i, column: 0, index: parent));
254 }
255 }
256}
257
258// -- BookmarkTreeModel
259
260BookmarkTreeModel::BookmarkTreeModel(QObject *parent)
261 : QSortFilterProxyModel(parent)
262{
263}
264
265int BookmarkTreeModel::columnCount(const QModelIndex &parent) const
266{
267 return qMin(a: 1, b: QSortFilterProxyModel::columnCount(parent));
268}
269
270bool BookmarkTreeModel::filterAcceptsRow(int row, const QModelIndex &parent) const
271{
272 Q_UNUSED(row);
273 BookmarkModel *model = qobject_cast<BookmarkModel*> (object: sourceModel());
274 if (model->rowCount(index: parent) > 0
275 && model->data(index: model->index(row, column: 0, index: parent), role: UserRoleFolder).toBool())
276 return true;
277 return false;
278}
279

source code of qttools/src/assistant/assistant/bookmarkfiltermodel.cpp