Compare commits

..

No commits in common. "factory" and "factory" have entirely different histories.

11 changed files with 673 additions and 2030 deletions

View File

@ -1,45 +0,0 @@
From e6e3da4de8fac7f52eb2591cb95a04ab413f8ace Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Olivier=20De=20Canni=C3=A8re?= <olivier.decanniere@qt.io>
Date: Wed, 9 Oct 2024 09:41:27 +0200
Subject: [PATCH] Compiler: Wrap raw string literals in QStringLiteral in
generated code
Amends e7146cd98700c29802214a39a4cefd9db146c97a
Fixes: QTBUG-129797
Change-Id: I5dc48412cf29bd2de877dd681ea309a6e74d75c5
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit d63c560ec4ce79c1bb24e1a01a20de41706dd039)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
---
src/qmlcompiler/qqmljscodegenerator.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp
index 807168ca09..e5622fe6f9 100644
--- a/src/qmlcompiler/qqmljscodegenerator.cpp
+++ b/src/qmlcompiler/qqmljscodegenerator.cpp
@@ -77,16 +77,16 @@ QString QQmlJSCodeGenerator::compositeListMetaType(const QString &elementName) c
{
return u"QQmlPrivate::compositeListMetaType(aotContext->compilationUnit, "_s
+ (m_jsUnitGenerator->hasStringId(elementName)
- ? QString::number(m_jsUnitGenerator->getStringId(elementName))
- : u'"' + elementName + u'"') + u")"_s;
+ ? QString::number(m_jsUnitGenerator->getStringId(elementName)) + u')'
+ : u"QStringLiteral(\"%1\"))"_s.arg(elementName));
}
QString QQmlJSCodeGenerator::compositeMetaType(const QString &elementName) const
{
return u"QQmlPrivate::compositeMetaType(aotContext->compilationUnit, "_s
+ (m_jsUnitGenerator->hasStringId(elementName)
- ? QString::number(m_jsUnitGenerator->getStringId(elementName))
- : u'"' + elementName + u'"') + u")"_s;
+ ? QString::number(m_jsUnitGenerator->getStringId(elementName)) + u')'
+ : u"QStringLiteral(\"%1\"))"_s.arg(elementName));
}
QString QQmlJSCodeGenerator::metaObject(const QQmlJSScope::ConstPtr &objectType)
--
2.47.0

View File

