commit:     fdb02a790eb6d83107b919fece7a199b7e1ae00f
Author:     Ionen Wolkens <ionen <AT> gentoo <DOT> org>
AuthorDate: Tue Oct  8 16:55:01 2024 +0000
Commit:     Ionen Wolkens <ionen <AT> gentoo <DOT> org>
CommitDate: Tue Oct  8 17:44:32 2024 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=fdb02a79

dev-qt/qtdeclarative: backport fix for QTBUG-125053 + 129797 early

QTBUG-129797's hasn't been merged yet but should be soon and may
as well do it at same time.

May need to do another revbump later for QTBUG-129622 when there
is a fix though, but this may or may not take a while.

Signed-off-by: Ionen Wolkens <ionen <AT> gentoo.org>

 .../files/qtdeclarative-6.7.3-QTBUG-125053.patch   | 259 +++++++++++++++++++++
 .../files/qtdeclarative-6.8.0-QTBUG-129797.patch   |  19 ++
 ...7.3-r1.ebuild => qtdeclarative-6.7.3-r2.ebuild} |   4 +
 ...-6.8.0.ebuild => qtdeclarative-6.8.0-r1.ebuild} |   5 +
 4 files changed, 287 insertions(+)

diff --git a/dev-qt/qtdeclarative/files/qtdeclarative-6.7.3-QTBUG-125053.patch 
b/dev-qt/qtdeclarative/files/qtdeclarative-6.7.3-QTBUG-125053.patch
new file mode 100644
index 000000000000..c1aa74599923
--- /dev/null
+++ b/dev-qt/qtdeclarative/files/qtdeclarative-6.7.3-QTBUG-125053.patch
@@ -0,0 +1,259 @@
+https://bugreports.qt.io/browse/QTBUG-125053
+https://bugreports.qt.io/browse/QTBUG-127340
+https://codereview.qt-project.org/c/qt/qtdeclarative/+/593122
+--- 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>
+ 
+@@ -168,5 +170,4 @@
+     , m_incubatorCleanupScheduled(false)
+     , m_waitingToFetchMore(false)
+-    , m_maybeResetRoleNames(false)
+     , m_cacheItems(nullptr)
+     , m_items(nullptr)
+@@ -373,6 +374,4 @@
+     qmlobject_connect(aim, QAbstractItemModel, 
SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
+                       q, QQmlDelegateModel, 
SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+-    QObject::connect(aim, &QAbstractItemModel::modelReset, q, 
&QQmlDelegateModel::handleModelReset);
+-    QObject::connect(aim, &QAbstractItemModel::layoutChanged, q, 
&QQmlDelegateModel::_q_layoutChanged);
+ }
+ 
+@@ -404,6 +403,4 @@
+     QObject::disconnect(aim, 
SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
+                         q, 
SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+-    QObject::disconnect(aim, &QAbstractItemModel::modelReset, q, 
&QQmlDelegateModel::handleModelReset);
+-    QObject::disconnect(aim, &QAbstractItemModel::layoutChanged, q, 
&QQmlDelegateModel::_q_layoutChanged);
+ }
+ 
+@@ -429,4 +426,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);
++    }
+ }
+ 
+@@ -1915,26 +1927,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);
+ }
+ 
+@@ -1946,21 +1955,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/files/qtdeclarative-6.8.0-QTBUG-129797.patch 
b/dev-qt/qtdeclarative/files/qtdeclarative-6.8.0-QTBUG-129797.patch
new file mode 100644
index 000000000000..12c15ad1accd
--- /dev/null
+++ b/dev-qt/qtdeclarative/files/qtdeclarative-6.8.0-QTBUG-129797.patch
@@ -0,0 +1,19 @@
+https://bugs.kde.org/show_bug.cgi?id=494281
+https://bugreports.qt.io/browse/QTBUG-129797
+https://codereview.qt-project.org/c/qt/qtdeclarative/+/596457
+--- a/src/qmlcompiler/qqmljscodegenerator.cpp
++++ b/src/qmlcompiler/qqmljscodegenerator.cpp
+@@ -79,5 +79,5 @@
+             + (m_jsUnitGenerator->hasStringId(elementName)
+                        ? 
QString::number(m_jsUnitGenerator->getStringId(elementName))
+-                       : u'"' + elementName + u'"') + u")"_s;
++                       : u"QStringLiteral(\"%1\")"_s.arg(elementName));
+ }
+ 
+@@ -87,5 +87,5 @@
+             + (m_jsUnitGenerator->hasStringId(elementName)
+                        ? 
QString::number(m_jsUnitGenerator->getStringId(elementName))
+-                       : u'"' + elementName + u'"') + u")"_s;
++                       : u"QStringLiteral(\"%1\")"_s.arg(elementName));
+ }
+ 

diff --git a/dev-qt/qtdeclarative/qtdeclarative-6.7.3-r1.ebuild 
b/dev-qt/qtdeclarative/qtdeclarative-6.7.3-r2.ebuild
similarity index 96%
rename from dev-qt/qtdeclarative/qtdeclarative-6.7.3-r1.ebuild
rename to dev-qt/qtdeclarative/qtdeclarative-6.7.3-r2.ebuild
index 724f992b0453..749123d1c04f 100644
--- a/dev-qt/qtdeclarative/qtdeclarative-6.7.3-r1.ebuild
+++ b/dev-qt/qtdeclarative/qtdeclarative-6.7.3-r2.ebuild
@@ -33,6 +33,10 @@ BDEPEND="
        ~dev-qt/qtshadertools-${PV}:6
 "
 
+PATCHES=(
+       "${FILESDIR}"/${PN}-6.7.3-QTBUG-125053.patch
+)
+
 src_configure() {
        local mycmakeargs=(
                $(cmake_use_find_package qmlls Qt6LanguageServerPrivate)

diff --git a/dev-qt/qtdeclarative/qtdeclarative-6.8.0.ebuild 
b/dev-qt/qtdeclarative/qtdeclarative-6.8.0-r1.ebuild
similarity index 94%
rename from dev-qt/qtdeclarative/qtdeclarative-6.8.0.ebuild
rename to dev-qt/qtdeclarative/qtdeclarative-6.8.0-r1.ebuild
index 724f992b0453..41fbd3c4f304 100644
--- a/dev-qt/qtdeclarative/qtdeclarative-6.8.0.ebuild
+++ b/dev-qt/qtdeclarative/qtdeclarative-6.8.0-r1.ebuild
@@ -33,6 +33,11 @@ BDEPEND="
        ~dev-qt/qtshadertools-${PV}:6
 "
 
+PATCHES=(
+       "${FILESDIR}"/${PN}-6.7.3-QTBUG-125053.patch
+       "${FILESDIR}"/${PN}-6.8.0-QTBUG-129797.patch
+)
+
 src_configure() {
        local mycmakeargs=(
                $(cmake_use_find_package qmlls Qt6LanguageServerPrivate)

Reply via email to