diff options
Diffstat (limited to 'dev-qt/qtcore/files/qtcore-5.7.1-qsfpm-1.patch')
-rw-r--r-- | dev-qt/qtcore/files/qtcore-5.7.1-qsfpm-1.patch | 252 |
1 files changed, 0 insertions, 252 deletions
diff --git a/dev-qt/qtcore/files/qtcore-5.7.1-qsfpm-1.patch b/dev-qt/qtcore/files/qtcore-5.7.1-qsfpm-1.patch deleted file mode 100644 index 9edbe18617a2..000000000000 --- a/dev-qt/qtcore/files/qtcore-5.7.1-qsfpm-1.patch +++ /dev/null @@ -1,252 +0,0 @@ -From 3bd0fd8f97e7a33a874929a383a42e6c710bfff3 Mon Sep 17 00:00:00 2001 -From: Stephen Kelly <steveire@gmail.com> -Date: Sat, 17 Dec 2016 06:20:06 +0000 -Subject: [PATCH] QSFPM: Fix handling of source model layout change - -In sourceLayoutAboutToBeChanged the source model update is ignored if -the affected parents are filtered out anyway. The same logic is -attempted in the sourceLayoutChanged slot, but there the early-return -logic is applied too late - the mapping is cleared before performing the -early-return. Because pointers into the mapping are used in the -internalPointer of QModelIndexes in this class, persistent indexes used -later will segfault when attempting to dereference it. - -Additionally, if a parent becomes invalid as a result of the -layoutChange, it would be filtered out by the condition in the loop, -resulting in a different result in the comparison of emptiness of the -parents container. - -Fix that by persisting the parent's container, and performing the test -for early-return before clearing the mapping. - -Task-number: QTBUG-47711 -Task-number: QTBUG-32981 -Change-Id: If45e8a1c97d39454160f52041bc9ae7e337dce97 -Reviewed-by: David Faure <david.faure@kdab.com> ---- - src/corelib/itemmodels/qsortfilterproxymodel.cpp | 31 ++--- - .../tst_qsortfilterproxymodel.cpp | 126 +++++++++++++++++++++ - 2 files changed, 137 insertions(+), 20 deletions(-) - -diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp -index b0ddfa8..3331521 100644 ---- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp -+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp -@@ -171,6 +171,7 @@ public: - QRowsRemoval itemsBeingRemoved; - - QModelIndexPairList saved_persistent_indexes; -+ QList<QPersistentModelIndex> saved_layoutChange_parents; - - QHash<QModelIndex, Mapping *>::const_iterator create_mapping( - const QModelIndex &source_parent) const; -@@ -1331,23 +1332,23 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList<Q - Q_UNUSED(hint); // We can't forward Hint because we might filter additional rows or columns - saved_persistent_indexes.clear(); - -- QList<QPersistentModelIndex> parents; -+ saved_layoutChange_parents.clear(); - for (const QPersistentModelIndex &parent : sourceParents) { - if (!parent.isValid()) { -- parents << QPersistentModelIndex(); -+ saved_layoutChange_parents << QPersistentModelIndex(); - continue; - } - const QModelIndex mappedParent = q->mapFromSource(parent); - // Might be filtered out. - if (mappedParent.isValid()) -- parents << mappedParent; -+ saved_layoutChange_parents << mappedParent; - } - - // All parents filtered out. -- if (!sourceParents.isEmpty() && parents.isEmpty()) -+ if (!sourceParents.isEmpty() && saved_layoutChange_parents.isEmpty()) - return; - -- emit q->layoutAboutToBeChanged(parents); -+ emit q->layoutAboutToBeChanged(saved_layoutChange_parents); - if (persistent.indexes.isEmpty()) - return; - -@@ -1359,6 +1360,9 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged(const QList<QPersisten - Q_Q(QSortFilterProxyModel); - Q_UNUSED(hint); // We can't forward Hint because we might filter additional rows or columns - -+ if (!sourceParents.isEmpty() && saved_layoutChange_parents.isEmpty()) -+ return; -+ - // Optimize: We only actually have to clear the mapping related to the contents of - // sourceParents, not everything. - qDeleteAll(source_index_mapping); -@@ -1373,21 +1377,8 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged(const QList<QPersisten - source_index_mapping.clear(); - } - -- QList<QPersistentModelIndex> parents; -- for (const QPersistentModelIndex &parent : sourceParents) { -- if (!parent.isValid()) { -- parents << QPersistentModelIndex(); -- continue; -- } -- const QModelIndex mappedParent = q->mapFromSource(parent); -- if (mappedParent.isValid()) -- parents << mappedParent; -- } -- -- if (!sourceParents.isEmpty() && parents.isEmpty()) -- return; -- -- emit q->layoutChanged(parents); -+ emit q->layoutChanged(saved_layoutChange_parents); -+ saved_layoutChange_parents.clear(); - } - - void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeInserted( -diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp -index 38e3c68..6b98d9f 100644 ---- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp -+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp -@@ -145,6 +145,8 @@ private slots: - void canDropMimeData(); - void filterHint(); - -+ void sourceLayoutChangeLeavesValidPersistentIndexes(); -+ - protected: - void buildHierarchy(const QStringList &data, QAbstractItemModel *model); - void checkHierarchy(const QStringList &data, const QAbstractItemModel *model); -@@ -4181,5 +4183,129 @@ void tst_QSortFilterProxyModel::filterHint() - QAbstractItemModel::NoLayoutChangeHint); - } - -+/** -+ -+ Creates a model where each item has one child, to a set depth, -+ and the last item has no children. For a model created with -+ setDepth(4): -+ -+ - 1 -+ - - 2 -+ - - - 3 -+ - - - - 4 -+*/ -+class StepTreeModel : public QAbstractItemModel -+{ -+ Q_OBJECT -+public: -+ StepTreeModel(QObject * parent = 0) -+ : QAbstractItemModel(parent), m_depth(0) {} -+ -+ int columnCount(const QModelIndex& = QModelIndex()) const override { return 1; } -+ -+ int rowCount(const QModelIndex& parent = QModelIndex()) const override -+ { -+ quintptr parentId = (parent.isValid()) ? parent.internalId() : 0; -+ return (parentId < m_depth) ? 1 : 0; -+ } -+ -+ QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override -+ { -+ if (role != Qt::DisplayRole) -+ return QVariant(); -+ -+ return QString::number(index.internalId()); -+ } -+ -+ QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const override -+ { -+ quintptr parentId = (parent.isValid()) ? parent.internalId() : 0; -+ if (parentId >= m_depth) -+ return QModelIndex(); -+ -+ return createIndex(0, 0, parentId + 1); -+ } -+ -+ QModelIndex parent(const QModelIndex& index) const override -+ { -+ if (index.internalId() == 0) -+ return QModelIndex(); -+ -+ return createIndex(0, 0, index.internalId() - 1); -+ } -+ -+ void setDepth(quintptr depth) -+ { -+ int parentIdWithLayoutChange = (m_depth < depth) ? m_depth : depth; -+ -+ QList<QPersistentModelIndex> parentsOfLayoutChange; -+ parentsOfLayoutChange.push_back(createIndex(0, 0, parentIdWithLayoutChange)); -+ -+ layoutAboutToBeChanged(parentsOfLayoutChange); -+ -+ auto existing = persistentIndexList(); -+ -+ QList<QModelIndex> updated; -+ -+ for (auto idx : existing) { -+ if (indexDepth(idx) <= depth) -+ updated.push_back(idx); -+ else -+ updated.push_back({}); -+ } -+ -+ m_depth = depth; -+ -+ changePersistentIndexList(existing, updated); -+ -+ layoutChanged(parentsOfLayoutChange); -+ } -+ -+private: -+ static quintptr indexDepth(QModelIndex const& index) -+ { -+ return (index.isValid()) ? 1 + indexDepth(index.parent()) : 0; -+ } -+ -+private: -+ quintptr m_depth; -+}; -+ -+void tst_QSortFilterProxyModel::sourceLayoutChangeLeavesValidPersistentIndexes() -+{ -+ StepTreeModel model; -+ Q_SET_OBJECT_NAME(model); -+ model.setDepth(4); -+ -+ QSortFilterProxyModel proxy1; -+ proxy1.setSourceModel(&model); -+ Q_SET_OBJECT_NAME(proxy1); -+ -+ proxy1.setFilterRegExp("1|2"); -+ -+ // The current state of things: -+ // model proxy -+ // - 1 - 1 -+ // - - 2 - - 2 -+ // - - - 3 -+ // - - - - 4 -+ -+ // The setDepth call below removes '4' with a layoutChanged call. -+ // Because the proxy filters that out anyway, the proxy doesn't need -+ // to emit any signals or update persistent indexes. -+ -+ QPersistentModelIndex persistentIndex = proxy1.index(0, 0, proxy1.index(0, 0)); -+ -+ model.setDepth(3); -+ -+ // Calling parent() causes the internalPointer to be used. -+ // Before fixing QTBUG-47711, that could be a dangling pointer. -+ // The use of qDebug here makes sufficient use of the heap to -+ // cause corruption at runtime with normal use on linux (before -+ // the fix). valgrind confirms the fix. -+ qDebug() << persistentIndex.parent(); -+ QVERIFY(persistentIndex.parent().isValid()); -+} -+ - QTEST_MAIN(tst_QSortFilterProxyModel) - #include "tst_qsortfilterproxymodel.moc" --- -2.7.4 - - |