diff options
author | Mikolaj Boc <[email protected]> | 2023-04-03 16:22:35 +0200 |
---|---|---|
committer | Mikolaj Boc <[email protected]> | 2023-04-05 22:47:33 +0200 |
commit | 163443c6f75110174c2c2939fdb255f38daf630f (patch) | |
tree | eaf97d4f95ea2414ca037dba2323ca0c0f9611be | |
parent | 10d5066983e909e29e4bbf96ca35925b6470264a (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.cpp | 9 | ||||
-rw-r--r-- | src/quick/util/qquickbehavior.cpp | 2 | ||||
-rw-r--r-- | tests/auto/quick/qquickbehaviors/data/duplicated.qml | 31 | ||||
-rw-r--r-- | tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp | 15 |
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; |