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 33 BookmarkFilterModel::BookmarkFilterModel(QObject *parent) 34 : QAbstractProxyModel(parent) 35 { 36 } 37 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 87 int BookmarkFilterModel::rowCount(const QModelIndex &index) const 88 { 89 Q_UNUSED(index); 90 return cache.count(); 91 } 92 93 int BookmarkFilterModel::columnCount(const QModelIndex &index) const 94 { 95 Q_UNUSED(index); 96 if (sourceModel) 97 return sourceModel->columnCount(); 98 return 0; 99 } 100 101 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 109 QModelIndex BookmarkFilterModel::mapFromSource(const QModelIndex &sourceIndex) const 110 { 111 return index(cache.indexOf(sourceIndex), 0, QModelIndex()); 112 } 113 114 QModelIndex BookmarkFilterModel::parent(const QModelIndex &child) const 115 { 116 Q_UNUSED(child); 117 return QModelIndex(); 118 } 119 120 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 131 Qt::DropActions BookmarkFilterModel::supportedDropActions () const 132 { 133 if (sourceModel) 134 return sourceModel->supportedDropActions(); 135 return Qt::IgnoreAction; 136 } 137 138 Qt::ItemFlags BookmarkFilterModel::flags(const QModelIndex &index) const 139 { 140 if (sourceModel) 141 return sourceModel->flags(index); 142 return Qt::NoItemFlags; 143 } 144 145 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 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 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 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 180 void BookmarkFilterModel::changed(const QModelIndex &topLeft, 181 const QModelIndex &bottomRight) 182 { 183 emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight)); 184 } 185 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 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 232 void BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int) 233 { 234 if (cache.contains(indexToRemove)) { 235 cache.removeAll(indexToRemove); 236 endRemoveRows(); 237 } 238 } 239 240 void BookmarkFilterModel::layoutAboutToBeChanged() 241 { 242 // TODO: ??? 243 } 244 245 void BookmarkFilterModel::layoutChanged() 246 { 247 // TODO: ??? 248 } 249 250 void BookmarkFilterModel::modelAboutToBeReset() 251 { 252 beginResetModel(); 253 } 254 255 void BookmarkFilterModel::modelReset() 256 { 257 if (sourceModel) 258 setupCache(sourceModel->index(0, 0, QModelIndex()).parent()); 259 endResetModel(); 260 } 261 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 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 285 BookmarkTreeModel::BookmarkTreeModel(QObject *parent) 286 : QSortFilterProxyModel(parent) 287 { 288 } 289 290 int BookmarkTreeModel::columnCount(const QModelIndex &parent) const 291 { 292 return qMin(1, QSortFilterProxyModel::columnCount(parent)); 293 } 294 295 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