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