1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Assistant of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28#include "bookmarkfiltermodel.h"
29
30#include "bookmarkitem.h"
31#include "bookmarkmodel.h"
32
33BookmarkFilterModel::BookmarkFilterModel(QObject *parent)
34 : QAbstractProxyModel(parent)
35{
36}
37
38void BookmarkFilterModel::setSourceModel(QAbstractItemModel *_sourceModel)
39{
40 beginResetModel();
41
42 if (sourceModel) {
43 disconnect(sender: sourceModel, signal: &QAbstractItemModel::dataChanged,
44 receiver: this, slot: &BookmarkFilterModel::changed);
45 disconnect(sender: sourceModel, signal: &QAbstractItemModel::rowsInserted,
46 receiver: this, slot: &BookmarkFilterModel::rowsInserted);
47 disconnect(sender: sourceModel, signal: &QAbstractItemModel::rowsAboutToBeRemoved,
48 receiver: this, slot: &BookmarkFilterModel::rowsAboutToBeRemoved);
49 disconnect(sender: sourceModel, signal: &QAbstractItemModel::rowsRemoved,
50 receiver: this, slot: &BookmarkFilterModel::rowsRemoved);
51 disconnect(sender: sourceModel, signal: &QAbstractItemModel::layoutAboutToBeChanged,
52 receiver: this, slot: &BookmarkFilterModel::layoutAboutToBeChanged);
53 disconnect(sender: sourceModel, signal: &QAbstractItemModel::layoutChanged,
54 receiver: this, slot: &BookmarkFilterModel::layoutChanged);
55 disconnect(sender: sourceModel, signal: &QAbstractItemModel::modelAboutToBeReset,
56 receiver: this, slot: &BookmarkFilterModel::modelAboutToBeReset);
57 disconnect(sender: sourceModel, signal: &QAbstractItemModel::modelReset,
58 receiver: this, slot: &BookmarkFilterModel::modelReset);
59 }
60
61 sourceModel = qobject_cast<BookmarkModel*> (object: _sourceModel);
62 QAbstractProxyModel::setSourceModel(sourceModel);
63
64 if (sourceModel) {
65 connect(sender: sourceModel, signal: &QAbstractItemModel::dataChanged,
66 receiver: this, slot: &BookmarkFilterModel::changed);
67 connect(sender: sourceModel, signal: &QAbstractItemModel::rowsInserted,
68 receiver: this, slot: &BookmarkFilterModel::rowsInserted);
69 connect(sender: sourceModel, signal: &QAbstractItemModel::rowsAboutToBeRemoved,
70 receiver: this, slot: &BookmarkFilterModel::rowsAboutToBeRemoved);
71 connect(sender: sourceModel, signal: &QAbstractItemModel::rowsRemoved,
72 receiver: this, slot: &BookmarkFilterModel::rowsRemoved);
73 connect(sender: sourceModel, signal: &QAbstractItemModel::layoutAboutToBeChanged,
74 receiver: this, slot: &BookmarkFilterModel::layoutAboutToBeChanged);
75 connect(sender: sourceModel, signal: &QAbstractItemModel::layoutChanged,
76 receiver: this, slot: &BookmarkFilterModel::layoutChanged);
77 connect(sender: sourceModel, signal: &QAbstractItemModel::modelAboutToBeReset,
78 receiver: this, slot: &BookmarkFilterModel::modelAboutToBeReset);
79 connect(sender: sourceModel, signal: &QAbstractItemModel::modelReset,
80 receiver: this, slot: &BookmarkFilterModel::modelReset);
81
82 setupCache(sourceModel->index(row: 0, column: 0, index: QModelIndex()).parent());
83 }
84 endResetModel();
85}
86
87int BookmarkFilterModel::rowCount(const QModelIndex &index) const
88{
89 Q_UNUSED(index);
90 return cache.count();
91}
92
93int BookmarkFilterModel::columnCount(const QModelIndex &index) const
94{
95 Q_UNUSED(index);
96 if (sourceModel)
97 return sourceModel->columnCount();
98 return 0;
99}
100
101QModelIndex BookmarkFilterModel::mapToSource(const QModelIndex &proxyIndex) const
102{
103 const int row = proxyIndex.row();
104 if (proxyIndex.isValid() && row >= 0 && row < cache.count())
105 return cache[row];
106 return QModelIndex();
107}
108
109QModelIndex BookmarkFilterModel::mapFromSource(const QModelIndex &sourceIndex) const
110{
111 return index(row: cache.indexOf(t: sourceIndex), column: 0, parent: QModelIndex());
112}
113
114QModelIndex BookmarkFilterModel::parent(const QModelIndex &child) const
115{
116 Q_UNUSED(child);
117 return QModelIndex();
118}
119
120QModelIndex BookmarkFilterModel::index(int row, int column,
121 const QModelIndex &index) const
122{
123 Q_UNUSED(index);
124 if (row < 0 || column < 0 || cache.count() <= row
125 || !sourceModel || sourceModel->columnCount() <= column) {
126 return QModelIndex();
127 }
128 return createIndex(arow: row, acolumn: 0);
129}
130
131Qt::DropActions BookmarkFilterModel::supportedDropActions () const
132{
133 if (sourceModel)
134 return sourceModel->supportedDropActions();
135 return Qt::IgnoreAction;
136}
137
138Qt::ItemFlags BookmarkFilterModel::flags(const QModelIndex &index) const
139{
140 if (sourceModel)
141 return sourceModel->flags(index);
142 return Qt::NoItemFlags;
143}
144
145QVariant BookmarkFilterModel::data(const QModelIndex &index, int role) const
146{
147 if (sourceModel)
148 return sourceModel->data(index: mapToSource(proxyIndex: index), role);
149 return QVariant();
150}
151
152bool BookmarkFilterModel::setData(const QModelIndex &index, const QVariant &value,
153 int role)
154{
155 if (sourceModel)
156 return sourceModel->setData(index: mapToSource(proxyIndex: index), value, role);
157 return false;
158}
159
160void BookmarkFilterModel::filterBookmarks()
161{
162 if (sourceModel) {
163 beginResetModel();
164 hideBookmarks = true;
165 setupCache(sourceModel->index(row: 0, column: 0, index: QModelIndex()).parent());
166 endResetModel();
167 }
168}
169
170void BookmarkFilterModel::filterBookmarkFolders()
171{
172 if (sourceModel) {
173 beginResetModel();
174 hideBookmarks = false;
175 setupCache(sourceModel->index(row: 0, column: 0, index: QModelIndex()).parent());
176 endResetModel();
177 }
178}
179
180void BookmarkFilterModel::changed(const QModelIndex &topLeft,
181 const QModelIndex &bottomRight)
182{
183 emit dataChanged(topLeft: mapFromSource(sourceIndex: topLeft), bottomRight: mapFromSource(sourceIndex: bottomRight));
184}
185
186void BookmarkFilterModel::rowsInserted(const QModelIndex &parent, int start,
187 int end)
188{
189 if (!sourceModel)
190 return;
191
192 QModelIndex cachePrevious = parent;
193 if (BookmarkItem *parentItem = sourceModel->itemFromIndex(index: parent)) {
194 BookmarkItem *newItem = parentItem->child(number: start);
195
196 // iterate over tree hirarchie to find the previous folder
197 for (int i = 0; i < parentItem->childCount(); ++i) {
198 if (BookmarkItem *child = parentItem->child(number: i)) {
199 const QModelIndex &tmp = sourceModel->indexFromItem(item: child);
200 if (tmp.data(arole: UserRoleFolder).toBool() && child != newItem)
201 cachePrevious = tmp;
202 }
203 }
204
205 const QModelIndex &newIndex = sourceModel->indexFromItem(item: newItem);
206 const bool isFolder = newIndex.data(arole: UserRoleFolder).toBool();
207 if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks)) {
208 beginInsertRows(parent: mapFromSource(sourceIndex: parent), first: start, last: end);
209 const int index = cache.indexOf(t: cachePrevious) + 1;
210 if (cache.value(i: index, defaultValue: QPersistentModelIndex()) != newIndex)
211 cache.insert(i: index, t: newIndex);
212 endInsertRows();
213 }
214 }
215}
216
217void BookmarkFilterModel::rowsAboutToBeRemoved(const QModelIndex &parent,
218 int start, int end)
219{
220 if (!sourceModel)
221 return;
222
223 if (BookmarkItem *parentItem = sourceModel->itemFromIndex(index: parent)) {
224 if (BookmarkItem *child = parentItem->child(number: start)) {
225 indexToRemove = sourceModel->indexFromItem(item: child);
226 if (cache.contains(t: indexToRemove))
227 beginRemoveRows(parent: mapFromSource(sourceIndex: parent), first: start, last: end);
228 }
229 }
230}
231
232void BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int)
233{
234 if (cache.contains(t: indexToRemove)) {
235 cache.removeAll(t: indexToRemove);
236 endRemoveRows();
237 }
238}
239
240void BookmarkFilterModel::layoutAboutToBeChanged()
241{
242 // TODO: ???
243}
244
245void BookmarkFilterModel::layoutChanged()
246{
247 // TODO: ???
248}
249
250void BookmarkFilterModel::modelAboutToBeReset()
251{
252 beginResetModel();
253}
254
255void BookmarkFilterModel::modelReset()
256{
257 if (sourceModel)
258 setupCache(sourceModel->index(row: 0, column: 0, index: QModelIndex()).parent());
259 endResetModel();
260}
261
262void BookmarkFilterModel::setupCache(const QModelIndex &parent)
263{
264 cache.clear();
265 for (int i = 0; i < sourceModel->rowCount(index: parent); ++i)
266 collectItems(parent: sourceModel->index(row: i, column: 0, index: parent));
267}
268
269void BookmarkFilterModel::collectItems(const QModelIndex &parent)
270{
271 if (parent.isValid()) {
272 bool isFolder = sourceModel->data(index: parent, role: UserRoleFolder).toBool();
273 if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks))
274 cache.append(t: parent);
275
276 if (sourceModel->hasChildren(parent)) {
277 for (int i = 0; i < sourceModel->rowCount(index: parent); ++i)
278 collectItems(parent: sourceModel->index(row: i, column: 0, index: parent));
279 }
280 }
281}
282
283// -- BookmarkTreeModel
284
285BookmarkTreeModel::BookmarkTreeModel(QObject *parent)
286 : QSortFilterProxyModel(parent)
287{
288}
289
290int BookmarkTreeModel::columnCount(const QModelIndex &parent) const
291{
292 return qMin(a: 1, b: QSortFilterProxyModel::columnCount(parent));
293}
294
295bool BookmarkTreeModel::filterAcceptsRow(int row, const QModelIndex &parent) const
296{
297 Q_UNUSED(row);
298 BookmarkModel *model = qobject_cast<BookmarkModel*> (object: sourceModel());
299 if (model->rowCount(index: parent) > 0
300 && model->data(index: model->index(row, column: 0, index: parent), role: UserRoleFolder).toBool())
301 return true;
302 return false;
303}
304

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