aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikolaj Boc <[email protected]>2023-04-03 16:22:35 +0200
committerMikolaj Boc <[email protected]>2023-04-05 22:47:33 +0200
commit163443c6f75110174c2c2939fdb255f38daf630f (patch)
treeeaf97d4f95ea2414ca037dba2323ca0c0f9611be
parent10d5066983e909e29e4bbf96ca35925b6470264a (diff)
Correctly discover metaType for UntypedProxyProperty
When attempting to set two behaviors on the same property, the second behavior's target property gets intercepted by the first behavior. Then, meta type for UntypedProxyPropertyBindable in UntypedProxyProperty's ctor will not be discovered correctly, since UntypedProxyPropertyBindable interface's metaType is explicitly set to nullptr. Use QUntypedBindable::metaType instead to access MetaTypeAccessorFlag via iface->getter. A warning shall also be reported in case two or more interceptors are set on the same property. Fixes: QTBUG-98896 Change-Id: Ie38ae75235e000e25a60a1c2ccaad70a46f5018e Reviewed-by: Fabian Kosmale <[email protected]>
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp9
-rw-r--r--src/quick/util/qquickbehavior.cpp2
-rw-r--r--tests/auto/quick/qquickbehaviors/data/duplicated.qml31
-rw-r--r--tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp15
4 files changed, 56 insertions, 1 deletions
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index c863fa6647..41dfbf74f8 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -248,6 +248,15 @@ QQmlInterceptorMetaObject::~QQmlInterceptorMetaObject()
void QQmlInterceptorMetaObject::registerInterceptor(QQmlPropertyIndex index, QQmlPropertyValueInterceptor *interceptor)
{
+ for (QQmlPropertyValueInterceptor *vi = interceptors; vi; vi = vi->m_next) {
+ if (Q_UNLIKELY(vi->m_propertyIndex.coreIndex() == index.coreIndex())) {
+ qWarning() << "Attempting to set another interceptor on "
+ << object->metaObject()->className() << "property"
+ << object->metaObject()->property(index.coreIndex()).name()
+ << "- unsupported";
+ }
+ }
+
interceptor->m_propertyIndex = index;
interceptor->m_next = interceptors;
interceptors = interceptor;
diff --git a/src/quick/util/qquickbehavior.cpp b/src/quick/util/qquickbehavior.cpp
index 2522db37eb..95223faca1 100644
--- a/src/quick/util/qquickbehavior.cpp
+++ b/src/quick/util/qquickbehavior.cpp
@@ -151,7 +151,7 @@ public:
UntypedProxyProperty::UntypedProxyProperty(QUntypedBindable bindable, QQuickBehaviorPrivate *behavior) :
m_sourcePropertyData(QUntypedBindablePrivate::getPropertyData(bindable)),
m_sourceInterface(QUntypedBindablePrivate::getInterface(bindable)),
- m_storage(QVariant(QUntypedBindablePrivate::getInterface(bindable)->metaType()))
+ m_storage(QVariant(bindable.metaType()))
{
behavior->setSource(m_bindingData);
}
diff --git a/tests/auto/quick/qquickbehaviors/data/duplicated.qml b/tests/auto/quick/qquickbehaviors/data/duplicated.qml
new file mode 100644
index 0000000000..15518a05cf
--- /dev/null
+++ b/tests/auto/quick/qquickbehaviors/data/duplicated.qml
@@ -0,0 +1,31 @@
+import QtQuick 2.0
+Rectangle {
+ id: main
+
+ width: 400
+ height: 400
+
+ property bool behavior1Triggered
+ property bool behavior2Triggered
+
+ Behavior on x {
+ ScriptAction { script: behavior1Triggered = true }
+ }
+ Behavior on x {
+ ScriptAction { script: behavior2Triggered = true }
+ }
+
+ MouseArea {
+ id: clicker
+ anchors.fill: parent
+ }
+
+ states: State {
+ name: "moved"
+ when: clicker.pressed
+ PropertyChanges {
+ target: main
+ x: 200
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
index 5ea11729d8..7b4da918a3 100644
--- a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
+++ b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
@@ -33,6 +33,7 @@ private slots:
void group();
void valueType();
void emptyBehavior();
+ void duplicatedBehavior();
void explicitSelection();
void nonSelectingBehavior();
void reassignedAnimation();
@@ -223,6 +224,20 @@ void tst_qquickbehaviors::emptyBehavior()
QCOMPARE(x, qreal(200)); //should change immediately
}
+void tst_qquickbehaviors::duplicatedBehavior()
+{
+ QTest::failOnWarning(QRegularExpression(".*"));
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg,
+ QRegularExpression("Attempting to set another interceptor on.*"));
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("duplicated.qml"));
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle *>(c.create()));
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
+
+ // Expecting no crash
+ QQuickItemPrivate::get(rect.data())->setState("moved");
+}
+
void tst_qquickbehaviors::explicitSelection()
{
QQmlEngine engine;