From: Matthew Vogt Date: Fri, 22 Jun 2012 05:32:46 +0000 (+1000) Subject: Add enum values from related types X-Git-Tag: upstream/5.2.1~1567 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a93c2608d69fa385c675a6b49e4d4bfb97f83ed2;p=platform%2Fupstream%2Fqtdeclarative.git Add enum values from related types If moc marks a type as being related to another type (by using that type's enums or properties), then include the enum values exported by the related type in those exposed by the dependent type. Task-number: QTBUG-22675 Change-Id: I78e72791a4f470200a9ba986a865ffac6c873725 Reviewed-by: Chris Adams --- diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp index 13ff9e8..fd42ab8 100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@ -2536,7 +2536,7 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop, return true; int value = 0; - bool ok; + bool ok = false; if (type && toQmlType(obj) == type) { // When these two match, we can short cut the search @@ -2547,13 +2547,15 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop, } } else { // Otherwise we have to search the whole type - // This matches the logic in QV8TypeWrapper - QByteArray enumName = enumValue.toUtf8(); - const QMetaObject *metaObject = type ? type->baseMetaObject() : StaticQtMetaObject::get(); - ok = false; - for (int ii = metaObject->enumeratorCount() - 1; !ok && ii >= 0; --ii) { - QMetaEnum e = metaObject->enumerator(ii); - value = e.keyToValue(enumName.constData(), &ok); + if (type) { + value = type->enumValue(QHashedStringRef(enumValue), &ok); + } else { + QByteArray enumName = enumValue.toUtf8(); + const QMetaObject *metaObject = StaticQtMetaObject::get(); + for (int ii = metaObject->enumeratorCount() - 1; !ok && ii >= 0; --ii) { + QMetaEnum e = metaObject->enumerator(ii); + value = e.keyToValue(enumName.constData(), &ok); + } } } @@ -2572,14 +2574,14 @@ int QQmlCompiler::evaluateEnum(const QHashedStringRef &scope, const QByteArray& { Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer"); *ok = false; - QQmlType *type = 0; + if (scope != QLatin1String("Qt")) { + QQmlType *type = 0; unit->imports().resolveType(scope, &type, 0, 0, 0, 0); - if (!type) - return -1; - + return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1; } - const QMetaObject *mo = type ? type->metaObject() : StaticQtMetaObject::get(); + + const QMetaObject *mo = StaticQtMetaObject::get(); int i = mo->enumeratorCount(); while (i--) { int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok); diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 80fb3ed..34c9cce 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -153,6 +153,7 @@ public: void init() const; void initEnums() const; + void insertEnums(const QMetaObject *metaObject) const; bool m_isInterface : 1; const char *m_iid; @@ -487,16 +488,28 @@ void QQmlTypePrivate::initEnums() const QWriteLocker lock(metaTypeDataLock()); if (m_isEnumSetup) return; - const QMetaObject *metaObject = m_baseMetaObject; - for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) { + insertEnums(m_baseMetaObject); - QMetaEnum e = metaObject->enumerator(ii); + m_isEnumSetup = true; +} - for (int jj = 0; jj < e.keyCount(); ++jj) - m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj)); +void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const +{ + // Add any enum values defined by 'related' classes + if (metaObject->d.relatedMetaObjects) { + const QMetaObject **related = metaObject->d.relatedMetaObjects; + if (related) { + while (*related) + insertEnums(*related++); + } } - m_isEnumSetup = true; + // Add any enum values defined by this class, overwriting any inherited values + for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) { + QMetaEnum e = metaObject->enumerator(ii); + for (int jj = 0; jj < e.keyCount(); ++jj) + m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj)); + } } QByteArray QQmlType::typeName() const @@ -671,20 +684,49 @@ int QQmlType::index() const return d->m_index; } -int QQmlType::enumValue(const QHashedStringRef &name) const +int QQmlType::enumValue(const QHashedStringRef &name, bool *ok) const { + Q_ASSERT(ok); + *ok = true; + d->initEnums(); int *rv = d->m_enums.value(name); - return rv?*rv:-1; + if (rv) + return *rv; + + *ok = false; + return -1; } -int QQmlType::enumValue(const QHashedV8String &name) const +int QQmlType::enumValue(const QHashedCStringRef &name, bool *ok) const { + Q_ASSERT(ok); + *ok = true; + d->initEnums(); int *rv = d->m_enums.value(name); - return rv?*rv:-1; + if (rv) + return *rv; + + *ok = false; + return -1; +} + +int QQmlType::enumValue(const QHashedV8String &name, bool *ok) const +{ + Q_ASSERT(ok); + *ok = true; + + d->initEnums(); + + int *rv = d->m_enums.value(name); + if (rv) + return *rv; + + *ok = false; + return -1; } QQmlTypeModule::QQmlTypeModule() diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index fbbc410..fbba733 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -143,6 +143,7 @@ private: static CompareFunction anchorLineCompareFunction; }; +class QHashedCStringRef; class QHashedV8String; class Q_QML_PRIVATE_EXPORT QQmlType { @@ -191,8 +192,9 @@ public: int index() const; - int enumValue(const QHashedStringRef &) const; - int enumValue(const QHashedV8String &) const; + int enumValue(const QHashedStringRef &, bool *ok) const; + int enumValue(const QHashedCStringRef &, bool *ok) const; + int enumValue(const QHashedV8String &, bool *ok) const; private: QQmlType *superType() const; friend class QQmlTypePrivate; diff --git a/src/qml/qml/v8/qv8typewrapper.cpp b/src/qml/qml/v8/qv8typewrapper.cpp index dbf369e..ff7e599 100644 --- a/src/qml/qml/v8/qv8typewrapper.cpp +++ b/src/qml/qml/v8/qv8typewrapper.cpp @@ -173,8 +173,9 @@ v8::Handle QV8TypeWrapper::Getter(v8::Local property, QQmlType *type = resource->type; if (QV8Engine::startsWithUpper(property)) { - int value = type->enumValue(propertystring); - if (-1 != value) + bool ok = false; + int value = type->enumValue(propertystring, &ok); + if (ok) return v8::Integer::New(value); // Fall through to return empty handle diff --git a/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.2.qml b/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.2.qml index 2c79729..ff6d731 100644 --- a/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.2.qml +++ b/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.2.qml @@ -3,6 +3,7 @@ import Qt.test 1.0 MyTypeObject { flagProperty: if(1) "FlagVal1 | FlagVal3" enumProperty: if(1) "EnumVal2" + relatedEnumProperty: if(1) "RelatedValue" stringProperty: if(1) "Hello World!" uintProperty: if(1) 10 intProperty: if(1) -19 diff --git a/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.qml b/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.qml index 86ff6b6..ce3511f 100644 --- a/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.qml +++ b/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.qml @@ -5,6 +5,7 @@ MyTypeObject { Component.onCompleted: { flagProperty = "FlagVal1 | FlagVal3" enumProperty = "EnumVal2" + relatedEnumProperty = "RelatedValue" stringProperty = "Hello World!" uintProperty = 10 intProperty = -19 diff --git a/tests/auto/qml/qqmlecmascript/data/enums.1.qml b/tests/auto/qml/qqmlecmascript/data/enums.1.qml index 6351823..b9295c5 100644 --- a/tests/auto/qml/qqmlecmascript/data/enums.1.qml +++ b/tests/auto/qml/qqmlecmascript/data/enums.1.qml @@ -2,6 +2,18 @@ import Qt.test 1.0 import Qt.test 1.0 as Namespace MyQmlObject { + // Enum property type + enumProperty: MyQmlObject.EnumValue2 + + // Enum property whose value is from a related type + relatedEnumProperty: MyQmlObject.RelatedValue + + // Enum property whose value is defined in an unrelated type + unrelatedEnumProperty: MyTypeObject.RelatedValue + + // Enum property whose value is defined in the Qt namespace + qtEnumProperty: Qt.CaseInsensitive + // Enums from non-namespaced type property int a: MyQmlObject.EnumValue1 property int b: MyQmlObject.EnumValue2 @@ -17,4 +29,10 @@ MyQmlObject { // Test that enums don't mask attached properties property int i: MyQmlObject.value property int j: Namespace.MyQmlObject.value + + // Enums from a related type + property int k: MyQmlObject.RelatedValue + + // Enum values defined both in a type and a related type + property int l: MyQmlObject.MultiplyDefined } diff --git a/tests/auto/qml/qqmlecmascript/data/enums.3.qml b/tests/auto/qml/qqmlecmascript/data/enums.3.qml index fd3432f..aaa6a33 100644 --- a/tests/auto/qml/qqmlecmascript/data/enums.3.qml +++ b/tests/auto/qml/qqmlecmascript/data/enums.3.qml @@ -22,6 +22,9 @@ Item { // -1 enum property int j: MyQmlObject.EnumValue5 + // Enums from a related type + property int k: MyQmlObject.RelatedValue + // Count the onChanged signals to see whether // they're assigned as literals or via bindings property int ac: 0 @@ -33,6 +36,7 @@ Item { property int hc: 0 property int ic: 0 property int jc: 0 + property int kc: 0 onAChanged: ac++ onBChanged: bc++ @@ -43,4 +47,5 @@ Item { onHChanged: hc++ onIChanged: ic++ onJChanged: jc++ + onKChanged: kc++ } diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index ab44d59..06e54ea 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -86,11 +86,22 @@ private: int m_value2; }; +class MyEnumContainer : public QObject +{ + Q_OBJECT + Q_ENUMS(RelatedEnum) + +public: + enum RelatedEnum { RelatedInvalid = -1, RelatedValue = 42, MultiplyDefined = 666 }; +}; + class MyQmlObject : public QObject { Q_OBJECT Q_ENUMS(MyEnum) Q_ENUMS(MyEnum2) + Q_ENUMS(MyEnum3) + Q_ENUMS(MyEnumContainer::RelatedEnum) Q_PROPERTY(int deleteOnSet READ deleteOnSet WRITE setDeleteOnSet) Q_PROPERTY(bool trueProperty READ trueProperty CONSTANT) Q_PROPERTY(bool falseProperty READ falseProperty CONSTANT) @@ -106,12 +117,17 @@ class MyQmlObject : public QObject Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty NOTIFY intChanged) Q_PROPERTY(QJSValue qjsvalue READ qjsvalue WRITE setQJSValue NOTIFY qjsvalueChanged) Q_PROPERTY(QJSValue qjsvalueWithReset READ qjsvalue WRITE setQJSValue RESET resetQJSValue NOTIFY qjsvalueChanged) + Q_PROPERTY(MyEnum enumProperty READ enumProperty WRITE setEnumProperty) + Q_PROPERTY(MyEnumContainer::RelatedEnum relatedEnumProperty READ relatedEnumProperty WRITE setRelatedEnumProperty) + Q_PROPERTY(MyEnumContainer::RelatedEnum unrelatedEnumProperty READ unrelatedEnumProperty WRITE setUnrelatedEnumProperty) + Q_PROPERTY(MyEnum qtEnumProperty READ qtEnumProperty WRITE setQtEnumProperty) public: MyQmlObject(): myinvokableObject(0), m_methodCalled(false), m_methodIntCalled(false), m_object(0), m_value(0), m_resetProperty(13), m_intProperty(0), m_buttons(0) {} enum MyEnum { EnumValue1 = 0, EnumValue2 = 1 }; enum MyEnum2 { EnumValue3 = 2, EnumValue4 = 3, EnumValue5 = -1 }; + enum MyEnum3 { MultiplyDefined = 333 }; bool trueProperty() const { return true; } bool falseProperty() const { return false; } @@ -189,6 +205,38 @@ public: Q_INVOKABLE MyEnum2 getEnumValue() const { return EnumValue4; } + MyEnum enumPropertyValue; + MyEnum enumProperty() const { + return enumPropertyValue; + } + void setEnumProperty(MyEnum v) { + enumPropertyValue = v; + } + + MyEnumContainer::RelatedEnum relatedEnumPropertyValue; + MyEnumContainer::RelatedEnum relatedEnumProperty() const { + return relatedEnumPropertyValue; + } + void setRelatedEnumProperty(MyEnumContainer::RelatedEnum v) { + relatedEnumPropertyValue = v; + } + + MyEnumContainer::RelatedEnum unrelatedEnumPropertyValue; + MyEnumContainer::RelatedEnum unrelatedEnumProperty() const { + return unrelatedEnumPropertyValue; + } + void setUnrelatedEnumProperty(MyEnumContainer::RelatedEnum v) { + unrelatedEnumPropertyValue = v; + } + + MyEnum qtEnumPropertyValue; + MyEnum qtEnumProperty() const { + return qtEnumPropertyValue; + } + void setQtEnumProperty(MyEnum v) { + qtEnumPropertyValue = v; + } + signals: void basicSignal(); void argumentSignal(int a, QString b, qreal c, MyEnum2 d, Qt::MouseButtons e); @@ -354,6 +402,7 @@ class MyTypeObject : public QObject { Q_OBJECT Q_ENUMS(MyEnum) + Q_ENUMS(MyEnumContainer::RelatedEnum) Q_FLAGS(MyFlags) Q_PROPERTY(QString id READ id WRITE setId) @@ -361,6 +410,7 @@ class MyTypeObject : public QObject Q_PROPERTY(QQmlComponent *componentProperty READ componentProperty WRITE setComponentProperty) Q_PROPERTY(MyFlags flagProperty READ flagProperty WRITE setFlagProperty) Q_PROPERTY(MyEnum enumProperty READ enumProperty WRITE setEnumProperty) + Q_PROPERTY(MyEnumContainer::RelatedEnum relatedEnumProperty READ relatedEnumProperty WRITE setRelatedEnumProperty) Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty) Q_PROPERTY(uint uintProperty READ uintProperty WRITE setUintProperty) Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty) @@ -433,6 +483,14 @@ public: enumPropertyValue = v; } + MyEnumContainer::RelatedEnum relatedEnumPropertyValue; + MyEnumContainer::RelatedEnum relatedEnumProperty() const { + return relatedEnumPropertyValue; + } + void setRelatedEnumProperty(MyEnumContainer::RelatedEnum v) { + relatedEnumPropertyValue = v; + } + QString stringPropertyValue; QString stringProperty() const { return stringPropertyValue; diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index c429ffa..e2f818c 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -295,6 +295,7 @@ void tst_qqmlecmascript::assignBasicTypes() QVERIFY(object != 0); QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3); QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2); + QCOMPARE(object->relatedEnumProperty(), MyEnumContainer::RelatedValue); QCOMPARE(object->stringProperty(), QString("Hello World!")); QCOMPARE(object->uintProperty(), uint(10)); QCOMPARE(object->intProperty(), -19); @@ -323,6 +324,7 @@ void tst_qqmlecmascript::assignBasicTypes() QVERIFY(object != 0); QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3); QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2); + QCOMPARE(object->relatedEnumProperty(), MyEnumContainer::RelatedValue); QCOMPARE(object->stringProperty(), QString("Hello World!")); QCOMPARE(object->uintProperty(), uint(10)); QCOMPARE(object->intProperty(), -19); @@ -910,6 +912,10 @@ void tst_qqmlecmascript::enums() QObject *object = component.create(); QVERIFY(object != 0); + QCOMPARE(object->property("enumProperty").toInt(), (int)MyQmlObject::EnumValue2); + QCOMPARE(object->property("relatedEnumProperty").toInt(), (int)MyEnumContainer::RelatedValue); + QCOMPARE(object->property("unrelatedEnumProperty").toInt(), (int)MyEnumContainer::RelatedValue); + QCOMPARE(object->property("qtEnumProperty").toInt(), (int)Qt::CaseInsensitive); QCOMPARE(object->property("a").toInt(), 0); QCOMPARE(object->property("b").toInt(), 1); QCOMPARE(object->property("c").toInt(), 2); @@ -920,6 +926,8 @@ void tst_qqmlecmascript::enums() QCOMPARE(object->property("h").toInt(), 3); QCOMPARE(object->property("i").toInt(), 19); QCOMPARE(object->property("j").toInt(), 19); + QCOMPARE(object->property("k").toInt(), 42); + QCOMPARE(object->property("l").toInt(), 333); delete object; } @@ -984,6 +992,7 @@ void tst_qqmlecmascript::enums() QCOMPARE(object->property("h").toInt(), 2); QCOMPARE(object->property("i").toInt(), 3); QCOMPARE(object->property("j").toInt(), -1); + QCOMPARE(object->property("k").toInt(), 42); // count of change signals QCOMPARE(object->property("ac").toInt(), 0); @@ -995,6 +1004,7 @@ void tst_qqmlecmascript::enums() QCOMPARE(object->property("hc").toInt(), 1); // namespace -> binding QCOMPARE(object->property("ic").toInt(), 1); // namespace -> binding QCOMPARE(object->property("jc").toInt(), 0); + QCOMPARE(object->property("kc").toInt(), 0); delete object; } diff --git a/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml b/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml index 697278e..4d54bc8 100644 --- a/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml +++ b/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml @@ -1,9 +1,12 @@ import Test 1.0 +import QtQuick 2.0 + MyTypeObject { flagProperty: "FlagVal1 | FlagVal3" enumProperty: "EnumVal2" qtEnumProperty: Qt.RichText mirroredEnumProperty: Qt.AlignHCenter + relatedEnumProperty: "RelatedValue" stringProperty: "Hello World!" uintProperty: 10 intProperty: -19 diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index 50b6089..01f26c7 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -205,11 +205,21 @@ private: }; +class MyEnumContainer : public QObject +{ + Q_OBJECT + Q_ENUMS(RelatedEnum) + +public: + enum RelatedEnum { RelatedInvalid = -1, RelatedValue = 42 }; +}; + class MyTypeObject : public QObject { Q_OBJECT Q_ENUMS(MyEnum) Q_ENUMS(MyMirroredEnum) + Q_ENUMS(MyEnumContainer::RelatedEnum) Q_FLAGS(MyFlags) Q_PROPERTY(QString id READ id WRITE setId) @@ -220,6 +230,7 @@ class MyTypeObject : public QObject Q_PROPERTY(MyEnum readOnlyEnumProperty READ readOnlyEnumProperty) Q_PROPERTY(Qt::TextFormat qtEnumProperty READ qtEnumProperty WRITE setQtEnumProperty NOTIFY qtEnumPropertyChanged) Q_PROPERTY(MyMirroredEnum mirroredEnumProperty READ mirroredEnumProperty WRITE setMirroredEnumProperty NOTIFY mirroredEnumPropertyChanged) + Q_PROPERTY(MyEnumContainer::RelatedEnum relatedEnumProperty READ relatedEnumProperty WRITE setRelatedEnumProperty) Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty NOTIFY stringPropertyChanged) Q_PROPERTY(uint uintProperty READ uintProperty WRITE setUintProperty NOTIFY uintPropertyChanged) Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty NOTIFY intPropertyChanged) @@ -323,6 +334,14 @@ public: emit mirroredEnumPropertyChanged(); } + MyEnumContainer::RelatedEnum relatedEnumPropertyValue; + MyEnumContainer::RelatedEnum relatedEnumProperty() const { + return relatedEnumPropertyValue; + } + void setRelatedEnumProperty(MyEnumContainer::RelatedEnum v) { + relatedEnumPropertyValue = v; + } + QString stringPropertyValue; QString stringProperty() const { return stringPropertyValue; diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 2f2f0a7..ed94eff 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -587,6 +587,7 @@ void tst_qqmllanguage::assignBasicTypes() QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2); QCOMPARE(object->qtEnumProperty(), Qt::RichText); QCOMPARE(object->mirroredEnumProperty(), MyTypeObject::MirroredEnumVal3); + QCOMPARE(object->relatedEnumProperty(), MyEnumContainer::RelatedValue); QCOMPARE(object->stringProperty(), QString("Hello World!")); QCOMPARE(object->uintProperty(), uint(10)); QCOMPARE(object->intProperty(), -19);