File indexing completed on 2025-01-05 03:59:21
0001 /* 0002 SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com> 0003 SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB a KDAB Group company <info@kdab.net> 0004 SPDX-FileContributor: Stephen Kelly <stephen@kdab.com> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "kdescendantsproxymodel.h" 0010 0011 #include <iterator> 0012 0013 #include <QStringList> 0014 #include <QTimer> 0015 0016 #include "kbihash_p.h" 0017 0018 namespace Marble 0019 { 0020 0021 typedef KHash2Map<QPersistentModelIndex, int> Mapping; 0022 0023 class KDescendantsProxyModelPrivate 0024 { 0025 KDescendantsProxyModelPrivate(KDescendantsProxyModel *qq) 0026 : q_ptr(qq), 0027 m_rowCount(0), 0028 m_ignoreNextLayoutAboutToBeChanged(false), 0029 m_ignoreNextLayoutChanged(false), 0030 m_relayouting(false), 0031 m_displayAncestorData(false), 0032 m_ancestorSeparator(QStringLiteral(" / ")) 0033 { 0034 } 0035 0036 Q_DECLARE_PUBLIC(KDescendantsProxyModel) 0037 KDescendantsProxyModel *const q_ptr; 0038 0039 mutable QVector<QPersistentModelIndex> m_pendingParents; 0040 0041 void scheduleProcessPendingParents() const; 0042 void processPendingParents(); 0043 0044 void synchronousMappingRefresh(); 0045 0046 void updateInternalIndexes(int start, int offset); 0047 0048 void resetInternalData(); 0049 0050 void sourceRowsAboutToBeInserted(const QModelIndex &, int, int); 0051 void sourceRowsInserted(const QModelIndex &, int, int); 0052 void sourceRowsAboutToBeRemoved(const QModelIndex &, int, int); 0053 void sourceRowsRemoved(const QModelIndex &, int, int); 0054 void sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int); 0055 void sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int); 0056 void sourceModelAboutToBeReset(); 0057 void sourceModelReset(); 0058 void sourceLayoutAboutToBeChanged(); 0059 void sourceLayoutChanged(); 0060 void sourceDataChanged(const QModelIndex &, const QModelIndex &); 0061 void sourceModelDestroyed(); 0062 0063 Mapping m_mapping; 0064 int m_rowCount; 0065 QPair<int, int> m_removePair; 0066 QPair<int, int> m_insertPair; 0067 0068 bool m_ignoreNextLayoutAboutToBeChanged; 0069 bool m_ignoreNextLayoutChanged; 0070 bool m_relayouting; 0071 0072 bool m_displayAncestorData; 0073 QString m_ancestorSeparator; 0074 0075 QList<QPersistentModelIndex> m_layoutChangePersistentIndexes; 0076 QModelIndexList m_proxyIndexes; 0077 }; 0078 0079 void KDescendantsProxyModelPrivate::resetInternalData() 0080 { 0081 m_rowCount = 0; 0082 m_mapping.clear(); 0083 m_layoutChangePersistentIndexes.clear(); 0084 m_proxyIndexes.clear(); 0085 } 0086 0087 void KDescendantsProxyModelPrivate::synchronousMappingRefresh() 0088 { 0089 m_rowCount = 0; 0090 m_mapping.clear(); 0091 m_pendingParents.clear(); 0092 0093 m_pendingParents.append(QModelIndex()); 0094 0095 m_relayouting = true; 0096 while (!m_pendingParents.isEmpty()) { 0097 processPendingParents(); 0098 } 0099 m_relayouting = false; 0100 } 0101 0102 void KDescendantsProxyModelPrivate::scheduleProcessPendingParents() const 0103 { 0104 const_cast<KDescendantsProxyModelPrivate *>(this)->processPendingParents(); 0105 } 0106 0107 void KDescendantsProxyModelPrivate::processPendingParents() 0108 { 0109 Q_Q(KDescendantsProxyModel); 0110 const QVector<QPersistentModelIndex>::iterator begin = m_pendingParents.begin(); 0111 QVector<QPersistentModelIndex>::iterator it = begin; 0112 0113 const QVector<QPersistentModelIndex>::iterator end = m_pendingParents.end(); 0114 0115 QVector<QPersistentModelIndex> newPendingParents; 0116 0117 while (it != end && it != m_pendingParents.end()) { 0118 const QModelIndex sourceParent = *it; 0119 if (!sourceParent.isValid() && m_rowCount > 0) { 0120 // It was removed from the source model before it was inserted. 0121 it = m_pendingParents.erase(it); 0122 continue; 0123 } 0124 const int rowCount = q->sourceModel()->rowCount(sourceParent); 0125 0126 Q_ASSERT(rowCount > 0); 0127 const QPersistentModelIndex sourceIndex = q->sourceModel()->index(rowCount - 1, 0, sourceParent); 0128 0129 Q_ASSERT(sourceIndex.isValid()); 0130 0131 const QModelIndex proxyParent = q->mapFromSource(sourceParent); 0132 0133 Q_ASSERT(sourceParent.isValid() == proxyParent.isValid()); 0134 const int proxyEndRow = proxyParent.row() + rowCount; 0135 const int proxyStartRow = proxyEndRow - rowCount + 1; 0136 0137 if (!m_relayouting) { 0138 q->beginInsertRows(QModelIndex(), proxyStartRow, proxyEndRow); 0139 } 0140 0141 updateInternalIndexes(proxyStartRow, rowCount); 0142 m_mapping.insert(sourceIndex, proxyEndRow); 0143 it = m_pendingParents.erase(it); 0144 m_rowCount += rowCount; 0145 0146 if (!m_relayouting) { 0147 q->endInsertRows(); 0148 } 0149 0150 for (int sourceRow = 0; sourceRow < rowCount; ++sourceRow) { 0151 static const int column = 0; 0152 const QModelIndex child = q->sourceModel()->index(sourceRow, column, sourceParent); 0153 Q_ASSERT(child.isValid()); 0154 0155 if (q->sourceModel()->hasChildren(child)) { 0156 Q_ASSERT(q->sourceModel()->rowCount(child) > 0); 0157 newPendingParents.append(child); 0158 } 0159 } 0160 } 0161 m_pendingParents += newPendingParents; 0162 if (!m_pendingParents.isEmpty()) { 0163 processPendingParents(); 0164 } 0165 // scheduleProcessPendingParents(); 0166 } 0167 0168 void KDescendantsProxyModelPrivate::updateInternalIndexes(int start, int offset) 0169 { 0170 // TODO: Make KHash2Map support key updates and do this backwards. 0171 QHash<int, QPersistentModelIndex> updates; 0172 { 0173 Mapping::right_iterator it = m_mapping.rightLowerBound(start); 0174 const Mapping::right_iterator end = m_mapping.rightEnd(); 0175 0176 while (it != end) { 0177 updates.insert(it.key() + offset, *it); 0178 ++it; 0179 } 0180 } 0181 0182 { 0183 QHash<int, QPersistentModelIndex>::const_iterator it = updates.constBegin(); 0184 const QHash<int, QPersistentModelIndex>::const_iterator end = updates.constEnd(); 0185 0186 for (; it != end; ++it) { 0187 m_mapping.insert(it.value(), it.key()); 0188 } 0189 } 0190 0191 } 0192 0193 KDescendantsProxyModel::KDescendantsProxyModel(QObject *parent) 0194 : QAbstractProxyModel(parent), d_ptr(new KDescendantsProxyModelPrivate(this)) 0195 { 0196 } 0197 0198 KDescendantsProxyModel::~KDescendantsProxyModel() 0199 { 0200 delete d_ptr; 0201 } 0202 0203 #if 0 0204 void KDescendantsProxyModel::setRootIndex(const QModelIndex &index) 0205 { 0206 Q_UNUSED(index) 0207 } 0208 #endif 0209 0210 QModelIndexList KDescendantsProxyModel::match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const 0211 { 0212 return QAbstractProxyModel::match(start, role, value, hits, flags); 0213 } 0214 0215 void KDescendantsProxyModel::setDisplayAncestorData(bool display) 0216 { 0217 Q_D(KDescendantsProxyModel); 0218 d->m_displayAncestorData = display; 0219 } 0220 0221 bool KDescendantsProxyModel::displayAncestorData() const 0222 { 0223 Q_D(const KDescendantsProxyModel); 0224 return d->m_displayAncestorData; 0225 } 0226 0227 void KDescendantsProxyModel::setAncestorSeparator(const QString &separator) 0228 { 0229 Q_D(KDescendantsProxyModel); 0230 d->m_ancestorSeparator = separator; 0231 } 0232 0233 QString KDescendantsProxyModel::ancestorSeparator() const 0234 { 0235 Q_D(const KDescendantsProxyModel); 0236 return d->m_ancestorSeparator; 0237 } 0238 0239 void KDescendantsProxyModel::setSourceModel(QAbstractItemModel *_sourceModel) 0240 { 0241 Q_D(KDescendantsProxyModel); 0242 0243 beginResetModel(); 0244 0245 static const char *const modelSignals[] = { 0246 SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), 0247 SIGNAL(rowsInserted(QModelIndex,int,int)), 0248 SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), 0249 SIGNAL(rowsRemoved(QModelIndex,int,int)), 0250 SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), 0251 SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), 0252 SIGNAL(modelAboutToBeReset()), 0253 SIGNAL(modelReset()), 0254 SIGNAL(dataChanged(QModelIndex,QModelIndex)), 0255 SIGNAL(layoutAboutToBeChanged()), 0256 SIGNAL(layoutChanged()), 0257 SIGNAL(destroyed()) 0258 }; 0259 static const char *const proxySlots[] = { 0260 SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)), 0261 SLOT(sourceRowsInserted(QModelIndex,int,int)), 0262 SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)), 0263 SLOT(sourceRowsRemoved(QModelIndex,int,int)), 0264 SLOT(sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), 0265 SLOT(sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)), 0266 SLOT(sourceModelAboutToBeReset()), 0267 SLOT(sourceModelReset()), 0268 SLOT(sourceDataChanged(QModelIndex,QModelIndex)), 0269 SLOT(sourceLayoutAboutToBeChanged()), 0270 SLOT(sourceLayoutChanged()), 0271 SLOT(sourceModelDestroyed()) 0272 }; 0273 0274 if (sourceModel()) { 0275 for (int i = 0; i < int(sizeof modelSignals / sizeof * modelSignals); ++i) { 0276 disconnect(sourceModel(), modelSignals[i], this, proxySlots[i]); 0277 } 0278 } 0279 0280 QAbstractProxyModel::setSourceModel(_sourceModel); 0281 0282 if (_sourceModel) { 0283 for (int i = 0; i < int(sizeof modelSignals / sizeof * modelSignals); ++i) { 0284 connect(_sourceModel, modelSignals[i], this, proxySlots[i]); 0285 } 0286 } 0287 0288 resetInternalData(); 0289 if (_sourceModel && _sourceModel->hasChildren()) { 0290 d->synchronousMappingRefresh(); 0291 } 0292 0293 endResetModel(); 0294 } 0295 0296 QModelIndex KDescendantsProxyModel::parent(const QModelIndex &index) const 0297 { 0298 Q_UNUSED(index) 0299 return QModelIndex(); 0300 } 0301 0302 bool KDescendantsProxyModel::hasChildren(const QModelIndex &parent) const 0303 { 0304 Q_D(const KDescendantsProxyModel); 0305 return !(d->m_mapping.isEmpty() || parent.isValid()); 0306 } 0307 0308 int KDescendantsProxyModel::rowCount(const QModelIndex &parent) const 0309 { 0310 Q_D(const KDescendantsProxyModel); 0311 if (d->m_pendingParents.contains(parent) || parent.isValid() || !sourceModel()) { 0312 return 0; 0313 } 0314 0315 if (d->m_mapping.isEmpty() && sourceModel()->hasChildren()) { 0316 Q_ASSERT(sourceModel()->rowCount() > 0); 0317 const_cast<KDescendantsProxyModelPrivate *>(d)->synchronousMappingRefresh(); 0318 } 0319 return d->m_rowCount; 0320 } 0321 0322 QModelIndex KDescendantsProxyModel::index(int row, int column, const QModelIndex &parent) const 0323 { 0324 if (parent.isValid()) { 0325 return QModelIndex(); 0326 } 0327 0328 if (!hasIndex(row, column, parent)) { 0329 return QModelIndex(); 0330 } 0331 0332 return createIndex(row, column); 0333 } 0334 0335 QModelIndex KDescendantsProxyModel::mapToSource(const QModelIndex &proxyIndex) const 0336 { 0337 Q_D(const KDescendantsProxyModel); 0338 if (d->m_mapping.isEmpty() || !proxyIndex.isValid() || !sourceModel()) { 0339 return QModelIndex(); 0340 } 0341 0342 const Mapping::right_const_iterator result = d->m_mapping.rightLowerBound(proxyIndex.row()); 0343 Q_ASSERT(result != d->m_mapping.rightEnd()); 0344 0345 const int proxyLastRow = result.key(); 0346 const QModelIndex sourceLastChild = result.value(); 0347 Q_ASSERT(sourceLastChild.isValid()); 0348 0349 // proxyLastRow is greater than proxyIndex.row(). 0350 // sourceLastChild is vertically below the result we're looking for 0351 // and not necessarily in the correct parent. 0352 // We travel up through its parent hierarchy until we are in the 0353 // right parent, then return the correct sibling. 0354 0355 // Source: Proxy: Row 0356 // - A - A - 0 0357 // - B - B - 1 0358 // - C - C - 2 0359 // - D - D - 3 0360 // - - E - E - 4 0361 // - - F - F - 5 0362 // - - G - G - 6 0363 // - - H - H - 7 0364 // - - I - I - 8 0365 // - - - J - J - 9 0366 // - - - K - K - 10 0367 // - - - L - L - 11 0368 // - - M - M - 12 0369 // - - N - N - 13 0370 // - O - O - 14 0371 0372 // Note that L, N and O are lastChildIndexes, and therefore have a mapping. If we 0373 // are trying to map G from the proxy to the source, We at this point have an iterator 0374 // pointing to (L -> 11). The proxy row of G is 6. (proxyIndex.row() == 6). We seek the 0375 // sourceIndex which is vertically above L by the distance proxyLastRow - proxyIndex.row(). 0376 // In this case the verticalDistance is 5. 0377 0378 int verticalDistance = proxyLastRow - proxyIndex.row(); 0379 0380 // We traverse the ancestors of L, until we can index the desired row in the source. 0381 0382 QModelIndex ancestor = sourceLastChild; 0383 while (ancestor.isValid()) { 0384 const int ancestorRow = ancestor.row(); 0385 if (verticalDistance <= ancestorRow) { 0386 return ancestor.sibling(ancestorRow - verticalDistance, proxyIndex.column()); 0387 } 0388 verticalDistance -= (ancestorRow + 1); 0389 ancestor = ancestor.parent(); 0390 } 0391 Q_ASSERT(!"Didn't find target row."); 0392 return QModelIndex(); 0393 } 0394 0395 QModelIndex KDescendantsProxyModel::mapFromSource(const QModelIndex &sourceIndex) const 0396 { 0397 Q_D(const KDescendantsProxyModel); 0398 0399 if (!sourceModel()) { 0400 return QModelIndex(); 0401 } 0402 0403 if (d->m_mapping.isEmpty()) { 0404 return QModelIndex(); 0405 } 0406 0407 { 0408 // TODO: Consider a parent Mapping to speed this up. 0409 0410 Mapping::right_const_iterator it = d->m_mapping.rightConstBegin(); 0411 const Mapping::right_const_iterator end = d->m_mapping.rightConstEnd(); 0412 const QModelIndex sourceParent = sourceIndex.parent(); 0413 Mapping::right_const_iterator result = end; 0414 0415 for (; it != end; ++it) { 0416 QModelIndex index = it.value(); 0417 bool found_block = false; 0418 while (index.isValid()) { 0419 const QModelIndex ancestor = index.parent(); 0420 if (ancestor == sourceParent && index.row() >= sourceIndex.row()) { 0421 found_block = true; 0422 if (result == end || it.key() < result.key()) { 0423 result = it; 0424 break; // Leave the while loop. index is still valid. 0425 } 0426 } 0427 index = ancestor; 0428 } 0429 if (found_block && !index.isValid()) 0430 // Looked through the ascendants of it.key() without finding sourceParent. 0431 // That means we've already got the result we need. 0432 { 0433 break; 0434 } 0435 } 0436 Q_ASSERT(result != end); 0437 const QModelIndex sourceLastChild = result.value(); 0438 int proxyRow = result.key(); 0439 QModelIndex index = sourceLastChild; 0440 while (index.isValid()) { 0441 const QModelIndex ancestor = index.parent(); 0442 if (ancestor == sourceParent) { 0443 return createIndex(proxyRow - (index.row() - sourceIndex.row()), sourceIndex.column()); 0444 } 0445 proxyRow -= (index.row() + 1); 0446 index = ancestor; 0447 } 0448 Q_ASSERT(!"Didn't find valid proxy mapping."); 0449 return QModelIndex(); 0450 } 0451 0452 } 0453 0454 int KDescendantsProxyModel::columnCount(const QModelIndex &parent) const 0455 { 0456 if (parent.isValid() /* || rowCount(parent) == 0 */ || !sourceModel()) { 0457 return 0; 0458 } 0459 0460 return sourceModel()->columnCount(); 0461 } 0462 0463 QVariant KDescendantsProxyModel::data(const QModelIndex &index, int role) const 0464 { 0465 Q_D(const KDescendantsProxyModel); 0466 0467 if (!sourceModel()) { 0468 return QVariant(); 0469 } 0470 0471 if (!index.isValid()) { 0472 return sourceModel()->data(index, role); 0473 } 0474 0475 QModelIndex sourceIndex = mapToSource(index); 0476 0477 if ((d->m_displayAncestorData) && (role == Qt::DisplayRole)) { 0478 if (!sourceIndex.isValid()) { 0479 return QVariant(); 0480 } 0481 QString displayData = sourceIndex.data().toString(); 0482 sourceIndex = sourceIndex.parent(); 0483 while (sourceIndex.isValid()) { 0484 displayData.prepend(d->m_ancestorSeparator); 0485 displayData.prepend(sourceIndex.data().toString()); 0486 sourceIndex = sourceIndex.parent(); 0487 } 0488 return displayData; 0489 } else { 0490 return sourceIndex.data(role); 0491 } 0492 } 0493 0494 QVariant KDescendantsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const 0495 { 0496 if (!sourceModel() || columnCount() <= section) { 0497 return QVariant(); 0498 } 0499 0500 return QAbstractProxyModel::headerData(section, orientation, role); 0501 } 0502 0503 Qt::ItemFlags KDescendantsProxyModel::flags(const QModelIndex &index) const 0504 { 0505 if (!index.isValid() || !sourceModel()) { 0506 return QAbstractProxyModel::flags(index); 0507 } 0508 0509 const QModelIndex srcIndex = mapToSource(index); 0510 Q_ASSERT(srcIndex.isValid()); 0511 return sourceModel()->flags(srcIndex); 0512 } 0513 0514 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end) 0515 { 0516 Q_Q(KDescendantsProxyModel); 0517 0518 if (!q->sourceModel()->hasChildren(parent)) { 0519 Q_ASSERT(q->sourceModel()->rowCount(parent) == 0); 0520 // parent was not a parent before. 0521 return; 0522 } 0523 0524 int proxyStart = -1; 0525 0526 const int rowCount = q->sourceModel()->rowCount(parent); 0527 0528 if (rowCount > start) { 0529 const QModelIndex belowStart = q->sourceModel()->index(start, 0, parent); 0530 proxyStart = q->mapFromSource(belowStart).row(); 0531 } else if (rowCount == 0) { 0532 proxyStart = q->mapFromSource(parent).row() + 1; 0533 } else { 0534 Q_ASSERT(rowCount == start); 0535 static const int column = 0; 0536 QModelIndex idx = q->sourceModel()->index(rowCount - 1, column, parent); 0537 while (q->sourceModel()->hasChildren(idx)) { 0538 Q_ASSERT(q->sourceModel()->rowCount(idx) > 0); 0539 idx = q->sourceModel()->index(q->sourceModel()->rowCount(idx) - 1, column, idx); 0540 } 0541 // The last item in the list is getting a sibling below it. 0542 proxyStart = q->mapFromSource(idx).row() + 1; 0543 } 0544 const int proxyEnd = proxyStart + (end - start); 0545 0546 m_insertPair = qMakePair(proxyStart, proxyEnd); 0547 q->beginInsertRows(QModelIndex(), proxyStart, proxyEnd); 0548 } 0549 0550 void KDescendantsProxyModelPrivate::sourceRowsInserted(const QModelIndex &parent, int start, int end) 0551 { 0552 Q_Q(KDescendantsProxyModel); 0553 0554 Q_ASSERT(q->sourceModel()->index(start, 0, parent).isValid()); 0555 0556 const int rowCount = q->sourceModel()->rowCount(parent); 0557 Q_ASSERT(rowCount > 0); 0558 0559 const int difference = end - start + 1; 0560 0561 if (rowCount == difference) { 0562 // @p parent was not a parent before. 0563 m_pendingParents.append(parent); 0564 scheduleProcessPendingParents(); 0565 return; 0566 } 0567 0568 const int proxyStart = m_insertPair.first; 0569 0570 Q_ASSERT(proxyStart >= 0); 0571 0572 updateInternalIndexes(proxyStart, difference); 0573 0574 if (rowCount - 1 == end) { 0575 // The previously last row (the mapped one) is no longer the last. 0576 // For example, 0577 0578 // - A - A 0 0579 // - - B - B 1 0580 // - - C - C 2 0581 // - - - D - D 3 0582 // - - - E -> - E 4 0583 // - - F - F 5 0584 // - - G -> - G 6 0585 // - H - H 7 0586 // - I -> - I 8 0587 0588 // As last children, E, F and G have mappings. 0589 // Consider that 'J' is appended to the children of 'C', below 'E'. 0590 0591 // - A - A 0 0592 // - - B - B 1 0593 // - - C - C 2 0594 // - - - D - D 3 0595 // - - - E -> - E 4 0596 // - - - J - ??? 5 0597 // - - F - F 6 0598 // - - G -> - G 7 0599 // - H - H 8 0600 // - I -> - I 9 0601 0602 // The updateInternalIndexes call above will have updated the F and G mappings correctly because proxyStart is 5. 0603 // That means that E -> 4 was not affected by the updateInternalIndexes call. 0604 // Now the mapping for E -> 4 needs to be updated so that it's a mapping for J -> 5. 0605 0606 Q_ASSERT(!m_mapping.isEmpty()); 0607 static const int column = 0; 0608 const QModelIndex oldIndex = q->sourceModel()->index(rowCount - 1 - difference, column, parent); 0609 Q_ASSERT(m_mapping.leftContains(oldIndex)); 0610 0611 const QModelIndex newIndex = q->sourceModel()->index(rowCount - 1, column, parent); 0612 0613 QModelIndex indexAbove = oldIndex; 0614 0615 if (start > 0) { 0616 // If we have something like this: 0617 // 0618 // - A 0619 // - - B 0620 // - - C 0621 // 0622 // and we then insert D as a sibling of A below it, we need to remove the mapping for A, 0623 // and the row number used for D must take into account the descendants of A. 0624 0625 while (q->sourceModel()->hasChildren(indexAbove)) { 0626 Q_ASSERT(q->sourceModel()->rowCount(indexAbove) > 0); 0627 indexAbove = q->sourceModel()->index(q->sourceModel()->rowCount(indexAbove) - 1, column, indexAbove); 0628 } 0629 Q_ASSERT(q->sourceModel()->rowCount(indexAbove) == 0); 0630 } 0631 0632 Q_ASSERT(m_mapping.leftContains(indexAbove)); 0633 0634 const int newProxyRow = m_mapping.leftToRight(indexAbove) + difference; 0635 0636 // oldIndex is E in the source. proxyRow is 4. 0637 m_mapping.removeLeft(oldIndex); 0638 0639 // newIndex is J. (proxyRow + difference) is 5. 0640 m_mapping.insert(newIndex, newProxyRow); 0641 } 0642 0643 for (int row = start; row <= end; ++row) { 0644 static const int column = 0; 0645 const QModelIndex idx = q->sourceModel()->index(row, column, parent); 0646 Q_ASSERT(idx.isValid()); 0647 if (q->sourceModel()->hasChildren(idx)) { 0648 Q_ASSERT(q->sourceModel()->rowCount(idx) > 0); 0649 m_pendingParents.append(idx); 0650 } 0651 } 0652 0653 m_rowCount += difference; 0654 0655 q->endInsertRows(); 0656 scheduleProcessPendingParents(); 0657 } 0658 0659 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) 0660 { 0661 Q_Q(KDescendantsProxyModel); 0662 0663 const int proxyStart = q->mapFromSource(q->sourceModel()->index(start, 0, parent)).row(); 0664 0665 static const int column = 0; 0666 QModelIndex idx = q->sourceModel()->index(end, column, parent); 0667 while (q->sourceModel()->hasChildren(idx)) { 0668 Q_ASSERT(q->sourceModel()->rowCount(idx) > 0); 0669 idx = q->sourceModel()->index(q->sourceModel()->rowCount(idx) - 1, column, idx); 0670 } 0671 const int proxyEnd = q->mapFromSource(idx).row(); 0672 0673 m_removePair = qMakePair(proxyStart, proxyEnd); 0674 0675 q->beginRemoveRows(QModelIndex(), proxyStart, proxyEnd); 0676 } 0677 0678 static QModelIndex getFirstDeepest(QAbstractItemModel *model, const QModelIndex &parent, int *count) 0679 { 0680 static const int column = 0; 0681 Q_ASSERT(model->hasChildren(parent)); 0682 Q_ASSERT(model->rowCount(parent) > 0); 0683 for (int row = 0; row < model->rowCount(parent); ++row) { 0684 (*count)++; 0685 const QModelIndex child = model->index(row, column, parent); 0686 Q_ASSERT(child.isValid()); 0687 if (model->hasChildren(child)) { 0688 return getFirstDeepest(model, child, count); 0689 } 0690 } 0691 return model->index(model->rowCount(parent) - 1, column, parent); 0692 } 0693 0694 void KDescendantsProxyModelPrivate::sourceRowsRemoved(const QModelIndex &parent, int start, int end) 0695 { 0696 Q_Q(KDescendantsProxyModel); 0697 Q_UNUSED(end) 0698 0699 const int rowCount = q->sourceModel()->rowCount(parent); 0700 0701 const int proxyStart = m_removePair.first; 0702 const int proxyEnd = m_removePair.second; 0703 0704 const int difference = proxyEnd - proxyStart + 1; 0705 { 0706 Mapping::right_iterator it = m_mapping.rightLowerBound(proxyStart); 0707 const Mapping::right_iterator endIt = m_mapping.rightUpperBound(proxyEnd); 0708 0709 if (endIt != m_mapping.rightEnd()) 0710 while (it != endIt) { 0711 it = m_mapping.eraseRight(it); 0712 } 0713 else 0714 while (it != m_mapping.rightUpperBound(proxyEnd)) { 0715 it = m_mapping.eraseRight(it); 0716 } 0717 } 0718 0719 m_removePair = qMakePair(-1, -1); 0720 m_rowCount -= difference; 0721 Q_ASSERT(m_rowCount >= 0); 0722 0723 updateInternalIndexes(proxyStart, -1 * difference); 0724 0725 if (rowCount != start || rowCount == 0) { 0726 q->endRemoveRows(); 0727 return; 0728 } 0729 0730 static const int column = 0; 0731 const QModelIndex newEnd = q->sourceModel()->index(rowCount - 1, column, parent); 0732 Q_ASSERT(newEnd.isValid()); 0733 0734 if (m_mapping.isEmpty()) { 0735 m_mapping.insert(newEnd, newEnd.row()); 0736 q->endRemoveRows(); 0737 return; 0738 } 0739 if (q->sourceModel()->hasChildren(newEnd)) { 0740 int count = 0; 0741 const QModelIndex firstDeepest = getFirstDeepest(q->sourceModel(), newEnd, &count); 0742 Q_ASSERT(firstDeepest.isValid()); 0743 const int firstDeepestProxy = m_mapping.leftToRight(firstDeepest); 0744 0745 m_mapping.insert(newEnd, firstDeepestProxy - count); 0746 q->endRemoveRows(); 0747 return; 0748 } 0749 Mapping::right_iterator lowerBound = m_mapping.rightLowerBound(proxyStart); 0750 if (lowerBound == m_mapping.rightEnd()) { 0751 int proxyRow = std::prev(lowerBound, 1).key(); 0752 0753 for (int row = newEnd.row(); row >= 0; --row) { 0754 const QModelIndex newEndSibling = q->sourceModel()->index(row, column, parent); 0755 if (!q->sourceModel()->hasChildren(newEndSibling)) { 0756 ++proxyRow; 0757 } else { 0758 break; 0759 } 0760 } 0761 m_mapping.insert(newEnd, proxyRow); 0762 q->endRemoveRows(); 0763 return; 0764 } else if (lowerBound == m_mapping.rightBegin()) { 0765 int proxyRow = rowCount - 1; 0766 QModelIndex trackedParent = parent; 0767 while (trackedParent.isValid()) { 0768 proxyRow += (trackedParent.row() + 1); 0769 trackedParent = trackedParent.parent(); 0770 } 0771 m_mapping.insert(newEnd, proxyRow); 0772 q->endRemoveRows(); 0773 return; 0774 } 0775 const Mapping::right_iterator boundAbove = std::prev(lowerBound, 1); 0776 0777 QVector<QModelIndex> targetParents; 0778 targetParents.push_back(parent); 0779 { 0780 QModelIndex target = parent; 0781 int count = 0; 0782 while (target.isValid()) { 0783 if (target == boundAbove.value()) { 0784 m_mapping.insert(newEnd, count + boundAbove.key() + newEnd.row() + 1); 0785 q->endRemoveRows(); 0786 return; 0787 } 0788 count += (target.row() + 1); 0789 target = target.parent(); 0790 if (target.isValid()) { 0791 targetParents.push_back(target); 0792 } 0793 } 0794 } 0795 0796 QModelIndex boundParent = boundAbove.value().parent(); 0797 QModelIndex prevParent = boundParent; 0798 Q_ASSERT(boundParent.isValid()); 0799 while (boundParent.isValid()) { 0800 prevParent = boundParent; 0801 boundParent = boundParent.parent(); 0802 0803 if (targetParents.contains(prevParent)) { 0804 break; 0805 } 0806 0807 if (!m_mapping.leftContains(prevParent)) { 0808 break; 0809 } 0810 0811 if (m_mapping.leftToRight(prevParent) > boundAbove.key()) { 0812 break; 0813 } 0814 } 0815 0816 QModelIndex trackedParent = parent; 0817 0818 int proxyRow = boundAbove.key(); 0819 0820 Q_ASSERT(prevParent.isValid()); 0821 proxyRow -= prevParent.row(); 0822 while (trackedParent != boundParent) { 0823 proxyRow += (trackedParent.row() + 1); 0824 trackedParent = trackedParent.parent(); 0825 } 0826 m_mapping.insert(newEnd, proxyRow + newEnd.row()); 0827 q->endRemoveRows(); 0828 } 0829 0830 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destStart) 0831 { 0832 Q_UNUSED(srcParent) 0833 Q_UNUSED(srcStart) 0834 Q_UNUSED(srcEnd) 0835 Q_UNUSED(destParent) 0836 Q_UNUSED(destStart) 0837 sourceLayoutAboutToBeChanged(); 0838 } 0839 0840 void KDescendantsProxyModelPrivate::sourceRowsMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destStart) 0841 { 0842 Q_UNUSED(srcParent) 0843 Q_UNUSED(srcStart) 0844 Q_UNUSED(srcEnd) 0845 Q_UNUSED(destParent) 0846 Q_UNUSED(destStart) 0847 sourceLayoutChanged(); 0848 } 0849 0850 void KDescendantsProxyModelPrivate::sourceModelAboutToBeReset() 0851 { 0852 Q_Q(KDescendantsProxyModel); 0853 q->beginResetModel(); 0854 } 0855 0856 void KDescendantsProxyModelPrivate::sourceModelReset() 0857 { 0858 Q_Q(KDescendantsProxyModel); 0859 resetInternalData(); 0860 if (q->sourceModel()->hasChildren()) { 0861 Q_ASSERT(q->sourceModel()->rowCount() > 0); 0862 m_pendingParents.append(QModelIndex()); 0863 scheduleProcessPendingParents(); 0864 } 0865 q->endResetModel(); 0866 } 0867 0868 void KDescendantsProxyModelPrivate::sourceLayoutAboutToBeChanged() 0869 { 0870 Q_Q(KDescendantsProxyModel); 0871 0872 if (m_ignoreNextLayoutChanged) { 0873 m_ignoreNextLayoutChanged = false; 0874 return; 0875 } 0876 0877 if (m_mapping.isEmpty()) { 0878 return; 0879 } 0880 0881 QPersistentModelIndex srcPersistentIndex; 0882 0883 for (const QModelIndex& proxyPersistentIndex: q->persistentIndexList()) 0884 { 0885 m_proxyIndexes << proxyPersistentIndex; 0886 Q_ASSERT(proxyPersistentIndex.isValid()); 0887 srcPersistentIndex = q->mapToSource(proxyPersistentIndex); 0888 Q_ASSERT(srcPersistentIndex.isValid()); 0889 m_layoutChangePersistentIndexes << srcPersistentIndex; 0890 } 0891 0892 q->layoutAboutToBeChanged(); 0893 } 0894 0895 void KDescendantsProxyModelPrivate::sourceLayoutChanged() 0896 { 0897 Q_Q(KDescendantsProxyModel); 0898 0899 if (m_ignoreNextLayoutAboutToBeChanged) { 0900 m_ignoreNextLayoutAboutToBeChanged = false; 0901 return; 0902 } 0903 0904 if (m_mapping.isEmpty()) { 0905 return; 0906 } 0907 0908 m_rowCount = 0; 0909 0910 synchronousMappingRefresh(); 0911 0912 for (int i = 0; i < m_proxyIndexes.size(); ++i) { 0913 q->changePersistentIndex(m_proxyIndexes.at(i), q->mapFromSource(m_layoutChangePersistentIndexes.at(i))); 0914 } 0915 0916 m_layoutChangePersistentIndexes.clear(); 0917 m_proxyIndexes.clear(); 0918 0919 q->layoutChanged(); 0920 } 0921 0922 void KDescendantsProxyModelPrivate::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) 0923 { 0924 Q_Q(KDescendantsProxyModel); 0925 Q_ASSERT(topLeft.model() == q->sourceModel()); 0926 Q_ASSERT(bottomRight.model() == q->sourceModel()); 0927 0928 const int topRow = topLeft.row(); 0929 const int bottomRow = bottomRight.row(); 0930 0931 for (int i = topRow; i <= bottomRow; ++i) { 0932 const QModelIndex sourceTopLeft = q->sourceModel()->index(i, topLeft.column(), topLeft.parent()); 0933 Q_ASSERT(sourceTopLeft.isValid()); 0934 const QModelIndex proxyTopLeft = q->mapFromSource(sourceTopLeft); 0935 // TODO. If an index does not have any descendants, then we can Q_EMIT in blocks of rows. 0936 // As it is we Q_EMIT once for each row. 0937 const QModelIndex sourceBottomRight = q->sourceModel()->index(i, bottomRight.column(), bottomRight.parent()); 0938 const QModelIndex proxyBottomRight = q->mapFromSource(sourceBottomRight); 0939 Q_ASSERT(proxyTopLeft.isValid()); 0940 Q_ASSERT(proxyBottomRight.isValid()); 0941 Q_EMIT q->dataChanged(proxyTopLeft, proxyBottomRight); 0942 } 0943 } 0944 0945 void KDescendantsProxyModelPrivate::sourceModelDestroyed() 0946 { 0947 resetInternalData(); 0948 } 0949 0950 QMimeData *KDescendantsProxyModel::mimeData(const QModelIndexList &indexes) const 0951 { 0952 if (!sourceModel()) { 0953 return QAbstractProxyModel::mimeData(indexes); 0954 } 0955 Q_ASSERT(sourceModel()); 0956 QModelIndexList sourceIndexes; 0957 for (const QModelIndex &index: indexes) { 0958 sourceIndexes << mapToSource(index); 0959 } 0960 return sourceModel()->mimeData(sourceIndexes); 0961 } 0962 0963 QStringList KDescendantsProxyModel::mimeTypes() const 0964 { 0965 if (!sourceModel()) { 0966 return QAbstractProxyModel::mimeTypes(); 0967 } 0968 Q_ASSERT(sourceModel()); 0969 return sourceModel()->mimeTypes(); 0970 } 0971 0972 Qt::DropActions KDescendantsProxyModel::supportedDropActions() const 0973 { 0974 if (!sourceModel()) { 0975 return QAbstractProxyModel::supportedDropActions(); 0976 } 0977 return sourceModel()->supportedDropActions(); 0978 } 0979 0980 } 0981 0982 #include "moc_kdescendantsproxymodel.cpp"