From 26a0a8942135fed725ec3067ba05bae31bb4e645 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 22 Apr 2020 08:25:18 +0200 Subject: [PATCH] Fix assigning int QFlag-type properties Ensure they are handled as enumerations in QMetaType. This is required for handling QFlag-type properties in Qt Designer Fixes: QTBUG-83689 Change-Id: Ifbfb5c5b5cd34fce462e299505d063e22e725c2e Reviewed-by: Friedemann Kleint Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qmetatype.h | 13 ++++- .../qmetaproperty/tst_qmetaproperty.cpp | 51 +++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index e956d497e9..eb81ac4c28 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -432,7 +432,16 @@ struct ConverterFunctor : public AbstractConverterFunction struct IsMetaTypePair; template struct MetaTypeSmartPointerHelper; -} + + template + struct IsQFlags : std::false_type {}; + + template + struct IsQFlags> : std::true_type {}; + + template + struct IsEnumOrFlags : std::disjunction, IsQFlags> {}; +} // namespace QtPrivate class Q_CORE_EXPORT QMetaType { public: @@ -1730,7 +1739,7 @@ namespace QtPrivate { | (IsSharedPointerToTypeDerivedFromQObject::Value ? QMetaType::SharedPointerToQObject : 0) | (IsWeakPointerToTypeDerivedFromQObject::Value ? QMetaType::WeakPointerToQObject : 0) | (IsTrackingPointerToTypeDerivedFromQObject::Value ? QMetaType::TrackingPointerToQObject : 0) - | (std::is_enum::value ? QMetaType::IsEnumeration : 0) + | (IsEnumOrFlags::value ? QMetaType::IsEnumeration : 0) | (IsGadgetHelper::IsGadgetOrDerivedFrom ? QMetaType::IsGadget : 0) | (IsPointerToGadgetHelper::IsGadgetOrDerivedFrom ? QMetaType::PointerToGadget : 0) | (QTypeInfo::isPointer ? QMetaType::IsPointer : 0) diff --git a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp index 43ed535019..9bce6a7a28 100644 --- a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp +++ b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp @@ -65,6 +65,7 @@ private slots: void readAndWriteWithLazyRegistration(); void mapProperty(); void conversion(); + void enumsFlags(); public: enum EnumType { EnumType1 }; @@ -181,6 +182,33 @@ public: {} }; +class EnumFlagsTester : public QObject +{ + Q_OBJECT + Q_PROPERTY(TestEnum enumProperty READ enumProperty WRITE setEnumProperty) + Q_PROPERTY(TestFlags flagProperty READ flagProperty WRITE setFlagProperty) +public: + enum TestEnum { e1, e2 }; + Q_ENUM(TestEnum) + + enum TestFlag { flag1 = 0x1, flag2 = 0x2 }; + Q_DECLARE_FLAGS(TestFlags, TestFlag) + + using QObject::QObject; + + TestEnum enumProperty() const { return m_enum; } + void setEnumProperty(TestEnum e) { m_enum = e; } + + TestFlags flagProperty() const { return m_flags; } + void setFlagProperty(TestFlags f) { m_flags = f; } + +private: + TestEnum m_enum = e1; + TestFlags m_flags; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(EnumFlagsTester::TestFlags) + void tst_QMetaProperty::readAndWriteWithLazyRegistration() { QCOMPARE(QMetaType::type("CustomReadObject*"), int(QMetaType::UnknownType)); @@ -246,5 +274,28 @@ void tst_QMetaProperty::conversion() QCOMPARE(value7, QLatin1String("reset")); } +void tst_QMetaProperty::enumsFlags() +{ + // QTBUG-83689, verify that enumerations and flags can be assigned from int, + // which is important for Qt Designer. + EnumFlagsTester t; + + auto mo = t.metaObject(); + + const int enumIndex = mo->indexOfProperty("enumProperty"); + QVERIFY(enumIndex >= 0); + auto enumProperty = mo->property(enumIndex); + QVERIFY(enumProperty.metaType().flags().testFlag(QMetaType::IsEnumeration)); + QVERIFY(enumProperty.write(&t, QVariant(int(EnumFlagsTester::e2)))); + QCOMPARE(t.enumProperty(), EnumFlagsTester::e2); + + const int flagsIndex = mo->indexOfProperty("flagProperty"); + QVERIFY(flagsIndex >= 0); + auto flagsProperty = mo->property(flagsIndex); + QVERIFY(flagsProperty.metaType().flags().testFlag(QMetaType::IsEnumeration)); + QVERIFY(flagsProperty.write(&t, QVariant(int(EnumFlagsTester::flag2)))); + QCOMPARE(t.flagProperty(), EnumFlagsTester::flag2); +} + QTEST_MAIN(tst_QMetaProperty) #include "tst_qmetaproperty.moc"