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"