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

KDE's Doxygen guidelines are available online.

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-4.8.3 API Reference

Skip menu "kdelibs-4.8.3 API Reference"
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal