commit:     87e6967f8b82468e077a8f2004732e2db1cbf751
Author:     Andreas Sturmlechner <asturm <AT> gentoo <DOT> org>
AuthorDate: Sun Apr 23 13:54:19 2017 +0000
Commit:     Andreas Sturmlechner <asturm <AT> gentoo <DOT> org>
CommitDate: Sun Apr 23 19:07:31 2017 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=87e6967f

dev-qt/qtcore: Try to fix random plasmashell crashes

Backports from Qt-5.8.0.

See also: https://bugs.kde.org/show_bug.cgi?id=342763

Package-Manager: Portage-2.3.3, Repoman-2.3.1

 dev-qt/qtcore/files/qtcore-5.7.1-qipm.patch    | 152 +++++++++++++++
 dev-qt/qtcore/files/qtcore-5.7.1-qsfpm-1.patch | 252 +++++++++++++++++++++++++
 dev-qt/qtcore/files/qtcore-5.7.1-qsfpm-2.patch | 195 +++++++++++++++++++
 dev-qt/qtcore/qtcore-5.7.1-r3.ebuild           |  48 +++++
 4 files changed, 647 insertions(+)

diff --git a/dev-qt/qtcore/files/qtcore-5.7.1-qipm.patch 
b/dev-qt/qtcore/files/qtcore-5.7.1-qipm.patch
new file mode 100644
index 00000000000..abea1458807
--- /dev/null
+++ b/dev-qt/qtcore/files/qtcore-5.7.1-qipm.patch
@@ -0,0 +1,152 @@
+From baad82d242a4d8c1af6c87faaa7f25584183fd53 Mon Sep 17 00:00:00 2001
+From: Stephen Kelly <[email protected]>
+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 <[email protected]>
+---
+ 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"
+-- 
+2.7.4
+

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
new file mode 100644
index 00000000000..9edbe18617a
--- /dev/null
+++ b/dev-qt/qtcore/files/qtcore-5.7.1-qsfpm-1.patch
@@ -0,0 +1,252 @@
+From 3bd0fd8f97e7a33a874929a383a42e6c710bfff3 Mon Sep 17 00:00:00 2001
+From: Stephen Kelly <[email protected]>
+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 <[email protected]>
+---
+ 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
+
+

diff --git a/dev-qt/qtcore/files/qtcore-5.7.1-qsfpm-2.patch 
b/dev-qt/qtcore/files/qtcore-5.7.1-qsfpm-2.patch
new file mode 100644
index 00000000000..973649637e6
--- /dev/null
+++ b/dev-qt/qtcore/files/qtcore-5.7.1-qsfpm-2.patch
@@ -0,0 +1,195 @@
+From 0874861bcc70313c343aba5e5566ed30b69eed1c Mon Sep 17 00:00:00 2001
+From: Stephen Kelly <[email protected]>
+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 <[email protected]>
+---
+ 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"
+-- 
+2.7.4
+
+

diff --git a/dev-qt/qtcore/qtcore-5.7.1-r3.ebuild 
b/dev-qt/qtcore/qtcore-5.7.1-r3.ebuild
new file mode 100644
index 00000000000..93fad42b1eb
--- /dev/null
+++ b/dev-qt/qtcore/qtcore-5.7.1-r3.ebuild
@@ -0,0 +1,48 @@
+# Copyright 1999-2017 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=6
+QT5_MODULE="qtbase"
+inherit qt5-build
+
+DESCRIPTION="Cross-platform application development framework"
+
+if [[ ${QT5_BUILD_TYPE} == release ]]; then
+       KEYWORDS="~amd64 ~arm ~arm64 ~hppa ~ppc ~ppc64 ~x86"
+fi
+
+IUSE="icu systemd"
+
+DEPEND="
+       dev-libs/double-conversion:=
+       dev-libs/glib:2
+       >=dev-libs/libpcre-8.38[pcre16,unicode]
+       >=sys-libs/zlib-1.2.5
+       virtual/libiconv
+       icu? ( dev-libs/icu:= )
+       systemd? ( sys-apps/systemd:= )
+"
+RDEPEND="${DEPEND}"
+
+PATCHES=(
+       "${FILESDIR}"/${PN}-5.6.2-plugins.patch
+       "${FILESDIR}"/${P}-qipm.patch
+       "${FILESDIR}"/${P}-qsfpm-{1,2}.patch
+)
+
+QT5_TARGET_SUBDIRS=(
+       src/tools/bootstrap
+       src/tools/moc
+       src/tools/rcc
+       src/corelib
+       src/tools/qlalr
+       doc
+)
+
+src_configure() {
+       local myconf=(
+               $(qt_use icu)
+               $(qt_use systemd journald)
+       )
+       qt5-build_src_configure
+}

Reply via email to