@ -1,116 +0,0 @@
From 71a9938f4e093c77fc7b9f1cf8043e6d3552aff3 Mon Sep 17 00:00:00 2001
From: Aleix Pol <aleixpol@kde.org>
Date: Tue, 22 Oct 2024 02:47:48 +0200
Subject: [PATCH] QQuickAccessibleAttached: Let implicit names work when
there's a proxy
QQuickAccessibleAttached has infrastructure to provide an implicit name
that we were bypassing now that we have proxies (introduced in 6.8).
We should only use the name of the proxy when it's being set, otherwise
we better provide the implicit name.
Amends 7bdeea2c309150c8b49558b135232926d6a89c50.
Fixes: QTBUG-130360
Pick-to: 6.8
Change-Id: I37470e1f28e837bdbb304726ee85f45ba6577621
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
---
src/quick/items/qquickaccessibleattached_p.h | 2 +-
.../data/actionAccessibility/button2.qml | 9 +++++
.../accessibility/tst_accessibility.cpp | 36 +++++++++++++++++++
3 files changed, 46 insertions(+), 1 deletion(-)
create mode 100644 tests/auto/quickcontrols/accessibility/data/actionAccessibility/button2.qml
diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h
index aa15b43..2d44000 100644
--- a/src/quick/items/qquickaccessibleattached_p.h
+++ b/src/quick/items/qquickaccessibleattached_p.h
@@ -87,7 +87,7 @@ public:
QString name() const {
if (m_state.passwordEdit)
return QString();
- if (m_proxying)
+ if (!m_nameExplicitlySet && m_proxying && m_proxying->wasNameExplicitlySet())
return m_proxying->name();
return m_name;
}
diff --git a/tests/auto/quickcontrols/accessibility/data/actionAccessibility/button2.qml b/tests/auto/quickcontrols/accessibility/data/actionAccessibility/button2.qml
new file mode 100644
index 0000000..1cd1c81
--- /dev/null
+++ b/tests/auto/quickcontrols/accessibility/data/actionAccessibility/button2.qml
@@ -0,0 +1,9 @@
+import QtQuick
+import QtQuick.Controls
+
+Button {
+ action: Action {
+ text: "Pears"
+ Accessible.description: "Show pears some love"
+ }
+}
diff --git a/tests/auto/quickcontrols/accessibility/tst_accessibility.cpp b/tests/auto/quickcontrols/accessibility/tst_accessibility.cpp
index 8bdd945..2018c0e 100644
--- a/tests/auto/quickcontrols/accessibility/tst_accessibility.cpp
+++ b/tests/auto/quickcontrols/accessibility/tst_accessibility.cpp
@@ -33,6 +33,8 @@ private slots:
void ordering();
void actionAccessibility();
+ void actionAccessibilityImplicitName();
+
private:
QQmlEngine engine;
};
@@ -279,6 +281,13 @@ void tst_accessibility::ordering()
void tst_accessibility::actionAccessibility()
{
#if QT_CONFIG(accessibility)
+ if (!QAccessible::isActive()) {
+ QPlatformAccessibility *accessibility = platformAccessibility();
+ if (!accessibility)
+ QSKIP("No QPlatformAccessibility available.");
+ accessibility->setActive(true);
+ }
+
QQmlComponent component(&engine);
component.loadUrl(testFileUrl("actionAccessibility/button.qml"));
@@ -296,6 +305,33 @@ void tst_accessibility::actionAccessibility()
#endif
}
+void tst_accessibility::actionAccessibilityImplicitName()
+{
+#if QT_CONFIG(accessibility)
+ if (!QAccessible::isActive()) {
+ QPlatformAccessibility *accessibility = platformAccessibility();
+ if (!accessibility)
+ QSKIP("No QPlatformAccessibility available.");
+ accessibility->setActive(true);
+ }
+
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("actionAccessibility/button2.qml"));
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
+
+ QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(item);
+ const QString description = "Show pears some love";
+ QCOMPARE(item->property("text"), "Pears");
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(item);
+ QVERIFY(iface);
+ QCOMPARE(iface->text(QAccessible::Name), "Pears"); // We get the action.text implicitly
+ QCOMPARE(iface->text(QAccessible::Description), description);
+#endif
+}
+
QTEST_MAIN(tst_accessibility)
#include "tst_accessibility.moc"
--
2.47.0

View File

