9#include "kselectionproxymodel.h"
11#include <QItemSelectionRange>
16#include "kmodelindexproxymapper.h"
17#include "kvoidpointerfactory_p.h"
19typedef KBiHash<QPersistentModelIndex, QModelIndex> SourceProxyIndexMapping;
20typedef KBiHash<void *, QModelIndex> ParentMapping;
21typedef KHash2Map<QPersistentModelIndex, int> SourceIndexProxyRowMapping;
27template<
typename ModelIndex>
54 if (selection.
contains(descendant)) {
95 int firstCommonParent = -1;
96 int bestParentRow = -1;
97 while (commonParent.
isValid()) {
98 youngestAncestor = commonParent;
99 commonParent = commonParent.
parent();
101 for (
int i = 0; i < rootAncestors.
size(); ++i) {
102 const QModelIndexList ancestorList = rootAncestors.
at(i);
104 const int parentRow = ancestorList.indexOf(commonParent);
110 if (parentRow > bestParentRow) {
111 firstCommonParent = i;
112 bestParentRow = parentRow;
116 if (firstCommonParent >= 0) {
122 Q_ASSERT(firstCommonParent >= 0);
124 const QModelIndexList firstAnsList = rootAncestors.
at(firstCommonParent);
126 const QModelIndex eldestSibling = firstAnsList.value(bestParentRow + 1);
131 if (eldestSibling.
row() >= youngestAncestor.
row()) {
132 return firstCommonParent;
136 int siblingOffset = 1;
141 if (rootAncestors.
size() <= firstCommonParent + siblingOffset) {
142 return firstCommonParent + siblingOffset;
156 QModelIndexList ansList = rootAncestors.
at(firstCommonParent + siblingOffset);
157 if (ansList.size() <= bestParentRow) {
158 return firstCommonParent + siblingOffset;
161 QModelIndex nextParent = ansList.at(bestParentRow);
162 while (nextParent == commonParent) {
163 if (ansList.size() < bestParentRow + 1)
170 const QModelIndex nextSibling = ansList.value(bestParentRow + 1);
176 if (youngestAncestor.
row() <= nextSibling.
row()) {
182 if (rootAncestors.
size() <= firstCommonParent + siblingOffset) {
186 ansList = rootAncestors.
at(firstCommonParent + siblingOffset);
190 if (ansList.size() <= bestParentRow) {
194 nextParent = ansList.at(bestParentRow);
197 return firstCommonParent + siblingOffset;
237 for (
const auto &root : list) {
238 QModelIndexList ancestors;
239 ancestors.append(root);
242 ancestors.prepend(parent);
246 rootAncestors.
append(ancestors);
248 return _getRootListRow(rootAncestors, index);
267 while (it != selection.
end()) {
268 if (!it->topLeft().parent().isValid()) {
269 rootSelection.
append(*it);
270 it = selection.
erase(it);
276 it = selection.
begin();
277 while (it != selection.
end()) {
279 it = selection.
erase(it);
281 if (isDescendantOf(rootSelection, range.
topLeft()) || isDescendantOf(selection, range.
topLeft())) {
285 rootSelection << range;
287 return rootSelection;
292struct RangeLessThan {
293 bool operator()(
const QItemSelectionRange &left,
const QItemSelectionRange &right)
const
297 const QModelIndex topLeftParent =
left.parent();
298 const QModelIndex otherTopLeftParent =
right.parent();
299 if (topLeftParent == otherTopLeftParent) {
311 return topLeftParent < otherTopLeftParent;
319 if (selection.
size() <= 1) {
330 while (scout != end) {
332 int bottom = it->bottom();
333 while (scout != end && it->parent() == scout->parent() && bottom + 1 == scout->top()) {
334 bottom = scout->bottom();
337 if (bottom != it->bottom()) {
341 Q_ASSERT(it != scout);
345 if (it + 1 == scout) {
359 if (selection.
size() <= 1) {
375 while (i != selection.
end()) {
377 i = selection.
erase(i);
384 std::sort(selection.
begin(), selection.
end(), lt);
385 return stableNormalizeSelection(selection);
388class KSelectionProxyModelPrivate
391 KSelectionProxyModelPrivate(KSelectionProxyModel *model)
393 , m_indexMapper(nullptr)
394 , m_startWithChildTrees(false)
395 , m_omitChildren(false)
396 , m_omitDescendants(false)
397 , m_includeAllSelected(false)
398 , m_rowsInserted(false)
399 , m_rowsRemoved(false)
400 , m_recreateFirstChildMappingOnRemoval(false)
403 , m_sourceModelResetting(false)
404 , m_doubleResetting(false)
405 , m_layoutChanging(false)
406 , m_ignoreNextLayoutAboutToBeChanged(false)
407 , m_ignoreNextLayoutChanged(false)
408 , m_selectionModel(nullptr)
409 , m_filterBehavior(KSelectionProxyModel::InvalidBehavior)
413 Q_DECLARE_PUBLIC(KSelectionProxyModel)
414 KSelectionProxyModel *
const q_ptr;
421 mutable ParentMapping m_parentIds;
424 mutable SourceProxyIndexMapping m_mappedParents;
426 KVoidPointerFactory<> m_voidPointerFactory;
440 void updateInternalIndexes(
const QModelIndex &parent,
int start,
int offset);
449 void updateInternalTopIndexes(
int start,
int offset);
451 void updateFirstChildMapping(
const QModelIndex &parent,
int offset);
455 return m_omitChildren || (m_omitDescendants && m_startWithChildTrees);
462 bool ensureMappable(
const QModelIndex &parent)
const;
463 bool parentIsMappable(
const QModelIndex &parent)
const
465 return parentAlreadyMapped(parent) || m_rootIndexList.contains(parent);
471 QModelIndex mapFromSource(
const QModelIndex &parent)
const;
478 void createParentMappings(
const QModelIndex &parent,
int start,
int end)
const;
479 void createFirstChildMapping(
const QModelIndex &parent,
int proxyRow)
const;
480 bool firstChildAlreadyMapped(
const QModelIndex &firstChild)
const;
481 bool parentAlreadyMapped(
const QModelIndex &parent)
const;
482 void removeFirstChildMappings(
int start,
int end);
483 void removeParentMappings(
const QModelIndex &parent,
int start,
int end);
495 QModelIndex mapParentToSource(
const QModelIndex &proxyParent)
const;
504 QModelIndex mapParentFromSource(
const QModelIndex &sourceParent)
const;
506 QModelIndex mapTopLevelToSource(
int row,
int column)
const;
507 QModelIndex mapTopLevelFromSource(
const QModelIndex &sourceIndex)
const;
508 QModelIndex createTopLevelIndex(
int row,
int column)
const;
509 int topLevelRowCount()
const;
511 void *parentId(
const QModelIndex &proxyParent)
const
513 return m_parentIds.rightToLeft(proxyParent);
515 QModelIndex parentForId(
void *
id)
const
517 return m_parentIds.leftToRight(
id);
522 mutable SourceIndexProxyRowMapping m_mappedFirstChildren;
525 QList<QPersistentModelIndex> m_rootIndexList;
527 KModelIndexProxyMapper *m_indexMapper;
529 QPair<int, int> beginRemoveRows(
const QModelIndex &parent,
int start,
int end)
const;
530 QPair<int, int> beginInsertRows(
const QModelIndex &parent,
int start,
int end)
const;
531 void endRemoveRows(
const QModelIndex &sourceParent,
int proxyStart,
int proxyEnd);
532 void endInsertRows(
const QModelIndex &parent,
int start,
int end);
534 void sourceRowsAboutToBeInserted(
const QModelIndex &parent,
int start,
int end);
535 void sourceRowsInserted(
const QModelIndex &parent,
int start,
int end);
536 void sourceRowsAboutToBeRemoved(
const QModelIndex &parent,
int start,
int end);
537 void sourceRowsRemoved(
const QModelIndex &parent,
int start,
int end);
538 void sourceRowsAboutToBeMoved(
const QModelIndex &parent,
int start,
int end,
const QModelIndex &destParent,
int destRow);
539 void sourceRowsMoved(
const QModelIndex &parent,
int start,
int end,
const QModelIndex &destParent,
int destRow);
540 void sourceModelAboutToBeReset();
541 void sourceModelReset();
542 void sourceLayoutAboutToBeChanged();
543 void sourceLayoutChanged();
544 void emitContinuousRanges(
const QModelIndex &sourceFirst,
const QModelIndex &sourceLast,
const QModelIndex &proxyFirst,
const QModelIndex &proxyLast);
545 void sourceDataChanged(
const QModelIndex &topLeft,
const QModelIndex &bottomRight);
547 void removeSelectionFromProxy(
const QItemSelection &selection);
549 void selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected);
550 void sourceModelDestroyed();
552 void resetInternalData();
554 bool rootWillBeRemoved(
const QItemSelection &selection,
const QModelIndex &root);
560 int getProxyInitialRow(
const QModelIndex &parent)
const;
571 int getTargetRow(
int rootListRow);
576 void insertSelectionIntoProxy(
const QItemSelection &selection);
578 bool m_startWithChildTrees;
580 bool m_omitDescendants;
581 bool m_includeAllSelected;
584 bool m_recreateFirstChildMappingOnRemoval;
585 QPair<int, int> m_proxyRemoveRows;
588 bool m_sourceModelResetting;
589 bool m_doubleResetting;
590 bool m_layoutChanging;
591 bool m_ignoreNextLayoutAboutToBeChanged;
592 bool m_ignoreNextLayoutChanged;
593 QPointer<QItemSelectionModel> m_selectionModel;
595 KSelectionProxyModel::FilterBehavior m_filterBehavior;
597 QList<QPersistentModelIndex> m_layoutChangePersistentIndexes;
598 QModelIndexList m_proxyIndexes;
600 struct PendingSelectionChange {
601 PendingSelectionChange()
604 PendingSelectionChange(
const QItemSelection &selected_,
const QItemSelection &deselected_)
605 : selected(selected_)
606 , deselected(deselected_)
609 QItemSelection selected;
610 QItemSelection deselected;
612 QList<PendingSelectionChange> m_pendingSelectionChanges;
613 QMetaObject::Connection selectionModelModelAboutToBeResetConnection;
614 QMetaObject::Connection selectionModelModelResetConnection;
617void KSelectionProxyModelPrivate::emitContinuousRanges(
const QModelIndex &sourceFirst,
622 Q_Q(KSelectionProxyModel);
624 Q_ASSERT(sourceFirst.
model() == q->sourceModel());
625 Q_ASSERT(sourceLast.
model() == q->sourceModel());
626 Q_ASSERT(proxyFirst.
model() == q);
627 Q_ASSERT(proxyLast.
model() == q);
629 const int proxyRangeSize = proxyLast.
row() - proxyFirst.
row();
630 const int sourceRangeSize = sourceLast.
row() - sourceFirst.
row();
632 if (proxyRangeSize == sourceRangeSize) {
633 Q_EMIT q->dataChanged(proxyFirst, proxyLast);
653 Q_EMIT q->dataChanged(proxyFirst, proxyLast);
656void KSelectionProxyModelPrivate::sourceDataChanged(
const QModelIndex &topLeft,
const QModelIndex &bottomRight)
658 Q_Q(KSelectionProxyModel);
660 Q_ASSERT(topLeft.
model() == q->sourceModel());
661 Q_ASSERT(bottomRight.
model() == q->sourceModel());
663 const QModelIndex sourceRangeParent = topLeft.
parent();
664 if (!sourceRangeParent.
isValid() && m_startWithChildTrees && !m_rootIndexList.contains(sourceRangeParent)) {
668 const QModelIndex proxyTopLeft = q->mapFromSource(topLeft);
669 const QModelIndex proxyBottomRight = q->mapFromSource(bottomRight);
671 const QModelIndex proxyRangeParent = proxyTopLeft.
parent();
673 if (!m_omitChildren && m_omitDescendants && m_startWithChildTrees && m_includeAllSelected) {
676 emitContinuousRanges(topLeft, bottomRight, proxyTopLeft, proxyBottomRight);
681 if ((m_omitChildren && !m_startWithChildTrees && m_includeAllSelected) || (!proxyRangeParent.
isValid() && !m_startWithChildTrees)) {
684 QList<int> changedRows;
685 for (
int row = topLeft.
row(); row <= bottomRight.
row(); ++row) {
686 const QModelIndex index = q->sourceModel()->index(row, topLeft.
column(), topLeft.
parent());
687 const int idx = m_rootIndexList.indexOf(index);
695 int first = changedRows.
first();
696 int previous = first;
697 QList<int>::const_iterator it = changedRows.
constBegin();
698 const QList<int>::const_iterator
end = changedRows.
constEnd();
699 for (; it !=
end; ++it) {
700 if (*it == previous + 1) {
703 const QModelIndex _top = q->index(first, topLeft.
column());
704 const QModelIndex _bottom = q->index(previous, bottomRight.
column());
705 Q_EMIT q->dataChanged(_top, _bottom);
706 previous = first = *it;
709 if (first != previous) {
710 const QModelIndex _top = q->index(first, topLeft.
column());
711 const QModelIndex _bottom = q->index(previous, bottomRight.
column());
712 Q_EMIT q->dataChanged(_top, _bottom);
716 if (proxyRangeParent.
isValid()) {
717 if (m_omitChildren && !m_startWithChildTrees && !m_includeAllSelected)
726 Q_EMIT q->dataChanged(proxyTopLeft, proxyBottomRight);
730 if (m_startWithChildTrees && !m_omitChildren && !m_includeAllSelected && !m_omitDescendants) {
733 Q_EMIT q->dataChanged(proxyTopLeft, proxyBottomRight);
739void KSelectionProxyModelPrivate::sourceLayoutAboutToBeChanged()
741 Q_Q(KSelectionProxyModel);
743 if (m_ignoreNextLayoutAboutToBeChanged) {
744 m_ignoreNextLayoutAboutToBeChanged =
false;
748 if (m_rootIndexList.isEmpty()) {
752 Q_EMIT q->layoutAboutToBeChanged();
754 QItemSelection selection;
755 for (
const auto &rootIndex : std::as_const(m_rootIndexList)) {
757 Q_EMIT q->rootIndexAboutToBeRemoved(rootIndex, KSelectionProxyModel::QPrivateSignal());
758 selection.
append(QItemSelectionRange(rootIndex, rootIndex));
761 selection = kNormalizeSelection(selection);
762 Q_EMIT q->rootSelectionAboutToBeRemoved(selection, KSelectionProxyModel::QPrivateSignal());
764 QPersistentModelIndex srcPersistentIndex;
765 const auto lst = q->persistentIndexList();
766 for (
const QModelIndex &proxyPersistentIndex : lst) {
767 m_proxyIndexes << proxyPersistentIndex;
768 Q_ASSERT(proxyPersistentIndex.isValid());
769 srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
770 Q_ASSERT(srcPersistentIndex.
isValid());
771 m_layoutChangePersistentIndexes << srcPersistentIndex;
774 m_rootIndexList.clear();
777void KSelectionProxyModelPrivate::sourceLayoutChanged()
779 Q_Q(KSelectionProxyModel);
781 if (m_ignoreNextLayoutChanged) {
782 m_ignoreNextLayoutChanged =
false;
786 if (!m_selectionModel || !m_selectionModel->hasSelection()) {
800 m_rootIndexList.clear();
801 m_mappedFirstChildren.clear();
802 m_mappedParents.clear();
806 m_layoutChanging =
true;
807 selectionChanged(m_selectionModel->selection(), QItemSelection());
809 m_layoutChanging =
false;
811 for (
int i = 0; i < m_proxyIndexes.size(); ++i) {
812 q->changePersistentIndex(m_proxyIndexes.at(i), q->mapFromSource(m_layoutChangePersistentIndexes.at(i)));
815 m_layoutChangePersistentIndexes.clear();
816 m_proxyIndexes.clear();
818 Q_EMIT q->layoutChanged();
821void KSelectionProxyModelPrivate::resetInternalData()
823 m_rootIndexList.clear();
824 m_layoutChangePersistentIndexes.clear();
825 m_proxyIndexes.clear();
826 m_mappedParents.clear();
828 m_mappedFirstChildren.clear();
829 m_voidPointerFactory.clear();
832void KSelectionProxyModelPrivate::sourceModelDestroyed()
837 m_sourceModelResetting =
false;
840void KSelectionProxyModelPrivate::sourceModelAboutToBeReset()
842 Q_Q(KSelectionProxyModel);
855 m_doubleResetting =
true;
859 q->beginResetModel();
861 m_sourceModelResetting =
true;
864void KSelectionProxyModelPrivate::sourceModelReset()
866 Q_Q(KSelectionProxyModel);
868 if (m_doubleResetting) {
869 m_doubleResetting =
false;
874 m_sourceModelResetting =
false;
876 selectionChanged(m_selectionModel->selection(), QItemSelection());
880int KSelectionProxyModelPrivate::getProxyInitialRow(
const QModelIndex &parent)
const
882 Q_ASSERT(m_rootIndexList.contains(parent));
902 Q_Q(
const KSelectionProxyModel);
904 Q_ASSERT(parent.
model() == q->sourceModel());
906 int parentPosition = m_rootIndexList.indexOf(parent);
908 QModelIndex parentAbove;
911 while (parentPosition > 0) {
914 parentAbove = m_rootIndexList.at(parentPosition);
915 Q_ASSERT(parentAbove.
isValid());
917 int rows = q->sourceModel()->rowCount(parentAbove);
919 QModelIndex sourceIndexAbove = q->sourceModel()->index(rows - 1, 0, parentAbove);
920 Q_ASSERT(sourceIndexAbove.
isValid());
921 QModelIndex proxyChildAbove = mapFromSource(sourceIndexAbove);
922 Q_ASSERT(proxyChildAbove.
isValid());
923 return proxyChildAbove.
row() + 1;
929void KSelectionProxyModelPrivate::updateFirstChildMapping(
const QModelIndex &parent,
int offset)
931 Q_Q(KSelectionProxyModel);
933 Q_ASSERT(parent.
isValid() ? parent.
model() == q->sourceModel() :
true);
935 static const int column = 0;
936 static const int row = 0;
938 const QPersistentModelIndex srcIndex = q->sourceModel()->index(row, column, parent);
940 const QPersistentModelIndex previousFirstChild = q->sourceModel()->index(offset, column, parent);
942 SourceIndexProxyRowMapping::left_iterator it = m_mappedFirstChildren.findLeft(previousFirstChild);
943 if (it == m_mappedFirstChildren.leftEnd()) {
948 const int proxyRow = it.value();
949 Q_ASSERT(proxyRow >= 0);
951 m_mappedFirstChildren.eraseLeft(it);
955 m_mappedFirstChildren.insert(srcIndex, proxyRow - offset);
958QPair<int, int> KSelectionProxyModelPrivate::beginInsertRows(
const QModelIndex &parent,
int start,
int end)
const
960 const QModelIndex proxyParent = mapFromSource(parent);
963 if (!m_startWithChildTrees) {
964 return qMakePair(-1, -1);
967 if (!m_rootIndexList.contains(parent)) {
968 return qMakePair(-1, -1);
972 if (!m_startWithChildTrees) {
975 return qMakePair(
start, end);
977 return qMakePair(-1, -1);
980 if (!m_includeAllSelected && proxyParent.
isValid()) {
982 return qMakePair(
start, end);
985 if (!m_rootIndexList.contains(parent)) {
986 return qMakePair(-1, -1);
989 const int proxyStartRow = getProxyInitialRow(parent) +
start;
990 return qMakePair(proxyStartRow, proxyStartRow + (end -
start));
993void KSelectionProxyModelPrivate::sourceRowsAboutToBeInserted(
const QModelIndex &parent,
int start,
int end)
995 Q_Q(KSelectionProxyModel);
997 Q_ASSERT(parent.
isValid() ? parent.
model() == q->sourceModel() :
true);
999 if (!m_selectionModel || !m_selectionModel->hasSelection()) {
1014 QPair<int, int> pair = beginInsertRows(parent,
start, end);
1015 if (pair.first == -1) {
1019 const QModelIndex proxyParent = m_startWithChildTrees ? QModelIndex() : mapFromSource(parent);
1021 m_rowsInserted =
true;
1022 q->beginInsertRows(proxyParent, pair.first, pair.second);
1025void KSelectionProxyModelPrivate::endInsertRows(
const QModelIndex &parent,
int start,
int end)
1027 Q_Q(
const KSelectionProxyModel);
1028 const QModelIndex proxyParent = mapFromSource(parent);
1029 const int offset =
end -
start + 1;
1031 const bool isNewParent = (q->sourceModel()->rowCount(parent) == offset);
1033 if (m_startWithChildTrees && m_rootIndexList.contains(parent)) {
1034 const int proxyInitialRow = getProxyInitialRow(parent);
1035 Q_ASSERT(proxyInitialRow >= 0);
1036 const int proxyStartRow = proxyInitialRow +
start;
1038 updateInternalTopIndexes(proxyStartRow, offset);
1040 createFirstChildMapping(parent, proxyStartRow);
1041 }
else if (
start == 0)
1045 updateFirstChildMapping(parent, end + 1);
1048 Q_ASSERT(proxyParent.
isValid());
1050 updateInternalIndexes(proxyParent,
start, offset);
1052 createParentMappings(parent.
parent(), parent.
row(), parent.
row());
1055 createParentMappings(parent,
start, end);
1058void KSelectionProxyModelPrivate::sourceRowsInserted(
const QModelIndex &parent,
int start,
int end)
1060 Q_Q(KSelectionProxyModel);
1062 Q_ASSERT(parent.
isValid() ? parent.
model() == q->sourceModel() :
true);
1064 if (!m_rowsInserted) {
1067 m_rowsInserted =
false;
1068 endInsertRows(parent,
start, end);
1070 for (
const PendingSelectionChange &pendingChange : std::as_const(m_pendingSelectionChanges)) {
1071 selectionChanged(pendingChange.selected, pendingChange.deselected);
1073 m_pendingSelectionChanges.clear();
1083 parent = parent.
parent();
1084 if (parent == ancestor) {
1085 return (prev.row() <= end && prev.row() >=
start);
1095 for (
auto &r : selection) {
1096 if (m_includeAllSelected) {
1097 if (r.parent() == root.
parent() && root.
row() <= r.bottom() && root.
row() >= r.top()) {
1101 if (rootWillBeRemovedFrom(r.parent(), r.top(), r.bottom(), root)) {
1109QPair<int, int> KSelectionProxyModelPrivate::beginRemoveRows(
const QModelIndex &parent,
int start,
int end)
const
1111 Q_Q(
const KSelectionProxyModel);
1113 if (!m_includeAllSelected && !m_omitChildren) {
1115 const QModelIndex proxyParent = mapParentFromSource(parent);
1117 return qMakePair(
start, end);
1121 if (m_startWithChildTrees && m_rootIndexList.contains(parent)) {
1122 const int proxyStartRow = getProxyInitialRow(parent) +
start;
1123 const int proxyEndRow = proxyStartRow + (
end -
start);
1124 return qMakePair(proxyStartRow, proxyEndRow);
1127 QList<QPersistentModelIndex>::const_iterator rootIt = m_rootIndexList.constBegin();
1128 const QList<QPersistentModelIndex>::const_iterator rootEnd = m_rootIndexList.constEnd();
1129 int proxyStartRemove = 0;
1131 for (; rootIt != rootEnd; ++rootIt) {
1132 if (rootWillBeRemovedFrom(parent,
start, end, *rootIt)) {
1135 if (m_startWithChildTrees) {
1136 proxyStartRemove += q->sourceModel()->rowCount(*rootIt);
1143 if (rootIt == rootEnd) {
1144 return qMakePair(-1, -1);
1147 int proxyEndRemove = proxyStartRemove;
1149 for (; rootIt != rootEnd; ++rootIt) {
1150 if (!rootWillBeRemovedFrom(parent,
start, end, *rootIt)) {
1153 if (m_startWithChildTrees) {
1154 proxyEndRemove += q->sourceModel()->rowCount(*rootIt);
1161 if (proxyEndRemove >= proxyStartRemove) {
1162 return qMakePair(proxyStartRemove, proxyEndRemove);
1164 return qMakePair(-1, -1);
1167void KSelectionProxyModelPrivate::sourceRowsAboutToBeRemoved(
const QModelIndex &parent,
int start,
int end)
1169 Q_Q(KSelectionProxyModel);
1171 Q_ASSERT(parent.
isValid() ? parent.
model() == q->sourceModel() :
true);
1173 if (!m_selectionModel || !m_selectionModel->hasSelection()) {
1177 QPair<int, int> pair = beginRemoveRows(parent,
start, end);
1178 if (pair.first == -1) {
1182 const QModelIndex proxyParent = mapParentFromSource(parent);
1184 m_rowsRemoved =
true;
1185 m_proxyRemoveRows = pair;
1186 m_recreateFirstChildMappingOnRemoval = m_mappedFirstChildren.leftContains(q->sourceModel()->index(
start, 0, parent));
1187 q->beginRemoveRows(proxyParent, pair.first, pair.second);
1190void KSelectionProxyModelPrivate::endRemoveRows(
const QModelIndex &sourceParent,
int proxyStart,
int proxyEnd)
1192 const QModelIndex proxyParent = mapParentFromSource(sourceParent);
1209 SourceProxyIndexMapping::right_iterator it = m_mappedParents.rightBegin();
1211 while (it != m_mappedParents.rightEnd()) {
1212 if (!it.value().isValid()) {
1213 m_parentIds.removeRight(it.key());
1214 it = m_mappedParents.eraseRight(it);
1238 removeFirstChildMappings(proxyStart, proxyEnd);
1243 updateInternalIndexes(proxyParent, proxyEnd + 1, -1 * (proxyEnd - proxyStart + 1));
1245 updateInternalTopIndexes(proxyEnd + 1, -1 * (proxyEnd - proxyStart + 1));
1248 QList<QPersistentModelIndex>::iterator rootIt = m_rootIndexList.begin();
1249 while (rootIt != m_rootIndexList.end()) {
1250 if (!rootIt->isValid()) {
1251 rootIt = m_rootIndexList.erase(rootIt);
1258void KSelectionProxyModelPrivate::sourceRowsRemoved(
const QModelIndex &parent,
int start,
int end)
1260 Q_Q(KSelectionProxyModel);
1264 Q_ASSERT(parent.
isValid() ? parent.
model() == q->sourceModel() :
true);
1266 if (!m_selectionModel) {
1270 if (!m_rowsRemoved) {
1273 m_rowsRemoved =
false;
1275 Q_ASSERT(m_proxyRemoveRows.first >= 0);
1276 Q_ASSERT(m_proxyRemoveRows.second >= 0);
1277 endRemoveRows(parent, m_proxyRemoveRows.first, m_proxyRemoveRows.second);
1278 if (m_recreateFirstChildMappingOnRemoval && q->sourceModel()->hasChildren(parent))
1282 createFirstChildMapping(parent, m_proxyRemoveRows.first);
1284 m_recreateFirstChildMappingOnRemoval =
false;
1286 m_proxyRemoveRows = qMakePair(-1, -1);
1290void KSelectionProxyModelPrivate::sourceRowsAboutToBeMoved(
const QModelIndex &srcParent,
int srcStart,
int srcEnd,
const QModelIndex &destParent,
int destRow)
1295 Q_UNUSED(destParent)
1299 sourceLayoutAboutToBeChanged();
1302void KSelectionProxyModelPrivate::sourceRowsMoved(
const QModelIndex &srcParent,
int srcStart,
int srcEnd,
const QModelIndex &destParent,
int destRow)
1307 Q_UNUSED(destParent)
1311 sourceLayoutChanged();
1316 return m_mappedParents.rightToLeft(proxyParent);
1321 return m_mappedParents.leftToRight(sourceParent);
1325indexIsValid(
bool startWithChildTrees,
int row,
const QList<QPersistentModelIndex> &rootIndexList,
const SourceIndexProxyRowMapping &mappedFirstChildren)
1327 if (!startWithChildTrees) {
1328 Q_ASSERT(rootIndexList.
size() > row);
1330 Q_ASSERT(!mappedFirstChildren.isEmpty());
1332 SourceIndexProxyRowMapping::right_const_iterator result = std::prev(mappedFirstChildren.rightUpperBound(row));
1334 Q_ASSERT(result != mappedFirstChildren.rightEnd());
1335 const int proxyFirstRow = result.key();
1336 const QModelIndex sourceFirstChild = result.value();
1337 Q_ASSERT(proxyFirstRow >= 0);
1338 Q_ASSERT(sourceFirstChild.
isValid());
1340 Q_ASSERT(row <= proxyFirstRow + sourceFirstChild.
model()->
rowCount(sourceFirstChild.
parent()));
1345QModelIndex KSelectionProxyModelPrivate::createTopLevelIndex(
int row,
int column)
const
1347 Q_Q(
const KSelectionProxyModel);
1349 Q_ASSERT(indexIsValid(m_startWithChildTrees, row, m_rootIndexList, m_mappedFirstChildren));
1350 return q->createIndex(row, column);
1355 Q_Q(
const KSelectionProxyModel);
1357 const QModelIndex sourceParent = sourceIndex.
parent();
1358 const int row = m_rootIndexList.indexOf(sourceIndex);
1360 return QModelIndex();
1363 if (!m_startWithChildTrees) {
1364 Q_ASSERT(m_rootIndexList.size() > row);
1365 return q->createIndex(row, sourceIndex.
column());
1367 if (!m_rootIndexList.contains(sourceParent)) {
1368 return QModelIndex();
1371 const QModelIndex firstChild = q->sourceModel()->index(0, 0, sourceParent);
1372 const int firstProxyRow = m_mappedFirstChildren.leftToRight(firstChild);
1374 return q->createIndex(firstProxyRow + sourceIndex.
row(), sourceIndex.
column());
1379 Q_Q(
const KSelectionProxyModel);
1381 const QModelIndex maybeMapped = mapParentFromSource(sourceIndex);
1386 const QModelIndex sourceParent = sourceIndex.
parent();
1388 const QModelIndex proxyParent = mapParentFromSource(sourceParent);
1390 void *
const parentId = m_parentIds.rightToLeft(proxyParent);
1391 static const int column = 0;
1392 return q->createIndex(sourceIndex.
row(), column, parentId);
1395 const QModelIndex firstChild = q->sourceModel()->index(0, 0, sourceParent);
1397 if (m_mappedFirstChildren.leftContains(firstChild)) {
1398 const int firstProxyRow = m_mappedFirstChildren.leftToRight(firstChild);
1399 return q->createIndex(firstProxyRow + sourceIndex.
row(), sourceIndex.
column());
1401 return mapTopLevelFromSource(sourceIndex);
1404int KSelectionProxyModelPrivate::topLevelRowCount()
const
1406 Q_Q(
const KSelectionProxyModel);
1408 if (!m_startWithChildTrees) {
1409 return m_rootIndexList.size();
1412 if (m_mappedFirstChildren.isEmpty()) {
1416 const SourceIndexProxyRowMapping::right_const_iterator result = std::prev(m_mappedFirstChildren.rightConstEnd());
1418 const int proxyFirstRow = result.key();
1419 const QModelIndex sourceFirstChild = result.value();
1420 Q_ASSERT(sourceFirstChild.
isValid());
1421 const QModelIndex sourceParent = sourceFirstChild.
parent();
1422 Q_ASSERT(sourceParent.
isValid());
1423 return q->sourceModel()->rowCount(sourceParent) + proxyFirstRow;
1426bool KSelectionProxyModelPrivate::ensureMappable(
const QModelIndex &parent)
const
1428 Q_Q(
const KSelectionProxyModel);
1434 if (parentIsMappable(parent)) {
1438 QModelIndex ancestor = parent.
parent();
1439 QModelIndexList ancestorList;
1441 if (parentIsMappable(ancestor)) {
1444 ancestorList.prepend(ancestor);
1447 ancestor = ancestor.
parent();
1457 for (
int i = 0; i < ancestorList.size(); ++i) {
1458 const QModelIndex existingAncestor = mapParentFromSource(ancestor);
1459 Q_ASSERT(existingAncestor.
isValid());
1461 void *
const ansId = m_parentIds.rightToLeft(existingAncestor);
1462 const QModelIndex newSourceParent = ancestorList.at(i);
1463 const QModelIndex newProxyParent = q->createIndex(newSourceParent.
row(), newSourceParent.
column(), ansId);
1465 void *
const newId = m_voidPointerFactory.createPointer();
1466 m_parentIds.insert(newId, newProxyParent);
1467 m_mappedParents.insert(QPersistentModelIndex(newSourceParent), newProxyParent);
1468 ancestor = newSourceParent;
1473void KSelectionProxyModelPrivate::updateInternalTopIndexes(
int start,
int offset)
1475 updateInternalIndexes(QModelIndex(),
start, offset);
1477 QHash<QPersistentModelIndex, int> updates;
1479 SourceIndexProxyRowMapping::right_iterator it = m_mappedFirstChildren.rightLowerBound(
start);
1480 const SourceIndexProxyRowMapping::right_iterator
end = m_mappedFirstChildren.rightEnd();
1482 for (; it !=
end; ++it) {
1483 updates.
insert(*it, it.key() + offset);
1487 QHash<QPersistentModelIndex, int>::const_iterator it = updates.
constBegin();
1488 const QHash<QPersistentModelIndex, int>::const_iterator
end = updates.
constEnd();
1490 for (; it !=
end; ++it) {
1491 m_mappedFirstChildren.insert(it.key(), it.value());
1496void KSelectionProxyModelPrivate::updateInternalIndexes(
const QModelIndex &parent,
int start,
int offset)
1498 Q_Q(KSelectionProxyModel);
1500 Q_ASSERT(
start + offset >= 0);
1501 Q_ASSERT(parent.
isValid() ? parent.
model() == q :
true);
1507 SourceProxyIndexMapping::left_iterator mappedParentIt = m_mappedParents.leftBegin();
1509 QHash<void *, QModelIndex> updatedParentIds;
1510 QHash<QPersistentModelIndex, QModelIndex> updatedParents;
1512 for (; mappedParentIt != m_mappedParents.leftEnd(); ++mappedParentIt) {
1513 const QModelIndex proxyIndex = mappedParentIt.value();
1514 Q_ASSERT(proxyIndex.
isValid());
1520 const QModelIndex proxyParent = proxyIndex.
parent();
1523 if (proxyParent != parent) {
1531 Q_ASSERT(m_parentIds.rightContains(proxyIndex));
1532 void *
const key = m_parentIds.rightToLeft(proxyIndex);
1534 const QModelIndex newIndex = q->createIndex(proxyIndex.
row() + offset, proxyIndex.
column(), proxyIndex.
internalPointer());
1538 updatedParentIds.
insert(key, newIndex);
1539 updatedParents.
insert(mappedParentIt.key(), newIndex);
1543 QHash<QPersistentModelIndex, QModelIndex>::const_iterator it = updatedParents.
constBegin();
1544 const QHash<QPersistentModelIndex, QModelIndex>::const_iterator
end = updatedParents.
constEnd();
1545 for (; it !=
end; ++it) {
1546 m_mappedParents.insert(it.key(), it.value());
1551 QHash<void *, QModelIndex>::const_iterator it = updatedParentIds.
constBegin();
1552 const QHash<void *, QModelIndex>::const_iterator
end = updatedParentIds.
constEnd();
1553 for (; it !=
end; ++it) {
1554 m_parentIds.insert(it.key(), it.value());
1559bool KSelectionProxyModelPrivate::parentAlreadyMapped(
const QModelIndex &parent)
const
1561 Q_Q(
const KSelectionProxyModel);
1563 Q_ASSERT(parent.
model() == q->sourceModel());
1564 return m_mappedParents.leftContains(parent);
1567bool KSelectionProxyModelPrivate::firstChildAlreadyMapped(
const QModelIndex &firstChild)
const
1569 Q_Q(
const KSelectionProxyModel);
1571 Q_ASSERT(firstChild.
model() == q->sourceModel());
1572 return m_mappedFirstChildren.leftContains(firstChild);
1575void KSelectionProxyModelPrivate::createFirstChildMapping(
const QModelIndex &parent,
int proxyRow)
const
1577 Q_Q(
const KSelectionProxyModel);
1579 Q_ASSERT(parent.
isValid() ? parent.
model() == q->sourceModel() :
true);
1581 static const int column = 0;
1582 static const int row = 0;
1584 const QPersistentModelIndex srcIndex = q->sourceModel()->index(row, column, parent);
1586 if (firstChildAlreadyMapped(srcIndex)) {
1591 m_mappedFirstChildren.insert(srcIndex, proxyRow);
1594void KSelectionProxyModelPrivate::createParentMappings(
const QModelIndex &parent,
int start,
int end)
const
1600 Q_Q(
const KSelectionProxyModel);
1602 Q_ASSERT(parent.
isValid() ? parent.
model() == q->sourceModel() :
true);
1604 static const int column = 0;
1606 for (
int row =
start; row <=
end; ++row) {
1607 const QModelIndex srcIndex = q->sourceModel()->index(row, column, parent);
1609 if (!q->sourceModel()->hasChildren(srcIndex) || parentAlreadyMapped(srcIndex)) {
1613 const QModelIndex proxyIndex = mapFromSource(srcIndex);
1618 void *
const newId = m_voidPointerFactory.createPointer();
1619 m_parentIds.insert(newId, proxyIndex);
1621 m_mappedParents.insert(QPersistentModelIndex(srcIndex), proxyIndex);
1625void KSelectionProxyModelPrivate::removeFirstChildMappings(
int start,
int end)
1627 SourceIndexProxyRowMapping::right_iterator it = m_mappedFirstChildren.rightLowerBound(
start);
1628 const SourceIndexProxyRowMapping::right_iterator endIt = m_mappedFirstChildren.rightUpperBound(end);
1629 while (it != endIt) {
1630 it = m_mappedFirstChildren.eraseRight(it);
1634void KSelectionProxyModelPrivate::removeParentMappings(
const QModelIndex &parent,
int start,
int end)
1636 Q_Q(KSelectionProxyModel);
1638 Q_ASSERT(parent.
isValid() ? parent.
model() == q :
true);
1641 struct RemovalInfo {
1642 QPersistentModelIndex idx;
1643 QModelIndex sourceIdx;
1645 std::vector<RemovalInfo> removals;
1646 removals.reserve(end -
start + 1);
1647 for (
auto it = m_mappedParents.rightBegin(); it != m_mappedParents.rightEnd(); ++it) {
1648 if (it.key().row() >=
start && it.key().row() <= end) {
1649 const QModelIndex sourceParent = it.value();
1650 const QModelIndex proxyGrandParent = mapParentFromSource(sourceParent.
parent());
1651 if (proxyGrandParent == parent) {
1652 removals.push_back({it.key(), it.value()});
1658 const bool flatList = isFlat();
1659 for (
const auto &r : removals) {
1661 removeParentMappings(r.idx, 0, q->sourceModel()->rowCount(r.sourceIdx) - 1);
1663 m_parentIds.removeRight(r.idx);
1664 m_mappedParents.removeRight(r.idx);
1668QModelIndex KSelectionProxyModelPrivate::mapTopLevelToSource(
int row,
int column)
const
1670 if (!m_startWithChildTrees) {
1671 const QModelIndex idx = m_rootIndexList.at(row);
1675 if (m_mappedFirstChildren.isEmpty()) {
1676 return QModelIndex();
1679 SourceIndexProxyRowMapping::right_iterator result = std::prev(m_mappedFirstChildren.rightUpperBound(row));
1681 Q_ASSERT(result != m_mappedFirstChildren.rightEnd());
1683 const int proxyFirstRow = result.key();
1684 const QModelIndex sourceFirstChild = result.value();
1685 Q_ASSERT(sourceFirstChild.
isValid());
1686 return sourceFirstChild.
sibling(row - proxyFirstRow, column);
1689void KSelectionProxyModelPrivate::removeSelectionFromProxy(
const QItemSelection &selection)
1691 Q_Q(KSelectionProxyModel);
1696 QList<QPersistentModelIndex>::iterator rootIt = m_rootIndexList.begin();
1697 const QList<QPersistentModelIndex>::iterator rootEnd = m_rootIndexList.end();
1698 int proxyStartRemove = 0;
1700 for (; rootIt != rootEnd; ++rootIt) {
1701 if (rootWillBeRemoved(selection, *rootIt)) {
1704 if (m_startWithChildTrees) {
1705 auto rc = q->sourceModel()->rowCount(*rootIt);
1706 proxyStartRemove += rc;
1713 if (rootIt == rootEnd) {
1717 int proxyEndRemove = proxyStartRemove;
1719 QList<QPersistentModelIndex>::iterator rootRemoveStart = rootIt;
1721 for (; rootIt != rootEnd; ++rootIt) {
1722 if (!rootWillBeRemoved(selection, *rootIt)) {
1725 q->rootIndexAboutToBeRemoved(*rootIt, KSelectionProxyModel::QPrivateSignal());
1726 if (m_startWithChildTrees) {
1727 auto rc = q->sourceModel()->rowCount(*rootIt);
1728 proxyEndRemove += rc;
1735 if (proxyEndRemove >= proxyStartRemove) {
1736 q->beginRemoveRows(QModelIndex(), proxyStartRemove, proxyEndRemove);
1738 rootIt = m_rootIndexList.erase(rootRemoveStart, rootIt);
1740 removeParentMappings(QModelIndex(), proxyStartRemove, proxyEndRemove);
1741 if (m_startWithChildTrees) {
1742 removeFirstChildMappings(proxyStartRemove, proxyEndRemove);
1744 updateInternalTopIndexes(proxyEndRemove + 1, -1 * (proxyEndRemove - proxyStartRemove + 1));
1748 rootIt = m_rootIndexList.erase(rootRemoveStart, rootIt);
1750 if (rootIt != rootEnd) {
1751 removeSelectionFromProxy(selection);
1757 Q_Q(KSelectionProxyModel);
1759 if (!q->sourceModel() || (_selected.
isEmpty() && _deselected.
isEmpty())) {
1763 if (m_sourceModelResetting) {
1767 if (m_rowsInserted || m_rowsRemoved) {
1768 m_pendingSelectionChanges.append(PendingSelectionChange(_selected, _deselected));
1785 const QItemSelection selected = kNormalizeSelection(m_indexMapper->mapSelectionRightToLeft(_selected));
1786 const QItemSelection deselected = kNormalizeSelection(m_indexMapper->mapSelectionRightToLeft(_deselected));
1788#if QT_VERSION < 0x040800
1791 QItemSelection reportedSelection = m_selectionModel->selection();
1793 QItemSelection fullSelection = m_indexMapper->mapSelectionRightToLeft(reportedSelection);
1795 QItemSelection fullSelection = m_indexMapper->mapSelectionRightToLeft(m_selectionModel->selection());
1798 fullSelection = kNormalizeSelection(fullSelection);
1800 QItemSelection newRootRanges;
1801 QItemSelection removedRootRanges;
1802 if (!m_includeAllSelected) {
1803 newRootRanges = getRootRanges(selected);
1805 QItemSelection existingSelection = fullSelection;
1812 const QItemSelection existingRootRanges = getRootRanges(existingSelection);
1814 QMutableListIterator<QItemSelectionRange> i(newRootRanges);
1815 while (i.hasNext()) {
1816 const QItemSelectionRange range = i.next();
1817 const QModelIndex topLeft = range.
topLeft();
1818 if (isDescendantOf(existingRootRanges, topLeft)) {
1824 QItemSelection exposedSelection;
1826 QItemSelection deselectedRootRanges = getRootRanges(deselected);
1827 QListIterator<QItemSelectionRange> i(deselectedRootRanges);
1828 while (i.hasNext()) {
1829 const QItemSelectionRange range = i.next();
1830 const QModelIndex topLeft = range.
topLeft();
1839 if (!isDescendantOf(existingRootRanges, topLeft)) {
1846 for (
const QItemSelectionRange &selectedRange : existingRootRanges) {
1847 const QModelIndex selectedRangeTopLeft = selectedRange.topLeft();
1850 if (isDescendantOf(range, selectedRangeTopLeft)
1853 && !isDescendantOf(newRootRanges, selectedRangeTopLeft)) {
1854 exposedSelection.
append(selectedRange);
1857 removedRootRanges << range;
1862 QItemSelection obscuredRanges;
1864 QListIterator<QItemSelectionRange> i(existingRootRanges);
1865 while (i.hasNext()) {
1866 const QItemSelectionRange range = i.next();
1867 if (isDescendantOf(newRootRanges, range.
topLeft())) {
1868 obscuredRanges << range;
1872 removedRootRanges << getRootRanges(obscuredRanges);
1873 newRootRanges << getRootRanges(exposedSelection);
1875 removedRootRanges = kNormalizeSelection(removedRootRanges);
1876 newRootRanges = kNormalizeSelection(newRootRanges);
1878 removedRootRanges = deselected;
1879 newRootRanges = selected;
1882 removeSelectionFromProxy(removedRootRanges);
1884 if (!m_selectionModel->hasSelection()) {
1885 Q_ASSERT(m_rootIndexList.isEmpty());
1886 Q_ASSERT(m_mappedFirstChildren.isEmpty());
1887 Q_ASSERT(m_mappedParents.isEmpty());
1888 Q_ASSERT(m_parentIds.isEmpty());
1891 insertSelectionIntoProxy(newRootRanges);
1894int KSelectionProxyModelPrivate::getTargetRow(
int rootListRow)
1896 Q_Q(KSelectionProxyModel);
1897 if (!m_startWithChildTrees) {
1902 while (rootListRow >= 0) {
1903 const QModelIndex idx = m_rootIndexList.at(rootListRow);
1905 const int rowCount = q->sourceModel()->rowCount(idx);
1907 static const int column = 0;
1908 const QModelIndex srcIdx = q->sourceModel()->index(rowCount - 1, column, idx);
1909 const QModelIndex proxyLastChild = mapFromSource(srcIdx);
1910 return proxyLastChild.
row() + 1;
1917void KSelectionProxyModelPrivate::insertSelectionIntoProxy(
const QItemSelection &selection)
1919 Q_Q(KSelectionProxyModel);
1925 const auto lst = selection.
indexes();
1926 for (
const QModelIndex &newIndex : lst) {
1927 Q_ASSERT(newIndex.
model() == q->sourceModel());
1928 if (newIndex.
column() > 0) {
1931 if (m_startWithChildTrees) {
1932 const int rootListRow = getRootListRow(m_rootIndexList, newIndex);
1933 Q_ASSERT(q->sourceModel() == newIndex.
model());
1934 const int rowCount = q->sourceModel()->rowCount(newIndex);
1935 const int startRow = getTargetRow(rootListRow);
1937 if (rowCount == 0) {
1940 m_rootIndexList.insert(rootListRow, newIndex);
1941 if (!m_resetting || m_layoutChanging) {
1942 Q_EMIT q->rootIndexAdded(newIndex, KSelectionProxyModel::QPrivateSignal());
1947 q->beginInsertRows(QModelIndex(), startRow, startRow + rowCount - 1);
1950 m_rootIndexList.insert(rootListRow, newIndex);
1951 if (!m_resetting || m_layoutChanging) {
1952 Q_EMIT q->rootIndexAdded(newIndex, KSelectionProxyModel::QPrivateSignal());
1956 for (
int i = 0; i < rootListRow; ++i) {
1957 _start += q->sourceModel()->rowCount(m_rootIndexList.at(i));
1960 updateInternalTopIndexes(_start, rowCount);
1961 createFirstChildMapping(newIndex, _start);
1962 createParentMappings(newIndex, 0, rowCount - 1);
1969 const int row = getRootListRow(m_rootIndexList, newIndex);
1971 q->beginInsertRows(QModelIndex(), row, row);
1975 m_rootIndexList.insert(row, newIndex);
1977 if (!m_resetting || m_layoutChanging) {
1978 Q_EMIT q->rootIndexAdded(newIndex, KSelectionProxyModel::QPrivateSignal());
1980 Q_ASSERT(m_rootIndexList.size() > row);
1981 updateInternalIndexes(QModelIndex(), row, 1);
1982 createParentMappings(newIndex.
parent(), newIndex.
row(), newIndex.
row());
1989 Q_EMIT q->rootSelectionAdded(selection, KSelectionProxyModel::QPrivateSignal());
1994 , d_ptr(new KSelectionProxyModelPrivate(this))
1996 setSelectionModel(selectionModel);
2001 , d_ptr(new KSelectionProxyModelPrivate(this))
2011 Q_ASSERT(behavior != InvalidBehavior);
2012 if (behavior == InvalidBehavior) {
2015 if (d->m_filterBehavior != behavior) {
2018 d->m_filterBehavior = behavior;
2021 case InvalidBehavior: {
2022 Q_ASSERT(!
"InvalidBehavior can't be used here");
2026 d->m_omitChildren =
false;
2027 d->m_omitDescendants =
false;
2028 d->m_startWithChildTrees =
false;
2029 d->m_includeAllSelected =
false;
2032 case SubTreeRoots: {
2033 d->m_omitChildren =
true;
2034 d->m_startWithChildTrees =
false;
2035 d->m_includeAllSelected =
false;
2038 case SubTreesWithoutRoots: {
2039 d->m_omitChildren =
false;
2040 d->m_omitDescendants =
false;
2041 d->m_startWithChildTrees =
true;
2042 d->m_includeAllSelected =
false;
2045 case ExactSelection: {
2046 d->m_omitChildren =
true;
2047 d->m_startWithChildTrees =
false;
2048 d->m_includeAllSelected =
true;
2051 case ChildrenOfExactSelection: {
2052 d->m_omitChildren =
false;
2053 d->m_omitDescendants =
true;
2054 d->m_startWithChildTrees =
true;
2055 d->m_includeAllSelected =
true;
2059 Q_EMIT filterBehaviorChanged(QPrivateSignal());
2060 d->resetInternalData();
2061 if (d->m_selectionModel) {
2062 d->selectionChanged(d->m_selectionModel->selection(),
QItemSelection());
2069KSelectionProxyModel::FilterBehavior KSelectionProxyModel::filterBehavior()
const
2072 return d->m_filterBehavior;
2079 Q_ASSERT(_sourceModel !=
this);
2086 d->m_resetting =
true;
2089 disconnect(oldSourceModel,
nullptr,
this,
nullptr);
2093 d->resetInternalData();
2096 if (d->m_selectionModel) {
2097 delete d->m_indexMapper;
2099 if (d->m_selectionModel->hasSelection()) {
2100 d->selectionChanged(d->m_selectionModel->selection(),
QItemSelection());
2105 d->sourceRowsAboutToBeInserted(parent,
start, end);
2109 d->sourceRowsInserted(parent,
start, end);
2113 d->sourceRowsAboutToBeRemoved(parent,
start, end);
2117 d->sourceRowsRemoved(parent,
start, end);
2124 d->sourceRowsAboutToBeMoved(parent,
start, end, destParent, destRow);
2131 d->sourceRowsMoved(parent,
start, end, destParent, destRow);
2135 d->sourceModelAboutToBeReset();
2139 d->sourceModelReset();
2143 d->sourceDataChanged(topLeft, bottomRight);
2147 d->sourceLayoutAboutToBeChanged();
2151 d->sourceLayoutChanged();
2155 d->sourceModelDestroyed();
2159 d->m_resetting =
false;
2171 Q_ASSERT(proxyIndex.
model() ==
this);
2174 return d->mapTopLevelToSource(proxyIndex.
row(), proxyIndex.
column());
2177 const QModelIndex proxyParent = d->parentForId(proxyIndex.
internalPointer());
2178 Q_ASSERT(proxyParent.
isValid());
2179 const QModelIndex sourceParent = d->mapParentToSource(proxyParent);
2180 Q_ASSERT(sourceParent.
isValid());
2189 return QModelIndex();
2195 return QModelIndex();
2198 if (!d->ensureMappable(sourceIndex)) {
2199 return QModelIndex();
2202 return d->mapFromSource(sourceIndex);
2205int KSelectionProxyModel::rowCount(
const QModelIndex &index)
const
2209 if (!
sourceModel() || index.column() > 0 || d->m_rootIndexList.isEmpty()) {
2213 Q_ASSERT(index.isValid() ? index.model() ==
this :
true);
2214 if (!index.isValid()) {
2215 return d->topLevelRowCount();
2223 QModelIndex sourceParent = d->mapParentToSource(index);
2226 sourceParent = mapToSource(index.parent());
2227 d->createParentMappings(sourceParent, 0,
sourceModel()->rowCount(sourceParent) - 1);
2228 sourceParent = d->mapParentToSource(index);
2231 if (!sourceParent.
isValid()) {
2243 return QModelIndex();
2246 Q_ASSERT(parent.isValid() ? parent.model() ==
this :
true);
2248 if (!parent.isValid()) {
2249 return d->createTopLevelIndex(row, column);
2252 void *
const parentId = d->parentId(parent);
2261 if (!
sourceModel() || !index.isValid() || d->m_rootIndexList.isEmpty()) {
2262 return QModelIndex();
2265 Q_ASSERT(index.model() ==
this);
2267 return d->parentForId(index.internalPointer());
2276 Q_ASSERT(index.model() ==
this);
2278 const QModelIndex srcIndex = mapToSource(index);
2289 if (index.isValid()) {
2290 Q_ASSERT(index.model() ==
this);
2291 const QModelIndex idx = mapToSource(index);
2292 return idx.
data(role);
2302 return sourceModel()->headerData(section, orientation, role);
2305QMimeData *KSelectionProxyModel::mimeData(
const QModelIndexList &indexes)
const
2310 QModelIndexList sourceIndexes;
2311 for (
const QModelIndex &index : indexes) {
2312 sourceIndexes << mapToSource(index);
2317QStringList KSelectionProxyModel::mimeTypes()
const
2333bool KSelectionProxyModel::hasChildren(
const QModelIndex &parent)
const
2337 if (d->m_rootIndexList.isEmpty() || !
sourceModel()) {
2341 if (parent.isValid()) {
2342 Q_ASSERT(parent.model() ==
this);
2346 return sourceModel()->hasChildren(mapToSource(parent));
2349 if (!d->m_startWithChildTrees) {
2353 return !d->m_mappedFirstChildren.isEmpty();
2356int KSelectionProxyModel::columnCount(
const QModelIndex &index)
const
2362 return sourceModel()->columnCount(mapToSource(index));
2368 return d->m_selectionModel;
2374 if (d->m_selectionModel != itemSelectionModel) {
2375 if (d->m_selectionModel) {
2377 SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
2379 SLOT(selectionChanged(QItemSelection, QItemSelection)));
2382 d->m_selectionModel = itemSelectionModel;
2383 Q_EMIT selectionModelChanged(QPrivateSignal());
2385 if (d->m_selectionModel) {
2386 connect(d->m_selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(selectionChanged(QItemSelection, QItemSelection)));
2388 auto handleSelectionModelModel = [&, d] {
2390 if (d->selectionModelModelAboutToBeResetConnection) {
2391 disconnect(d->selectionModelModelAboutToBeResetConnection);
2393 if (d->selectionModelModelResetConnection) {
2394 disconnect(d->selectionModelModelResetConnection);
2396 if (d->m_selectionModel->model()) {
2397 d->selectionModelModelAboutToBeResetConnection =
2399 d->selectionModelModelResetConnection =
connect(d->m_selectionModel->model(), SIGNAL(
modelReset()),
this, SLOT(sourceModelReset()));
2400 d->m_rootIndexList.clear();
2401 delete d->m_indexMapper;
2402 d->m_indexMapper =
new KModelIndexProxyMapper(
sourceModel(), d->m_selectionModel->model(),
this);
2407 handleSelectionModelModel();
2411 delete d->m_indexMapper;
2412 d->m_indexMapper =
new KModelIndexProxyMapper(
sourceModel(), d->m_selectionModel->model(),
this);
2413 if (d->m_selectionModel->hasSelection()) {
2414 d->selectionChanged(d->m_selectionModel->selection(), QItemSelection());
2423 if (!
sourceModel() || d->m_rootIndexList.isEmpty()) {
2427 if ((row == -1) && (column == -1)) {
2428 return sourceModel()->dropMimeData(data, action, -1, -1, mapToSource(parent));
2431 int source_destination_row = -1;
2432 int source_destination_column = -1;
2433 QModelIndex source_parent;
2435 if (row == rowCount(parent)) {
2436 source_parent = mapToSource(parent);
2437 source_destination_row =
sourceModel()->rowCount(source_parent);
2439 const QModelIndex proxy_index = index(row, column, parent);
2440 const QModelIndex source_index = mapToSource(proxy_index);
2441 source_destination_row = source_index.
row();
2442 source_destination_column = source_index.
column();
2443 source_parent = source_index.
parent();
2445 return sourceModel()->dropMimeData(data, action, source_destination_row, source_destination_column, source_parent);
2451 return d->m_rootIndexList;
2460 QModelIndexList
list;
2461 QModelIndex proxyIndex;
2462 const auto lst =
sourceModel()->match(mapToSource(
start), role, value, hits, flags);
2463 for (
const QModelIndex &idx : lst) {
2464 proxyIndex = mapFromSource(idx);
2475 if (!d->m_startWithChildTrees && d->m_includeAllSelected) {
2478 QItemSelection proxySelection;
2479 for (
const QItemSelectionRange &range : selection) {
2480 QModelIndex proxyTopLeft = mapFromSource(range.
topLeft());
2481 if (!proxyTopLeft.
isValid()) {
2484 QModelIndex proxyBottomRight = mapFromSource(range.
bottomRight());
2485 Q_ASSERT(proxyBottomRight.
isValid());
2486 proxySelection.
append(QItemSelectionRange(proxyTopLeft, proxyBottomRight));
2488 return proxySelection;
2491 QItemSelection proxySelection;
2492 QItemSelection::const_iterator it = selection.
constBegin();
2493 const QItemSelection::const_iterator
end = selection.constEnd();
2494 for (; it !=
end; ++it) {
2495 const QModelIndex proxyTopLeft = mapFromSource(it->topLeft());
2496 if (!proxyTopLeft.
isValid()) {
2500 if (it->height() == 1 && it->width() == 1) {
2501 proxySelection.
append(QItemSelectionRange(proxyTopLeft, proxyTopLeft));
2503 proxySelection.
append(QItemSelectionRange(proxyTopLeft, d->mapFromSource(it->bottomRight())));
2506 return proxySelection;
2517 if (!d->m_startWithChildTrees && d->m_includeAllSelected) {
2520 QItemSelection sourceSelection;
2521 for (
const QItemSelectionRange &range : selection) {
2522 QModelIndex sourceTopLeft = mapToSource(range.
topLeft());
2523 Q_ASSERT(sourceTopLeft.
isValid());
2525 QModelIndex sourceBottomRight = mapToSource(range.
bottomRight());
2526 Q_ASSERT(sourceBottomRight.
isValid());
2527 sourceSelection.
append(QItemSelectionRange(sourceTopLeft, sourceBottomRight));
2529 return sourceSelection;
2532 QItemSelection sourceSelection;
2533 QItemSelection extraSelection;
2534 QItemSelection::const_iterator it = selection.constBegin();
2535 const QItemSelection::const_iterator
end = selection.constEnd();
2536 for (; it !=
end; ++it) {
2537 const QModelIndex sourceTopLeft = mapToSource(it->topLeft());
2538 if (it->height() == 1 && it->width() == 1) {
2539 sourceSelection.
append(QItemSelectionRange(sourceTopLeft, sourceTopLeft));
2540 }
else if (it->parent().isValid()) {
2541 sourceSelection.
append(QItemSelectionRange(sourceTopLeft, mapToSource(it->bottomRight())));
2545 if (d->m_startWithChildTrees) {
2546 const QModelIndex sourceParent = mapFromSource(sourceTopLeft);
2547 Q_ASSERT(sourceParent.
isValid());
2548 const int rowCount =
sourceModel()->rowCount(sourceParent);
2549 if (rowCount < it->bottom()) {
2550 Q_ASSERT(sourceTopLeft.
isValid());
2551 Q_ASSERT(it->bottomRight().isValid());
2552 const QModelIndex sourceBottomRight = mapToSource(it->bottomRight());
2553 Q_ASSERT(sourceBottomRight.
isValid());
2554 sourceSelection.
append(QItemSelectionRange(sourceTopLeft, sourceBottomRight));
2558 const QModelIndex sourceBottomRight =
sourceModel()->index(rowCount - 1, it->right(), sourceParent);
2559 Q_ASSERT(sourceTopLeft.
isValid());
2560 Q_ASSERT(sourceBottomRight.
isValid());
2561 sourceSelection.
append(QItemSelectionRange(sourceTopLeft, sourceBottomRight));
2563 extraSelection.
append(QItemSelectionRange(
createIndex(it->top() - rowCount, it->right()), it->bottomRight()));
2565 QItemSelection topSelection;
2566 const QModelIndex idx =
createIndex(it->top(), it->right());
2567 const QModelIndex sourceIdx = mapToSource(idx);
2568 Q_ASSERT(sourceIdx.
isValid());
2569 topSelection.
append(QItemSelectionRange(sourceTopLeft, sourceIdx));
2570 for (
int i = it->top() + 1; i <= it->bottom(); ++i) {
2573 Q_ASSERT(
left.isValid());
2574 Q_ASSERT(
right.isValid());
2575 topSelection.
append(QItemSelectionRange(left, right));
2577 sourceSelection += kNormalizeSelection(topSelection);
2581 sourceSelection << mapSelectionToSource(extraSelection);
2582 return sourceSelection;
2585#include "moc_kselectionproxymodel.cpp"
This class facilitates easy mapping of indexes and selections through proxy models.
A Proxy Model which presents a subset of its source model to observers.
KSelectionProxyModel()
Default constructor.
void setFilterBehavior(FilterBehavior behavior)
Set the filter behaviors of this model.
void setSourceModel(QAbstractItemModel *sourceModel) override
reimp.
~KSelectionProxyModel() override
dtor
KSelectionProxyModel(QItemSelectionModel *selectionModel, QObject *parent=nullptr)
ctor.
Q_SCRIPTABLE QString start(QString train="")
Q_SCRIPTABLE Q_NOREPLY void start()
KIOCORE_EXPORT QStringList list(const QString &fileClass)
const QList< QKeySequence > & end()
QAbstractItemModel(QObject *parent)
QModelIndex createIndex(int row, int column, const void *ptr) const const
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles)
bool hasIndex(int row, int column, const QModelIndex &parent) const const
void layoutAboutToBeChanged(const QList< QPersistentModelIndex > &parents, QAbstractItemModel::LayoutChangeHint hint)
void layoutChanged(const QList< QPersistentModelIndex > &parents, QAbstractItemModel::LayoutChangeHint hint)
virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const const
void modelAboutToBeReset()
virtual int rowCount(const QModelIndex &parent) const const=0
void rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
void rowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
void rowsInserted(const QModelIndex &parent, int first, int last)
void rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
void rowsRemoved(const QModelIndex &parent, int first, int last)
QAbstractProxyModel(QObject *parent)
virtual Qt::ItemFlags flags(const QModelIndex &index) const const override
virtual QMimeData * mimeData(const QModelIndexList &indexes) const const override
virtual QStringList mimeTypes() const const override
virtual void setSourceModel(QAbstractItemModel *sourceModel)
virtual Qt::DropActions supportedDropActions() const const override
const_iterator constBegin() const const
const_iterator constEnd() const const
iterator insert(const Key &key, const T &value)
bool contains(const QModelIndex &index) const const
QModelIndexList indexes() const const
void merge(const QItemSelection &other, QItemSelectionModel::SelectionFlags command)
void modelChanged(QAbstractItemModel *model)
const QPersistentModelIndex & bottomRight() const const
bool contains(const QModelIndex &index) const const
const QPersistentModelIndex & topLeft() const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
const_iterator constBegin() const const
const_iterator constEnd() const const
iterator erase(const_iterator begin, const_iterator end)
bool isEmpty() const const
qsizetype size() const const
QVariant data(int role) const const
void * internalPointer() const const
bool isValid() const const
const QAbstractItemModel * model() const const
QModelIndex parent() const const
QModelIndex sibling(int row, int column) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void destroyed(QObject *obj)
bool disconnect(const QMetaObject::Connection &connection)
QObject * parent() const const
bool isValid() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)