commit:     07424846a2e87d58e386a16f3d3d279ed5ed7385
Author:     Ionen Wolkens <ionen <AT> gentoo <DOT> org>
AuthorDate: Fri Nov 15 07:45:10 2024 +0000
Commit:     Ionen Wolkens <ionen <AT> gentoo <DOT> org>
CommitDate: Fri Nov 15 08:02:45 2024 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=07424846

dev-qt/qtdeclarative: fix 6.8.0's QTBUG-125053 patch

The version for 6.7.3 seems correct but sharing it with 6.8.0 was not,
thankfully 6.8.0 is masked so this didn't affect many people.

Closes: https://bugs.gentoo.org/943527
Signed-off-by: Ionen Wolkens <ionen <AT> gentoo.org>

 .../files/qtdeclarative-6.8.0-QTBUG-125053.patch   | 258 +++++++++++++++++++++
 ...8.0-r5.ebuild => qtdeclarative-6.8.0-r6.ebuild} |   2 +-
 2 files changed, 259 insertions(+), 1 deletion(-)

diff --git a/dev-qt/qtdeclarative/files/qtdeclarative-6.8.0-QTBUG-125053.patch 
b/dev-qt/qtdeclarative/files/qtdeclarative-6.8.0-QTBUG-125053.patch
new file mode 100644
index 000000000000..250a33f7b166
--- /dev/null
+++ b/dev-qt/qtdeclarative/files/qtdeclarative-6.8.0-QTBUG-125053.patch
@@ -0,0 +1,258 @@
+https://bugreports.qt.io/browse/QTBUG-125053
+https://bugreports.qt.io/browse/QTBUG-127340
+https://codereview.qt-project.org/c/qt/qtdeclarative/+/593122
+https://bugs.gentoo.org/943527 (see also)
+--- a/src/qmlmodels/qqmldelegatemodel.cpp
++++ b/src/qmlmodels/qqmldelegatemodel.cpp
+@@ -4,4 +4,6 @@
+ #include "qqmldelegatemodel_p_p.h"
+ 
++#include <QtCore/private/qabstractitemmodel_p.h>
++
+ #include <QtQml/qqmlinfo.h>
+ 
+@@ -172,5 +174,4 @@
+     , m_incubatorCleanupScheduled(false)
+     , m_waitingToFetchMore(false)
+-    , m_maybeResetRoleNames(false)
+     , m_cacheItems(nullptr)
+     , m_items(nullptr)
+@@ -366,5 +367,4 @@
+     QObject::connect(aim, &QAbstractItemModel::rowsMoved, q, 
&QQmlDelegateModel::_q_rowsMoved);
+     QObject::connect(aim, &QAbstractItemModel::modelAboutToBeReset, q, 
&QQmlDelegateModel::_q_modelAboutToBeReset);
+-    QObject::connect(aim, &QAbstractItemModel::modelReset, q, 
&QQmlDelegateModel::handleModelReset);
+     QObject::connect(aim, &QAbstractItemModel::layoutChanged, q, 
&QQmlDelegateModel::_q_layoutChanged);
+ }
+@@ -387,5 +387,4 @@
+     QObject::disconnect(aim, &QAbstractItemModel::rowsMoved, q, 
&QQmlDelegateModel::_q_rowsMoved);
+     QObject::disconnect(aim, &QAbstractItemModel::modelAboutToBeReset, q, 
&QQmlDelegateModel::_q_modelAboutToBeReset);
+-    QObject::disconnect(aim, &QAbstractItemModel::modelReset, q, 
&QQmlDelegateModel::handleModelReset);
+     QObject::disconnect(aim, &QAbstractItemModel::layoutChanged, q, 
&QQmlDelegateModel::_q_layoutChanged);
+ }
+@@ -412,4 +411,19 @@
+         d->requestMoreIfNecessary();
+     }
++
++    // Since 837c2f18cd223707e7cedb213257b0158ea07146, we connect to 
modelAboutToBeReset
++    // rather than modelReset so that we can handle role name changes. 
_q_modelAboutToBeReset
++    // now connects modelReset to handleModelReset with a single shot 
connection instead.
++    // However, it's possible for user code to begin the reset before 
connectToAbstractItemModel is called
++    // (QTBUG-125053), in which case we connect to modelReset too late and 
handleModelReset is never called,
++    // resulting in delegates not being created in certain cases.
++    // So, we check at the earliest point we can if the model is in the 
process of being reset,
++    // and if so, connect modelReset to handleModelReset.
++    if (d->m_adaptorModel.adaptsAim()) {
++        auto *aim = d->m_adaptorModel.aim();
++        auto *aimPrivate = QAbstractItemModelPrivate::get(aim);
++        if (aimPrivate->resetting)
++            QObject::connect(aim, &QAbstractItemModel::modelReset, this, 
&QQmlDelegateModel::handleModelReset, Qt::SingleShotConnection);
++    }
+ }
+ 
+@@ -1898,26 +1912,23 @@
+     if (!d->m_adaptorModel.adaptsAim())
+         return;
+-
+-    /*
+-        roleNames are generally guaranteed to be stable (given that QAIM has 
no
+-        change signal for them), except that resetting the model is allowed to
+-        invalidate them (QTBUG-32132). DelegateModel must take this into 
account by
+-        snapshotting the current roleNames before the model is reset.
+-        Afterwards, if we detect that roleNames has changed, we throw the
+-        current model set up away and rebuild everything from scratch – it is
+-        unlikely that a more efficient implementation would be worth it.
+-
+-        If we detect no changes, we simply use the existing logic to handle 
the
+-        model reset.
+-
+-        This (role name resetting) logic relies on the fact that
+-        modelAboutToBeReset must be followed by a modelReset signal before any
+-        further modelAboutToBeReset can occur. However, it's possible for user
+-        code to begin the reset before connectToAbstractItemModel is called
+-        (QTBUG-125053), in which case we don't attempt to reset the role 
names.
+-    */
+-    Q_ASSERT(!d->m_maybeResetRoleNames);
+-    d->m_maybeResetRoleNames = true;
+-    d->m_roleNamesBeforeReset = d->m_adaptorModel.aim()->roleNames();
++    auto aim = d->m_adaptorModel.aim();
++    auto oldRoleNames = aim->roleNames();
++    // this relies on the fact that modelAboutToBeReset must be followed
++    // by a modelReset signal before any further modelAboutToBeReset can occur
++    QObject::connect(aim, &QAbstractItemModel::modelReset, this, [this, d, 
oldRoleNames, aim](){
++        if (!d->m_adaptorModel.adaptsAim() || d->m_adaptorModel.aim() != aim)
++            return;
++        if (oldRoleNames == aim->roleNames()) {
++            // if the rolenames stayed the same (most common case), then we 
don't have
++            // to throw away all the setup that we did
++            handleModelReset();
++        } else {
++            // If they did change, we give up and just start from scratch via 
setMode
++            setModel(QVariant::fromValue(model()));
++            // but we still have to call handleModelReset, otherwise views 
will
++            // not refresh
++            handleModelReset();
++        }
++    }, Qt::SingleShotConnection);
+ }
+ 
+@@ -1929,21 +1940,4 @@
+ 
+     int oldCount = d->m_count;
+-
+-    if (d->m_maybeResetRoleNames) {
+-        auto aim = d->m_adaptorModel.aim();
+-        if (!d->m_adaptorModel.adaptsAim() || d->m_adaptorModel.aim() != aim)
+-            return;
+-
+-        // If the role names stayed the same (most common case), then we 
don't have
+-        // to throw away all the setup that we did.
+-        // If they did change, we give up and just start from scratch via 
setModel.
+-        // We do this before handling the reset to ensure that views refresh.
+-        if (aim->roleNames() != d->m_roleNamesBeforeReset)
+-            setModel(QVariant::fromValue(model()));
+-
+-        d->m_maybeResetRoleNames = false;
+-        d->m_roleNamesBeforeReset.clear();
+-    }
+-
+     d->m_adaptorModel.rootIndex = QModelIndex();
+ 
+--- a/src/qmlmodels/qqmldelegatemodel_p_p.h
++++ b/src/qmlmodels/qqmldelegatemodel_p_p.h
+@@ -335,5 +335,4 @@
+     QList<QQDMIncubationTask *> m_finishedIncubating;
+     QList<QByteArray> m_watchedRoles;
+-    QHash<int, QByteArray> m_roleNamesBeforeReset;
+ 
+     QString m_filterGroup;
+@@ -349,5 +348,4 @@
+     bool m_incubatorCleanupScheduled : 1;
+     bool m_waitingToFetchMore : 1;
+-    bool m_maybeResetRoleNames : 1;
+ 
+     union {
+--- 
a/tests/auto/qml/qqmldelegatemodel/data/proxyModelWithDelayedSourceModelInListView.qml
++++ 
b/tests/auto/qml/qqmldelegatemodel/data/proxyModelWithDelayedSourceModelInListView.qml
+@@ -0,0 +1,30 @@
++import QtQuick
++import Test
++
++Window {
++    id: root
++    title: listView.count
++
++    property alias listView: listView
++    property ProxySourceModel connectionModel: null
++
++    Component {
++        id: modelComponent
++        ProxySourceModel {}
++    }
++
++    ListView {
++        id: listView
++        anchors.fill: parent
++
++        delegate: Text {
++            text: model.Name
++        }
++
++        model: ProxyModel {
++            sourceModel: root.connectionModel
++        }
++    }
++
++    Component.onCompleted: root.connectionModel = 
modelComponent.createObject(root)
++}
+--- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
++++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
+@@ -4,4 +4,5 @@
+ #include <QtTest/qtest.h>
+ #include <QtCore/qjsonobject.h>
++#include <QtCore/qsortfilterproxymodel.h>
+ #include <QtCore/QConcatenateTablesProxyModel>
+ #include <QtCore/qtimer.h>
+@@ -52,4 +53,5 @@
+     void clearCacheDuringInsertion();
+     void viewUpdatedOnDelegateChoiceAffectingRoleChange();
++    void proxyModelWithDelayedSourceModelInListView();
+ };
+ 
+@@ -732,4 +734,77 @@
+ }
+ 
++class ProxySourceModel : public QAbstractListModel
++{
++    Q_OBJECT
++    QML_ELEMENT
++public:
++    explicit ProxySourceModel(QObject *parent = nullptr)
++        : QAbstractListModel(parent)
++    {
++        for (int i = 0; i < rows; ++i) {
++            beginInsertRows(QModelIndex(), i, i);
++            endInsertRows();
++        }
++    }
++
++    ~ProxySourceModel() override = default;
++
++    int rowCount(const QModelIndex &) const override
++    {
++        return rows;
++    }
++
++    QVariant data(const QModelIndex &, int ) const override
++    {
++        return "Hello";
++    }
++
++    QHash<int, QByteArray> roleNames() const override
++    {
++        QHash<int, QByteArray> roles = QAbstractListModel::roleNames();
++        roles[Qt::UserRole + 1] = "Name";
++
++        return roles;
++    }
++
++    static const int rows = 1;
++};
++
++class ProxyModel : public QSortFilterProxyModel
++{
++    Q_OBJECT
++    QML_ELEMENT
++    Q_PROPERTY(QAbstractItemModel *sourceModel READ sourceModel WRITE 
setSourceModel)
++
++public:
++    explicit ProxyModel(QObject *parent = nullptr)
++        : QSortFilterProxyModel(parent)
++    {
++    }
++
++    ~ProxyModel() override = default;
++};
++
++// Checks that the correct amount of delegates are created when using a proxy
++// model whose source model is set after a delay.
++void tst_QQmlDelegateModel::proxyModelWithDelayedSourceModelInListView()
++{
++    QTest::failOnWarning();
++
++    qmlRegisterTypesAndRevisions<ProxySourceModel>("Test", 1);
++    qmlRegisterTypesAndRevisions<ProxyModel>("Test", 1);
++
++    QQuickApplicationHelper helper(this, 
"proxyModelWithDelayedSourceModelInListView.qml");
++    QVERIFY2(helper.ready, helper.failureMessage());
++    QQuickWindow *window = helper.window;
++    window->show();
++    QVERIFY(QTest::qWaitForWindowExposed(window));
++
++    auto *listView = window->property("listView").value<QQuickListView *>();
++    QVERIFY(listView);
++    const auto delegateModel = QQuickItemViewPrivate::get(listView)->model;
++    QTRY_COMPARE(listView->count(), 1);
++}
++
+ QTEST_MAIN(tst_QQmlDelegateModel)
+ 

diff --git a/dev-qt/qtdeclarative/qtdeclarative-6.8.0-r5.ebuild 
b/dev-qt/qtdeclarative/qtdeclarative-6.8.0-r6.ebuild
similarity index 97%
rename from dev-qt/qtdeclarative/qtdeclarative-6.8.0-r5.ebuild
rename to dev-qt/qtdeclarative/qtdeclarative-6.8.0-r6.ebuild
index 3dcd70472b17..7f4c05e68b3e 100644
--- a/dev-qt/qtdeclarative/qtdeclarative-6.8.0-r5.ebuild
+++ b/dev-qt/qtdeclarative/qtdeclarative-6.8.0-r6.ebuild
@@ -35,8 +35,8 @@ BDEPEND="
 "
 
 PATCHES=(
-       "${FILESDIR}"/${PN}-6.7.3-QTBUG-125053.patch
        "${FILESDIR}"/${PN}-6.7.3-QTBUG-129622.patch
+       "${FILESDIR}"/${PN}-6.8.0-QTBUG-125053.patch
        "${FILESDIR}"/${PN}-6.8.0-QTBUG-129797.patch
        "${FILESDIR}"/${PN}-6.8.0-QTBUG-129500.patch
 )

Reply via email to