File indexing completed on 2025-02-16 04:45:51
0001 /* 0002 This file is part of Akonadi Contact. 0003 0004 SPDX-FileCopyrightText: 2010 KDAB 0005 SPDX-FileContributor: Tobias Koenig <tokoe@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #include "leafextensionproxymodel_p.h" 0011 0012 #include <QSet> 0013 0014 using namespace Akonadi; 0015 0016 class Akonadi::LeafExtensionProxyModelPrivate 0017 { 0018 public: 0019 explicit LeafExtensionProxyModelPrivate(LeafExtensionProxyModel *qq) 0020 : q(qq) 0021 { 0022 } 0023 0024 void sourceRowsInserted(const QModelIndex &parentIndex, int start, int end); 0025 void sourceRowsRemoved(const QModelIndex &parentIndex, int start, int end); 0026 0027 LeafExtensionProxyModel *const q; 0028 QMap<qint64, QModelIndex> mParentIndexes; 0029 QSet<QModelIndex> mOwnIndexes; 0030 qint64 mUniqueKeyCounter = 0; 0031 }; 0032 0033 void LeafExtensionProxyModelPrivate::sourceRowsInserted(const QModelIndex &parentIndex, int start, int end) 0034 { 0035 // iterate over all of our stored parent indexes 0036 QMutableMapIterator<qint64, QModelIndex> it(mParentIndexes); 0037 while (it.hasNext()) { 0038 it.next(); 0039 if (it.value().parent() == parentIndex) { 0040 if (it.value().row() >= start) { 0041 const QModelIndex newIndex = q->QSortFilterProxyModel::index(it.value().row() + (end - start) + 1, it.value().column(), parentIndex); 0042 it.setValue(newIndex); 0043 } 0044 } 0045 } 0046 } 0047 0048 void LeafExtensionProxyModelPrivate::sourceRowsRemoved(const QModelIndex &parentIndex, int start, int end) 0049 { 0050 // iterate over all of our stored parent indexes 0051 QMutableMapIterator<qint64, QModelIndex> it(mParentIndexes); 0052 while (it.hasNext()) { 0053 it.next(); 0054 if (it.value().parent() == parentIndex) { 0055 if (it.value().row() >= start && it.value().row() <= end) { 0056 it.remove(); 0057 } else if (it.value().row() > end) { 0058 const QModelIndex newIndex = q->index(it.value().row() - (end - start) - 1, it.value().column(), parentIndex); 0059 it.setValue(newIndex); 0060 } 0061 } 0062 } 0063 } 0064 0065 LeafExtensionProxyModel::LeafExtensionProxyModel(QObject *parent) 0066 : QSortFilterProxyModel(parent) 0067 , d(new LeafExtensionProxyModelPrivate(this)) 0068 { 0069 } 0070 0071 LeafExtensionProxyModel::~LeafExtensionProxyModel() = default; 0072 0073 QModelIndex LeafExtensionProxyModel::index(int row, int column, const QModelIndex &parent) const 0074 { 0075 if (row < 0 || column < 0) { 0076 return {}; 0077 } 0078 0079 if (parent.isValid()) { 0080 const QModelIndex sourceParent = mapToSource(parent); 0081 const QModelIndex sourceIndex = sourceModel()->index(row, column, sourceParent); 0082 if (!sourceIndex.isValid()) { 0083 qint64 key = -1; 0084 QMapIterator<qint64, QModelIndex> it(d->mParentIndexes); 0085 while (it.hasNext()) { 0086 it.next(); 0087 if (it.value() == parent) { 0088 key = it.key(); 0089 break; 0090 } 0091 } 0092 0093 if (key == -1) { 0094 key = ++(d->mUniqueKeyCounter); 0095 d->mParentIndexes.insert(key, parent); 0096 } 0097 0098 const QModelIndex index = createIndex(row, column, static_cast<quint32>(key)); 0099 d->mOwnIndexes.insert(index); 0100 0101 return index; 0102 } 0103 } 0104 0105 return QSortFilterProxyModel::index(row, column, parent); 0106 } 0107 0108 QModelIndex LeafExtensionProxyModel::parent(const QModelIndex &index) const 0109 { 0110 if (d->mOwnIndexes.contains(index)) { 0111 return d->mParentIndexes.value(index.internalId()); 0112 } 0113 0114 return QSortFilterProxyModel::parent(index); 0115 } 0116 0117 int LeafExtensionProxyModel::rowCount(const QModelIndex &index) const 0118 { 0119 if (d->mOwnIndexes.contains(index)) { 0120 return 0; 0121 } 0122 0123 const QModelIndex sourceIndex = mapToSource(index); 0124 if (sourceModel()->rowCount(sourceIndex) == 0) { 0125 return leafRowCount(index); 0126 } 0127 0128 return QSortFilterProxyModel::rowCount(index); 0129 } 0130 0131 int LeafExtensionProxyModel::columnCount(const QModelIndex &index) const 0132 { 0133 if (d->mOwnIndexes.contains(index)) { 0134 return 1; 0135 } 0136 0137 return QSortFilterProxyModel::columnCount(index); 0138 } 0139 0140 QVariant LeafExtensionProxyModel::data(const QModelIndex &index, int role) const 0141 { 0142 if (d->mOwnIndexes.contains(index)) { 0143 return leafData(index.parent(), index.row(), index.column(), role); 0144 } 0145 0146 return QSortFilterProxyModel::data(index, role); 0147 } 0148 0149 Qt::ItemFlags LeafExtensionProxyModel::flags(const QModelIndex &index) const 0150 { 0151 if (d->mOwnIndexes.contains(index)) { 0152 return Qt::ItemFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); 0153 } 0154 0155 return QSortFilterProxyModel::flags(index); 0156 } 0157 0158 bool LeafExtensionProxyModel::setData(const QModelIndex &index, const QVariant &data, int role) 0159 { 0160 if (d->mOwnIndexes.contains(index)) { 0161 return false; 0162 } 0163 0164 return QSortFilterProxyModel::setData(index, data, role); 0165 } 0166 0167 bool LeafExtensionProxyModel::hasChildren(const QModelIndex &parent) const 0168 { 0169 if (d->mOwnIndexes.contains(parent)) { 0170 return false; // extensible in the future? 0171 } 0172 0173 const QModelIndex sourceParent = mapToSource(parent); 0174 if (sourceModel() && sourceModel()->rowCount(sourceParent) == 0) { 0175 return leafRowCount(parent) != 0; 0176 } 0177 0178 return QSortFilterProxyModel::hasChildren(parent); 0179 } 0180 0181 QModelIndex LeafExtensionProxyModel::buddy(const QModelIndex &index) const 0182 { 0183 if (d->mOwnIndexes.contains(index)) { 0184 return index; 0185 } 0186 0187 return QSortFilterProxyModel::buddy(index); 0188 } 0189 0190 void LeafExtensionProxyModel::fetchMore(const QModelIndex &index) 0191 { 0192 if (d->mOwnIndexes.contains(index)) { 0193 return; 0194 } 0195 0196 QSortFilterProxyModel::fetchMore(index); 0197 } 0198 0199 void LeafExtensionProxyModel::setSourceModel(QAbstractItemModel *_sourceModel) 0200 { 0201 if (_sourceModel == sourceModel()) { 0202 return; 0203 } 0204 0205 beginResetModel(); 0206 0207 disconnect(this, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(sourceRowsInserted(QModelIndex, int, int))); 0208 disconnect(this, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(sourceRowsRemoved(QModelIndex, int, int))); 0209 0210 QSortFilterProxyModel::setSourceModel(_sourceModel); 0211 0212 connect(this, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(sourceRowsInserted(QModelIndex, int, int))); 0213 connect(this, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(sourceRowsRemoved(QModelIndex, int, int))); 0214 0215 endResetModel(); 0216 } 0217 0218 #include "moc_leafextensionproxymodel_p.cpp"