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
BookmarkFilterModel(QObject * parent)33 BookmarkFilterModel::BookmarkFilterModel(QObject *parent)
34 : QAbstractProxyModel(parent)
35 {
36 }
37
setSourceModel(QAbstractItemModel * _sourceModel)38 void BookmarkFilterModel::setSourceModel(QAbstractItemModel *_sourceModel)
39 {
40 beginResetModel();
41
42 if (sourceModel) {
43 disconnect(sourceModel, &QAbstractItemModel::dataChanged,
44 this, &BookmarkFilterModel::changed);
45 disconnect(sourceModel, &QAbstractItemModel::rowsInserted,
46 this, &BookmarkFilterModel::rowsInserted);
47 disconnect(sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved,
48 this, &BookmarkFilterModel::rowsAboutToBeRemoved);
49 disconnect(sourceModel, &QAbstractItemModel::rowsRemoved,
50 this, &BookmarkFilterModel::rowsRemoved);
51 disconnect(sourceModel, &QAbstractItemModel::layoutAboutToBeChanged,
52 this, &BookmarkFilterModel::layoutAboutToBeChanged);
53 disconnect(sourceModel, &QAbstractItemModel::layoutChanged,
54 this, &BookmarkFilterModel::layoutChanged);
55 disconnect(sourceModel, &QAbstractItemModel::modelAboutToBeReset,
56 this, &BookmarkFilterModel::modelAboutToBeReset);
57 disconnect(sourceModel, &QAbstractItemModel::modelReset,
58 this, &BookmarkFilterModel::modelReset);
59 }
60
61 sourceModel = qobject_cast<BookmarkModel*> (_sourceModel);
62 QAbstractProxyModel::setSourceModel(sourceModel);
63
64 if (sourceModel) {
65 connect(sourceModel, &QAbstractItemModel::dataChanged,
66 this, &BookmarkFilterModel::changed);
67 connect(sourceModel, &QAbstractItemModel::rowsInserted,
68 this, &BookmarkFilterModel::rowsInserted);
69 connect(sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved,
70 this, &BookmarkFilterModel::rowsAboutToBeRemoved);
71 connect(sourceModel, &QAbstractItemModel::rowsRemoved,
72 this, &BookmarkFilterModel::rowsRemoved);
73 connect(sourceModel, &QAbstractItemModel::layoutAboutToBeChanged,
74 this, &BookmarkFilterModel::layoutAboutToBeChanged);
75 connect(sourceModel, &QAbstractItemModel::layoutChanged,
76 this, &BookmarkFilterModel::layoutChanged);
77 connect(sourceModel, &QAbstractItemModel::modelAboutToBeReset,
78 this, &BookmarkFilterModel::modelAboutToBeReset);
79 connect(sourceModel, &QAbstractItemModel::modelReset,
80 this, &BookmarkFilterModel::modelReset);
81
82 setupCache(sourceModel->index(0, 0, QModelIndex()).parent());
83 }
84 endResetModel();
85 }
86
rowCount(const QModelIndex & index) const87 int BookmarkFilterModel::rowCount(const QModelIndex &index) const
88 {
89 Q_UNUSED(index);
90 return cache.count();
91 }
92
columnCount(const QModelIndex & index) const93 int BookmarkFilterModel::columnCount(const QModelIndex &index) const
94 {
95 Q_UNUSED(index);
96 if (sourceModel)
97 return sourceModel->columnCount();
98 return 0;
99 }
100
mapToSource(const QModelIndex & proxyIndex) const101 QModelIndex 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
mapFromSource(const QModelIndex & sourceIndex) const109 QModelIndex BookmarkFilterModel::mapFromSource(const QModelIndex &sourceIndex) const
110 {
111 return index(cache.indexOf(sourceIndex), 0, QModelIndex());
112 }
113
parent(const QModelIndex & child) const114 QModelIndex BookmarkFilterModel::parent(const QModelIndex &child) const
115 {
116 Q_UNUSED(child);
117 return QModelIndex();
118 }
119
index(int row,int column,const QModelIndex & index) const120 QModelIndex 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(row, 0);
129 }
130
supportedDropActions() const131 Qt::DropActions BookmarkFilterModel::supportedDropActions () const
132 {
133 if (sourceModel)
134 return sourceModel->supportedDropActions();
135 return Qt::IgnoreAction;
136 }
137
flags(const QModelIndex & index) const138 Qt::ItemFlags BookmarkFilterModel::flags(const QModelIndex &index) const
139 {
140 if (sourceModel)
141 return sourceModel->flags(index);
142 return Qt::NoItemFlags;
143 }
144
data(const QModelIndex & index,int role) const145 QVariant BookmarkFilterModel::data(const QModelIndex &index, int role) const
146 {
147 if (sourceModel)
148 return sourceModel->data(mapToSource(index), role);
149 return QVariant();
150 }
151
setData(const QModelIndex & index,const QVariant & value,int role)152 bool BookmarkFilterModel::setData(const QModelIndex &index, const QVariant &value,
153 int role)
154 {
155 if (sourceModel)
156 return sourceModel->setData(mapToSource(index), value, role);
157 return false;
158 }
159
filterBookmarks()160 void BookmarkFilterModel::filterBookmarks()
161 {
162 if (sourceModel) {
163 beginResetModel();
164 hideBookmarks = true;
165 setupCache(sourceModel->index(0, 0, QModelIndex()).parent());
166 endResetModel();
167 }
168 }
169
filterBookmarkFolders()170 void BookmarkFilterModel::filterBookmarkFolders()
171 {
172 if (sourceModel) {
173 beginResetModel();
174 hideBookmarks = false;
175 setupCache(sourceModel->index(0, 0, QModelIndex()).parent());
176 endResetModel();
177 }
178 }
179
changed(const QModelIndex & topLeft,const QModelIndex & bottomRight)180 void BookmarkFilterModel::changed(const QModelIndex &topLeft,
181 const QModelIndex &bottomRight)
182 {
183 emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight));
184 }
185
rowsInserted(const QModelIndex & parent,int start,int end)186 void 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(parent)) {
194 BookmarkItem *newItem = parentItem->child(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(i)) {
199 const QModelIndex &tmp = sourceModel->indexFromItem(child);
200 if (tmp.data(UserRoleFolder).toBool() && child != newItem)
201 cachePrevious = tmp;
202 }
203 }
204
205 const QModelIndex &newIndex = sourceModel->indexFromItem(newItem);
206 const bool isFolder = newIndex.data(UserRoleFolder).toBool();
207 if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks)) {
208 beginInsertRows(mapFromSource(parent), start, end);
209 const int index = cache.indexOf(cachePrevious) + 1;
210 if (cache.value(index, QPersistentModelIndex()) != newIndex)
211 cache.insert(index, newIndex);
212 endInsertRows();
213 }
214 }
215 }
216
rowsAboutToBeRemoved(const QModelIndex & parent,int start,int end)217 void BookmarkFilterModel::rowsAboutToBeRemoved(const QModelIndex &parent,
218 int start, int end)
219 {
220 if (!sourceModel)
221 return;
222
223 if (BookmarkItem *parentItem = sourceModel->itemFromIndex(parent)) {
224 if (BookmarkItem *child = parentItem->child(start)) {
225 indexToRemove = sourceModel->indexFromItem(child);
226 if (cache.contains(indexToRemove))
227 beginRemoveRows(mapFromSource(parent), start, end);
228 }
229 }
230 }
231
rowsRemoved(const QModelIndex &,int,int)232 void BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int)
233 {
234 if (cache.contains(indexToRemove)) {
235 cache.removeAll(indexToRemove);
236 endRemoveRows();
237 }
238 }
239
layoutAboutToBeChanged()240 void BookmarkFilterModel::layoutAboutToBeChanged()
241 {
242 // TODO: ???
243 }
244
layoutChanged()245 void BookmarkFilterModel::layoutChanged()
246 {
247 // TODO: ???
248 }
249
modelAboutToBeReset()250 void BookmarkFilterModel::modelAboutToBeReset()
251 {
252 beginResetModel();
253 }
254
modelReset()255 void BookmarkFilterModel::modelReset()
256 {
257 if (sourceModel)
258 setupCache(sourceModel->index(0, 0, QModelIndex()).parent());
259 endResetModel();
260 }
261
setupCache(const QModelIndex & parent)262 void BookmarkFilterModel::setupCache(const QModelIndex &parent)
263 {
264 cache.clear();
265 for (int i = 0; i < sourceModel->rowCount(parent); ++i)
266 collectItems(sourceModel->index(i, 0, parent));
267 }
268
collectItems(const QModelIndex & parent)269 void BookmarkFilterModel::collectItems(const QModelIndex &parent)
270 {
271 if (parent.isValid()) {
272 bool isFolder = sourceModel->data(parent, UserRoleFolder).toBool();
273 if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks))
274 cache.append(parent);
275
276 if (sourceModel->hasChildren(parent)) {
277 for (int i = 0; i < sourceModel->rowCount(parent); ++i)
278 collectItems(sourceModel->index(i, 0, parent));
279 }
280 }
281 }
282
283 // -- BookmarkTreeModel
284
BookmarkTreeModel(QObject * parent)285 BookmarkTreeModel::BookmarkTreeModel(QObject *parent)
286 : QSortFilterProxyModel(parent)
287 {
288 }
289
columnCount(const QModelIndex & parent) const290 int BookmarkTreeModel::columnCount(const QModelIndex &parent) const
291 {
292 return qMin(1, QSortFilterProxyModel::columnCount(parent));
293 }
294
filterAcceptsRow(int row,const QModelIndex & parent) const295 bool BookmarkTreeModel::filterAcceptsRow(int row, const QModelIndex &parent) const
296 {
297 Q_UNUSED(row);
298 BookmarkModel *model = qobject_cast<BookmarkModel*> (sourceModel());
299 if (model->rowCount(parent) > 0
300 && model->data(model->index(row, 0, parent), UserRoleFolder).toBool())
301 return true;
302 return false;
303 }
304