diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 84e7a65a54..af99546f04 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -84,6 +84,10 @@ class QString; #define Q_OVERRIDE(text) #define Q_ENUMS(x) #define Q_FLAGS(x) +#define Q_ENUM(ENUM) \ + friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) Q_DECL_NOEXCEPT { return &staticMetaObject; } \ + friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) Q_DECL_NOEXCEPT { return #ENUM; } +#define Q_FLAG(ENUM) Q_ENUM(ENUM) #define Q_SCRIPTABLE #define Q_INVOKABLE #define Q_SIGNAL @@ -185,6 +189,8 @@ private: \ #define Q_REVISION(v) Q_REVISION(v) #define Q_OVERRIDE(text) Q_OVERRIDE(text) #define Q_ENUMS(x) Q_ENUMS(x) +#define Q_FLAGS(x) Q_FLAGS(x) +#define Q_ENUM(x) Q_ENUM(x) #define Q_FLAGS(x) Q_FLAGS(x) /* qmake ignore Q_OBJECT */ #define Q_OBJECT Q_OBJECT diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp index bb4f2883cb..5bee666c8d 100644 --- a/src/tools/moc/keywords.cpp +++ b/src/tools/moc/keywords.cpp @@ -840,12 +840,12 @@ static const struct {CHARACTER, 0, 78, 393, CHARACTER}, {CHARACTER, 0, 85, 394, CHARACTER}, {CHARACTER, 0, 77, 395, CHARACTER}, - {CHARACTER, 0, 83, 396, CHARACTER}, + {Q_ENUM_TOKEN, 0, 83, 396, CHARACTER}, {Q_ENUMS_TOKEN, 0, 0, 0, CHARACTER}, {CHARACTER, 0, 76, 398, CHARACTER}, {CHARACTER, 0, 65, 399, CHARACTER}, {CHARACTER, 0, 71, 400, CHARACTER}, - {CHARACTER, 0, 83, 401, CHARACTER}, + {Q_FLAG_TOKEN, 0, 83, 401, CHARACTER}, {Q_FLAGS_TOKEN, 0, 0, 0, CHARACTER}, {CHARACTER, 0, 69, 403, CHARACTER}, {CHARACTER, 0, 67, 404, CHARACTER}, diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 75349191d4..fe59f430f5 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -696,9 +696,11 @@ void Moc::parse() parsePluginData(&def); break; case Q_ENUMS_TOKEN: + case Q_ENUM_TOKEN: parseEnumOrFlag(&def, false); break; case Q_FLAGS_TOKEN: + case Q_FLAG_TOKEN: parseEnumOrFlag(&def, true); break; case Q_DECLARE_FLAGS_TOKEN: diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h index 57be5b4999..19832e5406 100644 --- a/src/tools/moc/token.h +++ b/src/tools/moc/token.h @@ -162,7 +162,9 @@ QT_BEGIN_NAMESPACE F(Q_PROPERTY_TOKEN) \ F(Q_PLUGIN_METADATA_TOKEN) \ F(Q_ENUMS_TOKEN) \ + F(Q_ENUM_TOKEN) \ F(Q_FLAGS_TOKEN) \ + F(Q_FLAG_TOKEN) \ F(Q_DECLARE_FLAGS_TOKEN) \ F(Q_DECLARE_INTERFACE_TOKEN) \ F(Q_DECLARE_METATYPE_TOKEN) \ diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp index 98800486a3..1d94d1fbdb 100644 --- a/src/tools/moc/util/generate_keywords.cpp +++ b/src/tools/moc/util/generate_keywords.cpp @@ -222,7 +222,9 @@ static const Keyword keywords[] = { { "Q_PROPERTY", "Q_PROPERTY_TOKEN" }, { "Q_PLUGIN_METADATA", "Q_PLUGIN_METADATA_TOKEN" }, { "Q_ENUMS", "Q_ENUMS_TOKEN" }, + { "Q_ENUM", "Q_ENUM_TOKEN" }, { "Q_FLAGS", "Q_FLAGS_TOKEN" }, + { "Q_FLAG", "Q_FLAG_TOKEN" }, { "Q_DECLARE_FLAGS", "Q_DECLARE_FLAGS_TOKEN" }, { "Q_DECLARE_INTERFACE", "Q_DECLARE_INTERFACE_TOKEN" }, { "Q_DECLARE_METATYPE", "Q_DECLARE_METATYPE_TOKEN" }, diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index 8a7e945730..7614c52e66 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -46,15 +46,13 @@ struct MyStruct }; namespace MyNamespace { + // Used in tst_QMetaObject::checkScope class MyClass : public QObject { Q_OBJECT Q_PROPERTY(MyEnum myEnum READ myEnum WRITE setMyEnum) Q_PROPERTY(MyFlags myFlags READ myFlags WRITE setMyFlags) - Q_ENUMS(MyEnum) - Q_ENUMS(MyAnotherEnum) - Q_FLAGS(MyFlags) public: enum MyEnum { MyEnum1, @@ -85,17 +83,65 @@ namespace MyNamespace { m_flags(MyFlag1|MyFlag2) { } private: + Q_ENUM(MyEnum) + Q_ENUM(MyAnotherEnum) + Q_FLAG(MyFlags) + MyEnum m_enum; MyFlags m_flags; }; Q_DECLARE_OPERATORS_FOR_FLAGS(MyClass::MyFlags) + + + // test the old Q_ENUMS macro + class MyClass2 : public QObject + { + Q_OBJECT + Q_PROPERTY(MyEnum myEnum READ myEnum WRITE setMyEnum) + Q_PROPERTY(MyFlags myFlags READ myFlags WRITE setMyFlags) + + public: + enum MyEnum { + MyEnum1, + MyEnum2, + MyEnum3 + }; + enum MyAnotherEnum { + MyAnotherEnum1 = 1, + MyAnotherEnum2 = 2, + MyAnotherEnum3 = -1 + }; + enum MyFlag { + MyFlag1 = 0x01, + MyFlag2 = 0x02, + MyFlag3 = 0x04 + }; + Q_DECLARE_FLAGS(MyFlags, MyFlag) + + MyEnum myEnum() const { return m_enum; } + void setMyEnum(MyEnum val) { m_enum = val; } + + MyFlags myFlags() const { return m_flags; } + void setMyFlags(MyFlags val) { m_flags = val; } + + MyClass2(QObject *parent = 0) + : QObject(parent), + m_enum(MyEnum1), + m_flags(MyFlag1|MyFlag2) + { } + private: + Q_ENUMS(MyEnum MyAnotherEnum) + Q_FLAGS(MyFlags) + + MyEnum m_enum; + MyFlags m_flags; + }; } class tst_QMetaObject : public QObject { Q_OBJECT - Q_ENUMS(EnumType) Q_PROPERTY(EnumType value WRITE setValue READ getValue) Q_PROPERTY(EnumType value2 WRITE set_value READ get_value) Q_PROPERTY(MyStruct value3 WRITE setVal3 READ val3) @@ -109,6 +155,7 @@ class tst_QMetaObject : public QObject public: enum EnumType { EnumType1 }; + Q_ENUM(EnumType); void setValue(EnumType) {} EnumType getValue() const { return EnumType1; } @@ -154,6 +201,7 @@ private slots: void normalizedType_data(); void normalizedType(); void customPropertyType(); + void checkScope_data(); void checkScope(); void propertyNotify(); void propertyConstant(); @@ -990,19 +1038,35 @@ void tst_QMetaObject::customPropertyType() QCOMPARE(prop.type(), QVariant::List); } +void tst_QMetaObject::checkScope_data() +{ + QTest::addColumn("object"); + QTest::addColumn("name"); + + static MyNamespace::MyClass obj1; + static MyNamespace::MyClass2 obj2; + + QTest::newRow("MyClass") << static_cast(&obj1) << QByteArray("MyClass"); + QTest::newRow("MyClass2") << static_cast(&obj2) << QByteArray("MyClass2"); + +} + + void tst_QMetaObject::checkScope() { - MyNamespace::MyClass obj; + QFETCH(QObject *, object); + QFETCH(QByteArray, name); + QObject &obj = *object; bool ok; const QMetaObject *mo = obj.metaObject(); QMetaEnum me = mo->enumerator(mo->indexOfEnumerator("MyEnum")); QVERIFY(me.isValid()); QVERIFY(!me.isFlag()); - QCOMPARE(QLatin1String(me.scope()), QLatin1String("MyNamespace::MyClass")); - QCOMPARE(me.keyToValue("MyNamespace::MyClass::MyEnum2", &ok), 1); + QCOMPARE(QByteArray(me.scope()), QByteArray("MyNamespace::" + name)); + QCOMPARE(me.keyToValue("MyNamespace::" + name + "::MyEnum2", &ok), 1); QCOMPARE(ok, true); - QCOMPARE(me.keyToValue("MyClass::MyEnum2", &ok), -1); + QCOMPARE(me.keyToValue(name + "::MyEnum2", &ok), -1); QCOMPARE(ok, false); QCOMPARE(me.keyToValue("MyNamespace::MyEnum2", &ok), -1); QCOMPARE(ok, false); @@ -1027,10 +1091,10 @@ void tst_QMetaObject::checkScope() QMetaEnum mf = mo->enumerator(mo->indexOfEnumerator("MyFlags")); QVERIFY(mf.isValid()); QVERIFY(mf.isFlag()); - QCOMPARE(QLatin1String(mf.scope()), QLatin1String("MyNamespace::MyClass")); - QCOMPARE(mf.keysToValue("MyNamespace::MyClass::MyFlag2", &ok), 2); + QCOMPARE(QByteArray(mf.scope()), QByteArray("MyNamespace::" + name)); + QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag2", &ok), 2); QCOMPARE(ok, true); - QCOMPARE(mf.keysToValue("MyClass::MyFlag2", &ok), -1); + QCOMPARE(mf.keysToValue(name + "::MyFlag2", &ok), -1); QCOMPARE(ok, false); QCOMPARE(mf.keysToValue("MyNamespace::MyFlag2", &ok), -1); QCOMPARE(ok, false); @@ -1039,9 +1103,9 @@ void tst_QMetaObject::checkScope() QCOMPARE(mf.keysToValue("MyFlag", &ok), -1); QCOMPARE(ok, false); QCOMPARE(QLatin1String(mf.valueToKey(2)), QLatin1String("MyFlag2")); - QCOMPARE(mf.keysToValue("MyNamespace::MyClass::MyFlag1|MyNamespace::MyClass::MyFlag2", &ok), 3); + QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag1|MyNamespace::" + name + "::MyFlag2", &ok), 3); QCOMPARE(ok, true); - QCOMPARE(mf.keysToValue("MyClass::MyFlag1|MyClass::MyFlag2", &ok), -1); + QCOMPARE(mf.keysToValue(name + "::MyFlag1|" + name + "::MyFlag2", &ok), -1); QCOMPARE(ok, false); QCOMPARE(mf.keysToValue("MyNamespace::MyFlag1|MyNamespace::MyFlag2", &ok), -1); QCOMPARE(ok, false); @@ -1049,9 +1113,9 @@ void tst_QMetaObject::checkScope() QCOMPARE(ok, true); QCOMPARE(mf.keysToValue("MyFlag2|MyFlag2", &ok), 2); QCOMPARE(ok, true); - QCOMPARE(mf.keysToValue("MyFlag1|MyNamespace::MyClass::MyFlag2", &ok), 3); + QCOMPARE(mf.keysToValue("MyFlag1|MyNamespace::" + name + "::MyFlag2", &ok), 3); QCOMPARE(ok, true); - QCOMPARE(mf.keysToValue("MyNamespace::MyClass::MyFlag2|MyNamespace::MyClass::MyFlag2", &ok), 2); + QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag2|MyNamespace::" + name + "::MyFlag2", &ok), 2); QCOMPARE(ok, true); QCOMPARE(QLatin1String(mf.valueToKeys(3)), QLatin1String("MyFlag1|MyFlag2")); } diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 83cdde5aa4..e5891658bb 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -1502,7 +1502,6 @@ typedef QString CustomString; class PropertyObject : public QObject { Q_OBJECT - Q_ENUMS(Alpha Priority) Q_PROPERTY(Alpha alpha READ alpha WRITE setAlpha) Q_PROPERTY(Priority priority READ priority WRITE setPriority) @@ -1564,6 +1563,9 @@ private: float m_float; qreal m_qreal; CustomString m_customString; + + Q_ENUM(Alpha) + Q_ENUM(Priority) }; Q_DECLARE_METATYPE(PropertyObject::Priority) diff --git a/tests/auto/tools/moc/cstyle-enums.h b/tests/auto/tools/moc/cstyle-enums.h index a930fa1117..ce89878e97 100644 --- a/tests/auto/tools/moc/cstyle-enums.h +++ b/tests/auto/tools/moc/cstyle-enums.h @@ -39,8 +39,10 @@ class CStyleEnums { Q_GADGET public: - Q_ENUMS(Baz) typedef enum { Foo, Bar } Baz; + typedef enum { Foo2, Bar2 } Baz2; + Q_ENUM(Baz) + Q_ENUMS(Baz2) }; #endif // CSTYLE_ENUMS_H diff --git a/tests/auto/tools/moc/cxx11-enums.h b/tests/auto/tools/moc/cxx11-enums.h index 21d17d0039..32acb25515 100644 --- a/tests/auto/tools/moc/cxx11-enums.h +++ b/tests/auto/tools/moc/cxx11-enums.h @@ -40,11 +40,26 @@ class CXX11Enums { Q_GADGET public: - Q_ENUMS(EnumClass TypedEnum TypedEnumClass NormalEnum) enum class EnumClass { A0, A1, A2, A3 }; enum TypedEnum : char { B0, B1 , B2, B3 }; enum class TypedEnumClass : char { C0, C1, C2, C3 }; enum NormalEnum { D2 = 2, D3, D0 =0 , D1 }; + Q_ENUM(EnumClass) + Q_ENUM(TypedEnum) + Q_ENUM(TypedEnumClass) + Q_ENUM(NormalEnum) +}; + +// Also test the Q_ENUMS macro +class CXX11Enums2 +{ + Q_GADGET +public: + enum class EnumClass { A0, A1, A2, A3 }; + enum TypedEnum : char { B0, B1 , B2, B3 }; + enum class TypedEnumClass : char { C0, C1, C2, C3 }; + enum NormalEnum { D2 = 2, D3, D0 =0 , D1 }; + Q_ENUMS(EnumClass TypedEnum TypedEnumClass NormalEnum) }; #else @@ -58,5 +73,10 @@ public: enum NormalEnum { D2 = 2, D3, D0 =0 , D1 }; enum TypedEnum { B0, B1 , B2, B3 }; }; + +class CXX11Enums2 : public CXX11Enums +{ + Q_GADGET +}; #endif #endif // CXX11_ENUMS_H diff --git a/tests/auto/tools/moc/gadgetwithnoenums.h b/tests/auto/tools/moc/gadgetwithnoenums.h index a19b970ab9..6a515862de 100644 --- a/tests/auto/tools/moc/gadgetwithnoenums.h +++ b/tests/auto/tools/moc/gadgetwithnoenums.h @@ -47,10 +47,10 @@ public: class DerivedGadgetWithEnums : public GadgetWithNoEnums { Q_GADGET - Q_ENUMS( FooEnum ) public: enum FooEnum { FooValue }; + Q_ENUM( FooEnum ) DerivedGadgetWithEnums() {} ~DerivedGadgetWithEnums() {} }; diff --git a/tests/auto/tools/moc/namespaced-flags.h b/tests/auto/tools/moc/namespaced-flags.h index 2b63ed0ae1..9448176218 100644 --- a/tests/auto/tools/moc/namespaced-flags.h +++ b/tests/auto/tools/moc/namespaced-flags.h @@ -38,13 +38,14 @@ namespace Foo { class Bar : public QObject { Q_OBJECT - Q_FLAGS( Flags ) Q_PROPERTY( Flags flags READ flags WRITE setFlags ) public: explicit Bar( QObject * parent=0 ) : QObject( parent ), mFlags() {} enum Flag { Read=1, Write=2 }; Q_DECLARE_FLAGS( Flags, Flag ) + Q_FLAG(Flags) + void setFlags( Flags f ) { mFlags = f; } Flags flags() const { return mFlags; } diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 8e5de04718..2813da1ef7 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -75,6 +75,9 @@ #include "non-gadget-parent-class.h" #include "grand-parent-gadget-class.h" +Q_DECLARE_METATYPE(const QMetaObject*); + + QT_USE_NAMESPACE template struct QTBUG_31218 {}; @@ -418,7 +421,7 @@ public: enum TestEnum { One, Two, Three }; - Q_ENUMS(TestEnum) + Q_ENUM(TestEnum) }; class PropertyUseClass : public QObject @@ -437,7 +440,7 @@ class EnumSourceClass : public QObject public: enum TestEnum { Value = 37 }; - Q_ENUMS(TestEnum) + Q_ENUM(TestEnum) }; class EnumUserClass : public QObject @@ -1142,12 +1145,18 @@ void tst_Moc::frameworkSearchPath() void tst_Moc::cstyleEnums() { const QMetaObject &obj = CStyleEnums::staticMetaObject; - QCOMPARE(obj.enumeratorCount(), 1); + QCOMPARE(obj.enumeratorCount(), 2); QMetaEnum metaEnum = obj.enumerator(0); QCOMPARE(metaEnum.name(), "Baz"); QCOMPARE(metaEnum.keyCount(), 2); QCOMPARE(metaEnum.key(0), "Foo"); QCOMPARE(metaEnum.key(1), "Bar"); + + QMetaEnum metaEnum2 = obj.enumerator(1); + QCOMPARE(metaEnum2.name(), "Baz2"); + QCOMPARE(metaEnum2.keyCount(), 2); + QCOMPARE(metaEnum2.key(0), "Foo2"); + QCOMPARE(metaEnum2.key(1), "Bar2"); } void tst_Moc::templateGtGt() @@ -1644,7 +1653,6 @@ class VersionTest : public QObject Q_OBJECT Q_PROPERTY(int prop1 READ foo) Q_PROPERTY(int prop2 READ foo REVISION 2) - Q_ENUMS(TestEnum); public: int foo() const { return 0; } @@ -1653,6 +1661,8 @@ public: Q_INVOKABLE Q_REVISION(4) void method2() {} enum TestEnum { One, Two }; + Q_ENUM(TestEnum); + public slots: void slot1() {} @@ -1677,7 +1687,6 @@ class VersionTestNotify : public QObject Q_OBJECT Q_PROPERTY(int prop1 READ foo NOTIFY fooChanged) Q_PROPERTY(int prop2 READ foo REVISION 2) - Q_ENUMS(TestEnum); public: int foo() const { return 0; } @@ -1686,6 +1695,7 @@ public: Q_INVOKABLE Q_REVISION(4) void method2() {} enum TestEnum { One, Two }; + Q_ENUM(TestEnum); public slots: void slot1() {} @@ -1915,19 +1925,26 @@ void tst_Moc::privateClass() void tst_Moc::cxx11Enums_data() { + QTest::addColumn("meta"); QTest::addColumn("enumName"); QTest::addColumn("prefix"); - QTest::newRow("EnumClass") << QByteArray("EnumClass") << 'A'; - QTest::newRow("TypedEnum") << QByteArray("TypedEnum") << 'B'; - QTest::newRow("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C'; - QTest::newRow("NormalEnum") << QByteArray("NormalEnum") << 'D'; -} + const QMetaObject *meta1 = &CXX11Enums::staticMetaObject; + const QMetaObject *meta2 = &CXX11Enums2::staticMetaObject; + QTest::newRow("EnumClass") << meta1 << QByteArray("EnumClass") << 'A'; + QTest::newRow("EnumClass 2") << meta2 << QByteArray("EnumClass") << 'A'; + QTest::newRow("TypedEnum") << meta1 << QByteArray("TypedEnum") << 'B'; + QTest::newRow("TypedEnum 2") << meta2 << QByteArray("TypedEnum") << 'B'; + QTest::newRow("TypedEnumClass") << meta1 << QByteArray("TypedEnumClass") << 'C'; + QTest::newRow("TypedEnumClass 2") << meta2 << QByteArray("TypedEnumClass") << 'C'; + QTest::newRow("NormalEnum") << meta1 << QByteArray("NormalEnum") << 'D'; + QTest::newRow("NormalEnum 2") << meta2 << QByteArray("NormalEnum") << 'D'; +} void tst_Moc::cxx11Enums() { - const QMetaObject *meta = &CXX11Enums::staticMetaObject; + QFETCH(const QMetaObject *,meta); QCOMPARE(meta->enumeratorOffset(), 0); QFETCH(QByteArray, enumName); @@ -2535,8 +2552,6 @@ void tst_Moc::finalClasses() QCOMPARE(className, expected); } -Q_DECLARE_METATYPE(const QMetaObject*); - void tst_Moc::explicitOverrideControl_data() { QTest::addColumn("mo");