From 4ba9a1b0c2fb9e5566210f751e983e5d55b85799 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen <erik.verbruggen@nokia.com> Date: Tue, 6 Apr 2010 15:40:47 +0200 Subject: [PATCH] Fixed qualified-enum handling. Done-with: ckamm --- src/libs/qmljs/qmljsinterpreter.cpp | 13 ++++ src/libs/qmljs/qmljsinterpreter.h | 1 + .../core/model/texttomodelmerger.cpp | 78 ++++++++++++++++++- 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index 514c734c23c..a7f8d916a1e 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -876,6 +876,19 @@ bool QmlObjectValue::isEnum(const QString &typeName) const return _metaObject->enumeratorIndex(typeName) != -1; } +bool QmlObjectValue::enumContainsKey(const QString &enumName, const QString &enumKeyName) const +{ + int idx = _metaObject->enumeratorIndex(enumName); + if (idx == -1) + return false; + const FakeMetaEnum &fme = _metaObject->enumerator(idx); + for (int i = 0; i < fme.keyCount(); ++i) { + if (fme.key(i) == enumKeyName) + return true; + } + return false; +} + bool QmlObjectValue::isDerivedFrom(const FakeMetaObject *base) const { for (const FakeMetaObject *iter = _metaObject; iter; iter = iter->superClass()) { diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index 97800977b7b..fc95e3f7deb 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -420,6 +420,7 @@ public: QString propertyType(const QString &propertyName) const; bool isListProperty(const QString &name) const; bool isEnum(const QString &typeName) const; + bool enumContainsKey(const QString &enumName, const QString &enumKeyName) const; protected: const Value *findOrCreateSignature(int index, const FakeMetaMethod &method, QString *methodName) const; diff --git a/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp index 5a827cc5a78..92148dc0566 100644 --- a/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp @@ -38,6 +38,7 @@ #include "rewriterview.h" #include "variantproperty.h" +#include <qmljs/qmljsevaluate.h> #include <qmljs/qmljsinterpreter.h> #include <qmljs/qmljslink.h> #include <qmljs/qmljsscopebuilder.h> @@ -371,6 +372,65 @@ public: return v; } + QVariant convertToEnum(Statement *rhs, UiQualifiedId *propertyId) + { + ExpressionStatement *eStmt = cast<ExpressionStatement *>(rhs); + if (!eStmt || !eStmt->expression) + return QVariant(); + + const Interpreter::ObjectValue *containingObject = 0; + QString name; + if (!lookupProperty(propertyId, 0, &containingObject, &name)) { + return QVariant(); + } + + for (const Interpreter::ObjectValue *iter = containingObject; iter; iter = iter->prototype(m_context)) { + if (iter->lookupMember(name, m_context, false)) { + containingObject = iter; + break; + } + } + const Interpreter::QmlObjectValue * lhsQmlObject = dynamic_cast<const Interpreter::QmlObjectValue *>(containingObject); + if (!lhsQmlObject) + return QVariant(); + const QString lhsPropertyTypeName = lhsQmlObject->propertyType(name); + + const Interpreter::ObjectValue *rhsValueObject = 0; + QString rhsValueName; + if (IdentifierExpression *idExp = cast<IdentifierExpression *>(eStmt->expression)) { + if (!m_context->scopeChain().qmlScopeObjects.isEmpty()) + rhsValueObject = m_context->scopeChain().qmlScopeObjects.last(); + if (idExp->name) + rhsValueName = idExp->name->asString(); + } else if (FieldMemberExpression *memberExp = cast<FieldMemberExpression *>(eStmt->expression)) { + Evaluate evaluate(m_context); + const Interpreter::Value *result = evaluate(memberExp->base); + rhsValueObject = result->asObjectValue(); + + if (memberExp->name) + rhsValueName = memberExp->name->asString(); + } + + if (!rhsValueObject) + return QVariant(); + + for (const Interpreter::ObjectValue *iter = rhsValueObject; iter; iter = iter->prototype(m_context)) { + if (iter->lookupMember(rhsValueName, m_context, false)) { + rhsValueObject = iter; + break; + } + } + + const Interpreter::QmlObjectValue *rhsQmlObjectValue = dynamic_cast<const Interpreter::QmlObjectValue *>(rhsValueObject); + if (!rhsQmlObjectValue) + return QVariant(); + + if (rhsQmlObjectValue->enumContainsKey(lhsPropertyTypeName, rhsValueName)) + return QVariant(rhsValueName); + else + return QVariant(); + } + private: Snapshot m_snapshot; Document::Ptr m_doc; @@ -639,13 +699,23 @@ void TextToModelMerger::syncNode(ModelNode &modelNode, } } } else { - if (typeName == QLatin1String("Qt/PropertyChanges") || context->lookupProperty(script->qualifiedId)) { + // First see if it is a qualified enum: + const QVariant enumValue = context->convertToEnum(script->statement, script->qualifiedId); + if (enumValue.isValid()) { + const QString astPropertyName = flatten(script->qualifiedId); AbstractProperty modelProperty = modelNode.property(astPropertyName); - syncExpressionProperty(modelProperty, astValue, differenceHandler); + syncVariantProperty(modelProperty, enumValue, QString(), differenceHandler); modelPropertyNames.remove(astPropertyName); } else { - qWarning() << "Skipping invalid expression property" << astPropertyName - << "for node type" << modelNode.type(); + // apparently not, so: + if (typeName == QLatin1String("Qt/PropertyChanges") || context->lookupProperty(script->qualifiedId)) { + AbstractProperty modelProperty = modelNode.property(astPropertyName); + syncExpressionProperty(modelProperty, astValue, differenceHandler); + modelPropertyNames.remove(astPropertyName); + } else { + qWarning() << "Skipping invalid expression property" << astPropertyName + << "for node type" << modelNode.type(); + } } } } else if (UiPublicMember *property = cast<UiPublicMember *>(member)) { -- GitLab