qt5: 5.7.1 -> 5.8.0

This commit is contained in:
Danny Rawlins 2017-02-10 20:09:30 +11:00
parent 1774dc0f26
commit 855eb81199
8 changed files with 4203 additions and 3352 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
7524ffba8411119d867f673155ec91bc qt-everywhere-opensource-src-5.7.1.tar.xz
078d8a051c06abf28451fd2cdb7f19ce plasma-crash-1.patch
92daaa3ebd7cf10ee725b963e44c95a7 plasma-crash-2.patch
76ab122615f1ba2d68c83477f82e389e plasma-crash-3.patch
66660cd3d9e1a6fed36e88adcb72e9fe qt-everywhere-opensource-src-5.8.0.tar.xz
67165bacd3231b57d7b7db1e6bcb7d89 qt5-logo.png
c86af27562bbbe05c3defd63d00130fd qtbug-49061.patch
7b11584d9ea1ccb6c419e9b9816dee63 qtbug-55583.patch

View File

@ -5,21 +5,21 @@
# Depends on: dbus gdk-pixbuf gst-plugins-base libepoxy libmng mtdev xorg-libxcomposite xorg-libxcursor xorg-libxi xorg-libxinerama xorg-libxrandr xorg-xcb-util-image xorg-xcb-util-keysyms xorg-xcb-util-wm
name=qt5
version=5.7.1
version=5.8.0
release=1
source=(http://download.qt.io/official_releases/qt/${version::3}/$version/single/qt-everywhere-opensource-src-$version.tar.xz
qt5-logo.png
qtbug-49061.patch
qtbug-55583.patch)
plasma-crash-1.patch
plasma-crash-2.patch
plasma-crash-3.patch)
build() {
cd qt-everywhere-opensource-src-$version
# Don't unload plugins in QPluginLoader https://bugreports.qt.io/browse/QTBUG-49061
patch -p1 -d qtbase -i $SRC/qtbug-49061.patch
# Fix file chooser segfault on gnome/wayland https://bugreports.qt.io/browse/QTBUG-55583
patch -p1 -d qtbase -i $SRC/qtbug-55583.patch
# Fix some Plasma taskbar crashes https://bugs.kde.org/show_bug.cgi?id=342763
patch -p1 -d qtbase -i $SRC/plasma-crash-1.patch
patch -p1 -d qtbase -i $SRC/plasma-crash-2.patch
patch -p1 -d qtbase -i $SRC/plasma-crash-3.patch
# Respect system CXX
[ "$CXX" ] || CXX=g++
@ -36,10 +36,6 @@ build() {
sed -i "s|^\(QMAKE_LFLAGS_RELEASE.*\)|\1 ${LDFLAGS}|" \
qtbase/mkspecs/common/g++-unix.conf
# Fix quoting bug
sed -i 's|"$COMPILER" -c|$COMPILER -c|' \
qtbase/config.tests/unix/fvisibility.test
export QTDIR="$PWD"
export LD_LIBRARY_PATH="$QTDIR/qtbase/lib:$QTDIR/qttools/lib:$LD_LIBRARY_PATH"
export QT_PLUGIN_PATH="$QTDIR/qtbase/plugins"

248
qt5/plasma-crash-1.patch Normal file
View File

@ -0,0 +1,248 @@
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 @@ class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate
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"

191
qt5/plasma-crash-2.patch Normal file
View File

@ -0,0 +1,191 @@
From 0874861bcc70313c343aba5e5566ed30b69eed1c Mon Sep 17 00:00:00 2001
From: Stephen Kelly <steveire@gmail.com>
Date: Mon, 19 Dec 2016 21:13:57 +0000
Subject: [PATCH] QSFPM: Remove data manipulation from move handlers
Similar to the fix in the parent commit, incorrect updating of the
internal data structures during layout changes can lead to dangling
pointers being dereferenced later. Moves are treated as layoutChanges
by this proxy by forwarding to the appropriate method. However, data is
incorrectly cleared prior to that forwarding. Remove that, and let the
layoutChange handling take appropriate action.
Change-Id: Iee951e37152328a4e6a5fb8e5385c32a2fe4c0bd
Reviewed-by: David Faure <david.faure@kdab.com>
---
src/corelib/itemmodels/qsortfilterproxymodel.cpp | 67 ++++------------------
.../tst_qsortfilterproxymodel.cpp | 46 +++++++++++++++
2 files changed, 58 insertions(+), 55 deletions(-)
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 3331521..226a240 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -1418,49 +1418,27 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsRemoved(
void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeMoved(
const QModelIndex &sourceParent, int /* sourceStart */, int /* sourceEnd */, const QModelIndex &destParent, int /* dest */)
{
- Q_Q(QSortFilterProxyModel);
// Because rows which are contiguous in the source model might not be contiguous
// in the proxy due to sorting, the best thing we can do here is be specific about what
// parents are having their children changed.
// Optimize: Emit move signals if the proxy is not sorted. Will need to account for rows
// being filtered out though.
- saved_persistent_indexes.clear();
-
QList<QPersistentModelIndex> parents;
- parents << q->mapFromSource(sourceParent);
+ parents << sourceParent;
if (sourceParent != destParent)
- parents << q->mapFromSource(destParent);
- emit q->layoutAboutToBeChanged(parents);
- if (persistent.indexes.isEmpty())
- return;
- saved_persistent_indexes = store_persistent_indexes();
+ parents << destParent;
+ _q_sourceLayoutAboutToBeChanged(parents, QAbstractItemModel::NoLayoutChangeHint);
}
void QSortFilterProxyModelPrivate::_q_sourceRowsMoved(
const QModelIndex &sourceParent, int /* sourceStart */, int /* sourceEnd */, const QModelIndex &destParent, int /* dest */)
{
- Q_Q(QSortFilterProxyModel);
-
- // Optimize: We only need to clear and update the persistent indexes which are children of
- // sourceParent or destParent
- qDeleteAll(source_index_mapping);
- source_index_mapping.clear();
-
- update_persistent_indexes(saved_persistent_indexes);
- saved_persistent_indexes.clear();
-
- if (dynamic_sortfilter && update_source_sort_column()) {
- //update_source_sort_column might have created wrong mapping so we have to clear it again
- qDeleteAll(source_index_mapping);
- source_index_mapping.clear();
- }
-
QList<QPersistentModelIndex> parents;
- parents << q->mapFromSource(sourceParent);
+ parents << sourceParent;
if (sourceParent != destParent)
- parents << q->mapFromSource(destParent);
- emit q->layoutChanged(parents);
+ parents << destParent;
+ _q_sourceLayoutChanged(parents, QAbstractItemModel::NoLayoutChangeHint);
}
void QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeInserted(
@@ -1522,42 +1500,21 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved(
void QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeMoved(
const QModelIndex &sourceParent, int /* sourceStart */, int /* sourceEnd */, const QModelIndex &destParent, int /* dest */)
{
- Q_Q(QSortFilterProxyModel);
-
- saved_persistent_indexes.clear();
-
QList<QPersistentModelIndex> parents;
- parents << q->mapFromSource(sourceParent);
+ parents << sourceParent;
if (sourceParent != destParent)
- parents << q->mapFromSource(destParent);
- emit q->layoutAboutToBeChanged(parents);
-
- if (persistent.indexes.isEmpty())
- return;
- saved_persistent_indexes = store_persistent_indexes();
+ parents << destParent;
+ _q_sourceLayoutAboutToBeChanged(parents, QAbstractItemModel::NoLayoutChangeHint);
}
void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved(
const QModelIndex &sourceParent, int /* sourceStart */, int /* sourceEnd */, const QModelIndex &destParent, int /* dest */)
{
- Q_Q(QSortFilterProxyModel);
-
- qDeleteAll(source_index_mapping);
- source_index_mapping.clear();
-
- update_persistent_indexes(saved_persistent_indexes);
- saved_persistent_indexes.clear();
-
- if (dynamic_sortfilter && update_source_sort_column()) {
- qDeleteAll(source_index_mapping);
- source_index_mapping.clear();
- }
-
QList<QPersistentModelIndex> parents;
- parents << q->mapFromSource(sourceParent);
+ parents << sourceParent;
if (sourceParent != destParent)
- parents << q->mapFromSource(destParent);
- emit q->layoutChanged(parents);
+ parents << destParent;
+ _q_sourceLayoutChanged(parents, QAbstractItemModel::NoLayoutChangeHint);
}
/*!
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
index 6b98d9f..7b6c470 100644
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
@@ -146,6 +146,7 @@ private slots:
void filterHint();
void sourceLayoutChangeLeavesValidPersistentIndexes();
+ void rowMoveLeavesValidPersistentIndexes();
protected:
void buildHierarchy(const QStringList &data, QAbstractItemModel *model);
@@ -4307,5 +4308,50 @@ void tst_QSortFilterProxyModel::sourceLayoutChangeLeavesValidPersistentIndexes()
QVERIFY(persistentIndex.parent().isValid());
}
+void tst_QSortFilterProxyModel::rowMoveLeavesValidPersistentIndexes()
+{
+ DynamicTreeModel model;
+ Q_SET_OBJECT_NAME(model);
+
+ QList<int> ancestors;
+ for (auto i = 0; i < 5; ++i)
+ {
+ Q_UNUSED(i);
+ ModelInsertCommand insertCommand(&model);
+ insertCommand.setAncestorRowNumbers(ancestors);
+ insertCommand.setStartRow(0);
+ insertCommand.setEndRow(0);
+ insertCommand.doCommand();
+ ancestors.push_back(0);
+ }
+
+ QSortFilterProxyModel proxy1;
+ proxy1.setSourceModel(&model);
+ Q_SET_OBJECT_NAME(proxy1);
+
+ proxy1.setFilterRegExp("1|2");
+
+ auto item5 = model.match(model.index(0, 0), Qt::DisplayRole, "5", 1, Qt::MatchRecursive).first();
+ auto item3 = model.match(model.index(0, 0), Qt::DisplayRole, "3", 1, Qt::MatchRecursive).first();
+
+ Q_ASSERT(item5.isValid());
+ Q_ASSERT(item3.isValid());
+
+ QPersistentModelIndex persistentIndex = proxy1.match(proxy1.index(0, 0), Qt::DisplayRole, "2", 1, Qt::MatchRecursive).first();
+
+ ModelMoveCommand moveCommand(&model, 0);
+ moveCommand.setAncestorRowNumbers(QList<int>{0, 0, 0, 0});
+ moveCommand.setStartRow(0);
+ moveCommand.setEndRow(0);
+ moveCommand.setDestRow(0);
+ moveCommand.setDestAncestors(QList<int>{0, 0, 0});
+ moveCommand.doCommand();
+
+ // Calling parent() causes the internalPointer to be used.
+ // Before fixing QTBUG-47711 (moveRows case), that could be
+ // a dangling pointer.
+ QVERIFY(persistentIndex.parent().isValid());
+}
+
QTEST_MAIN(tst_QSortFilterProxyModel)
#include "tst_qsortfilterproxymodel.moc"

149
qt5/plasma-crash-3.patch Normal file
View File

@ -0,0 +1,149 @@
From baad82d242a4d8c1af6c87faaa7f25584183fd53 Mon Sep 17 00:00:00 2001
From: Stephen Kelly <steveire@gmail.com>
Date: Tue, 20 Dec 2016 00:44:12 +0000
Subject: [PATCH] QIPM: Persist model indexes after emitting layoutChange, not
before
Callers can persist a QModelIndex which was not persisted before in a
slot connected to the signal, and such a persisted index must be updated
in the course of the layoutChange.
Store the indexes to persist after emitting the signal.
Task-number: QTBUG-32981
Change-Id: Ibee4c0d84817d72603a03fe5b22fdeefeac0695e
Reviewed-by: David Faure <david.faure@kdab.com>
---
src/corelib/itemmodels/qidentityproxymodel.cpp | 18 ++---
.../tst_qidentityproxymodel.cpp | 76 ++++++++++++++++++++++
2 files changed, 85 insertions(+), 9 deletions(-)
diff --git a/src/corelib/itemmodels/qidentityproxymodel.cpp b/src/corelib/itemmodels/qidentityproxymodel.cpp
index e537793..7c30679 100644
--- a/src/corelib/itemmodels/qidentityproxymodel.cpp
+++ b/src/corelib/itemmodels/qidentityproxymodel.cpp
@@ -496,15 +496,6 @@ void QIdentityProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList<QPe
{
Q_Q(QIdentityProxyModel);
- const auto proxyPersistentIndexes = q->persistentIndexList();
- for (const QPersistentModelIndex &proxyPersistentIndex : proxyPersistentIndexes) {
- proxyIndexes << proxyPersistentIndex;
- Q_ASSERT(proxyPersistentIndex.isValid());
- const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
- Q_ASSERT(srcPersistentIndex.isValid());
- layoutChangePersistentIndexes << srcPersistentIndex;
- }
-
QList<QPersistentModelIndex> parents;
parents.reserve(sourceParents.size());
for (const QPersistentModelIndex &parent : sourceParents) {
@@ -518,6 +509,15 @@ void QIdentityProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList<QPe
}
q->layoutAboutToBeChanged(parents, hint);
+
+ const auto proxyPersistentIndexes = q->persistentIndexList();
+ for (const QPersistentModelIndex &proxyPersistentIndex : proxyPersistentIndexes) {
+ proxyIndexes << proxyPersistentIndex;
+ Q_ASSERT(proxyPersistentIndex.isValid());
+ const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
+ Q_ASSERT(srcPersistentIndex.isValid());
+ layoutChangePersistentIndexes << srcPersistentIndex;
+ }
}
void QIdentityProxyModelPrivate::_q_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
diff --git a/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp b/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp
index e946f31..564b854 100644
--- a/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp
@@ -68,6 +68,8 @@ private slots:
void itemData();
+ void persistIndexOnLayoutChange();
+
protected:
void verifyIdentity(QAbstractItemModel *model, const QModelIndex &parent = QModelIndex());
@@ -377,5 +379,79 @@ void tst_QIdentityProxyModel::itemData()
QCOMPARE(proxy.itemData(topIndex).value(Qt::DisplayRole).toString(), QStringLiteral("Monday_appended"));
}
+void dump(QAbstractItemModel* model, QString const& indent = " - ", QModelIndex const& parent = {})
+{
+ for (auto row = 0; row < model->rowCount(parent); ++row)
+ {
+ auto idx = model->index(row, 0, parent);
+ qDebug() << (indent + idx.data().toString());
+ dump(model, indent + "- ", idx);
+ }
+}
+
+void tst_QIdentityProxyModel::persistIndexOnLayoutChange()
+{
+ DynamicTreeModel model;
+
+ QList<int> ancestors;
+ for (auto i = 0; i < 3; ++i)
+ {
+ Q_UNUSED(i);
+ ModelInsertCommand insertCommand(&model);
+ insertCommand.setAncestorRowNumbers(ancestors);
+ insertCommand.setStartRow(0);
+ insertCommand.setEndRow(0);
+ insertCommand.doCommand();
+ ancestors.push_back(0);
+ }
+ ModelInsertCommand insertCommand(&model);
+ insertCommand.setAncestorRowNumbers(ancestors);
+ insertCommand.setStartRow(0);
+ insertCommand.setEndRow(1);
+ insertCommand.doCommand();
+
+ // dump(&model);
+ // " - 1"
+ // " - - 2"
+ // " - - - 3"
+ // " - - - - 4"
+ // " - - - - 5"
+
+ QIdentityProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QPersistentModelIndex persistentIndex;
+
+ QPersistentModelIndex sourcePersistentIndex = model.match(model.index(0, 0), Qt::DisplayRole, "5", 1, Qt::MatchRecursive).first();
+
+ QCOMPARE(sourcePersistentIndex.data().toString(), QStringLiteral("5"));
+
+ bool gotLayoutAboutToBeChanged = false;
+ bool gotLayoutChanged = false;
+
+ QObject::connect(&proxy, &QAbstractItemModel::layoutAboutToBeChanged, &proxy, [&proxy, &persistentIndex, &gotLayoutAboutToBeChanged]
+ {
+ gotLayoutAboutToBeChanged = true;
+ persistentIndex = proxy.match(proxy.index(0, 0), Qt::DisplayRole, "5", 1, Qt::MatchRecursive).first();
+ });
+
+ QObject::connect(&proxy, &QAbstractItemModel::layoutChanged, &proxy, [&proxy, &persistentIndex, &sourcePersistentIndex, &gotLayoutChanged]
+ {
+ gotLayoutChanged = true;
+ QCOMPARE(QModelIndex(persistentIndex), proxy.mapFromSource(sourcePersistentIndex));
+ });
+
+ ModelChangeChildrenLayoutsCommand layoutChangeCommand(&model, 0);
+
+ layoutChangeCommand.setAncestorRowNumbers(QList<int>{0, 0, 0});
+ layoutChangeCommand.setSecondAncestorRowNumbers(QList<int>{0, 0});
+
+ layoutChangeCommand.doCommand();
+
+ QVERIFY(gotLayoutAboutToBeChanged);
+ QVERIFY(gotLayoutChanged);
+ QVERIFY(persistentIndex.isValid());
+}
+
QTEST_MAIN(tst_QIdentityProxyModel)
#include "tst_qidentityproxymodel.moc"

View File

@ -1,77 +0,0 @@
From 494376f980e96339b6f1eff7c41336ca4d853065 Mon Sep 17 00:00:00 2001
From: Thiago Macieira <thiago.macieira@intel.com>
Date: Thu, 12 Nov 2015 10:14:51 -0800
Subject: [PATCH] Stop unloading plugins in QPluginLoader and QFactoryLoader
QPluginLoader hasn't unloaded in its destructor since Qt 5.0, but we
missed the equivalent code in QFactoryLoader (which bypasses
QPluginLoader). Besides, QPluginLoader::unload() was still doing
unloading, which it won't anymore.
Not unloading plugins is Qt's policy, as decided during the 5.0
development process and reaffirmed now in 5.6. This is due to static
data in plugins leaking out and remaining in use past the unloading of
the plugin, causing crashes.
This does not affect QLibrary and QLibrary::unload(). Those are meant
for non-Qt loadable modules, so unloading them may be safe.
Task-number: QTBUG-49061
Discussed-on: http://lists.qt-project.org/pipermail/development/2015-November/023681.html
Change-Id: I461e9fc7199748faa187ffff1416070f138df8db
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
---
src/corelib/plugin/qfactoryloader.cpp | 6 ++++--
src/corelib/plugin/qpluginloader.cpp | 5 +++--
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 53b38c3..c820d53 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -203,10 +203,12 @@ void QFactoryLoader::update()
++keyUsageCount;
}
}
- if (keyUsageCount || keys.isEmpty())
+ if (keyUsageCount || keys.isEmpty()) {
+ library->setLoadHints(QLibrary::PreventUnloadHint); // once loaded, don't unload
d->libraryList += library;
- else
+ } else {
library->release();
+ }
}
}
#else
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
index 62067c7..4752f69 100644
--- a/src/corelib/plugin/qpluginloader.cpp
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -154,6 +154,7 @@ QPluginLoader::QPluginLoader(const QString &fileName, QObject *parent)
: QObject(parent), d(0), did_load(false)
{
setFileName(fileName);
+ setLoadHints(QLibrary::PreventUnloadHint);
}
/*!
@@ -348,7 +349,7 @@ static QString locatePlugin(const QString& fileName)
void QPluginLoader::setFileName(const QString &fileName)
{
#if defined(QT_SHARED)
- QLibrary::LoadHints lh;
+ QLibrary::LoadHints lh = QLibrary::PreventUnloadHint;
if (d) {
lh = d->loadHints();
d->release();
@@ -394,7 +395,7 @@ QString QPluginLoader::errorString() const
\brief Give the load() function some hints on how it should behave.
You can give hints on how the symbols in the plugin are
- resolved. By default, none of the hints are set.
+ resolved. By default since Qt 5.7, QLibrary::PreventUnloadHint is set.
See the documentation of QLibrary::loadHints for a complete
description of how this property works.

View File

@ -1,38 +0,0 @@
From 84ea00d47049d882f2fabf1446ec6c6eb5fe3038 Mon Sep 17 00:00:00 2001
From: J-P Nurmi <jpnurmi@qt.io>
Date: Tue, 6 Dec 2016 16:30:31 +0100
Subject: [PATCH] QGtk3Dialog: don't crash on Wayland
Check if it's an X11 window before calling XSetTransientForHint().
No transient parent will be set for GTK+ dialogs on Wayland. That
has to be implemented separately.
Task-number: QTBUG-55583
Change-Id: Iabc2a72681c8157bb2f2fe500892853aa397106b
Reviewed-by: Dmitry Shachnev <mitya57@gmail.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
---
src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp
index ba5089a..699b058 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp
+++ b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp
@@ -135,10 +135,12 @@ bool QGtk3Dialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWind
GdkWindow *gdkWindow = gtk_widget_get_window(gtkWidget);
if (parent) {
- GdkDisplay *gdkDisplay = gdk_window_get_display(gdkWindow);
- XSetTransientForHint(gdk_x11_display_get_xdisplay(gdkDisplay),
- gdk_x11_window_get_xid(gdkWindow),
- parent->winId());
+ if (GDK_IS_X11_WINDOW(gdkWindow)) {
+ GdkDisplay *gdkDisplay = gdk_window_get_display(gdkWindow);
+ XSetTransientForHint(gdk_x11_display_get_xdisplay(gdkDisplay),
+ gdk_x11_window_get_xid(gdkWindow),
+ parent->winId());
+ }
}
if (modality != Qt::NonModal) {