• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDEUI

kselectionproxymodel.cpp
Go to the documentation of this file.
00001 /*
00002     Copyright (c) 2009 Stephen Kelly <steveire@gmail.com>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #include "kselectionproxymodel.h"
00021 
00022 #include <QtCore/QStack>
00023 #include <QtCore/QStringList>
00024 #include <QtCore/QWeakPointer>
00025 #include <QtGui/QItemSelectionRange>
00026 
00027 #include "kmodelindexproxymapper.h"
00028 #include "kbihash_p.h"
00029 #include "kvoidpointerfactory_p.h"
00030 
00031 #include "kdebug.h"
00032 
00033 typedef KBiHash<QPersistentModelIndex, QModelIndex> SourceProxyIndexMapping;
00034 typedef KBiHash<void*, QModelIndex> ParentMapping;
00035 typedef KHash2Map<QPersistentModelIndex, int> SourceIndexProxyRowMapping;
00036 
00037 #define KDO(object) kDebug() << #object << object
00038 #define SON(object) object->setObjectName(#object)
00039 
00044 template<typename ModelIndex>
00045 bool isDescendantOf(const QList<ModelIndex> &list, const QModelIndex &idx)
00046 {
00047     if (!idx.isValid())
00048         return false;
00049 
00050     if (list.contains(idx))
00051         return false;
00052 
00053     QModelIndex parent = idx.parent();
00054     while (parent.isValid()) {
00055         if (list.contains(parent))
00056             return true;
00057         parent = parent.parent();
00058     }
00059     return false;
00060 }
00061 
00062 static bool isDescendantOf(const QModelIndex &ancestor, const QModelIndex &descendant)
00063 {
00064     if (!descendant.isValid())
00065         return false;
00066 
00067     if (ancestor == descendant)
00068         return false;
00069 
00070     QModelIndex parent = descendant.parent();
00071     while (parent.isValid()) {
00072         if (parent == ancestor)
00073             return true;
00074 
00075         parent = parent.parent();
00076     }
00077     return false;
00078 }
00079 
00080 static bool isDescendantOf(const QItemSelection &selection, const QModelIndex &descendant)
00081 {
00082     if (!descendant.isValid())
00083         return false;
00084 
00085     if (selection.contains(descendant))
00086         return false;
00087 
00088     QModelIndex parent = descendant.parent();
00089     while (parent.isValid()) {
00090         if (selection.contains(parent))
00091             return true;
00092 
00093         parent = parent.parent();
00094     }
00095     return false;
00096 }
00097 
00098 static bool isDescendantOf(const QItemSelectionRange &range, const QModelIndex &descendant)
00099 {
00100     if (!descendant.isValid())
00101         return false;
00102 
00103     if (range.contains(descendant))
00104         return false;
00105 
00106     QModelIndex parent = descendant.parent();
00107     while (parent.isValid()) {
00108         if (range.contains(parent))
00109             return true;
00110 
00111         parent = parent.parent();
00112     }
00113     return false;
00114 }
00115 
00116 static int _getRootListRow(const QList<QModelIndexList> &rootAncestors, const QModelIndex &index)
00117 {
00118     QModelIndex commonParent = index;
00119     QModelIndex youngestAncestor;
00120 
00121     int firstCommonParent = -1;
00122     int bestParentRow = -1;
00123     while (commonParent.isValid()) {
00124         youngestAncestor = commonParent;
00125         commonParent = commonParent.parent();
00126 
00127         for (int i = 0; i < rootAncestors.size(); ++i) {
00128             const QModelIndexList ancestorList = rootAncestors.at(i);
00129 
00130             const int parentRow = ancestorList.indexOf(commonParent);
00131 
00132             if (parentRow < 0)
00133                 continue;
00134 
00135             if (parentRow > bestParentRow) {
00136                 firstCommonParent = i;
00137                 bestParentRow = parentRow;
00138             }
00139         }
00140 
00141         if (firstCommonParent >= 0)
00142             break;
00143     }
00144 
00145     // If @p list is non-empty, the invalid QModelIndex() will at least be found in ancestorList.
00146     Q_ASSERT(firstCommonParent >= 0);
00147 
00148     const QModelIndexList firstAnsList = rootAncestors.at(firstCommonParent);
00149 
00150     const QModelIndex eldestSibling = firstAnsList.value(bestParentRow + 1);
00151 
00152     if (eldestSibling.isValid()) {
00153         // firstCommonParent is a sibling of one of the ancestors of @p index.
00154         // It is the first index to share a common parent with one of the ancestors of @p index.
00155         if (eldestSibling.row() >= youngestAncestor.row())
00156             return firstCommonParent;
00157     }
00158 
00159     int siblingOffset = 1;
00160 
00161     // The same commonParent might be common to several root indexes.
00162     // If this is the last in the list, it's the only match. We instruct the model
00163     // to insert the new index after it ( + siblingOffset).
00164     if (rootAncestors.size() <= firstCommonParent + siblingOffset) {
00165         return firstCommonParent + siblingOffset;
00166     }
00167 
00168     // A
00169     // - B
00170     //   - C
00171     //   - D
00172     //   - E
00173     // F
00174     //
00175     // F is selected, then C then D. When inserting D into the model, the commonParent is B (the parent of C).
00176     // The next existing sibling of B is F (in the proxy model). bestParentRow will then refer to an index on
00177     // the level of a child of F (which doesn't exist - Boom!). If it doesn't exist, then we've already found
00178     // the place to insert D
00179     QModelIndexList ansList = rootAncestors.at(firstCommonParent + siblingOffset);
00180     if (ansList.size() <= bestParentRow) {
00181         return firstCommonParent + siblingOffset;
00182     }
00183 
00184     QModelIndex nextParent = ansList.at(bestParentRow);
00185     while (nextParent == commonParent) {
00186         if (ansList.size() < bestParentRow + 1)
00187             // If the list is longer, it means that at the end of it is a descendant of the new index.
00188             // We insert the ancestors items first in that case.
00189             break;
00190 
00191         const QModelIndex nextSibling = ansList.value(bestParentRow + 1);
00192 
00193         if (!nextSibling.isValid()) {
00194             continue;
00195         }
00196 
00197         if (youngestAncestor.row() <= nextSibling.row()) {
00198             break;
00199         }
00200 
00201         siblingOffset++;
00202 
00203         if (rootAncestors.size() <= firstCommonParent + siblingOffset)
00204             break;
00205 
00206         ansList = rootAncestors.at(firstCommonParent + siblingOffset);
00207 
00208         // In the scenario above, E is selected after D, causing this loop to be entered,
00209         // and requiring a similar result if the next sibling in the proxy model does not have children.
00210         if (ansList.size() <= bestParentRow) {
00211             break;
00212         }
00213 
00214         nextParent = ansList.at(bestParentRow);
00215     }
00216 
00217     return firstCommonParent + siblingOffset;
00218 }
00219 
00223 template<typename ModelIndex>
00224 static int getRootListRow(const QList<ModelIndex> &list, const QModelIndex &index)
00225 {
00226     if (!index.isValid())
00227         return -1;
00228 
00229     if (list.isEmpty())
00230         return 0;
00231 
00232     // What's going on?
00233     // Consider a tree like
00234     //
00235     // A
00236     // - B
00237     // - - C
00238     // - - - D
00239     // - E
00240     // - F
00241     // - - G
00242     // - - - H
00243     // - I
00244     // - - J
00245     // - K
00246     //
00247     // 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.
00248     // To figure that out, we create a list for each already selected index of its ancestors. Then,
00249     // we climb the ancestors of H until we reach an index with siblings which have a descendant
00250     // selected (F above has siblings B, E and I which have descendants which are already selected).
00251     // Those child indexes are traversed to find the right sibling to put F beside.
00252     //
00253     // i.e., new items are inserted in the expected location.
00254 
00255     QList<QModelIndexList> rootAncestors;
00256     foreach(const QModelIndex &root, list) {
00257         QModelIndexList ancestors;
00258         ancestors << root;
00259         QModelIndex parent = root.parent();
00260         while (parent.isValid()) {
00261             ancestors.prepend(parent);
00262             parent = parent.parent();
00263         }
00264         ancestors.prepend(QModelIndex());
00265         rootAncestors << ancestors;
00266     }
00267     return _getRootListRow(rootAncestors, index);
00268 }
00269 
00281 static QItemSelection getRootRanges(const QItemSelection &_selection)
00282 {
00283     QItemSelection rootSelection;
00284     QItemSelection selection = _selection;
00285     QList<QItemSelectionRange>::iterator it = selection.begin();
00286     while (it != selection.end()) {
00287         if (!it->topLeft().parent().isValid())
00288         {
00289             rootSelection.append(*it);
00290             it = selection.erase(it);
00291         } else
00292             ++it;
00293     }
00294 
00295     it = selection.begin();
00296     const QList<QItemSelectionRange>::iterator end = selection.end();
00297     while ( it != end ) {
00298         const QItemSelectionRange range = *it;
00299         it = selection.erase(it);
00300 
00301         if (isDescendantOf(rootSelection, range.topLeft()) || isDescendantOf(selection, range.topLeft()))
00302             continue;
00303 
00304         rootSelection << range;
00305     }
00306     return rootSelection;
00307 }
00308 
00311 struct RangeLessThan
00312 {
00313     bool operator()(const QItemSelectionRange &left, const QItemSelectionRange &right) const
00314     {
00315         if (right.model() == left.model()) {
00316             // parent has to be calculated, so we only do so once.
00317             const QModelIndex topLeftParent = left.parent();
00318             const QModelIndex otherTopLeftParent = right.parent();
00319             if (topLeftParent == otherTopLeftParent) {
00320                 if (right.top() == left.top()) {
00321                     if (right.left() == left.left()) {
00322                         if (right.bottom() == left.bottom()) {
00323                             return left.right() < right.right();
00324                         }
00325                         return left.bottom() < right.bottom();
00326                     }
00327                     return left.left() < right.left();
00328                 }
00329                 return left.top() < right.top();
00330             }
00331             return topLeftParent < otherTopLeftParent;
00332         }
00333         return left.model() < right.model();
00334     }
00335 };
00336 
00337 static QItemSelection stableNormalizeSelection(QItemSelection selection)
00338 {
00339     if (selection.size() <= 1)
00340         return selection;
00341 
00342     QList<QItemSelectionRange>::iterator it = selection.begin();
00343 
00344     Q_ASSERT(it != selection.end());
00345     QList<QItemSelectionRange>::iterator scout = it + 1;
00346     while (scout != selection.end()) {
00347         Q_ASSERT(it != selection.end());
00348         int bottom = it->bottom();
00349         while (scout != selection.end() && it->parent() == scout->parent() && bottom + 1 == scout->top()) {
00350             bottom = scout->bottom();
00351             scout = selection.erase(scout);
00352         }
00353         if (bottom != it->bottom()) {
00354             const QModelIndex topLeft = it->topLeft();
00355             *it = QItemSelectionRange(topLeft, topLeft.sibling(bottom, it->right()));
00356         }
00357         Q_ASSERT(it != scout);
00358         if (scout == selection.end())
00359             break;
00360         it = scout;
00361         ++scout;
00362     }
00363     return selection;
00364 }
00365 
00366 QItemSelection kNormalizeSelection(QItemSelection selection)
00367 {
00368     if (selection.size() <= 1)
00369         return selection;
00370 
00371     RangeLessThan lt;
00372     qSort(selection.begin(), selection.end(), lt);
00373     return stableNormalizeSelection(selection);
00374 }
00375 
00376 
00377 class KSelectionProxyModelPrivate
00378 {
00379 public:
00380     KSelectionProxyModelPrivate(KSelectionProxyModel *model, QItemSelectionModel *selectionModel)
00381           : q_ptr(model),
00382             m_startWithChildTrees(false),
00383             m_omitChildren(false),
00384             m_omitDescendants(false),
00385             m_includeAllSelected(false),
00386             m_rowsInserted(false),
00387             m_rowsRemoved(false),
00388             m_rowsMoved(false),
00389             m_resetting(false),
00390             m_doubleResetting(false),
00391             m_layoutChanging(false),
00392             m_ignoreNextLayoutAboutToBeChanged(false),
00393             m_ignoreNextLayoutChanged(false),
00394             m_selectionModel(selectionModel)
00395     {
00396     }
00397 
00398     Q_DECLARE_PUBLIC(KSelectionProxyModel)
00399     KSelectionProxyModel * const q_ptr;
00400 
00401     // A unique id is generated for each parent. It is used for the internalPointer of its children in the proxy
00402     // This is used to store a unique id for QModelIndexes in the proxy which have children.
00403     // If an index newly gets children it is added to this hash. If its last child is removed it is removed from this map.
00404     // If this map contains an index, that index hasChildren(). This hash is populated when new rows are inserted in the
00405     // source model, or a new selection is made.
00406     mutable ParentMapping m_parentIds;
00407     // This mapping maps indexes with children in the source to indexes with children in the proxy.
00408     // The order of indexes in this list is not relevant.
00409     mutable SourceProxyIndexMapping m_mappedParents;
00410 
00411     KVoidPointerFactory<> m_voidPointerFactory;
00412 
00425     void updateInternalIndexes(const QModelIndex &parent, int start, int offset);
00426 
00434     void updateInternalTopIndexes(int start, int offset);
00435 
00436     void updateFirstChildMapping(const QModelIndex& parent, int offset);
00437 
00438     bool isFlat() const { return m_omitChildren || (m_omitDescendants && m_startWithChildTrees); }
00439 
00444     bool ensureMappable(const QModelIndex &parent) const;
00445     bool parentIsMappable(const QModelIndex &parent) const { return parentAlreadyMapped(parent) || m_rootIndexList.contains(parent); }
00446 
00450     QModelIndex mapFromSource(const QModelIndex &parent) const;
00451 
00457     void createParentMappings(const QModelIndex &parent, int start, int end) const;
00458     void createFirstChildMapping(const QModelIndex &parent, int proxyRow) const;
00459     bool firstChildAlreadyMapped(const QModelIndex &firstChild) const;
00460     bool parentAlreadyMapped(const QModelIndex &parent) const;
00461     void removeFirstChildMappings(int start, int end);
00462     void removeParentMappings(const QModelIndex &parent, int start, int end);
00463 
00473     QModelIndex mapParentToSource(const QModelIndex &proxyParent) const;
00474 
00482     QModelIndex mapParentFromSource(const QModelIndex &sourceParent) const;
00483 
00484     QModelIndex mapTopLevelToSource(int row, int column) const;
00485     QModelIndex mapTopLevelFromSource(const QModelIndex &sourceIndex) const;
00486     QModelIndex createTopLevelIndex(int row, int column) const;
00487     int topLevelRowCount() const;
00488 
00489     void* parentId(const QModelIndex &proxyParent) const { return m_parentIds.rightToLeft(proxyParent); }
00490     QModelIndex parentForId(void *id) const { return m_parentIds.leftToRight(id); }
00491 
00492     // Only populated if m_startWithChildTrees.
00493 
00494     mutable SourceIndexProxyRowMapping m_mappedFirstChildren;
00495 
00496     // Source list is the selection in the source model.
00497     QList<QPersistentModelIndex> m_rootIndexList;
00498 
00499     KModelIndexProxyMapper *m_indexMapper;
00500 
00501     QPair<int, int> beginRemoveRows(const QModelIndex &parent, int start, int end) const;
00502     QPair<int, int> beginInsertRows(const QModelIndex &parent, int start, int end) const;
00503     void endRemoveRows(const QModelIndex &sourceParent, int proxyStart, int proxyEnd);
00504     void endInsertRows(const QModelIndex &parent, int start, int end);
00505 
00506     void sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
00507     void sourceRowsInserted(const QModelIndex &parent, int start, int end);
00508     void sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
00509     void sourceRowsRemoved(const QModelIndex &parent, int start, int end);
00510     void sourceRowsAboutToBeMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destParent, int destRow);
00511     void sourceRowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destParent, int destRow);
00512     void sourceModelAboutToBeReset();
00513     void sourceModelReset();
00514     void sourceLayoutAboutToBeChanged();
00515     void sourceLayoutChanged();
00516     void emitContinuousRanges(const QModelIndex &sourceFirst, const QModelIndex &sourceLast,
00517                               const QModelIndex &proxyFirst, const QModelIndex &proxyLast);
00518     void sourceDataChanged(const QModelIndex &topLeft , const QModelIndex &bottomRight);
00519 
00520     void removeSelectionFromProxy(const QItemSelection &selection);
00521     void removeRangeFromProxy(const QItemSelectionRange &range);
00522 
00523     void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
00524     void sourceModelDestroyed();
00525 
00526     void resetInternalData();
00527 
00532     int getProxyInitialRow(const QModelIndex &parent) const;
00533 
00543     int getTargetRow(int rootListRow);
00544 
00548     void insertSelectionIntoProxy(const QItemSelection& selection);
00549 
00550     bool m_startWithChildTrees;
00551     bool m_omitChildren;
00552     bool m_omitDescendants;
00553     bool m_includeAllSelected;
00554     bool m_rowsInserted;
00555     bool m_rowsRemoved;
00556     QPair<int, int> m_proxyRemoveRows;
00557     bool m_rowsMoved;
00558     bool m_resetting;
00559     bool m_doubleResetting;
00560     bool m_layoutChanging;
00561     bool m_ignoreNextLayoutAboutToBeChanged;
00562     bool m_ignoreNextLayoutChanged;
00563     const QWeakPointer<QItemSelectionModel> m_selectionModel;
00564 
00565     KSelectionProxyModel::FilterBehavior m_filterBehavior;
00566 
00567     QList<QPersistentModelIndex> m_layoutChangePersistentIndexes;
00568     QModelIndexList m_proxyIndexes;
00569 
00570     struct PendingSelectionChange
00571     {
00572       PendingSelectionChange() {}
00573       PendingSelectionChange(const QItemSelection &selected_, const QItemSelection &deselected_)
00574         : selected(selected_), deselected(deselected_)
00575       {
00576 
00577       }
00578       QItemSelection selected;
00579       QItemSelection deselected;
00580     };
00581     QVector<PendingSelectionChange> m_pendingSelectionChanges;
00582 };
00583 
00584 void KSelectionProxyModelPrivate::emitContinuousRanges(const QModelIndex &sourceFirst, const QModelIndex &sourceLast,
00585                                                        const QModelIndex &proxyFirst, const QModelIndex &proxyLast)
00586 {
00587     Q_Q(KSelectionProxyModel);
00588 
00589     Q_ASSERT(sourceFirst.model() == q->sourceModel());
00590     Q_ASSERT(sourceLast.model() == q->sourceModel());
00591     Q_ASSERT(proxyFirst.model() == q);
00592     Q_ASSERT(proxyLast.model() == q);
00593 
00594     const int proxyRangeSize = proxyLast.row() - proxyFirst.row();
00595     const int sourceRangeSize = sourceLast.row() - sourceFirst.row();
00596 
00597     if (proxyRangeSize == sourceRangeSize) {
00598         emit q->dataChanged(proxyFirst, proxyLast);
00599         return;
00600     }
00601 
00602 
00603     // TODO: Loop to skip descendant ranges.
00604 //     int lastRow;
00605 //
00606 //     const QModelIndex sourceHalfWay = sourceFirst.sibling(sourceFirst.row() + (sourceRangeSize / 2));
00607 //     const QModelIndex proxyHalfWay = proxyFirst.sibling(proxyFirst.row() + (proxyRangeSize / 2));
00608 //     const QModelIndex mappedSourceHalfway = q->mapToSource(proxyHalfWay);
00609 //
00610 //     const int halfProxyRange = mappedSourceHalfway.row() - proxyFirst.row();
00611 //     const int halfSourceRange = sourceHalfWay.row() - sourceFirst.row();
00612 //
00613 //     if (proxyRangeSize == sourceRangeSize)
00614 //     {
00615 //         emit q->dataChanged(proxyFirst, proxyLast.sibling(proxyFirst.row() + proxyRangeSize, proxyLast.column()));
00616 //         return;
00617 //     }
00618 
00619     emit q->dataChanged(proxyFirst, proxyLast);
00620 }
00621 
00622 void KSelectionProxyModelPrivate::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
00623 {
00624     Q_Q(KSelectionProxyModel);
00625 
00626     Q_ASSERT(topLeft.model() == q->sourceModel());
00627     Q_ASSERT(bottomRight.model() == q->sourceModel());
00628 
00629     const QModelIndex sourceRangeParent = topLeft.parent();
00630     if (!sourceRangeParent.isValid() && m_startWithChildTrees && !m_rootIndexList.contains(sourceRangeParent))
00631         return;
00632 
00633     const QModelIndex proxyTopLeft = q->mapFromSource(topLeft);
00634     const QModelIndex proxyBottomRight = q->mapFromSource(bottomRight);
00635 
00636     const QModelIndex proxyRangeParent = proxyTopLeft.parent();
00637 
00638     if (!m_omitChildren && m_omitDescendants && m_startWithChildTrees && m_includeAllSelected) {
00639         // ChildrenOfExactSelection
00640         if (proxyTopLeft.isValid())
00641             emitContinuousRanges(topLeft, bottomRight, proxyTopLeft, proxyBottomRight);
00642         return;
00643     }
00644 
00645     if ((m_omitChildren && !m_startWithChildTrees && m_includeAllSelected)
00646             || (!proxyRangeParent.isValid() && !m_startWithChildTrees)) {
00647         // Exact selection and SubTreeRoots and SubTrees in top level
00648         // Emit continuous ranges.
00649         QList<int> changedRows;
00650         for (int row = topLeft.row(); row <= bottomRight.row(); ++row) {
00651             const QModelIndex index = q->sourceModel()->index(row, topLeft.column(), topLeft.parent());
00652             const int idx = m_rootIndexList.indexOf(index);
00653             if (idx != -1) {
00654                 changedRows.append(idx);
00655             }
00656         }
00657         if (changedRows.isEmpty())
00658             return;
00659         int first = changedRows.first();
00660         int previous = first;
00661         QList<int>::const_iterator it = changedRows.constBegin();
00662         const QList<int>::const_iterator end = changedRows.constEnd();
00663         for ( ; it != end; ++it) {
00664             if (*it == previous + 1) {
00665                 ++previous;
00666             } else {
00667                 const QModelIndex _top = q->index(first, topLeft.column());
00668                 const QModelIndex _bottom = q->index(previous, bottomRight.column());
00669                 emit q->dataChanged(_top, _bottom);
00670                 previous = first = *it;
00671             }
00672         }
00673         if (first != previous) {
00674             const QModelIndex _top = q->index(first, topLeft.column());
00675             const QModelIndex _bottom = q->index(previous, bottomRight.column());
00676             emit q->dataChanged(_top, _bottom);
00677         }
00678         return;
00679     }
00680     if (proxyRangeParent.isValid()) {
00681         if (m_omitChildren && !m_startWithChildTrees && !m_includeAllSelected)
00682             // SubTreeRoots
00683             return;
00684         if (!proxyTopLeft.isValid())
00685             return;
00686         // SubTrees and SubTreesWithoutRoots
00687         emit q->dataChanged(proxyTopLeft, proxyBottomRight);
00688         return;
00689     }
00690 
00691     if (m_startWithChildTrees && !m_omitChildren && !m_includeAllSelected && !m_omitDescendants) {
00692         // SubTreesWithoutRoots
00693         if (proxyTopLeft.isValid())
00694             emit q->dataChanged(proxyTopLeft, proxyBottomRight);
00695         return;
00696     }
00697 }
00698 
00699 void KSelectionProxyModelPrivate::sourceLayoutAboutToBeChanged()
00700 {
00701     Q_Q(KSelectionProxyModel);
00702 
00703     if (m_ignoreNextLayoutAboutToBeChanged) {
00704         m_ignoreNextLayoutAboutToBeChanged = false;
00705         return;
00706     }
00707 
00708     if (m_rootIndexList.isEmpty())
00709         return;
00710 
00711     emit q->layoutAboutToBeChanged();
00712 
00713     QPersistentModelIndex srcPersistentIndex;
00714     foreach(const QPersistentModelIndex &proxyPersistentIndex, q->persistentIndexList()) {
00715         m_proxyIndexes << proxyPersistentIndex;
00716         Q_ASSERT(proxyPersistentIndex.isValid());
00717         srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
00718         Q_ASSERT(srcPersistentIndex.isValid());
00719         m_layoutChangePersistentIndexes << srcPersistentIndex;
00720     }
00721 
00722     QItemSelection selection;
00723     foreach (const QModelIndex &rootIndex, m_rootIndexList)
00724     {
00725       // This will be optimized later.
00726       emit q->rootIndexAboutToBeRemoved(rootIndex);
00727       selection.append(QItemSelectionRange(rootIndex, rootIndex));
00728     }
00729 
00730     selection = kNormalizeSelection(selection);
00731     emit q->rootSelectionAboutToBeRemoved(selection);
00732 
00733     m_rootIndexList.clear();
00734 }
00735 
00736 void KSelectionProxyModelPrivate::sourceLayoutChanged()
00737 {
00738     Q_Q(KSelectionProxyModel);
00739 
00740     if (m_ignoreNextLayoutChanged) {
00741         m_ignoreNextLayoutChanged = false;
00742         return;
00743     }
00744 
00745     if (m_selectionModel.data()->selection().isEmpty()) {
00746         return;
00747     }
00748 
00749     // Handling this signal is slow.
00750     // The problem is that anything can happen between emissions of layoutAboutToBeChanged and layoutChanged.
00751     // We can't assume anything is the same about the structure anymore. items have been sorted, items which
00752     // were parents before are now not, items which were not parents before now are, items which used to be the
00753     // first child are now the Nth child and items which used to be the Nth child are now the first child.
00754     // We effectively can't update our mapping because we don't have enough information to update everything.
00755     // The only way we would have is if we take a persistent index of the entire source model
00756     // on sourceLayoutAboutToBeChanged and then examine it here. That would be far too expensive.
00757     // Instead we just have to clear the entire mapping and recreate it.
00758 
00759     m_rootIndexList.clear();
00760     m_mappedFirstChildren.clear();
00761     m_mappedParents.clear();
00762     m_parentIds.clear();
00763 
00764     m_resetting = true;
00765     m_layoutChanging = true;
00766     selectionChanged(m_selectionModel.data()->selection(), QItemSelection());
00767     m_resetting = false;
00768     m_layoutChanging = false;
00769 
00770     for (int i = 0; i < m_proxyIndexes.size(); ++i) {
00771         q->changePersistentIndex(m_proxyIndexes.at(i), q->mapFromSource(m_layoutChangePersistentIndexes.at(i)));
00772     }
00773 
00774     m_layoutChangePersistentIndexes.clear();
00775     m_proxyIndexes.clear();
00776 
00777     emit q->layoutChanged();
00778 }
00779 
00780 void KSelectionProxyModelPrivate::resetInternalData()
00781 {
00782     m_rootIndexList.clear();
00783     m_layoutChangePersistentIndexes.clear();
00784     m_proxyIndexes.clear();
00785     m_mappedParents.clear();
00786     m_parentIds.clear();
00787     m_mappedFirstChildren.clear();
00788     m_voidPointerFactory.clear();
00789 }
00790 
00791 void KSelectionProxyModelPrivate::sourceModelDestroyed()
00792 {
00793     Q_Q(KSelectionProxyModel);
00794     // There is very little we can do here.
00795     resetInternalData();
00796     m_resetting = false;
00797   //  q->endResetModel();
00798 }
00799 
00800 void KSelectionProxyModelPrivate::sourceModelAboutToBeReset()
00801 {
00802     Q_Q(KSelectionProxyModel);
00803 
00804     // We might be resetting as a result of the selection source model resetting.
00805     // If so we don't want to emit
00806     // sourceModelAboutToBeReset
00807     // sourceModelAboutToBeReset
00808     // sourceModelReset
00809     // sourceModelReset
00810     // So we ensure that we just emit one.
00811     if (m_resetting) {
00812 
00813       // If both the source model and the selection source model are reset,
00814       // We want to begin our reset before the first one is reset and end
00815       // it after the second one is reset.
00816       m_doubleResetting = true;
00817       return;
00818     }
00819 
00820     q->beginResetModel();
00821     m_resetting = true;
00822 }
00823 
00824 void KSelectionProxyModelPrivate::sourceModelReset()
00825 {
00826     Q_Q(KSelectionProxyModel);
00827 
00828     if (m_doubleResetting) {
00829       m_doubleResetting = false;
00830       return;
00831     }
00832 
00833     resetInternalData();
00834     // No need to try to refill this. When the model is reset it doesn't have a meaningful selection anymore,
00835     // but when it gets one we'll be notified anyway.
00836     if (!m_selectionModel.isNull())
00837       m_selectionModel.data()->reset();
00838     m_resetting = false;
00839     q->endResetModel();
00840 }
00841 
00842 int KSelectionProxyModelPrivate::getProxyInitialRow(const QModelIndex &parent) const
00843 {
00844     Q_ASSERT(m_rootIndexList.contains(parent));
00845 
00846     // The difficulty here is that parent and parent.parent() might both be in the m_rootIndexList.
00847 
00848     // - A
00849     // - B
00850     // - - C
00851     // - - D
00852     // - - - E
00853 
00854     // Consider that B and D are selected. The proxy model is:
00855 
00856     // - C
00857     // - D
00858     // - E
00859 
00860     // Then D gets a new child at 0. In that case we require adding F between D and E.
00861 
00862     // Consider instead that D gets removed. Then @p parent will be B.
00863 
00864 
00865     Q_Q(const KSelectionProxyModel);
00866 
00867     Q_ASSERT(parent.model() == q->sourceModel());
00868 
00869     int parentPosition = m_rootIndexList.indexOf(parent);
00870 
00871     QModelIndex parentAbove;
00872 
00873     // If parentPosition == 0, then parent.parent() is not also in the model. (ordering is preserved)
00874     while (parentPosition > 0) {
00875         parentPosition--;
00876 
00877         parentAbove = m_rootIndexList.at(parentPosition);
00878         Q_ASSERT(parentAbove.isValid());
00879 
00880         int rows = q->sourceModel()->rowCount(parentAbove);
00881         if (rows > 0) {
00882             QModelIndex sourceIndexAbove = q->sourceModel()->index(rows - 1, 0, parentAbove);
00883             Q_ASSERT(sourceIndexAbove.isValid());
00884             QModelIndex proxyChildAbove = mapFromSource(sourceIndexAbove);
00885             Q_ASSERT(proxyChildAbove.isValid());
00886             return proxyChildAbove.row() + 1;
00887         }
00888     }
00889     return 0;
00890 }
00891 
00892 void KSelectionProxyModelPrivate::updateFirstChildMapping(const QModelIndex& parent, int offset)
00893 {
00894     Q_Q(KSelectionProxyModel);
00895 
00896     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
00897 
00898     static const int column = 0;
00899     static const int row = 0;
00900 
00901     const QPersistentModelIndex srcIndex = q->sourceModel()->index(row, column, parent);
00902 
00903     const QPersistentModelIndex previousFirstChild = q->sourceModel()->index(offset, column, parent);
00904 
00905     SourceIndexProxyRowMapping::left_iterator it = m_mappedFirstChildren.findLeft(previousFirstChild);
00906     if (it == m_mappedFirstChildren.leftEnd())
00907         return;
00908 
00909     Q_ASSERT(srcIndex.isValid());
00910     const int proxyRow = it.value();
00911     Q_ASSERT(proxyRow >= 0);
00912 
00913     m_mappedFirstChildren.eraseLeft(it);
00914 
00915     // The proxy row in the mapping has already been updated by the offset in updateInternalTopIndexes
00916     // so we restore it by applying the reverse.
00917     m_mappedFirstChildren.insert(srcIndex, proxyRow - offset);
00918 }
00919 
00920 QPair< int, int > KSelectionProxyModelPrivate::beginInsertRows(const QModelIndex& parent, int start, int end) const
00921 {
00922     const QModelIndex proxyParent = mapFromSource(parent);
00923 
00924     if (!proxyParent.isValid())
00925     {
00926         if (!m_startWithChildTrees)
00927             return qMakePair(-1, -1);
00928 
00929         if (!m_rootIndexList.contains(parent))
00930             return qMakePair(-1, -1);
00931     }
00932 
00933     if (!m_startWithChildTrees) {
00934         // SubTrees
00935         if (proxyParent.isValid())
00936             return qMakePair(start, end);
00937         return qMakePair(-1, -1);
00938     }
00939 
00940     if (!m_includeAllSelected && proxyParent.isValid()) {
00941         // SubTreesWithoutRoots deeper than topLevel
00942         return qMakePair(start, end);
00943     }
00944 
00945     if (!m_rootIndexList.contains(parent))
00946         return qMakePair(-1, -1);
00947 
00948     const int proxyStartRow = getProxyInitialRow(parent) + start;
00949     return qMakePair(proxyStartRow, proxyStartRow + (end - start));
00950 }
00951 
00952 void KSelectionProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
00953 {
00954     Q_Q(KSelectionProxyModel);
00955 
00956     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
00957 
00958     if (!m_selectionModel.data()->hasSelection())
00959         return;
00960 
00961     if (m_omitChildren)
00962         // ExactSelection and SubTreeRoots
00963         return;
00964 
00965     // topLevel insertions can be ignored because topLevel items would need to be selected to affect the proxy.
00966     if (!parent.isValid())
00967         return;
00968 
00969     QPair<int, int> pair = beginInsertRows(parent, start, end);
00970     if (pair.first == -1)
00971         return;
00972 
00973     const QModelIndex proxyParent = m_startWithChildTrees ? QModelIndex() : mapFromSource(parent);
00974 
00975     m_rowsInserted = true;
00976     q->beginInsertRows(proxyParent, pair.first, pair.second);
00977 }
00978 
00979 void KSelectionProxyModelPrivate::endInsertRows(const QModelIndex& parent, int start, int end)
00980 {
00981     Q_Q(const KSelectionProxyModel);
00982     const QModelIndex proxyParent = mapFromSource(parent);
00983     const int offset = end - start + 1;
00984 
00985     const bool isNewParent = (q->sourceModel()->rowCount(parent) == offset);
00986 
00987     if (m_startWithChildTrees && m_rootIndexList.contains(parent)) {
00988         const int proxyInitialRow = getProxyInitialRow(parent);
00989         Q_ASSERT(proxyInitialRow >= 0);
00990         const int proxyStartRow = proxyInitialRow + start;
00991 
00992         updateInternalTopIndexes(proxyStartRow, offset);
00993         if (isNewParent)
00994             createFirstChildMapping(parent, proxyStartRow);
00995         else if (start == 0)
00996             // We already have a first child mapping, but what we have mapped is not the first child anymore
00997             // so we need to update it.
00998             updateFirstChildMapping(parent, end + 1);
00999     } else {
01000         Q_ASSERT(proxyParent.isValid());
01001         if (!isNewParent)
01002             updateInternalIndexes(proxyParent, start, offset);
01003         else
01004             createParentMappings(parent.parent(), parent.row(), parent.row());
01005     }
01006     createParentMappings(parent, start, end);
01007 }
01008 
01009 void KSelectionProxyModelPrivate::sourceRowsInserted(const QModelIndex &parent, int start, int end)
01010 {
01011     Q_Q(KSelectionProxyModel);
01012 
01013     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
01014 
01015     if (!m_rowsInserted)
01016         return;
01017     m_rowsInserted = false;
01018     endInsertRows(parent, start, end);
01019     q->endInsertRows();
01020     foreach(const PendingSelectionChange &pendingChange, m_pendingSelectionChanges)
01021     {
01022       selectionChanged(pendingChange.selected, pendingChange.deselected);
01023     }
01024     m_pendingSelectionChanges.clear();
01025 }
01026 
01027 QPair<int, int> KSelectionProxyModelPrivate::beginRemoveRows(const QModelIndex& parent, int start, int end) const
01028 {
01029     Q_Q(const KSelectionProxyModel);
01030 
01031     QPair<int, int> pair = qMakePair(start, end);
01032 
01033     if (m_omitChildren && !m_startWithChildTrees && !m_includeAllSelected) {
01034         // SubTreeRoots
01035         if (m_rootIndexList.contains(parent) || isDescendantOf(m_rootIndexList, parent)) {
01036             return qMakePair(-1, -1);
01037         }
01038     }
01039 
01040     const QModelIndex proxyParent = mapParentFromSource(parent);
01041 
01042     if (!m_includeAllSelected && !m_omitChildren) {
01043         // SubTrees and SubTreesWithoutRoots
01044         if (proxyParent.isValid()) {
01045             return pair;
01046         }
01047         if (m_startWithChildTrees && m_rootIndexList.contains(parent)) {
01048             // SubTreesWithoutRoots topLevel
01049             const int proxyStartRow = getProxyInitialRow(parent) + start;
01050             return qMakePair(proxyStartRow, proxyStartRow + (end - start));
01051         }
01052     }
01053 
01054     if (m_includeAllSelected && m_startWithChildTrees) {
01055         // ChildrenOfExactSelection
01056         int position = m_rootIndexList.indexOf(parent);
01057         if (position != -1) {
01058             const int proxyStartRow = getProxyInitialRow(parent) + start;
01059             int proxyEndRow = proxyStartRow + (end - start);
01060             ++position;
01061             while (m_rootIndexList.size() < position) {
01062                 const QModelIndex idx = m_rootIndexList.at(position);
01063                 if (isDescendantOf(parent, idx))
01064                     proxyEndRow += q->sourceModel()->rowCount(idx);
01065                 else
01066                     break;
01067             }
01068             return qMakePair(proxyStartRow, proxyEndRow);
01069         }
01070     }
01071 
01072     QList<QPersistentModelIndex>::const_iterator rootIt = m_rootIndexList.constBegin();
01073     const QList<QPersistentModelIndex>::const_iterator rootEnd = m_rootIndexList.constEnd();
01074     int rootPosition = 0;
01075     int rootStartRemove = -1;
01076     int rootEndRemove = -1;
01077     int siblingCount = 0;
01078 
01079     for ( ; rootIt != rootEnd; ++rootIt, ++rootPosition) {
01080         if (m_omitChildren && m_includeAllSelected) {
01081             // ExactSelection
01082             if (parent == rootIt->parent() && rootIt->row() <= end && rootIt->row() >= start) {
01083                 if (rootStartRemove == -1)
01084                     rootStartRemove = rootPosition;
01085                 ++rootEndRemove;
01086             } else {
01087                 if (rootStartRemove != -1)
01088                     break;
01089             }
01090         } else {
01091             if (isDescendantOf(parent, *rootIt)) {
01092                 if (rootStartRemove == -1)
01093                     rootStartRemove = rootPosition;
01094                 ++rootEndRemove;
01095                 if (m_startWithChildTrees)
01096                     siblingCount += q->sourceModel()->rowCount(*rootIt);
01097             } else {
01098                 if (rootStartRemove != -1)
01099                     break;
01100             }
01101         }
01102     }
01103     if (rootStartRemove != -1) {
01104         return qMakePair(siblingCount + rootStartRemove, siblingCount + rootEndRemove);
01105     }
01106 
01107     return qMakePair(-1, -1);
01108 }
01109 
01110 void KSelectionProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
01111 {
01112     Q_Q(KSelectionProxyModel);
01113 
01114     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
01115 
01116     if (!m_selectionModel.data()->hasSelection())
01117         return;
01118 
01119     QPair<int, int> pair = beginRemoveRows(parent, start, end);
01120     if (pair.first == -1)
01121         return;
01122 
01123     const QModelIndex proxyParent = mapParentFromSource(parent);
01124 
01125     m_rowsRemoved = true;
01126     m_proxyRemoveRows = pair;
01127     q->beginRemoveRows(proxyParent, pair.first, pair.second);
01128 }
01129 
01130 void KSelectionProxyModelPrivate::endRemoveRows(const QModelIndex &sourceParent, int proxyStart, int proxyEnd)
01131 {
01132     const QModelIndex proxyParent = mapParentFromSource(sourceParent);
01133 
01134     // We need to make sure to remove entries from the mappings before updating internal indexes.
01135 
01136     // - A
01137     // - - B
01138     // - C
01139     // - - D
01140 
01141     // If A and C are selected, B and D are in the proxy. B maps to row 0 and D maps to row 1.
01142     // If B is then deleted leaving only D in the proxy, D needs to be updated to be a mapping
01143     // to row 0 instead of row 1. If that is done before removing the mapping for B, then the mapping
01144     // for D would overwrite the mapping for B and then the code for removing mappings would incorrectly
01145     // remove D.
01146     // So we first remove B and then update D.
01147 
01148     {
01149         SourceProxyIndexMapping::right_iterator it = m_mappedParents.rightBegin();
01150 
01151         while (it != m_mappedParents.rightEnd()) {
01152             if (!it.value().isValid()) {
01153                 m_parentIds.removeRight(it.key());
01154                 it = m_mappedParents.eraseRight(it);
01155             } else
01156                 ++it;
01157         }
01158     }
01159 
01160     {
01161         // Depending on what is selected at the time, a single removal in the source could invalidate
01162         // many mapped first child items at once.
01163 
01164         // - A
01165         // - B
01166         // - - C
01167         // - - D
01168         // - - - E
01169         // - - - F
01170         // - - - - G
01171         // - - - - H
01172 
01173         // If D and F are selected, the proxy contains E, F, G, H. If B is then deleted E to H will
01174         // be removed, including both first child mappings at E and G.
01175 
01176         removeFirstChildMappings(proxyStart, proxyEnd);
01177     }
01178 
01179     if (proxyParent.isValid())
01180         updateInternalIndexes(proxyParent, proxyEnd + 1, -1*(proxyEnd - proxyStart + 1));
01181     else
01182         updateInternalTopIndexes(proxyEnd + 1, -1*(proxyEnd - proxyStart + 1));
01183 
01184     QList<QPersistentModelIndex>::iterator rootIt = m_rootIndexList.begin();
01185     while (rootIt != m_rootIndexList.end()) {
01186         if (!rootIt->isValid())
01187             rootIt = m_rootIndexList.erase(rootIt);
01188         else
01189             ++rootIt;
01190     }
01191 }
01192 
01193 void KSelectionProxyModelPrivate::sourceRowsRemoved(const QModelIndex &parent, int start, int end)
01194 {
01195     Q_Q(KSelectionProxyModel);
01196     Q_UNUSED(end)
01197 
01198     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
01199 
01200     if (!m_selectionModel.data()->hasSelection())
01201         return;
01202 
01203     if (!m_rowsRemoved)
01204         return;
01205     m_rowsRemoved = false;
01206 
01207     Q_ASSERT(m_proxyRemoveRows.first >= 0);
01208     Q_ASSERT(m_proxyRemoveRows.second >= 0);
01209     endRemoveRows(parent, m_proxyRemoveRows.first, m_proxyRemoveRows.second);
01210     if (m_startWithChildTrees && start == 0 && q->sourceModel()->hasChildren(parent))
01211         // The private endRemoveRows call might remove the first child mapping for parent, so
01212         // we create it again in that case.
01213         createFirstChildMapping(parent, m_proxyRemoveRows.first);
01214 
01215     m_proxyRemoveRows = qMakePair(-1, -1);
01216     q->endRemoveRows();
01217 }
01218 
01219 void KSelectionProxyModelPrivate::sourceRowsAboutToBeMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow)
01220 {
01221   Q_UNUSED(srcParent)
01222   Q_UNUSED(srcStart)
01223   Q_UNUSED(srcEnd)
01224   Q_UNUSED(destParent)
01225   Q_UNUSED(destRow)
01226 }
01227 
01228 void KSelectionProxyModelPrivate::sourceRowsMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow)
01229 {
01230   Q_UNUSED(srcParent)
01231   Q_UNUSED(srcStart)
01232   Q_UNUSED(srcEnd)
01233   Q_UNUSED(destParent)
01234   Q_UNUSED(destRow)
01235 }
01236 
01237 QModelIndex KSelectionProxyModelPrivate::mapParentToSource(const QModelIndex &proxyParent) const
01238 {
01239     return m_mappedParents.rightToLeft(proxyParent);
01240 }
01241 
01242 QModelIndex KSelectionProxyModelPrivate::mapParentFromSource(const QModelIndex &sourceParent) const
01243 {
01244     return m_mappedParents.leftToRight(sourceParent);
01245 }
01246 
01247 static bool indexIsValid(bool startWithChildTrees, int row, const QList<QPersistentModelIndex> &rootIndexList, const SourceIndexProxyRowMapping &mappedFirstChildren)
01248 {
01249     if (!startWithChildTrees) {
01250         Q_ASSERT(rootIndexList.size() > row);
01251         Q_UNUSED(rootIndexList);
01252     } else {
01253 
01254         Q_ASSERT(!mappedFirstChildren.isEmpty());
01255 
01256         SourceIndexProxyRowMapping::right_const_iterator result = mappedFirstChildren.rightUpperBound(row) - 1;
01257 
01258         Q_ASSERT(result != mappedFirstChildren.rightEnd());
01259         const int proxyFirstRow = result.key();
01260         const QModelIndex sourceFirstChild = result.value();
01261         Q_ASSERT(proxyFirstRow >= 0);
01262         Q_ASSERT(sourceFirstChild.isValid());
01263         Q_ASSERT(sourceFirstChild.parent().isValid());
01264         Q_ASSERT(row <= proxyFirstRow + sourceFirstChild.model()->rowCount(sourceFirstChild.parent()));
01265     }
01266     return true;
01267 }
01268 
01269 QModelIndex KSelectionProxyModelPrivate::createTopLevelIndex(int row, int column) const
01270 {
01271     Q_Q(const KSelectionProxyModel);
01272 
01273     Q_ASSERT(indexIsValid(m_startWithChildTrees, row, m_rootIndexList, m_mappedFirstChildren));
01274     return q->createIndex(row, column);
01275 }
01276 
01277 
01278 QModelIndex KSelectionProxyModelPrivate::mapTopLevelFromSource(const QModelIndex &sourceIndex) const
01279 {
01280     Q_Q(const KSelectionProxyModel);
01281 
01282     const QModelIndex sourceParent = sourceIndex.parent();
01283     const int row = m_rootIndexList.indexOf(sourceIndex);
01284     if (row == -1)
01285         return QModelIndex();
01286 
01287     if (!m_startWithChildTrees) {
01288         Q_ASSERT(m_rootIndexList.size() > row);
01289         return q->createIndex(row, sourceIndex.column());
01290     }
01291     if (!m_rootIndexList.contains(sourceParent))
01292         return QModelIndex();
01293 
01294     const QModelIndex firstChild = q->sourceModel()->index(0, 0, sourceParent);
01295     const int firstProxyRow = m_mappedFirstChildren.leftToRight(firstChild);
01296 
01297     return q->createIndex(firstProxyRow + sourceIndex.row(), sourceIndex.column());
01298 }
01299 
01300 QModelIndex KSelectionProxyModelPrivate::mapFromSource(const QModelIndex &sourceIndex) const
01301 {
01302     Q_Q(const KSelectionProxyModel);
01303 
01304     const QModelIndex maybeMapped = mapParentFromSource(sourceIndex);
01305     if (maybeMapped.isValid()) {
01306 //     Q_ASSERT((!d->m_startWithChildTrees && d->m_rootIndexList.contains(maybeMapped)) ? maybeMapped.row() < 0 : true );
01307         return maybeMapped;
01308     }
01309     const QModelIndex sourceParent = sourceIndex.parent();
01310 
01311     const QModelIndex proxyParent = mapParentFromSource(sourceParent);
01312     if (proxyParent.isValid()) {
01313         void * const parentId = m_parentIds.rightToLeft(proxyParent);
01314         static const int column = 0;
01315         return q->createIndex(sourceIndex.row(), column, parentId);
01316     }
01317 
01318     const QModelIndex firstChild = q->sourceModel()->index(0, 0, sourceParent);
01319 
01320     if (m_mappedFirstChildren.leftContains(firstChild))
01321     {
01322         const int firstProxyRow = m_mappedFirstChildren.leftToRight(firstChild);
01323         return q->createIndex(firstProxyRow + sourceIndex.row(), sourceIndex.column());
01324     }
01325     return mapTopLevelFromSource(sourceIndex);
01326 }
01327 
01328 int KSelectionProxyModelPrivate::topLevelRowCount() const
01329 {
01330     Q_Q(const KSelectionProxyModel);
01331 
01332     if (!m_startWithChildTrees)
01333         return m_rootIndexList.size();
01334 
01335     if (m_mappedFirstChildren.isEmpty())
01336       return 0;
01337 
01338     const SourceIndexProxyRowMapping::right_const_iterator result = m_mappedFirstChildren.rightConstEnd() - 1;
01339 
01340     const int proxyFirstRow = result.key();
01341     const QModelIndex sourceFirstChild = result.value();
01342     Q_ASSERT(sourceFirstChild.isValid());
01343     const QModelIndex sourceParent = sourceFirstChild.parent();
01344     Q_ASSERT(sourceParent.isValid());
01345     return q->sourceModel()->rowCount(sourceParent) + proxyFirstRow;
01346 }
01347 
01348 bool KSelectionProxyModelPrivate::ensureMappable(const QModelIndex &parent) const
01349 {
01350     Q_Q(const KSelectionProxyModel);
01351 
01352     if (isFlat())
01353         return true;
01354 
01355     if (parentIsMappable(parent))
01356         return true;
01357 
01358     QModelIndex ancestor = parent.parent();
01359     QModelIndexList ancestorList;
01360     while (ancestor.isValid())
01361     {
01362         if (parentIsMappable(ancestor))
01363             break;
01364         else
01365             ancestorList.prepend(ancestor);
01366 
01367         ancestor = ancestor.parent();
01368     }
01369 
01370     if (!ancestor.isValid())
01371         // @p parent is not a descendant of m_rootIndexList.
01372         return false;
01373 
01374     // sourceIndex can be mapped to the proxy. We just need to create mappings for its ancestors first.
01375     for(int i = 0; i < ancestorList.size(); ++i)
01376     {
01377         const QModelIndex existingAncestor = mapParentFromSource(ancestor);
01378         Q_ASSERT(existingAncestor.isValid());
01379 
01380         void * const ansId = m_parentIds.rightToLeft(existingAncestor);
01381         const QModelIndex newSourceParent = ancestorList.at(i);
01382         const QModelIndex newProxyParent = q->createIndex(newSourceParent.row(), newSourceParent.column(), ansId);
01383 
01384         void * const newId = m_voidPointerFactory.createPointer();
01385         m_parentIds.insert(newId, newProxyParent);
01386         m_mappedParents.insert(QPersistentModelIndex(newSourceParent), newProxyParent);
01387         ancestor = newSourceParent;
01388     }
01389     return true;
01390 }
01391 
01392 void KSelectionProxyModelPrivate::updateInternalTopIndexes(int start, int offset)
01393 {
01394     updateInternalIndexes(QModelIndex(), start, offset);
01395 
01396     QHash<QPersistentModelIndex, int> updates;
01397     {
01398         SourceIndexProxyRowMapping::right_iterator it = m_mappedFirstChildren.rightLowerBound(start);
01399         const SourceIndexProxyRowMapping::right_iterator end = m_mappedFirstChildren.rightEnd();
01400 
01401         for ( ; it != end; ++it)
01402         {
01403             updates.insert(*it, it.key() + offset);
01404         }
01405     }
01406     {
01407         QHash<QPersistentModelIndex, int>::const_iterator it = updates.constBegin();
01408         const QHash<QPersistentModelIndex, int>::const_iterator end = updates.constEnd();
01409 
01410         for ( ; it != end; ++it)
01411         {
01412             m_mappedFirstChildren.insert(it.key(), it.value());
01413         }
01414     }
01415 }
01416 
01417 void KSelectionProxyModelPrivate::updateInternalIndexes(const QModelIndex &parent, int start, int offset)
01418 {
01419     Q_Q(KSelectionProxyModel);
01420 
01421     Q_ASSERT(start + offset >= 0);
01422     Q_ASSERT(parent.isValid() ? parent.model() == q : true);
01423 
01424     if (isFlat())
01425         return;
01426 
01427     SourceProxyIndexMapping::left_iterator mappedParentIt = m_mappedParents.leftBegin();
01428 
01429     QHash<void*, QModelIndex> updatedParentIds;
01430     QHash<QPersistentModelIndex, QModelIndex> updatedParents;
01431 
01432     for ( ; mappedParentIt != m_mappedParents.leftEnd(); ++mappedParentIt) {
01433         const QModelIndex proxyIndex = mappedParentIt.value();
01434         Q_ASSERT(proxyIndex.isValid());
01435 
01436         if (proxyIndex.row() < start)
01437             continue;
01438 
01439         const QModelIndex proxyParent = proxyIndex.parent();
01440 
01441         if (parent.isValid()) {
01442             if (proxyParent != parent)
01443                 continue;
01444         } else {
01445             if (proxyParent.isValid())
01446                 continue;
01447         }
01448         Q_ASSERT(m_parentIds.rightContains(proxyIndex));
01449         void * const key = m_parentIds.rightToLeft(proxyIndex);
01450 
01451         const QModelIndex newIndex = q->createIndex(proxyIndex.row() + offset, proxyIndex.column(), proxyIndex.internalPointer());
01452 
01453         Q_ASSERT(newIndex.isValid());
01454 
01455         updatedParentIds.insert(key, newIndex);
01456         updatedParents.insert(mappedParentIt.key(), newIndex);
01457     }
01458 
01459     {
01460         QHash<QPersistentModelIndex, QModelIndex>::const_iterator it = updatedParents.constBegin();
01461         const QHash<QPersistentModelIndex, QModelIndex>::const_iterator end = updatedParents.constEnd();
01462         for ( ; it != end; ++it)
01463             m_mappedParents.insert(it.key(), it.value());
01464     }
01465 
01466     {
01467         QHash<void*, QModelIndex>::const_iterator it = updatedParentIds.constBegin();
01468         const QHash<void*, QModelIndex>::const_iterator end = updatedParentIds.constEnd();
01469         for ( ; it != end; ++it)
01470             m_parentIds.insert(it.key(), it.value());
01471     }
01472 }
01473 
01474 bool KSelectionProxyModelPrivate::parentAlreadyMapped(const QModelIndex &parent) const
01475 {
01476     Q_Q(const KSelectionProxyModel);
01477     Q_ASSERT(parent.model() == q->sourceModel());
01478     return m_mappedParents.leftContains(parent);
01479 }
01480 
01481 bool KSelectionProxyModelPrivate::firstChildAlreadyMapped(const QModelIndex &firstChild) const
01482 {
01483     Q_Q(const KSelectionProxyModel);
01484     Q_ASSERT(firstChild.model() == q->sourceModel());
01485     return m_mappedFirstChildren.leftContains(firstChild);
01486 }
01487 
01488 void KSelectionProxyModelPrivate::createFirstChildMapping(const QModelIndex& parent, int proxyRow) const
01489 {
01490     Q_Q(const KSelectionProxyModel);
01491 
01492     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
01493 
01494     static const int column = 0;
01495     static const int row = 0;
01496 
01497     const QPersistentModelIndex srcIndex = q->sourceModel()->index(row, column, parent);
01498 
01499     if (firstChildAlreadyMapped(srcIndex))
01500         return;
01501 
01502     Q_ASSERT(srcIndex.isValid());
01503     m_mappedFirstChildren.insert(srcIndex, proxyRow);
01504 }
01505 
01506 void KSelectionProxyModelPrivate::createParentMappings(const QModelIndex &parent, int start, int end) const
01507 {
01508     if (isFlat())
01509         return;
01510 
01511     Q_Q(const KSelectionProxyModel);
01512 
01513     Q_ASSERT(parent.isValid() ? parent.model() == q->sourceModel() : true);
01514 
01515     static const int column = 0;
01516 
01517     for (int row = start; row <= end; ++row) {
01518         const QModelIndex srcIndex = q->sourceModel()->index(row, column, parent);
01519         Q_ASSERT(srcIndex.isValid());
01520         if (!q->sourceModel()->hasChildren(srcIndex) || parentAlreadyMapped(srcIndex))
01521             continue;
01522 
01523         const QModelIndex proxyIndex = mapFromSource(srcIndex);
01524         if (!proxyIndex.isValid())
01525             return; // If one of them is not mapped, its siblings won't be either
01526 
01527         void * const newId = m_voidPointerFactory.createPointer();
01528         m_parentIds.insert(newId, proxyIndex);
01529         Q_ASSERT(srcIndex.isValid());
01530         m_mappedParents.insert(QPersistentModelIndex(srcIndex), proxyIndex);
01531     }
01532 }
01533 
01534 void KSelectionProxyModelPrivate::removeFirstChildMappings(int start, int end)
01535 {
01536     SourceIndexProxyRowMapping::right_iterator it = m_mappedFirstChildren.rightLowerBound(start);
01537     const SourceIndexProxyRowMapping::right_iterator endIt = m_mappedFirstChildren.rightUpperBound(end);
01538     while (it != endIt)
01539       it = m_mappedFirstChildren.eraseRight(it);
01540 }
01541 
01542 void KSelectionProxyModelPrivate::removeParentMappings(const QModelIndex &parent, int start, int end)
01543 {
01544     Q_Q(KSelectionProxyModel);
01545 
01546     Q_ASSERT(parent.isValid() ? parent.model() == q : true);
01547 
01548     SourceProxyIndexMapping::right_iterator it = m_mappedParents.rightBegin();
01549     SourceProxyIndexMapping::right_iterator endIt = m_mappedParents.rightEnd();
01550 
01551     typedef QPair<QModelIndex, QPersistentModelIndex> Pair;
01552 
01553     QList<Pair> pairs;
01554 
01555     QModelIndexList list;
01556 
01557     const bool flatList = isFlat();
01558 
01559     while (it != endIt) {
01560         if (it.key().row() >= start && it.key().row() <= end)
01561         {
01562             const QModelIndex sourceParent = it.value();
01563             const QModelIndex proxyGrandParent = mapParentFromSource(sourceParent.parent());
01564             if (proxyGrandParent == parent)
01565             {
01566                 if (!flatList)
01567                     // Due to recursive calls, we could have several iterators on the container
01568                     // when erase is called. That's safe accoring to the QHash::iterator docs though.
01569                     removeParentMappings(it.key(), 0, q->sourceModel()->rowCount(it.value()) - 1);
01570 
01571                 m_parentIds.removeRight(it.key());
01572                 it = m_mappedParents.eraseRight(it);
01573             } else
01574                ++it;
01575         } else
01576            ++it;
01577     }
01578 }
01579 
01580 QModelIndex KSelectionProxyModelPrivate::mapTopLevelToSource(int row, int column) const
01581 {
01582     if (!m_startWithChildTrees)
01583     {
01584         const QModelIndex idx = m_rootIndexList.at(row);
01585         return idx.sibling(idx.row(), column);
01586     }
01587 
01588     if (m_mappedFirstChildren.isEmpty())
01589       return QModelIndex();
01590 
01591     SourceIndexProxyRowMapping::right_iterator result = m_mappedFirstChildren.rightUpperBound(row) - 1;
01592 
01593     Q_ASSERT(result != m_mappedFirstChildren.rightEnd());
01594 
01595     const int proxyFirstRow = result.key();
01596     const QModelIndex sourceFirstChild = result.value();
01597     Q_ASSERT(sourceFirstChild.isValid());
01598     return sourceFirstChild.sibling(row - proxyFirstRow, column);
01599 }
01600 
01601 void KSelectionProxyModelPrivate::removeSelectionFromProxy(const QItemSelection &selection)
01602 {
01603     Q_Q(KSelectionProxyModel);
01604     if (selection.isEmpty())
01605         return;
01606 
01607     q->rootSelectionAboutToBeRemoved(selection);
01608 
01609     foreach(const QItemSelectionRange range, selection)
01610         removeRangeFromProxy(range);
01611 }
01612 
01613 void KSelectionProxyModelPrivate::removeRangeFromProxy(const QItemSelectionRange &range)
01614 {
01615     Q_Q(KSelectionProxyModel);
01616 
01617     Q_ASSERT(range.model() == q->sourceModel());
01618 
01619     const QModelIndex sourceTopLeft = range.topLeft();
01620     const QModelIndex proxyTopLeft = mapFromSource(sourceTopLeft);
01621     const QModelIndex sourceBottomLeft = range.bottomRight().sibling(range.bottom(), 0);
01622     const QModelIndex proxyBottomLeft = mapFromSource(sourceBottomLeft);
01623     const QModelIndex proxyParent = proxyTopLeft.parent();
01624     const QModelIndex sourceParent = sourceTopLeft.parent();
01625 
01626     if (m_startWithChildTrees) {
01627         Q_ASSERT(sourceTopLeft.isValid());
01628         Q_ASSERT(sourceBottomLeft.isValid());
01629         const int startRootIdx = m_rootIndexList.indexOf(sourceTopLeft);
01630         int endRootIdx = m_rootIndexList.indexOf(sourceBottomLeft);
01631         QItemSelection extraRanges;
01632         if (m_includeAllSelected) {
01633             // It can happen that indexes of descendants get in between indexes which make up a range.
01634             // We handle only the first contiguous block here and handle the rest later.
01635             int idx = startRootIdx;
01636             const int bottomIdx = endRootIdx;
01637             const int rootListSize = m_rootIndexList.size();
01638             int next = idx + 1;
01639             while (next <= bottomIdx)
01640             {
01641                 if (next < rootListSize && m_rootIndexList.at(next).parent() == sourceParent) {
01642                     idx = next;
01643                     ++next;
01644                 } else
01645                     break;
01646             }
01647             endRootIdx = idx;
01648             ++idx;
01649             while (idx <= bottomIdx)
01650             {
01651                 const QModelIndex index= m_rootIndexList.at(idx);
01652                 if (m_rootIndexList.at(idx).parent() == sourceParent)
01653                     extraRanges << QItemSelectionRange(index, index);
01654                 ++idx;
01655             }
01656         }
01657         Q_ASSERT(endRootIdx != -1);
01658         int childrenCount = q->sourceModel()->rowCount(sourceTopLeft);
01659         for (int rootIdx = startRootIdx + 1; rootIdx <= endRootIdx; ++rootIdx)
01660         {
01661             childrenCount += q->sourceModel()->rowCount(m_rootIndexList.at(rootIdx));
01662         }
01663         if (childrenCount == 0)
01664         {
01665             for (int rootIdx = startRootIdx; rootIdx <= endRootIdx; --endRootIdx)
01666             {
01667                 const QModelIndex idx = m_rootIndexList.at(rootIdx);
01668                 q->rootIndexAboutToBeRemoved(idx);
01669                 m_rootIndexList.removeOne(idx);
01670             }
01671             return;
01672         }
01673         if (!m_includeAllSelected)
01674         {
01675             ++endRootIdx;
01676             for ( ; endRootIdx < m_rootIndexList.size(); ++endRootIdx) {
01677                 const QModelIndex idx = m_rootIndexList.at(endRootIdx);
01678                 if (isDescendantOf(sourceBottomLeft, idx))
01679                     childrenCount += q->sourceModel()->rowCount(idx);
01680                 else
01681                     break;
01682             }
01683             --endRootIdx;
01684         }
01685         const int proxyStart = getTargetRow(startRootIdx);
01686         int proxyEnd = proxyStart + childrenCount - 1;
01687         q->beginRemoveRows(QModelIndex(), proxyStart, proxyEnd);
01688 
01689         for (int rootIdx = startRootIdx; rootIdx <= endRootIdx; ++rootIdx)
01690         {
01691             q->rootIndexAboutToBeRemoved(m_rootIndexList.at(rootIdx));
01692         }
01693 
01694         removeParentMappings(QModelIndex(), proxyStart, proxyEnd);
01695         removeFirstChildMappings(proxyStart, proxyEnd);
01696         int numRemovedChildren = 0;
01697         for (int rootIdx = startRootIdx; rootIdx <= endRootIdx; --endRootIdx)
01698         {
01699           const QModelIndex idx = m_rootIndexList.at(rootIdx);
01700           const int childCount = q->sourceModel()->rowCount(idx);
01701           m_rootIndexList.removeAt(rootIdx);
01702           numRemovedChildren += childCount;
01703         }
01704         updateInternalTopIndexes(proxyEnd + 1, -1 * numRemovedChildren);
01705         q->endRemoveRows();
01706         if (m_includeAllSelected) {
01707             removeSelectionFromProxy(kNormalizeSelection(extraRanges));
01708         }
01709     } else {
01710         if (!proxyTopLeft.isValid())
01711             return;
01712         const int height = range.height();
01713         q->beginRemoveRows(proxyParent, proxyTopLeft.row(), proxyTopLeft.row() + height - 1);
01714 
01715         // TODO: Do this conditionally if the signal is connected to anything.
01716         for (int i = 0; i < height; ++i)
01717         {
01718             const QModelIndex idx = sourceTopLeft.sibling(range.top() + i, sourceTopLeft.column());
01719             q->rootIndexAboutToBeRemoved(idx);
01720         }
01721 
01722         removeParentMappings(proxyParent, proxyTopLeft.row(), proxyTopLeft.row() + height - 1);
01723         updateInternalIndexes(proxyParent, proxyTopLeft.row() + height, -1 * height);
01724 
01725         for (int i = 0; i < height; ++i)
01726         {
01727             const QModelIndex idx = sourceTopLeft.sibling(range.top() + i, sourceTopLeft.column());
01728             Q_ASSERT(idx.isValid());
01729             const bool b = m_rootIndexList.removeOne(idx);
01730             Q_UNUSED(b)
01731             if (!b)
01732               kDebug() << idx;
01733             Q_ASSERT(b);
01734         }
01735 
01736         q->endRemoveRows();
01737     }
01738 }
01739 
01740 void KSelectionProxyModelPrivate::selectionChanged(const QItemSelection &_selected, const QItemSelection &_deselected)
01741 {
01742     Q_Q(KSelectionProxyModel);
01743 
01744     if (!q->sourceModel() || (_selected.isEmpty() && _deselected.isEmpty()))
01745         return;
01746 
01747     if (m_rowsInserted || m_rowsRemoved) {
01748         m_pendingSelectionChanges.append(PendingSelectionChange(_selected, _deselected));
01749         return;
01750     }
01751 
01752     // Any deselected indexes in the m_rootIndexList are removed. Then, any
01753     // indexes in the selected range which are not a descendant of one of the already selected indexes
01754     // are inserted into the model.
01755     //
01756     // All ranges from the selection model need to be split into individual rows. Ranges which are contiguous in
01757     // the selection model may not be contiguous in the source model if there's a sort filter proxy model in the chain.
01758     //
01759     // Some descendants of deselected indexes may still be selected. The ranges in m_selectionModel.data()->selection()
01760     // are examined. If any of the ranges are descendants of one of the
01761     // indexes in deselected, they are added to the ranges to be inserted into the model.
01762     //
01763     // The new indexes are inserted in sorted order.
01764 
01765     const QItemSelection selected = kNormalizeSelection(m_indexMapper->mapSelectionRightToLeft(_selected));
01766     const QItemSelection deselected = kNormalizeSelection(m_indexMapper->mapSelectionRightToLeft(_deselected));
01767 
01768 #if QT_VERSION < 0x040800
01769     // The QItemSelectionModel sometimes doesn't remove deselected items from its selection
01770     // Fixed in Qt 4.8 : http://qt.gitorious.org/qt/qt/merge_requests/2403
01771     QItemSelection reportedSelection = m_selectionModel.data()->selection();
01772     reportedSelection.merge(deselected, QItemSelectionModel::Deselect);
01773     QItemSelection fullSelection = m_indexMapper->mapSelectionRightToLeft(reportedSelection);
01774 #else
01775     QItemSelection fullSelection = m_indexMapper->mapSelectionRightToLeft(m_selectionModel.data()->selection());
01776 #endif
01777 
01778     fullSelection = kNormalizeSelection(fullSelection);
01779 
01780     QItemSelection newRootRanges;
01781     QItemSelection removedRootRanges;
01782     if (!m_includeAllSelected) {
01783         newRootRanges = getRootRanges(selected);
01784 
01785         QItemSelection existingSelection = fullSelection;
01786         // What was selected before the selection was made.
01787         existingSelection.merge(selected, QItemSelectionModel::Deselect);
01788 
01789         // This is similar to m_rootRanges, but that m_rootRanges at this point still contains the roots
01790         // of deselected and existingRootRanges does not.
01791 
01792         const QItemSelection existingRootRanges = getRootRanges(existingSelection);
01793         {
01794             QMutableListIterator<QItemSelectionRange> i(newRootRanges);
01795             while (i.hasNext()) {
01796                 const QItemSelectionRange range = i.next();
01797                 const QModelIndex topLeft = range.topLeft();
01798                 if (isDescendantOf(existingRootRanges, topLeft)) {
01799                     i.remove();
01800                 }
01801             }
01802         }
01803 
01804         QItemSelection exposedSelection;
01805         {
01806             QItemSelection deselectedRootRanges = getRootRanges(deselected);
01807             QListIterator<QItemSelectionRange> i(deselectedRootRanges);
01808             while (i.hasNext()) {
01809                 const QItemSelectionRange range = i.next();
01810                 const QModelIndex topLeft = range.topLeft();
01811                 // Consider this:
01812                 //
01813                 // - A
01814                 // - - B
01815                 // - - - C
01816                 // - - - - D
01817                 //
01818                 // B and D were selected, then B was deselected and C was selected in one go.
01819                 if (!isDescendantOf(existingRootRanges, topLeft)) {
01820                     // B is topLeft and fullSelection contains D.
01821                     // B is not a descendant of D.
01822 
01823                     // range is not a descendant of the selection, but maybe the selection is a descendant of range.
01824                     // no need to check selected here. That's already in newRootRanges.
01825                     // existingRootRanges and newRootRanges do not overlap.
01826                     foreach (const QItemSelectionRange &selectedRange, existingRootRanges) {
01827                         const QModelIndex selectedRangeTopLeft = selectedRange.topLeft();
01828                         // existingSelection (and selectedRangeTopLeft) is D.
01829                         // D is a descendant of B, so when B was removed, D might have been exposed as a root.
01830                         if (isDescendantOf(range, selectedRangeTopLeft)
01831                                 // But D is also a descendant of part of the new selection C, which is already set to be a new root
01832                                 // so D would not be added to exposedSelection because C is in newRootRanges.
01833                                 && !isDescendantOf(newRootRanges, selectedRangeTopLeft))
01834                             exposedSelection.append(selectedRange);
01835                     }
01836                     removedRootRanges << range;
01837                 }
01838             }
01839         }
01840 
01841         QItemSelection obscuredRanges;
01842         {
01843             QListIterator<QItemSelectionRange> i(existingRootRanges);
01844             while (i.hasNext()) {
01845                 const QItemSelectionRange range = i.next();
01846                 if (isDescendantOf(newRootRanges, range.topLeft()))
01847                     obscuredRanges << range;
01848             }
01849         }
01850         removedRootRanges << getRootRanges(obscuredRanges);
01851         newRootRanges << getRootRanges(exposedSelection);
01852 
01853         removedRootRanges = kNormalizeSelection(removedRootRanges);
01854         newRootRanges = kNormalizeSelection(newRootRanges);
01855     } else {
01856         removedRootRanges = deselected;
01857         newRootRanges = selected;
01858     }
01859 
01860     removeSelectionFromProxy(removedRootRanges);
01861 
01862     if (!m_selectionModel.data()->hasSelection())
01863     {
01864         Q_ASSERT(m_rootIndexList.isEmpty());
01865         Q_ASSERT(m_mappedFirstChildren.isEmpty());
01866         Q_ASSERT(m_mappedParents.isEmpty());
01867         Q_ASSERT(m_parentIds.isEmpty());
01868     }
01869 
01870     insertSelectionIntoProxy(newRootRanges);
01871 }
01872 
01873 int KSelectionProxyModelPrivate::getTargetRow(int rootListRow)
01874 {
01875     Q_Q(KSelectionProxyModel);
01876     if (!m_startWithChildTrees)
01877         return rootListRow;
01878 
01879     --rootListRow;
01880     while (rootListRow >= 0) {
01881         const QModelIndex idx = m_rootIndexList.at(rootListRow);
01882         Q_ASSERT(idx.isValid());
01883         const int rowCount = q->sourceModel()->rowCount(idx);
01884         if (rowCount > 0) {
01885             static const int column = 0;
01886             const QModelIndex srcIdx = q->sourceModel()->index(rowCount - 1, column, idx);
01887             const QModelIndex proxyLastChild = mapFromSource(srcIdx);
01888             return proxyLastChild.row() + 1;
01889         }
01890         --rootListRow;
01891     }
01892     return 0;
01893 }
01894 
01895 void KSelectionProxyModelPrivate::insertSelectionIntoProxy(const QItemSelection &selection)
01896 {
01897     Q_Q(KSelectionProxyModel);
01898 
01899     if (selection.isEmpty())
01900         return;
01901 
01902     foreach(const QModelIndex &newIndex, selection.indexes()) {
01903         Q_ASSERT(newIndex.model() == q->sourceModel());
01904         if (newIndex.column() > 0)
01905             continue;
01906         if (m_startWithChildTrees) {
01907             const int rootListRow = getRootListRow(m_rootIndexList, newIndex);
01908             Q_ASSERT(q->sourceModel() == newIndex.model());
01909             const int rowCount = q->sourceModel()->rowCount(newIndex);
01910             const int startRow = getTargetRow(rootListRow);
01911 
01912             if (rowCount == 0) {
01913                 // Even if the newindex doesn't have any children to put into the model yet,
01914                 // We still need to make sure it's future children are inserted into the model.
01915                 m_rootIndexList.insert(rootListRow, newIndex);
01916                 if (!m_resetting || m_layoutChanging)
01917                     emit q->rootIndexAdded(newIndex);
01918                 continue;
01919             }
01920             if (!m_resetting)
01921                 q->beginInsertRows(QModelIndex(), startRow, startRow + rowCount - 1);
01922             Q_ASSERT(newIndex.isValid());
01923             m_rootIndexList.insert(rootListRow, newIndex);
01924             if (!m_resetting || m_layoutChanging)
01925                 emit q->rootIndexAdded(newIndex);
01926 
01927             int _start = 0;
01928             for (int i = 0; i < rootListRow; ++i)
01929                 _start += q->sourceModel()->rowCount(m_rootIndexList.at(i));
01930 
01931             updateInternalTopIndexes(_start, rowCount);
01932             createFirstChildMapping(newIndex, _start);
01933             createParentMappings(newIndex, 0, rowCount - 1);
01934 
01935             if (!m_resetting) {
01936                 q->endInsertRows();
01937             }
01938 
01939         } else {
01940             const int row = getRootListRow(m_rootIndexList, newIndex);
01941             if (!m_resetting)
01942                 q->beginInsertRows(QModelIndex(), row, row);
01943 
01944             Q_ASSERT(newIndex.isValid());
01945             m_rootIndexList.insert(row, newIndex);
01946 
01947             if (!m_resetting || m_layoutChanging)
01948                 emit q->rootIndexAdded(newIndex);
01949             Q_ASSERT(m_rootIndexList.size() > row);
01950             updateInternalIndexes(QModelIndex(), row, 1);
01951             createParentMappings(newIndex.parent(), newIndex.row(), newIndex.row());
01952 
01953             if (!m_resetting) {
01954                 q->endInsertRows();
01955             }
01956         }
01957     }
01958     q->rootSelectionAdded(selection);
01959 }
01960 
01961 KSelectionProxyModel::KSelectionProxyModel(QItemSelectionModel *selectionModel, QObject *parent)
01962         : QAbstractProxyModel(parent), d_ptr(new KSelectionProxyModelPrivate(this, selectionModel))
01963 {
01964 }
01965 
01966 KSelectionProxyModel::~KSelectionProxyModel()
01967 {
01968     delete d_ptr;
01969 }
01970 
01971 void KSelectionProxyModel::setFilterBehavior(FilterBehavior behavior)
01972 {
01973     Q_D(KSelectionProxyModel);
01974 
01975     beginResetModel();
01976 
01977     d->m_filterBehavior = behavior;
01978 
01979     switch (behavior) {
01980     case SubTrees: {
01981         d->m_omitChildren = false;
01982         d->m_omitDescendants = false;
01983         d->m_startWithChildTrees = false;
01984         d->m_includeAllSelected = false;
01985         break;
01986     }
01987     case SubTreeRoots: {
01988         d->m_omitChildren = true;
01989         d->m_startWithChildTrees = false;
01990         d->m_includeAllSelected = false;
01991         break;
01992     }
01993     case SubTreesWithoutRoots: {
01994         d->m_omitChildren = false;
01995         d->m_omitDescendants = false;
01996         d->m_startWithChildTrees = true;
01997         d->m_includeAllSelected = false;
01998         break;
01999     }
02000     case ExactSelection: {
02001         d->m_omitChildren = true;
02002         d->m_startWithChildTrees = false;
02003         d->m_includeAllSelected = true;
02004         break;
02005     }
02006     case ChildrenOfExactSelection: {
02007         d->m_omitChildren = false;
02008         d->m_omitDescendants = true;
02009         d->m_startWithChildTrees = true;
02010         d->m_includeAllSelected = true;
02011         break;
02012     }
02013     }
02014     d->resetInternalData();
02015     d->selectionChanged(d->m_selectionModel.data()->selection(), QItemSelection());
02016 
02017     endResetModel();
02018 }
02019 
02020 KSelectionProxyModel::FilterBehavior KSelectionProxyModel::filterBehavior() const
02021 {
02022     Q_D(const KSelectionProxyModel);
02023     return d->m_filterBehavior;
02024 }
02025 
02026 void KSelectionProxyModel::setSourceModel(QAbstractItemModel *_sourceModel)
02027 {
02028     Q_D(KSelectionProxyModel);
02029 
02030     Q_ASSERT(_sourceModel != this);
02031 
02032     if (_sourceModel == sourceModel())
02033         return;
02034 
02035     disconnect(d->m_selectionModel.data()->model(), SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()));
02036     connect(d->m_selectionModel.data()->model(), SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()));
02037     disconnect(d->m_selectionModel.data()->model(), SIGNAL(modelReset()), this, SLOT(sourceModelReset()));
02038     connect(d->m_selectionModel.data()->model(), SIGNAL(modelReset()), this, SLOT(sourceModelReset()));
02039 
02040     disconnect(d->m_selectionModel.data(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
02041             this, SLOT(selectionChanged(const QItemSelection &, const QItemSelection &)));
02042     connect(d->m_selectionModel.data(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
02043             SLOT(selectionChanged(const QItemSelection &, const QItemSelection &)));
02044 
02045     beginResetModel();
02046     d->m_resetting = true;
02047 
02048     if (_sourceModel) {
02049         disconnect(_sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
02050                    this, SLOT(sourceRowsAboutToBeInserted(const QModelIndex &, int, int)));
02051         disconnect(_sourceModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
02052                    this, SLOT(sourceRowsInserted(const QModelIndex &, int, int)));
02053         disconnect(_sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
02054                    this, SLOT(sourceRowsAboutToBeRemoved(const QModelIndex &, int, int)));
02055         disconnect(_sourceModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
02056                    this, SLOT(sourceRowsRemoved(const QModelIndex &, int, int)));
02057 //     disconnect(_sourceModel, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
02058 //             this, SLOT(sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
02059 //     disconnect(_sourceModel, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
02060 //             this, SLOT(sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
02061         disconnect(_sourceModel, SIGNAL(modelAboutToBeReset()),
02062                    this, SLOT(sourceModelAboutToBeReset()));
02063         disconnect(_sourceModel, SIGNAL(modelReset()),
02064                    this, SLOT(sourceModelReset()));
02065         disconnect(_sourceModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
02066                    this, SLOT(sourceDataChanged(const QModelIndex &, const QModelIndex &)));
02067         disconnect(_sourceModel, SIGNAL(layoutAboutToBeChanged()),
02068                    this, SLOT(sourceLayoutAboutToBeChanged()));
02069         disconnect(_sourceModel, SIGNAL(layoutChanged()),
02070                    this, SLOT(sourceLayoutChanged()));
02071         disconnect(_sourceModel, SIGNAL(destroyed()),
02072                    this, SLOT(sourceModelDestroyed()));
02073     }
02074 
02075     // Must be called before QAbstractProxyModel::setSourceModel because it emits some signals.
02076     d->resetInternalData();
02077     QAbstractProxyModel::setSourceModel(_sourceModel);
02078     if (_sourceModel) {
02079         d->m_indexMapper = new KModelIndexProxyMapper(_sourceModel, d->m_selectionModel.data()->model(), this);
02080         if (d->m_selectionModel.data()->hasSelection())
02081             d->selectionChanged(d->m_selectionModel.data()->selection(), QItemSelection());
02082 
02083         connect(_sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
02084                 SLOT(sourceRowsAboutToBeInserted(const QModelIndex &, int, int)));
02085         connect(_sourceModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
02086                 SLOT(sourceRowsInserted(const QModelIndex &, int, int)));
02087         connect(_sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
02088                 SLOT(sourceRowsAboutToBeRemoved(const QModelIndex &, int, int)));
02089         connect(_sourceModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
02090                 SLOT(sourceRowsRemoved(const QModelIndex &, int, int)));
02091 //     connect(_sourceModel, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
02092 //             SLOT(sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
02093 //     connect(_sourceModel, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
02094 //             SLOT(sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
02095         connect(_sourceModel, SIGNAL(modelAboutToBeReset()),
02096                 SLOT(sourceModelAboutToBeReset()));
02097         connect(_sourceModel, SIGNAL(modelReset()),
02098                 SLOT(sourceModelReset()));
02099         connect(_sourceModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
02100                 SLOT(sourceDataChanged(const QModelIndex &, const QModelIndex &)));
02101         connect(_sourceModel, SIGNAL(layoutAboutToBeChanged()),
02102                 SLOT(sourceLayoutAboutToBeChanged()));
02103         connect(_sourceModel, SIGNAL(layoutChanged()),
02104                 SLOT(sourceLayoutChanged()));
02105         connect(_sourceModel, SIGNAL(destroyed()),
02106                 SLOT(sourceModelDestroyed()));
02107     }
02108 
02109     d->m_resetting = false;
02110     endResetModel();
02111 }
02112 
02113 QModelIndex KSelectionProxyModel::mapToSource(const QModelIndex &proxyIndex) const
02114 {
02115     Q_D(const KSelectionProxyModel);
02116 
02117     if (!proxyIndex.isValid() || !sourceModel() || d->m_rootIndexList.isEmpty())
02118         return QModelIndex();
02119 
02120     Q_ASSERT(proxyIndex.internalPointer() >= 0);
02121     Q_ASSERT(proxyIndex.model() == this);
02122 
02123     if (proxyIndex.internalPointer() == 0)
02124         return d->mapTopLevelToSource(proxyIndex.row(), proxyIndex.column());
02125 
02126     const QModelIndex proxyParent = d->parentForId(proxyIndex.internalPointer());
02127     Q_ASSERT(proxyParent.isValid());
02128     const QModelIndex sourceParent = d->mapParentToSource(proxyParent);
02129     Q_ASSERT(sourceParent.isValid());
02130     return sourceModel()->index(proxyIndex.row(), proxyIndex.column(), sourceParent);
02131 }
02132 
02133 QModelIndex KSelectionProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
02134 {
02135     Q_D(const KSelectionProxyModel);
02136 
02137     if (!sourceModel() || !sourceIndex.isValid() || d->m_rootIndexList.isEmpty())
02138         return QModelIndex();
02139 
02140     Q_ASSERT(sourceIndex.model() == sourceModel());
02141 
02142     if (!sourceIndex.isValid())
02143         return QModelIndex();
02144 
02145     if (!d->ensureMappable(sourceIndex))
02146         return QModelIndex();
02147 
02148     return d->mapFromSource(sourceIndex);
02149 }
02150 
02151 int KSelectionProxyModel::rowCount(const QModelIndex &index) const
02152 {
02153     Q_D(const KSelectionProxyModel);
02154 
02155     if (!sourceModel() || index.column() > 0 || d->m_rootIndexList.isEmpty())
02156         return 0;
02157 
02158     Q_ASSERT(index.isValid() ? index.model() == this : true);
02159     if (!index.isValid())
02160         return d->topLevelRowCount();
02161 
02162     // index is valid
02163     if (d->isFlat())
02164         return 0;
02165 
02166     QModelIndex sourceParent = d->mapParentToSource(index);
02167 
02168     if (!sourceParent.isValid() && sourceModel()->hasChildren(sourceParent)) {
02169         sourceParent = mapToSource(index.parent());
02170         d->createParentMappings(sourceParent, 0, sourceModel()->rowCount(sourceParent) - 1);
02171         sourceParent = d->mapParentToSource(index);
02172     }
02173 
02174     if (!sourceParent.isValid())
02175         return 0;
02176 
02177     return sourceModel()->rowCount(sourceParent);
02178 }
02179 
02180 QModelIndex KSelectionProxyModel::index(int row, int column, const QModelIndex &parent) const
02181 {
02182     Q_D(const KSelectionProxyModel);
02183 
02184     if (!sourceModel() || d->m_rootIndexList.isEmpty() || !hasIndex(row, column, parent))
02185         return QModelIndex();
02186 
02187     Q_ASSERT(parent.isValid() ? parent.model() == this : true);
02188 
02189     if (!parent.isValid())
02190         return d->createTopLevelIndex(row, column);
02191 
02192     void * const parentId = d->parentId(parent);
02193     Q_ASSERT(parentId);
02194     return createIndex(row, column, parentId);
02195 }
02196 
02197 QModelIndex KSelectionProxyModel::parent(const QModelIndex &index) const
02198 {
02199     Q_D(const KSelectionProxyModel);
02200 
02201     if (!sourceModel() || !index.isValid() || d->m_rootIndexList.isEmpty())
02202         return QModelIndex();
02203 
02204     Q_ASSERT(index.model() == this);
02205 
02206     return d->parentForId(index.internalPointer());
02207 }
02208 
02209 Qt::ItemFlags KSelectionProxyModel::flags(const QModelIndex &index) const
02210 {
02211     if (!index.isValid() || !sourceModel())
02212         return QAbstractProxyModel::flags(index);
02213 
02214     Q_ASSERT(index.model() == this);
02215 
02216     const QModelIndex srcIndex = mapToSource(index);
02217     Q_ASSERT(srcIndex.isValid());
02218     return sourceModel()->flags(srcIndex);
02219 }
02220 
02221 QVariant KSelectionProxyModel::data(const QModelIndex & index, int role) const
02222 {
02223     if (!sourceModel())
02224         return QVariant();
02225 
02226     if (index.isValid()) {
02227         Q_ASSERT(index.model() == this);
02228         const QModelIndex idx = mapToSource(index);
02229         return idx.data(role);
02230     }
02231     return sourceModel()->data(index, role);
02232 }
02233 
02234 QVariant KSelectionProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
02235 {
02236     if (!sourceModel())
02237         return QVariant();
02238     return sourceModel()->headerData(section, orientation, role);
02239 }
02240 
02241 QMimeData* KSelectionProxyModel::mimeData(const QModelIndexList & indexes) const
02242 {
02243     if (!sourceModel())
02244         return QAbstractProxyModel::mimeData(indexes);
02245     QModelIndexList sourceIndexes;
02246     foreach(const QModelIndex& index, indexes)
02247         sourceIndexes << mapToSource(index);
02248     return sourceModel()->mimeData(sourceIndexes);
02249 }
02250 
02251 QStringList KSelectionProxyModel::mimeTypes() const
02252 {
02253     if (!sourceModel())
02254         return QAbstractProxyModel::mimeTypes();
02255     return sourceModel()->mimeTypes();
02256 }
02257 
02258 Qt::DropActions KSelectionProxyModel::supportedDropActions() const
02259 {
02260     if (!sourceModel())
02261         return QAbstractProxyModel::supportedDropActions();
02262     return sourceModel()->supportedDropActions();
02263 }
02264 
02265 bool KSelectionProxyModel::hasChildren(const QModelIndex & parent) const
02266 {
02267     Q_D(const KSelectionProxyModel);
02268 
02269     if (d->m_rootIndexList.isEmpty() || !sourceModel())
02270         return false;
02271 
02272     if (parent.isValid()) {
02273         Q_ASSERT(parent.model() == this);
02274         if (d->isFlat())
02275             return false;
02276         return sourceModel()->hasChildren(mapToSource(parent));
02277     }
02278 
02279     if (!d->m_startWithChildTrees)
02280         return true;
02281 
02282     return !d->m_mappedFirstChildren.isEmpty();
02283 }
02284 
02285 int KSelectionProxyModel::columnCount(const QModelIndex &index) const
02286 {
02287     Q_D(const KSelectionProxyModel);
02288 
02289     if (!sourceModel() || index.column() > 0
02290       // Qt 4.6 doesn't notice changes in columnCount, so we can't return 0 when
02291       // it's actually 0 ,but must return what the source model says, even if we
02292       // have no rows or columns.
02293 #if QT_VERSION >= 0x040700
02294       || d->m_rootIndexList.isEmpty()
02295 #endif
02296         )
02297         return 0;
02298 
02299     return sourceModel()->columnCount(mapToSource(index));
02300 }
02301 
02302 QItemSelectionModel* KSelectionProxyModel::selectionModel() const
02303 {
02304     Q_D(const KSelectionProxyModel);
02305     return d->m_selectionModel.data();
02306 }
02307 
02308 bool KSelectionProxyModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
02309 {
02310     Q_D(const KSelectionProxyModel);
02311     if (!sourceModel() || d->m_rootIndexList.isEmpty())
02312         return false;
02313 
02314     if ((row == -1) && (column == -1))
02315         return sourceModel()->dropMimeData(data, action, -1, -1, mapToSource(parent));
02316 
02317     int source_destination_row = -1;
02318     int source_destination_column = -1;
02319     QModelIndex source_parent;
02320 
02321     if (row == rowCount(parent)) {
02322         source_parent = mapToSource(parent);
02323         source_destination_row = sourceModel()->rowCount(source_parent);
02324     } else {
02325         const QModelIndex proxy_index = index(row, column, parent);
02326         const QModelIndex source_index = mapToSource(proxy_index);
02327         source_destination_row = source_index.row();
02328         source_destination_column = source_index.column();
02329         source_parent = source_index.parent();
02330     }
02331     return sourceModel()->dropMimeData(data, action, source_destination_row,
02332                                        source_destination_column, source_parent);
02333 }
02334 
02335 QList<QPersistentModelIndex> KSelectionProxyModel::sourceRootIndexes() const
02336 {
02337     Q_D(const KSelectionProxyModel);
02338     return d->m_rootIndexList;
02339 }
02340 
02341 QModelIndexList KSelectionProxyModel::match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const
02342 {
02343     if (role < Qt::UserRole)
02344         return QAbstractProxyModel::match(start, role, value, hits, flags);
02345 
02346     QModelIndexList list;
02347     QModelIndex proxyIndex;
02348     foreach(const QModelIndex &idx, sourceModel()->match(mapToSource(start), role, value, hits, flags)) {
02349         proxyIndex = mapFromSource(idx);
02350         if (proxyIndex.isValid())
02351             list << proxyIndex;
02352     }
02353     return list;
02354 }
02355 
02356 QItemSelection KSelectionProxyModel::mapSelectionFromSource(const QItemSelection& selection) const
02357 {
02358     Q_D(const KSelectionProxyModel);
02359     if (!d->m_startWithChildTrees && d->m_includeAllSelected) {
02360         // QAbstractProxyModel::mapSelectionFromSource puts invalid ranges in the result
02361         // without checking. We can't have that.
02362         QItemSelection proxySelection;
02363         foreach(const QItemSelectionRange &range, selection)
02364         {
02365           QModelIndex proxyTopLeft = mapFromSource(range.topLeft());
02366           if (!proxyTopLeft.isValid())
02367             continue;
02368           QModelIndex proxyBottomRight = mapFromSource(range.bottomRight());
02369           Q_ASSERT(proxyBottomRight.isValid());
02370           proxySelection.append(QItemSelectionRange(proxyTopLeft, proxyBottomRight));
02371         }
02372         return proxySelection;
02373     }
02374 
02375     QItemSelection proxySelection;
02376     QItemSelection::const_iterator it = selection.constBegin();
02377     const QItemSelection::const_iterator end = selection.constEnd();
02378     for ( ; it != end; ++it) {
02379         const QModelIndex proxyTopLeft = mapFromSource(it->topLeft());
02380         if (!proxyTopLeft.isValid())
02381             continue;
02382 
02383         if (it->height() == 1 && it->width() == 1)
02384             proxySelection.append(QItemSelectionRange(proxyTopLeft, proxyTopLeft));
02385         else
02386             proxySelection.append(QItemSelectionRange(proxyTopLeft, d->mapFromSource(it->bottomRight())));
02387     }
02388     return proxySelection;
02389 }
02390 
02391 QItemSelection KSelectionProxyModel::mapSelectionToSource(const QItemSelection& selection) const
02392 {
02393     Q_D(const KSelectionProxyModel);
02394 
02395     if (selection.isEmpty())
02396         return selection;
02397 
02398     if (!d->m_startWithChildTrees && d->m_includeAllSelected) {
02399         // QAbstractProxyModel::mapSelectionFromSource puts invalid ranges in the result
02400         // without checking. We can't have that.
02401         QItemSelection sourceSelection;
02402         foreach(const QItemSelectionRange &range, selection)
02403         {
02404           QModelIndex sourceTopLeft = mapToSource(range.topLeft());
02405           Q_ASSERT(sourceTopLeft.isValid());
02406 
02407           QModelIndex sourceBottomRight = mapToSource(range.bottomRight());
02408           Q_ASSERT(sourceBottomRight.isValid());
02409           sourceSelection.append(QItemSelectionRange(sourceTopLeft, sourceBottomRight));
02410         }
02411         return sourceSelection;
02412     }
02413 
02414 
02415     QItemSelection sourceSelection;
02416     QItemSelection extraSelection;
02417     QItemSelection::const_iterator it = selection.constBegin();
02418     const QItemSelection::const_iterator end = selection.constEnd();
02419     for ( ; it != end; ++it) {
02420         const QModelIndex sourceTopLeft = mapToSource(it->topLeft());
02421         if (it->height() == 1 && it->width() == 1) {
02422             sourceSelection.append(QItemSelectionRange(sourceTopLeft, sourceTopLeft));
02423         } else if (it->parent().isValid()) {
02424             sourceSelection.append(QItemSelectionRange(sourceTopLeft, mapToSource(it->bottomRight())));
02425         } else {
02426             // A contiguous selection in the proxy might not be contiguous in the source if it
02427             // is at the top level of the proxy.
02428             if (d->m_startWithChildTrees) {
02429                 const QModelIndex sourceParent = mapFromSource(sourceTopLeft);
02430                 Q_ASSERT(sourceParent.isValid());
02431                 const int rowCount = sourceModel()->rowCount(sourceParent);
02432                 if (rowCount < it->bottom()) {
02433                     Q_ASSERT(sourceTopLeft.isValid());
02434                     Q_ASSERT(it->bottomRight().isValid());
02435                     const QModelIndex sourceBottomRight = mapToSource(it->bottomRight());
02436                     Q_ASSERT(sourceBottomRight.isValid());
02437                     sourceSelection.append(QItemSelectionRange(sourceTopLeft, sourceBottomRight));
02438                     continue;
02439                 }
02440                 // Store the contiguous part...
02441                 const QModelIndex sourceBottomRight = sourceModel()->index(rowCount - 1, it->right(), sourceParent);
02442                 Q_ASSERT(sourceTopLeft.isValid());
02443                 Q_ASSERT(sourceBottomRight.isValid());
02444                 sourceSelection.append(QItemSelectionRange(sourceTopLeft, sourceBottomRight));
02445                 // ... and the rest will be processed later.
02446                 extraSelection.append(QItemSelectionRange(createIndex(it->top() - rowCount, it->right()), it->bottomRight()));
02447             } else {
02448                 QItemSelection topSelection;
02449                 const QModelIndex idx = createIndex(it->top(), it->right());
02450                 const QModelIndex sourceIdx = mapToSource(idx);
02451                 Q_ASSERT(sourceIdx.isValid());
02452                 topSelection.append(QItemSelectionRange(sourceTopLeft, sourceIdx));
02453                 for (int i = it->top() + 1; i < it->bottom(); ++it) {
02454                   const QModelIndex left = mapToSource(createIndex(i, 0));
02455                   const QModelIndex right = mapToSource(createIndex(i, it->right()));
02456                   Q_ASSERT(left.isValid());
02457                   Q_ASSERT(right.isValid());
02458                   topSelection.append(QItemSelectionRange(left, right));
02459                 }
02460                 sourceSelection += kNormalizeSelection(topSelection);
02461             }
02462         }
02463     }
02464     sourceSelection << mapSelectionToSource(extraSelection);
02465     return sourceSelection;
02466 }
02467 
02468 #include "moc_kselectionproxymodel.cpp"

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal