From 55faad4873a9409bb1b33a10da7329d13a95aff9 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 22 Jun 2012 09:23:26 +1000 Subject: [PATCH] Handle enum values of -1 correctly. This was already handled correctly most places; now the remaining cases (using an enum in ListModel, and assigning an enum to an integer property) should also work correctly. Task-number: QTBUG-21679 Change-Id: Ibff13f0b94da94b18e2e3bae4aa6ba44e0fa944b Reviewed-by: Chris Adams --- src/qml/qml/qqmlcompiler.cpp | 14 ++++++++------ src/qml/qml/qqmlcompiler_p.h | 2 +- src/qml/qml/qqmlcustomparser.cpp | 14 +++++++++----- src/qml/qml/qqmlcustomparser_p.h | 2 +- src/qml/qml/qquicklistmodel.cpp | 5 +++-- tests/auto/qml/qqmlecmascript/data/enums.3.qml | 5 +++++ tests/auto/qml/qqmlecmascript/testtypes.h | 2 +- tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 2 ++ tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp | 6 ++++++ 9 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp index 5df02d0..2bb99dd 100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@ -2517,8 +2517,9 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop, if (isIntProp) { // Allow enum assignment to ints. - int enumval = evaluateEnum(typeName, enumValue.toUtf8()); - if (enumval != -1) { + bool ok; + int enumval = evaluateEnum(typeName, enumValue.toUtf8(), &ok); + if (ok) { v->type = Value::Literal; v->value = QQmlScript::Variant((double)enumval); *isAssignment = true; @@ -2565,8 +2566,10 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop, } // Similar logic to above, but not knowing target property. -int QQmlCompiler::evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue) const +int QQmlCompiler::evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const { + Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer"); + *ok = false; QQmlType *type = 0; if (scope != QLatin1String("Qt")) { unit->imports().resolveType(scope, &type, 0, 0, 0, 0); @@ -2577,9 +2580,8 @@ int QQmlCompiler::evaluateEnum(const QHashedStringRef &scope, const QByteArray& const QMetaObject *mo = type ? type->metaObject() : StaticQtMetaObject::get(); int i = mo->enumeratorCount(); while (i--) { - bool ok; - int v = mo->enumerator(i).keyToValue(enumValue.constData(), &ok); - if (ok) + int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok); + if (*ok) return v; } return -1; diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index 4b730c2..b919b53 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -295,7 +295,7 @@ public: static bool isAttachedPropertyName(const QHashedStringRef &); static bool isSignalPropertyName(const QHashedStringRef &); - int evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue) const; // for QQmlCustomParser::evaluateEnum + int evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const; // for QQmlCustomParser::evaluateEnum const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType int rewriteBinding(const QQmlScript::Variant& value, const QString& name); // for QQmlCustomParser::rewriteBinding QString rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name); // for QQmlCustomParser::rewriteSignalHandler diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index f020376..7c7a2f5 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -279,18 +279,22 @@ void QQmlCustomParser::error(const QQmlCustomParserNode& node, const QString& de } /*! - If \a script is a simply enum expression (eg. Text.AlignLeft), - returns the integer equivalent (eg. 1). + If \a script is a simple enum expression (eg. Text.AlignLeft), + returns the integer equivalent (eg. 1), and sets \a ok to true. - Otherwise, returns -1. + Otherwise sets \a ok to false. + + A valid \a ok must be provided, or the function will assert. */ -int QQmlCustomParser::evaluateEnum(const QByteArray& script) const +int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const { + Q_ASSERT_X(ok, "QQmlCustomParser::evaluateEnum", "ok must not be a null pointer"); + *ok = false; int dot = script.indexOf('.'); if (dot == -1) return -1; - return compiler->evaluateEnum(QString::fromUtf8(script.left(dot)), script.mid(dot+1)); + return compiler->evaluateEnum(QString::fromUtf8(script.left(dot)), script.mid(dot+1), ok); } /*! diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h index 0207797..b8cc9f7 100644 --- a/src/qml/qml/qqmlcustomparser_p.h +++ b/src/qml/qml/qqmlcustomparser_p.h @@ -137,7 +137,7 @@ protected: void error(const QQmlCustomParserProperty&, const QString& description); void error(const QQmlCustomParserNode&, const QString& description); - int evaluateEnum(const QByteArray&) const; + int evaluateEnum(const QByteArray&, bool *ok) const; const QMetaObject *resolveType(const QString&) const; diff --git a/src/qml/qml/qquicklistmodel.cpp b/src/qml/qml/qquicklistmodel.cpp index 461d4d8..52ef2ab 100644 --- a/src/qml/qml/qquicklistmodel.cpp +++ b/src/qml/qml/qquicklistmodel.cpp @@ -2229,8 +2229,9 @@ bool QQuickListModelParser::compileProperty(const QQmlCustomParserProperty &prop d[0] = char(QQmlScript::Variant::Invalid); // marks empty list } else { QByteArray script = variant.asScript().toUtf8(); - int v = evaluateEnum(script); - if (v<0) { + bool ok; + int v = evaluateEnum(script, &ok); + if (!ok) { using namespace QQmlJS; AST::Node *node = variant.asAST(); AST::StringLiteral *literal = 0; diff --git a/tests/auto/qml/qqmlecmascript/data/enums.3.qml b/tests/auto/qml/qqmlecmascript/data/enums.3.qml index c77d635..fd3432f 100644 --- a/tests/auto/qml/qqmlecmascript/data/enums.3.qml +++ b/tests/auto/qml/qqmlecmascript/data/enums.3.qml @@ -19,6 +19,9 @@ Item { property int h: Namespace.MyQmlObject.EnumValue3 property int i: Namespace.MyQmlObject.EnumValue4 + // -1 enum + property int j: MyQmlObject.EnumValue5 + // Count the onChanged signals to see whether // they're assigned as literals or via bindings property int ac: 0 @@ -29,6 +32,7 @@ Item { property int fc: 0 property int hc: 0 property int ic: 0 + property int jc: 0 onAChanged: ac++ onBChanged: bc++ @@ -38,4 +42,5 @@ Item { onFChanged: fc++ onHChanged: hc++ onIChanged: ic++ + onJChanged: jc++ } diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index 8f3804a..ab44d59 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -111,7 +111,7 @@ 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 }; + enum MyEnum2 { EnumValue3 = 2, EnumValue4 = 3, EnumValue5 = -1 }; bool trueProperty() const { return true; } bool falseProperty() const { return false; } diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index d344758..c429ffa 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -983,6 +983,7 @@ void tst_qqmlecmascript::enums() QCOMPARE(object->property("f").toInt(), 3); QCOMPARE(object->property("h").toInt(), 2); QCOMPARE(object->property("i").toInt(), 3); + QCOMPARE(object->property("j").toInt(), -1); // count of change signals QCOMPARE(object->property("ac").toInt(), 0); @@ -993,6 +994,7 @@ void tst_qqmlecmascript::enums() QCOMPARE(object->property("fc").toInt(), 0); QCOMPARE(object->property("hc").toInt(), 1); // namespace -> binding QCOMPARE(object->property("ic").toInt(), 1); // namespace -> binding + QCOMPARE(object->property("jc").toInt(), 0); delete object; } diff --git a/tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp b/tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp index 4c4aa48..89e8886 100644 --- a/tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp +++ b/tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -228,6 +229,11 @@ void tst_qquicklistmodel::static_types_data() << QVariant(double(Qt::AlignBottom)) << QString(); + QTest::newRow("negative enum") + << "ListElement { foo: Animation.Infinite }" + << QVariant(double(QQuickAbstractAnimation::Infinite)) + << QString(); + QTest::newRow("role error") << "ListElement { foo: 1 } ListElement { foo: 'string' }" << QVariant() -- 2.7.4