File indexing completed on 2024-05-12 15:43:01

0001 /*
0002     SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
0003     SPDX-FileCopyrightText: 2016 Ableton AG <info@ableton.com>
0004     SPDX-FileContributor: Stephen Kelly <stephen.kelly@ableton.com>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "kselectionproxymodel.h"
0010 
0011 #include <QItemSelectionRange>
0012 #include <QPointer>
0013 #include <QStringList>
0014 
0015 #include "kbihash_p.h"
0016 #include "kmodelindexproxymapper.h"
0017 #include "kvoidpointerfactory_p.h"
0018 
0019 typedef KBiHash<QPersistentModelIndex, QModelIndex> SourceProxyIndexMapping;
0020 typedef KBiHash<void *, QModelIndex> ParentMapping;
0021 typedef KHash2Map<QPersistentModelIndex, int> SourceIndexProxyRowMapping;
0022 
0023 /**
0024   Return true if @p idx is a descendant of one of the indexes in @p list.
0025   Note that this returns false if @p list contains @p idx.
0026 */
0027 template<typename ModelIndex>
0028 bool isDescendantOf(const QList<ModelIndex> &list, const QModelIndex &idx)
0029 {
0030     if (!idx.isValid()) {
0031         return false;
0032     }
0033 
0034     if (list.contains(idx)) {
0035         return false;
0036     }
0037 
0038     QModelIndex parent = idx.parent();
0039     while (parent.isValid()) {
0040         if (list.contains(parent)) {
0041             return true;
0042         }
0043         parent = parent.parent();
0044     }
0045     return false;
0046 }
0047 
0048 static bool isDescendantOf(const QItemSelection &selection, const QModelIndex &descendant)
0049 {
0050     if (!descendant.isValid()) {
0051         return false;
0052     }
0053 
0054     if (selection.contains(descendant)) {
0055         return false;
0056     }
0057 
0058     QModelIndex parent = descendant.parent();
0059     while (parent.isValid()) {
0060         if (selection.contains(parent)) {
0061             return true;
0062         }
0063 
0064         parent = parent.parent();
0065     }
0066     return false;
0067 }
0068 
0069 static bool isDescendantOf(const QItemSelectionRange &range, const QModelIndex &descendant)
0070 {
0071     if (!descendant.isValid()) {
0072         return false;
0073     }
0074 
0075     if (range.contains(descendant)) {
0076         return false;
0077     }
0078 
0079     QModelIndex parent = descendant.parent();
0080     while (parent.isValid()) {
0081         if (range.contains(parent)) {
0082             return true;
0083         }
0084 
0085         parent = parent.parent();
0086     }
0087     return false;
0088 }
0089 
0090 static int _getRootListRow(const QList<QModelIndexList> &rootAncestors, const QModelIndex &index)
0091 {
0092     QModelIndex commonParent = index;
0093     QModelIndex youngestAncestor;
0094 
0095     int firstCommonParent = -1;
0096     int bestParentRow = -1;
0097     while (commonParent.isValid()) {
0098         youngestAncestor = commonParent;
0099         commonParent = commonParent.parent();
0100 
0101         for (int i = 0; i < rootAncestors.size(); ++i) {
0102             const QModelIndexList ancestorList = rootAncestors.at(i);
0103 
0104             const int parentRow = ancestorList.indexOf(commonParent);
0105 
0106             if (parentRow < 0) {
0107                 continue;
0108             }
0109 
0110             if (parentRow > bestParentRow) {
0111                 firstCommonParent = i;
0112                 bestParentRow = parentRow;
0113             }
0114         }
0115 
0116         if (firstCommonParent >= 0) {
0117             break;
0118         }
0119     }
0120 
0121     // If @p list is non-empty, the invalid QModelIndex() will at least be found in ancestorList.
0122     Q_ASSERT(firstCommonParent >= 0);
0123 
0124     const QModelIndexList firstAnsList = rootAncestors.at(firstCommonParent);
0125 
0126     const QModelIndex eldestSibling = firstAnsList.value(bestParentRow + 1);
0127 
0128     if (eldestSibling.isValid()) {
0129         // firstCommonParent is a sibling of one of the ancestors of @p index.
0130         // It is the first index to share a common parent with one of the ancestors of @p index.
0131         if (eldestSibling.row() >= youngestAncestor.row()) {
0132             return firstCommonParent;
0133         }
0134     }
0135 
0136     int siblingOffset = 1;
0137 
0138     // The same commonParent might be common to several root indexes.
0139     // If this is the last in the list, it's the only match. We instruct the model
0140     // to insert the new index after it ( + siblingOffset).
0141     if (rootAncestors.size() <= firstCommonParent + siblingOffset) {
0142         return firstCommonParent + siblingOffset;
0143     }
0144 
0145     // A
0146     // - B
0147     //   - C
0148     //   - D
0149     //   - E
0150     // F
0151     //
0152     // F is selected, then C then D. When inserting D into the model, the commonParent is B (the parent of C).
0153     // The next existing sibling of B is F (in the proxy model). bestParentRow will then refer to an index on
0154     // the level of a child of F (which doesn't exist - Boom!). If it doesn't exist, then we've already found
0155     // the place to insert D
0156     QModelIndexList ansList = rootAncestors.at(firstCommonParent + siblingOffset);
0157     if (ansList.size() <= bestParentRow) {
0158         return firstCommonParent + siblingOffset;
0159     }
0160 
0161     QModelIndex nextParent = ansList.at(bestParentRow);
0162     while (nextParent == commonParent) {
0163         if (ansList.size() < bestParentRow + 1)
0164         // If the list is longer, it means that at the end of it is a descendant of the new index.
0165         // We insert the ancestors items first in that case.
0166         {
0167             break;
0168         }
0169 
0170         const QModelIndex nextSibling = ansList.value(bestParentRow + 1);
0171 
0172         if (!nextSibling.isValid()) {
0173             continue;
0174         }
0175 
0176         if (youngestAncestor.row() <= nextSibling.row()) {
0177             break;
0178         }
0179 
0180         siblingOffset++;
0181 
0182         if (rootAncestors.size() <= firstCommonParent + siblingOffset) {
0183             break;
0184         }
0185 
0186         ansList = rootAncestors.at(firstCommonParent + siblingOffset);
0187 
0188         // In the scenario above, E is selected after D, causing this loop to be entered,
0189         // and requiring a similar result if the next sibling in the proxy model does not have children.
0190         if (ansList.size() <= bestParentRow) {
0191             break;
0192         }
0193 
0194         nextParent = ansList.at(bestParentRow);
0195     }
0196 
0197     return firstCommonParent + siblingOffset;
0198 }
0199 
0200 /**
0201   Determines the correct location to insert @p index into @p list.
0202 */
0203 template<typename ModelIndex>
0204 static int getRootListRow(const QList<ModelIndex> &list, const QModelIndex &index)
0205 {
0206     if (!index.isValid()) {
0207         return -1;
0208     }
0209 
0210     if (list.isEmpty()) {
0211         return 0;
0212     }
0213 
0214     // What's going on?
0215     // Consider a tree like
0216     //
0217     // A
0218     // - B
0219     // - - C
0220     // - - - D
0221     // - E
0222     // - F
0223     // - - G
0224     // - - - H
0225     // - I
0226     // - - J
0227     // - K
0228     //
0229     // If D, E and J are already selected, and H is newly selected, we need to put H between E and J in the proxy model.
0230     // To figure that out, we create a list for each already selected index of its ancestors. Then,
0231     // we climb the ancestors of H until we reach an index with siblings which have a descendant
0232     // selected (F above has siblings B, E and I which have descendants which are already selected).
0233     // Those child indexes are traversed to find the right sibling to put F beside.
0234     //
0235     // i.e., new items are inserted in the expected location.
0236 
0237     QList<QModelIndexList> rootAncestors;
0238     for (const QModelIndex &root : list) {
0239         QModelIndexList ancestors;
0240         ancestors << root;
0241         QModelIndex parent = root.parent();
0242         while (parent.isValid()) {
0243             ancestors.prepend(parent);
0244             parent = parent.parent();
0245         }
0246         ancestors.prepend(QModelIndex());
0247         rootAncestors << ancestors;
0248     }
0249     return _getRootListRow(rootAncestors, index);
0250 }
0251 
0252 /**
0253   Returns a selection in which no descendants of selected indexes are also themselves selected.
0254   For example,
0255   @code
0256     A
0257     - B
0258     C
0259     D
0260   @endcode
0261   If A, B and D are selected in @p selection, the returned selection contains only A and D.
0262 */
0263 static QItemSelection getRootRanges(const QItemSelection &_selection)
0264 {
0265     QItemSelection rootSelection;
0266     QItemSelection selection = _selection;
0267     QList<QItemSelectionRange>::iterator it = selection.begin();
0268     while (it != selection.end()) {
0269         if (!it->topLeft().parent().isValid()) {
0270             rootSelection.append(*it);
0271             it = selection.erase(it);
0272         } else {
0273             ++it;
0274         }
0275     }
0276 
0277     it = selection.begin();
0278     while (it != selection.end()) {
0279         const QItemSelectionRange range = *it;
0280         it = selection.erase(it);
0281 
0282         if (isDescendantOf(rootSelection, range.topLeft()) || isDescendantOf(selection, range.topLeft())) {
0283             continue;
0284         }
0285 
0286         rootSelection << range;
0287     }
0288     return rootSelection;
0289 }
0290 
0291 /**
0292  */
0293 struct RangeLessThan {
0294     bool operator()(const QItemSelectionRange &left, const QItemSelectionRange &right) const
0295     {
0296         if (right.model() == left.model()) {
0297             // parent has to be calculated, so we only do so once.
0298             const QModelIndex topLeftParent = left.parent();
0299             const QModelIndex otherTopLeftParent = right.parent();
0300             if (topLeftParent == otherTopLeftParent) {
0301                 if (right.top() == left.top()) {
0302                     if (right.left() == left.left()) {
0303                         if (right.bottom() == left.bottom()) {
0304                             return left.right() < right.right();
0305                         }
0306                         return left.bottom() < right.bottom();
0307                     }
0308                     return left.left() < right.left();
0309                 }
0310                 return left.top() < right.top();
0311             }
0312             return topLeftParent < otherTopLeftParent;
0313         }
0314         return left.model() < right.model();
0315     }
0316 };
0317 
0318 static QItemSelection stableNormalizeSelection(const QItemSelection &selection)
0319 {
0320     if (selection.size() <= 1) {
0321         return selection;
0322     }
0323 
0324     QItemSelection::const_iterator it = selection.begin();
0325     const QItemSelection::const_iterator end = selection.end();
0326 
0327     Q_ASSERT(it != end);
0328     QItemSelection::const_iterator scout = it + 1;
0329 
0330     QItemSelection result;
0331     while (scout != end) {
0332         Q_ASSERT(it != end);
0333         int bottom = it->bottom();
0334         while (scout != end && it->parent() == scout->parent() && bottom + 1 == scout->top()) {
0335             bottom = scout->bottom();
0336             ++scout;
0337         }
0338         if (bottom != it->bottom()) {
0339             const QModelIndex topLeft = it->topLeft();
0340             result << QItemSelectionRange(topLeft, topLeft.sibling(bottom, it->right()));
0341         }
0342         Q_ASSERT(it != scout);
0343         if (scout == end) {
0344             break;
0345         }
0346         if (it + 1 == scout) {
0347             result << *it;
0348         }
0349         it = scout;
0350         ++scout;
0351         if (scout == end) {
0352             result << *it;
0353         }
0354     }
0355     return result;
0356 }
0357 
0358 static QItemSelection kNormalizeSelection(QItemSelection selection)
0359 {
0360     if (selection.size() <= 1) {
0361         return selection;
0362     }
0363 
0364     // KSelectionProxyModel has a strong assumption that
0365     // the views always select rows, so usually the
0366     // @p selection here contains ranges that span all
0367     // columns. However, if a QSortFilterProxyModel
0368     // is used too, it splits up the complete ranges into
0369     // one index per range. That confuses the data structures
0370     // held by this proxy (which keeps track of indexes in the
0371     // first column). As this proxy already assumes that if the
0372     // zeroth column is selected, then its entire row is selected,
0373     // we can safely remove the ranges which do not include
0374     // column 0 without a loss of functionality.
0375     QItemSelection::iterator i = selection.begin();
0376     while (i != selection.end()) {
0377         if (i->left() > 0) {
0378             i = selection.erase(i);
0379         } else {
0380             ++i;
0381         }
0382     }
0383 
0384     RangeLessThan lt;
0385     std::sort(selection.begin(), selection.end(), lt);
0386     return stableNormalizeSelection(selection);
0387 }
0388 
0389 class KSelectionProxyModelPrivate
0390 {
0391 public:
0392     KSelectionProxyModelPrivate(KSelectionProxyModel *model)
0393         : q_ptr(model)
0394         , m_indexMapper(nullptr)
0395         , m_startWithChildTrees(false)
0396         , m_omitChildren(false)
0397         , m_omitDescendants(false)
0398         , m_includeAllSelected(false)
0399         , m_rowsInserted(false)
0400         , m_rowsRemoved(false)
0401         , m_recreateFirstChildMappingOnRemoval(false)
0402         , m_rowsMoved(false)
0403         , m_resetting(false)
0404         , m_sourceModelResetting(false)
0405         , m_doubleResetting(false)
0406         , m_layoutChanging(false)
0407         , m_ignoreNextLayoutAboutToBeChanged(false)
0408         , m_ignoreNextLayoutChanged(false)
0409         , m_selectionModel(nullptr)
0410         , m_filterBehavior(KSelectionProxyModel::InvalidBehavior)
0411     {
0412     }
0413 
0414     Q_DECLARE_PUBLIC(KSelectionProxyModel)
0415     KSelectionProxyModel *const q_ptr;
0416 
0417     // A unique id is generated for each parent. It is used for the internalPointer of its children in the proxy
0418     // This is used to store a unique id for QModelIndexes in the proxy which have children.
0419     // If an index newly gets children it is added to this hash. If its last child is removed it is removed from this map.
0420     // If this map contains an index, that index hasChildren(). This hash is populated when new rows are inserted in the
0421     // source model, or a new selection is made.
0422     mutable ParentMapping m_parentIds;
0423     // This mapping maps indexes with children in the source to indexes with children in the proxy.
0424     // The order of indexes in this list is not relevant.
0425     mutable SourceProxyIndexMapping m_mappedParents;
0426 
0427     KVoidPointerFactory<> m_voidPointerFactory;
0428 
0429     /**
0430       Keeping Persistent indexes from this model in this model breaks in certain situations
0431       such as after source insert, but before calling endInsertRows in this model. In such a state,
0432       the persistent indexes are not updated, but the methods assume they are already up-to-date.
0433 
0434       Instead of using persistentindexes for proxy indexes in m_mappedParents, we maintain them ourselves with this method.
0435 
0436       m_mappedParents and m_parentIds are affected.
0437 
0438       @p parent and @p start refer to the proxy model. Any rows >= @p start will be updated.
0439       @p offset is the amount that affected indexes will be changed.
0440     */
0441     void updateInternalIndexes(const QModelIndex &parent, int start, int offset);
0442 
0443     /**
0444      * Updates stored indexes in the proxy. Any proxy row >= @p start is changed by @p offset.
0445      *
0446      * This is only called to update indexes in the top level of the proxy. Most commonly that is
0447      *
0448      * m_mappedParents, m_parentIds and m_mappedFirstChildren are affected.
0449      */
0450     void updateInternalTopIndexes(int start, int offset);
0451 
0452     void updateFirstChildMapping(const QModelIndex &parent, int offset);
0453 
0454     bool isFlat() const
0455     {
0456         return m_omitChildren || (m_omitDescendants && m_startWithChildTrees);
0457     }
0458 
0459     /**
0460      * Tries to ensure that @p parent is a mapped parent in the proxy.
0461      * Returns true if parent is mappable in the model, and false otherwise.
0462      */
0463     bool ensureMappable(const QModelIndex &parent) const;
0464     bool parentIsMappable(const QModelIndex &parent) const
0465     {
0466         return parentAlreadyMapped(parent) || m_rootIndexList.contains(parent);
0467     }
0468 
0469     /**
0470      * Maps @p parent to source if it is already mapped, and otherwise returns an invalid QModelIndex.
0471      */
0472     QModelIndex mapFromSource(const QModelIndex &parent) const;
0473 
0474     /**
0475       Creates mappings in m_parentIds and m_mappedParents between the source and the proxy.
0476 
0477       This is not recursive
0478     */
0479     void createParentMappings(const QModelIndex &parent, int start, int end) const;
0480     void createFirstChildMapping(const QModelIndex &parent, int proxyRow) const;
0481     bool firstChildAlreadyMapped(const QModelIndex &firstChild) const;
0482     bool parentAlreadyMapped(const QModelIndex &parent) const;
0483     void removeFirstChildMappings(int start, int end);
0484     void removeParentMappings(const QModelIndex &parent, int start, int end);
0485 
0486     /**
0487       Given a QModelIndex in the proxy, return the corresponding QModelIndex in the source.
0488 
0489       This method works only if the index has children in the proxy model which already has a mapping from the source.
0490 
0491       This means that if the proxy is a flat list, this method will always return QModelIndex(). Additionally, it means that m_mappedParents is not populated
0492       automatically and must be populated manually.
0493 
0494       No new mapping is created by this method.
0495     */
0496     QModelIndex mapParentToSource(const QModelIndex &proxyParent) const;
0497 
0498     /**
0499       Given a QModelIndex in the source model, return the corresponding QModelIndex in the proxy.
0500 
0501       This method works only if the index has children in the proxy model which already has a mapping from the source.
0502 
0503       No new mapping is created by this method.
0504     */
0505     QModelIndex mapParentFromSource(const QModelIndex &sourceParent) const;
0506 
0507     QModelIndex mapTopLevelToSource(int row, int column) const;
0508     QModelIndex mapTopLevelFromSource(const QModelIndex &sourceIndex) const;
0509     QModelIndex createTopLevelIndex(int row, int column) const;
0510     int topLevelRowCount() const;
0511 
0512     void *parentId(const QModelIndex &proxyParent) const
0513     {
0514         return m_parentIds.rightToLeft(proxyParent);
0515     }
0516     QModelIndex parentForId(void *id) const
0517     {
0518         return m_parentIds.leftToRight(id);
0519     }
0520 
0521     // Only populated if m_startWithChildTrees.
0522 
0523     mutable SourceIndexProxyRowMapping m_mappedFirstChildren;
0524 
0525     // Source list is the selection in the source model.
0526     QList<QPersistentModelIndex> m_rootIndexList;
0527 
0528     KModelIndexProxyMapper *m_indexMapper;
0529 
0530     QPair<int, int> beginRemoveRows(const QModelIndex &parent, int start, int end) const;
0531     QPair<int, int> beginInsertRows(const QModelIndex &parent, int start, int end) const;
0532     void endRemoveRows(const QModelIndex &sourceParent, int proxyStart, int proxyEnd);
0533     void endInsertRows(const QModelIndex &parent, int start, int end);
0534 
0535     void sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
0536     void sourceRowsInserted(const QModelIndex &parent, int start, int end);
0537     void sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
0538     void sourceRowsRemoved(const QModelIndex &parent, int start, int end);
0539     void sourceRowsAboutToBeMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destParent, int destRow);
0540     void sourceRowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destParent, int destRow);
0541     void sourceModelAboutToBeReset();
0542     void sourceModelReset();
0543     void sourceLayoutAboutToBeChanged();
0544     void sourceLayoutChanged();
0545     void emitContinuousRanges(const QModelIndex &sourceFirst, const QModelIndex &sourceLast, const QModelIndex &proxyFirst, const QModelIndex &proxyLast);
0546     void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
0547 
0548     void removeSelectionFromProxy(const QItemSelection &selection);
0549 
0550     void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
0551     void sourceModelDestroyed();
0552 
0553     void resetInternalData();
0554 
0555     bool rootWillBeRemoved(const QItemSelection &selection, const QModelIndex &root);
0556 
0557     /**
0558       When items are inserted or removed in the m_startWithChildTrees configuration,
0559       this method helps find the startRow for use emitting the signals from the proxy.
0560     */
0561     int getProxyInitialRow(const QModelIndex &parent) const;
0562 
0563     /**
0564       If m_startWithChildTrees is true, this method returns the row in the proxy model to insert newIndex
0565       items.
0566 
0567       This is a special case because the items above rootListRow in the list are not in the model, but
0568       their children are. Those children must be counted.
0569 
0570       If m_startWithChildTrees is false, this method returns @p rootListRow.
0571     */
0572     int getTargetRow(int rootListRow);
0573 
0574     /**
0575       Inserts the indexes in @p list into the proxy model.
0576     */
0577     void insertSelectionIntoProxy(const QItemSelection &selection);
0578 
0579     bool m_startWithChildTrees;
0580     bool m_omitChildren;
0581     bool m_omitDescendants;
0582     bool m_includeAllSelected;
0583     bool m_rowsInserted;
0584     bool m_rowsRemoved;
0585     bool m_recreateFirstChildMappingOnRemoval;
0586     QPair<int, int> m_proxyRemoveRows;
0587     bool m_rowsMoved;
0588     bool m_resetting;
0589     bool m_sourceModelResetting;
0590     bool m_doubleResetting;
0591     bool m_layoutChanging;
0592     bool m_ignoreNextLayoutAboutToBeChanged;
0593     bool m_ignoreNextLayoutChanged;
0594     QPointer<QItemSelectionModel> m_selectionModel;
0595 
0596     KSelectionProxyModel::FilterBehavior m_filterBehavior;
0597 
0598     QList<QPersistentModelIndex> m_layoutChangePersistentIndexes;
0599     QModelIndexList m_proxyIndexes;
0600 
0601     struct PendingSelectionChange {
0602         PendingSelectionChange()
0603         {
0604         }
0605         PendingSelectionChange(const QItemSelection &selected_, const QItemSelection &deselected_)
0606             : selected(selected_)
0607             , deselected(deselected_)
0608         {
0609         }
0610         QItemSelection selected;
0611         QItemSelection deselected;
0612     };
0613     QVector<PendingSelectionChange> m_pendingSelectionChanges;
0614     QMetaObject::Connection selectionModelModelAboutToBeResetConnection;
0615     QMetaObject::Connection selectionModelModelResetConnection;
0616 };
0617 
0618 void KSelectionProxyModelPrivate::emitContinuousRanges(const QModelIndex &sourceFirst,
0619                                                        const QModelIndex &sourceLast,
0620                                                        const QModelIndex &proxyFirst,
0621                                                        const QModelIndex &proxyLast)
0622 {
0623     Q_Q(KSelectionProxyModel);
0624 
0625     Q_ASSERT(sourceFirst.model() == q->sourceModel());
0626     Q_ASSERT(sourceLast.model() == q->sourceModel());
0627     Q_ASSERT(proxyFirst.model() == q);
0628     Q_ASSERT(proxyLast.model() == q);
0629 
0630     const int proxyRangeSize = proxyLast.row() - proxyFirst.row();
0631     const int sourceRangeSize = sourceLast.row() - sourceFirst.row();
0632 
0633     if (proxyRangeSize == sourceRangeSize) {
0634         Q_EMIT q->dataChanged(proxyFirst, proxyLast);
0635         return;
0636     }
0637 
0638     // TODO: Loop to skip descendant ranges.
0639     //     int lastRow;
0640     //
0641     //     const QModelIndex sourceHalfWay = sourceFirst.sibling(sourceFirst.row() + (sourceRangeSize / 2));
0642     //     const QModelIndex proxyHalfWay = proxyFirst.sibling(proxyFirst.row() + (proxyRangeSize / 2));
0643     //     const QModelIndex mappedSourceHalfway = q->mapToSource(proxyHalfWay);
0644     //
0645     //     const int halfProxyRange = mappedSourceHalfway.row() - proxyFirst.row();
0646     //     const int halfSourceRange = sourceHalfWay.row() - sourceFirst.row();
0647     //
0648     //     if (proxyRangeSize == sourceRangeSize)
0649     //     {
0650     //         Q_EMIT q->dataChanged(proxyFirst, proxyLast.sibling(proxyFirst.row() + proxyRangeSize, proxyLast.column()));
0651     //         return;
0652     //     }
0653 
0654     Q_EMIT q->dataChanged(proxyFirst, proxyLast);
0655 }
0656 
0657 void KSelectionProxyModelPrivate::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
0658 {
0659     Q_Q(KSelectionProxyModel);
0660 
0661     Q_ASSERT(topLeft.model() == q->sourceModel());
0662     Q_ASSERT(bottomRight.model() == q->sourceModel());
0663 
0664     const QModelIndex sourceRangeParent = topLeft.parent();
0665     if (!sourceRangeParent.isValid() && m_startWithChildTrees && !m_rootIndexList.contains(sourceRangeParent)) {
0666         return;
0667     }
0668 
0669     const QModelIndex proxyTopLeft = q->mapFromSource(topLeft);
0670     const QModelIndex proxyBottomRight = q->mapFromSource(bottomRight);
0671 
0672     const QModelIndex proxyRangeParent = proxyTopLeft.parent();
0673 
0674     if (!m_omitChildren && m_omitDescendants && m_startWithChildTrees && m_includeAllSelected) {
0675         // ChildrenOfExactSelection
0676         if (proxyTopLeft.isValid()) {
0677             emitContinuousRanges(topLeft, bottomRight, proxyTopLeft, proxyBottomRight);
0678         }
0679         return;
0680     }
0681 
0682     if ((m_omitChildren && !m_startWithChildTrees && m_includeAllSelected) || (!proxyRangeParent.isValid() && !m_startWithChildTrees)) {
0683         // Exact selection and SubTreeRoots and SubTrees in top level
0684         // Emit continuous ranges.
0685         QList<int> changedRows;
0686         for (int row = topLeft.row(); row <= bottomRight.row(); ++row) {
0687             const QModelIndex index = q->sourceModel()->index(row, topLeft.column(), topLeft.parent());
0688             const int idx = m_rootIndexList.indexOf(index);
0689             if (idx != -1) {
0690                 changedRows.append(idx);
0691             }
0692         }
0693         if (changedRows.isEmpty()) {
0694             return;
0695         }
0696         int first = changedRows.first();
0697         int previous = first;
0698         QList<int>::const_iterator it = changedRows.constBegin();
0699         const QList<int>::const_iterator end = changedRows.constEnd();
0700         for (; it != end; ++it) {
0701             if (*it == previous + 1) {
0702                 ++previous;
0703             } else {
0704                 const QModelIndex _top = q->index(first, topLeft.column());
0705                 const QModelIndex _bottom = q->index(previous, bottomRight.column());
0706                 Q_EMIT q->dataChanged(_top, _bottom);
0707                 previous = first = *it;
0708             }
0709         }
0710         if (first != previous) {
0711             const QModelIndex _top = q->index(first, topLeft.column());
0712             const QModelIndex _bottom = q->index(previous, bottomRight.column());
0713             Q_EMIT q->dataChanged(_top, _bottom);
0714         }
0715         return;
0716     }
0717     if (proxyRangeParent.isValid()) {
0718         if (m_omitChildren && !m_startWithChildTrees && !m_includeAllSelected)
0719         // SubTreeRoots
0720         {
0721             return;
0722         }
0723         if (!proxyTopLeft.isValid()) {
0724             return;
0725         }
0726         // SubTrees and SubTreesWithoutRoots
0727         Q_EMIT q->dataChanged(proxyTopLeft, proxyBottomRight);
0728         return;
0729     }
0730 
0731     if (m_startWithChildTrees && !m_omitChildren && !m_includeAllSelected && !m_omitDescendants) {
0732         // SubTreesWithoutRoots
0733         if (proxyTopLeft.isValid()) {
0734             Q_EMIT q->dataChanged(proxyTopLeft, proxyBottomRight);
0735         }
0736         return;
0737     }
0738 }
0739 
0740 void KSelectionProxyModelPrivate::sourceLayoutAboutToBeChanged()
0741 {
0742     Q_Q(KSelectionProxyModel);
0743 
0744     if (m_ignoreNextLayoutAboutToBeChanged) {
0745         m_ignoreNextLayoutAboutToBeChanged = false;
0746         return;
0747     }
0748 
0749     if (m_rootIndexList.isEmpty()) {
0750         return;
0751     }
0752 
0753     Q_EMIT q->layoutAboutToBeChanged();
0754 
0755     QItemSelection selection;
0756     for (const QModelIndex &rootIndex : std::as_const(m_rootIndexList)) {
0757         // This will be optimized later.
0758         Q_EMIT q->rootIndexAboutToBeRemoved(rootIndex, KSelectionProxyModel::QPrivateSignal());
0759         selection.append(QItemSelectionRange(rootIndex, rootIndex));
0760     }
0761 
0762     selection = kNormalizeSelection(selection);
0763     Q_EMIT q->rootSelectionAboutToBeRemoved(selection, KSelectionProxyModel::QPrivateSignal());
0764 
0765     QPersistentModelIndex srcPersistentIndex;
0766     const auto lst = q->persistentIndexList();
0767     for (const QModelIndex &proxyPersistentIndex : lst) {
0768         m_proxyIndexes << proxyPersistentIndex;
0769         Q_ASSERT(proxyPersistentIndex.isValid());
0770         srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
0771         Q_ASSERT(srcPersistentIndex.isValid());
0772         m_layoutChangePersistentIndexes << srcPersistentIndex;
0773     }
0774 
0775     m_rootIndexList.clear();
0776 }
0777 
0778 void KSelectionProxyModelPrivate::sourceLayoutChanged()
0779 {
0780     Q_Q(KSelectionProxyModel);
0781 
0782     if (m_ignoreNextLayoutChanged) {
0783         m_ignoreNextLayoutChanged = false;
0784         return;
0785     }
0786 
0787     if (!m_selectionModel || !m_selectionModel->hasSelection()) {
0788         return;
0789     }
0790 
0791     // Handling this signal is slow.
0792     // The problem is that anything can happen between emissions of layoutAboutToBeChanged and layoutChanged.
0793     // We can't assume anything is the same about the structure anymore. items have been sorted, items which
0794     // were parents before are now not, items which were not parents before now are, items which used to be the
0795     // first child are now the Nth child and items which used to be the Nth child are now the first child.
0796     // We effectively can't update our mapping because we don't have enough information to update everything.
0797     // The only way we would have is if we take a persistent index of the entire source model
0798     // on sourceLayoutAboutToBeChanged and then examine it here. That would be far too expensive.
0799     // Instead we just have to clear the entire mapping and recreate it.
0800 
0801     m_rootIndexList.clear();
0802     m_mappedFirstChildren.clear();
0803     m_mappedParents.clear();
0804     m_parentIds.clear();
0805 
0806     m_resetting = true;
0807     m_layoutChanging = true;
0808     selectionChanged(m_selectionModel->selection(), QItemSelection());
0809     m_resetting = false;
0810     m_layoutChanging = false;
0811 
0812     for (int i = 0; i < m_proxyIndexes.size(); ++i) {
0813         q->changePersistentIndex(m_proxyIndexes.at(i), q->mapFromSource(m_layoutChangePersistentIndexes.at(i)));
0814     }
0815 
0816     m_layoutChangePersistentIndexes.clear();
0817     m_proxyIndexes.clear();
0818 
0819     Q_EMIT q->layoutChanged();
0820 }
0821 
0822 void KSelectionProxyModelPrivate::resetInternalData()
0823 {
0824     m_rootIndexList.clear();
0825     m_layoutChangePersistentIndexes.clear();
0826     m_proxyIndexes.clear();
0827     m_mappedParents.clear();
0828     m_parentIds.clear();
0829     m_mappedFirstChildren.clear();
0830     m_voidPointerFactory.clear();
0831 }
0832 
0833 void KSelectionProxyModelPrivate::sourceModelDestroyed()
0834 {
0835     // There is very little we can do here.
0836     resetInternalData();
0837     m_resetting = false;
0838     m_sourceModelResetting = false;
0839 }
0840 
0841 void KSelectionProxyModelPrivate::sourceModelAboutToBeReset()
0842 {
0843     Q_Q(KSelectionProxyModel);
0844 
0845     // We might be resetting as a result of the selection source model resetting.
0846     // If so we don't want to emit
0847     // sourceModelAboutToBeReset
0848     // sourceModelAboutToBeReset
0849     // sourceModelReset
0850     // sourceModelReset
0851     // So we ensure that we just emit one.
0852     if (m_resetting) {
0853         // If both the source model and the selection source model are reset,
0854         // We want to begin our reset before the first one is reset and end
0855         // it after the second one is reset.
0856         m_doubleResetting = true;
0857         return;
0858     }
0859 
0860     q->beginResetModel();
0861     m_resetting = true;
0862     m_sourceModelResetting = true;
0863 }
0864 
0865 void KSelectionProxyModelPrivate::sourceModelReset()
0866 {
0867     Q_Q(KSelectionProxyModel);
0868 
0869     if (m_doubleResetting) {
0870         m_doubleResetting = false;
0871         return;
0872     }
0873 
0874     resetInternalData();
0875     m_sourceModelResetting = false;
0876     m_resetting = false;
0877     selectionChanged(m_selectionModel->selection(), QItemSelection());
0878     q->endResetModel();
0879 }
0880 
0881 int KSelectionProxyModelPrivate::getProxyInitialRow(const QModelIndex &parent) const
0882 {
0883     Q_ASSERT(m_rootIndexList.contains(parent));
0884 
0885     // The difficulty here is that parent and parent.parent() might both be in the m_rootIndexList.
0886 
0887     // - A
0888     // - B
0889     // - - C
0890     // - - D
0891     // - - - E
0892 
0893     // Consider that B and D are selected. The proxy model is:
0894 
0895     // - C
0896     // - D
0897     // - E
0898 
0899     // Then D gets a new child at 0. In that case we require adding F between D and E.
0900 
0901     // Consider instead that D gets removed. Then @p parent will be B.
0902 
0903     Q_Q(const KSelectionProxyModel);
0904 
0905     Q_ASSERT(parent.model() == q->sourceModel());
0906 
0907     int parentPosition = m_rootIndexList.indexOf(parent);
0908 
0909     QModelIndex parentAbove;
0910 
0911     // If parentPosition == 0, then parent.parent() is not also in the model. (ordering is preserved)
0912     while (parentPosition > 0) {
0913         parentPosition--;
0914 
0915         parentAbove = m_rootIndexList.at(parentPosition);
0916         Q_ASSERT(parentAbove.isValid());
0917 
0918         int rows = q->sourceModel()->rowCount(parentAbove);
0919         if (rows > 0) {
0920             QModelIndex sourceIndexAbove = q->sourceModel()->index(rows - 1, 0, parentAbove);
0921             Q_ASSERT(sourceIndexAbove.isValid());
0922             QModelIndex proxyChildAbove = mapFromSource(sourceIndexAbove);
0923             Q_ASSERT(proxyChildAbove.isValid());
0924             return proxyChildAbove.row() + 1;
0925         }
0926     }
0927     return 0;
0928 }
0929 
0930 void KSelectionProxyModelPrivate::updateFirstChildMapping(const QModelIndex &parent, int offset)
0931 {
0932     Q_Q(KSelectionProxyModel);
0933 
0934     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
0935 
0936     static const int column = 0;
0937     static const int row = 0;
0938 
0939     const QPersistentModelIndex srcIndex = q->sourceModel()->index(row, column, parent);
0940 
0941     const QPersistentModelIndex previousFirstChild = q->sourceModel()->index(offset, column, parent);
0942 
0943     SourceIndexProxyRowMapping::left_iterator it = m_mappedFirstChildren.findLeft(previousFirstChild);
0944     if (it == m_mappedFirstChildren.leftEnd()) {
0945         return;
0946     }
0947 
0948     Q_ASSERT(srcIndex.isValid());
0949     const int proxyRow = it.value();
0950     Q_ASSERT(proxyRow >= 0);
0951 
0952     m_mappedFirstChildren.eraseLeft(it);
0953 
0954     // The proxy row in the mapping has already been updated by the offset in updateInternalTopIndexes
0955     // so we restore it by applying the reverse.
0956     m_mappedFirstChildren.insert(srcIndex, proxyRow - offset);
0957 }
0958 
0959 QPair<int, int> KSelectionProxyModelPrivate::beginInsertRows(const QModelIndex &parent, int start, int end) const
0960 {
0961     const QModelIndex proxyParent = mapFromSource(parent);
0962 
0963     if (!proxyParent.isValid()) {
0964         if (!m_startWithChildTrees) {
0965             return qMakePair(-1, -1);
0966         }
0967 
0968         if (!m_rootIndexList.contains(parent)) {
0969             return qMakePair(-1, -1);
0970         }
0971     }
0972 
0973     if (!m_startWithChildTrees) {
0974         // SubTrees
0975         if (proxyParent.isValid()) {
0976             return qMakePair(start, end);
0977         }
0978         return qMakePair(-1, -1);
0979     }
0980 
0981     if (!m_includeAllSelected && proxyParent.isValid()) {
0982         // SubTreesWithoutRoots deeper than topLevel
0983         return qMakePair(start, end);
0984     }
0985 
0986     if (!m_rootIndexList.contains(parent)) {
0987         return qMakePair(-1, -1);
0988     }
0989 
0990     const int proxyStartRow = getProxyInitialRow(parent) + start;
0991     return qMakePair(proxyStartRow, proxyStartRow + (end - start));
0992 }
0993 
0994 void KSelectionProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
0995 {
0996     Q_Q(KSelectionProxyModel);
0997 
0998     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
0999 
1000     if (!m_selectionModel || !m_selectionModel->hasSelection()) {
1001         return;
1002     }
1003 
1004     if (m_omitChildren)
1005     // ExactSelection and SubTreeRoots
1006     {
1007         return;
1008     }
1009 
1010     // topLevel insertions can be ignored because topLevel items would need to be selected to affect the proxy.
1011     if (!parent.isValid()) {
1012         return;
1013     }
1014 
1015     QPair<int, int> pair = beginInsertRows(parent, start, end);
1016     if (pair.first == -1) {
1017         return;
1018     }
1019 
1020     const QModelIndex proxyParent = m_startWithChildTrees ? QModelIndex() : mapFromSource(parent);
1021 
1022     m_rowsInserted = true;
1023     q->beginInsertRows(proxyParent, pair.first, pair.second);
1024 }
1025 
1026 void KSelectionProxyModelPrivate::endInsertRows(const QModelIndex &parent, int start, int end)
1027 {
1028     Q_Q(const KSelectionProxyModel);
1029     const QModelIndex proxyParent = mapFromSource(parent);
1030     const int offset = end - start + 1;
1031 
1032     const bool isNewParent = (q->sourceModel()->rowCount(parent) == offset);
1033 
1034     if (m_startWithChildTrees && m_rootIndexList.contains(parent)) {
1035         const int proxyInitialRow = getProxyInitialRow(parent);
1036         Q_ASSERT(proxyInitialRow >= 0);
1037         const int proxyStartRow = proxyInitialRow + start;
1038 
1039         updateInternalTopIndexes(proxyStartRow, offset);
1040         if (isNewParent) {
1041             createFirstChildMapping(parent, proxyStartRow);
1042         } else if (start == 0)
1043         // We already have a first child mapping, but what we have mapped is not the first child anymore
1044         // so we need to update it.
1045         {
1046             updateFirstChildMapping(parent, end + 1);
1047         }
1048     } else {
1049         Q_ASSERT(proxyParent.isValid());
1050         if (!isNewParent) {
1051             updateInternalIndexes(proxyParent, start, offset);
1052         } else {
1053             createParentMappings(parent.parent(), parent.row(), parent.row());
1054         }
1055     }
1056     createParentMappings(parent, start, end);
1057 }
1058 
1059 void KSelectionProxyModelPrivate::sourceRowsInserted(const QModelIndex &parent, int start, int end)
1060 {
1061     Q_Q(KSelectionProxyModel);
1062 
1063     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
1064 
1065     if (!m_rowsInserted) {
1066         return;
1067     }
1068     m_rowsInserted = false;
1069     endInsertRows(parent, start, end);
1070     q->endInsertRows();
1071     for (const PendingSelectionChange &pendingChange : std::as_const(m_pendingSelectionChanges)) {
1072         selectionChanged(pendingChange.selected, pendingChange.deselected);
1073     }
1074     m_pendingSelectionChanges.clear();
1075 }
1076 
1077 static bool rootWillBeRemovedFrom(const QModelIndex &ancestor, int start, int end, const QModelIndex &root)
1078 {
1079     Q_ASSERT(root.isValid());
1080 
1081     auto parent = root;
1082     while (parent.isValid()) {
1083         auto prev = parent;
1084         parent = parent.parent();
1085         if (parent == ancestor) {
1086             return (prev.row() <= end && prev.row() >= start);
1087         }
1088     }
1089     return false;
1090 }
1091 
1092 bool KSelectionProxyModelPrivate::rootWillBeRemoved(const QItemSelection &selection, const QModelIndex &root)
1093 {
1094     Q_ASSERT(root.isValid());
1095 
1096     for (auto &r : selection) {
1097         if (m_includeAllSelected) {
1098             if (r.parent() == root.parent() && root.row() <= r.bottom() && root.row() >= r.top()) {
1099                 return true;
1100             }
1101         } else {
1102             if (rootWillBeRemovedFrom(r.parent(), r.top(), r.bottom(), root)) {
1103                 return true;
1104             }
1105         }
1106     }
1107     return false;
1108 }
1109 
1110 QPair<int, int> KSelectionProxyModelPrivate::beginRemoveRows(const QModelIndex &parent, int start, int end) const
1111 {
1112     Q_Q(const KSelectionProxyModel);
1113 
1114     if (!m_includeAllSelected && !m_omitChildren) {
1115         // SubTrees and SubTreesWithoutRoots
1116         const QModelIndex proxyParent = mapParentFromSource(parent);
1117         if (proxyParent.isValid()) {
1118             return qMakePair(start, end);
1119         }
1120     }
1121 
1122     if (m_startWithChildTrees && m_rootIndexList.contains(parent)) {
1123         const int proxyStartRow = getProxyInitialRow(parent) + start;
1124         const int proxyEndRow = proxyStartRow + (end - start);
1125         return qMakePair(proxyStartRow, proxyEndRow);
1126     }
1127 
1128     QList<QPersistentModelIndex>::const_iterator rootIt = m_rootIndexList.constBegin();
1129     const QList<QPersistentModelIndex>::const_iterator rootEnd = m_rootIndexList.constEnd();
1130     int proxyStartRemove = 0;
1131 
1132     for (; rootIt != rootEnd; ++rootIt) {
1133         if (rootWillBeRemovedFrom(parent, start, end, *rootIt)) {
1134             break;
1135         } else {
1136             if (m_startWithChildTrees) {
1137                 proxyStartRemove += q->sourceModel()->rowCount(*rootIt);
1138             } else {
1139                 ++proxyStartRemove;
1140             }
1141         }
1142     }
1143 
1144     if (rootIt == rootEnd) {
1145         return qMakePair(-1, -1);
1146     }
1147 
1148     int proxyEndRemove = proxyStartRemove;
1149 
1150     for (; rootIt != rootEnd; ++rootIt) {
1151         if (!rootWillBeRemovedFrom(parent, start, end, *rootIt)) {
1152             break;
1153         }
1154         if (m_startWithChildTrees) {
1155             proxyEndRemove += q->sourceModel()->rowCount(*rootIt);
1156         } else {
1157             ++proxyEndRemove;
1158         }
1159     }
1160 
1161     --proxyEndRemove;
1162     if (proxyEndRemove >= proxyStartRemove) {
1163         return qMakePair(proxyStartRemove, proxyEndRemove);
1164     }
1165     return qMakePair(-1, -1);
1166 }
1167 
1168 void KSelectionProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
1169 {
1170     Q_Q(KSelectionProxyModel);
1171 
1172     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
1173 
1174     if (!m_selectionModel || !m_selectionModel->hasSelection()) {
1175         return;
1176     }
1177 
1178     QPair<int, int> pair = beginRemoveRows(parent, start, end);
1179     if (pair.first == -1) {
1180         return;
1181     }
1182 
1183     const QModelIndex proxyParent = mapParentFromSource(parent);
1184 
1185     m_rowsRemoved = true;
1186     m_proxyRemoveRows = pair;
1187     m_recreateFirstChildMappingOnRemoval = m_mappedFirstChildren.leftContains(q->sourceModel()->index(start, 0, parent));
1188     q->beginRemoveRows(proxyParent, pair.first, pair.second);
1189 }
1190 
1191 void KSelectionProxyModelPrivate::endRemoveRows(const QModelIndex &sourceParent, int proxyStart, int proxyEnd)
1192 {
1193     const QModelIndex proxyParent = mapParentFromSource(sourceParent);
1194 
1195     // We need to make sure to remove entries from the mappings before updating internal indexes.
1196 
1197     // - A
1198     // - - B
1199     // - C
1200     // - - D
1201 
1202     // If A and C are selected, B and D are in the proxy. B maps to row 0 and D maps to row 1.
1203     // If B is then deleted leaving only D in the proxy, D needs to be updated to be a mapping
1204     // to row 0 instead of row 1. If that is done before removing the mapping for B, then the mapping
1205     // for D would overwrite the mapping for B and then the code for removing mappings would incorrectly
1206     // remove D.
1207     // So we first remove B and then update D.
1208 
1209     {
1210         SourceProxyIndexMapping::right_iterator it = m_mappedParents.rightBegin();
1211 
1212         while (it != m_mappedParents.rightEnd()) {
1213             if (!it.value().isValid()) {
1214                 m_parentIds.removeRight(it.key());
1215                 it = m_mappedParents.eraseRight(it);
1216             } else {
1217                 ++it;
1218             }
1219         }
1220     }
1221 
1222     {
1223         // Depending on what is selected at the time, a single removal in the source could invalidate
1224         // many mapped first child items at once.
1225 
1226         // - A
1227         // - B
1228         // - - C
1229         // - - D
1230         // - - - E
1231         // - - - F
1232         // - - - - G
1233         // - - - - H
1234 
1235         // If D and F are selected, the proxy contains E, F, G, H. If B is then deleted E to H will
1236         // be removed, including both first child mappings at E and G.
1237 
1238         if (!proxyParent.isValid()) {
1239             removeFirstChildMappings(proxyStart, proxyEnd);
1240         }
1241     }
1242 
1243     if (proxyParent.isValid()) {
1244         updateInternalIndexes(proxyParent, proxyEnd + 1, -1 * (proxyEnd - proxyStart + 1));
1245     } else {
1246         updateInternalTopIndexes(proxyEnd + 1, -1 * (proxyEnd - proxyStart + 1));
1247     }
1248 
1249     QList<QPersistentModelIndex>::iterator rootIt = m_rootIndexList.begin();
1250     while (rootIt != m_rootIndexList.end()) {
1251         if (!rootIt->isValid()) {
1252             rootIt = m_rootIndexList.erase(rootIt);
1253         } else {
1254             ++rootIt;
1255         }
1256     }
1257 }
1258 
1259 void KSelectionProxyModelPrivate::sourceRowsRemoved(const QModelIndex &parent, int start, int end)
1260 {
1261     Q_Q(KSelectionProxyModel);
1262     Q_UNUSED(end)
1263     Q_UNUSED(start)
1264 
1265     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
1266 
1267     if (!m_selectionModel) {
1268         return;
1269     }
1270 
1271     if (!m_rowsRemoved) {
1272         return;
1273     }
1274     m_rowsRemoved = false;
1275 
1276     Q_ASSERT(m_proxyRemoveRows.first >= 0);
1277     Q_ASSERT(m_proxyRemoveRows.second >= 0);
1278     endRemoveRows(parent, m_proxyRemoveRows.first, m_proxyRemoveRows.second);
1279     if (m_recreateFirstChildMappingOnRemoval && q->sourceModel()->hasChildren(parent))
1280     // The private endRemoveRows call might remove the first child mapping for parent, so
1281     // we create it again in that case.
1282     {
1283         createFirstChildMapping(parent, m_proxyRemoveRows.first);
1284     }
1285     m_recreateFirstChildMappingOnRemoval = false;
1286 
1287     m_proxyRemoveRows = qMakePair(-1, -1);
1288     q->endRemoveRows();
1289 }
1290 
1291 void KSelectionProxyModelPrivate::sourceRowsAboutToBeMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow)
1292 {
1293     Q_UNUSED(srcParent)
1294     Q_UNUSED(srcStart)
1295     Q_UNUSED(srcEnd)
1296     Q_UNUSED(destParent)
1297     Q_UNUSED(destRow)
1298     // we cheat and just act like the layout changed; this might benefit from some
1299     // optimization
1300     sourceLayoutAboutToBeChanged();
1301 }
1302 
1303 void KSelectionProxyModelPrivate::sourceRowsMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow)
1304 {
1305     Q_UNUSED(srcParent)
1306     Q_UNUSED(srcStart)
1307     Q_UNUSED(srcEnd)
1308     Q_UNUSED(destParent)
1309     Q_UNUSED(destRow)
1310     // we cheat and just act like the layout changed; this might benefit from some
1311     // optimization
1312     sourceLayoutChanged();
1313 }
1314 
1315 QModelIndex KSelectionProxyModelPrivate::mapParentToSource(const QModelIndex &proxyParent) const
1316 {
1317     return m_mappedParents.rightToLeft(proxyParent);
1318 }
1319 
1320 QModelIndex KSelectionProxyModelPrivate::mapParentFromSource(const QModelIndex &sourceParent) const
1321 {
1322     return m_mappedParents.leftToRight(sourceParent);
1323 }
1324 
1325 static bool
1326 indexIsValid(bool startWithChildTrees, int row, const QList<QPersistentModelIndex> &rootIndexList, const SourceIndexProxyRowMapping &mappedFirstChildren)
1327 {
1328     if (!startWithChildTrees) {
1329         Q_ASSERT(rootIndexList.size() > row);
1330     } else {
1331         Q_ASSERT(!mappedFirstChildren.isEmpty());
1332 
1333         SourceIndexProxyRowMapping::right_const_iterator result = mappedFirstChildren.rightUpperBound(row) - 1;
1334 
1335         Q_ASSERT(result != mappedFirstChildren.rightEnd());
1336         const int proxyFirstRow = result.key();
1337         const QModelIndex sourceFirstChild = result.value();
1338         Q_ASSERT(proxyFirstRow >= 0);
1339         Q_ASSERT(sourceFirstChild.isValid());
1340         Q_ASSERT(sourceFirstChild.parent().isValid());
1341         Q_ASSERT(row <= proxyFirstRow + sourceFirstChild.model()->rowCount(sourceFirstChild.parent()));
1342     }
1343     return true;
1344 }
1345 
1346 QModelIndex KSelectionProxyModelPrivate::createTopLevelIndex(int row, int column) const
1347 {
1348     Q_Q(const KSelectionProxyModel);
1349 
1350     Q_ASSERT(indexIsValid(m_startWithChildTrees, row, m_rootIndexList, m_mappedFirstChildren));
1351     return q->createIndex(row, column);
1352 }
1353 
1354 QModelIndex KSelectionProxyModelPrivate::mapTopLevelFromSource(const QModelIndex &sourceIndex) const
1355 {
1356     Q_Q(const KSelectionProxyModel);
1357 
1358     const QModelIndex sourceParent = sourceIndex.parent();
1359     const int row = m_rootIndexList.indexOf(sourceIndex);
1360     if (row == -1) {
1361         return QModelIndex();
1362     }
1363 
1364     if (!m_startWithChildTrees) {
1365         Q_ASSERT(m_rootIndexList.size() > row);
1366         return q->createIndex(row, sourceIndex.column());
1367     }
1368     if (!m_rootIndexList.contains(sourceParent)) {
1369         return QModelIndex();
1370     }
1371 
1372     const QModelIndex firstChild = q->sourceModel()->index(0, 0, sourceParent);
1373     const int firstProxyRow = m_mappedFirstChildren.leftToRight(firstChild);
1374 
1375     return q->createIndex(firstProxyRow + sourceIndex.row(), sourceIndex.column());
1376 }
1377 
1378 QModelIndex KSelectionProxyModelPrivate::mapFromSource(const QModelIndex &sourceIndex) const
1379 {
1380     Q_Q(const KSelectionProxyModel);
1381 
1382     const QModelIndex maybeMapped = mapParentFromSource(sourceIndex);
1383     if (maybeMapped.isValid()) {
1384         //     Q_ASSERT((!d->m_startWithChildTrees && d->m_rootIndexList.contains(maybeMapped)) ? maybeMapped.row() < 0 : true );
1385         return maybeMapped;
1386     }
1387     const QModelIndex sourceParent = sourceIndex.parent();
1388 
1389     const QModelIndex proxyParent = mapParentFromSource(sourceParent);
1390     if (proxyParent.isValid()) {
1391         void *const parentId = m_parentIds.rightToLeft(proxyParent);
1392         static const int column = 0;
1393         return q->createIndex(sourceIndex.row(), column, parentId);
1394     }
1395 
1396     const QModelIndex firstChild = q->sourceModel()->index(0, 0, sourceParent);
1397 
1398     if (m_mappedFirstChildren.leftContains(firstChild)) {
1399         const int firstProxyRow = m_mappedFirstChildren.leftToRight(firstChild);
1400         return q->createIndex(firstProxyRow + sourceIndex.row(), sourceIndex.column());
1401     }
1402     return mapTopLevelFromSource(sourceIndex);
1403 }
1404 
1405 int KSelectionProxyModelPrivate::topLevelRowCount() const
1406 {
1407     Q_Q(const KSelectionProxyModel);
1408 
1409     if (!m_startWithChildTrees) {
1410         return m_rootIndexList.size();
1411     }
1412 
1413     if (m_mappedFirstChildren.isEmpty()) {
1414         return 0;
1415     }
1416 
1417     const SourceIndexProxyRowMapping::right_const_iterator result = m_mappedFirstChildren.rightConstEnd() - 1;
1418 
1419     const int proxyFirstRow = result.key();
1420     const QModelIndex sourceFirstChild = result.value();
1421     Q_ASSERT(sourceFirstChild.isValid());
1422     const QModelIndex sourceParent = sourceFirstChild.parent();
1423     Q_ASSERT(sourceParent.isValid());
1424     return q->sourceModel()->rowCount(sourceParent) + proxyFirstRow;
1425 }
1426 
1427 bool KSelectionProxyModelPrivate::ensureMappable(const QModelIndex &parent) const
1428 {
1429     Q_Q(const KSelectionProxyModel);
1430 
1431     if (isFlat()) {
1432         return true;
1433     }
1434 
1435     if (parentIsMappable(parent)) {
1436         return true;
1437     }
1438 
1439     QModelIndex ancestor = parent.parent();
1440     QModelIndexList ancestorList;
1441     while (ancestor.isValid()) {
1442         if (parentIsMappable(ancestor)) {
1443             break;
1444         } else {
1445             ancestorList.prepend(ancestor);
1446         }
1447 
1448         ancestor = ancestor.parent();
1449     }
1450 
1451     if (!ancestor.isValid())
1452     // @p parent is not a descendant of m_rootIndexList.
1453     {
1454         return false;
1455     }
1456 
1457     // sourceIndex can be mapped to the proxy. We just need to create mappings for its ancestors first.
1458     for (int i = 0; i < ancestorList.size(); ++i) {
1459         const QModelIndex existingAncestor = mapParentFromSource(ancestor);
1460         Q_ASSERT(existingAncestor.isValid());
1461 
1462         void *const ansId = m_parentIds.rightToLeft(existingAncestor);
1463         const QModelIndex newSourceParent = ancestorList.at(i);
1464         const QModelIndex newProxyParent = q->createIndex(newSourceParent.row(), newSourceParent.column(), ansId);
1465 
1466         void *const newId = m_voidPointerFactory.createPointer();
1467         m_parentIds.insert(newId, newProxyParent);
1468         m_mappedParents.insert(QPersistentModelIndex(newSourceParent), newProxyParent);
1469         ancestor = newSourceParent;
1470     }
1471     return true;
1472 }
1473 
1474 void KSelectionProxyModelPrivate::updateInternalTopIndexes(int start, int offset)
1475 {
1476     updateInternalIndexes(QModelIndex(), start, offset);
1477 
1478     QHash<QPersistentModelIndex, int> updates;
1479     {
1480         SourceIndexProxyRowMapping::right_iterator it = m_mappedFirstChildren.rightLowerBound(start);
1481         const SourceIndexProxyRowMapping::right_iterator end = m_mappedFirstChildren.rightEnd();
1482 
1483         for (; it != end; ++it) {
1484             updates.insert(*it, it.key() + offset);
1485         }
1486     }
1487     {
1488         QHash<QPersistentModelIndex, int>::const_iterator it = updates.constBegin();
1489         const QHash<QPersistentModelIndex, int>::const_iterator end = updates.constEnd();
1490 
1491         for (; it != end; ++it) {
1492             m_mappedFirstChildren.insert(it.key(), it.value());
1493         }
1494     }
1495 }
1496 
1497 void KSelectionProxyModelPrivate::updateInternalIndexes(const QModelIndex &parent, int start, int offset)
1498 {
1499     Q_Q(KSelectionProxyModel);
1500 
1501     Q_ASSERT(start + offset >= 0);
1502     Q_ASSERT(parent.isValid() ? parent.model() == q : true);
1503 
1504     if (isFlat()) {
1505         return;
1506     }
1507 
1508     SourceProxyIndexMapping::left_iterator mappedParentIt = m_mappedParents.leftBegin();
1509 
1510     QHash<void *, QModelIndex> updatedParentIds;
1511     QHash<QPersistentModelIndex, QModelIndex> updatedParents;
1512 
1513     for (; mappedParentIt != m_mappedParents.leftEnd(); ++mappedParentIt) {
1514         const QModelIndex proxyIndex = mappedParentIt.value();
1515         Q_ASSERT(proxyIndex.isValid());
1516 
1517         if (proxyIndex.row() < start) {
1518             continue;
1519         }
1520 
1521         const QModelIndex proxyParent = proxyIndex.parent();
1522 
1523         if (parent.isValid()) {
1524             if (proxyParent != parent) {
1525                 continue;
1526             }
1527         } else {
1528             if (proxyParent.isValid()) {
1529                 continue;
1530             }
1531         }
1532         Q_ASSERT(m_parentIds.rightContains(proxyIndex));
1533         void *const key = m_parentIds.rightToLeft(proxyIndex);
1534 
1535         const QModelIndex newIndex = q->createIndex(proxyIndex.row() + offset, proxyIndex.column(), proxyIndex.internalPointer());
1536 
1537         Q_ASSERT(newIndex.isValid());
1538 
1539         updatedParentIds.insert(key, newIndex);
1540         updatedParents.insert(mappedParentIt.key(), newIndex);
1541     }
1542 
1543     {
1544         QHash<QPersistentModelIndex, QModelIndex>::const_iterator it = updatedParents.constBegin();
1545         const QHash<QPersistentModelIndex, QModelIndex>::const_iterator end = updatedParents.constEnd();
1546         for (; it != end; ++it) {
1547             m_mappedParents.insert(it.key(), it.value());
1548         }
1549     }
1550 
1551     {
1552         QHash<void *, QModelIndex>::const_iterator it = updatedParentIds.constBegin();
1553         const QHash<void *, QModelIndex>::const_iterator end = updatedParentIds.constEnd();
1554         for (; it != end; ++it) {
1555             m_parentIds.insert(it.key(), it.value());
1556         }
1557     }
1558 }
1559 
1560 bool KSelectionProxyModelPrivate::parentAlreadyMapped(const QModelIndex &parent) const
1561 {
1562     Q_Q(const KSelectionProxyModel);
1563     Q_UNUSED(q) // except in Q_ASSERT
1564     Q_ASSERT(parent.model() == q->sourceModel());
1565     return m_mappedParents.leftContains(parent);
1566 }
1567 
1568 bool KSelectionProxyModelPrivate::firstChildAlreadyMapped(const QModelIndex &firstChild) const
1569 {
1570     Q_Q(const KSelectionProxyModel);
1571     Q_UNUSED(q) // except in Q_ASSERT
1572     Q_ASSERT(firstChild.model() == q->sourceModel());
1573     return m_mappedFirstChildren.leftContains(firstChild);
1574 }
1575 
1576 void KSelectionProxyModelPrivate::createFirstChildMapping(const QModelIndex &parent, int proxyRow) const
1577 {
1578     Q_Q(const KSelectionProxyModel);
1579 
1580     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
1581 
1582     static const int column = 0;
1583     static const int row = 0;
1584 
1585     const QPersistentModelIndex srcIndex = q->sourceModel()->index(row, column, parent);
1586 
1587     if (firstChildAlreadyMapped(srcIndex)) {
1588         return;
1589     }
1590 
1591     Q_ASSERT(srcIndex.isValid());
1592     m_mappedFirstChildren.insert(srcIndex, proxyRow);
1593 }
1594 
1595 void KSelectionProxyModelPrivate::createParentMappings(const QModelIndex &parent, int start, int end) const
1596 {
1597     if (isFlat()) {
1598         return;
1599     }
1600 
1601     Q_Q(const KSelectionProxyModel);
1602 
1603     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
1604 
1605     static const int column = 0;
1606 
1607     for (int row = start; row <= end; ++row) {
1608         const QModelIndex srcIndex = q->sourceModel()->index(row, column, parent);
1609         Q_ASSERT(srcIndex.isValid());
1610         if (!q->sourceModel()->hasChildren(srcIndex) || parentAlreadyMapped(srcIndex)) {
1611             continue;
1612         }
1613 
1614         const QModelIndex proxyIndex = mapFromSource(srcIndex);
1615         if (!proxyIndex.isValid()) {
1616             return; // If one of them is not mapped, its siblings won't be either
1617         }
1618 
1619         void *const newId = m_voidPointerFactory.createPointer();
1620         m_parentIds.insert(newId, proxyIndex);
1621         Q_ASSERT(srcIndex.isValid());
1622         m_mappedParents.insert(QPersistentModelIndex(srcIndex), proxyIndex);
1623     }
1624 }
1625 
1626 void KSelectionProxyModelPrivate::removeFirstChildMappings(int start, int end)
1627 {
1628     SourceIndexProxyRowMapping::right_iterator it = m_mappedFirstChildren.rightLowerBound(start);
1629     const SourceIndexProxyRowMapping::right_iterator endIt = m_mappedFirstChildren.rightUpperBound(end);
1630     while (it != endIt) {
1631         it = m_mappedFirstChildren.eraseRight(it);
1632     }
1633 }
1634 
1635 void KSelectionProxyModelPrivate::removeParentMappings(const QModelIndex &parent, int start, int end)
1636 {
1637     Q_Q(KSelectionProxyModel);
1638 
1639     Q_ASSERT(parent.isValid() ? parent.model() == q : true);
1640 
1641     // collect all removals first, as executing them recursively will invalidate our iterators
1642     struct RemovalInfo {
1643         QPersistentModelIndex idx;
1644         QModelIndex sourceIdx;
1645     };
1646     std::vector<RemovalInfo> removals;
1647     removals.reserve(end - start + 1);
1648     for (auto it = m_mappedParents.rightBegin(); it != m_mappedParents.rightEnd(); ++it) {
1649         if (it.key().row() >= start && it.key().row() <= end) {
1650             const QModelIndex sourceParent = it.value();
1651             const QModelIndex proxyGrandParent = mapParentFromSource(sourceParent.parent());
1652             if (proxyGrandParent == parent) {
1653                 removals.push_back({it.key(), it.value()});
1654             }
1655         }
1656     }
1657 
1658     // execute the removals
1659     const bool flatList = isFlat();
1660     for (const auto &r : removals) {
1661         if (!flatList) {
1662             removeParentMappings(r.idx, 0, q->sourceModel()->rowCount(r.sourceIdx) - 1);
1663         }
1664         m_parentIds.removeRight(r.idx);
1665         m_mappedParents.removeRight(r.idx);
1666     }
1667 }
1668 
1669 QModelIndex KSelectionProxyModelPrivate::mapTopLevelToSource(int row, int column) const
1670 {
1671     if (!m_startWithChildTrees) {
1672         const QModelIndex idx = m_rootIndexList.at(row);
1673         return idx.sibling(idx.row(), column);
1674     }
1675 
1676     if (m_mappedFirstChildren.isEmpty()) {
1677         return QModelIndex();
1678     }
1679 
1680     SourceIndexProxyRowMapping::right_iterator result = m_mappedFirstChildren.rightUpperBound(row) - 1;
1681 
1682     Q_ASSERT(result != m_mappedFirstChildren.rightEnd());
1683 
1684     const int proxyFirstRow = result.key();
1685     const QModelIndex sourceFirstChild = result.value();
1686     Q_ASSERT(sourceFirstChild.isValid());
1687     return sourceFirstChild.sibling(row - proxyFirstRow, column);
1688 }
1689 
1690 void KSelectionProxyModelPrivate::removeSelectionFromProxy(const QItemSelection &selection)
1691 {
1692     Q_Q(KSelectionProxyModel);
1693     if (selection.isEmpty()) {
1694         return;
1695     }
1696 
1697     QList<QPersistentModelIndex>::iterator rootIt = m_rootIndexList.begin();
1698     const QList<QPersistentModelIndex>::iterator rootEnd = m_rootIndexList.end();
1699     int proxyStartRemove = 0;
1700 
1701     for (; rootIt != rootEnd; ++rootIt) {
1702         if (rootWillBeRemoved(selection, *rootIt)) {
1703             break;
1704         } else {
1705             if (m_startWithChildTrees) {
1706                 auto rc = q->sourceModel()->rowCount(*rootIt);
1707                 proxyStartRemove += rc;
1708             } else {
1709                 ++proxyStartRemove;
1710             }
1711         }
1712     }
1713 
1714     if (rootIt == rootEnd) {
1715         return;
1716     }
1717 
1718     int proxyEndRemove = proxyStartRemove;
1719 
1720     QList<QPersistentModelIndex>::iterator rootRemoveStart = rootIt;
1721 
1722     for (; rootIt != rootEnd; ++rootIt) {
1723         if (!rootWillBeRemoved(selection, *rootIt)) {
1724             break;
1725         }
1726         q->rootIndexAboutToBeRemoved(*rootIt, KSelectionProxyModel::QPrivateSignal());
1727         if (m_startWithChildTrees) {
1728             auto rc = q->sourceModel()->rowCount(*rootIt);
1729             proxyEndRemove += rc;
1730         } else {
1731             ++proxyEndRemove;
1732         }
1733     }
1734 
1735     --proxyEndRemove;
1736     if (proxyEndRemove >= proxyStartRemove) {
1737         q->beginRemoveRows(QModelIndex(), proxyStartRemove, proxyEndRemove);
1738 
1739         rootIt = m_rootIndexList.erase(rootRemoveStart, rootIt);
1740 
1741         removeParentMappings(QModelIndex(), proxyStartRemove, proxyEndRemove);
1742         if (m_startWithChildTrees) {
1743             removeFirstChildMappings(proxyStartRemove, proxyEndRemove);
1744         }
1745         updateInternalTopIndexes(proxyEndRemove + 1, -1 * (proxyEndRemove - proxyStartRemove + 1));
1746 
1747         q->endRemoveRows();
1748     } else {
1749         rootIt = m_rootIndexList.erase(rootRemoveStart, rootIt);
1750     }
1751     if (rootIt != rootEnd) {
1752         removeSelectionFromProxy(selection);
1753     }
1754 }
1755 
1756 void KSelectionProxyModelPrivate::selectionChanged(const QItemSelection &_selected, const QItemSelection &_deselected)
1757 {
1758     Q_Q(KSelectionProxyModel);
1759 
1760     if (!q->sourceModel() || (_selected.isEmpty() && _deselected.isEmpty())) {
1761         return;
1762     }
1763 
1764     if (m_sourceModelResetting) {
1765         return;
1766     }
1767 
1768     if (m_rowsInserted || m_rowsRemoved) {
1769         m_pendingSelectionChanges.append(PendingSelectionChange(_selected, _deselected));
1770         return;
1771     }
1772 
1773     // Any deselected indexes in the m_rootIndexList are removed. Then, any
1774     // indexes in the selected range which are not a descendant of one of the already selected indexes
1775     // are inserted into the model.
1776     //
1777     // All ranges from the selection model need to be split into individual rows. Ranges which are contiguous in
1778     // the selection model may not be contiguous in the source model if there's a sort filter proxy model in the chain.
1779     //
1780     // Some descendants of deselected indexes may still be selected. The ranges in m_selectionModel->selection()
1781     // are examined. If any of the ranges are descendants of one of the
1782     // indexes in deselected, they are added to the ranges to be inserted into the model.
1783     //
1784     // The new indexes are inserted in sorted order.
1785 
1786     const QItemSelection selected = kNormalizeSelection(m_indexMapper->mapSelectionRightToLeft(_selected));
1787     const QItemSelection deselected = kNormalizeSelection(m_indexMapper->mapSelectionRightToLeft(_deselected));
1788 
1789 #if QT_VERSION < 0x040800
1790     // The QItemSelectionModel sometimes doesn't remove deselected items from its selection
1791     // Fixed in Qt 4.8 : http://qt.gitorious.org/qt/qt/merge_requests/2403
1792     QItemSelection reportedSelection = m_selectionModel->selection();
1793     reportedSelection.merge(deselected, QItemSelectionModel::Deselect);
1794     QItemSelection fullSelection = m_indexMapper->mapSelectionRightToLeft(reportedSelection);
1795 #else
1796     QItemSelection fullSelection = m_indexMapper->mapSelectionRightToLeft(m_selectionModel->selection());
1797 #endif
1798 
1799     fullSelection = kNormalizeSelection(fullSelection);
1800 
1801     QItemSelection newRootRanges;
1802     QItemSelection removedRootRanges;
1803     if (!m_includeAllSelected) {
1804         newRootRanges = getRootRanges(selected);
1805 
1806         QItemSelection existingSelection = fullSelection;
1807         // What was selected before the selection was made.
1808         existingSelection.merge(selected, QItemSelectionModel::Deselect);
1809 
1810         // This is similar to m_rootRanges, but that m_rootRanges at this point still contains the roots
1811         // of deselected and existingRootRanges does not.
1812 
1813         const QItemSelection existingRootRanges = getRootRanges(existingSelection);
1814         {
1815             QMutableListIterator<QItemSelectionRange> i(newRootRanges);
1816             while (i.hasNext()) {
1817                 const QItemSelectionRange range = i.next();
1818                 const QModelIndex topLeft = range.topLeft();
1819                 if (isDescendantOf(existingRootRanges, topLeft)) {
1820                     i.remove();
1821                 }
1822             }
1823         }
1824 
1825         QItemSelection exposedSelection;
1826         {
1827             QItemSelection deselectedRootRanges = getRootRanges(deselected);
1828             QListIterator<QItemSelectionRange> i(deselectedRootRanges);
1829             while (i.hasNext()) {
1830                 const QItemSelectionRange range = i.next();
1831                 const QModelIndex topLeft = range.topLeft();
1832                 // Consider this:
1833                 //
1834                 // - A
1835                 // - - B
1836                 // - - - C
1837                 // - - - - D
1838                 //
1839                 // B and D were selected, then B was deselected and C was selected in one go.
1840                 if (!isDescendantOf(existingRootRanges, topLeft)) {
1841                     // B is topLeft and fullSelection contains D.
1842                     // B is not a descendant of D.
1843 
1844                     // range is not a descendant of the selection, but maybe the selection is a descendant of range.
1845                     // no need to check selected here. That's already in newRootRanges.
1846                     // existingRootRanges and newRootRanges do not overlap.
1847                     for (const QItemSelectionRange &selectedRange : existingRootRanges) {
1848                         const QModelIndex selectedRangeTopLeft = selectedRange.topLeft();
1849                         // existingSelection (and selectedRangeTopLeft) is D.
1850                         // D is a descendant of B, so when B was removed, D might have been exposed as a root.
1851                         if (isDescendantOf(range, selectedRangeTopLeft)
1852                             // But D is also a descendant of part of the new selection C, which is already set to be a new root
1853                             // so D would not be added to exposedSelection because C is in newRootRanges.
1854                             && !isDescendantOf(newRootRanges, selectedRangeTopLeft)) {
1855                             exposedSelection.append(selectedRange);
1856                         }
1857                     }
1858                     removedRootRanges << range;
1859                 }
1860             }
1861         }
1862 
1863         QItemSelection obscuredRanges;
1864         {
1865             QListIterator<QItemSelectionRange> i(existingRootRanges);
1866             while (i.hasNext()) {
1867                 const QItemSelectionRange range = i.next();
1868                 if (isDescendantOf(newRootRanges, range.topLeft())) {
1869                     obscuredRanges << range;
1870                 }
1871             }
1872         }
1873         removedRootRanges << getRootRanges(obscuredRanges);
1874         newRootRanges << getRootRanges(exposedSelection);
1875 
1876         removedRootRanges = kNormalizeSelection(removedRootRanges);
1877         newRootRanges = kNormalizeSelection(newRootRanges);
1878     } else {
1879         removedRootRanges = deselected;
1880         newRootRanges = selected;
1881     }
1882 
1883     removeSelectionFromProxy(removedRootRanges);
1884 
1885     if (!m_selectionModel->hasSelection()) {
1886         Q_ASSERT(m_rootIndexList.isEmpty());
1887         Q_ASSERT(m_mappedFirstChildren.isEmpty());
1888         Q_ASSERT(m_mappedParents.isEmpty());
1889         Q_ASSERT(m_parentIds.isEmpty());
1890     }
1891 
1892     insertSelectionIntoProxy(newRootRanges);
1893 }
1894 
1895 int KSelectionProxyModelPrivate::getTargetRow(int rootListRow)
1896 {
1897     Q_Q(KSelectionProxyModel);
1898     if (!m_startWithChildTrees) {
1899         return rootListRow;
1900     }
1901 
1902     --rootListRow;
1903     while (rootListRow >= 0) {
1904         const QModelIndex idx = m_rootIndexList.at(rootListRow);
1905         Q_ASSERT(idx.isValid());
1906         const int rowCount = q->sourceModel()->rowCount(idx);
1907         if (rowCount > 0) {
1908             static const int column = 0;
1909             const QModelIndex srcIdx = q->sourceModel()->index(rowCount - 1, column, idx);
1910             const QModelIndex proxyLastChild = mapFromSource(srcIdx);
1911             return proxyLastChild.row() + 1;
1912         }
1913         --rootListRow;
1914     }
1915     return 0;
1916 }
1917 
1918 void KSelectionProxyModelPrivate::insertSelectionIntoProxy(const QItemSelection &selection)
1919 {
1920     Q_Q(KSelectionProxyModel);
1921 
1922     if (selection.isEmpty()) {
1923         return;
1924     }
1925 
1926     const auto lst = selection.indexes();
1927     for (const QModelIndex &newIndex : lst) {
1928         Q_ASSERT(newIndex.model() == q->sourceModel());
1929         if (newIndex.column() > 0) {
1930             continue;
1931         }
1932         if (m_startWithChildTrees) {
1933             const int rootListRow = getRootListRow(m_rootIndexList, newIndex);
1934             Q_ASSERT(q->sourceModel() == newIndex.model());
1935             const int rowCount = q->sourceModel()->rowCount(newIndex);
1936             const int startRow = getTargetRow(rootListRow);
1937 
1938             if (rowCount == 0) {
1939                 // Even if the newindex doesn't have any children to put into the model yet,
1940                 // We still need to make sure its future children are inserted into the model.
1941                 m_rootIndexList.insert(rootListRow, newIndex);
1942                 if (!m_resetting || m_layoutChanging) {
1943                     Q_EMIT q->rootIndexAdded(newIndex, KSelectionProxyModel::QPrivateSignal());
1944                 }
1945                 continue;
1946             }
1947             if (!m_resetting) {
1948                 q->beginInsertRows(QModelIndex(), startRow, startRow + rowCount - 1);
1949             }
1950             Q_ASSERT(newIndex.isValid());
1951             m_rootIndexList.insert(rootListRow, newIndex);
1952             if (!m_resetting || m_layoutChanging) {
1953                 Q_EMIT q->rootIndexAdded(newIndex, KSelectionProxyModel::QPrivateSignal());
1954             }
1955 
1956             int _start = 0;
1957             for (int i = 0; i < rootListRow; ++i) {
1958                 _start += q->sourceModel()->rowCount(m_rootIndexList.at(i));
1959             }
1960 
1961             updateInternalTopIndexes(_start, rowCount);
1962             createFirstChildMapping(newIndex, _start);
1963             createParentMappings(newIndex, 0, rowCount - 1);
1964 
1965             if (!m_resetting) {
1966                 q->endInsertRows();
1967             }
1968 
1969         } else {
1970             const int row = getRootListRow(m_rootIndexList, newIndex);
1971             if (!m_resetting) {
1972                 q->beginInsertRows(QModelIndex(), row, row);
1973             }
1974 
1975             Q_ASSERT(newIndex.isValid());
1976             m_rootIndexList.insert(row, newIndex);
1977 
1978             if (!m_resetting || m_layoutChanging) {
1979                 Q_EMIT q->rootIndexAdded(newIndex, KSelectionProxyModel::QPrivateSignal());
1980             }
1981             Q_ASSERT(m_rootIndexList.size() > row);
1982             updateInternalIndexes(QModelIndex(), row, 1);
1983             createParentMappings(newIndex.parent(), newIndex.row(), newIndex.row());
1984 
1985             if (!m_resetting) {
1986                 q->endInsertRows();
1987             }
1988         }
1989     }
1990     Q_EMIT q->rootSelectionAdded(selection, KSelectionProxyModel::QPrivateSignal());
1991 }
1992 
1993 KSelectionProxyModel::KSelectionProxyModel(QItemSelectionModel *selectionModel, QObject *parent)
1994     : QAbstractProxyModel(parent)
1995     , d_ptr(new KSelectionProxyModelPrivate(this))
1996 {
1997     setSelectionModel(selectionModel);
1998 }
1999 
2000 KSelectionProxyModel::KSelectionProxyModel()
2001     : QAbstractProxyModel(nullptr)
2002     , d_ptr(new KSelectionProxyModelPrivate(this))
2003 {
2004 }
2005 
2006 KSelectionProxyModel::~KSelectionProxyModel() = default;
2007 
2008 void KSelectionProxyModel::setFilterBehavior(FilterBehavior behavior)
2009 {
2010     Q_D(KSelectionProxyModel);
2011 
2012     Q_ASSERT(behavior != InvalidBehavior);
2013     if (behavior == InvalidBehavior) {
2014         return;
2015     }
2016     if (d->m_filterBehavior != behavior) {
2017         beginResetModel();
2018 
2019         d->m_filterBehavior = behavior;
2020 
2021         switch (behavior) {
2022         case InvalidBehavior: {
2023             Q_ASSERT(!"InvalidBehavior can't be used here");
2024             return;
2025         }
2026         case SubTrees: {
2027             d->m_omitChildren = false;
2028             d->m_omitDescendants = false;
2029             d->m_startWithChildTrees = false;
2030             d->m_includeAllSelected = false;
2031             break;
2032         }
2033         case SubTreeRoots: {
2034             d->m_omitChildren = true;
2035             d->m_startWithChildTrees = false;
2036             d->m_includeAllSelected = false;
2037             break;
2038         }
2039         case SubTreesWithoutRoots: {
2040             d->m_omitChildren = false;
2041             d->m_omitDescendants = false;
2042             d->m_startWithChildTrees = true;
2043             d->m_includeAllSelected = false;
2044             break;
2045         }
2046         case ExactSelection: {
2047             d->m_omitChildren = true;
2048             d->m_startWithChildTrees = false;
2049             d->m_includeAllSelected = true;
2050             break;
2051         }
2052         case ChildrenOfExactSelection: {
2053             d->m_omitChildren = false;
2054             d->m_omitDescendants = true;
2055             d->m_startWithChildTrees = true;
2056             d->m_includeAllSelected = true;
2057             break;
2058         }
2059         }
2060         Q_EMIT filterBehaviorChanged(QPrivateSignal());
2061         d->resetInternalData();
2062         if (d->m_selectionModel) {
2063             d->selectionChanged(d->m_selectionModel->selection(), QItemSelection());
2064         }
2065 
2066         endResetModel();
2067     }
2068 }
2069 
2070 KSelectionProxyModel::FilterBehavior KSelectionProxyModel::filterBehavior() const
2071 {
2072     Q_D(const KSelectionProxyModel);
2073     return d->m_filterBehavior;
2074 }
2075 
2076 void KSelectionProxyModel::setSourceModel(QAbstractItemModel *_sourceModel)
2077 {
2078     Q_D(KSelectionProxyModel);
2079 
2080     Q_ASSERT(_sourceModel != this);
2081 
2082     if (_sourceModel == sourceModel()) {
2083         return;
2084     }
2085 
2086     beginResetModel();
2087     d->m_resetting = true;
2088 
2089     if (auto *oldSourceModel = sourceModel()) {
2090         disconnect(oldSourceModel, nullptr, this, nullptr);
2091     }
2092 
2093     // Must be called before QAbstractProxyModel::setSourceModel because it emit some signals.
2094     d->resetInternalData();
2095     QAbstractProxyModel::setSourceModel(_sourceModel);
2096     if (_sourceModel) {
2097         if (d->m_selectionModel) {
2098             delete d->m_indexMapper;
2099             d->m_indexMapper = new KModelIndexProxyMapper(_sourceModel, d->m_selectionModel->model(), this);
2100             if (d->m_selectionModel->hasSelection()) {
2101                 d->selectionChanged(d->m_selectionModel->selection(), QItemSelection());
2102             }
2103         }
2104 
2105         connect(_sourceModel, &QAbstractItemModel::rowsAboutToBeInserted, this, [d](const QModelIndex &parent, int start, int end) {
2106             d->sourceRowsAboutToBeInserted(parent, start, end);
2107         });
2108 
2109         connect(_sourceModel, &QAbstractItemModel::rowsInserted, this, [d](const QModelIndex &parent, int start, int end) {
2110             d->sourceRowsInserted(parent, start, end);
2111         });
2112 
2113         connect(_sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, [d](const QModelIndex &parent, int start, int end) {
2114             d->sourceRowsAboutToBeRemoved(parent, start, end);
2115         });
2116 
2117         connect(_sourceModel, &QAbstractItemModel::rowsRemoved, this, [d](const QModelIndex &parent, int start, int end) {
2118             d->sourceRowsRemoved(parent, start, end);
2119         });
2120 
2121         connect(_sourceModel,
2122                 &QAbstractItemModel::rowsAboutToBeMoved,
2123                 this,
2124                 [d](const QModelIndex &parent, int start, int end, const QModelIndex &destParent, int destRow) {
2125                     d->sourceRowsAboutToBeMoved(parent, start, end, destParent, destRow);
2126                 });
2127 
2128         connect(_sourceModel,
2129                 &QAbstractItemModel::rowsMoved,
2130                 this,
2131                 [d](const QModelIndex &parent, int start, int end, const QModelIndex &destParent, int destRow) {
2132                     d->sourceRowsMoved(parent, start, end, destParent, destRow);
2133                 });
2134 
2135         connect(_sourceModel, &QAbstractItemModel::modelAboutToBeReset, this, [d]() {
2136             d->sourceModelAboutToBeReset();
2137         });
2138 
2139         connect(_sourceModel, &QAbstractItemModel::modelReset, this, [d]() {
2140             d->sourceModelReset();
2141         });
2142 
2143         connect(_sourceModel, &QAbstractItemModel::dataChanged, this, [d](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
2144             d->sourceDataChanged(topLeft, bottomRight);
2145         });
2146 
2147         connect(_sourceModel, &QAbstractItemModel::layoutAboutToBeChanged, this, [d]() {
2148             d->sourceLayoutAboutToBeChanged();
2149         });
2150 
2151         connect(_sourceModel, &QAbstractItemModel::layoutChanged, this, [d]() {
2152             d->sourceLayoutChanged();
2153         });
2154 
2155         connect(_sourceModel, &QObject::destroyed, this, [d]() {
2156             d->sourceModelDestroyed();
2157         });
2158     }
2159 
2160     d->m_resetting = false;
2161     endResetModel();
2162 }
2163 
2164 QModelIndex KSelectionProxyModel::mapToSource(const QModelIndex &proxyIndex) const
2165 {
2166     Q_D(const KSelectionProxyModel);
2167 
2168     if (!proxyIndex.isValid() || !sourceModel() || d->m_rootIndexList.isEmpty()) {
2169         return QModelIndex();
2170     }
2171 
2172     Q_ASSERT(proxyIndex.model() == this);
2173 
2174     if (proxyIndex.internalPointer() == nullptr) {
2175         return d->mapTopLevelToSource(proxyIndex.row(), proxyIndex.column());
2176     }
2177 
2178     const QModelIndex proxyParent = d->parentForId(proxyIndex.internalPointer());
2179     Q_ASSERT(proxyParent.isValid());
2180     const QModelIndex sourceParent = d->mapParentToSource(proxyParent);
2181     Q_ASSERT(sourceParent.isValid());
2182     return sourceModel()->index(proxyIndex.row(), proxyIndex.column(), sourceParent);
2183 }
2184 
2185 QModelIndex KSelectionProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
2186 {
2187     Q_D(const KSelectionProxyModel);
2188 
2189     if (!sourceModel() || !sourceIndex.isValid() || d->m_rootIndexList.isEmpty()) {
2190         return QModelIndex();
2191     }
2192 
2193     Q_ASSERT(sourceIndex.model() == sourceModel());
2194 
2195     if (!sourceIndex.isValid()) {
2196         return QModelIndex();
2197     }
2198 
2199     if (!d->ensureMappable(sourceIndex)) {
2200         return QModelIndex();
2201     }
2202 
2203     return d->mapFromSource(sourceIndex);
2204 }
2205 
2206 int KSelectionProxyModel::rowCount(const QModelIndex &index) const
2207 {
2208     Q_D(const KSelectionProxyModel);
2209 
2210     if (!sourceModel() || index.column() > 0 || d->m_rootIndexList.isEmpty()) {
2211         return 0;
2212     }
2213 
2214     Q_ASSERT(index.isValid() ? index.model() == this : true);
2215     if (!index.isValid()) {
2216         return d->topLevelRowCount();
2217     }
2218 
2219     // index is valid
2220     if (d->isFlat()) {
2221         return 0;
2222     }
2223 
2224     QModelIndex sourceParent = d->mapParentToSource(index);
2225 
2226     if (!sourceParent.isValid() && sourceModel()->hasChildren(sourceParent)) {
2227         sourceParent = mapToSource(index.parent());
2228         d->createParentMappings(sourceParent, 0, sourceModel()->rowCount(sourceParent) - 1);
2229         sourceParent = d->mapParentToSource(index);
2230     }
2231 
2232     if (!sourceParent.isValid()) {
2233         return 0;
2234     }
2235 
2236     return sourceModel()->rowCount(sourceParent);
2237 }
2238 
2239 QModelIndex KSelectionProxyModel::index(int row, int column, const QModelIndex &parent) const
2240 {
2241     Q_D(const KSelectionProxyModel);
2242 
2243     if (!sourceModel() || d->m_rootIndexList.isEmpty() || !hasIndex(row, column, parent)) {
2244         return QModelIndex();
2245     }
2246 
2247     Q_ASSERT(parent.isValid() ? parent.model() == this : true);
2248 
2249     if (!parent.isValid()) {
2250         return d->createTopLevelIndex(row, column);
2251     }
2252 
2253     void *const parentId = d->parentId(parent);
2254     Q_ASSERT(parentId);
2255     return createIndex(row, column, parentId);
2256 }
2257 
2258 QModelIndex KSelectionProxyModel::parent(const QModelIndex &index) const
2259 {
2260     Q_D(const KSelectionProxyModel);
2261 
2262     if (!sourceModel() || !index.isValid() || d->m_rootIndexList.isEmpty()) {
2263         return QModelIndex();
2264     }
2265 
2266     Q_ASSERT(index.model() == this);
2267 
2268     return d->parentForId(index.internalPointer());
2269 }
2270 
2271 Qt::ItemFlags KSelectionProxyModel::flags(const QModelIndex &index) const
2272 {
2273     if (!index.isValid() || !sourceModel()) {
2274         return QAbstractProxyModel::flags(index);
2275     }
2276 
2277     Q_ASSERT(index.model() == this);
2278 
2279     const QModelIndex srcIndex = mapToSource(index);
2280     Q_ASSERT(srcIndex.isValid());
2281     return sourceModel()->flags(srcIndex);
2282 }
2283 
2284 QVariant KSelectionProxyModel::data(const QModelIndex &index, int role) const
2285 {
2286     if (!sourceModel()) {
2287         return QVariant();
2288     }
2289 
2290     if (index.isValid()) {
2291         Q_ASSERT(index.model() == this);
2292         const QModelIndex idx = mapToSource(index);
2293         return idx.data(role);
2294     }
2295     return sourceModel()->data(index, role);
2296 }
2297 
2298 QVariant KSelectionProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
2299 {
2300     if (!sourceModel()) {
2301         return QVariant();
2302     }
2303     return sourceModel()->headerData(section, orientation, role);
2304 }
2305 
2306 QMimeData *KSelectionProxyModel::mimeData(const QModelIndexList &indexes) const
2307 {
2308     if (!sourceModel()) {
2309         return QAbstractProxyModel::mimeData(indexes);
2310     }
2311     QModelIndexList sourceIndexes;
2312     for (const QModelIndex &index : indexes) {
2313         sourceIndexes << mapToSource(index);
2314     }
2315     return sourceModel()->mimeData(sourceIndexes);
2316 }
2317 
2318 QStringList KSelectionProxyModel::mimeTypes() const
2319 {
2320     if (!sourceModel()) {
2321         return QAbstractProxyModel::mimeTypes();
2322     }
2323     return sourceModel()->mimeTypes();
2324 }
2325 
2326 Qt::DropActions KSelectionProxyModel::supportedDropActions() const
2327 {
2328     if (!sourceModel()) {
2329         return QAbstractProxyModel::supportedDropActions();
2330     }
2331     return sourceModel()->supportedDropActions();
2332 }
2333 
2334 bool KSelectionProxyModel::hasChildren(const QModelIndex &parent) const
2335 {
2336     Q_D(const KSelectionProxyModel);
2337 
2338     if (d->m_rootIndexList.isEmpty() || !sourceModel()) {
2339         return false;
2340     }
2341 
2342     if (parent.isValid()) {
2343         Q_ASSERT(parent.model() == this);
2344         if (d->isFlat()) {
2345             return false;
2346         }
2347         return sourceModel()->hasChildren(mapToSource(parent));
2348     }
2349 
2350     if (!d->m_startWithChildTrees) {
2351         return true;
2352     }
2353 
2354     return !d->m_mappedFirstChildren.isEmpty();
2355 }
2356 
2357 int KSelectionProxyModel::columnCount(const QModelIndex &index) const
2358 {
2359     if (!sourceModel() || index.column() > 0) {
2360         return 0;
2361     }
2362 
2363     return sourceModel()->columnCount(mapToSource(index));
2364 }
2365 
2366 QItemSelectionModel *KSelectionProxyModel::selectionModel() const
2367 {
2368     Q_D(const KSelectionProxyModel);
2369     return d->m_selectionModel;
2370 }
2371 
2372 void KSelectionProxyModel::setSelectionModel(QItemSelectionModel *itemSelectionModel)
2373 {
2374     Q_D(KSelectionProxyModel);
2375     if (d->m_selectionModel != itemSelectionModel) {
2376         if (d->m_selectionModel) {
2377             disconnect(d->m_selectionModel,
2378                        SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
2379                        this,
2380                        SLOT(selectionChanged(QItemSelection, QItemSelection)));
2381         }
2382 
2383         d->m_selectionModel = itemSelectionModel;
2384         Q_EMIT selectionModelChanged(QPrivateSignal());
2385 
2386         if (d->m_selectionModel) {
2387             connect(d->m_selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(selectionChanged(QItemSelection, QItemSelection)));
2388 
2389             auto handleSelectionModelModel = [&, d] {
2390                 beginResetModel();
2391                 if (d->selectionModelModelAboutToBeResetConnection) {
2392                     disconnect(d->selectionModelModelAboutToBeResetConnection);
2393                 }
2394                 if (d->selectionModelModelResetConnection) {
2395                     disconnect(d->selectionModelModelResetConnection);
2396                 }
2397                 if (d->m_selectionModel->model()) {
2398                     d->selectionModelModelAboutToBeResetConnection =
2399                         connect(d->m_selectionModel->model(), SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()));
2400                     d->selectionModelModelResetConnection = connect(d->m_selectionModel->model(), SIGNAL(modelReset()), this, SLOT(sourceModelReset()));
2401                     d->m_rootIndexList.clear();
2402                     delete d->m_indexMapper;
2403                     d->m_indexMapper = new KModelIndexProxyMapper(sourceModel(), d->m_selectionModel->model(), this);
2404                 }
2405                 endResetModel();
2406             };
2407             connect(d->m_selectionModel.data(), &QItemSelectionModel::modelChanged, this, handleSelectionModelModel);
2408             handleSelectionModelModel();
2409         }
2410 
2411         if (sourceModel()) {
2412             delete d->m_indexMapper;
2413             d->m_indexMapper = new KModelIndexProxyMapper(sourceModel(), d->m_selectionModel->model(), this);
2414             if (d->m_selectionModel->hasSelection()) {
2415                 d->selectionChanged(d->m_selectionModel->selection(), QItemSelection());
2416             }
2417         }
2418     }
2419 }
2420 
2421 bool KSelectionProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
2422 {
2423     Q_D(const KSelectionProxyModel);
2424     if (!sourceModel() || d->m_rootIndexList.isEmpty()) {
2425         return false;
2426     }
2427 
2428     if ((row == -1) && (column == -1)) {
2429         return sourceModel()->dropMimeData(data, action, -1, -1, mapToSource(parent));
2430     }
2431 
2432     int source_destination_row = -1;
2433     int source_destination_column = -1;
2434     QModelIndex source_parent;
2435 
2436     if (row == rowCount(parent)) {
2437         source_parent = mapToSource(parent);
2438         source_destination_row = sourceModel()->rowCount(source_parent);
2439     } else {
2440         const QModelIndex proxy_index = index(row, column, parent);
2441         const QModelIndex source_index = mapToSource(proxy_index);
2442         source_destination_row = source_index.row();
2443         source_destination_column = source_index.column();
2444         source_parent = source_index.parent();
2445     }
2446     return sourceModel()->dropMimeData(data, action, source_destination_row, source_destination_column, source_parent);
2447 }
2448 
2449 QList<QPersistentModelIndex> KSelectionProxyModel::sourceRootIndexes() const
2450 {
2451     Q_D(const KSelectionProxyModel);
2452     return d->m_rootIndexList;
2453 }
2454 
2455 QModelIndexList KSelectionProxyModel::match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const
2456 {
2457     if (role < Qt::UserRole) {
2458         return QAbstractProxyModel::match(start, role, value, hits, flags);
2459     }
2460 
2461     QModelIndexList list;
2462     QModelIndex proxyIndex;
2463     const auto lst = sourceModel()->match(mapToSource(start), role, value, hits, flags);
2464     for (const QModelIndex &idx : lst) {
2465         proxyIndex = mapFromSource(idx);
2466         if (proxyIndex.isValid()) {
2467             list << proxyIndex;
2468         }
2469     }
2470     return list;
2471 }
2472 
2473 QItemSelection KSelectionProxyModel::mapSelectionFromSource(const QItemSelection &selection) const
2474 {
2475     Q_D(const KSelectionProxyModel);
2476     if (!d->m_startWithChildTrees && d->m_includeAllSelected) {
2477         // QAbstractProxyModel::mapSelectionFromSource puts invalid ranges in the result
2478         // without checking. We can't have that.
2479         QItemSelection proxySelection;
2480         for (const QItemSelectionRange &range : selection) {
2481             QModelIndex proxyTopLeft = mapFromSource(range.topLeft());
2482             if (!proxyTopLeft.isValid()) {
2483                 continue;
2484             }
2485             QModelIndex proxyBottomRight = mapFromSource(range.bottomRight());
2486             Q_ASSERT(proxyBottomRight.isValid());
2487             proxySelection.append(QItemSelectionRange(proxyTopLeft, proxyBottomRight));
2488         }
2489         return proxySelection;
2490     }
2491 
2492     QItemSelection proxySelection;
2493     QItemSelection::const_iterator it = selection.constBegin();
2494     const QItemSelection::const_iterator end = selection.constEnd();
2495     for (; it != end; ++it) {
2496         const QModelIndex proxyTopLeft = mapFromSource(it->topLeft());
2497         if (!proxyTopLeft.isValid()) {
2498             continue;
2499         }
2500 
2501         if (it->height() == 1 && it->width() == 1) {
2502             proxySelection.append(QItemSelectionRange(proxyTopLeft, proxyTopLeft));
2503         } else {
2504             proxySelection.append(QItemSelectionRange(proxyTopLeft, d->mapFromSource(it->bottomRight())));
2505         }
2506     }
2507     return proxySelection;
2508 }
2509 
2510 QItemSelection KSelectionProxyModel::mapSelectionToSource(const QItemSelection &selection) const
2511 {
2512     Q_D(const KSelectionProxyModel);
2513 
2514     if (selection.isEmpty()) {
2515         return selection;
2516     }
2517 
2518     if (!d->m_startWithChildTrees && d->m_includeAllSelected) {
2519         // QAbstractProxyModel::mapSelectionFromSource puts invalid ranges in the result
2520         // without checking. We can't have that.
2521         QItemSelection sourceSelection;
2522         for (const QItemSelectionRange &range : selection) {
2523             QModelIndex sourceTopLeft = mapToSource(range.topLeft());
2524             Q_ASSERT(sourceTopLeft.isValid());
2525 
2526             QModelIndex sourceBottomRight = mapToSource(range.bottomRight());
2527             Q_ASSERT(sourceBottomRight.isValid());
2528             sourceSelection.append(QItemSelectionRange(sourceTopLeft, sourceBottomRight));
2529         }
2530         return sourceSelection;
2531     }
2532 
2533     QItemSelection sourceSelection;
2534     QItemSelection extraSelection;
2535     QItemSelection::const_iterator it = selection.constBegin();
2536     const QItemSelection::const_iterator end = selection.constEnd();
2537     for (; it != end; ++it) {
2538         const QModelIndex sourceTopLeft = mapToSource(it->topLeft());
2539         if (it->height() == 1 && it->width() == 1) {
2540             sourceSelection.append(QItemSelectionRange(sourceTopLeft, sourceTopLeft));
2541         } else if (it->parent().isValid()) {
2542             sourceSelection.append(QItemSelectionRange(sourceTopLeft, mapToSource(it->bottomRight())));
2543         } else {
2544             // A contiguous selection in the proxy might not be contiguous in the source if it
2545             // is at the top level of the proxy.
2546             if (d->m_startWithChildTrees) {
2547                 const QModelIndex sourceParent = mapFromSource(sourceTopLeft);
2548                 Q_ASSERT(sourceParent.isValid());
2549                 const int rowCount = sourceModel()->rowCount(sourceParent);
2550                 if (rowCount < it->bottom()) {
2551                     Q_ASSERT(sourceTopLeft.isValid());
2552                     Q_ASSERT(it->bottomRight().isValid());
2553                     const QModelIndex sourceBottomRight = mapToSource(it->bottomRight());
2554                     Q_ASSERT(sourceBottomRight.isValid());
2555                     sourceSelection.append(QItemSelectionRange(sourceTopLeft, sourceBottomRight));
2556                     continue;
2557                 }
2558                 // Store the contiguous part...
2559                 const QModelIndex sourceBottomRight = sourceModel()->index(rowCount - 1, it->right(), sourceParent);
2560                 Q_ASSERT(sourceTopLeft.isValid());
2561                 Q_ASSERT(sourceBottomRight.isValid());
2562                 sourceSelection.append(QItemSelectionRange(sourceTopLeft, sourceBottomRight));
2563                 // ... and the rest will be processed later.
2564                 extraSelection.append(QItemSelectionRange(createIndex(it->top() - rowCount, it->right()), it->bottomRight()));
2565             } else {
2566                 QItemSelection topSelection;
2567                 const QModelIndex idx = createIndex(it->top(), it->right());
2568                 const QModelIndex sourceIdx = mapToSource(idx);
2569                 Q_ASSERT(sourceIdx.isValid());
2570                 topSelection.append(QItemSelectionRange(sourceTopLeft, sourceIdx));
2571                 for (int i = it->top() + 1; i <= it->bottom(); ++i) {
2572                     const QModelIndex left = mapToSource(createIndex(i, 0));
2573                     const QModelIndex right = mapToSource(createIndex(i, it->right()));
2574                     Q_ASSERT(left.isValid());
2575                     Q_ASSERT(right.isValid());
2576                     topSelection.append(QItemSelectionRange(left, right));
2577                 }
2578                 sourceSelection += kNormalizeSelection(topSelection);
2579             }
2580         }
2581     }
2582     sourceSelection << mapSelectionToSource(extraSelection);
2583     return sourceSelection;
2584 }
2585 
2586 #include "moc_kselectionproxymodel.cpp"