|
|
72ccf7 |
From 55324650f9e759a43dce927f823c9858574106c3 Mon Sep 17 00:00:00 2001
|
|
|
72ccf7 |
From: Alexey Edelev <alexey.edelev@qt.io>
|
|
|
72ccf7 |
Date: Tue, 12 Jan 2021 16:37:09 +0100
|
|
|
72ccf7 |
Subject: [PATCH 36/36] Do not revert properties of deleted objects
|
|
|
72ccf7 |
|
|
|
72ccf7 |
If state contains revert action of properties of deleted objects,
|
|
|
72ccf7 |
we should avoid adding them to apply list
|
|
|
72ccf7 |
|
|
|
72ccf7 |
Fixes: QTBUG-85106
|
|
|
72ccf7 |
Pick-to: 5.15
|
|
|
72ccf7 |
Change-Id: Iff57eb9958a054476096f6d951ab7390277a2b39
|
|
|
72ccf7 |
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
|
|
|
72ccf7 |
(cherry picked from commit 96763dbb105fde20431a264789ac27abfdab841c)
|
|
|
72ccf7 |
---
|
|
|
72ccf7 |
src/quick/util/qquickstate.cpp | 5 ++
|
|
|
72ccf7 |
.../data/revertNullObjectBinding.qml | 48 +++++++++++++
|
|
|
72ccf7 |
.../quick/qquickstates/tst_qquickstates.cpp | 68 +++++++++++++++++++
|
|
|
72ccf7 |
3 files changed, 121 insertions(+)
|
|
|
72ccf7 |
create mode 100644 tests/auto/quick/qquickstates/data/revertNullObjectBinding.qml
|
|
|
72ccf7 |
|
|
|
72ccf7 |
diff --git a/src/quick/util/qquickstate.cpp b/src/quick/util/qquickstate.cpp
|
|
|
72ccf7 |
index 71ab1f4d62..6a72754bde 100644
|
|
|
72ccf7 |
--- a/src/quick/util/qquickstate.cpp
|
|
|
72ccf7 |
+++ b/src/quick/util/qquickstate.cpp
|
|
|
72ccf7 |
@@ -635,6 +635,11 @@ void QQuickState::apply(QQuickTransition *trans, QQuickState *revert)
|
|
|
72ccf7 |
}
|
|
|
72ccf7 |
}
|
|
|
72ccf7 |
if (!found) {
|
|
|
72ccf7 |
+ // If revert list contains bindings assigned to deleted objects, we need to
|
|
|
72ccf7 |
+ // prevent reverting properties of those objects.
|
|
|
72ccf7 |
+ if (d->revertList.at(ii).binding() && !d->revertList.at(ii).property().object()) {
|
|
|
72ccf7 |
+ continue;
|
|
|
72ccf7 |
+ }
|
|
|
72ccf7 |
QVariant cur = d->revertList.at(ii).property().read();
|
|
|
72ccf7 |
QQmlPropertyPrivate::removeBinding(d->revertList.at(ii).property());
|
|
|
72ccf7 |
|
|
|
72ccf7 |
diff --git a/tests/auto/quick/qquickstates/data/revertNullObjectBinding.qml b/tests/auto/quick/qquickstates/data/revertNullObjectBinding.qml
|
|
|
72ccf7 |
new file mode 100644
|
|
|
72ccf7 |
index 0000000000..dee82f52ed
|
|
|
72ccf7 |
--- /dev/null
|
|
|
72ccf7 |
+++ b/tests/auto/quick/qquickstates/data/revertNullObjectBinding.qml
|
|
|
72ccf7 |
@@ -0,0 +1,48 @@
|
|
|
72ccf7 |
+import QtQuick 2.12
|
|
|
72ccf7 |
+import Qt.test 1.0
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+Item {
|
|
|
72ccf7 |
+ id: root
|
|
|
72ccf7 |
+ readonly property int someProp: 1234
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+ property bool state1Active: false
|
|
|
72ccf7 |
+ property bool state2Active: false
|
|
|
72ccf7 |
+ StateGroup {
|
|
|
72ccf7 |
+ states: [
|
|
|
72ccf7 |
+ State {
|
|
|
72ccf7 |
+ id: state1
|
|
|
72ccf7 |
+ name: "state1"
|
|
|
72ccf7 |
+ when: state1Active
|
|
|
72ccf7 |
+ changes: [
|
|
|
72ccf7 |
+ PropertyChanges {
|
|
|
72ccf7 |
+ objectName: "propertyChanges1"
|
|
|
72ccf7 |
+ target: ContainingObj.obj
|
|
|
72ccf7 |
+ prop: root.someProp
|
|
|
72ccf7 |
+ }
|
|
|
72ccf7 |
+ ]
|
|
|
72ccf7 |
+ }
|
|
|
72ccf7 |
+ ]}
|
|
|
72ccf7 |
+ StateGroup {
|
|
|
72ccf7 |
+ states: [
|
|
|
72ccf7 |
+ State {
|
|
|
72ccf7 |
+ id: state2
|
|
|
72ccf7 |
+ name: "state2"
|
|
|
72ccf7 |
+ when: state2Active
|
|
|
72ccf7 |
+ changes: [
|
|
|
72ccf7 |
+ PropertyChanges {
|
|
|
72ccf7 |
+ objectName: "propertyChanges2"
|
|
|
72ccf7 |
+ target: ContainingObj.obj
|
|
|
72ccf7 |
+ prop: 11111
|
|
|
72ccf7 |
+ }
|
|
|
72ccf7 |
+ ]
|
|
|
72ccf7 |
+ }
|
|
|
72ccf7 |
+ ]
|
|
|
72ccf7 |
+ }
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+ Component.onCompleted: {
|
|
|
72ccf7 |
+ state1Active = true;
|
|
|
72ccf7 |
+ state2Active = true;
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+ ContainingObj.reset()
|
|
|
72ccf7 |
+ }
|
|
|
72ccf7 |
+}
|
|
|
72ccf7 |
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
|
|
|
72ccf7 |
index d5fea3cb28..849522454f 100644
|
|
|
72ccf7 |
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
|
|
|
72ccf7 |
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
|
|
|
72ccf7 |
@@ -79,6 +79,55 @@ private:
|
|
|
72ccf7 |
QML_DECLARE_TYPE(MyRect)
|
|
|
72ccf7 |
QML_DECLARE_TYPEINFO(MyRect, QML_HAS_ATTACHED_PROPERTIES)
|
|
|
72ccf7 |
|
|
|
72ccf7 |
+class RemovableObj : public QObject
|
|
|
72ccf7 |
+{
|
|
|
72ccf7 |
+ Q_OBJECT
|
|
|
72ccf7 |
+ Q_PROPERTY(int prop READ prop WRITE setProp NOTIFY propChanged)
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+public:
|
|
|
72ccf7 |
+ RemovableObj(QObject *parent) : QObject(parent), m_prop(4321) { }
|
|
|
72ccf7 |
+ int prop() const { return m_prop; }
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+public slots:
|
|
|
72ccf7 |
+ void setProp(int prop)
|
|
|
72ccf7 |
+ {
|
|
|
72ccf7 |
+ if (m_prop == prop)
|
|
|
72ccf7 |
+ return;
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+ m_prop = prop;
|
|
|
72ccf7 |
+ emit propChanged(m_prop);
|
|
|
72ccf7 |
+ }
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+signals:
|
|
|
72ccf7 |
+ void propChanged(int prop);
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+private:
|
|
|
72ccf7 |
+ int m_prop;
|
|
|
72ccf7 |
+};
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+class ContainingObj : public QObject
|
|
|
72ccf7 |
+{
|
|
|
72ccf7 |
+ Q_OBJECT
|
|
|
72ccf7 |
+ Q_PROPERTY(RemovableObj *obj READ obj NOTIFY objChanged)
|
|
|
72ccf7 |
+ RemovableObj *m_obj;
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+public:
|
|
|
72ccf7 |
+ ContainingObj() : m_obj(new RemovableObj(this)) { }
|
|
|
72ccf7 |
+ RemovableObj *obj() const { return m_obj; }
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+ Q_INVOKABLE void reset()
|
|
|
72ccf7 |
+ {
|
|
|
72ccf7 |
+ if (m_obj) {
|
|
|
72ccf7 |
+ m_obj->deleteLater();
|
|
|
72ccf7 |
+ }
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+ m_obj = new RemovableObj(this);
|
|
|
72ccf7 |
+ emit objChanged();
|
|
|
72ccf7 |
+ }
|
|
|
72ccf7 |
+signals:
|
|
|
72ccf7 |
+ void objChanged();
|
|
|
72ccf7 |
+};
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
class tst_qquickstates : public QQmlDataTest
|
|
|
72ccf7 |
{
|
|
|
72ccf7 |
Q_OBJECT
|
|
|
72ccf7 |
@@ -140,12 +189,20 @@ private slots:
|
|
|
72ccf7 |
void duplicateStateName();
|
|
|
72ccf7 |
void trivialWhen();
|
|
|
72ccf7 |
void parentChangeCorrectReversal();
|
|
|
72ccf7 |
+ void revertNullObjectBinding();
|
|
|
72ccf7 |
};
|
|
|
72ccf7 |
|
|
|
72ccf7 |
void tst_qquickstates::initTestCase()
|
|
|
72ccf7 |
{
|
|
|
72ccf7 |
QQmlDataTest::initTestCase();
|
|
|
72ccf7 |
qmlRegisterType<MyRect>("Qt.test", 1, 0, "MyRectangle");
|
|
|
72ccf7 |
+ qmlRegisterSingletonType<ContainingObj>(
|
|
|
72ccf7 |
+ "Qt.test", 1, 0, "ContainingObj", [](QQmlEngine *engine, QJSEngine *) {
|
|
|
72ccf7 |
+ static ContainingObj instance;
|
|
|
72ccf7 |
+ engine->setObjectOwnership(&instance, QQmlEngine::CppOwnership);
|
|
|
72ccf7 |
+ return &instance;
|
|
|
72ccf7 |
+ });
|
|
|
72ccf7 |
+ qmlRegisterUncreatableType<RemovableObj>("Qt.test", 1, 0, "RemovableObj", "Uncreatable");
|
|
|
72ccf7 |
}
|
|
|
72ccf7 |
|
|
|
72ccf7 |
QByteArray tst_qquickstates::fullDataPath(const QString &path) const
|
|
|
72ccf7 |
@@ -1692,6 +1749,17 @@ void tst_qquickstates::parentChangeCorrectReversal()
|
|
|
72ccf7 |
QCOMPARE(oldX, stayingRectX.read().toDouble());
|
|
|
72ccf7 |
}
|
|
|
72ccf7 |
|
|
|
72ccf7 |
+void tst_qquickstates::revertNullObjectBinding()
|
|
|
72ccf7 |
+{
|
|
|
72ccf7 |
+ QQmlEngine engine;
|
|
|
72ccf7 |
+
|
|
|
72ccf7 |
+ QQmlComponent c(&engine, testFileUrl("revertNullObjectBinding.qml"));
|
|
|
72ccf7 |
+ QScopedPointer<QObject> root { c.create() };
|
|
|
72ccf7 |
+ QVERIFY(root);
|
|
|
72ccf7 |
+ QTest::qWait(10);
|
|
|
72ccf7 |
+ QQmlProperty state2Active(root.get(), "state2Active");
|
|
|
72ccf7 |
+ state2Active.write(false);
|
|
|
72ccf7 |
+}
|
|
|
72ccf7 |
|
|
|
72ccf7 |
QTEST_MAIN(tst_qquickstates)
|
|
|
72ccf7 |
|
|
|
72ccf7 |
--
|
|
|
72ccf7 |
2.31.1
|
|
|
72ccf7 |
|