From d61a15d043e70d79f5b27f04e85595a36014a734 Mon Sep 17 00:00:00 2001 From: Phil Thompson Date: Wed, 23 Oct 2024 16:28:27 +0100 Subject: [PATCH] Fix QFlag properties built by QMetaObjectBuilder When Q_PROPERTY is used to define a property with type (for example) Qt::Alignment the name of the type stored in the meta-object is "Qt::Alignment". When QMetaObjectBuilder.addProperty() is used it will instead use the name of the meta-type (ie. "QFlags") which it has obtained from QMetaType::fromName("Qt::Alignment").name(). In the QMetaProperty ctor it tries to resolve the QMetaEnum for the property and uses the internal parse_scope() to extract the scope and qualified key from the name. However it does not handle template names and so fails with dynamically created properties. This change to parse_scope() removes the "QFlags<>" so that the template type can then be parsed. Another solution would be for addProperty() to always use the type name it was given rather than use QMetaType::fromName(). That has the advantage that the layout of the dynamic meta-object would match that generated by moc. Change-Id: Iac9e2db2f134029709158b4e500286922396501d Reviewed-by: Thiago Macieira (cherry picked from commit 5624060865e3ccd3c487f10355cb740b7322f93c) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qmetaobject.cpp | 2 ++ .../kernel/qmetaproperty/tst_qmetaproperty.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 3d0cfb4b33d..f375a7b8a96 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -163,6 +163,8 @@ static auto parse_scope(QByteArrayView qualifiedKey) noexcept std::optional scope; QByteArrayView key; }; + if (qualifiedKey.startsWith("QFlags<") && qualifiedKey.endsWith('>')) + qualifiedKey.slice(7, qualifiedKey.length() - 8); const auto scopePos = qualifiedKey.lastIndexOf("::"_L1); if (scopePos < 0) return R{std::nullopt, qualifiedKey}; diff --git a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp index 3bf6211a539..5b3792bcb8d 100644 --- a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp +++ b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp @@ -41,6 +41,7 @@ class tst_QMetaProperty : public Base Q_PROPERTY(QMap map MEMBER map) Q_PROPERTY(CustomType custom MEMBER custom) Q_PROPERTY(int propWithInheritedSig READ propWithInheritedSig NOTIFY baseSignal) + Q_PROPERTY(QFlags qflags_value MEMBER qflags_value) private slots: void hasStdCppSet(); @@ -52,6 +53,7 @@ private slots: void conversion(); void enumsFlags(); void notifySignalIndex(); + void qflags(); public: enum EnumType { EnumType1 }; @@ -71,6 +73,7 @@ public: QString value7; QMap map; CustomType custom; + QFlags qflags_value; }; void tst_QMetaProperty::hasStdCppSet() @@ -112,6 +115,16 @@ void tst_QMetaProperty::isFinal() QVERIFY(!prop.isFinal()); } +void tst_QMetaProperty::qflags() +{ + const QMetaObject *mo = metaObject(); + + QMetaProperty prop = mo->property(mo->indexOfProperty("qflags_value")); + QVERIFY(prop.isEnumType()); + QVERIFY(prop.isFlagType()); +} + + class MyGadget { Q_GADGET Q_PROPERTY(QString value READ getValue WRITE setValue RESET resetValue)