File indexing completed on 2024-05-12 15:42:58

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 
0013 #include "kbihash_p.h"
0014 
0015 typedef KHash2Map<QPersistentModelIndex, int> Mapping;
0016 
0017 class KDescendantsProxyModelPrivate
0018 {
0019     KDescendantsProxyModelPrivate(KDescendantsProxyModel *qq)
0020         : q_ptr(qq)
0021         , m_rowCount(0)
0022         , m_ignoreNextLayoutAboutToBeChanged(false)
0023         , m_ignoreNextLayoutChanged(false)
0024         , m_relayouting(false)
0025         , m_displayAncestorData(false)
0026         , m_ancestorSeparator(QStringLiteral(" / "))
0027     {
0028     }
0029 
0030     Q_DECLARE_PUBLIC(KDescendantsProxyModel)
0031     KDescendantsProxyModel *const q_ptr;
0032 
0033     mutable QVector<QPersistentModelIndex> m_pendingParents;
0034 
0035     void scheduleProcessPendingParents() const;
0036     void processPendingParents();
0037 
0038     void synchronousMappingRefresh();
0039 
0040     void updateInternalIndexes(int start, int offset);
0041 
0042     void resetInternalData();
0043 
0044     void notifyhasSiblings(const QModelIndex &parent);
0045     void sourceRowsAboutToBeInserted(const QModelIndex &, int, int);
0046     void sourceRowsInserted(const QModelIndex &, int, int);
0047     void sourceRowsAboutToBeRemoved(const QModelIndex &, int, int);
0048     void sourceRowsRemoved(const QModelIndex &, int, int);
0049     void sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int);
0050     void sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
0051     void sourceModelAboutToBeReset();
0052     void sourceModelReset();
0053     void sourceLayoutAboutToBeChanged();
0054     void sourceLayoutChanged();
0055     void sourceDataChanged(const QModelIndex &, const QModelIndex &);
0056     void sourceModelDestroyed();
0057 
0058     Mapping m_mapping;
0059     int m_rowCount;
0060     QPair<int, int> m_removePair;
0061     QPair<int, int> m_insertPair;
0062 
0063     bool m_expandsByDefault = true;
0064     bool m_ignoreNextLayoutAboutToBeChanged;
0065     bool m_ignoreNextLayoutChanged;
0066     bool m_relayouting;
0067 
0068     bool m_displayAncestorData;
0069     QString m_ancestorSeparator;
0070 
0071     QSet<QPersistentModelIndex> m_expandedSourceIndexes;
0072     QSet<QPersistentModelIndex> m_collapsedSourceIndexes;
0073 
0074     QList<QPersistentModelIndex> m_layoutChangePersistentIndexes;
0075     QModelIndexList m_proxyIndexes;
0076 };
0077 
0078 void KDescendantsProxyModelPrivate::resetInternalData()
0079 {
0080     m_rowCount = 0;
0081     m_mapping.clear();
0082     m_layoutChangePersistentIndexes.clear();
0083     m_proxyIndexes.clear();
0084 }
0085 
0086 void KDescendantsProxyModelPrivate::synchronousMappingRefresh()
0087 {
0088     m_rowCount = 0;
0089     m_mapping.clear();
0090     m_pendingParents.clear();
0091 
0092     m_pendingParents.append(QModelIndex());
0093 
0094     m_relayouting = true;
0095     while (!m_pendingParents.isEmpty()) {
0096         processPendingParents();
0097     }
0098     m_relayouting = false;
0099 }
0100 
0101 void KDescendantsProxyModelPrivate::scheduleProcessPendingParents() const
0102 {
0103     const_cast<KDescendantsProxyModelPrivate *>(this)->processPendingParents();
0104 }
0105 
0106 void KDescendantsProxyModelPrivate::processPendingParents()
0107 {
0108     Q_Q(KDescendantsProxyModel);
0109     const QVector<QPersistentModelIndex>::iterator begin = m_pendingParents.begin();
0110     QVector<QPersistentModelIndex>::iterator it = begin;
0111 
0112     const QVector<QPersistentModelIndex>::iterator end = m_pendingParents.end();
0113 
0114     QVector<QPersistentModelIndex> newPendingParents;
0115 
0116     while (it != end && it != m_pendingParents.end()) {
0117         const QModelIndex sourceParent = *it;
0118         if (!sourceParent.isValid() && m_rowCount > 0) {
0119             // It was removed from the source model before it was inserted.
0120             it = m_pendingParents.erase(it);
0121             continue;
0122         }
0123         if (!q->isSourceIndexVisible(sourceParent)) {
0124             // It's a collapsed node, or its parents are collapsed, ignore.
0125             it = m_pendingParents.erase(it);
0126             continue;
0127         }
0128 
0129         const int rowCount = q->sourceModel()->rowCount(sourceParent);
0130 
0131         // A node can be marked as collapsed or expanded even if it doesn't have children
0132         if (rowCount == 0) {
0133             it = m_pendingParents.erase(it);
0134             continue;
0135         }
0136         const QPersistentModelIndex sourceIndex = q->sourceModel()->index(rowCount - 1, 0, sourceParent);
0137 
0138         Q_ASSERT(sourceIndex.isValid());
0139 
0140         const QModelIndex proxyParent = q->mapFromSource(sourceParent);
0141 
0142         Q_ASSERT(sourceParent.isValid() == proxyParent.isValid());
0143         const int proxyEndRow = proxyParent.row() + rowCount;
0144         const int proxyStartRow = proxyEndRow - rowCount + 1;
0145 
0146         if (!m_relayouting) {
0147             q->beginInsertRows(QModelIndex(), proxyStartRow, proxyEndRow);
0148         }
0149 
0150         updateInternalIndexes(proxyStartRow, rowCount);
0151         m_mapping.insert(sourceIndex, proxyEndRow);
0152         it = m_pendingParents.erase(it);
0153         m_rowCount += rowCount;
0154 
0155         if (!m_relayouting) {
0156             q->endInsertRows();
0157         }
0158 
0159         for (int sourceRow = 0; sourceRow < rowCount; ++sourceRow) {
0160             static const int column = 0;
0161             const QModelIndex child = q->sourceModel()->index(sourceRow, column, sourceParent);
0162             Q_ASSERT(child.isValid());
0163 
0164             if (q->sourceModel()->hasChildren(child) && q->isSourceIndexExpanded(child) && q->sourceModel()->rowCount(child) > 0) {
0165                 newPendingParents.append(child);
0166             }
0167         }
0168     }
0169     m_pendingParents += newPendingParents;
0170     if (!m_pendingParents.isEmpty()) {
0171         processPendingParents();
0172     }
0173     //   scheduleProcessPendingParents();
0174 }
0175 
0176 void KDescendantsProxyModelPrivate::updateInternalIndexes(int start, int offset)
0177 {
0178     // TODO: Make KHash2Map support key updates and do this backwards.
0179     QHash<int, QPersistentModelIndex> updates;
0180     {
0181         Mapping::right_iterator it = m_mapping.rightLowerBound(start);
0182         const Mapping::right_iterator end = m_mapping.rightEnd();
0183 
0184         while (it != end) {
0185             updates.insert(it.key() + offset, *it);
0186             ++it;
0187         }
0188     }
0189 
0190     {
0191         QHash<int, QPersistentModelIndex>::const_iterator it = updates.constBegin();
0192         const QHash<int, QPersistentModelIndex>::const_iterator end = updates.constEnd();
0193 
0194         for (; it != end; ++it) {
0195             m_mapping.insert(it.value(), it.key());
0196         }
0197     }
0198 }
0199 
0200 KDescendantsProxyModel::KDescendantsProxyModel(QObject *parent)
0201     : QAbstractProxyModel(parent)
0202     , d_ptr(new KDescendantsProxyModelPrivate(this))
0203 {
0204 }
0205 
0206 KDescendantsProxyModel::~KDescendantsProxyModel() = default;
0207 
0208 QHash<int, QByteArray> KDescendantsProxyModel::roleNames() const
0209 {
0210     QHash<int, QByteArray> roleNames = QAbstractProxyModel::roleNames();
0211 
0212     roleNames[LevelRole] = "kDescendantLevel";
0213     roleNames[ExpandableRole] = "kDescendantExpandable";
0214     roleNames[ExpandedRole] = "kDescendantExpanded";
0215     roleNames[HasSiblingsRole] = "kDescendantHasSiblings";
0216     return roleNames;
0217 }
0218 
0219 void KDescendantsProxyModel::setExpandsByDefault(bool expand)
0220 {
0221     if (d_ptr->m_expandsByDefault == expand) {
0222         return;
0223     }
0224 
0225     beginResetModel();
0226     d_ptr->m_expandsByDefault = expand;
0227     d_ptr->m_expandedSourceIndexes.clear();
0228     d_ptr->m_collapsedSourceIndexes.clear();
0229     endResetModel();
0230 }
0231 
0232 bool KDescendantsProxyModel::expandsByDefault() const
0233 {
0234     return d_ptr->m_expandsByDefault;
0235 }
0236 
0237 bool KDescendantsProxyModel::isSourceIndexExpanded(const QModelIndex &sourceIndex) const
0238 {
0239     // Root is always expanded
0240     if (!sourceIndex.isValid()) {
0241         return true;
0242     } else if (d_ptr->m_expandsByDefault) {
0243         return !d_ptr->m_collapsedSourceIndexes.contains(QPersistentModelIndex(sourceIndex));
0244     } else {
0245         return d_ptr->m_expandedSourceIndexes.contains(QPersistentModelIndex(sourceIndex));
0246     }
0247 }
0248 
0249 bool KDescendantsProxyModel::isSourceIndexVisible(const QModelIndex &sourceIndex) const
0250 {
0251     // Root is always visible
0252     if (!sourceIndex.isValid()) {
0253         return true;
0254     }
0255 
0256     QModelIndex index(sourceIndex);
0257     do {
0258         index = index.parent();
0259         if (!index.isValid()) {
0260             return true;
0261         }
0262     } while (isSourceIndexExpanded(index));
0263 
0264     return false;
0265 }
0266 
0267 void KDescendantsProxyModel::expandSourceIndex(const QModelIndex &sourceIndex)
0268 {
0269     if (!sourceIndex.isValid() || isSourceIndexExpanded(sourceIndex)) {
0270         return;
0271     }
0272 
0273     if (d_ptr->m_expandsByDefault) {
0274         d_ptr->m_collapsedSourceIndexes.remove(QPersistentModelIndex(sourceIndex));
0275     } else {
0276         d_ptr->m_expandedSourceIndexes << QPersistentModelIndex(sourceIndex);
0277     }
0278 
0279     d_ptr->m_pendingParents << sourceIndex;
0280     d_ptr->scheduleProcessPendingParents();
0281     Q_EMIT sourceIndexExpanded(sourceIndex);
0282 
0283     const QModelIndex index = mapFromSource(sourceIndex);
0284     Q_EMIT dataChanged(index, index, {ExpandedRole});
0285 }
0286 
0287 void KDescendantsProxyModel::collapseSourceIndex(const QModelIndex &sourceIndex)
0288 {
0289     if (!sourceIndex.isValid() || !isSourceIndexExpanded(sourceIndex)) {
0290         return;
0291     }
0292 
0293     const int row = mapFromSource(sourceIndex).row();
0294     const int rowStart = row + 1;
0295     int rowEnd = row;
0296 
0297     QList<QModelIndex> toVisit = {sourceIndex};
0298     QSet<QModelIndex> visited;
0299     while (!toVisit.isEmpty()) {
0300         QModelIndex index = toVisit.takeLast();
0301         if (!visited.contains(index)) {
0302             visited << index;
0303             const int nRows = sourceModel()->rowCount(index);
0304             rowEnd += nRows;
0305             for (int i = 0; i < nRows; ++i) {
0306                 QModelIndex child = sourceModel()->index(i, 0, index);
0307                 if (isSourceIndexExpanded(child)) {
0308                     toVisit << child;
0309                 }
0310             }
0311         }
0312     }
0313 
0314     beginRemoveRows(QModelIndex(), rowStart, rowEnd);
0315 
0316     if (d_ptr->m_expandsByDefault) {
0317         d_ptr->m_collapsedSourceIndexes << QPersistentModelIndex(sourceIndex);
0318     } else {
0319         d_ptr->m_expandedSourceIndexes.remove(QPersistentModelIndex(sourceIndex));
0320     }
0321 
0322     {
0323         Mapping::right_iterator it = d_ptr->m_mapping.rightLowerBound(rowStart);
0324         const Mapping::right_iterator endIt = d_ptr->m_mapping.rightUpperBound(rowEnd);
0325 
0326         if (endIt != d_ptr->m_mapping.rightEnd()) {
0327             while (it != endIt) {
0328                 it = d_ptr->m_mapping.eraseRight(it);
0329             }
0330         } else {
0331             while (it != d_ptr->m_mapping.rightUpperBound(rowEnd)) {
0332                 it = d_ptr->m_mapping.eraseRight(it);
0333             }
0334         }
0335     }
0336 
0337     d_ptr->m_removePair = qMakePair(rowStart, rowEnd);
0338 
0339     d_ptr->synchronousMappingRefresh();
0340     endRemoveRows();
0341     Q_EMIT sourceIndexCollapsed(sourceIndex);
0342 
0343     const QModelIndex ownIndex = mapFromSource(sourceIndex);
0344     Q_EMIT dataChanged(ownIndex, ownIndex, {ExpandedRole});
0345 }
0346 
0347 #if KITEMMODELS_BUILD_DEPRECATED_SINCE(4, 8)
0348 void KDescendantsProxyModel::setRootIndex(const QModelIndex &index)
0349 {
0350     Q_UNUSED(index)
0351 }
0352 #endif
0353 
0354 QModelIndexList KDescendantsProxyModel::match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const
0355 {
0356     return QAbstractProxyModel::match(start, role, value, hits, flags);
0357 }
0358 
0359 namespace
0360 {
0361 // we only work on DisplayRole for now
0362 static const QVector<int> changedRoles = {Qt::DisplayRole};
0363 }
0364 
0365 void KDescendantsProxyModel::setDisplayAncestorData(bool display)
0366 {
0367     Q_D(KDescendantsProxyModel);
0368     bool displayChanged = (display != d->m_displayAncestorData);
0369     d->m_displayAncestorData = display;
0370     if (displayChanged) {
0371         Q_EMIT displayAncestorDataChanged();
0372         // send out big hammer. Everything needs to be updated.
0373         Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1), changedRoles);
0374     }
0375 }
0376 
0377 bool KDescendantsProxyModel::displayAncestorData() const
0378 {
0379     Q_D(const KDescendantsProxyModel);
0380     return d->m_displayAncestorData;
0381 }
0382 
0383 void KDescendantsProxyModel::setAncestorSeparator(const QString &separator)
0384 {
0385     Q_D(KDescendantsProxyModel);
0386     bool separatorChanged = (separator != d->m_ancestorSeparator);
0387     d->m_ancestorSeparator = separator;
0388     if (separatorChanged) {
0389         Q_EMIT ancestorSeparatorChanged();
0390         if (d->m_displayAncestorData) {
0391             // send out big hammer. Everything needs to be updated.
0392             Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1), changedRoles);
0393         }
0394     }
0395 }
0396 
0397 QString KDescendantsProxyModel::ancestorSeparator() const
0398 {
0399     Q_D(const KDescendantsProxyModel);
0400     return d->m_ancestorSeparator;
0401 }
0402 
0403 void KDescendantsProxyModel::setSourceModel(QAbstractItemModel *_sourceModel)
0404 {
0405     Q_D(KDescendantsProxyModel);
0406 
0407     beginResetModel();
0408 
0409     if (sourceModel()) {
0410         disconnect(sourceModel(), nullptr, this, nullptr);
0411     }
0412 
0413     QAbstractProxyModel::setSourceModel(_sourceModel);
0414     d_ptr->m_expandedSourceIndexes.clear();
0415 
0416     if (_sourceModel) {
0417         connect(_sourceModel, &QAbstractItemModel::rowsAboutToBeInserted, this, [d](const QModelIndex &parent, int start, int end) {
0418             d->sourceRowsAboutToBeInserted(parent, start, end);
0419         });
0420 
0421         connect(_sourceModel, &QAbstractItemModel::rowsInserted, this, [d](const QModelIndex &parent, int start, int end) {
0422             d->sourceRowsInserted(parent, start, end);
0423         });
0424 
0425         connect(_sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, [d](const QModelIndex &parent, int start, int end) {
0426             d->sourceRowsAboutToBeRemoved(parent, start, end);
0427         });
0428 
0429         connect(_sourceModel, &QAbstractItemModel::rowsRemoved, this, [d](const QModelIndex &parent, int start, int end) {
0430             d->sourceRowsRemoved(parent, start, end);
0431         });
0432 
0433         connect(_sourceModel,
0434                 &QAbstractItemModel::rowsAboutToBeMoved,
0435                 this,
0436                 [d](const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destStart) {
0437                     d->sourceRowsAboutToBeMoved(srcParent, srcStart, srcEnd, destParent, destStart);
0438                 });
0439 
0440         connect(_sourceModel,
0441                 &QAbstractItemModel::rowsMoved,
0442                 this,
0443                 [d](const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destStart) {
0444                     d->sourceRowsMoved(srcParent, srcStart, srcEnd, destParent, destStart);
0445                 });
0446 
0447         connect(_sourceModel, &QAbstractItemModel::modelAboutToBeReset, this, [d]() {
0448             d->sourceModelAboutToBeReset();
0449         });
0450 
0451         connect(_sourceModel, &QAbstractItemModel::modelReset, this, [d]() {
0452             d->sourceModelReset();
0453         });
0454 
0455         connect(_sourceModel, &QAbstractItemModel::dataChanged, this, [d](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
0456             d->sourceDataChanged(topLeft, bottomRight);
0457         });
0458 
0459         connect(_sourceModel, &QAbstractItemModel::layoutAboutToBeChanged, this, [d]() {
0460             d->sourceLayoutAboutToBeChanged();
0461         });
0462 
0463         connect(_sourceModel, &QAbstractItemModel::layoutChanged, this, [d]() {
0464             d->sourceLayoutChanged();
0465         });
0466 
0467         connect(_sourceModel, &QObject::destroyed, this, [d]() {
0468             d->sourceModelDestroyed();
0469         });
0470     }
0471 
0472     resetInternalData();
0473     if (_sourceModel && _sourceModel->hasChildren()) {
0474         d->synchronousMappingRefresh();
0475     }
0476 
0477     endResetModel();
0478     Q_EMIT sourceModelChanged();
0479 }
0480 
0481 QModelIndex KDescendantsProxyModel::parent(const QModelIndex &index) const
0482 {
0483     Q_UNUSED(index)
0484     return QModelIndex();
0485 }
0486 
0487 bool KDescendantsProxyModel::hasChildren(const QModelIndex &parent) const
0488 {
0489     Q_D(const KDescendantsProxyModel);
0490     return !(d->m_mapping.isEmpty() || parent.isValid());
0491 }
0492 
0493 int KDescendantsProxyModel::rowCount(const QModelIndex &parent) const
0494 {
0495     Q_D(const KDescendantsProxyModel);
0496     if (d->m_pendingParents.contains(parent) || parent.isValid() || !sourceModel()) {
0497         return 0;
0498     }
0499 
0500     if (d->m_mapping.isEmpty() && sourceModel()->hasChildren()) {
0501         const_cast<KDescendantsProxyModelPrivate *>(d)->synchronousMappingRefresh();
0502     }
0503     return d->m_rowCount;
0504 }
0505 
0506 QModelIndex KDescendantsProxyModel::index(int row, int column, const QModelIndex &parent) const
0507 {
0508     if (parent.isValid()) {
0509         return QModelIndex();
0510     }
0511 
0512     if (!hasIndex(row, column, parent)) {
0513         return QModelIndex();
0514     }
0515 
0516     return createIndex(row, column);
0517 }
0518 
0519 QModelIndex KDescendantsProxyModel::mapToSource(const QModelIndex &proxyIndex) const
0520 {
0521     Q_D(const KDescendantsProxyModel);
0522     if (d->m_mapping.isEmpty() || !proxyIndex.isValid() || !sourceModel()) {
0523         return QModelIndex();
0524     }
0525 
0526     const Mapping::right_const_iterator result = d->m_mapping.rightLowerBound(proxyIndex.row());
0527     Q_ASSERT(result != d->m_mapping.rightEnd());
0528 
0529     const int proxyLastRow = result.key();
0530     const QModelIndex sourceLastChild = result.value();
0531     Q_ASSERT(sourceLastChild.isValid());
0532 
0533     // proxyLastRow is greater than proxyIndex.row().
0534     // sourceLastChild is vertically below the result we're looking for
0535     // and not necessarily in the correct parent.
0536     // We travel up through its parent hierarchy until we are in the
0537     // right parent, then return the correct sibling.
0538 
0539     // Source:           Proxy:    Row
0540     // - A               - A       - 0
0541     // - B               - B       - 1
0542     // - C               - C       - 2
0543     // - D               - D       - 3
0544     // - - E             - E       - 4
0545     // - - F             - F       - 5
0546     // - - G             - G       - 6
0547     // - - H             - H       - 7
0548     // - - I             - I       - 8
0549     // - - - J           - J       - 9
0550     // - - - K           - K       - 10
0551     // - - - L           - L       - 11
0552     // - - M             - M       - 12
0553     // - - N             - N       - 13
0554     // - O               - O       - 14
0555 
0556     // Note that L, N and O are lastChildIndexes, and therefore have a mapping. If we
0557     // are trying to map G from the proxy to the source, We at this point have an iterator
0558     // pointing to (L -> 11). The proxy row of G is 6. (proxyIndex.row() == 6). We seek the
0559     // sourceIndex which is vertically above L by the distance proxyLastRow - proxyIndex.row().
0560     // In this case the verticalDistance is 5.
0561 
0562     int verticalDistance = proxyLastRow - proxyIndex.row();
0563 
0564     // We traverse the ancestors of L, until we can index the desired row in the source.
0565 
0566     QModelIndex ancestor = sourceLastChild;
0567     while (ancestor.isValid()) {
0568         const int ancestorRow = ancestor.row();
0569         if (verticalDistance <= ancestorRow) {
0570             return ancestor.sibling(ancestorRow - verticalDistance, proxyIndex.column());
0571         }
0572         verticalDistance -= (ancestorRow + 1);
0573         ancestor = ancestor.parent();
0574     }
0575     Q_ASSERT(!"Didn't find target row.");
0576     return QModelIndex();
0577 }
0578 
0579 QModelIndex KDescendantsProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
0580 {
0581     Q_D(const KDescendantsProxyModel);
0582 
0583     if (!sourceModel()) {
0584         return QModelIndex();
0585     }
0586 
0587     if (d->m_mapping.isEmpty()) {
0588         return QModelIndex();
0589     }
0590 
0591     {
0592         // TODO: Consider a parent Mapping to speed this up.
0593 
0594         Mapping::right_const_iterator it = d->m_mapping.rightConstBegin();
0595         const Mapping::right_const_iterator end = d->m_mapping.rightConstEnd();
0596         const QModelIndex sourceParent = sourceIndex.parent();
0597         Mapping::right_const_iterator result = end;
0598 
0599         if (!isSourceIndexVisible(sourceIndex)) {
0600             return QModelIndex();
0601         }
0602 
0603         for (; it != end; ++it) {
0604             QModelIndex index = it.value();
0605             bool found_block = false;
0606             while (index.isValid()) {
0607                 const QModelIndex ancestor = index.parent();
0608                 if (ancestor == sourceParent && index.row() >= sourceIndex.row()) {
0609                     found_block = true;
0610                     if (result == end || it.key() < result.key()) {
0611                         result = it;
0612                         break; // Leave the while loop. index is still valid.
0613                     }
0614                 }
0615                 index = ancestor;
0616             }
0617             if (found_block && !index.isValid())
0618             // Looked through the ascendants of it.key() without finding sourceParent.
0619             // That means we've already got the result we need.
0620             {
0621                 break;
0622             }
0623         }
0624         Q_ASSERT(result != end);
0625         const QModelIndex sourceLastChild = result.value();
0626         int proxyRow = result.key();
0627         QModelIndex index = sourceLastChild;
0628         while (index.isValid()) {
0629             const QModelIndex ancestor = index.parent();
0630             if (ancestor == sourceParent) {
0631                 return createIndex(proxyRow - (index.row() - sourceIndex.row()), sourceIndex.column());
0632             }
0633             proxyRow -= (index.row() + 1);
0634             index = ancestor;
0635         }
0636         Q_ASSERT(!"Didn't find valid proxy mapping.");
0637         return QModelIndex();
0638     }
0639 }
0640 
0641 int KDescendantsProxyModel::columnCount(const QModelIndex &parent) const
0642 {
0643     if (parent.isValid() /* || rowCount(parent) == 0 */ || !sourceModel()) {
0644         return 0;
0645     }
0646 
0647     return sourceModel()->columnCount();
0648 }
0649 
0650 QVariant KDescendantsProxyModel::data(const QModelIndex &index, int role) const
0651 {
0652     Q_D(const KDescendantsProxyModel);
0653 
0654     if (!sourceModel()) {
0655         return QVariant();
0656     }
0657 
0658     if (!index.isValid()) {
0659         return sourceModel()->data(index, role);
0660     }
0661 
0662     QModelIndex sourceIndex = mapToSource(index);
0663 
0664     if ((d->m_displayAncestorData) && (role == Qt::DisplayRole)) {
0665         if (!sourceIndex.isValid()) {
0666             return QVariant();
0667         }
0668         QString displayData = sourceIndex.data().toString();
0669         sourceIndex = sourceIndex.parent();
0670         while (sourceIndex.isValid()) {
0671             displayData.prepend(d->m_ancestorSeparator);
0672             displayData.prepend(sourceIndex.data().toString());
0673             sourceIndex = sourceIndex.parent();
0674         }
0675         return displayData;
0676     } else if (role == LevelRole) {
0677         QModelIndex sourceIndex = mapToSource(index);
0678         int level = 0;
0679         while (sourceIndex.isValid()) {
0680             sourceIndex = sourceIndex.parent();
0681             ++level;
0682         }
0683         return level;
0684     } else if (role == ExpandableRole) {
0685         QModelIndex sourceIndex = mapToSource(index);
0686         return sourceModel()->hasChildren(sourceIndex);
0687     } else if (role == ExpandedRole) {
0688         return isSourceIndexExpanded(mapToSource(index));
0689     } else if (role == HasSiblingsRole) {
0690         QModelIndex sourceIndex = mapToSource(index);
0691         QList<bool> hasSibling;
0692         while (sourceIndex.isValid()) {
0693             hasSibling.prepend(sourceModel()->rowCount(sourceIndex.parent()) > sourceIndex.row() + 1);
0694             sourceIndex = sourceIndex.parent();
0695         }
0696         return QVariant::fromValue(hasSibling);
0697     } else {
0698         return sourceIndex.data(role);
0699     }
0700 }
0701 
0702 QVariant KDescendantsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
0703 {
0704     if (!sourceModel() || columnCount() <= section) {
0705         return QVariant();
0706     }
0707 
0708     // Here is safe to do sourceModel()->headerData, as in this proxy we neither filter out nor reorder columns
0709     return sourceModel()->headerData(section, orientation, role);
0710 }
0711 
0712 Qt::ItemFlags KDescendantsProxyModel::flags(const QModelIndex &index) const
0713 {
0714     if (!index.isValid() || !sourceModel()) {
0715         return QAbstractProxyModel::flags(index);
0716     }
0717 
0718     const QModelIndex srcIndex = mapToSource(index);
0719     Q_ASSERT(srcIndex.isValid());
0720     return sourceModel()->flags(srcIndex);
0721 }
0722 
0723 void KDescendantsProxyModelPrivate::notifyhasSiblings(const QModelIndex &parent)
0724 {
0725     Q_Q(KDescendantsProxyModel);
0726 
0727     if (!parent.isValid()) {
0728         return;
0729     }
0730 
0731     QModelIndex localParent = q->mapFromSource(parent);
0732     Q_EMIT q->dataChanged(localParent, localParent, {KDescendantsProxyModel::HasSiblingsRole});
0733     for (int i = 0; i < q->sourceModel()->rowCount(parent); ++i) {
0734         notifyhasSiblings(q->sourceModel()->index(i, 0, parent));
0735     }
0736 }
0737 
0738 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
0739 {
0740     Q_Q(KDescendantsProxyModel);
0741 
0742     if (parent.isValid() && (!q->isSourceIndexExpanded(parent) || !q->isSourceIndexVisible(parent))) {
0743         return;
0744     }
0745 
0746     if (!q->sourceModel()->hasChildren(parent)) {
0747         Q_ASSERT(q->sourceModel()->rowCount(parent) == 0);
0748         // parent was not a parent before.
0749         return;
0750     }
0751 
0752     int proxyStart = -1;
0753 
0754     const int rowCount = q->sourceModel()->rowCount(parent);
0755 
0756     if (rowCount > start) {
0757         const QModelIndex belowStart = q->sourceModel()->index(start, 0, parent);
0758         proxyStart = q->mapFromSource(belowStart).row();
0759     } else if (rowCount == 0) {
0760         proxyStart = q->mapFromSource(parent).row() + 1;
0761     } else {
0762         Q_ASSERT(rowCount == start);
0763         static const int column = 0;
0764         QModelIndex idx = q->sourceModel()->index(rowCount - 1, column, parent);
0765         while (q->isSourceIndexExpanded(idx) && q->sourceModel()->hasChildren(idx) && q->sourceModel()->rowCount(idx) > 0) {
0766             idx = q->sourceModel()->index(q->sourceModel()->rowCount(idx) - 1, column, idx);
0767         }
0768         // The last item in the list is getting a sibling below it.
0769         proxyStart = q->mapFromSource(idx).row() + 1;
0770     }
0771     const int proxyEnd = proxyStart + (end - start);
0772 
0773     m_insertPair = qMakePair(proxyStart, proxyEnd);
0774     q->beginInsertRows(QModelIndex(), proxyStart, proxyEnd);
0775 }
0776 
0777 void KDescendantsProxyModelPrivate::sourceRowsInserted(const QModelIndex &parent, int start, int end)
0778 {
0779     Q_Q(KDescendantsProxyModel);
0780     if (parent.isValid() && (!q->isSourceIndexExpanded(parent) || !q->isSourceIndexVisible(parent))) {
0781         const QModelIndex index = q->mapFromSource(parent);
0782         Q_EMIT q->dataChanged(index,
0783                               index,
0784                               {KDescendantsProxyModel::ExpandableRole, KDescendantsProxyModel::ExpandedRole, KDescendantsProxyModel::HasSiblingsRole});
0785         if (start > 0) {
0786             notifyhasSiblings(q->sourceModel()->index(start - 1, 0, parent));
0787         }
0788         return;
0789     }
0790     Q_ASSERT(q->sourceModel()->index(start, 0, parent).isValid());
0791 
0792     const int rowCount = q->sourceModel()->rowCount(parent);
0793     Q_ASSERT(rowCount > 0);
0794 
0795     const int difference = end - start + 1;
0796 
0797     if (rowCount == difference) {
0798         const QModelIndex index = q->mapFromSource(parent);
0799         if (parent.isValid()) {
0800             Q_EMIT q->dataChanged(index,
0801                                   index,
0802                                   {KDescendantsProxyModel::ExpandableRole, KDescendantsProxyModel::ExpandedRole, KDescendantsProxyModel::HasSiblingsRole});
0803         }
0804         // @p parent was not a parent before.
0805         m_pendingParents.append(parent);
0806         scheduleProcessPendingParents();
0807         if (start > 0) {
0808             notifyhasSiblings(q->sourceModel()->index(start - 1, 0, parent));
0809         }
0810         return;
0811     }
0812 
0813     const int proxyStart = m_insertPair.first;
0814 
0815     Q_ASSERT(proxyStart >= 0);
0816 
0817     updateInternalIndexes(proxyStart, difference);
0818 
0819     if (rowCount - 1 == end) {
0820         // The previously last row (the mapped one) is no longer the last.
0821         // For example,
0822 
0823         // - A            - A           0
0824         // - - B          - B           1
0825         // - - C          - C           2
0826         // - - - D        - D           3
0827         // - - - E   ->   - E           4
0828         // - - F          - F           5
0829         // - - G     ->   - G           6
0830         // - H            - H           7
0831         // - I       ->   - I           8
0832 
0833         // As last children, E, F and G have mappings.
0834         // Consider that 'J' is appended to the children of 'C', below 'E'.
0835 
0836         // - A            - A           0
0837         // - - B          - B           1
0838         // - - C          - C           2
0839         // - - - D        - D           3
0840         // - - - E   ->   - E           4
0841         // - - - J        - ???         5
0842         // - - F          - F           6
0843         // - - G     ->   - G           7
0844         // - H            - H           8
0845         // - I       ->   - I           9
0846 
0847         // The updateInternalIndexes call above will have updated the F and G mappings correctly because proxyStart is 5.
0848         // That means that E -> 4 was not affected by the updateInternalIndexes call.
0849         // Now the mapping for E -> 4 needs to be updated so that it's a mapping for J -> 5.
0850 
0851         Q_ASSERT(!m_mapping.isEmpty());
0852         static const int column = 0;
0853         const QModelIndex oldIndex = q->sourceModel()->index(rowCount - 1 - difference, column, parent);
0854         Q_ASSERT(m_mapping.leftContains(oldIndex));
0855 
0856         const QModelIndex newIndex = q->sourceModel()->index(rowCount - 1, column, parent);
0857 
0858         QModelIndex indexAbove = oldIndex;
0859 
0860         if (start > 0) {
0861             // If we have something like this:
0862             //
0863             // - A
0864             // - - B
0865             // - - C
0866             //
0867             // and we then insert D as a sibling of A below it, we need to remove the mapping for A,
0868             // and the row number used for D must take into account the descendants of A.
0869 
0870             while (q->isSourceIndexExpanded(indexAbove) && q->sourceModel()->hasChildren(indexAbove)) {
0871                 Q_ASSERT(q->sourceModel()->rowCount(indexAbove) > 0);
0872                 indexAbove = q->sourceModel()->index(q->sourceModel()->rowCount(indexAbove) - 1, column, indexAbove);
0873             }
0874             Q_ASSERT(!q->isSourceIndexExpanded(indexAbove) || q->sourceModel()->rowCount(indexAbove) == 0);
0875         }
0876 
0877         Q_ASSERT(m_mapping.leftContains(indexAbove));
0878 
0879         const int newProxyRow = m_mapping.leftToRight(indexAbove) + difference;
0880 
0881         // oldIndex is E in the source. proxyRow is 4.
0882         m_mapping.removeLeft(oldIndex);
0883 
0884         // newIndex is J. (proxyRow + difference) is 5.
0885         m_mapping.insert(newIndex, newProxyRow);
0886     }
0887 
0888     for (int row = start; row <= end; ++row) {
0889         static const int column = 0;
0890         const QModelIndex idx = q->sourceModel()->index(row, column, parent);
0891         Q_ASSERT(idx.isValid());
0892 
0893         if (q->isSourceIndexExpanded(idx) && q->sourceModel()->hasChildren(idx) && q->sourceModel()->rowCount(idx) > 0) {
0894             m_pendingParents.append(idx);
0895         }
0896     }
0897 
0898     m_rowCount += difference;
0899 
0900     q->endInsertRows();
0901     scheduleProcessPendingParents();
0902     if (parent.isValid()) {
0903         const QModelIndex index = q->mapFromSource(parent);
0904         Q_EMIT q->dataChanged(index,
0905                               index,
0906                               {KDescendantsProxyModel::ExpandableRole, KDescendantsProxyModel::ExpandedRole, KDescendantsProxyModel::HasSiblingsRole});
0907     }
0908 
0909     if (start > 0) {
0910         notifyhasSiblings(q->sourceModel()->index(start - 1, 0, parent));
0911     }
0912 }
0913 
0914 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
0915 {
0916     Q_Q(KDescendantsProxyModel);
0917 
0918     if (!q->isSourceIndexExpanded(parent) || !q->isSourceIndexVisible(parent)) {
0919         return;
0920     }
0921 
0922     const int proxyStart = q->mapFromSource(q->sourceModel()->index(start, 0, parent)).row();
0923 
0924     static const int column = 0;
0925     QModelIndex idx = q->sourceModel()->index(end, column, parent);
0926     while (q->sourceModel()->hasChildren(idx) && q->sourceModel()->rowCount(idx) > 0) {
0927         idx = q->sourceModel()->index(q->sourceModel()->rowCount(idx) - 1, column, idx);
0928     }
0929     const int proxyEnd = q->mapFromSource(idx).row();
0930 
0931     for (int i = start; i <= end; ++i) {
0932         QModelIndex idx = q->sourceModel()->index(i, column, parent);
0933         m_expandedSourceIndexes.remove(QPersistentModelIndex(idx));
0934     }
0935 
0936     m_removePair = qMakePair(proxyStart, proxyEnd);
0937 
0938     q->beginRemoveRows(QModelIndex(), proxyStart, proxyEnd);
0939 }
0940 
0941 static QModelIndex getFirstDeepest(QAbstractItemModel *model, const QModelIndex &parent, int *count)
0942 {
0943     static const int column = 0;
0944     Q_ASSERT(model->hasChildren(parent));
0945     Q_ASSERT(model->rowCount(parent) > 0);
0946     for (int row = 0; row < model->rowCount(parent); ++row) {
0947         (*count)++;
0948         const QModelIndex child = model->index(row, column, parent);
0949         Q_ASSERT(child.isValid());
0950         if (model->hasChildren(child)) {
0951             return getFirstDeepest(model, child, count);
0952         }
0953     }
0954     return model->index(model->rowCount(parent) - 1, column, parent);
0955 }
0956 
0957 void KDescendantsProxyModelPrivate::sourceRowsRemoved(const QModelIndex &parent, int start, int end)
0958 {
0959     Q_Q(KDescendantsProxyModel);
0960     Q_UNUSED(end)
0961 
0962     if (!q->isSourceIndexExpanded(parent) || !q->isSourceIndexVisible(parent)) {
0963         if (parent.isValid()) {
0964             const QModelIndex index = q->mapFromSource(parent);
0965             Q_EMIT q->dataChanged(index, index, {KDescendantsProxyModel::ExpandableRole, KDescendantsProxyModel::ExpandedRole});
0966         }
0967         return;
0968     }
0969 
0970     const int rowCount = q->sourceModel()->rowCount(parent);
0971 
0972     const int proxyStart = m_removePair.first;
0973     const int proxyEnd = m_removePair.second;
0974 
0975     const int difference = proxyEnd - proxyStart + 1;
0976     {
0977         Mapping::right_iterator it = m_mapping.rightLowerBound(proxyStart);
0978         const Mapping::right_iterator endIt = m_mapping.rightUpperBound(proxyEnd);
0979 
0980         if (endIt != m_mapping.rightEnd()) {
0981             while (it != endIt) {
0982                 it = m_mapping.eraseRight(it);
0983             }
0984         } else {
0985             while (it != m_mapping.rightUpperBound(proxyEnd)) {
0986                 it = m_mapping.eraseRight(it);
0987             }
0988         }
0989     }
0990 
0991     m_removePair = qMakePair(-1, -1);
0992     m_rowCount -= difference;
0993     Q_ASSERT(m_rowCount >= 0);
0994 
0995     updateInternalIndexes(proxyStart, -1 * difference);
0996 
0997     if (rowCount != start || rowCount == 0) {
0998         q->endRemoveRows();
0999         if (parent.isValid()) {
1000             const QModelIndex index = q->mapFromSource(parent);
1001             Q_EMIT q->dataChanged(index, index, {KDescendantsProxyModel::ExpandableRole, KDescendantsProxyModel::ExpandedRole});
1002         }
1003         if (start > 0) {
1004             notifyhasSiblings(q->sourceModel()->index(start - 1, 0, parent));
1005         }
1006         return;
1007     }
1008 
1009     static const int column = 0;
1010     const QModelIndex newEnd = q->sourceModel()->index(rowCount - 1, column, parent);
1011     Q_ASSERT(newEnd.isValid());
1012 
1013     if (m_mapping.isEmpty()) {
1014         m_mapping.insert(newEnd, newEnd.row());
1015         q->endRemoveRows();
1016         if (start > 0) {
1017             notifyhasSiblings(q->sourceModel()->index(start - 1, 0, parent));
1018         }
1019         return;
1020     }
1021     if (q->sourceModel()->hasChildren(newEnd)) {
1022         int count = 0;
1023         const QModelIndex firstDeepest = getFirstDeepest(q->sourceModel(), newEnd, &count);
1024         Q_ASSERT(firstDeepest.isValid());
1025         const int firstDeepestProxy = m_mapping.leftToRight(firstDeepest);
1026 
1027         m_mapping.insert(newEnd, firstDeepestProxy - count);
1028         q->endRemoveRows();
1029         if (start > 0) {
1030             notifyhasSiblings(q->sourceModel()->index(start - 1, 0, parent));
1031         }
1032         return;
1033     }
1034     Mapping::right_iterator lowerBound = m_mapping.rightLowerBound(proxyStart);
1035     if (lowerBound == m_mapping.rightEnd()) {
1036         int proxyRow = (lowerBound - 1).key();
1037 
1038         for (int row = newEnd.row(); row >= 0; --row) {
1039             const QModelIndex newEndSibling = q->sourceModel()->index(row, column, parent);
1040             if (!q->sourceModel()->hasChildren(newEndSibling)) {
1041                 ++proxyRow;
1042             } else {
1043                 break;
1044             }
1045         }
1046         m_mapping.insert(newEnd, proxyRow);
1047         q->endRemoveRows();
1048         if (start > 0) {
1049             notifyhasSiblings(q->sourceModel()->index(start - 1, 0, parent));
1050         }
1051         return;
1052     } else if (lowerBound == m_mapping.rightBegin()) {
1053         int proxyRow = rowCount - 1;
1054         QModelIndex trackedParent = parent;
1055         while (trackedParent.isValid()) {
1056             proxyRow += (trackedParent.row() + 1);
1057             trackedParent = trackedParent.parent();
1058         }
1059         m_mapping.insert(newEnd, proxyRow);
1060         q->endRemoveRows();
1061         if (start > 0) {
1062             notifyhasSiblings(q->sourceModel()->index(start - 1, 0, parent));
1063         }
1064         return;
1065     }
1066     const Mapping::right_iterator boundAbove = lowerBound - 1;
1067 
1068     QVector<QModelIndex> targetParents;
1069     targetParents.push_back(parent);
1070     {
1071         QModelIndex target = parent;
1072         int count = 0;
1073         while (target.isValid()) {
1074             if (target == boundAbove.value()) {
1075                 m_mapping.insert(newEnd, count + boundAbove.key() + newEnd.row() + 1);
1076                 q->endRemoveRows();
1077                 if (start > 0) {
1078                     notifyhasSiblings(q->sourceModel()->index(start - 1, 0, parent));
1079                 }
1080                 return;
1081             }
1082             count += (target.row() + 1);
1083             target = target.parent();
1084             if (target.isValid()) {
1085                 targetParents.push_back(target);
1086             }
1087         }
1088     }
1089 
1090     QModelIndex boundParent = boundAbove.value().parent();
1091     QModelIndex prevParent = boundParent;
1092     Q_ASSERT(boundParent.isValid());
1093     while (boundParent.isValid()) {
1094         prevParent = boundParent;
1095         boundParent = boundParent.parent();
1096 
1097         if (targetParents.contains(prevParent)) {
1098             break;
1099         }
1100 
1101         if (!m_mapping.leftContains(prevParent)) {
1102             break;
1103         }
1104 
1105         if (m_mapping.leftToRight(prevParent) > boundAbove.key()) {
1106             break;
1107         }
1108     }
1109 
1110     QModelIndex trackedParent = parent;
1111 
1112     int proxyRow = boundAbove.key();
1113 
1114     Q_ASSERT(prevParent.isValid());
1115     proxyRow -= prevParent.row();
1116     while (trackedParent != boundParent) {
1117         proxyRow += (trackedParent.row() + 1);
1118         trackedParent = trackedParent.parent();
1119     }
1120     m_mapping.insert(newEnd, proxyRow + newEnd.row());
1121     q->endRemoveRows();
1122 
1123     if (parent.isValid()) {
1124         const QModelIndex oindex = q->mapFromSource(parent);
1125         QVector<int> rolesChanged({KDescendantsProxyModel::ExpandableRole});
1126 
1127         if (!q->sourceModel()->hasChildren(parent)) {
1128             rolesChanged << KDescendantsProxyModel::ExpandedRole;
1129         } else if (q->sourceModel()->rowCount(parent) <= start) {
1130             const QModelIndex index = q->mapFromSource(q->sourceModel()->index(q->sourceModel()->rowCount(parent) - 1, 0, parent));
1131             Q_EMIT q->dataChanged(index, index, {KDescendantsProxyModel::ExpandedRole});
1132         }
1133 
1134         Q_EMIT q->dataChanged(oindex, oindex, rolesChanged);
1135     }
1136 
1137     if (start > 0) {
1138         notifyhasSiblings(q->sourceModel()->index(start - 1, 0, parent));
1139     }
1140 }
1141 
1142 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeMoved(const QModelIndex &srcParent,
1143                                                              int srcStart,
1144                                                              int srcEnd,
1145                                                              const QModelIndex &destParent,
1146                                                              int destStart)
1147 {
1148     Q_Q(KDescendantsProxyModel);
1149 
1150     Q_UNUSED(destStart)
1151 
1152     if (q->isSourceIndexExpanded(srcParent) && q->isSourceIndexVisible(srcParent)
1153         && (!q->isSourceIndexExpanded(destParent) || !q->isSourceIndexVisible(destParent))) {
1154         const QModelIndex proxySrcParent = q->mapFromSource(srcParent);
1155         const int proxyParentRow = proxySrcParent.isValid() ? proxySrcParent.row() : 0;
1156         q->beginRemoveRows(QModelIndex(), proxyParentRow + srcStart, proxyParentRow + srcEnd);
1157 
1158     } else if ((!q->isSourceIndexExpanded(srcParent) || !q->isSourceIndexVisible(srcParent)) && q->isSourceIndexExpanded(destParent)
1159                && q->isSourceIndexVisible(destParent)) {
1160         const QModelIndex proxyDestParent = q->mapFromSource(srcParent);
1161         const int proxyParentRow = proxyDestParent.isValid() ? proxyDestParent.row() : 0;
1162 
1163         q->beginInsertRows(QModelIndex(), proxyParentRow + destStart, proxyParentRow + destStart + (srcEnd - srcStart));
1164     }
1165 
1166     sourceLayoutAboutToBeChanged();
1167 }
1168 
1169 void KDescendantsProxyModelPrivate::sourceRowsMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destStart)
1170 {
1171     Q_Q(KDescendantsProxyModel);
1172 
1173     Q_UNUSED(srcParent)
1174     Q_UNUSED(srcStart)
1175     Q_UNUSED(srcEnd)
1176     Q_UNUSED(destParent)
1177     Q_UNUSED(destStart)
1178 
1179     if (q->isSourceIndexExpanded(srcParent) && q->isSourceIndexVisible(srcParent)
1180         && (!q->isSourceIndexExpanded(destParent) || !q->isSourceIndexVisible(destParent))) {
1181         q->endRemoveRows();
1182     } else if (!q->isSourceIndexExpanded(srcParent) && q->isSourceIndexExpanded(destParent)) {
1183         q->endInsertRows();
1184     }
1185 
1186     sourceLayoutChanged();
1187 
1188     const QModelIndex index1 = q->mapFromSource(srcParent);
1189     const QModelIndex index2 = q->mapFromSource(destParent);
1190     Q_EMIT q->dataChanged(index1, index1, {KDescendantsProxyModel::ExpandableRole});
1191     if (index1 != index2) {
1192         Q_EMIT q->dataChanged(index2, index2, {KDescendantsProxyModel::ExpandableRole});
1193         if (!q->sourceModel()->hasChildren(destParent)) {
1194             Q_EMIT q->dataChanged(index2, index2, {KDescendantsProxyModel::ExpandableRole});
1195         }
1196     }
1197     const QModelIndex lastIndex = q->mapFromSource(q->sourceModel()->index(q->sourceModel()->rowCount(srcParent) - 1, 0, srcParent));
1198     Q_EMIT q->dataChanged(lastIndex, lastIndex, {KDescendantsProxyModel::ExpandableRole});
1199 
1200     if (srcStart > 0) {
1201         notifyhasSiblings(q->sourceModel()->index(srcStart - 1, 0, srcParent));
1202     }
1203     if (destStart > 0) {
1204         notifyhasSiblings(q->sourceModel()->index(destStart - 1, 0, destParent));
1205     }
1206 }
1207 
1208 void KDescendantsProxyModelPrivate::sourceModelAboutToBeReset()
1209 {
1210     Q_Q(KDescendantsProxyModel);
1211     q->beginResetModel();
1212 }
1213 
1214 void KDescendantsProxyModelPrivate::sourceModelReset()
1215 {
1216     Q_Q(KDescendantsProxyModel);
1217     resetInternalData();
1218     if (q->sourceModel()->hasChildren() && q->sourceModel()->rowCount() > 0) {
1219         m_pendingParents.append(QModelIndex());
1220         scheduleProcessPendingParents();
1221     }
1222     q->endResetModel();
1223 }
1224 
1225 void KDescendantsProxyModelPrivate::sourceLayoutAboutToBeChanged()
1226 {
1227     Q_Q(KDescendantsProxyModel);
1228 
1229     if (m_ignoreNextLayoutChanged) {
1230         m_ignoreNextLayoutChanged = false;
1231         return;
1232     }
1233 
1234     if (m_mapping.isEmpty()) {
1235         return;
1236     }
1237 
1238     Q_EMIT q->layoutAboutToBeChanged();
1239 
1240     QPersistentModelIndex srcPersistentIndex;
1241     const auto lst = q->persistentIndexList();
1242     for (const QModelIndex &proxyPersistentIndex : lst) {
1243         m_proxyIndexes << proxyPersistentIndex;
1244         Q_ASSERT(proxyPersistentIndex.isValid());
1245         srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
1246         Q_ASSERT(srcPersistentIndex.isValid());
1247         m_layoutChangePersistentIndexes << srcPersistentIndex;
1248     }
1249 }
1250 
1251 void KDescendantsProxyModelPrivate::sourceLayoutChanged()
1252 {
1253     Q_Q(KDescendantsProxyModel);
1254 
1255     if (m_ignoreNextLayoutAboutToBeChanged) {
1256         m_ignoreNextLayoutAboutToBeChanged = false;
1257         return;
1258     }
1259 
1260     if (m_mapping.isEmpty()) {
1261         return;
1262     }
1263 
1264     m_rowCount = 0;
1265 
1266     synchronousMappingRefresh();
1267 
1268     for (int i = 0; i < m_proxyIndexes.size(); ++i) {
1269         q->changePersistentIndex(m_proxyIndexes.at(i), q->mapFromSource(m_layoutChangePersistentIndexes.at(i)));
1270     }
1271 
1272     m_layoutChangePersistentIndexes.clear();
1273     m_proxyIndexes.clear();
1274 
1275     Q_EMIT q->layoutChanged();
1276 }
1277 
1278 void KDescendantsProxyModelPrivate::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
1279 {
1280     Q_Q(KDescendantsProxyModel);
1281     // It is actually possible in a real world scenario that the source model emits dataChanged
1282     // with invalid indexes when the source model is a QSortFilterProxyModel
1283     // because QSortFilterProxyModel doesn't check for mapped index validity when its
1284     // source model emitted dataChanged on a column QSortFilterProxyModel doesn't accept.
1285     // See https://bugreports.qt.io/browse/QTBUG-86850
1286     if (!topLeft.isValid() || !bottomRight.isValid()) {
1287         return;
1288     }
1289     Q_ASSERT(topLeft.model() == q->sourceModel());
1290     Q_ASSERT(bottomRight.model() == q->sourceModel());
1291 
1292     if (!q->isSourceIndexExpanded(topLeft.parent()) || !q->isSourceIndexVisible(topLeft.parent())) {
1293         return;
1294     }
1295 
1296     const int topRow = topLeft.row();
1297     const int bottomRow = bottomRight.row();
1298 
1299     for (int i = topRow; i <= bottomRow; ++i) {
1300         const QModelIndex sourceTopLeft = q->sourceModel()->index(i, topLeft.column(), topLeft.parent());
1301 
1302         Q_ASSERT(sourceTopLeft.isValid());
1303         const QModelIndex proxyTopLeft = q->mapFromSource(sourceTopLeft);
1304         // TODO. If an index does not have any descendants, then we can emit in blocks of rows.
1305         // As it is we emit once for each row.
1306         const QModelIndex sourceBottomRight = q->sourceModel()->index(i, bottomRight.column(), bottomRight.parent());
1307         const QModelIndex proxyBottomRight = q->mapFromSource(sourceBottomRight);
1308         Q_ASSERT(proxyTopLeft.isValid());
1309         Q_ASSERT(proxyBottomRight.isValid());
1310         Q_EMIT q->dataChanged(proxyTopLeft, proxyBottomRight);
1311     }
1312 }
1313 
1314 void KDescendantsProxyModelPrivate::sourceModelDestroyed()
1315 {
1316     resetInternalData();
1317 }
1318 
1319 QMimeData *KDescendantsProxyModel::mimeData(const QModelIndexList &indexes) const
1320 {
1321     if (!sourceModel()) {
1322         return QAbstractProxyModel::mimeData(indexes);
1323     }
1324     Q_ASSERT(sourceModel());
1325     QModelIndexList sourceIndexes;
1326     for (const QModelIndex &index : indexes) {
1327         sourceIndexes << mapToSource(index);
1328     }
1329     return sourceModel()->mimeData(sourceIndexes);
1330 }
1331 
1332 QStringList KDescendantsProxyModel::mimeTypes() const
1333 {
1334     if (!sourceModel()) {
1335         return QAbstractProxyModel::mimeTypes();
1336     }
1337     Q_ASSERT(sourceModel());
1338     return sourceModel()->mimeTypes();
1339 }
1340 
1341 Qt::DropActions KDescendantsProxyModel::supportedDropActions() const
1342 {
1343     if (!sourceModel()) {
1344         return QAbstractProxyModel::supportedDropActions();
1345     }
1346     return sourceModel()->supportedDropActions();
1347 }
1348 
1349 #include "moc_kdescendantsproxymodel.cpp"