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 Thu May 10 2012 20:53:06 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:53:06 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.