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"