Compare commits
No commits in common. 'i10ce' and 'c9' have entirely different histories.
@ -1 +1 @@
|
|||||||
SOURCES/qtdeclarative-everywhere-opensource-src-5.15.15.tar.xz
|
SOURCES/qtdeclarative-everywhere-opensource-src-5.15.9.tar.xz
|
||||||
|
@ -1 +1 @@
|
|||||||
04598aaa01a546648769e85e2e225047d153e7a8 SOURCES/qtdeclarative-everywhere-opensource-src-5.15.15.tar.xz
|
c1230f5c709f80d5bf7e61456a7d605983201cde SOURCES/qtdeclarative-everywhere-opensource-src-5.15.9.tar.xz
|
||||||
|
@ -0,0 +1,113 @@
|
|||||||
|
From 7be5422134167fe6d9fd44ef683f407bbda1bce7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ulf Hermann <ulf.hermann@qt.io>
|
||||||
|
Date: Tue, 30 Nov 2021 14:39:48 +0100
|
||||||
|
Subject: [PATCH 14/19] Qml: Don't crash when as-casting to type with errors
|
||||||
|
|
||||||
|
Such types don't have a compilation unit, but we still know their names.
|
||||||
|
|
||||||
|
Pick-to: 6.2
|
||||||
|
Fixes: QTBUG-98792
|
||||||
|
Change-Id: I2db8dea3a5a02ec1492f7f7a054fd3ad4c6ad69a
|
||||||
|
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
||||||
|
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
|
||||||
|
(cherry picked from commit e0cd201e91ae64b9c03e0128cd17656b00611fbb)
|
||||||
|
---
|
||||||
|
src/qml/qml/qqmltypewrapper.cpp | 6 ++++--
|
||||||
|
src/qml/types/qqmlconnections.cpp | 2 +-
|
||||||
|
tests/auto/qml/qqmllanguage/data/Broken.qml | 5 +++++
|
||||||
|
tests/auto/qml/qqmllanguage/data/asBroken.qml | 6 ++++++
|
||||||
|
tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 16 ++++++++++++++++
|
||||||
|
5 files changed, 32 insertions(+), 3 deletions(-)
|
||||||
|
create mode 100644 tests/auto/qml/qqmllanguage/data/Broken.qml
|
||||||
|
create mode 100644 tests/auto/qml/qqmllanguage/data/asBroken.qml
|
||||||
|
|
||||||
|
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
|
||||||
|
index 175de8b936..a6ba4b8cb3 100644
|
||||||
|
--- a/src/qml/qml/qqmltypewrapper.cpp
|
||||||
|
+++ b/src/qml/qml/qqmltypewrapper.cpp
|
||||||
|
@@ -419,8 +419,10 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const
|
||||||
|
return Encode(false);
|
||||||
|
|
||||||
|
QQmlRefPointer<QQmlTypeData> td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl());
|
||||||
|
- ExecutableCompilationUnit *cu = td->compilationUnit();
|
||||||
|
- myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId);
|
||||||
|
+ if (ExecutableCompilationUnit *cu = td->compilationUnit())
|
||||||
|
+ myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId);
|
||||||
|
+ else
|
||||||
|
+ return Encode(false); // It seems myQmlType has some errors, so we could not compile it.
|
||||||
|
} else {
|
||||||
|
myQmlType = qenginepriv->metaObjectForType(myTypeId);
|
||||||
|
}
|
||||||
|
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
|
||||||
|
index 29ed62cd39..aba930dfe1 100644
|
||||||
|
--- a/src/qml/types/qqmlconnections.cpp
|
||||||
|
+++ b/src/qml/types/qqmlconnections.cpp
|
||||||
|
@@ -338,7 +338,7 @@ void QQmlConnections::connectSignalsToMethods()
|
||||||
|
&& propName.at(2).isUpper()) {
|
||||||
|
qmlWarning(this) << tr("Detected function \"%1\" in Connections element. "
|
||||||
|
"This is probably intended to be a signal handler but no "
|
||||||
|
- "signal of the target matches the name.").arg(propName);
|
||||||
|
+ "signal of the \"%2\" target matches the name.").arg(propName).arg(target->metaObject()->className());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/tests/auto/qml/qqmllanguage/data/Broken.qml b/tests/auto/qml/qqmllanguage/data/Broken.qml
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..e24d9112a8
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/auto/qml/qqmllanguage/data/Broken.qml
|
||||||
|
@@ -0,0 +1,5 @@
|
||||||
|
+import QtQml 2.15
|
||||||
|
+
|
||||||
|
+QtObject {
|
||||||
|
+ notThere: 5
|
||||||
|
+}
|
||||||
|
diff --git a/tests/auto/qml/qqmllanguage/data/asBroken.qml b/tests/auto/qml/qqmllanguage/data/asBroken.qml
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..bd88d14c76
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/auto/qml/qqmllanguage/data/asBroken.qml
|
||||||
|
@@ -0,0 +1,6 @@
|
||||||
|
+import QtQml 2.15
|
||||||
|
+
|
||||||
|
+QtObject {
|
||||||
|
+ id: self
|
||||||
|
+ property var selfAsBroken: self as Broken
|
||||||
|
+}
|
||||||
|
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
|
||||||
|
index bffb62c59e..97cc64991f 100644
|
||||||
|
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
|
||||||
|
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
|
||||||
|
@@ -336,6 +336,7 @@ private slots:
|
||||||
|
void bareInlineComponent();
|
||||||
|
|
||||||
|
void hangOnWarning();
|
||||||
|
+ void objectAsBroken();
|
||||||
|
|
||||||
|
void ambiguousContainingType();
|
||||||
|
|
||||||
|
@@ -5876,6 +5877,21 @@ void tst_qqmllanguage::ambiguousContainingType()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+void tst_qqmllanguage::objectAsBroken()
|
||||||
|
+{
|
||||||
|
+ QQmlEngine engine;
|
||||||
|
+ QQmlComponent c(&engine, testFileUrl("asBroken.qml"));
|
||||||
|
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
|
||||||
|
+ QScopedPointer<QObject> o(c.create());
|
||||||
|
+ QVERIFY(!o.isNull());
|
||||||
|
+ QVariant selfAsBroken = o->property("selfAsBroken");
|
||||||
|
+ QVERIFY(selfAsBroken.isValid());
|
||||||
|
+ // QCOMPARE(selfAsBroken.metaType(), QMetaType::fromType<std::nullptr_t>());
|
||||||
|
+
|
||||||
|
+ QQmlComponent b(&engine, testFileUrl("Broken.qml"));
|
||||||
|
+ QVERIFY(b.isError());
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
QTEST_MAIN(tst_qqmllanguage)
|
||||||
|
|
||||||
|
#include "tst_qqmllanguage.moc"
|
||||||
|
--
|
||||||
|
2.40.0
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
From d54b978c0cba2bf75e145c9e1b00d2a9ab495d70 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||||
|
Date: Mon, 19 Dec 2022 10:05:33 +0100
|
||||||
|
Subject: [PATCH 15/19] Fix missing glyphs when using NativeRendering
|
||||||
|
|
||||||
|
When we look up glyphs with subpixel positions in the glyph cache,
|
||||||
|
we use the calculated subpixel position (from a set of predefined
|
||||||
|
subpixel positions) as key. In some very rare cases, we could end
|
||||||
|
up with different subpixel positions when looking up an on-screen
|
||||||
|
position than when we entered it into the cache, due to numerical
|
||||||
|
differences when doing the calculation.
|
||||||
|
|
||||||
|
The reason for this was that when entering the glyph into the
|
||||||
|
cache, we used the 16.6 fixed point representation, whereas when
|
||||||
|
looking up, we used the unmodified float. In some cases, the
|
||||||
|
converted fixed point approximation might snap to a different
|
||||||
|
predefined subpixel position than the floating point equivalent.
|
||||||
|
|
||||||
|
To avoid this, we reuse the converted fixed point positions when
|
||||||
|
looking up the glyphs in the cache.
|
||||||
|
|
||||||
|
[ChangeLog][Text] Fixed an issue where text using NativeRendering
|
||||||
|
would sometimes be missing glyphs.
|
||||||
|
|
||||||
|
Pick-to: 5.15 6.2 6.4 6.5
|
||||||
|
Fixes: QTBUG-108713
|
||||||
|
Change-Id: Iecc264eb3d27e875c24257eaefcfb18a1a5fb5be
|
||||||
|
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
|
||||||
|
Reviewed-by: Lars Knoll <lars@knoll.priv.no>
|
||||||
|
(cherry picked from commit 4bad329985b75090c68a70cceee7edadc172d7ab)
|
||||||
|
---
|
||||||
|
src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
|
||||||
|
index f912da5799..fd128aa06e 100644
|
||||||
|
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
|
||||||
|
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
|
||||||
|
@@ -839,9 +839,11 @@ void QSGTextMaskMaterial::populate(const QPointF &p,
|
||||||
|
bool supportsSubPixelPositions = fontD->fontEngine->supportsSubPixelPositions();
|
||||||
|
for (int i=0; i<glyphIndexes.size(); ++i) {
|
||||||
|
QPointF glyphPosition = glyphPositions.at(i) + position;
|
||||||
|
+ QFixedPoint fixedPointPosition = fixedPointPositions.at(i);
|
||||||
|
+
|
||||||
|
QFixed subPixelPosition;
|
||||||
|
if (supportsSubPixelPositions)
|
||||||
|
- subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(glyphPosition.x()));
|
||||||
|
+ subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(fixedPointPosition.x.toReal() * glyphCacheScaleX));
|
||||||
|
|
||||||
|
QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphIndexes.at(i), subPixelPosition);
|
||||||
|
const QTextureGlyphCache::Coord &c = cache->coords.value(glyph);
|
||||||
|
--
|
||||||
|
2.40.0
|
||||||
|
|
@ -1,51 +0,0 @@
|
|||||||
From 7882c22b04ecd7bc349d3d585b3de860b2c64781 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ulf Hermann <ulf.hermann@qt.io>
|
|
||||||
Date: Wed, 29 Mar 2023 16:36:03 +0200
|
|
||||||
Subject: [PATCH 15/25] Models: Avoid crashes when deleting cache items
|
|
||||||
|
|
||||||
Pick-to: 6.5 6.2 5.15
|
|
||||||
Fixes: QTBUG-91425
|
|
||||||
Change-Id: I58cf9ee29922f83fc6621f771b80ed557b31f106
|
|
||||||
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
|
|
||||||
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
|
||||||
(cherry picked from commit 0cfdecba54e4f40468c4c9a8a6668cc1bc0eff65)
|
|
||||||
|
|
||||||
* asturmlechner 2023-04-08: Resolve conflict with dev branch commit
|
|
||||||
c2d490a2385ea6f389340a296acaac0fa198c8b9 (qAsConst to std::as_const)
|
|
||||||
---
|
|
||||||
.../qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp | 12 ++++++++++++
|
|
||||||
1 file changed, 12 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
|
|
||||||
index e128d77c52..e5daf2d28b 100644
|
|
||||||
--- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
|
|
||||||
+++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
|
|
||||||
@@ -51,6 +51,7 @@ private slots:
|
|
||||||
void contextAccessedByHandler();
|
|
||||||
void deleteRace();
|
|
||||||
void redrawUponColumnChange();
|
|
||||||
+ void deleteRace();
|
|
||||||
};
|
|
||||||
|
|
||||||
class AbstractItemModel : public QAbstractItemModel
|
|
||||||
@@ -214,6 +215,17 @@ void tst_QQmlDelegateModel::redrawUponColumnChange()
|
|
||||||
QCOMPARE(item->property("text").toString(), "Coconut");
|
|
||||||
}
|
|
||||||
|
|
||||||
+void tst_QQmlDelegateModel::deleteRace()
|
|
||||||
+{
|
|
||||||
+ QQmlEngine engine;
|
|
||||||
+ QQmlComponent c(&engine, testFileUrl("deleteRace.qml"));
|
|
||||||
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
|
|
||||||
+ QScopedPointer<QObject> o(c.create());
|
|
||||||
+ QVERIFY(!o.isNull());
|
|
||||||
+ QTRY_COMPARE(o->property("count").toInt(), 2);
|
|
||||||
+ QTRY_COMPARE(o->property("count").toInt(), 0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
QTEST_MAIN(tst_QQmlDelegateModel)
|
|
||||||
|
|
||||||
#include "tst_qqmldelegatemodel.moc"
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
From 70b44dd18b9727e9aae857297265a751700a297e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Fushan Wen <qydwhotmail@gmail.com>
|
||||||
|
Date: Tue, 10 Jan 2023 20:42:04 +0800
|
||||||
|
Subject: [PATCH 16/19] Revert "Fix missing glyphs when using NativeRendering"
|
||||||
|
|
||||||
|
This reverts commit da5e53b649f50cd9cdd89dadbba16f05e4070be2.
|
||||||
|
|
||||||
|
It breaks fonts on Wayland when global scale > 100%.
|
||||||
|
---
|
||||||
|
src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 4 +---
|
||||||
|
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
|
||||||
|
index fd128aa06e..f912da5799 100644
|
||||||
|
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
|
||||||
|
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
|
||||||
|
@@ -839,11 +839,9 @@ void QSGTextMaskMaterial::populate(const QPointF &p,
|
||||||
|
bool supportsSubPixelPositions = fontD->fontEngine->supportsSubPixelPositions();
|
||||||
|
for (int i=0; i<glyphIndexes.size(); ++i) {
|
||||||
|
QPointF glyphPosition = glyphPositions.at(i) + position;
|
||||||
|
- QFixedPoint fixedPointPosition = fixedPointPositions.at(i);
|
||||||
|
-
|
||||||
|
QFixed subPixelPosition;
|
||||||
|
if (supportsSubPixelPositions)
|
||||||
|
- subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(fixedPointPosition.x.toReal() * glyphCacheScaleX));
|
||||||
|
+ subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(glyphPosition.x()));
|
||||||
|
|
||||||
|
QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphIndexes.at(i), subPixelPosition);
|
||||||
|
const QTextureGlyphCache::Coord &c = cache->coords.value(glyph);
|
||||||
|
--
|
||||||
|
2.40.0
|
||||||
|
|
@ -1,35 +0,0 @@
|
|||||||
From e2c7bdca3d1442b9e4e265378ee17b9ac347b4c3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Maximilian Goldstein <max.goldstein@qt.io>
|
|
||||||
Date: Wed, 9 Jun 2021 15:02:45 +0200
|
|
||||||
Subject: [PATCH 16/25] qv4function: Fix crash due to reference being
|
|
||||||
invalidated
|
|
||||||
|
|
||||||
Function::updateInternalClass creates a reference to a QStringList that is appended to before being used.
|
|
||||||
This is unsafe and can leads to a segfault if the append() causes a reallocation.
|
|
||||||
|
|
||||||
Fixes: QTBUG-94360
|
|
||||||
Pick-to: 5.15 6.1 6.2
|
|
||||||
Change-Id: Iac49e8d816cf440ca2b70e133c88314eb8df6b91
|
|
||||||
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
|
||||||
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
|
|
||||||
(cherry picked from commit 7fa28f98824a94396106eadfc028b329985a0cfc)
|
|
||||||
---
|
|
||||||
src/qml/jsruntime/qv4function.cpp | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
|
|
||||||
index cf8a53cf9f..223e64271e 100644
|
|
||||||
--- a/src/qml/jsruntime/qv4function.cpp
|
|
||||||
+++ b/src/qml/jsruntime/qv4function.cpp
|
|
||||||
@@ -136,7 +136,7 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr
|
|
||||||
if (duplicate == -1) {
|
|
||||||
parameterNames.append(QString::fromUtf8(param));
|
|
||||||
} else {
|
|
||||||
- const QString &dup = parameterNames[duplicate];
|
|
||||||
+ const QString dup = parameterNames[duplicate];
|
|
||||||
parameterNames.append(dup);
|
|
||||||
parameterNames[duplicate] =
|
|
||||||
QString(0xfffe) + QString::number(duplicate) + dup;
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -1,141 +0,0 @@
|
|||||||
From 980ed9bae736634ed6edf2d2b85b91bdb90e4f19 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Fabian Kosmale <fabian.kosmale@qt.io>
|
|
||||||
Date: Tue, 29 Mar 2022 10:44:04 +0200
|
|
||||||
Subject: [PATCH 17/25] Quick Animations: Fix crash
|
|
||||||
|
|
||||||
SwipeDelegate causes the running animation job to be deleted when
|
|
||||||
calling swipe.close in swipe.completed. Employ the RETURN_IF_DELETED
|
|
||||||
check in more places to avoid crashes.
|
|
||||||
|
|
||||||
Fixes: QTBUG-100560
|
|
||||||
Task-number: QTBUG-103223
|
|
||||||
Pick-to: 6.3 6.2 5.15
|
|
||||||
Change-Id: I276eeaa9aed1bdb36449b322a24641fa02c4d5e4
|
|
||||||
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
|
|
||||||
(cherry picked from commit 0238af0bd48b831d72126f2228d5913eccf67bae)
|
|
||||||
|
|
||||||
* asturmlechner 2023-04-09: Resolve conflict with dev branch commit
|
|
||||||
4938984f9a779192264757a06e6ca555fc8f5e91
|
|
||||||
---
|
|
||||||
.../qcontinuinganimationgroupjob.cpp | 4 +-
|
|
||||||
.../animations/qparallelanimationgroupjob.cpp | 4 +-
|
|
||||||
.../swipedelegate/CloseOnCompletedWorks.qml | 74 +++++++++++++++++++
|
|
||||||
3 files changed, 78 insertions(+), 4 deletions(-)
|
|
||||||
create mode 100644 tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml
|
|
||||||
|
|
||||||
diff --git a/src/qml/animations/qcontinuinganimationgroupjob.cpp b/src/qml/animations/qcontinuinganimationgroupjob.cpp
|
|
||||||
index 88c0e9e60e..61a9dc36f8 100644
|
|
||||||
--- a/src/qml/animations/qcontinuinganimationgroupjob.cpp
|
|
||||||
+++ b/src/qml/animations/qcontinuinganimationgroupjob.cpp
|
|
||||||
@@ -82,9 +82,9 @@ void QContinuingAnimationGroupJob::updateState(QAbstractAnimationJob::State newS
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) {
|
|
||||||
- resetUncontrolledAnimationFinishTime(animation);
|
|
||||||
+ RETURN_IF_DELETED(resetUncontrolledAnimationFinishTime(animation));
|
|
||||||
animation->setDirection(m_direction);
|
|
||||||
- animation->start();
|
|
||||||
+ RETURN_IF_DELETED(animation->start());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
diff --git a/src/qml/animations/qparallelanimationgroupjob.cpp b/src/qml/animations/qparallelanimationgroupjob.cpp
|
|
||||||
index 420a934ba2..a828d0e234 100644
|
|
||||||
--- a/src/qml/animations/qparallelanimationgroupjob.cpp
|
|
||||||
+++ b/src/qml/animations/qparallelanimationgroupjob.cpp
|
|
||||||
@@ -144,10 +144,10 @@ void QParallelAnimationGroupJob::updateState(QAbstractAnimationJob::State newSta
|
|
||||||
animation->stop();
|
|
||||||
m_previousLoop = m_direction == Forward ? 0 : m_loopCount - 1;
|
|
||||||
}
|
|
||||||
- resetUncontrolledAnimationFinishTime(animation);
|
|
||||||
+ RETURN_IF_DELETED(resetUncontrolledAnimationFinishTime(animation));
|
|
||||||
animation->setDirection(m_direction);
|
|
||||||
if (shouldAnimationStart(animation, oldState == Stopped))
|
|
||||||
- animation->start();
|
|
||||||
+ RETURN_IF_DELETED(animation->start());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
diff --git a/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml b/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..38dfde41c3
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml
|
|
||||||
@@ -0,0 +1,74 @@
|
|
||||||
+/****************************************************************************
|
|
||||||
+**
|
|
||||||
+** Copyright (C) 2022 The Qt Company Ltd.
|
|
||||||
+** Contact: https://www.qt.io/licensing/
|
|
||||||
+**
|
|
||||||
+** This file is part of the test suite of the Qt Toolkit.
|
|
||||||
+**
|
|
||||||
+** $QT_BEGIN_LICENSE:BSD$
|
|
||||||
+** Commercial License Usage
|
|
||||||
+** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
+** accordance with the commercial license agreement provided with the
|
|
||||||
+** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
+** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
+** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
+** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
+**
|
|
||||||
+** BSD License Usage
|
|
||||||
+** Alternatively, you may use this file under the terms of the BSD license
|
|
||||||
+** as follows:
|
|
||||||
+**
|
|
||||||
+** "Redistribution and use in source and binary forms, with or without
|
|
||||||
+** modification, are permitted provided that the following conditions are
|
|
||||||
+** met:
|
|
||||||
+** * Redistributions of source code must retain the above copyright
|
|
||||||
+** notice, this list of conditions and the following disclaimer.
|
|
||||||
+** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
+** notice, this list of conditions and the following disclaimer in
|
|
||||||
+** the documentation and/or other materials provided with the
|
|
||||||
+** distribution.
|
|
||||||
+** * Neither the name of The Qt Company Ltd nor the names of its
|
|
||||||
+** contributors may be used to endorse or promote products derived
|
|
||||||
+** from this software without specific prior written permission.
|
|
||||||
+**
|
|
||||||
+**
|
|
||||||
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
|
||||||
+**
|
|
||||||
+** $QT_END_LICENSE$
|
|
||||||
+**
|
|
||||||
+****************************************************************************/
|
|
||||||
+
|
|
||||||
+import QtQuick 2
|
|
||||||
+import QtQuick.Controls 2
|
|
||||||
+ApplicationWindow {
|
|
||||||
+ visible: true
|
|
||||||
+ width: 640
|
|
||||||
+ height: 480
|
|
||||||
+
|
|
||||||
+ ListView {
|
|
||||||
+ anchors.fill: parent
|
|
||||||
+ model: 2
|
|
||||||
+
|
|
||||||
+ delegate: SwipeDelegate {
|
|
||||||
+ text: "Swipe me left (should not crash)"
|
|
||||||
+
|
|
||||||
+ swipe.right: Label {
|
|
||||||
+ text: "Release (should not crash)"
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ swipe.onCompleted: {
|
|
||||||
+ swipe.close()
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -1,129 +0,0 @@
|
|||||||
From d6d08e3bee98f150cc3182dba9b38996b1409a34 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Joni Poikelin <joni.poikelin@qt.io>
|
|
||||||
Date: Thu, 3 Sep 2020 14:22:26 +0300
|
|
||||||
Subject: [PATCH 18/25] Prevent crash when destroying asynchronous Loader
|
|
||||||
|
|
||||||
Fixes: QTBUG-86255
|
|
||||||
Pick-to: 5.15
|
|
||||||
Change-Id: I30488b64d910a1409a43e2e98ee7ab084aec33d2
|
|
||||||
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
|
|
||||||
(cherry picked from commit 149c1dd07b54ee0c027d94a49d52160dc4f4e2ac)
|
|
||||||
|
|
||||||
* asturmlechner 2023-01-06: Resolve conflict with dev branch commits
|
|
||||||
d51c007ecc8aa6256cb95cf3992e5ac34a70fa3f and
|
|
||||||
b2a4a61e8cb0839ba293783ac03c72f35c7b1307
|
|
||||||
---
|
|
||||||
src/qml/qml/qqmlvmemetaobject.cpp | 2 +-
|
|
||||||
.../quick/qquickgridview/data/qtbug86255.qml | 55 +++++++++++++++++++
|
|
||||||
.../qquickgridview/tst_qquickgridview.cpp | 13 +++++
|
|
||||||
3 files changed, 69 insertions(+), 1 deletion(-)
|
|
||||||
create mode 100644 tests/auto/quick/qquickgridview/data/qtbug86255.qml
|
|
||||||
|
|
||||||
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
|
|
||||||
index 1e0e4e419f..a0532d1794 100644
|
|
||||||
--- a/src/qml/qml/qqmlvmemetaobject.cpp
|
|
||||||
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
|
|
||||||
@@ -251,7 +251,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
|
|
||||||
if (!pd)
|
|
||||||
return;
|
|
||||||
|
|
||||||
- if (pd->notifyIndex() != -1)
|
|
||||||
+ if (pd->notifyIndex() != -1 && ctxt->engine)
|
|
||||||
connect(target, pd->notifyIndex(), ctxt->engine);
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/tests/auto/quick/qquickgridview/data/qtbug86255.qml b/tests/auto/quick/qquickgridview/data/qtbug86255.qml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..20688b1967
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tests/auto/quick/qquickgridview/data/qtbug86255.qml
|
|
||||||
@@ -0,0 +1,55 @@
|
|
||||||
+import QtQuick 2.15
|
|
||||||
+
|
|
||||||
+Item {
|
|
||||||
+ width: 240
|
|
||||||
+ height: 320
|
|
||||||
+
|
|
||||||
+ GridView {
|
|
||||||
+ id: grid
|
|
||||||
+ objectName: "view"
|
|
||||||
+ anchors.fill: parent
|
|
||||||
+ cellWidth: 64
|
|
||||||
+ cellHeight: 64
|
|
||||||
+ model: ListModel {
|
|
||||||
+ id: listModel
|
|
||||||
+
|
|
||||||
+ Component.onCompleted: reload()
|
|
||||||
+
|
|
||||||
+ function reload() {
|
|
||||||
+ clear();
|
|
||||||
+ for (let i = 0; i < 1000; i++) {
|
|
||||||
+ let magic = Math.random();
|
|
||||||
+ append( { magic } );
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ clip: true
|
|
||||||
+ delegate: Item {
|
|
||||||
+ id: d
|
|
||||||
+ property string val: magic
|
|
||||||
+ Loader {
|
|
||||||
+ property alias value: d.val
|
|
||||||
+ asynchronous: true
|
|
||||||
+ sourceComponent: cmp
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ Timer {
|
|
||||||
+ running: true
|
|
||||||
+ interval: 1000
|
|
||||||
+ onTriggered: listModel.reload()
|
|
||||||
+ }
|
|
||||||
+ Timer {
|
|
||||||
+ running: true
|
|
||||||
+ interval: 500
|
|
||||||
+ onTriggered: grid.flick(0, -4000)
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ Component {
|
|
||||||
+ id: cmp
|
|
||||||
+ Text {
|
|
||||||
+ text: value
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
|
|
||||||
index 94ec4f44d5..7d0d9fa7a7 100644
|
|
||||||
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
|
|
||||||
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
|
|
||||||
@@ -213,6 +213,7 @@ private slots:
|
|
||||||
void QTBUG_45640();
|
|
||||||
void QTBUG_49218();
|
|
||||||
void QTBUG_48870_fastModelUpdates();
|
|
||||||
+ void QTBUG_86255();
|
|
||||||
|
|
||||||
void keyNavigationEnabled();
|
|
||||||
void resizeDynamicCellWidthRtL();
|
|
||||||
@@ -6814,6 +6815,18 @@ void tst_QQuickGridView::resizeDynamicCellWidthRtL()
|
|
||||||
QTRY_COMPARE(gridview->contentX(), 0.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void tst_QQuickGridView::QTBUG_86255()
|
|
||||||
+{
|
|
||||||
+ QScopedPointer<QQuickView> window(createView());
|
|
||||||
+ window->setSource(testFileUrl("qtbug86255.qml"));
|
|
||||||
+ window->show();
|
|
||||||
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
|
|
||||||
+ QQuickGridView *view = findItem<QQuickGridView>(window->rootObject(), "view");
|
|
||||||
+ QVERIFY(view != nullptr);
|
|
||||||
+ QTRY_COMPARE(view->isFlicking(), true);
|
|
||||||
+ QTRY_COMPARE(view->isFlicking(), false);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void tst_QQuickGridView::releaseItems()
|
|
||||||
{
|
|
||||||
QScopedPointer<QQuickView> view(createView());
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -0,0 +1,162 @@
|
|||||||
|
From 89bf481b9b14f038c5e16421a7fce6dc6523785f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ulf Hermann <ulf.hermann@qt.io>
|
||||||
|
Date: Wed, 29 Mar 2023 16:36:03 +0200
|
||||||
|
Subject: [PATCH 19/19] Models: Avoid crashes when deleting cache items
|
||||||
|
|
||||||
|
Pick-to: 6.5 6.2 5.15
|
||||||
|
Fixes: QTBUG-91425
|
||||||
|
Change-Id: I58cf9ee29922f83fc6621f771b80ed557b31f106
|
||||||
|
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
|
||||||
|
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
||||||
|
(cherry picked from commit 0cfdecba54e4f40468c4c9a8a6668cc1bc0eff65)
|
||||||
|
|
||||||
|
* asturmlechner 2023-04-08: Resolve conflict with dev branch commit
|
||||||
|
c2d490a2385ea6f389340a296acaac0fa198c8b9 (qAsConst to std::as_const)
|
||||||
|
---
|
||||||
|
src/qmlmodels/qqmldelegatemodel.cpp | 23 ++++++---
|
||||||
|
.../qml/qqmldelegatemodel/data/deleteRace.qml | 50 +++++++++++++++++++
|
||||||
|
.../tst_qqmldelegatemodel.cpp | 12 +++++
|
||||||
|
3 files changed, 78 insertions(+), 7 deletions(-)
|
||||||
|
create mode 100644 tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml
|
||||||
|
|
||||||
|
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
|
||||||
|
index bc6b2447af..551e0ede95 100644
|
||||||
|
--- a/src/qmlmodels/qqmldelegatemodel.cpp
|
||||||
|
+++ b/src/qmlmodels/qqmldelegatemodel.cpp
|
||||||
|
@@ -1883,10 +1883,15 @@ void QQmlDelegateModelPrivate::emitChanges()
|
||||||
|
for (int i = 1; i < m_groupCount; ++i)
|
||||||
|
QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitModelUpdated(reset);
|
||||||
|
|
||||||
|
- auto cacheCopy = m_cache; // deliberate; emitChanges may alter m_cache
|
||||||
|
- for (QQmlDelegateModelItem *cacheItem : qAsConst(cacheCopy)) {
|
||||||
|
- if (cacheItem->attached)
|
||||||
|
- cacheItem->attached->emitChanges();
|
||||||
|
+ // emitChanges may alter m_cache and delete items
|
||||||
|
+ QVarLengthArray<QPointer<QQmlDelegateModelAttached>> attachedObjects;
|
||||||
|
+ attachedObjects.reserve(m_cache.length());
|
||||||
|
+ for (const QQmlDelegateModelItem *cacheItem : qAsConst(m_cache))
|
||||||
|
+ attachedObjects.append(cacheItem->attached);
|
||||||
|
+
|
||||||
|
+ for (const QPointer<QQmlDelegateModelAttached> &attached : qAsConst(attachedObjects)) {
|
||||||
|
+ if (attached && attached->m_cacheItem)
|
||||||
|
+ attached->emitChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2707,20 +2712,24 @@ void QQmlDelegateModelAttached::emitChanges()
|
||||||
|
m_previousGroups = m_cacheItem->groups;
|
||||||
|
|
||||||
|
int indexChanges = 0;
|
||||||
|
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) {
|
||||||
|
+ const int groupCount = m_cacheItem->metaType->groupCount;
|
||||||
|
+ for (int i = 1; i < groupCount; ++i) {
|
||||||
|
if (m_previousIndex[i] != m_currentIndex[i]) {
|
||||||
|
m_previousIndex[i] = m_currentIndex[i];
|
||||||
|
indexChanges |= (1 << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Don't access m_cacheItem anymore once we've started sending signals.
|
||||||
|
+ // We don't own it and someone might delete it.
|
||||||
|
+
|
||||||
|
int notifierId = 0;
|
||||||
|
const QMetaObject *meta = metaObject();
|
||||||
|
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) {
|
||||||
|
+ for (int i = 1; i < groupCount; ++i, ++notifierId) {
|
||||||
|
if (groupChanges & (1 << i))
|
||||||
|
QMetaObject::activate(this, meta, notifierId, nullptr);
|
||||||
|
}
|
||||||
|
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) {
|
||||||
|
+ for (int i = 1; i < groupCount; ++i, ++notifierId) {
|
||||||
|
if (indexChanges & (1 << i))
|
||||||
|
QMetaObject::activate(this, meta, notifierId, nullptr);
|
||||||
|
}
|
||||||
|
diff --git a/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml b/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..23874970e7
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml
|
||||||
|
@@ -0,0 +1,50 @@
|
||||||
|
+import QtQuick 2.15
|
||||||
|
+import QtQml.Models 2.15
|
||||||
|
+
|
||||||
|
+Item {
|
||||||
|
+ DelegateModel {
|
||||||
|
+ id: delegateModel
|
||||||
|
+ model: ListModel {
|
||||||
|
+ id: sourceModel
|
||||||
|
+
|
||||||
|
+ ListElement { title: "foo" }
|
||||||
|
+ ListElement { title: "bar" }
|
||||||
|
+
|
||||||
|
+ function clear() {
|
||||||
|
+ if (count > 0)
|
||||||
|
+ remove(0, count);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ groups: [
|
||||||
|
+ DelegateModelGroup { name: "selectedItems" }
|
||||||
|
+ ]
|
||||||
|
+
|
||||||
|
+ delegate: Text {
|
||||||
|
+ height: DelegateModel.inSelectedItems ? implicitHeight * 2 : implicitHeight
|
||||||
|
+ Component.onCompleted: {
|
||||||
|
+ if (index === 0)
|
||||||
|
+ DelegateModel.inSelectedItems = true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ Component.onCompleted: {
|
||||||
|
+ items.create(0)
|
||||||
|
+ items.create(1)
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ListView {
|
||||||
|
+ anchors.fill: parent
|
||||||
|
+ model: delegateModel
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ Timer {
|
||||||
|
+ running: true
|
||||||
|
+ interval: 10
|
||||||
|
+ onTriggered: sourceModel.clear()
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ property int count: delegateModel.items.count
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
|
||||||
|
index 1722447830..f473cff75f 100644
|
||||||
|
--- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
|
||||||
|
+++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
|
||||||
|
@@ -50,6 +50,7 @@ private slots:
|
||||||
|
void qtbug_86017();
|
||||||
|
void contextAccessedByHandler();
|
||||||
|
void redrawUponColumnChange();
|
||||||
|
+ void deleteRace();
|
||||||
|
};
|
||||||
|
|
||||||
|
class AbstractItemModel : public QAbstractItemModel
|
||||||
|
@@ -213,6 +214,17 @@ void tst_QQmlDelegateModel::redrawUponColumnChange()
|
||||||
|
QCOMPARE(item->property("text").toString(), "Coconut");
|
||||||
|
}
|
||||||
|
|
||||||
|
+void tst_QQmlDelegateModel::deleteRace()
|
||||||
|
+{
|
||||||
|
+ QQmlEngine engine;
|
||||||
|
+ QQmlComponent c(&engine, testFileUrl("deleteRace.qml"));
|
||||||
|
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
|
||||||
|
+ QScopedPointer<QObject> o(c.create());
|
||||||
|
+ QVERIFY(!o.isNull());
|
||||||
|
+ QTRY_COMPARE(o->property("count").toInt(), 2);
|
||||||
|
+ QTRY_COMPARE(o->property("count").toInt(), 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
QTEST_MAIN(tst_QQmlDelegateModel)
|
||||||
|
|
||||||
|
#include "tst_qqmldelegatemodel.moc"
|
||||||
|
--
|
||||||
|
2.40.0
|
||||||
|
|
@ -1,81 +0,0 @@
|
|||||||
From 11f5bc3d80c57ad2094ab2e8010955a1a0130feb Mon Sep 17 00:00:00 2001
|
|
||||||
From: Volker Hilsheimer <volker.hilsheimer@qt.io>
|
|
||||||
Date: Fri, 18 Nov 2022 14:20:20 +0100
|
|
||||||
Subject: [PATCH 19/25] QQuickItem: Fix effective visibility for items without
|
|
||||||
parent
|
|
||||||
|
|
||||||
Items are visible if they are children of a visible parent, and not
|
|
||||||
explicitly hidden. The effectiveVisible member stores the state and is
|
|
||||||
updated when conditions that impact the item visibility changes.
|
|
||||||
|
|
||||||
The old code returned true for items outside a visual hierarchy, which
|
|
||||||
broke signal emission when items were removed from a parent, e.g.
|
|
||||||
because the parent got destroyed. With this change, items removed from
|
|
||||||
a visual hierarchy will emit the visibleChanged signal.
|
|
||||||
|
|
||||||
Note: QQuickItem initializes the effectiveVisible member to true, even
|
|
||||||
if the item was created without parent item. Visual items are required
|
|
||||||
to be added to a visual hierarchy via setParentItem. For this reason,
|
|
||||||
newly created items never emit visibleChanged when they are added to
|
|
||||||
a parent.
|
|
||||||
|
|
||||||
Adjust the QQuickItem::visible test - it creates an item hierarchy
|
|
||||||
without window. Such items are never visible, so add a window and
|
|
||||||
parent the test item hierarchy to the window's content item.
|
|
||||||
|
|
||||||
This fixes the expected failures in the tests. It does introduce an
|
|
||||||
incompatibility with QGraphicsView and QGraphicsItem, which continue
|
|
||||||
to return true from QGraphicsItem::isVisible for items that are not
|
|
||||||
in an item hierarchy.
|
|
||||||
|
|
||||||
[ChangeLog][Qt Quick][QQuickItem] The visible property of Items without
|
|
||||||
a parent now always returns false, and the visibleChanged signal gets
|
|
||||||
emitted when the parent item of a visible item becomes null.
|
|
||||||
|
|
||||||
Fixes: QTBUG-108213
|
|
||||||
Change-Id: If4b2947cefd1407853f0f29e6c3fdbd49fc9af65
|
|
||||||
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
|
||||||
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
|
|
||||||
(cherry picked from commit d1b9a4cacfb966cf0a37983d8f8044f3aedf5de3)
|
|
||||||
|
|
||||||
CCBUG: 467909
|
|
||||||
CCBUG: 396359
|
|
||||||
---
|
|
||||||
src/quick/items/qquickitem.cpp | 6 ++----
|
|
||||||
tests/auto/quick/qquickitem/tst_qquickitem.cpp | 2 ++
|
|
||||||
2 files changed, 4 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
|
|
||||||
index 708dc5fe5e..7236973216 100644
|
|
||||||
--- a/src/quick/items/qquickitem.cpp
|
|
||||||
+++ b/src/quick/items/qquickitem.cpp
|
|
||||||
@@ -6082,10 +6082,8 @@ void QQuickItem::setEnabled(bool e)
|
|
||||||
|
|
||||||
bool QQuickItemPrivate::calcEffectiveVisible() const
|
|
||||||
{
|
|
||||||
- // XXX todo - Should the effective visible of an element with no parent just be the current
|
|
||||||
- // effective visible? This would prevent pointless re-processing in the case of an element
|
|
||||||
- // moving to/from a no-parent situation, but it is different from what graphics view does.
|
|
||||||
- return explicitVisible && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveVisible);
|
|
||||||
+ // An item is visible if it is a child of a visible parent, and not explicitly hidden.
|
|
||||||
+ return explicitVisible && parentItem && QQuickItemPrivate::get(parentItem)->effectiveVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
|
|
||||||
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
|
|
||||||
index 42348d8dd1..34eefd85e6 100644
|
|
||||||
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
|
|
||||||
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
|
|
||||||
@@ -989,7 +989,9 @@ void tst_qquickitem::setParentItem()
|
|
||||||
|
|
||||||
void tst_qquickitem::visible()
|
|
||||||
{
|
|
||||||
+ QQuickWindow window;
|
|
||||||
QQuickItem *root = new QQuickItem;
|
|
||||||
+ root->setParentItem(window.contentItem());
|
|
||||||
|
|
||||||
QQuickItem *child1 = new QQuickItem;
|
|
||||||
child1->setParentItem(root);
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
|||||||
From 9c27fd5c02dd4314192d142a9f2120be45748414 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Fushan Wen <qydwhotmail@gmail.com>
|
|
||||||
Date: Fri, 21 Apr 2023 23:38:04 +0800
|
|
||||||
Subject: [PATCH 20/25] Revert "QQuickItem: Fix effective visibility for items
|
|
||||||
without parent"
|
|
||||||
|
|
||||||
This breaks applications that use QQmlPropertyList to store QQuickItem
|
|
||||||
and don't set a parentItem for them.
|
|
||||||
|
|
||||||
Ref: https://github.com/musescore/MuseScore/issues/17276
|
|
||||||
|
|
||||||
This reverts commit 45c22a0221937682f4496801a495458a00f76d3a.
|
|
||||||
---
|
|
||||||
src/quick/items/qquickitem.cpp | 6 ++++--
|
|
||||||
tests/auto/quick/qquickitem/tst_qquickitem.cpp | 2 --
|
|
||||||
2 files changed, 4 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
|
|
||||||
index 7236973216..708dc5fe5e 100644
|
|
||||||
--- a/src/quick/items/qquickitem.cpp
|
|
||||||
+++ b/src/quick/items/qquickitem.cpp
|
|
||||||
@@ -6082,8 +6082,10 @@ void QQuickItem::setEnabled(bool e)
|
|
||||||
|
|
||||||
bool QQuickItemPrivate::calcEffectiveVisible() const
|
|
||||||
{
|
|
||||||
- // An item is visible if it is a child of a visible parent, and not explicitly hidden.
|
|
||||||
- return explicitVisible && parentItem && QQuickItemPrivate::get(parentItem)->effectiveVisible;
|
|
||||||
+ // XXX todo - Should the effective visible of an element with no parent just be the current
|
|
||||||
+ // effective visible? This would prevent pointless re-processing in the case of an element
|
|
||||||
+ // moving to/from a no-parent situation, but it is different from what graphics view does.
|
|
||||||
+ return explicitVisible && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveVisible);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
|
|
||||||
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
|
|
||||||
index 34eefd85e6..42348d8dd1 100644
|
|
||||||
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
|
|
||||||
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
|
|
||||||
@@ -989,9 +989,7 @@ void tst_qquickitem::setParentItem()
|
|
||||||
|
|
||||||
void tst_qquickitem::visible()
|
|
||||||
{
|
|
||||||
- QQuickWindow window;
|
|
||||||
QQuickItem *root = new QQuickItem;
|
|
||||||
- root->setParentItem(window.contentItem());
|
|
||||||
|
|
||||||
QQuickItem *child1 = new QQuickItem;
|
|
||||||
child1->setParentItem(root);
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
|||||||
From 9a1488c33d888e8d22905373599219b1d716aa8a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Volker Hilsheimer <volker.hilsheimer@qt.io>
|
|
||||||
Date: Tue, 18 Apr 2023 22:05:36 +0200
|
|
||||||
Subject: [PATCH 21/25] Accessibility: respect value in attached Accessible in
|
|
||||||
controls
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
QQuickItemPrivate::accessibleRole is virtual and called by the framework
|
|
||||||
to determine the role of an item. The default implementation checks and
|
|
||||||
respects a possible Accessible attached object. However, subclasses that
|
|
||||||
override the virtual don't, so the attached properties are ignored, and
|
|
||||||
the class-specific implementation wins. This makes it impossible to
|
|
||||||
change the role of e.g. a checkable button.
|
|
||||||
|
|
||||||
To fix that, move the code respecting the attached object into a non-
|
|
||||||
virtual function that the framework calls instead, and only call the
|
|
||||||
virtual member if there is no attached object, or if that object is not
|
|
||||||
initialized with a role. Replace calls to the virtual from the
|
|
||||||
framework with calls to the non-virtual wrapper.
|
|
||||||
|
|
||||||
Do this for both QQuickItem and for QQuickPopup, and adjust the logic
|
|
||||||
in QQuickControl types that create an attached object and initialize
|
|
||||||
it's role when accessibility becomes active. Use the non-overridable
|
|
||||||
effective role value for that as well.
|
|
||||||
|
|
||||||
Add a test case, and to avoid any new framework calls to the virtual,
|
|
||||||
make it private.
|
|
||||||
|
|
||||||
Fixes: QTBUG-110114
|
|
||||||
Pick-to: 6.5 6.2
|
|
||||||
Change-Id: Ia709cecbd181b6d8ee3297a4af60c1e7db9a2c51
|
|
||||||
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
|
|
||||||
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
|
|
||||||
(cherry picked from commit 3c08d08ae2bbd449cc0579a1b3cb499383c7a60c)
|
|
||||||
---
|
|
||||||
src/quick/accessible/qaccessiblequickitem.cpp | 2 +-
|
|
||||||
src/quick/items/qquickitem.cpp | 17 ++++++++++++-----
|
|
||||||
src/quick/items/qquickitem_p.h | 3 +++
|
|
||||||
3 files changed, 16 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
|
|
||||||
index a8df58d450..99e6eff7c3 100644
|
|
||||||
--- a/src/quick/accessible/qaccessiblequickitem.cpp
|
|
||||||
+++ b/src/quick/accessible/qaccessiblequickitem.cpp
|
|
||||||
@@ -230,7 +230,7 @@ QAccessible::Role QAccessibleQuickItem::role() const
|
|
||||||
|
|
||||||
QAccessible::Role role = QAccessible::NoRole;
|
|
||||||
if (item())
|
|
||||||
- role = QQuickItemPrivate::get(item())->accessibleRole();
|
|
||||||
+ role = QQuickItemPrivate::get(item())->effectiveAccessibleRole();
|
|
||||||
if (role == QAccessible::NoRole) {
|
|
||||||
if (qobject_cast<QQuickText*>(const_cast<QQuickItem *>(item())))
|
|
||||||
role = QAccessible::StaticText;
|
|
||||||
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
|
|
||||||
index 708dc5fe5e..8b139cb539 100644
|
|
||||||
--- a/src/quick/items/qquickitem.cpp
|
|
||||||
+++ b/src/quick/items/qquickitem.cpp
|
|
||||||
@@ -2401,7 +2401,7 @@ bool QQuickItemPrivate::canAcceptTabFocus(QQuickItem *item)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
#if QT_CONFIG(accessibility)
|
|
||||||
- QAccessible::Role role = QQuickItemPrivate::get(item)->accessibleRole();
|
|
||||||
+ QAccessible::Role role = QQuickItemPrivate::get(item)->effectiveAccessibleRole();
|
|
||||||
if (role == QAccessible::EditableText || role == QAccessible::Table || role == QAccessible::List) {
|
|
||||||
return true;
|
|
||||||
} else if (role == QAccessible::ComboBox || role == QAccessible::SpinBox) {
|
|
||||||
@@ -9010,13 +9010,20 @@ QQuickItemPrivate::ExtraData::ExtraData()
|
|
||||||
|
|
||||||
|
|
||||||
#if QT_CONFIG(accessibility)
|
|
||||||
-QAccessible::Role QQuickItemPrivate::accessibleRole() const
|
|
||||||
+QAccessible::Role QQuickItemPrivate::effectiveAccessibleRole() const
|
|
||||||
{
|
|
||||||
Q_Q(const QQuickItem);
|
|
||||||
- QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, false));
|
|
||||||
- if (accessibleAttached)
|
|
||||||
- return accessibleAttached->role();
|
|
||||||
+ auto *attached = qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, false);
|
|
||||||
+ auto role = QAccessible::NoRole;
|
|
||||||
+ if (auto *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(attached))
|
|
||||||
+ role = accessibleAttached->role();
|
|
||||||
+ if (role == QAccessible::NoRole)
|
|
||||||
+ role = accessibleRole();
|
|
||||||
+ return role;
|
|
||||||
+}
|
|
||||||
|
|
||||||
+QAccessible::Role QQuickItemPrivate::accessibleRole() const
|
|
||||||
+{
|
|
||||||
return QAccessible::NoRole;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
|
|
||||||
index ade8fb61f2..6f329bd119 100644
|
|
||||||
--- a/src/quick/items/qquickitem_p.h
|
|
||||||
+++ b/src/quick/items/qquickitem_p.h
|
|
||||||
@@ -575,7 +575,10 @@ public:
|
|
||||||
virtual void implicitHeightChanged();
|
|
||||||
|
|
||||||
#if QT_CONFIG(accessibility)
|
|
||||||
+ QAccessible::Role effectiveAccessibleRole() const;
|
|
||||||
+private:
|
|
||||||
virtual QAccessible::Role accessibleRole() const;
|
|
||||||
+public:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void setImplicitAntialiasing(bool antialiasing);
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
|||||||
From 788c7ea1500dd6e82dd602fc51e5aa6f639bcf5e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ulf Hermann <ulf.hermann@qt.io>
|
|
||||||
Date: Mon, 10 Jul 2023 07:43:28 +0200
|
|
||||||
Subject: [PATCH 22/25] QtQml: Clean up QQmlData ctor
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Initialize the "dummy" member even though we never use it. Static
|
|
||||||
analyzers complain about it and we may appreciate it having a defined
|
|
||||||
value in the future. Also, initialize other members inline where
|
|
||||||
possible.
|
|
||||||
|
|
||||||
Coverity-Id: 415867
|
|
||||||
Change-Id: Ie428eb3294d6363afe9d7ab2d2bed6e52df0b304
|
|
||||||
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
|
|
||||||
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
|
||||||
(cherry picked from commit 10985a568db8cfb4140140967f7d247627ec4350)
|
|
||||||
|
|
||||||
* asturmlechner 2023-08-12: Resolve conflicts with dev branch commits
|
|
||||||
10985a568db8cfb4140140967f7d247627ec4350 and
|
|
||||||
e5246cafffb93f69a49c133210390c253fcb71f2 and
|
|
||||||
d3b3fef5a878d7fd53de6a9f9fff196a273930e3
|
|
||||||
---
|
|
||||||
src/qml/qml/qqmldata_p.h | 20 ++++++++++----------
|
|
||||||
src/qml/qml/qqmlengine.cpp | 7 ++-----
|
|
||||||
2 files changed, 12 insertions(+), 15 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
|
|
||||||
index ee31cb38d9..bb0adf9dfa 100644
|
|
||||||
--- a/src/qml/qml/qqmldata_p.h
|
|
||||||
+++ b/src/qml/qml/qqmldata_p.h
|
|
||||||
@@ -187,7 +187,7 @@ public:
|
|
||||||
private:
|
|
||||||
void layout(QQmlNotifierEndpoint*);
|
|
||||||
};
|
|
||||||
- NotifyList *notifyList;
|
|
||||||
+ NotifyList *notifyList = nullptr;
|
|
||||||
|
|
||||||
inline QQmlNotifierEndpoint *notify(int index);
|
|
||||||
void addNotify(int index, QQmlNotifierEndpoint *);
|
|
||||||
@@ -201,12 +201,12 @@ public:
|
|
||||||
QQmlContextData *outerContext = nullptr;
|
|
||||||
QQmlContextDataRef ownContext;
|
|
||||||
|
|
||||||
- QQmlAbstractBinding *bindings;
|
|
||||||
- QQmlBoundSignal *signalHandlers;
|
|
||||||
+ QQmlAbstractBinding *bindings = nullptr;
|
|
||||||
+ QQmlBoundSignal *signalHandlers = nullptr;
|
|
||||||
|
|
||||||
// Linked list for QQmlContext::contextObjects
|
|
||||||
- QQmlData *nextContextObject;
|
|
||||||
- QQmlData**prevContextObject;
|
|
||||||
+ QQmlData *nextContextObject = nullptr;
|
|
||||||
+ QQmlData**prevContextObject = nullptr;
|
|
||||||
|
|
||||||
inline bool hasBindingBit(int) const;
|
|
||||||
inline void setBindingBit(QObject *obj, int);
|
|
||||||
@@ -216,10 +216,10 @@ public:
|
|
||||||
inline void setPendingBindingBit(QObject *obj, int);
|
|
||||||
inline void clearPendingBindingBit(int);
|
|
||||||
|
|
||||||
- quint16 lineNumber;
|
|
||||||
- quint16 columnNumber;
|
|
||||||
+ quint16 lineNumber = 0;
|
|
||||||
+ quint16 columnNumber = 0;
|
|
||||||
|
|
||||||
- quint32 jsEngineId; // id of the engine that created the jsWrapper
|
|
||||||
+ quint32 jsEngineId = 0; // id of the engine that created the jsWrapper
|
|
||||||
|
|
||||||
struct DeferredData {
|
|
||||||
DeferredData();
|
|
||||||
@@ -240,7 +240,7 @@ public:
|
|
||||||
|
|
||||||
QQmlPropertyCache *propertyCache;
|
|
||||||
|
|
||||||
- QQmlGuardImpl *guards;
|
|
||||||
+ QQmlGuardImpl *guards = 0;
|
|
||||||
|
|
||||||
static QQmlData *get(const QObject *object, bool create = false) {
|
|
||||||
QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
|
|
||||||
@@ -289,7 +289,7 @@ public:
|
|
||||||
|
|
||||||
private:
|
|
||||||
// For attachedProperties
|
|
||||||
- mutable QQmlDataExtended *extendedData;
|
|
||||||
+ mutable QQmlDataExtended *extendedData = nullptr;
|
|
||||||
|
|
||||||
Q_NEVER_INLINE static QQmlData *createQQmlData(QObjectPrivate *priv);
|
|
||||||
Q_NEVER_INLINE static QQmlPropertyCache *createPropertyCache(QJSEngine *engine, QObject *object);
|
|
||||||
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
|
|
||||||
index 852a673ebd..86a2d2b45a 100644
|
|
||||||
--- a/src/qml/qml/qqmlengine.cpp
|
|
||||||
+++ b/src/qml/qml/qqmlengine.cpp
|
|
||||||
@@ -725,11 +725,8 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
|
|
||||||
QQmlData::QQmlData()
|
|
||||||
: ownedByQml1(false), ownMemory(true), indestructible(true), explicitIndestructibleSet(false),
|
|
||||||
hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
|
|
||||||
- hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false),
|
|
||||||
- bindingBitsArraySize(InlineBindingArraySize), notifyList(nullptr),
|
|
||||||
- bindings(nullptr), signalHandlers(nullptr), nextContextObject(nullptr), prevContextObject(nullptr),
|
|
||||||
- lineNumber(0), columnNumber(0), jsEngineId(0),
|
|
||||||
- propertyCache(nullptr), guards(nullptr), extendedData(nullptr)
|
|
||||||
+ hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), dummy(0),
|
|
||||||
+ bindingBitsArraySize(InlineBindingArraySize), propertyCache(nullptr)
|
|
||||||
{
|
|
||||||
memset(bindingBitsValue, 0, sizeof(bindingBitsValue));
|
|
||||||
init();
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -1,277 +0,0 @@
|
|||||||
From d15877e074b5e7c0e61589168b5eaaced7e55bf4 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ulf Hermann <ulf.hermann@qt.io>
|
|
||||||
Date: Tue, 8 Aug 2023 14:54:01 +0200
|
|
||||||
Subject: [PATCH 23/25] QML: Make notify list thread safe
|
|
||||||
|
|
||||||
We keep the notifyList itself alive until the QQmlData itself is
|
|
||||||
deleted. This way any isSignalConnected() called while an
|
|
||||||
intermediate dtor runs can safely access it. We use atomics to make the
|
|
||||||
concurrent access to the pointer and the connection mask defined
|
|
||||||
behavior. However, we never need anything but relaxed semantics when
|
|
||||||
accessing it.
|
|
||||||
|
|
||||||
Pick-to: 5.15 6.2 6.5 6.6
|
|
||||||
Fixes: QTBUG-105090
|
|
||||||
Change-Id: I82537be86e5cc33c2a3d76ec639fcbac87eb45ad
|
|
||||||
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
|
||||||
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
|
|
||||||
(cherry picked from commit 691956654c1acab356ce704c58602cc3a99fabc3)
|
|
||||||
|
|
||||||
* asturmlechner 2023-08-12: Resolve conflict with dev branch commit
|
|
||||||
c249edb83fa67b3e5f711b28923397e66876182d which introduces a behavior
|
|
||||||
change, so cannot be backported. Applied changes logically as if that
|
|
||||||
commit never happened.
|
|
||||||
---
|
|
||||||
src/qml/qml/qqmldata_p.h | 66 ++++++++++++++++++-----------
|
|
||||||
src/qml/qml/qqmlengine.cpp | 85 +++++++++++++++++++++++++-------------
|
|
||||||
2 files changed, 99 insertions(+), 52 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
|
|
||||||
index bb0adf9dfa..187339169b 100644
|
|
||||||
--- a/src/qml/qml/qqmldata_p.h
|
|
||||||
+++ b/src/qml/qml/qqmldata_p.h
|
|
||||||
@@ -176,24 +176,24 @@ public:
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NotifyList {
|
|
||||||
- quint64 connectionMask;
|
|
||||||
-
|
|
||||||
- quint16 maximumTodoIndex;
|
|
||||||
- quint16 notifiesSize;
|
|
||||||
-
|
|
||||||
- QQmlNotifierEndpoint *todo;
|
|
||||||
- QQmlNotifierEndpoint**notifies;
|
|
||||||
+ QAtomicInteger<quint64> connectionMask;
|
|
||||||
+ QQmlNotifierEndpoint *todo = nullptr;
|
|
||||||
+ QQmlNotifierEndpoint**notifies = nullptr;
|
|
||||||
+ quint16 maximumTodoIndex = 0;
|
|
||||||
+ quint16 notifiesSize = 0;
|
|
||||||
void layout();
|
|
||||||
private:
|
|
||||||
void layout(QQmlNotifierEndpoint*);
|
|
||||||
};
|
|
||||||
- NotifyList *notifyList = nullptr;
|
|
||||||
+ QAtomicPointer<NotifyList> notifyList;
|
|
||||||
|
|
||||||
- inline QQmlNotifierEndpoint *notify(int index);
|
|
||||||
+ inline QQmlNotifierEndpoint *notify(int index) const;
|
|
||||||
void addNotify(int index, QQmlNotifierEndpoint *);
|
|
||||||
int endpointCount(int index);
|
|
||||||
bool signalHasEndpoint(int index) const;
|
|
||||||
- void disconnectNotifiers();
|
|
||||||
+
|
|
||||||
+ enum class DeleteNotifyList { Yes, No };
|
|
||||||
+ void disconnectNotifiers(DeleteNotifyList doDelete);
|
|
||||||
|
|
||||||
// The context that created the C++ object
|
|
||||||
QQmlContextData *context = nullptr;
|
|
||||||
@@ -240,7 +240,7 @@ public:
|
|
||||||
|
|
||||||
QQmlPropertyCache *propertyCache;
|
|
||||||
|
|
||||||
- QQmlGuardImpl *guards = 0;
|
|
||||||
+ QQmlGuardImpl *guards = nullptr;
|
|
||||||
|
|
||||||
static QQmlData *get(const QObject *object, bool create = false) {
|
|
||||||
QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
|
|
||||||
@@ -342,23 +342,31 @@ bool QQmlData::wasDeleted(const QObject *object)
|
|
||||||
return ddata && ddata->isQueuedForDeletion;
|
|
||||||
}
|
|
||||||
|
|
||||||
-QQmlNotifierEndpoint *QQmlData::notify(int index)
|
|
||||||
+inline bool isIndexInConnectionMask(quint64 connectionMask, int index)
|
|
||||||
+{
|
|
||||||
+ return connectionMask & (1ULL << quint64(index % 64));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+QQmlNotifierEndpoint *QQmlData::notify(int index) const
|
|
||||||
{
|
|
||||||
+ // Can only happen on "home" thread. We apply relaxed semantics when loading the atomics.
|
|
||||||
+
|
|
||||||
Q_ASSERT(index <= 0xFFFF);
|
|
||||||
|
|
||||||
- if (!notifyList || !(notifyList->connectionMask & (1ULL << quint64(index % 64)))) {
|
|
||||||
+ NotifyList *list = notifyList.loadRelaxed();
|
|
||||||
+ if (!list || !isIndexInConnectionMask(list->connectionMask.loadRelaxed(), index))
|
|
||||||
return nullptr;
|
|
||||||
- } else if (index < notifyList->notifiesSize) {
|
|
||||||
- return notifyList->notifies[index];
|
|
||||||
- } else if (index <= notifyList->maximumTodoIndex) {
|
|
||||||
- notifyList->layout();
|
|
||||||
- }
|
|
||||||
|
|
||||||
- if (index < notifyList->notifiesSize) {
|
|
||||||
- return notifyList->notifies[index];
|
|
||||||
- } else {
|
|
||||||
- return nullptr;
|
|
||||||
+ if (index < list->notifiesSize)
|
|
||||||
+ return list->notifies[index];
|
|
||||||
+
|
|
||||||
+ if (index <= list->maximumTodoIndex) {
|
|
||||||
+ list->layout();
|
|
||||||
+ if (index < list->notifiesSize)
|
|
||||||
+ return list->notifies[index];
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -367,7 +375,19 @@ QQmlNotifierEndpoint *QQmlData::notify(int index)
|
|
||||||
*/
|
|
||||||
inline bool QQmlData::signalHasEndpoint(int index) const
|
|
||||||
{
|
|
||||||
- return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
|
|
||||||
+ // This can be called from any thread.
|
|
||||||
+ // We still use relaxed semantics. If we're on a thread different from the "home" thread
|
|
||||||
+ // of the QQmlData, two interesting things might happen:
|
|
||||||
+ //
|
|
||||||
+ // 1. The list might go away while we hold it. In that case we are dealing with an object whose
|
|
||||||
+ // QObject dtor is being executed concurrently. This is UB already without the notify lists.
|
|
||||||
+ // Therefore, we don't need to consider it.
|
|
||||||
+ // 2. The connectionMask may be amended or zeroed while we are looking at it. In that case
|
|
||||||
+ // we "misreport" the endpoint. Since ordering of events across threads is inherently
|
|
||||||
+ // nondeterministic, either result is correct in that case. We can accept it.
|
|
||||||
+
|
|
||||||
+ NotifyList *list = notifyList.loadRelaxed();
|
|
||||||
+ return list && isIndexInConnectionMask(list->connectionMask.loadRelaxed(), index);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QQmlData::hasBindingBit(int coreIndex) const
|
|
||||||
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
|
|
||||||
index 86a2d2b45a..d6b2711c2d 100644
|
|
||||||
--- a/src/qml/qml/qqmlengine.cpp
|
|
||||||
+++ b/src/qml/qml/qqmlengine.cpp
|
|
||||||
@@ -718,7 +718,7 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
|
|
||||||
// Disconnect the notifiers now - during object destruction this would be too late, since
|
|
||||||
// the disconnect call wouldn't be able to call disconnectNotify(), as it isn't possible to
|
|
||||||
// get the metaobject anymore.
|
|
||||||
- d->disconnectNotifiers();
|
|
||||||
+ d->disconnectNotifiers(QQmlData::DeleteNotifyList::No);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -786,7 +786,10 @@ void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int in
|
|
||||||
// QQmlEngine to emit signals from a different thread. These signals are then automatically
|
|
||||||
// marshalled back onto the QObject's thread and handled by QML from there. This is tested
|
|
||||||
// by the qqmlecmascript::threadSignal() autotest.
|
|
||||||
- if (!ddata->notifyList)
|
|
||||||
+
|
|
||||||
+ // Relaxed semantics here. If we're on a different thread we might schedule a useless event,
|
|
||||||
+ // but that should be rare.
|
|
||||||
+ if (!ddata->notifyList.loadRelaxed())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto objectThreadData = QObjectPrivate::get(object)->threadData.loadRelaxed();
|
|
||||||
@@ -1832,49 +1835,73 @@ void QQmlData::releaseDeferredData()
|
|
||||||
|
|
||||||
void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
|
|
||||||
{
|
|
||||||
- if (!notifyList) {
|
|
||||||
- notifyList = (NotifyList *)malloc(sizeof(NotifyList));
|
|
||||||
- notifyList->connectionMask = 0;
|
|
||||||
- notifyList->maximumTodoIndex = 0;
|
|
||||||
- notifyList->notifiesSize = 0;
|
|
||||||
- notifyList->todo = nullptr;
|
|
||||||
- notifyList->notifies = nullptr;
|
|
||||||
+ // Can only happen on "home" thread. We apply relaxed semantics when loading the atomics.
|
|
||||||
+
|
|
||||||
+ NotifyList *list = notifyList.loadRelaxed();
|
|
||||||
+
|
|
||||||
+ if (!list) {
|
|
||||||
+ list = new NotifyList;
|
|
||||||
+ // We don't really care when this change takes effect on other threads. The notifyList can
|
|
||||||
+ // only become non-null once in the life time of a QQmlData. It becomes null again when the
|
|
||||||
+ // underlying QObject is deleted. At that point any interaction with the QQmlData is UB
|
|
||||||
+ // anyway. So, for all intents and purposese, the list becomes non-null once and then stays
|
|
||||||
+ // non-null "forever". We can apply relaxed semantics.
|
|
||||||
+ notifyList.storeRelaxed(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_ASSERT(!endpoint->isConnected());
|
|
||||||
|
|
||||||
index = qMin(index, 0xFFFF - 1);
|
|
||||||
- notifyList->connectionMask |= (1ULL << quint64(index % 64));
|
|
||||||
|
|
||||||
- if (index < notifyList->notifiesSize) {
|
|
||||||
+ // Likewise, we don't really care _when_ the change in the connectionMask is propagated to other
|
|
||||||
+ // threads. Cross-thread event ordering is inherently nondeterministic. Therefore, when querying
|
|
||||||
+ // the conenctionMask in the presence of concurrent modification, any result is correct.
|
|
||||||
+ list->connectionMask.storeRelaxed(
|
|
||||||
+ list->connectionMask.loadRelaxed() | (1ULL << quint64(index % 64)));
|
|
||||||
|
|
||||||
- endpoint->next = notifyList->notifies[index];
|
|
||||||
+ if (index < list->notifiesSize) {
|
|
||||||
+ endpoint->next = list->notifies[index];
|
|
||||||
if (endpoint->next) endpoint->next->prev = &endpoint->next;
|
|
||||||
- endpoint->prev = ¬ifyList->notifies[index];
|
|
||||||
- notifyList->notifies[index] = endpoint;
|
|
||||||
-
|
|
||||||
+ endpoint->prev = &list->notifies[index];
|
|
||||||
+ list->notifies[index] = endpoint;
|
|
||||||
} else {
|
|
||||||
- notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
|
|
||||||
+ list->maximumTodoIndex = qMax(int(list->maximumTodoIndex), index);
|
|
||||||
|
|
||||||
- endpoint->next = notifyList->todo;
|
|
||||||
+ endpoint->next = list->todo;
|
|
||||||
if (endpoint->next) endpoint->next->prev = &endpoint->next;
|
|
||||||
- endpoint->prev = ¬ifyList->todo;
|
|
||||||
- notifyList->todo = endpoint;
|
|
||||||
+ endpoint->prev = &list->todo;
|
|
||||||
+ list->todo = endpoint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-void QQmlData::disconnectNotifiers()
|
|
||||||
+void QQmlData::disconnectNotifiers(QQmlData::DeleteNotifyList doDelete)
|
|
||||||
{
|
|
||||||
- if (notifyList) {
|
|
||||||
- while (notifyList->todo)
|
|
||||||
- notifyList->todo->disconnect();
|
|
||||||
- for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
|
|
||||||
- while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
|
|
||||||
+ // Can only happen on "home" thread. We apply relaxed semantics when loading the atomics.
|
|
||||||
+ if (NotifyList *list = notifyList.loadRelaxed()) {
|
|
||||||
+ while (QQmlNotifierEndpoint *todo = list->todo)
|
|
||||||
+ todo->disconnect();
|
|
||||||
+ for (int ii = 0; ii < list->notifiesSize; ++ii) {
|
|
||||||
+ while (QQmlNotifierEndpoint *ep = list->notifies[ii])
|
|
||||||
ep->disconnect();
|
|
||||||
}
|
|
||||||
- free(notifyList->notifies);
|
|
||||||
- free(notifyList);
|
|
||||||
- notifyList = nullptr;
|
|
||||||
+ free(list->notifies);
|
|
||||||
+
|
|
||||||
+ if (doDelete == DeleteNotifyList::Yes) {
|
|
||||||
+ // We can only get here from QQmlData::destroyed(), and that can only come from the
|
|
||||||
+ // the QObject dtor. If you're still sending signals at that point you have UB already
|
|
||||||
+ // without any threads. Therefore, it's enough to apply relaxed semantics.
|
|
||||||
+ notifyList.storeRelaxed(nullptr);
|
|
||||||
+ delete list;
|
|
||||||
+ } else {
|
|
||||||
+ // We can use relaxed semantics here. The worst thing that can happen is that some
|
|
||||||
+ // signal is falsely reported as connected. Signal connectedness across threads
|
|
||||||
+ // is not quite deterministic anyway.
|
|
||||||
+ list->connectionMask.storeRelaxed(0);
|
|
||||||
+ list->maximumTodoIndex = 0;
|
|
||||||
+ list->notifiesSize = 0;
|
|
||||||
+ list->notifies = nullptr;
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1958,7 +1985,7 @@ void QQmlData::destroyed(QObject *object)
|
|
||||||
guard->objectDestroyed(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
- disconnectNotifiers();
|
|
||||||
+ disconnectNotifiers(DeleteNotifyList::Yes);
|
|
||||||
|
|
||||||
if (extendedData)
|
|
||||||
delete extendedData;
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
From 83cac09d86872edaa6fd4779597d6ba0bc4d2a8e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ulf Hermann <ulf.hermann@qt.io>
|
|
||||||
Date: Wed, 8 Feb 2023 12:14:21 +0100
|
|
||||||
Subject: [PATCH 24/25] QML: Fortify qmlExecuteDeferred some more
|
|
||||||
|
|
||||||
I don't know how to trigger this, but a recent crash report from the CI
|
|
||||||
shows that we can get there without a valid engine.
|
|
||||||
|
|
||||||
Pick-to: 6.5
|
|
||||||
Change-Id: I9f17894da82b8e7eab88181c96dfa8eaf7795523
|
|
||||||
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
|
||||||
(cherry picked from commit f69b6f0940b178b46ecbaa5f0b4956ac44e8379e)
|
|
||||||
---
|
|
||||||
src/qml/qml/qqmlengine.cpp | 21 +++++++++++++--------
|
|
||||||
1 file changed, 13 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
|
|
||||||
index d6b2711c2d..5f3367e4d2 100644
|
|
||||||
--- a/src/qml/qml/qqmlengine.cpp
|
|
||||||
+++ b/src/qml/qml/qqmlengine.cpp
|
|
||||||
@@ -1588,17 +1588,22 @@ void qmlExecuteDeferred(QObject *object)
|
|
||||||
{
|
|
||||||
QQmlData *data = QQmlData::get(object);
|
|
||||||
|
|
||||||
- if (data && !data->deferredData.isEmpty() && !data->wasDeleted(object)) {
|
|
||||||
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
|
|
||||||
+ if (!data
|
|
||||||
+ || !data->context
|
|
||||||
+ || !data->context->engine
|
|
||||||
+ || data->deferredData.isEmpty()
|
|
||||||
+ || data->wasDeleted(object)) {
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- QQmlComponentPrivate::DeferredState state;
|
|
||||||
- QQmlComponentPrivate::beginDeferred(ep, object, &state);
|
|
||||||
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
|
|
||||||
+ QQmlComponentPrivate::DeferredState state;
|
|
||||||
+ QQmlComponentPrivate::beginDeferred(ep, object, &state);
|
|
||||||
|
|
||||||
- // Release the reference for the deferral action (we still have one from construction)
|
|
||||||
- data->releaseDeferredData();
|
|
||||||
+ // Release the reference for the deferral action (we still have one from construction)
|
|
||||||
+ data->releaseDeferredData();
|
|
||||||
|
|
||||||
- QQmlComponentPrivate::completeDeferred(ep, &state);
|
|
||||||
- }
|
|
||||||
+ QQmlComponentPrivate::completeDeferred(ep, &state);
|
|
||||||
}
|
|
||||||
|
|
||||||
QQmlContext *qmlContext(const QObject *obj)
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
|||||||
From 310c124dac82d711ab15309a9cb0b9d95db9ea8f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Antonio Napolitano <anton@polit.no>
|
|
||||||
Date: Sat, 30 Dec 2023 19:11:32 +0100
|
|
||||||
Subject: [PATCH 25/25] masm: Don't crash on failed MADV_DONTNEED on Linux
|
|
||||||
|
|
||||||
The application could call mlockall(MCL_CURRENT|MCL_FUTURE) to lock all
|
|
||||||
its memory for performance reasons, causing the madvise call to fail.
|
|
||||||
There's no need to crash. Instead, manually zero-out the memory when
|
|
||||||
decommitting.
|
|
||||||
|
|
||||||
Fixes: QTBUG-120450
|
|
||||||
Pick-to: 5.15 6.2 6.5 6.6 6.7
|
|
||||||
Change-Id: I6f1a8968853cc5e61561371bd2a435a686eaf0e4
|
|
||||||
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
|
||||||
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
|
|
||||||
(cherry picked from commit 524d260c5c135d193e06350e48357444ddb13ddb)
|
|
||||||
---
|
|
||||||
src/3rdparty/masm/wtf/OSAllocatorPosix.cpp | 11 +++++------
|
|
||||||
1 file changed, 5 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp b/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp
|
|
||||||
index b5c5f6a2b0..1a3d3cdf97 100644
|
|
||||||
--- a/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp
|
|
||||||
+++ b/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp
|
|
||||||
@@ -112,10 +112,7 @@ void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable,
|
|
||||||
if (result == MAP_FAILED)
|
|
||||||
CRASH();
|
|
||||||
|
|
||||||
- while (madvise(result, bytes, MADV_DONTNEED)) {
|
|
||||||
- if (errno != EAGAIN)
|
|
||||||
- CRASH();
|
|
||||||
- }
|
|
||||||
+ while (madvise(result, bytes, MADV_DONTNEED) == -1 && errno == EAGAIN) { }
|
|
||||||
|
|
||||||
if (fd != -1)
|
|
||||||
close(fd);
|
|
||||||
@@ -248,8 +245,10 @@ void OSAllocator::decommit(void* address, size_t bytes)
|
|
||||||
mmap(address, bytes, PROT_NONE, MAP_FIXED | MAP_LAZY | MAP_PRIVATE | MAP_ANON, -1, 0);
|
|
||||||
#elif OS(LINUX)
|
|
||||||
while (madvise(address, bytes, MADV_DONTNEED)) {
|
|
||||||
- if (errno != EAGAIN)
|
|
||||||
- CRASH();
|
|
||||||
+ if (errno != EAGAIN) {
|
|
||||||
+ memset(address, 0, bytes); // We rely on madvise to zero-out the memory
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
if (mprotect(address, bytes, PROT_NONE))
|
|
||||||
CRASH();
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
|||||||
|
From e2bdde18d9758efdc6a0d7d106aad56995df1271 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ulf Hermann <ulf.hermann@qt.io>
|
||||||
|
Date: Wed, 15 Mar 2023 08:59:43 +0100
|
||||||
|
Subject: [PATCH] JIT: Add missing {STORE|LOAD}_ACC() to CreateCallContext
|
||||||
|
|
||||||
|
We cannot assume anything about the accumulator register after calling
|
||||||
|
PushCallContext::call(). Also add a note about not needing to re-load
|
||||||
|
the accumulator on ThrowException.
|
||||||
|
|
||||||
|
Pick-to: 6.5 6.2 5.15
|
||||||
|
Fixes: QTBUG-111935
|
||||||
|
Change-Id: I7196585e1d2697c215f4fe87d8d7ac9b98b622a3
|
||||||
|
---
|
||||||
|
src/qml/jit/qv4baselinejit.cpp | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp
|
||||||
|
index 14e183adb8..1d65169dce 100644
|
||||||
|
--- a/src/qml/jit/qv4baselinejit.cpp
|
||||||
|
+++ b/src/qml/jit/qv4baselinejit.cpp
|
||||||
|
@@ -506,6 +506,8 @@ void BaselineJIT::generate_ThrowException()
|
||||||
|
as->passEngineAsArg(0);
|
||||||
|
BASELINEJIT_GENERATE_RUNTIME_CALL(ThrowException, CallResultDestination::Ignore);
|
||||||
|
as->gotoCatchException();
|
||||||
|
+
|
||||||
|
+ // LOAD_ACC(); <- not needed here since it would be unreachable.
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaselineJIT::generate_GetException() { as->getException(); }
|
||||||
|
@@ -513,9 +515,11 @@ void BaselineJIT::generate_SetException() { as->setException(); }
|
||||||
|
|
||||||
|
void BaselineJIT::generate_CreateCallContext()
|
||||||
|
{
|
||||||
|
+ STORE_ACC();
|
||||||
|
as->prepareCallWithArgCount(1);
|
||||||
|
as->passCppFrameAsArg(0);
|
||||||
|
BASELINEJIT_GENERATE_RUNTIME_CALL(PushCallContext, CallResultDestination::Ignore);
|
||||||
|
+ LOAD_ACC();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaselineJIT::generate_PushCatchContext(int index, int name) { as->pushCatchContext(index, name); }
|
||||||
|
--
|
||||||
|
2.39.2
|
||||||
|
|
@ -0,0 +1,12 @@
|
|||||||
|
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
|
||||||
|
index 621e8bb4..24ea2201 100644
|
||||||
|
--- a/tests/auto/qml/qml.pro
|
||||||
|
+++ b/tests/auto/qml/qml.pro
|
||||||
|
@@ -25,7 +25,6 @@ PUBLICTESTS += \
|
||||||
|
qqmlmoduleplugin \
|
||||||
|
qqmlnotifier \
|
||||||
|
qqmlqt \
|
||||||
|
- qqmlxmlhttprequest \
|
||||||
|
qqmlpromise \
|
||||||
|
qtqmlmodules \
|
||||||
|
qquickfolderlistmodel \
|
Loading…
Reference in new issue