qt6-declarative/0001-Revert-QQmlDelegateModel-fix-delegates-not-being-cre.patch
Christophe Marin 5449df6cce - Add upstream changes:
* 0001-QQuickItemView-fix-crash-with-zero-size-SwipeView-th.patch
    (QTBUG-129622, kde#493854)
  * 0001-QQuickAccessibleAttached-Let-implicit-names-work-whe.patch
    (QTBUG-130360)

OBS-URL: https://build.opensuse.org/package/show/KDE:Qt6/qt6-declarative?expand=0&rev=81
2024-10-25 13:40:53 +00:00

421 lines
14 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 3330731d0cb221477ab3d856db032126403ae6a0 Mon Sep 17 00:00:00 2001
From: Mitch Curtis <mitch.curtis@qt.io>
Date: Tue, 24 Sep 2024 08:18:14 +0800
Subject: [PATCH 1/2] Revert "QQmlDelegateModel: fix delegates not being
created in certain cases"
This reverts commit 6561344dd2d1ba69abe6edec4fe340b256da9e13. It needs
to be fixed in a different way.
Fixes: QTBUG-127340
Pick-to: 6.7 6.5
Change-Id: I8503b22a5257e0fb5ee11a1bdf83d3dcab4a600a
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
(cherry picked from commit 281f620ceea03e7a222d796ae0cca917a9778368)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
---
src/qmlmodels/qqmldelegatemodel.cpp | 61 +++-----
src/qmlmodels/qqmldelegatemodel_p_p.h | 2 -
.../auto/qml/qqmldelegatemodel/CMakeLists.txt | 1 -
.../auto/qml/qqmldelegatemodel/data/reset.qml | 28 ----
.../data/resetInQAIMConstructor.qml | 28 ----
.../tst_qqmldelegatemodel.cpp | 135 ++----------------
6 files changed, 29 insertions(+), 226 deletions(-)
delete mode 100644 tests/auto/qml/qqmldelegatemodel/data/reset.qml
delete mode 100644 tests/auto/qml/qqmldelegatemodel/data/resetInQAIMConstructor.qml
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
index 9af58d7a22..7cfa662aa6 100644
--- a/src/qmlmodels/qqmldelegatemodel.cpp
+++ b/src/qmlmodels/qqmldelegatemodel.cpp
@@ -172,7 +172,6 @@ QQmlDelegateModelPrivate::QQmlDelegateModelPrivate(QQmlContext *ctxt)
, m_transaction(false)
, m_incubatorCleanupScheduled(false)
, m_waitingToFetchMore(false)
- , m_maybeResetRoleNames(false)
, m_cacheItems(nullptr)
, m_items(nullptr)
, m_persistedItems(nullptr)
@@ -366,7 +365,6 @@ void QQmlDelegateModelPrivate::connectToAbstractItemModel()
QObject::connect(aim, &QAbstractItemModel::dataChanged, q, &QQmlDelegateModel::_q_dataChanged);
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,7 +385,6 @@ void QQmlDelegateModelPrivate::disconnectFromAbstractItemModel()
QObject::disconnect(aim, &QAbstractItemModel::dataChanged, q, &QQmlDelegateModel::_q_dataChanged);
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);
}
@@ -1898,28 +1895,25 @@ void QQmlDelegateModel::_q_modelAboutToBeReset()
Q_D(QQmlDelegateModel);
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);
}
void QQmlDelegateModel::handleModelReset()
@@ -1929,23 +1923,6 @@ void QQmlDelegateModel::handleModelReset()
return;
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();
if (d->m_complete) {
diff --git a/src/qmlmodels/qqmldelegatemodel_p_p.h b/src/qmlmodels/qqmldelegatemodel_p_p.h
index bae8fc8a23..3c7ab9281d 100644
--- a/src/qmlmodels/qqmldelegatemodel_p_p.h
+++ b/src/qmlmodels/qqmldelegatemodel_p_p.h
@@ -334,7 +334,6 @@ public:
QQmlReusableDelegateModelItemsPool m_reusableItemsPool;
QList<QQDMIncubationTask *> m_finishedIncubating;
QList<QByteArray> m_watchedRoles;
- QHash<int, QByteArray> m_roleNamesBeforeReset;
QString m_filterGroup;
@@ -348,7 +347,6 @@ public:
bool m_transaction : 1;
bool m_incubatorCleanupScheduled : 1;
bool m_waitingToFetchMore : 1;
- bool m_maybeResetRoleNames : 1;
union {
struct {
diff --git a/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt b/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt
index 966f5229df..8d8a90e0a7 100644
--- a/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt
@@ -29,7 +29,6 @@ qt_internal_add_test(tst_qqmldelegatemodel
Qt::QmlModelsPrivate
Qt::QmlPrivate
Qt::Quick
- Qt::QuickPrivate
Qt::QuickTestUtilsPrivate
TESTDATA ${test_data}
)
diff --git a/tests/auto/qml/qqmldelegatemodel/data/reset.qml b/tests/auto/qml/qqmldelegatemodel/data/reset.qml
deleted file mode 100644
index 0fcd5e8afa..0000000000
--- a/tests/auto/qml/qqmldelegatemodel/data/reset.qml
+++ /dev/null
@@ -1,28 +0,0 @@
-import QtQuick
-import Test
-
-Window {
- id: root
- width: 200
- height: 200
-
- property alias listView: listView
-
- ResettableModel {
- id: resetModel
- }
-
- ListView {
- id: listView
- anchors.fill: parent
- model: resetModel
-
- delegate: Rectangle {
- implicitWidth: 100
- implicitHeight: 50
- color: "olivedrab"
-
- required property string display
- }
- }
-}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/resetInQAIMConstructor.qml b/tests/auto/qml/qqmldelegatemodel/data/resetInQAIMConstructor.qml
deleted file mode 100644
index cb1f226737..0000000000
--- a/tests/auto/qml/qqmldelegatemodel/data/resetInQAIMConstructor.qml
+++ /dev/null
@@ -1,28 +0,0 @@
-import QtQuick
-import Test
-
-Window {
- id: root
- width: 200
- height: 200
-
- property alias listView: listView
-
- ResetInConstructorModel {
- id: resetInConstructorModel
- }
-
- ListView {
- id: listView
- anchors.fill: parent
- model: resetInConstructorModel
-
- delegate: Rectangle {
- implicitWidth: 100
- implicitHeight: 50
- color: "olivedrab"
-
- required property string display
- }
- }
-}
diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
index d9f8b7aeba..2cacda5513 100644
--- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
+++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
@@ -4,7 +4,6 @@
#include <QtTest/qtest.h>
#include <QtCore/qjsonobject.h>
#include <QtCore/QConcatenateTablesProxyModel>
-#include <QtCore/qtimer.h>
#include <QtGui/QStandardItemModel>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlapplicationengine.h>
@@ -12,17 +11,11 @@
#include <QtQmlModels/private/qqmllistmodel_p.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
-#include <QtQuick/private/qquickitemview_p_p.h>
-#include <QtQuick/private/qquicklistview_p.h>
-#include <QtQuickTest/quicktest.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
-#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtTest/QSignalSpy>
#include <forward_list>
-using namespace QQuickVisualTestUtils;
-
class tst_QQmlDelegateModel : public QQmlDataTest
{
Q_OBJECT
@@ -32,8 +25,6 @@ public:
private slots:
void resettingRolesRespected();
- void resetInQAIMConstructor();
- void reset();
void valueWithoutCallingObjectFirst_data();
void valueWithoutCallingObjectFirst();
void qtbug_86017();
@@ -53,9 +44,16 @@ private slots:
void viewUpdatedOnDelegateChoiceAffectingRoleChange();
};
-class BaseAbstractItemModel : public QAbstractItemModel
+class AbstractItemModel : public QAbstractItemModel
{
+ Q_OBJECT
public:
+ AbstractItemModel()
+ {
+ for (int i = 0; i < 3; ++i)
+ mValues.append(QString::fromLatin1("Item %1").arg(i));
+ }
+
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
{
if (parent.isValid())
@@ -93,21 +91,10 @@ public:
return mValues.at(index.row());
}
-protected:
+private:
QVector<QString> mValues;
};
-class AbstractItemModel : public BaseAbstractItemModel
-{
- Q_OBJECT
-public:
- AbstractItemModel()
- {
- for (int i = 0; i < 3; ++i)
- mValues.append(QString::fromLatin1("Item %1").arg(i));
- }
-};
-
tst_QQmlDelegateModel::tst_QQmlDelegateModel()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
@@ -166,109 +153,7 @@ void tst_QQmlDelegateModel::resettingRolesRespected()
QObject *root = engine.rootObjects().constFirst();
QVERIFY(!root->property("success").toBool());
model->change();
- QTRY_VERIFY_WITH_TIMEOUT(root->property("success").toBool(), 100);
-}
-
-class ResetInConstructorModel : public BaseAbstractItemModel
-{
- Q_OBJECT
- QML_ELEMENT
-
-public:
- ResetInConstructorModel()
- {
- beginResetModel();
- QTimer::singleShot(0, this, &ResetInConstructorModel::finishReset);
- }
-
-private:
- void finishReset()
- {
- mValues.append("First");
- endResetModel();
- }
-};
-
-void tst_QQmlDelegateModel::resetInQAIMConstructor()
-{
- qmlRegisterTypesAndRevisions<ResetInConstructorModel>("Test", 1);
-
- QQuickApplicationHelper helper(this, "resetInQAIMConstructor.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);
- QTRY_VERIFY_WITH_TIMEOUT(listView->itemAtIndex(0), 100);
- QQuickItem *firstDelegateItem = listView->itemAtIndex(0);
- QVERIFY(firstDelegateItem);
- QCOMPARE(firstDelegateItem->property("display").toString(), "First");
-}
-
-class ResettableModel : public BaseAbstractItemModel
-{
- Q_OBJECT
- QML_ELEMENT
-
-public:
- ResettableModel()
- {
- mValues.append("First");
- }
-
- void callBeginResetModel()
- {
- beginResetModel();
- mValues.clear();
- }
-
- void appendData()
- {
- mValues.append(QString::fromLatin1("Item %1").arg(mValues.size()));
- }
-
- void callEndResetModel()
- {
- endResetModel();
- }
-};
-
-// Tests that everything works as expected when calling beginResetModel/endResetModel
-// after the QAIM subclass constructor has run.
-void tst_QQmlDelegateModel::reset()
-{
- qmlRegisterTypesAndRevisions<ResettableModel>("Test", 1);
-
- QQuickApplicationHelper helper(this, "reset.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);
- QQuickItem *firstDelegateItem = listView->itemAtIndex(0);
- QVERIFY(firstDelegateItem);
- QCOMPARE(firstDelegateItem->property("display").toString(), "First");
-
- const auto delegateModel = QQuickItemViewPrivate::get(listView)->model;
- QSignalSpy rootIndexChangedSpy(delegateModel, SIGNAL(rootIndexChanged()));
- QVERIFY(rootIndexChangedSpy.isValid());
-
- auto *model = listView->model().value<ResettableModel *>();
- model->callBeginResetModel();
- model->appendData();
- model->callEndResetModel();
- // This is verifies that handleModelReset isn't called
- // more than once during this process, since it unconditionally emits rootIndexChanged.
- QCOMPARE(rootIndexChangedSpy.count(), 1);
-
- QTRY_VERIFY_WITH_TIMEOUT(listView->itemAtIndex(0), 100);
- firstDelegateItem = listView->itemAtIndex(0);
- QVERIFY(firstDelegateItem);
- QCOMPARE(firstDelegateItem->property("display").toString(), "Item 0");
+ QTRY_VERIFY(root->property("success").toBool());
}
void tst_QQmlDelegateModel::valueWithoutCallingObjectFirst_data()
--
2.46.1