9#include "kdescendantsproxymodel.h"
15typedef KHash2Map<QPersistentModelIndex, int> Mapping;
17class KDescendantsProxyModelPrivate
22 , m_ignoreNextLayoutAboutToBeChanged(false)
23 , m_ignoreNextLayoutChanged(false)
24 , m_relayouting(false)
25 , m_displayAncestorData(false)
26 , m_ancestorSeparator(QStringLiteral(
" / "))
35 void scheduleProcessPendingParents()
const;
36 void processPendingParents();
38 void synchronousMappingRefresh();
40 void updateInternalIndexes(
int start,
int offset);
42 void resetInternalData();
45 void sourceRowsAboutToBeInserted(
const QModelIndex &,
int,
int);
46 void sourceRowsInserted(
const QModelIndex &,
int,
int);
47 void sourceRowsAboutToBeRemoved(
const QModelIndex &,
int,
int);
48 void sourceRowsRemoved(
const QModelIndex &,
int,
int);
51 void sourceModelAboutToBeReset();
52 void sourceModelReset();
53 void sourceLayoutAboutToBeChanged();
54 void sourceLayoutChanged();
56 void sourceModelDestroyed();
60 QPair<int, int> m_removePair;
61 QPair<int, int> m_insertPair;
63 bool m_expandsByDefault =
true;
64 bool m_ignoreNextLayoutAboutToBeChanged;
65 bool m_ignoreNextLayoutChanged;
68 bool m_displayAncestorData;
75 QModelIndexList m_proxyIndexes;
78void KDescendantsProxyModelPrivate::resetInternalData()
82 m_layoutChangePersistentIndexes.
clear();
83 m_proxyIndexes.clear();
86void KDescendantsProxyModelPrivate::synchronousMappingRefresh()
90 m_pendingParents.
clear();
95 while (!m_pendingParents.
isEmpty()) {
96 processPendingParents();
98 m_relayouting =
false;
101void KDescendantsProxyModelPrivate::scheduleProcessPendingParents()
const
103 const_cast<KDescendantsProxyModelPrivate *
>(
this)->processPendingParents();
106void KDescendantsProxyModelPrivate::processPendingParents()
116 while (it != end && it != m_pendingParents.
end()) {
118 if (!sourceParent.
isValid() && m_rowCount > 0) {
120 it = m_pendingParents.
erase(it);
123 if (!q->isSourceIndexVisible(sourceParent)) {
125 it = m_pendingParents.
erase(it);
129 const int rowCount = q->sourceModel()->rowCount(sourceParent);
133 it = m_pendingParents.
erase(it);
138 Q_ASSERT(sourceIndex.
isValid());
140 const QModelIndex proxyParent = q->mapFromSource(sourceParent);
143 const int proxyEndRow = proxyParent.
row() + rowCount;
144 const int proxyStartRow = proxyEndRow - rowCount + 1;
146 if (!m_relayouting) {
147 q->beginInsertRows(
QModelIndex(), proxyStartRow, proxyEndRow);
150 updateInternalIndexes(proxyStartRow, rowCount);
151 m_mapping.insert(sourceIndex, proxyEndRow);
152 it = m_pendingParents.
erase(it);
153 m_rowCount += rowCount;
155 if (!m_relayouting) {
159 for (
int sourceRow = 0; sourceRow < rowCount; ++sourceRow) {
160 static const int column = 0;
161 const QModelIndex child = q->sourceModel()->index(sourceRow, column, sourceParent);
164 if (q->sourceModel()->hasChildren(child) && q->isSourceIndexExpanded(child) && q->sourceModel()->rowCount(child) > 0) {
165 newPendingParents.
append(child);
169 m_pendingParents += newPendingParents;
170 if (!m_pendingParents.
isEmpty()) {
171 processPendingParents();
176void KDescendantsProxyModelPrivate::updateInternalIndexes(
int start,
int offset)
181 Mapping::right_iterator it = m_mapping.rightLowerBound(
start);
182 const Mapping::right_iterator
end = m_mapping.rightEnd();
185 updates.
insert(it.key() + offset, *it);
194 for (; it !=
end; ++it) {
195 m_mapping.insert(it.value(), it.key());
202 , d_ptr(new KDescendantsProxyModelPrivate(this))
212 roleNames[LevelRole] =
"kDescendantLevel";
213 roleNames[ExpandableRole] =
"kDescendantExpandable";
214 roleNames[ExpandedRole] =
"kDescendantExpanded";
215 roleNames[HasSiblingsRole] =
"kDescendantHasSiblings";
221 if (d_ptr->m_expandsByDefault == expand) {
226 d_ptr->m_expandsByDefault = expand;
227 d_ptr->m_expandedSourceIndexes.clear();
228 d_ptr->m_collapsedSourceIndexes.clear();
234 return d_ptr->m_expandsByDefault;
242 }
else if (d_ptr->m_expandsByDefault) {
273 if (d_ptr->m_expandsByDefault) {
279 d_ptr->m_pendingParents << sourceIndex;
280 d_ptr->scheduleProcessPendingParents();
281 Q_EMIT sourceIndexExpanded(sourceIndex);
283 const QModelIndex index = mapFromSource(sourceIndex);
293 const int row = mapFromSource(sourceIndex).
row();
294 const int rowStart = row + 1;
305 for (
int i = 0; i < nRows; ++i) {
316 if (d_ptr->m_expandsByDefault) {
323 Mapping::right_iterator it = d_ptr->m_mapping.rightLowerBound(rowStart);
324 const Mapping::right_iterator endIt = d_ptr->m_mapping.rightUpperBound(rowEnd);
326 if (endIt != d_ptr->m_mapping.rightEnd()) {
327 while (it != endIt) {
328 it = d_ptr->m_mapping.eraseRight(it);
331 while (it != d_ptr->m_mapping.rightUpperBound(rowEnd)) {
332 it = d_ptr->m_mapping.eraseRight(it);
337 d_ptr->m_removePair = qMakePair(rowStart, rowEnd);
339 d_ptr->synchronousMappingRefresh();
341 Q_EMIT sourceIndexCollapsed(sourceIndex);
343 const QModelIndex ownIndex = mapFromSource(sourceIndex);
361 bool displayChanged = (display != d->m_displayAncestorData);
362 d->m_displayAncestorData = display;
363 if (displayChanged) {
364 Q_EMIT displayAncestorDataChanged();
366 Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1), changedRoles);
373 return d->m_displayAncestorData;
379 bool separatorChanged = (separator != d->m_ancestorSeparator);
380 d->m_ancestorSeparator = separator;
381 if (separatorChanged) {
382 Q_EMIT ancestorSeparatorChanged();
383 if (d->m_displayAncestorData) {
385 Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1), changedRoles);
393 return d->m_ancestorSeparator;
407 d_ptr->m_expandedSourceIndexes.clear();
411 d->sourceRowsAboutToBeInserted(
parent,
start, end);
429 [d](
const QModelIndex &srcParent,
int srcStart,
int srcEnd,
const QModelIndex &destParent,
int destStart) {
430 d->sourceRowsAboutToBeMoved(srcParent, srcStart, srcEnd, destParent, destStart);
436 [d](
const QModelIndex &srcParent,
int srcStart,
int srcEnd,
const QModelIndex &destParent,
int destStart) {
437 d->sourceRowsMoved(srcParent, srcStart, srcEnd, destParent, destStart);
441 d->sourceModelAboutToBeReset();
445 d->sourceModelReset();
449 d->sourceDataChanged(topLeft, bottomRight);
453 d->sourceLayoutAboutToBeChanged();
457 d->sourceLayoutChanged();
461 d->sourceModelDestroyed();
467 d->synchronousMappingRefresh();
471 Q_EMIT sourceModelChanged();
480bool KDescendantsProxyModel::hasChildren(
const QModelIndex &parent)
const
483 return !(d->m_mapping.isEmpty() ||
parent.isValid());
486int KDescendantsProxyModel::rowCount(
const QModelIndex &parent)
const
493 if (d->m_mapping.isEmpty() &&
sourceModel()->hasChildren()) {
494 const_cast<KDescendantsProxyModelPrivate *
>(d)->synchronousMappingRefresh();
496 return d->m_rowCount;
519 const Mapping::right_const_iterator result = d->m_mapping.rightLowerBound(proxyIndex.
row());
520 Q_ASSERT(result != d->m_mapping.rightEnd());
522 const int proxyLastRow = result.key();
523 const QModelIndex sourceLastChild = result.value();
524 Q_ASSERT(sourceLastChild.
isValid());
555 int verticalDistance = proxyLastRow - proxyIndex.
row();
561 const int ancestorRow = ancestor.
row();
562 if (verticalDistance <= ancestorRow) {
563 return ancestor.
sibling(ancestorRow - verticalDistance, proxyIndex.
column());
565 verticalDistance -= (ancestorRow + 1);
566 ancestor = ancestor.
parent();
568 Q_ASSERT(!
"Didn't find target row.");
580 if (d->m_mapping.isEmpty()) {
587 Mapping::right_const_iterator it = d->m_mapping.rightConstBegin();
588 const Mapping::right_const_iterator
end = d->m_mapping.rightConstEnd();
590 Mapping::right_const_iterator result =
end;
596 for (; it !=
end; ++it) {
598 bool found_block =
false;
601 if (ancestor == sourceParent && index.
row() >= sourceIndex.
row()) {
603 if (result == end || it.key() < result.key()) {
610 if (found_block && !index.
isValid())
617 Q_ASSERT(result != end);
618 const QModelIndex sourceLastChild = result.value();
619 int proxyRow = result.key();
623 if (ancestor == sourceParent) {
626 proxyRow -= (index.
row() + 1);
629 Q_ASSERT(!
"Didn't find valid proxy mapping.");
634int KDescendantsProxyModel::columnCount(
const QModelIndex &parent)
const
662 sourceIndex = sourceIndex.
parent();
663 while (sourceIndex.
isValid()) {
664 displayData.
prepend(d->m_ancestorSeparator);
666 sourceIndex = sourceIndex.
parent();
669 }
else if (role == LevelRole) {
672 while (sourceIndex.
isValid()) {
673 sourceIndex = sourceIndex.
parent();
677 }
else if (role == ExpandableRole) {
680 }
else if (role == ExpandedRole) {
682 }
else if (role == HasSiblingsRole) {
685 while (sourceIndex.
isValid()) {
687 sourceIndex = sourceIndex.
parent();
691 return sourceIndex.
data(role);
702 return sourceModel()->headerData(section, orientation, role);
716void KDescendantsProxyModelPrivate::notifyhasSiblings(
const QModelIndex &parent)
724 QModelIndex localParent = q->mapFromSource(parent);
725 Q_EMIT q->dataChanged(localParent, localParent, {KDescendantsProxyModel::HasSiblingsRole});
726 for (
int i = 0; i < q->sourceModel()->rowCount(parent); ++i) {
727 notifyhasSiblings(q->sourceModel()->index(i, 0, parent));
731void KDescendantsProxyModelPrivate::sourceRowsAboutToBeInserted(
const QModelIndex &parent,
int start,
int end)
735 if (parent.
isValid() && (!q->isSourceIndexExpanded(parent) || !q->isSourceIndexVisible(parent))) {
739 if (!q->sourceModel()->hasChildren(parent)) {
740 Q_ASSERT(q->sourceModel()->rowCount(parent) == 0);
747 const int rowCount = q->sourceModel()->rowCount(parent);
749 if (rowCount >
start) {
751 proxyStart = q->mapFromSource(belowStart).row();
752 }
else if (rowCount == 0) {
753 proxyStart = q->mapFromSource(parent).row() + 1;
755 Q_ASSERT(rowCount ==
start);
756 static const int column = 0;
757 QModelIndex idx = q->sourceModel()->index(rowCount - 1, column, parent);
758 while (q->isSourceIndexExpanded(idx) && q->sourceModel()->hasChildren(idx) && q->sourceModel()->rowCount(idx) > 0) {
759 idx = q->sourceModel()->index(q->sourceModel()->rowCount(idx) - 1, column, idx);
762 proxyStart = q->mapFromSource(idx).row() + 1;
764 const int proxyEnd = proxyStart + (
end -
start);
766 m_insertPair = qMakePair(proxyStart, proxyEnd);
767 q->beginInsertRows(
QModelIndex(), proxyStart, proxyEnd);
770void KDescendantsProxyModelPrivate::sourceRowsInserted(
const QModelIndex &parent,
int start,
int end)
773 if (parent.
isValid() && (!q->isSourceIndexExpanded(parent) || !q->isSourceIndexVisible(parent))) {
774 const QModelIndex index = q->mapFromSource(parent);
775 Q_EMIT q->dataChanged(index,
777 {KDescendantsProxyModel::ExpandableRole, KDescendantsProxyModel::ExpandedRole, KDescendantsProxyModel::HasSiblingsRole});
779 notifyhasSiblings(q->sourceModel()->index(
start - 1, 0, parent));
783 Q_ASSERT(q->sourceModel()->index(
start, 0, parent).isValid());
785 const int rowCount = q->sourceModel()->rowCount(parent);
786 Q_ASSERT(rowCount > 0);
788 const int difference =
end -
start + 1;
790 if (rowCount == difference) {
791 const QModelIndex index = q->mapFromSource(parent);
793 Q_EMIT q->dataChanged(index,
795 {KDescendantsProxyModel::ExpandableRole, KDescendantsProxyModel::ExpandedRole, KDescendantsProxyModel::HasSiblingsRole});
798 m_pendingParents.
append(parent);
799 scheduleProcessPendingParents();
801 notifyhasSiblings(q->sourceModel()->index(
start - 1, 0, parent));
806 const int proxyStart = m_insertPair.first;
808 Q_ASSERT(proxyStart >= 0);
810 updateInternalIndexes(proxyStart, difference);
812 if (rowCount - 1 == end) {
844 Q_ASSERT(!m_mapping.isEmpty());
845 static const int column = 0;
846 const QModelIndex oldIndex = q->sourceModel()->index(rowCount - 1 - difference, column, parent);
847 Q_ASSERT(m_mapping.leftContains(oldIndex));
849 const QModelIndex newIndex = q->sourceModel()->index(rowCount - 1, column, parent);
863 while (q->isSourceIndexExpanded(indexAbove) && q->sourceModel()->hasChildren(indexAbove)) {
864 Q_ASSERT(q->sourceModel()->rowCount(indexAbove) > 0);
865 indexAbove = q->sourceModel()->index(q->sourceModel()->rowCount(indexAbove) - 1, column, indexAbove);
867 Q_ASSERT(!q->isSourceIndexExpanded(indexAbove) || q->sourceModel()->rowCount(indexAbove) == 0);
870 Q_ASSERT(m_mapping.leftContains(indexAbove));
872 const int newProxyRow = m_mapping.leftToRight(indexAbove) + difference;
875 m_mapping.removeLeft(oldIndex);
878 m_mapping.insert(newIndex, newProxyRow);
881 for (
int row =
start; row <=
end; ++row) {
882 static const int column = 0;
883 const QModelIndex idx = q->sourceModel()->index(row, column, parent);
886 if (q->isSourceIndexExpanded(idx) && q->sourceModel()->hasChildren(idx) && q->sourceModel()->rowCount(idx) > 0) {
887 m_pendingParents.
append(idx);
891 m_rowCount += difference;
894 scheduleProcessPendingParents();
896 const QModelIndex index = q->mapFromSource(parent);
897 Q_EMIT q->dataChanged(index,
899 {KDescendantsProxyModel::ExpandableRole, KDescendantsProxyModel::ExpandedRole, KDescendantsProxyModel::HasSiblingsRole});
903 notifyhasSiblings(q->sourceModel()->index(
start - 1, 0, parent));
907void KDescendantsProxyModelPrivate::sourceRowsAboutToBeRemoved(
const QModelIndex &parent,
int start,
int end)
911 if (!q->isSourceIndexExpanded(parent) || !q->isSourceIndexVisible(parent)) {
915 const int proxyStart = q->mapFromSource(q->sourceModel()->index(
start, 0, parent)).row();
917 static const int column = 0;
918 QModelIndex idx = q->sourceModel()->index(end, column, parent);
919 while (q->sourceModel()->hasChildren(idx) && q->sourceModel()->rowCount(idx) > 0) {
920 idx = q->sourceModel()->index(q->sourceModel()->rowCount(idx) - 1, column, idx);
922 const int proxyEnd = q->mapFromSource(idx).row();
924 for (
int i =
start; i <=
end; ++i) {
925 QModelIndex idx = q->sourceModel()->index(i, column, parent);
929 m_removePair = qMakePair(proxyStart, proxyEnd);
931 q->beginRemoveRows(
QModelIndex(), proxyStart, proxyEnd);
936 static const int column = 0;
938 Q_ASSERT(model->
rowCount(parent) > 0);
939 for (
int row = 0; row < model->
rowCount(parent); ++row) {
944 return getFirstDeepest(model, child, count);
947 return model->
index(model->
rowCount(parent) - 1, column, parent);
950void KDescendantsProxyModelPrivate::sourceRowsRemoved(
const QModelIndex &parent,
int start,
int end)
955 if (!q->isSourceIndexExpanded(parent) || !q->isSourceIndexVisible(parent)) {
957 const QModelIndex index = q->mapFromSource(parent);
958 Q_EMIT q->dataChanged(index, index, {KDescendantsProxyModel::ExpandableRole, KDescendantsProxyModel::ExpandedRole});
963 const int rowCount = q->sourceModel()->rowCount(parent);
965 const int proxyStart = m_removePair.first;
966 const int proxyEnd = m_removePair.second;
968 const int difference = proxyEnd - proxyStart + 1;
970 Mapping::right_iterator it = m_mapping.rightLowerBound(proxyStart);
971 const Mapping::right_iterator endIt = m_mapping.rightUpperBound(proxyEnd);
973 if (endIt != m_mapping.rightEnd()) {
974 while (it != endIt) {
975 it = m_mapping.eraseRight(it);
978 while (it != m_mapping.rightUpperBound(proxyEnd)) {
979 it = m_mapping.eraseRight(it);
984 m_removePair = qMakePair(-1, -1);
985 m_rowCount -= difference;
986 Q_ASSERT(m_rowCount >= 0);
988 updateInternalIndexes(proxyStart, -1 * difference);
990 if (rowCount !=
start || rowCount == 0) {
993 const QModelIndex index = q->mapFromSource(parent);
994 Q_EMIT q->dataChanged(index, index, {KDescendantsProxyModel::ExpandableRole, KDescendantsProxyModel::ExpandedRole});
997 notifyhasSiblings(q->sourceModel()->index(
start - 1, 0, parent));
1002 static const int column = 0;
1003 const QModelIndex newEnd = q->sourceModel()->index(rowCount - 1, column, parent);
1006 if (m_mapping.isEmpty()) {
1007 m_mapping.insert(newEnd, newEnd.
row());
1010 notifyhasSiblings(q->sourceModel()->index(
start - 1, 0, parent));
1014 if (q->sourceModel()->hasChildren(newEnd)) {
1016 const QModelIndex firstDeepest = getFirstDeepest(q->sourceModel(), newEnd, &count);
1017 Q_ASSERT(firstDeepest.
isValid());
1018 const int firstDeepestProxy = m_mapping.leftToRight(firstDeepest);
1020 m_mapping.insert(newEnd, firstDeepestProxy - count);
1023 notifyhasSiblings(q->sourceModel()->index(
start - 1, 0, parent));
1027 Mapping::right_iterator lowerBound = m_mapping.rightLowerBound(proxyStart);
1028 if (lowerBound == m_mapping.rightEnd()) {
1029 int proxyRow = std::prev(lowerBound).key();
1031 for (
int row = newEnd.
row(); row >= 0; --row) {
1032 const QModelIndex newEndSibling = q->sourceModel()->index(row, column, parent);
1033 if (!q->sourceModel()->hasChildren(newEndSibling)) {
1039 m_mapping.insert(newEnd, proxyRow);
1042 notifyhasSiblings(q->sourceModel()->index(
start - 1, 0, parent));
1045 }
else if (lowerBound == m_mapping.rightBegin()) {
1046 int proxyRow = rowCount - 1;
1048 while (trackedParent.
isValid()) {
1049 proxyRow += (trackedParent.
row() + 1);
1050 trackedParent = trackedParent.
parent();
1052 m_mapping.insert(newEnd, proxyRow);
1055 notifyhasSiblings(q->sourceModel()->index(
start - 1, 0, parent));
1059 const Mapping::right_iterator boundAbove = std::prev(lowerBound);
1067 if (target == boundAbove.value()) {
1068 m_mapping.insert(newEnd, count + boundAbove.key() + newEnd.
row() + 1);
1071 notifyhasSiblings(q->sourceModel()->index(
start - 1, 0, parent));
1075 count += (target.
row() + 1);
1076 target = target.
parent();
1085 Q_ASSERT(boundParent.
isValid());
1086 while (boundParent.
isValid()) {
1087 prevParent = boundParent;
1088 boundParent = boundParent.
parent();
1090 if (targetParents.
contains(prevParent)) {
1094 if (!m_mapping.leftContains(prevParent)) {
1098 if (m_mapping.leftToRight(prevParent) > boundAbove.key()) {
1105 int proxyRow = boundAbove.key();
1107 Q_ASSERT(prevParent.
isValid());
1108 proxyRow -= prevParent.
row();
1109 while (trackedParent != boundParent) {
1110 proxyRow += (trackedParent.
row() + 1);
1111 trackedParent = trackedParent.
parent();
1113 m_mapping.insert(newEnd, proxyRow + newEnd.
row());
1117 const QModelIndex oindex = q->mapFromSource(parent);
1118 QList<int> rolesChanged({KDescendantsProxyModel::ExpandableRole});
1120 if (!q->sourceModel()->hasChildren(parent)) {
1121 rolesChanged << KDescendantsProxyModel::ExpandedRole;
1122 }
else if (q->sourceModel()->rowCount(parent) <=
start) {
1123 const QModelIndex index = q->mapFromSource(q->sourceModel()->index(q->sourceModel()->rowCount(parent) - 1, 0, parent));
1124 Q_EMIT q->dataChanged(index, index, {KDescendantsProxyModel::ExpandedRole});
1127 Q_EMIT q->dataChanged(oindex, oindex, rolesChanged);
1131 notifyhasSiblings(q->sourceModel()->index(
start - 1, 0, parent));
1135void KDescendantsProxyModelPrivate::sourceRowsAboutToBeMoved(
const QModelIndex &srcParent,
1145 if (q->isSourceIndexExpanded(srcParent) && q->isSourceIndexVisible(srcParent)
1146 && (!q->isSourceIndexExpanded(destParent) || !q->isSourceIndexVisible(destParent))) {
1147 const QModelIndex proxySrcParent = q->mapFromSource(srcParent);
1148 const int proxyParentRow = proxySrcParent.
isValid() ? proxySrcParent.
row() : 0;
1149 q->beginRemoveRows(
QModelIndex(), proxyParentRow + srcStart, proxyParentRow + srcEnd);
1151 }
else if ((!q->isSourceIndexExpanded(srcParent) || !q->isSourceIndexVisible(srcParent)) && q->isSourceIndexExpanded(destParent)
1152 && q->isSourceIndexVisible(destParent)) {
1153 const QModelIndex proxyDestParent = q->mapFromSource(srcParent);
1154 const int proxyParentRow = proxyDestParent.
isValid() ? proxyDestParent.
row() : 0;
1156 q->beginInsertRows(
QModelIndex(), proxyParentRow + destStart, proxyParentRow + destStart + (srcEnd - srcStart));
1159 sourceLayoutAboutToBeChanged();
1162void KDescendantsProxyModelPrivate::sourceRowsMoved(
const QModelIndex &srcParent,
int srcStart,
int srcEnd,
const QModelIndex &destParent,
int destStart)
1169 Q_UNUSED(destParent)
1172 if (q->isSourceIndexExpanded(srcParent) && q->isSourceIndexVisible(srcParent)
1173 && (!q->isSourceIndexExpanded(destParent) || !q->isSourceIndexVisible(destParent))) {
1175 }
else if (!q->isSourceIndexExpanded(srcParent) && q->isSourceIndexExpanded(destParent)) {
1179 sourceLayoutChanged();
1181 const QModelIndex index1 = q->mapFromSource(srcParent);
1182 const QModelIndex index2 = q->mapFromSource(destParent);
1183 Q_EMIT q->dataChanged(index1, index1, {KDescendantsProxyModel::ExpandableRole});
1184 if (index1 != index2) {
1185 Q_EMIT q->dataChanged(index2, index2, {KDescendantsProxyModel::ExpandableRole});
1186 if (!q->sourceModel()->hasChildren(destParent)) {
1187 Q_EMIT q->dataChanged(index2, index2, {KDescendantsProxyModel::ExpandableRole});
1190 const QModelIndex lastIndex = q->mapFromSource(q->sourceModel()->index(q->sourceModel()->rowCount(srcParent) - 1, 0, srcParent));
1191 Q_EMIT q->dataChanged(lastIndex, lastIndex, {KDescendantsProxyModel::ExpandableRole});
1194 notifyhasSiblings(q->sourceModel()->index(srcStart - 1, 0, srcParent));
1196 if (destStart > 0) {
1197 notifyhasSiblings(q->sourceModel()->index(destStart - 1, 0, destParent));
1201void KDescendantsProxyModelPrivate::sourceModelAboutToBeReset()
1204 q->beginResetModel();
1205 m_relayouting =
true;
1208void KDescendantsProxyModelPrivate::sourceModelReset()
1211 resetInternalData();
1212 if (q->sourceModel()->hasChildren() && q->sourceModel()->rowCount() > 0) {
1214 scheduleProcessPendingParents();
1216 m_relayouting =
false;
1220void KDescendantsProxyModelPrivate::sourceLayoutAboutToBeChanged()
1224 if (m_ignoreNextLayoutChanged) {
1225 m_ignoreNextLayoutChanged =
false;
1229 if (m_mapping.isEmpty()) {
1233 Q_EMIT q->layoutAboutToBeChanged();
1236 const auto lst = q->persistentIndexList();
1237 for (
const QModelIndex &proxyPersistentIndex : lst) {
1238 m_proxyIndexes << proxyPersistentIndex;
1239 Q_ASSERT(proxyPersistentIndex.isValid());
1240 srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
1241 Q_ASSERT(srcPersistentIndex.
isValid());
1242 m_layoutChangePersistentIndexes << srcPersistentIndex;
1246void KDescendantsProxyModelPrivate::sourceLayoutChanged()
1250 if (m_ignoreNextLayoutAboutToBeChanged) {
1251 m_ignoreNextLayoutAboutToBeChanged =
false;
1255 if (m_mapping.isEmpty()) {
1261 synchronousMappingRefresh();
1263 for (
int i = 0; i < m_proxyIndexes.size(); ++i) {
1264 q->changePersistentIndex(m_proxyIndexes.at(i), q->mapFromSource(m_layoutChangePersistentIndexes.
at(i)));
1267 m_layoutChangePersistentIndexes.
clear();
1268 m_proxyIndexes.clear();
1270 Q_EMIT q->layoutChanged();
1273void KDescendantsProxyModelPrivate::sourceDataChanged(
const QModelIndex &topLeft,
const QModelIndex &bottomRight)
1284 Q_ASSERT(topLeft.
model() == q->sourceModel());
1285 Q_ASSERT(bottomRight.
model() == q->sourceModel());
1287 if (!q->isSourceIndexExpanded(topLeft.
parent()) || !q->isSourceIndexVisible(topLeft.
parent())) {
1291 const int topRow = topLeft.
row();
1292 const int bottomRow = bottomRight.
row();
1294 for (
int i = topRow; i <= bottomRow; ++i) {
1297 Q_ASSERT(sourceTopLeft.
isValid());
1298 const QModelIndex proxyTopLeft = q->mapFromSource(sourceTopLeft);
1302 const QModelIndex proxyBottomRight = q->mapFromSource(sourceBottomRight);
1303 Q_ASSERT(proxyTopLeft.
isValid());
1304 Q_ASSERT(proxyBottomRight.
isValid());
1305 Q_EMIT q->dataChanged(proxyTopLeft, proxyBottomRight);
1309void KDescendantsProxyModelPrivate::sourceModelDestroyed()
1311 resetInternalData();
1314QMimeData *KDescendantsProxyModel::mimeData(
const QModelIndexList &indexes)
const
1320 QModelIndexList sourceIndexes;
1322 sourceIndexes << mapToSource(index);
1327QStringList KDescendantsProxyModel::mimeTypes()
const
1344#include "moc_kdescendantsproxymodel.cpp"
Proxy Model for restructuring a Tree into a list.
KDescendantsProxyModel(QObject *parent=nullptr)
Creates a new descendant entities proxy model.
~KDescendantsProxyModel() override
Destroys the descendant entities proxy model.
void collapseSourceIndex(const QModelIndex &sourceIndex)
Maps a source index as collapsed in the proxy, all its children will be hidden.
void setAncestorSeparator(const QString &separator)
Sets the ancestor separator used between data of ancestors.
bool isSourceIndexExpanded(const QModelIndex &sourceIndex) const
virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits=1, Qt::MatchFlags flags=Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const override
Reimplemented to match all descendants.
void expandSourceIndex(const QModelIndex &sourceIndex)
Maps a source index as expanded in the proxy, all its children will become visible.
bool isSourceIndexVisible(const QModelIndex &sourceIndex) const
void setDisplayAncestorData(bool display)
Set whether to show ancestor data in the model.
bool expandsByDefault
If true, all the nodes in the whole tree will be expanded upon loading and all items of the source mo...
void setExpandsByDefault(bool expand)
If true, all the nodes in the whole tree will be expanded upon loading (default)
QString ancestorSeparator
void setSourceModel(QAbstractItemModel *model) override
Sets the source model of the proxy.
Q_SCRIPTABLE Q_NOREPLY void start()
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
QStringView level(QStringView ifopt)
const QList< QKeySequence > & begin()
void beginRemoveRows(const QModelIndex &parent, int first, int last)
QModelIndex createIndex(int row, int column, const void *ptr) const const
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles)
virtual bool hasChildren(const QModelIndex &parent) const const
bool hasIndex(int row, int column, const QModelIndex &parent) const const
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
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 void resetInternalData()
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)
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 QHash< int, QByteArray > roleNames() 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)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
bool contains(const AT &value) const const
iterator erase(const_iterator begin, const_iterator end)
bool isEmpty() const const
void prepend(parameter_type value)
void push_back(parameter_type value)
QVariant data(int role) 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(const QSet< T > &other) const const
bool remove(const T &value)
QString & prepend(QChar ch)
QVariant fromValue(T &&value)
QString toString() const const