File indexing completed on 2024-07-21 03:42:03

0001 /*
0002     SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "kreparentingproxymodel.h"
0008 #include <QDebug>
0009 #include <QList>
0010 
0011 #include <algorithm>
0012 #include <functional>
0013 
0014 class KReparentingProxyModelPrivate
0015 {
0016     KReparentingProxyModelPrivate(KReparentingProxyModel *proxyModel)
0017         : m_nextId(0)
0018         , q_ptr(proxyModel)
0019     {
0020     }
0021 
0022     qint64 newId() const
0023     {
0024         return m_nextId++;
0025     }
0026 
0027     enum MapStrategy {
0028         MapDescendants,
0029         MapChildrenOnly,
0030     };
0031 
0032     /**
0033       Creates mappings of indexes in the source model between @p start
0034       and @p end which should be represented in the proxy model as descendants
0035       of @p parent.
0036     */
0037     QHash<QModelIndex, QModelIndexList> recreateMappings(const QModelIndex &parent, int start, int end = -1, int strategy = MapChildrenOnly) const;
0038 
0039     /**
0040       Merges all indexes from @p mappings which are descendants of @p parent into the model.
0041       Returns the remaining mappings.
0042 
0043       Note that this changes the internal model structure and must only be called between begin/end insert/remove/move/reset calls.
0044     */
0045     QHash<QModelIndex, QModelIndexList> mergeDescendants(QHash<QModelIndex, QModelIndexList> mappings, const QModelIndex &parent, int start);
0046 
0047     /**
0048       Verifies that the indexes below @p parent between @p start and rowCount(parent)
0049       are in the correct positions in the proxy model. Repositions them if not.
0050     */
0051     void verifyStructure(const QModelIndex &parent, int start);
0052 
0053     /**
0054       Returns the index vertically below index in the model @p model.
0055       If @p model is 0, the sourceModel is used
0056       Returns an invalid index if there is no index below @p index.
0057     */
0058     QModelIndex getIndexBelow(const QModelIndex &index, QAbstractItemModel *model = nullptr) const;
0059 
0060     /**
0061       Returns the last descendant of @p index or itself if it has no children
0062     */
0063     QModelIndex getLastDescendant(const QModelIndex &index) const;
0064 
0065     bool isDescendantInModel(const QModelIndex &ancestor, const QModelIndex &descendant) const;
0066 
0067     /**
0068       Returns the ancestors of @p descendant that are already in the proxy model.
0069 
0070       Note that @p descendant does not have to be in the proxy yet, and it is not part of the
0071       result list.
0072     */
0073     QList<QModelIndex> getExistingAncestors(const QModelIndex &descendant) const;
0074 
0075     void sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
0076     void sourceRowsInserted(const QModelIndex &parent, int start, int end);
0077     void sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
0078     void sourceRowsRemoved(const QModelIndex &parent, int start, int end);
0079     void sourceRowsAboutToBeMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destParent, int destRow);
0080     void sourceRowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destParent, int destRow);
0081     void sourceModelAboutToBeReset();
0082     void endResetProxy();
0083     void sourceModelReset();
0084     void sourceLayoutAboutToBeChanged();
0085     void sourceLayoutChanged();
0086     void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
0087 
0088     mutable QHash<qint64, QPersistentModelIndex> m_parents;
0089     mutable QHash<QPersistentModelIndex, QList<QPersistentModelIndex>> m_childIndexes;
0090 
0091     struct PendingInsertion {
0092         PendingInsertion()
0093             : parentId(-1)
0094             , start(-1)
0095             , end(-1)
0096         {
0097         }
0098 
0099         PendingInsertion(const QModelIndex &_index, int _start, int _end)
0100             : index(_index)
0101             , start(_start)
0102             , end(_end)
0103         {
0104         }
0105 
0106         QPersistentModelIndex index;
0107         QModelIndex sourceIndex;
0108         qint64 parentId;
0109         int start;
0110         int end;
0111     };
0112 
0113     struct PendingRemoval : PendingInsertion {
0114         int numTrailing;
0115     };
0116     // Needed between the beginRemoveRows and endRemoveRows signals.
0117     mutable QHash<qint64, QPersistentModelIndex> m_pendingRemovalParents;
0118     mutable QHash<QPersistentModelIndex, QList<QPersistentModelIndex>> m_pendingRemovalChildIndexes;
0119 
0120     QHash<QModelIndex, QModelIndexList> insertTree(QHash<QModelIndex, QModelIndexList> mappings, const QModelIndex &parent);
0121 
0122     void handleInsertion(const PendingInsertion &pendingInsertion);
0123 
0124     void handleRemoval(const PendingRemoval &pendingRemoval);
0125 
0126     mutable QHash<QModelIndex, PendingInsertion> m_pendingInsertions;
0127     mutable QList<PendingRemoval> m_pendingRemovals;
0128 
0129     mutable qint64 m_nextId;
0130 
0131     Q_DECLARE_PUBLIC(KReparentingProxyModel)
0132     KReparentingProxyModel *q_ptr;
0133 
0134     QList<QPersistentModelIndex> m_layoutChangePersistentIndexes;
0135     QModelIndexList m_proxyIndexes;
0136 
0137     void emitDataChangedSignals(const QModelIndex &parent, int maxChanged);
0138 
0139     /**
0140       Given @p parent in the proxy model, return the last index lying between @p start and @p end
0141       which is also a descendant of @p parent.
0142     */
0143     QModelIndex findLastInParent(QModelIndex parent, int start, int end);
0144 
0145     /**
0146       Removes @P idx (which is a source model index) and its children from the model data structures.
0147     */
0148     void removeTree(const QPersistentModelIndex &idx, int start = 0, int end = -1);
0149 
0150     int pendingRemovalRowCount(const QModelIndex &sourceIndex) const;
0151 };
0152 
0153 class LessThan
0154 {
0155     const KReparentingProxyModel *m_model;
0156 
0157 public:
0158     LessThan(const KReparentingProxyModel *model)
0159         : m_model(model)
0160     {
0161     }
0162     bool operator()(const QModelIndex &ancestor, const QModelIndex &descendant)
0163     {
0164         return m_model->isDescendantOf(ancestor, descendant);
0165     }
0166 };
0167 
0168 QModelIndex KReparentingProxyModelPrivate::getIndexBelow(const QModelIndex &index, QAbstractItemModel *model) const
0169 {
0170     Q_Q(const KReparentingProxyModel);
0171 
0172     //   qDebug() << index.data() << index;
0173 
0174     if (!model) {
0175         model = q->sourceModel();
0176     }
0177 
0178     if (model->hasChildren(index)) {
0179         return model->index(0, 0, index);
0180     }
0181 
0182     QModelIndex sibling = index.sibling(index.row() + 1, index.column());
0183     if (sibling.isValid()) {
0184         return sibling;
0185     }
0186 
0187     QModelIndex parent = index.parent();
0188 
0189     if (!parent.isValid()) {
0190         return QModelIndex();
0191     }
0192 
0193     int affectedRow = index.row();
0194     const int column = 0;
0195 
0196     while (parent.isValid()) {
0197         //     qDebug() << "parent" << parent.data() << model->rowCount(parent) << affectedRow;
0198         if (affectedRow < model->rowCount(parent) - 1) {
0199             return model->index(affectedRow + 1, column, parent);
0200         }
0201 
0202         affectedRow = parent.row();
0203         parent = parent.parent();
0204     }
0205 
0206     if (model->rowCount(parent) >= affectedRow) {
0207         return model->index(affectedRow + 1, column, parent);
0208     }
0209 
0210     return QModelIndex();
0211 }
0212 
0213 QModelIndex KReparentingProxyModelPrivate::getLastDescendant(const QModelIndex &index) const
0214 {
0215     Q_Q(const KReparentingProxyModel);
0216 
0217     QModelIndex proxyIndex = q->mapFromSource(index);
0218 
0219     while (q->hasChildren(proxyIndex)) {
0220         proxyIndex = q->index(q->rowCount(proxyIndex), proxyIndex.column(), proxyIndex);
0221         if (!proxyIndex.isValid()) {
0222             break;
0223         }
0224     }
0225     return q->mapToSource(proxyIndex);
0226 }
0227 
0228 QList<QModelIndex> KReparentingProxyModelPrivate::getExistingAncestors(const QModelIndex &descendant) const
0229 {
0230     Q_Q(const KReparentingProxyModel);
0231 
0232     QList<QModelIndex> vector;
0233     if (!descendant.isValid()) {
0234         return vector;
0235     }
0236 
0237     QModelIndex parent = q->mapFromSource(descendant).parent();
0238     QModelIndex sourceParent = q->mapToSource(parent);
0239     if (!sourceParent.isValid()) {
0240         return vector;
0241     }
0242 
0243     vector.append(sourceParent);
0244     while (parent.isValid()) {
0245         parent = parent.parent();
0246         sourceParent = q->mapToSource(parent);
0247         if (!sourceParent.isValid()) {
0248             return vector;
0249         }
0250         vector.prepend(sourceParent);
0251     }
0252     return vector;
0253 }
0254 
0255 QHash<QModelIndex, QModelIndexList> KReparentingProxyModelPrivate::recreateMappings(const QModelIndex &ancestor, int start, int end, int strategy) const
0256 {
0257     Q_Q(const KReparentingProxyModel);
0258     const int column = 0;
0259 
0260     QHash<QModelIndex, QModelIndexList> mappings;
0261     // Handle listing the root QModelIndex().
0262     if (!ancestor.isValid() && !q->sourceModel()->hasChildren())
0263     // Empty model. Nothing to do.
0264     {
0265         return mappings;
0266     }
0267 
0268     // A
0269     // - B
0270     // - - C
0271     // - D
0272     // If start refers to D, existing ancestors will contain only A.
0273     // We need to go 'up' to C and get its ancestors in case D is to be made a child of B or C (for example if B and C have just been inserted)
0274     QModelIndex indexAbove;
0275     if (start > 0) {
0276         indexAbove = getLastDescendant(q->sourceModel()->index(start - 1, column, ancestor));
0277     } else {
0278         indexAbove = ancestor;
0279     }
0280 
0281     QList<QModelIndex> ancestors = getExistingAncestors(indexAbove);
0282 
0283     //   ancestors.append(indexAbove);
0284     //   qDebug() << ancestors;
0285     QModelIndex nextIndex = ancestor;
0286 
0287     for (int row = start; (row <= end || end == -1);) {
0288         // A
0289         // - B
0290         // - - C
0291         // - D
0292         // The nextIndex of the invalid QModelIndex is A,
0293         // The nextIndex of A is B,
0294         // The nextIndex of B is C,
0295         // The nextIndex of C is D,
0296         // The nextIndex of D is invalid,
0297         // When the nextIndex is invalid we're finished creating mappings.
0298         if (MapDescendants == strategy) {
0299             nextIndex = getIndexBelow(nextIndex);
0300         } else {
0301             nextIndex = q->sourceModel()->index(row, column, ancestor);
0302         }
0303 
0304         if (!nextIndex.isValid()) {
0305             break;
0306         }
0307 
0308         const QList<QModelIndex>::iterator ancestorIt = std::lower_bound(ancestors.begin(), ancestors.end(), nextIndex, LessThan(q));
0309 
0310         ancestors.erase(ancestorIt, ancestors.end());
0311 
0312         QModelIndex parent;
0313         if (ancestorIt != ancestors.begin()) {
0314             parent = *(ancestorIt - 1);
0315         }
0316 
0317         ancestors.append(nextIndex);
0318 
0319         mappings[parent].append(nextIndex);
0320     }
0321 
0322     return mappings;
0323 }
0324 
0325 void KReparentingProxyModelPrivate::verifyStructure(const QModelIndex &sourceParent, int sourceStart)
0326 {
0327     Q_Q(KReparentingProxyModel);
0328 
0329     // If the start structure is:
0330 
0331     // C
0332     // D
0333     // E
0334 
0335     // and then A and B are inserted, we may need to move C D and E. Not all of the siblings will
0336     // necessarily be moved to the same destination parent.
0337     // Some example finished scenarios depending on the outcome of isDescendantOf:
0338 
0339     // A
0340     // B
0341     // C
0342     // D
0343     // E
0344 
0345     // A
0346     // B
0347     // - C
0348     // - D
0349     // - E
0350 
0351     // A
0352     // - B
0353     // - C
0354     // - D
0355     // - E
0356 
0357     // A
0358     // - B
0359     // - - C
0360     // - D
0361     // E
0362 
0363     // Local variable mappings now contains all the information about finished state
0364     // When we locate the first child to be moved, we process it and its siblings
0365 
0366     QHash<QModelIndex, QModelIndexList> mappings = recreateMappings(sourceParent, sourceStart, -1);
0367 
0368     if (mappings.isEmpty()) {
0369         return;
0370     }
0371 
0372     QModelIndex sourceFirstIndex = q->sourceModel()->index(sourceStart, 0, sourceParent);
0373 
0374     QModelIndex destinationParent;
0375     QModelIndexList movedIndexes;
0376 
0377     QHashIterator<QModelIndex, QModelIndexList> it(mappings);
0378     while (it.hasNext()) {
0379         it.next();
0380         //     qDebug() << it.key() << it.key().data() << it.value();
0381         if (it.value().at(0) == sourceFirstIndex) {
0382             destinationParent = it.key();
0383             movedIndexes = it.value();
0384             break;
0385         }
0386     }
0387 
0388     Q_FOREVER {
0389         if (destinationParent == sourceParent)
0390         // No indexes moved
0391         {
0392             return;
0393         }
0394 
0395         Q_ASSERT(destinationParent.isValid());
0396         Q_ASSERT(!movedIndexes.isEmpty());
0397 
0398         // It's only possible for things to move right, and even that's only an option
0399         // for children of parent, but not their descendants. ie, children of C D and E will not need to be reparented.
0400         // They are already in the correct positions.
0401 
0402         QList<QPersistentModelIndex> &existingSourceIndexes = m_childIndexes[sourceParent];
0403         QList<QPersistentModelIndex> existingDestinationIndexes = m_childIndexes[destinationParent];
0404 
0405         QModelIndex proxySourceParent = q->mapFromSource(sourceParent);
0406         QModelIndex proxyDestinationParent = q->mapFromSource(destinationParent);
0407 
0408         // That is, start position of indexes to be moved from the source parent.
0409         int proxySourceStart = m_childIndexes.value(sourceParent).indexOf(movedIndexes.at(0));
0410         int proxySourceEnd = proxySourceStart + movedIndexes.size() - 1;
0411 
0412         // The moved indexes are appended to the destinationParent. Nothing else is possible.
0413         // If they were to be inserted in the middle somewhere, they would already be there.
0414 
0415         int destinationRow = existingDestinationIndexes.size();
0416 
0417         bool allowMove = q->beginMoveRows(proxySourceParent, proxySourceStart, proxySourceEnd, proxyDestinationParent, destinationRow);
0418         Q_ASSERT(allowMove);
0419 
0420         for (int row = proxySourceEnd; row >= proxySourceStart; --row) {
0421             existingSourceIndexes.removeAt(row);
0422         }
0423 
0424         QHash<QModelIndex, QModelIndexList> mapping;
0425         mapping.insert(destinationParent, movedIndexes);
0426         mergeDescendants(mapping, destinationParent, existingDestinationIndexes.size());
0427 
0428         q->endMoveRows();
0429 
0430         if (!mappings.contains(q->mapToSource(proxyDestinationParent.parent()))) {
0431             break;
0432         }
0433 
0434         destinationParent = q->mapToSource(proxyDestinationParent.parent());
0435         movedIndexes = mappings.value(destinationParent);
0436     }
0437 }
0438 
0439 KReparentingProxyModel::KReparentingProxyModel(QObject *parent)
0440     : QAbstractProxyModel(parent)
0441     , d_ptr(new KReparentingProxyModelPrivate(this))
0442 {
0443 }
0444 
0445 KReparentingProxyModel::~KReparentingProxyModel()
0446 {
0447     delete d_ptr;
0448 }
0449 
0450 bool KReparentingProxyModelPrivate::isDescendantInModel(const QModelIndex &ancestor, const QModelIndex &descendant) const
0451 {
0452     //   qDebug() << ancestor.data() << descendant.data();
0453 
0454     //   if (!ancestor.isValid())
0455     //     return true;
0456 
0457     QModelIndex _ancestor = descendant.parent();
0458     while (_ancestor.isValid()) {
0459         if (_ancestor == ancestor) {
0460             return true;
0461         }
0462         _ancestor = _ancestor.parent();
0463     }
0464     return (!ancestor.isValid() && descendant.isValid());
0465 }
0466 
0467 bool KReparentingProxyModel::isDescendantOf(const QModelIndex &ancestor, const QModelIndex &descendant) const
0468 {
0469     Q_D(const KReparentingProxyModel);
0470     return d->isDescendantInModel(ancestor, descendant);
0471     //   return (!ancestor.isValid() && descendant.isValid());
0472 }
0473 
0474 QModelIndex KReparentingProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
0475 {
0476     Q_D(const KReparentingProxyModel);
0477     if (!sourceIndex.isValid()) {
0478         return QModelIndex();
0479     }
0480 
0481     QModelIndex sourceIndexFirstColumn = sourceIndex.sibling(sourceIndex.row(), 0);
0482 
0483     QHash<QPersistentModelIndex, QList<QPersistentModelIndex>>::const_iterator it;
0484     const QHash<QPersistentModelIndex, QList<QPersistentModelIndex>>::const_iterator begin = d->m_childIndexes.constBegin();
0485     const QHash<QPersistentModelIndex, QList<QPersistentModelIndex>>::const_iterator end = d->m_childIndexes.constEnd();
0486 
0487     for (it = begin; it != end; ++it) {
0488         QList<QPersistentModelIndex> list = it.value();
0489         if (list.contains(sourceIndexFirstColumn)) {
0490             QModelIndex sourceParent = it.key();
0491             int row = list.indexOf(sourceIndexFirstColumn);
0492 
0493             // There must have been a mapping made for it.
0494             Q_ASSERT(d->m_parents.values().contains(sourceParent));
0495 
0496             qint64 id = d->m_parents.key(sourceParent);
0497 
0498             // id refers to the parent.
0499             return createIndex(row, sourceIndex.column(), reinterpret_cast<void *>(id));
0500         }
0501     }
0502     return QModelIndex();
0503 }
0504 
0505 QModelIndex KReparentingProxyModel::mapToSource(const QModelIndex &proxyIndex) const
0506 {
0507     Q_D(const KReparentingProxyModel);
0508 
0509     //   qDebug() << "MMMMMM" << proxyIndex;
0510 
0511     if (!proxyIndex.isValid()) {
0512         return QModelIndex();
0513     }
0514 
0515     qint64 id = reinterpret_cast<qint64>(proxyIndex.internalPointer());
0516 
0517     //   if (!d->m_parents.contains(id))
0518     //     qDebug() << d->m_parents << id;
0519 
0520     QModelIndex sourceParent;
0521     if (d->m_pendingRemovalParents.contains(id)) {
0522         //     qDebug() << "pending";
0523         sourceParent = d->m_pendingRemovalParents.value(id);
0524     } else {
0525         Q_ASSERT(d->m_parents.contains(id));
0526         sourceParent = d->m_parents.value(id);
0527     }
0528 
0529     // qDebug() <<  sourceParent << sourceParent.data();
0530 
0531     QModelIndex sourceIndexFirstColumn;
0532     if (d->m_pendingRemovalChildIndexes.contains(sourceParent)) {
0533         //     qDebug() << "#############";
0534 
0535         for (const KReparentingProxyModelPrivate::PendingRemoval &pendingRemoval : std::as_const(d->m_pendingRemovals)) {
0536             //       qDebug() << "In" << pendingRemoval.index << pendingRemoval.sourceIndex << sourceParent;
0537             if (pendingRemoval.sourceIndex == sourceParent) {
0538                 //         qDebug() << "Out" << pendingRemoval.sourceIndex << sourceParent;
0539                 int proxyRow = proxyIndex.row();
0540                 int row = proxyRow - pendingRemoval.start;
0541 
0542                 //         qDebug() << d->m_pendingRemovalChildIndexes.value(sourceParent) << proxyRow << row << pendingRemoval.end;
0543 
0544                 if (proxyRow > pendingRemoval.end) {
0545                     Q_ASSERT(d->m_childIndexes.contains(sourceParent));
0546                     row = proxyRow - (pendingRemoval.end - pendingRemoval.start + 1);
0547                     //           qDebug() << "new row" << row;
0548                     sourceIndexFirstColumn = d->m_childIndexes.value(sourceParent).at(row);
0549                 } else {
0550                     sourceIndexFirstColumn = d->m_pendingRemovalChildIndexes.value(sourceParent).at(row);
0551                 }
0552                 break;
0553             }
0554         }
0555     } else {
0556         Q_ASSERT(d->m_childIndexes.contains(sourceParent));
0557         sourceIndexFirstColumn = d->m_childIndexes.value(sourceParent).at(proxyIndex.row());
0558     }
0559 
0560     Q_ASSERT(sourceIndexFirstColumn.isValid());
0561 
0562     return sourceIndexFirstColumn.sibling(sourceIndexFirstColumn.row(), proxyIndex.column());
0563 }
0564 
0565 int KReparentingProxyModel::columnCount(const QModelIndex &parent) const
0566 {
0567     Q_D(const KReparentingProxyModel);
0568 
0569     if (!sourceModel()) {
0570         return 0;
0571     }
0572 
0573     if (!parent.isValid()) {
0574         return sourceModel()->columnCount();
0575     }
0576 
0577     if (parent.column() > 0) {
0578         return 0;
0579     }
0580     QModelIndex sourceIndex = mapToSource(parent);
0581 
0582     return (d->m_childIndexes.value(sourceIndex).size() > 0) ? sourceModel()->columnCount() : 0;
0583 }
0584 
0585 QVariant KReparentingProxyModel::data(const QModelIndex &proxyIndex, int role) const
0586 {
0587     return QAbstractProxyModel::data(proxyIndex, role);
0588 }
0589 
0590 QModelIndex KReparentingProxyModel::index(int row, int column, const QModelIndex &parent) const
0591 {
0592     Q_D(const KReparentingProxyModel);
0593 
0594     if (!hasIndex(row, column, parent)) {
0595         return QModelIndex();
0596     }
0597 
0598     QModelIndex sourceParent = mapToSource(parent);
0599 
0600     //   if (!d->m_pendingRemovals.isEmpty())
0601     //     qDebug() << sourceParent << sourceParent.data();
0602 
0603     // ### This is where we need to have the children of removed indexes stored.
0604 
0605     //   if (!d->m_parents.values().contains(sourceParent))
0606     //   {
0607     //     qDebug() << d->m_pendingRemovalParents.values() << sourceParent << d->m_pendingRemovalParents.values().contains(sourceParent);
0608     //   }
0609 
0610     qint64 id;
0611     if (d->m_pendingRemovalParents.values().contains(sourceParent)) {
0612         id = d->m_pendingRemovalParents.key(sourceParent);
0613     } else {
0614         // There must have been a mapping made for it.
0615         Q_ASSERT(d->m_parents.values().contains(sourceParent));
0616         id = d->m_parents.key(sourceParent);
0617     }
0618     return createIndex(row, column, reinterpret_cast<void *>(id));
0619 }
0620 
0621 QModelIndex KReparentingProxyModel::parent(const QModelIndex &child) const
0622 {
0623     Q_D(const KReparentingProxyModel);
0624 
0625     if (!child.isValid()) {
0626         return QModelIndex();
0627     }
0628 
0629     QModelIndex sourceIndex = mapToSource(child);
0630 
0631     QModelIndex firstColumnChild = sourceIndex;
0632     if (sourceIndex.column() > 0) {
0633         firstColumnChild = sourceIndex.sibling(sourceIndex.row(), 0);
0634     }
0635 
0636     QHashIterator<QPersistentModelIndex, QList<QPersistentModelIndex>> itPending(d->m_pendingRemovalChildIndexes);
0637 
0638     while (itPending.hasNext()) {
0639         itPending.next();
0640 
0641         if (itPending.value().contains(firstColumnChild)) {
0642             return mapFromSource(itPending.key());
0643         }
0644     }
0645 
0646     QHashIterator<QPersistentModelIndex, QList<QPersistentModelIndex>> it(d->m_childIndexes);
0647 
0648     while (it.hasNext()) {
0649         it.next();
0650 
0651         if (it.value().contains(firstColumnChild)) {
0652             return mapFromSource(it.key());
0653         }
0654     }
0655     return QModelIndex();
0656 }
0657 
0658 int KReparentingProxyModelPrivate::pendingRemovalRowCount(const QModelIndex &sourceIndex) const
0659 {
0660     for (const PendingRemoval &pendingRemoval : std::as_const(m_pendingRemovals)) {
0661         //     qDebug() << pendingRemoval.sourceIndex;
0662         if (pendingRemoval.sourceIndex == sourceIndex) {
0663             return pendingRemoval.end - pendingRemoval.start + 1;
0664         }
0665     }
0666     return 0;
0667 }
0668 
0669 int KReparentingProxyModel::rowCount(const QModelIndex &parent) const
0670 {
0671     Q_D(const KReparentingProxyModel);
0672 
0673     if (parent.column() > 0) {
0674         return 0;
0675     }
0676 
0677     QModelIndex sourceIndex = mapToSource(parent);
0678 
0679     int size = d->m_childIndexes.value(sourceIndex).size() + d->m_pendingRemovalChildIndexes.value(sourceIndex).size();
0680 
0681     //   qDebug() << d->m_pendingRemovalChildIndexes.value(sourceIndex).size();
0682 
0683     //   if (!d->m_pendingRemovals.isEmpty())
0684     //   {
0685     //     qDebug() << "SIZE" << sourceIndex << sourceIndex.data() << size << d->m_pendingRemovals.size() << d->pendingRemovalRowCount(sourceIndex);
0686     //   }
0687 
0688     return size;
0689 }
0690 
0691 bool KReparentingProxyModel::hasChildren(const QModelIndex &parent) const
0692 {
0693     return rowCount(parent) > 0;
0694 }
0695 
0696 void KReparentingProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
0697 {
0698     Q_D(KReparentingProxyModel);
0699 
0700     beginResetModel();
0701 
0702     disconnect(sourceModel, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)), this, SLOT(sourceRowsAboutToBeInserted(QModelIndex, int, int)));
0703     disconnect(sourceModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(sourceRowsInserted(QModelIndex, int, int)));
0704     disconnect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex, int, int)));
0705     disconnect(sourceModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(sourceRowsRemoved(QModelIndex, int, int)));
0706     disconnect(sourceModel,
0707                SIGNAL(rowsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int)),
0708                this,
0709                SLOT(sourceRowsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int)));
0710     disconnect(sourceModel, SIGNAL(rowsMoved(QModelIndex, int, int, QModelIndex, int)), this, SLOT(sourceRowsMoved(QModelIndex, int, int, QModelIndex, int)));
0711     disconnect(sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()));
0712     disconnect(sourceModel, SIGNAL(modelReset()), this, SLOT(sourceModelReset()));
0713     disconnect(sourceModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(sourceDataChanged(QModelIndex, QModelIndex)));
0714     disconnect(sourceModel, SIGNAL(layoutAboutToBeChanged()), this, SLOT(sourceLayoutAboutToBeChanged()));
0715     disconnect(sourceModel, SIGNAL(layoutChanged()), this, SLOT(sourceLayoutChanged()));
0716 
0717     QAbstractProxyModel::setSourceModel(sourceModel);
0718 
0719     //   qDebug() << "set";
0720     QHash<QModelIndex, QModelIndexList> mappings =
0721         d->recreateMappings(QModelIndex(), 0, sourceModel->rowCount() - 1, KReparentingProxyModelPrivate::MapDescendants);
0722     //   qDebug() << "begin";
0723     d->mergeDescendants(mappings, QModelIndex(), 0);
0724 
0725     connect(sourceModel, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)), SLOT(sourceRowsAboutToBeInserted(QModelIndex, int, int)));
0726     connect(sourceModel, SIGNAL(rowsInserted(QModelIndex, int, int)), SLOT(sourceRowsInserted(QModelIndex, int, int)));
0727     connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), SLOT(sourceRowsAboutToBeRemoved(QModelIndex, int, int)));
0728     connect(sourceModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), SLOT(sourceRowsRemoved(QModelIndex, int, int)));
0729     connect(sourceModel,
0730             SIGNAL(rowsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int)),
0731             SLOT(sourceRowsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int)));
0732     connect(sourceModel, SIGNAL(rowsMoved(QModelIndex, int, int, QModelIndex, int)), SLOT(sourceRowsMoved(QModelIndex, int, int, QModelIndex, int)));
0733     connect(sourceModel, SIGNAL(modelAboutToBeReset()), SLOT(sourceModelAboutToBeReset()));
0734     connect(sourceModel, SIGNAL(modelReset()), SLOT(sourceModelReset()));
0735     connect(sourceModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), SLOT(sourceDataChanged(QModelIndex, QModelIndex)));
0736     connect(sourceModel, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged()));
0737     connect(sourceModel, SIGNAL(layoutChanged()), SLOT(sourceLayoutChanged()));
0738 
0739     endResetModel();
0740 }
0741 
0742 void KReparentingProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
0743 {
0744     Q_UNUSED(parent);
0745     Q_UNUSED(start);
0746     Q_UNUSED(end);
0747 
0748     Q_Q(KReparentingProxyModel);
0749     return q->beginResetModel();
0750 #if 0
0751     // We can't figure out the structure until the indexes are in the model.
0752     // Store the signal until the new rows are actually there in sourceRowsInserted.
0753     PendingInsertion pendingInsertion(parent, start, end);
0754     m_pendingInsertions.insert(parent, pendingInsertion);
0755 #endif
0756 }
0757 
0758 QHash<QModelIndex, QModelIndexList>
0759 KReparentingProxyModelPrivate::mergeDescendants(QHash<QModelIndex, QModelIndexList> mappings, const QModelIndex &parent, int start)
0760 {
0761     const QModelIndexList childIndexes = mappings.take(parent);
0762     //   qDebug() << childIndexes;
0763     if (!childIndexes.isEmpty()) {
0764         if (!m_parents.values().contains(parent)) {
0765             m_parents.insert(newId(), QPersistentModelIndex(parent));
0766         }
0767     }
0768     int row = start;
0769     for (const QModelIndex &idx : childIndexes) {
0770         m_childIndexes[parent].insert(row++, QPersistentModelIndex(idx));
0771         mappings = mergeDescendants(mappings, idx, 0);
0772     }
0773     return mappings;
0774 }
0775 
0776 QHash<QModelIndex, QModelIndexList> KReparentingProxyModelPrivate::insertTree(QHash<QModelIndex, QModelIndexList>, const QModelIndex &)
0777 {
0778     return QHash<QModelIndex, QModelIndexList>();
0779 }
0780 
0781 void KReparentingProxyModelPrivate::handleInsertion(const PendingInsertion &pendingInsertion)
0782 {
0783     Q_Q(KReparentingProxyModel);
0784     QModelIndex parent = pendingInsertion.index;
0785     int start = pendingInsertion.start;
0786     int end = pendingInsertion.end;
0787 
0788     //   qDebug() << parent << parent.data() << start << end;
0789 
0790     //   for (int i = start; i < end; ++i)
0791     //   {
0792     //     QModelIndex idx = q->sourceModel()->index(i, 0, parent);
0793     //     qDebug() << idx << idx.data();
0794     //   }
0795 
0796     QHash<QModelIndex, QModelIndexList> newItemMappings = recreateMappings(parent, start, end, KReparentingProxyModelPrivate::MapDescendants);
0797 
0798     // iterate over keys. if key in keys iterate up. This gives list of top level parents.
0799     // Pick the one whose parent is @p parent. Insert it. Look up until find the parent of another one and insert that.
0800     // If one of the parents is invalid it is necessarily the last one to be processed (if there are more to process, they'll be children of it)
0801     // That case should work too.
0802 
0803     //   qDebug() << "new item mappings" << newItemMappings;
0804 
0805     const int column = 0;
0806 
0807     //   qDebug() << m_childIndexes.contains(parent);
0808 
0809     if (newItemMappings.contains(parent)) {
0810         QModelIndexList newItemList = newItemMappings.value(parent);
0811         //     qDebug() << "newItemList" << newItemList;
0812         int proxyStart = 0;
0813 
0814         // A single insertion in the source model might be multiple insertions in the proxy model.
0815         Q_FOREVER {
0816             if (newItemList.isEmpty()) {
0817                 if (!newItemMappings.contains(parent.parent())) {
0818                     break;
0819                 }
0820 
0821                 newItemList = newItemMappings.value(parent.parent());
0822                 continue;
0823             }
0824 
0825             proxyStart = 0;
0826 
0827             QModelIndex proxyParent = q->mapFromSource(parent);
0828             if (start > 0) {
0829                 QModelIndex lastDesc = q->mapFromSource(getLastDescendant(q->sourceModel()->index(start - 1, column, parent)));
0830 
0831                 while (lastDesc.parent() != proxyParent) {
0832                     lastDesc = lastDesc.parent();
0833                 }
0834                 proxyStart = lastDesc.row() + 1;
0835             }
0836 
0837             q->beginInsertRows(proxyParent, proxyStart, proxyStart + newItemList.size() - 1);
0838 
0839             newItemMappings = mergeDescendants(newItemMappings, parent, proxyStart);
0840 
0841             q->endInsertRows();
0842 
0843             if (!newItemMappings.contains(parent.parent())) {
0844                 break;
0845             }
0846 
0847             newItemList = newItemMappings.value(parent.parent());
0848         }
0849     }
0850 
0851     //   // The rest are not descendants of pendingInsertion.index in the proxy model, but are elsewhere.
0852     //   Q_FOREACH(const QModelIndex &parent, newItemMappings.keys())
0853     //   {
0854     //
0855     //   }
0856 
0857     return;
0858 }
0859 
0860 void KReparentingProxyModelPrivate::sourceRowsInserted(const QModelIndex &parent, int, int end)
0861 {
0862     Q_UNUSED(parent);
0863     Q_UNUSED(end);
0864 
0865     return endResetProxy();
0866 
0867 #if 0
0868     Q_Q(KReparentingProxyModel);
0869     if (m_pendingInsertions.contains(parent)) {
0870         PendingInsertion pendingInsertion = m_pendingInsertions.value(parent);
0871         handleInsertion(pendingInsertion);
0872 
0873         if (q->sourceModel()->rowCount(parent) <= (end + 1)) {
0874             return;
0875         }
0876 
0877         // The presence of new rows might affect the structure of indexes below.
0878         verifyStructure(parent, end + 1);
0879     }
0880 #endif
0881 }
0882 
0883 void KReparentingProxyModelPrivate::removeTree(const QPersistentModelIndex &idxToRemove, int start, int end)
0884 {
0885     if (!m_childIndexes.contains(idxToRemove)) {
0886         return;
0887     }
0888 
0889     //   qDebug() << "idxToRemove" << idxToRemove << start << end;
0890 
0891     QList<QPersistentModelIndex> &toRemove = m_childIndexes[idxToRemove];
0892     //   qDebug() << toRemove << toRemove.size();
0893 
0894     //   QList<int> intList;
0895     //   intList << 1 << 2 << 3 << 4 << 5;
0896     //
0897     //   QList<int>::iterator intit = intList.begin();
0898     //   QList<int>::iterator intendIt = intList.end();
0899     //
0900     //   if (end == 0)
0901     //     intendIt = intit + 1;
0902     //
0903     //   if (end > 0)
0904     //   {
0905     //     intendIt = intit + (end - start + 1) + 1;
0906     //     qDebug() << "intend" << *intendIt;
0907     //   }
0908     //   intit += start;
0909     //
0910     //   while (intit != intendIt)
0911     //   {
0912     //     int i = *intit;
0913     //     qDebug() << i;
0914     //     intit = intList.erase(intit);
0915     //   }
0916 
0917     QList<QPersistentModelIndex>::iterator it = toRemove.begin();
0918     QList<QPersistentModelIndex>::iterator endIt = toRemove.end();
0919 
0920     if (end == 0) {
0921         endIt = it + 1;
0922     }
0923 
0924     if (end > 0) {
0925         endIt = it + (end - start + 1) + 1;
0926     }
0927     it += start;
0928 
0929     int i = start;
0930     while (it != endIt) {
0931         QPersistentModelIndex idx = *it;
0932         //     qDebug() << "removing" << idx << idx.data();
0933 
0934         if (m_parents.values().contains(idx)) {
0935             qint64 key = m_parents.key(idx);
0936             QPersistentModelIndex value = m_parents.take(key);
0937             m_pendingRemovalParents.insert(key, value);
0938             //       qDebug() << "take from parent" << value;
0939         }
0940         removeTree(idx);
0941 
0942         ++i;
0943 
0944         m_pendingRemovalChildIndexes[idxToRemove].append(idx);
0945         //     qDebug() << idxToRemove << idxToRemove.data() << idx << idx.data();
0946 
0947         it = toRemove.erase(it);
0948         //     qDebug() << (it == endIt);
0949         //     if (i > end)
0950         //       break;
0951 
0952         //     if (it == toRemove.end())
0953         //       break;
0954     }
0955 
0956     //   qDebug() << "toRemove" << toRemove;
0957 
0958     //   for(int i = start; (i <= end || (end == -1 && toRemove.size() > i)); )
0959     //   {
0960     //     qDebug() << i;
0961     //     QPersistentModelIndex idx = toRemove.takeAt(i);
0962     //     --end;
0963     //
0964     //     qDebug() << "removing" << idx.data();
0965     //
0966     //     if (m_parents.values().contains(idx))
0967     //     {
0968     //       QPersistentModelIndex bah = m_parents.take(m_parents.key(idx));
0969     // //       qDebug() << "take from parent" << bah;
0970     //     }
0971     //     removeTree(idx);
0972     //   }
0973 }
0974 
0975 void KReparentingProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
0976 {
0977     Q_UNUSED(parent);
0978     Q_UNUSED(start);
0979     Q_UNUSED(end);
0980 
0981     Q_Q(KReparentingProxyModel);
0982     q->beginResetModel();
0983 
0984     return;
0985 #if 0
0986 //   qDebug() << parent << start << end;
0987 
0988     // This is really tricky.
0989     //
0990     // We could have something like:
0991     //
0992     //   A              A
0993     //   B              - B
0994     //   C    ->        - - C
0995     //   D              D
0996     //   E              - E
0997     //
0998     // And have to remove something like B to D. That would mean a remove signal for B, move E to its grandparent, remove D.
0999 
1000 //   QHashIterator<QPersistentModelIndex, QList< QPersistentModelIndex> > it(m_childIndexes);
1001 //   while (it.hasNext())
1002 //   {
1003 //     it.next();
1004 //     qDebug() << it.key() << it.key().data();
1005 //     qDebug() << it.value();
1006 //   }
1007 
1008     const int column = 0;
1009 
1010     QModelIndex firstAffectedIndex = q->mapFromSource(q->sourceModel()->index(start, column, parent));
1011     QModelIndex lastAffectedIndex = q->mapFromSource(q->sourceModel()->index(end, column, parent));
1012 
1013 //   qDebug() << "firstAffectedIndex" << firstAffectedIndex.data();
1014 //   qDebug() << "lastAffectedIndex" << lastAffectedIndex.data();
1015 
1016     QModelIndex proxyParent = firstAffectedIndex.parent();
1017 
1018     Q_ASSERT(firstAffectedIndex.isValid() && lastAffectedIndex.isValid());
1019 
1020     Q_FOREVER {
1021     if (isDescendantInModel(proxyParent, lastAffectedIndex))
1022         {
1023             // They share a common ancestor.
1024 
1025             QModelIndex _parent = lastAffectedIndex.parent();
1026             QModelIndex lastAffectedAncestor = lastAffectedIndex;
1027 //       qDebug() << "last affected ancestor" << lastAffectedAncestor.data();
1028             while (_parent != proxyParent) {
1029                 lastAffectedAncestor = _parent;
1030                 _parent = _parent.parent();
1031             }
1032 
1033             if (q->hasChildren(lastAffectedAncestor)) {
1034                 QModelIndex next = q->index(0, 0, lastAffectedAncestor);
1035 
1036                 QModelIndex proxySourceParent = lastAffectedAncestor;
1037                 int startRow = next.row();
1038                 int lastRow = q->rowCount(lastAffectedAncestor) - 1;
1039 
1040                 QList<QPersistentModelIndex> &existingSourceIndexes = m_childIndexes[q->mapToSource(proxySourceParent)];
1041                 QList<QPersistentModelIndex> &existingDestinationIndexes = m_childIndexes[q->mapToSource(proxyParent)];
1042 
1043                 int destRow = lastAffectedAncestor.row() + 1;
1044 
1045 //         qDebug() << "Move from" << lastAffectedAncestor.data() << startRow << lastRow << " To " << proxyParent.data() << destRow;
1046                 bool allowMove = q->beginMoveRows(lastAffectedAncestor, startRow, lastRow, proxyParent, destRow);
1047                 Q_ASSERT(allowMove);
1048 
1049                 for (int i = startRow; i <= lastRow; ++i) {
1050                     QPersistentModelIndex movingIdx = existingSourceIndexes.takeAt(startRow);
1051                     existingDestinationIndexes.insert(destRow + (i - startRow), movingIdx);
1052                 }
1053 
1054                 // TODO: If source was a parent before, it might not be now.
1055                 // dest was already a parent.
1056 
1057                 q->endMoveRows();
1058             }
1059             PendingRemoval removal;
1060             removal.index = proxyParent;
1061             removal.start = firstAffectedIndex.row();
1062             removal.end = lastAffectedAncestor.row();
1063             removal.parentId = proxyParent.internalId();
1064             removal.sourceIndex = q->mapToSource(proxyParent);
1065             m_pendingRemovals.append(removal);
1066 
1067             removeTree(q->mapToSource(proxyParent), removal.start, removal.end);
1068 
1069 //       qDebug() << "beg rem 1";
1070             q->beginRemoveRows(proxyParent, removal.start, removal.end);
1071 
1072             return;
1073 
1074         } else {
1075             QModelIndex next = getIndexBelow(firstAffectedIndex);
1076 
1077             proxyParent = next.parent();
1078 
1079             while (isDescendantInModel(proxyParent, next))
1080             {
1081                 next = getIndexBelow(next);
1082             }
1083             QModelIndex _parent = next.parent();
1084             QModelIndex lastAffectedAncestor = next;
1085 
1086             while (_parent != proxyParent)
1087             {
1088                 lastAffectedAncestor = _parent;
1089                 _parent = _parent.parent();
1090             }
1091 
1092             PendingRemoval removal;
1093             removal.index = proxyParent;
1094             removal.start = firstAffectedIndex.row();
1095             removal.end = lastAffectedAncestor.row();
1096             removal.parentId = proxyParent.internalId();
1097             removal.sourceIndex = q->mapToSource(proxyParent);
1098             m_pendingRemovals.append(removal);
1099 
1100             removeTree(q->mapToSource(proxyParent), removal.start, removal.end);
1101 
1102 //       qDebug() << "beg rem 1";
1103             q->beginRemoveRows(proxyParent, removal.start, removal.end);
1104 
1105             proxyParent = next.parent();
1106         }
1107     }
1108 
1109 // //   qDebug() << proxyParent.data() << lastAffectedIndex.parent().data() << proxyParent << lastAffectedIndex.parent();
1110 //   if (proxyParent == lastAffectedIndex.parent())
1111 //   {
1112 //     PendingRemoval removal;
1113 //     removal.index = proxyParent;
1114 //     removal.start = firstAffectedIndex.row();
1115 //     removal.end = lastAffectedIndex.row();
1116 //     removal.parentId = proxyParent.internalId();
1117 //     removal.sourceIndex = q->mapToSource(proxyParent);
1118 //     m_pendingRemovals.append(removal);
1119 //
1120 //     // Also need to store a removal object for each of the descendants.
1121 //
1122 //     removeTree(q->mapToSource(proxyParent), removal.start, removal.end);
1123 //
1124 // //     qDebug() << "beg rem 1";
1125 //     q->beginRemoveRows(proxyParent, removal.start, removal.end);
1126 //     return;
1127 //   }
1128 //
1129 //   QModelIndex lastParent = lastAffectedIndex.parent();
1130 //   while (lastParent.parent().isValid())
1131 //   {
1132 //     if (lastParent.parent() == proxyParent)
1133 //     {
1134 //       PendingRemoval removal;
1135 //       removal.index = proxyParent;
1136 //       removal.start = firstAffectedIndex.row();
1137 //       removal.end = lastParent.row();
1138 //       removal.parentId = proxyParent.internalId();
1139 //       removal.sourceIndex = q->mapToSource(proxyParent);
1140 //       m_pendingRemovals.append(removal);
1141 //
1142 // //       qDebug() << "beg rem 2";
1143 //       q->beginRemoveRows(proxyParent, removal.start, removal.end);
1144 //       return;
1145 //     }
1146 //     lastParent = lastParent.parent();
1147 //   }
1148 //
1149 //   // Several blocks need to be removed from the proxy model.
1150 //   // Divide and conquer to find them.
1151 //
1152 //   int proxyStart = firstAffectedIndex.row();
1153 //   int proxyEnd = proxyStart + (end - start);
1154 //   int processedUntil = start;
1155 //
1156 //   while (processedUntil <= end)
1157 //   {
1158 //     QModelIndex lastInParent = findLastInParent(proxyParent, proxyStart, proxyEnd);
1159 //     qDebug() << "lastInParent" << lastInParent;
1160 //
1161 //     QModelIndex sourceLast = q->mapToSource(lastInParent);
1162 //     processedUntil = sourceLast.row();
1163 //
1164 //     PendingRemoval removal;
1165 //     removal.index = proxyParent;
1166 //     removal.start = proxyStart;
1167 //     removal.end = lastInParent.row();
1168 //     removal.parentId = proxyParent.internalId();
1169 //     removal.sourceIndex = q->mapToSource(proxyParent);
1170 //     m_pendingRemovals.append(removal);
1171 //
1172 //     qDebug() << "beg rem 3";
1173 //     q->beginRemoveRows(proxyParent, removal.start, removal.end);
1174 //
1175 //     QModelIndex proxyIndexBelow = getIndexBelow(lastInParent, q);
1176 //
1177 //     if (!proxyIndexBelow.isValid())
1178 //       return;
1179 //
1180 //     proxyParent = proxyIndexBelow.parent();
1181 //     proxyStart = proxyIndexBelow.row();
1182 //   }
1183 #endif
1184 }
1185 
1186 QModelIndex KReparentingProxyModelPrivate::findLastInParent(QModelIndex parent, int start, int end)
1187 {
1188     Q_Q(KReparentingProxyModel);
1189 
1190     const int column = 0;
1191 
1192     if (start == end) {
1193         return q->index(start, column, parent);
1194     }
1195 
1196     int middle = start + (end - start / 2);
1197 
1198     QModelIndex sourceParent = q->mapToSource(parent);
1199     QModelIndex middleIndex = q->mapFromSource(q->sourceModel()->index(middle, column, sourceParent));
1200 
1201     if (middleIndex.parent() == parent) {
1202         return findLastInParent(parent, middle, end);
1203     } else {
1204         return findLastInParent(parent, start + ((middle - start) / 2), middle);
1205     }
1206 }
1207 
1208 //   qDebug() << affectedIndex << affectedIndex.data() << proxyParent;
1209 //
1210 //   QHash<QModelIndex, PendingRemoval> pendingRemovals;
1211 //
1212 //   int i = start;
1213 //   while (i <= end)
1214 //   {
1215 //     affectedIndex = affectedIndex.sibling(i, column);
1216 //
1217 // //     affectedIndex = getIndexBelow(affectedIndex, q);
1218 //     if (!affectedIndex.isValid())
1219 //       break;
1220 // //     Q_ASSERT(affectedIndex.isValid());
1221 //
1222 //     if (affectedIndex.parent() != proxyParent)
1223 //     {
1224 //       // affectedIndex.parent() must be left of proxyParent
1225 //
1226 //       PendingRemoval removal;
1227 //       removal.index = proxyParent;
1228 //       removal.start = start;
1229 //       removal.end = i;
1230 //       pendingRemovals.insert(proxyParent, removal);
1231 //
1232 //       Q_EMIT q->rowsAboutToBeRemoved(proxyParent, start, i);
1233 //       proxyParent = affectedIndex.parent();
1234 //
1235 //       end -= (i - start + 1);
1236 //       start = affectedIndex.row();
1237 //       i = start;
1238 //     }
1239 //
1240 //     ++i;
1241 //   }
1242 
1243 // Move younger siblings out of the way so that the rows can be removed easily
1244 // No. It's easier to use verifyStructure afterward.
1245 
1246 //   // Removing rows in the source model could require sending the children to their grandparents.
1247 //
1248 //   QHash<QModelIndex, QModelIndexList> mappings;
1249 //   recreateMappings(parent, start, end);
1250 //
1251 //   QHashIterator<QModelIndex, QModelIndexList> it(mappings);
1252 //   while (it.hasNext())
1253 //   {
1254 //     it.next();
1255 //     QModelIndexList removedList = it.value();
1256 //     PendingRemoval pendingRemoval;
1257 //     pendingRemoval.index = it.key();
1258 //     pendingRemoval.start = q->mapFromSource(removedList.at(0)).row();
1259 //     pendingRemoval.end = pendingRemoval.start + removedList.size() - 1;
1260 //     m_pendingRemovals.insert(parent, pendingRemoval);
1261 //   }
1262 // }
1263 
1264 void KReparentingProxyModelPrivate::handleRemoval(const PendingRemoval &pendingRemoval)
1265 {
1266     Q_UNUSED(pendingRemoval)
1267     //   Q_Q(KReparentingProxyModel);
1268     //   q->beginRemoveRows(pendingRemoval.index, pendingRemoval.start, pendingRemoval.end);
1269     //   m_childIndexes.remove(pendingRemoval.index);
1270     //   // Remove stuff from m_parents.
1271     //   q->endRemoveRows();
1272 }
1273 
1274 void KReparentingProxyModelPrivate::sourceRowsRemoved(const QModelIndex &parent, int, int)
1275 {
1276     return endResetProxy();
1277 
1278     Q_Q(KReparentingProxyModel);
1279 
1280     // loop over pending removals and process each one. Then look after the last one
1281     // to move displaced rows to where they should be.
1282 
1283     int lastAffectedRow = m_pendingRemovals.last().end;
1284     QModelIndex lastAffectedIndex = m_pendingRemovals.last().index;
1285 
1286     QMutableListIterator<PendingRemoval> it(m_pendingRemovals);
1287 
1288     while (it.hasNext()) {
1289         PendingRemoval removal = it.next();
1290         m_pendingRemovalChildIndexes.remove(removal.sourceIndex);
1291         m_pendingRemovalParents.remove(parent.internalId());
1292         it.remove();
1293 
1294         Q_EMIT q->endRemoveRows();
1295     }
1296     //   qDebug() << "Remove done ##########";
1297 
1298     //   qDebug() << lastAffectedIndex << lastAffectedIndex.data() << lastAffectedRow;
1299 
1300     verifyStructure(lastAffectedIndex, lastAffectedRow - 1);
1301 }
1302 
1303 void KReparentingProxyModelPrivate::sourceRowsAboutToBeMoved(const QModelIndex &parent, int start, int end, const QModelIndex &, int)
1304 {
1305     // This could be several individual moves in the proxy model, or it could be no moves at all.
1306     // We can get the top indexes of the moved list and move those.
1307     // because their children won't be moved anywhere different.
1308 
1309     // I could look at the indexes between start and end (proxied could be several blocks), and move them to dest.
1310     // Then verify structure.
1311     // This could lead to an illegal move.
1312     // If we have
1313     //
1314     // Source:        Proxy:
1315     // A              A
1316     // B              B
1317     // C              - C
1318     // D              - D
1319     // E              E
1320     //
1321     // then source can legally move B to between C and D, however, implemented naively the proxymodel would attempt an illegal move.
1322     // We must first reparent everything below destRow in the proxy to the parent of parent in this case, then perform the move, then
1323     // verifyStructure.
1324     //
1325     // Moving B C and D to below E would be a legal move in the proxy model.
1326     //
1327     // Children of moved indexes which are not themselves moved must be first sent to their grandparents.
1328     // So if B and C were moved in the source model above to below E, D would first be moved to its grandparent, then B would be moved below E,
1329     // then the structure would need to be verified.
1330     //
1331     // Proxy start state:     Intermediate state:   Intermediate or final state:   Possible alternative final state:
1332     //       A                      A                     A                              A
1333     //       B                      B                     E                              E
1334     //       - C                    - C                   D                              - D
1335     //       - D                    D                     B                              B
1336     //       E                      E                     - C                            - C
1337 
1338     // So, I could iterate from start to end in proxySourceParent and if the depth goes less than parent, emit a block move, then start again.
1339 
1340     QHash<QModelIndex, QModelIndexList> newMappings = recreateMappings(parent, start, end);
1341 }
1342 
1343 void KReparentingProxyModelPrivate::sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)
1344 {
1345 }
1346 
1347 void KReparentingProxyModelPrivate::sourceLayoutAboutToBeChanged()
1348 {
1349     Q_Q(KReparentingProxyModel);
1350 
1351     q->beginResetModel();
1352     return;
1353 #if 0
1354 
1355     Q_EMIT q->layoutAboutToBeChanged();
1356 
1357     Q_FOREACH (QPersistentModelIndex proxyPersistentIndex, q->persistentIndexList()) {
1358         m_proxyIndexes << proxyPersistentIndex;
1359         m_layoutChangePersistentIndexes << QPersistentModelIndex(q->mapToSource(proxyPersistentIndex));
1360     }
1361 #endif
1362 }
1363 
1364 void KReparentingProxyModelPrivate::sourceLayoutChanged()
1365 {
1366     endResetProxy();
1367     return;
1368 #if 0
1369     Q_Q(KReparentingProxyModel);
1370 
1371     for (int i = 0; i < m_proxyIndexes.size(); ++i) {
1372         q->changePersistentIndex(m_proxyIndexes.at(i), q->mapFromSource(m_layoutChangePersistentIndexes.at(i)));
1373     }
1374 
1375     m_layoutChangePersistentIndexes.clear();
1376     m_proxyIndexes.clear();
1377 
1378     Q_EMIT q->layoutChanged();
1379 #endif
1380 }
1381 
1382 void KReparentingProxyModelPrivate::sourceModelAboutToBeReset()
1383 {
1384     Q_Q(KReparentingProxyModel);
1385     q->beginResetModel();
1386 }
1387 
1388 void KReparentingProxyModelPrivate::endResetProxy()
1389 {
1390     Q_Q(KReparentingProxyModel);
1391 
1392     m_parents.clear();
1393     m_childIndexes.clear();
1394     m_nextId = 0;
1395     m_pendingInsertions.clear();
1396     m_pendingRemovals.clear();
1397     m_pendingRemovalChildIndexes.clear();
1398     m_pendingRemovalParents.clear();
1399     //   qDebug() << q->sourceModel()->rowCount();
1400     QHash<QModelIndex, QModelIndexList> mappings =
1401         recreateMappings(QModelIndex(), 0, q->sourceModel()->rowCount() - 1, KReparentingProxyModelPrivate::MapDescendants);
1402     qDebug() << mappings;
1403 
1404     mergeDescendants(mappings, QModelIndex(), 0);
1405     q->endResetModel();
1406 }
1407 
1408 void KReparentingProxyModelPrivate::sourceModelReset()
1409 {
1410     endResetProxy();
1411 }
1412 
1413 void KReparentingProxyModelPrivate::emitDataChangedSignals(const QModelIndex &startIndex, int maxChanged)
1414 {
1415     Q_Q(KReparentingProxyModel);
1416 
1417     QModelIndex proxyParent = startIndex.parent();
1418 
1419     int numChanged = 1;
1420 
1421     QModelIndex lastAffectedSibling = startIndex;
1422     QModelIndex proxySibling = getIndexBelow(startIndex, q);
1423 
1424     Q_FOREVER {
1425         if (proxySibling.parent() != proxyParent || numChanged >= maxChanged) {
1426             break;
1427         }
1428 
1429         numChanged++;
1430         lastAffectedSibling = proxySibling;
1431 
1432         proxySibling = getIndexBelow(proxySibling);
1433     }
1434 
1435     Q_EMIT q->dataChanged(startIndex, lastAffectedSibling);
1436     if (numChanged < maxChanged) {
1437         emitDataChangedSignals(proxySibling, maxChanged - numChanged);
1438     }
1439 }
1440 
1441 void KReparentingProxyModelPrivate::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
1442 {
1443     Q_UNUSED(topLeft);
1444     Q_UNUSED(bottomRight);
1445 
1446     Q_Q(KReparentingProxyModel);
1447 
1448     q->beginResetModel();
1449     endResetProxy();
1450     return;
1451 #if 0
1452     QModelIndex parent = topLeft.parent();
1453     const int start = topLeft.row();
1454     const int end = bottomRight.row();
1455     const int column = 0;
1456     const int maxChanged = end - start + 1;
1457 
1458     // Create mappings to the end because changing data can affect structure of siblings.
1459     verifyStructure(parent, start);
1460 
1461     // mapFromSource and emit signals.
1462 
1463     QModelIndex proxyStartIndex = q->mapFromSource(q->sourceModel()->index(start, column, parent));
1464 
1465     emitDataChangedSignals(proxyStartIndex, maxChanged);
1466 #endif
1467 }
1468 
1469 Qt::DropActions KReparentingProxyModel::supportedDropActions() const
1470 {
1471     Q_ASSERT(sourceModel());
1472     return sourceModel()->supportedDropActions();
1473 }
1474 
1475 void KReparentingProxyModel::beginChangeRule()
1476 {
1477     Q_D(KReparentingProxyModel);
1478     d->sourceModelAboutToBeReset();
1479     //   beginResetModel();
1480     //   d->m_childIndexes.clear();
1481     //   d->m_layoutChangePersistentIndexes.clear();
1482     //   d->m_nextId = 1;
1483     //   d->m_parents.clear();
1484     //   d->m_pendingInsertions.clear();
1485     //   d->m_pendingRemovalChildIndexes.clear();
1486     //   d->m_pendingRemovalParents.clear();
1487     //   d->m_pendingRemovals.clear();
1488     //   d->m_proxyIndexes.clear();
1489 }
1490 
1491 void KReparentingProxyModel::endChangeRule()
1492 {
1493     Q_D(KReparentingProxyModel);
1494     d->endResetProxy();
1495     return;
1496 }
1497 
1498 #include "moc_kreparentingproxymodel.cpp"