@ -1,126 +0,0 @@
From 0ae3697cf40bcd3ae1de20621abad17cf6c5f52d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= <tor.arne.vestbo@qt.io>
Date: Wed, 2 Oct 2024 17:04:25 +0200
Subject: [PATCH] QQuickItem::map{To,From}Item: Account for not having a window
yet
Prior to 06ace3e226b2394362e27d1bc4743c1170777af1 we would not
account for items in different scenes, and would map them as if
they were part of the same scene.
After 06ace3e226b2394362e27d1bc4743c1170777af1 we took the scenes
into account, but failed to guard against one or both of the items
not having a scene (yet), causing potential crashes.
We now properly check that both items have a scene before trying
any scene to scene mapping.
The semantics if one or both of the items are not in a scene is
kept as it was before 06ace3e226b2394362e27d1bc4743c1170777af1,
where we assume the two items are part of the same scene, and an
item without a parent is assumed to be the root of its scene.
Fixes: QTBUG-129500
Change-Id: I897faf73d04dddd68a7a8797e5238743efdd4f73
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
(cherry picked from commit 08b0e3e39e899bea013057a7ac038b8878809712)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
---
src/quick/items/qquickitem.cpp | 14 +++++-----
.../data/mapCoordinatesWithWindows.qml | 11 ++++++++
.../auto/quick/qquickitem2/tst_qquickitem.cpp | 27 +++++++++++++++++++
3 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 9288df17a4..802f4dad55 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -8755,9 +8755,10 @@ QPointF QQuickItem::mapToItem(const QQuickItem *item, const QPointF &point) cons
{
QPointF p = mapToScene(point);
if (item) {
- const QQuickWindow *itemWindow = item->window();
- if (itemWindow != nullptr && itemWindow != window())
- p = itemWindow->mapFromGlobal(window()->mapToGlobal(p));
+ const auto *itemWindow = item->window();
+ const auto *thisWindow = window();
+ if (thisWindow && itemWindow && itemWindow != thisWindow)
+ p = itemWindow->mapFromGlobal(thisWindow->mapToGlobal(p));
p = item->mapFromScene(p);
}
@@ -8862,9 +8863,10 @@ QPointF QQuickItem::mapFromItem(const QQuickItem *item, const QPointF &point) co
QPointF p = point;
if (item) {
p = item->mapToScene(point);
-
- if (item->window() != window())
- p = window()->mapFromGlobal(item->window()->mapToGlobal(p));
+ const auto *itemWindow = item->window();
+ const auto *thisWindow = window();
+ if (thisWindow && itemWindow && itemWindow != thisWindow)
+ p = thisWindow->mapFromGlobal(itemWindow->mapToGlobal(p));
}
return mapFromScene(p);
}
diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml b/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml
index 98fc0e77af..1696699a75 100644
--- a/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml
+++ b/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml
@@ -48,4 +48,15 @@ QtObject {
color: "cyan"
}
}
+
+ property Item itemWithoutWindowA: Item {
+ x: 20; y: 20
+ }
+ property Item itemWithoutWindowB: Item {
+ x: 40; y: 40
+ Item {
+ objectName: "childItemWithoutWindow"
+ x: 30; y: 30
+ }
+ }
}
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index 154c4a661f..eb4f62e65f 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -2945,6 +2945,33 @@ void tst_QQuickItem::mapCoordinatesWithWindows()
globalItemOffset(childItemInChildWindow, childItemInOtherWindow));
QCOMPARE(childItemInChildWindow->mapFromItem(childItemInOtherWindow, {0, 0}),
globalItemOffset(childItemInOtherWindow, childItemInChildWindow));
+
+ // If one or both of the items are not in a scene (yet), they are assumed
+ // to eventually be in the same scene.
+
+ auto *itemWithoutWindowA = root->property("itemWithoutWindowA").value<QQuickItem*>();
+ QVERIFY(itemWithoutWindowA);
+ auto *itemWithoutWindowB = root->property("itemWithoutWindowB").value<QQuickItem*>();
+ QVERIFY(itemWithoutWindowB);
+ auto *childItemWithoutWindow = itemWithoutWindowB->findChild<QQuickItem*>("childItemWithoutWindow");
+ QVERIFY(childItemWithoutWindow);
+
+ QPoint itemWithoutWindowAPos = itemWithoutWindowA->position().toPoint();
+ QPoint itemWithoutWindowBPos = itemWithoutWindowB->position().toPoint();
+
+ QCOMPARE(itemWithoutWindowA->mapToItem(childItemWithoutWindow, {0, 0}),
+ itemWithoutWindowAPos - (itemWithoutWindowBPos + childItemWithoutWindow->position()));
+ QCOMPARE(itemWithoutWindowA->mapFromItem(childItemWithoutWindow, {0, 0}),
+ (itemWithoutWindowBPos + childItemWithoutWindow->position()) - itemWithoutWindowAPos);
+
+ QCOMPARE(itemWithoutWindowA->mapToItem(childItem, {0, 0}),
+ itemWithoutWindowAPos - itemPos);
+ QCOMPARE(itemWithoutWindowA->mapFromItem(childItem, {0, 0}),
+ itemPos - itemWithoutWindowAPos);
+ QCOMPARE(childItem->mapToItem(itemWithoutWindowA, {0, 0}),
+ itemPos - itemWithoutWindowAPos);
+ QCOMPARE(childItem->mapFromItem(itemWithoutWindowA, {0, 0}),
+ itemWithoutWindowAPos - itemPos);
}
void tst_QQuickItem::transforms_data()
--
2.47.0

