diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2024-02-26 12:44:21 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-03-01 09:51:19 +0100 |
commit | 939c132db071873ab7bf7159d53541ab17182214 (patch) | |
tree | 230b02423671ad69bcb08f94797188d7dc62eb04 | |
parent | 72571aac9a393f0494831916ee53df8fa20f98c5 (diff) |
QQmlPropertyCache: Correctly set flags when loading methods
We commonly load multiple methods in sequence into the same
QQmlPropertyData. We need to set all the relevant flags for each one.
Otherwise the wrong flags are transferred to subsequent methods.
Pick-to: 6.5
Task-number: QTBUG-112366
Change-Id: I7432500b9149fdd8dd2dd98eb923ada70232fb6d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
(cherry picked from commit 69ca18785c6693b6cf167dc95275a19399c7f4e1)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 93f72abeb2756a9f0306904b8a74b0f340a4ecc6)
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 33 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/childobject.qml | 8 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h | 7 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 8 |
4 files changed, 48 insertions, 8 deletions
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index b51fc963f7..ddab42336f 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -84,27 +84,44 @@ void QQmlPropertyData::load(const QMetaMethod &m) { setCoreIndex(m.methodIndex()); setArguments(nullptr); + m_flags.type = Flags::FunctionType; - setPropType(m.returnMetaType()); + // We need to set the constructor, signal, constant, arguments, V4Function, cloned flags. + // These are specific to methods and change with each method. + // The same QQmlPropertyData may be loaded with multiple methods in sequence. - m_flags.type = Flags::FunctionType; - if (m.methodType() == QMetaMethod::Signal) { + switch (m.methodType()) { + case QMetaMethod::Signal: m_flags.setIsSignal(true); - } else if (m.methodType() == QMetaMethod::Constructor) { + m_flags.setIsConstructor(false); + setPropType(m.returnMetaType()); + break; + case QMetaMethod::Constructor: + m_flags.setIsSignal(false); m_flags.setIsConstructor(true); setPropType(QMetaType::fromType<QObject *>()); + break; + default: + m_flags.setIsSignal(false); + m_flags.setIsConstructor(false); + setPropType(m.returnMetaType()); + break; } + m_flags.setIsConstant(m.isConst()); const int paramCount = m.parameterCount(); if (paramCount) { m_flags.setHasArguments(true); - if ((paramCount == 1) && (m.parameterMetaType(0) == QMetaType::fromType<QQmlV4Function *>())) - m_flags.setIsV4Function(true); + m_flags.setIsV4Function( + paramCount == 1 && + m.parameterMetaType(0) == QMetaType::fromType<QQmlV4Function *>()); + } else { + m_flags.setHasArguments(false); + m_flags.setIsV4Function(false); } - if (m.attributes() & QMetaMethod::Cloned) - m_flags.setIsCloned(true); + m_flags.setIsCloned(m.attributes() & QMetaMethod::Cloned); Q_ASSERT(m.revision() <= std::numeric_limits<quint16>::max()); setRevision(QTypeRevision::fromEncodedVersion(m.revision())); diff --git a/tests/auto/qml/qmlcppcodegen/data/childobject.qml b/tests/auto/qml/qmlcppcodegen/data/childobject.qml index db6b910ec2..76ad8fbbb2 100644 --- a/tests/auto/qml/qmlcppcodegen/data/childobject.qml +++ b/tests/auto/qml/qmlcppcodegen/data/childobject.qml @@ -8,6 +8,14 @@ QtObject { function doString() { overloaded("string"); } function doNumber() { overloaded(5.2); } function doArray() { overloaded({a: 2, b: 3, c: 3}); } + + function doString2() { overloaded2("string"); } + function doNumber2() { overloaded2(5.2); } + + // Artificially pass an extra argument to avoid choosing the "string" overload. + // Unfortunately this is still order-dependent on the metaobject level. + function doArray2() { overloaded2({a: 2, b: 3, c: 3}, 1); } + function doFoo() { foo(this); } } objectName: child.objectName diff --git a/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h b/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h index ee01d2a0d2..9d706ff9ac 100644 --- a/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h +++ b/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h @@ -29,12 +29,19 @@ public: QProperty<int> theThing; QBindable<int> theThingBindable() { return QBindable<int>(&theThing); } + // The meta methods are populated back to front. + // The V4Function flag should not bleed into the others in either case. + Q_INVOKABLE void overloaded(QQmlV4Function *) { setObjectName(QStringLiteral("javaScript")); } Q_INVOKABLE void overloaded(double) { setObjectName(QStringLiteral("double")); } Q_INVOKABLE void overloaded(const QString &) { setObjectName(QStringLiteral("string")); } Q_INVOKABLE void foo(const QString &bla) { setObjectName(bla); } Q_INVOKABLE void foo(ObjectWithMethod *) { setObjectName(QStringLiteral("ObjectWithMethod")); } + + Q_INVOKABLE void overloaded2(double) { setObjectName(QStringLiteral("double")); } + Q_INVOKABLE void overloaded2(const QString &) { setObjectName(QStringLiteral("string")); } + Q_INVOKABLE void overloaded2(QQmlV4Function *) { setObjectName(QStringLiteral("javaScript")); } }; class OverriddenObjectName : public ObjectWithMethod diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index cc8e6a81c5..beaf88cb3f 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -3321,6 +3321,14 @@ void tst_QmlCppCodegen::overriddenProperty() QCOMPARE(child->objectName(), u"double"_s); QMetaObject::invokeMethod(child, "doArray"); QCOMPARE(child->objectName(), u"javaScript"_s); + + QMetaObject::invokeMethod(child, "doString2"); + QCOMPARE(child->objectName(), u"string"_s); + QMetaObject::invokeMethod(child, "doNumber2"); + QCOMPARE(child->objectName(), u"double"_s); + QMetaObject::invokeMethod(child, "doArray2"); + QCOMPARE(child->objectName(), u"javaScript"_s); + QMetaObject::invokeMethod(child, "doFoo"); QCOMPARE(child->objectName(), u"ObjectWithMethod"_s); |