From 4c9d326230a2c522bc8fd80eee9664c7d0c1205f Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Thu, 15 Mar 2012 17:09:13 +1000 Subject: [PATCH] Allow literal enum to int property assignments Previously, enum to int property assignments were considered bindings. This commit adds support for assigning enum values to int properties as enums. Note that to use an enum in QML, it must have been declared with Q_ENUMS or otherwise registered as a metatype. Enum values from the global Qt object are also usable. Task-number: QTBUG-23403 Change-Id: I50db6cae54a24400ea472bde43619d547e4ceb78 Reviewed-by: Michael Brasser --- src/qml/qml/qqmlcompiler.cpp | 18 ++++++-- .../auto/qml/qqmlecmascript/data/enums.3.qml | 41 +++++++++++++++++++ .../qml/qqmlecmascript/tst_qqmlecmascript.cpp | 28 +++++++++++++ 3 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 tests/auto/qml/qqmlecmascript/data/enums.3.qml diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp index 9304a75fbf..fe0cc7a95c 100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@ -2227,7 +2227,7 @@ bool QQmlCompiler::buildValueTypeProperty(QObject *type, //optimization for . enum assignments bool isEnumAssignment = false; - if (prop->core.isEnum()) + if (prop->core.isEnum() || prop->core.propType == QMetaType::Int) COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, value, &isEnumAssignment)); if (isEnumAssignment) { @@ -2495,7 +2495,7 @@ bool QQmlCompiler::buildPropertyLiteralAssignment(QQmlScript::Property *prop, if (v->value.isScript()) { //optimization for . enum assignments - if (prop->core.isEnum()) { + if (prop->core.isEnum() || prop->core.propType == QMetaType::Int) { bool isEnumAssignment = false; COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, v, &isEnumAssignment)); if (isEnumAssignment) { @@ -2525,8 +2525,9 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop, QQmlScript::Value *v, bool *isAssignment) { + bool isIntProp = (prop->core.propType == QMetaType::Int) && !prop->core.isEnum(); *isAssignment = false; - if (!prop->core.isEnum()) + if (!prop->core.isEnum() && !isIntProp) return true; QMetaProperty mprop = obj->metaObject()->property(prop->index); @@ -2538,6 +2539,17 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop, if (!string.at(0).isUpper()) return true; + if (isIntProp) { + // Allow enum assignment to ints. + int enumval = evaluateEnum(string.toUtf8()); + if (enumval != -1) { + v->type = Value::Literal; + v->value = QQmlScript::Variant((double)enumval); + *isAssignment = true; + } + return true; + } + QStringList parts = string.split(QLatin1Char('.')); if (parts.count() != 2) return true; diff --git a/tests/auto/qml/qqmlecmascript/data/enums.3.qml b/tests/auto/qml/qqmlecmascript/data/enums.3.qml new file mode 100644 index 0000000000..c77d635a1e --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/enums.3.qml @@ -0,0 +1,41 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import Qt.test 1.0 as Namespace + +Item { + // Enums from type + property int a: Item.Center + property int b: Item.Right + + // Enums from Qt + property int c: Qt.blue + property int d: Qt.darkRed + + // Enums from other type + property int e: MyQmlObject.EnumValue3 + property int f: MyQmlObject.EnumValue4 + + // Enums from namespaced other type + property int h: Namespace.MyQmlObject.EnumValue3 + property int i: Namespace.MyQmlObject.EnumValue4 + + // Count the onChanged signals to see whether + // they're assigned as literals or via bindings + property int ac: 0 + property int bc: 0 + property int cc: 0 + property int dc: 0 + property int ec: 0 + property int fc: 0 + property int hc: 0 + property int ic: 0 + + onAChanged: ac++ + onBChanged: bc++ + onCChanged: cc++ + onDChanged: dc++ + onEChanged: ec++ + onFChanged: fc++ + onHChanged: hc++ + onIChanged: ic++ +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index ca4708e7ee..a94e8374cc 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -846,6 +846,34 @@ void tst_qqmlecmascript::enums() QCOMPARE(object->property("a").toInt(), 0); QCOMPARE(object->property("b").toInt(), 0); + delete object; + } + // Enums as literals + { + QQmlComponent component(&engine, testFileUrl("enums.3.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + // check the values are what we expect + QCOMPARE(object->property("a").toInt(), 4); + QCOMPARE(object->property("b").toInt(), 5); + QCOMPARE(object->property("c").toInt(), 9); + QCOMPARE(object->property("d").toInt(), 13); + QCOMPARE(object->property("e").toInt(), 2); + QCOMPARE(object->property("f").toInt(), 3); + QCOMPARE(object->property("h").toInt(), 2); + QCOMPARE(object->property("i").toInt(), 3); + + // count of change signals + QCOMPARE(object->property("ac").toInt(), 0); + QCOMPARE(object->property("bc").toInt(), 0); + QCOMPARE(object->property("cc").toInt(), 0); + QCOMPARE(object->property("dc").toInt(), 0); + QCOMPARE(object->property("ec").toInt(), 0); + QCOMPARE(object->property("fc").toInt(), 0); + QCOMPARE(object->property("hc").toInt(), 1); // namespace -> binding + QCOMPARE(object->property("ic").toInt(), 1); // namespace -> binding + delete object; } }