View File

@ -1,127 +0,0 @@
From c343a0bb2a8f87758bf97241223224770e5c4687 Mon Sep 17 00:00:00 2001
From: Mitch Curtis <mitch.curtis@qt.io>
Date: Tue, 22 Oct 2024 13:26:08 +0800
Subject: [PATCH] QQuickItemView: fix crash with zero-size SwipeView that uses
Repeater
When running the minimal example from the bug report, the order of
events is:
1. deletables are iterated in QQuickRepeater::clear(), and deleteLater
is called on the delegate item.
2. deletables are unparented. This causes Container (SwipeView) to be
notified of the parent change and it removes the item. Part of this
involves changing the currentIndex, since the removed item was current.
3. SwipeView's contentItem (ListView) has its currentIndex bound to the
container's, so QQuickItemView::setCurrentIndex is called.
4. setCurrentIndex calls updateCurrent, which detects that the
currentIndex (which is -1, because there was only one item) is out of
range and so releases the item. This causes it to be added to
unrequestedItems, even though it has been scheduled for deletion.
This patch makes QQuickItemView detect that the item is going to be
deleted and not add it to the list of deletables.
Fixes: QTBUG-129622
Pick-to: 6.5 6.8
Change-Id: I999aedbdfafc61ff6d33eb6579331f470e9c1454
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
---
src/quick/items/qquickitemview.cpp | 4 +-
.../controls/data/tst_swipeview.qml | 59 +++++++++++++++++++
2 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 19e5b7f..dabd563 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -2499,7 +2499,9 @@ bool QQuickItemViewPrivate::releaseItem(FxViewItem *item, QQmlInstanceModel::Reu
// One case where this can happen is moving an item out of one ObjectModel and into another.
QQuickItemPrivate::get(item->item)->setCulled(true);
}
- if (!isClearing)
+ // If deleteLater was called, the item isn't long for this world and so we shouldn't store references to it.
+ // This can happen when a Repeater is used to populate items in SwipeView's ListView contentItem.
+ if (!isClearing && !QObjectPrivate::get(item->item)->deleteLaterCalled)
unrequestedItems.insert(item->item, model->indexOf(item->item, q));
} else if (flags & QQmlInstanceModel::Destroyed) {
item->item->setParentItem(nullptr);
diff --git a/tests/auto/quickcontrols/controls/data/tst_swipeview.qml b/tests/auto/quickcontrols/controls/data/tst_swipeview.qml
index 3a7558c..a3dd16c 100644
--- a/tests/auto/quickcontrols/controls/data/tst_swipeview.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_swipeview.qml
@@ -4,6 +4,7 @@
import QtQuick
import QtTest
import QtQuick.Controls
+import QtQuick.Layouts
TestCase {
id: testCase
@@ -760,4 +761,62 @@ TestCase {
tryCompare(swipeListView, "contentX", swipeListView.width, 1000)
compare(item2.x, swipeListView.width)
}
+
+ Component {
+ id: zeroSizeSwipeViewWithRepeatersComponent
+
+ Item {
+ objectName: "rootItem"
+ anchors.fill: parent
+
+ property alias swipeView: swipeView
+ property int d
+
+ Timer {
+ interval: 2
+ running: true
+ repeat: false
+ onTriggered: d = 2
+ }
+
+ SwipeView {
+ id: swipeView
+ contentItem.objectName: "swipeViewListView"
+
+ Repeater {
+ objectName: "swipeViewContentItemRepeater"
+ model: [
+ {
+ title: d
+ }
+ ]
+
+ delegate: GridLayout {
+ objectName: "gridLayoutDelegate"
+
+ Repeater {
+ id: repeater
+ objectName: "delegateRepeater"
+ model: d
+ delegate: Item {
+ objectName: "delegate" + index
+
+ required property int index
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // QTBUG-129622
+ function test_zeroSizeSwipeViewWithRepeaters() {
+ let root = createTemporaryObject(zeroSizeSwipeViewWithRepeatersComponent, testCase)
+ verify(root)
+
+ let swipeView = root.swipeView
+ tryCompare(root, "d", 2)
+ // Shouldn't crash when the model is changed.
+ }
}
--
2.47.0

View File

@ -1,420 +0,0 @@
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

View File

@ -1,473 +0,0 @@
From 2aefbca84d2f3dca2c2697f13710b6907c0c7e59 Mon Sep 17 00:00:00 2001
From: Mitch Curtis <mitch.curtis@qt.io>
Date: Tue, 24 Sep 2024 10:22:12 +0800
Subject: [PATCH 2/2] QQmlDelegateModel: fix delegates not being created in
certain cases v2
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.
This is a less intrusive alternative to
6561344dd2d1ba69abe6edec4fe340b256da9e13, which caused regressions and
was reverted.
Fixes: QTBUG-125053
Task-number: QTBUG-127340
Pick-to: 6.7 6.5
Change-Id: I2bfe192ed61eddaa481de4b1e14b1fa5d07a51c1
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
(cherry picked from commit 4bb16ce2c8ea94f768991593a581c8838d48f3a3)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
---
src/qmlmodels/qqmldelegatemodel.cpp | 17 ++
.../auto/qml/qqmldelegatemodel/CMakeLists.txt | 1 +
...yModelWithDelayedSourceModelInListView.qml | 30 +++
.../auto/qml/qqmldelegatemodel/data/reset.qml | 28 +++
.../data/resetInQAIMConstructor.qml | 28 +++
.../tst_qqmldelegatemodel.cpp | 210 +++++++++++++++++-
6 files changed, 304 insertions(+), 10 deletions(-)
create mode 100644 tests/auto/qml/qqmldelegatemodel/data/proxyModelWithDelayedSourceModelInListView.qml
create mode 100644 tests/auto/qml/qqmldelegatemodel/data/reset.qml
create mode 100644 tests/auto/qml/qqmldelegatemodel/data/resetInQAIMConstructor.qml
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
index 7cfa662aa6..f8de5cba82 100644
--- a/src/qmlmodels/qqmldelegatemodel.cpp
+++ b/src/qmlmodels/qqmldelegatemodel.cpp
@@ -3,6 +3,8 @@
#include "qqmldelegatemodel_p_p.h"
+#include <QtCore/private/qabstractitemmodel_p.h>
+
#include <QtQml/qqmlinfo.h>
#include <private/qqmlabstractdelegatecomponent_p.h>
@@ -409,6 +411,21 @@ void QQmlDelegateModel::setModel(const QVariant &model)
_q_itemsInserted(0, d->adaptorModelCount());
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);
+ }
}
/*!
diff --git a/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt b/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt
index 8d8a90e0a7..966f5229df 100644
--- a/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt
@@ -29,6 +29,7 @@ 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/proxyModelWithDelayedSourceModelInListView.qml b/tests/auto/qml/qqmldelegatemodel/data/proxyModelWithDelayedSourceModelInListView.qml
new file mode 100644
index 0000000000..b6733bd38c
--- /dev/null
+++ 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)
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/reset.qml b/tests/auto/qml/qqmldelegatemodel/data/reset.qml
new file mode 100644
index 0000000000..0fcd5e8afa
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/reset.qml
@@ -0,0 +1,28 @@
+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
new file mode 100644
index 0000000000..cb1f226737
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/resetInQAIMConstructor.qml
@@ -0,0 +1,28 @@
+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 2cacda5513..3f08d8fc85 100644
--- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
+++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
@@ -3,7 +3,9 @@
#include <QtTest/qtest.h>
#include <QtCore/qjsonobject.h>
+#include <QtCore/qsortfilterproxymodel.h>
#include <QtCore/QConcatenateTablesProxyModel>
+#include <QtCore/qtimer.h>
#include <QtGui/QStandardItemModel>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlapplicationengine.h>
@@ -11,11 +13,17 @@
#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
@@ -25,6 +33,8 @@ public:
private slots:
void resettingRolesRespected();
+ void resetInQAIMConstructor();
+ void reset();
void valueWithoutCallingObjectFirst_data();
void valueWithoutCallingObjectFirst();
void qtbug_86017();
@@ -42,18 +52,12 @@ private slots:
void doNotUnrefObjectUnderConstruction();
void clearCacheDuringInsertion();
void viewUpdatedOnDelegateChoiceAffectingRoleChange();
+ void proxyModelWithDelayedSourceModelInListView();
};
-class AbstractItemModel : public QAbstractItemModel
+class BaseAbstractItemModel : 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())
@@ -91,10 +95,21 @@ public:
return mValues.at(index.row());
}
-private:
+protected:
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)
{
@@ -153,7 +168,109 @@ void tst_QQmlDelegateModel::resettingRolesRespected()
QObject *root = engine.rootObjects().constFirst();
QVERIFY(!root->property("success").toBool());
model->change();
- QTRY_VERIFY(root->property("success").toBool());
+ 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");
}
void tst_QQmlDelegateModel::valueWithoutCallingObjectFirst_data()
@@ -616,6 +733,79 @@ void tst_QQmlDelegateModel::viewUpdatedOnDelegateChoiceAffectingRoleChange()
QVERIFY(returnedValue);
}
+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)
#include "tst_qqmldelegatemodel.moc"
--
2.46.1

View File

@ -2,20 +2,10 @@
<constraints>
<hardware>
<disk>
<size unit="G">25</size>
<size unit="G">20</size>
</disk>
<processors>4</processors>
</hardware>
<overwrite>
<conditions>
<arch>s390x</arch>
</conditions>
<hardware>
<memory>
<size unit="G">9</size>
</memory>
</hardware>
</overwrite>
<overwrite>
<conditions>
<arch>ppc64</arch>
@ -45,7 +35,7 @@
</conditions>
<hardware>
<disk>
<size unit="G">3</size>
<size unit="G">2</size>
</disk>
<memory>
<size unit="G">2</size>

View File

@ -1,52 +1,3 @@
-------------------------------------------------------------------
Mon Nov 4 17:50:07 UTC 2024 - Christophe Marin <christophe@krop.fr>
- Add upstream change (QTBUG-129500, kde#495089):
* 0001-QQuickItem-map-To-From-Item-Account-for-not-having-a.patch
-------------------------------------------------------------------
Fri Oct 25 11:42:28 UTC 2024 - Christophe Marin <christophe@krop.fr>
- 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)
-------------------------------------------------------------------
Tue Oct 15 09:37:16 UTC 2024 - Antonio Larrosa <alarrosa@suse.com>
- Update memory constraints for s390x and use %limit_build
-------------------------------------------------------------------
Tue Oct 15 07:52:36 UTC 2024 - Christophe Marin <christophe@krop.fr>
- Update disk constraints
-------------------------------------------------------------------
Wed Oct 9 16:52:34 UTC 2024 - Christophe Marin <christophe@krop.fr>
- Add upstream change to fix compilation failures (kde#494281, QTBUG-129797)
* 0001-Compiler-Wrap-raw-string-literals-in-QStringLiteral-.patch
-------------------------------------------------------------------
Tue Oct 8 10:17:37 UTC 2024 - Christophe Marin <christophe@krop.fr>
- Update to 6.8.0:
* https://www.qt.io/blog/qt-6.8-released
- Add upstream changes:
* 0001-Revert-QQmlDelegateModel-fix-delegates-not-being-cre.patch
* 0002-QQmlDelegateModel-fix-delegates-not-being-created-in.patch
(kde#493116, QTBUG-127340)
- Merge some -devel and -private-devel packages that only have
private API.
-------------------------------------------------------------------
Sat Sep 28 08:22:56 UTC 2024 - Christophe Marin <christophe@krop.fr>
- Update to 6.7.3
* https://www.qt.io/blog/qt-6.7.3-released
-------------------------------------------------------------------
Wed Jun 19 07:25:41 UTC 2024 - Christophe Marin <christophe@krop.fr>

File diff suppressed because it is too large Load Diff

BIN
qtdeclarative-everywhere-src-6.7.2.tar.xz (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3b41a36b42e919a3aa0da1f71107591504200f41707bee2ad8e8d4f99b5644c2
size 37029068