diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-09-03 00:14:54 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-09-03 00:14:54 (GMT) |
commit | b9c834048d6dc6e04567c1c73212ecb1b9c96664 (patch) | |
tree | 223b1d3d101883dabadadbf68b020808de56399e /src/declarative/qml | |
parent | dc26066be54bed3d508b460db1cc8d8b4b68cc1f (diff) | |
download | Qt-b9c834048d6dc6e04567c1c73212ecb1b9c96664.zip Qt-b9c834048d6dc6e04567c1c73212ecb1b9c96664.tar.gz Qt-b9c834048d6dc6e04567c1c73212ecb1b9c96664.tar.bz2 |
Add QML enum support
Enums are accessed as <Type Name>.<Enum value name>
Currently this is highly unoptimal - enum assignments are not detected
in the compiler, nor are they cached in the script engine.
Diffstat (limited to 'src/declarative/qml')
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler_p.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlcomponent.cpp | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine.cpp | 135 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine_p.h | 33 |
6 files changed, 155 insertions, 19 deletions
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index c0f7bfd..6519dff 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -642,6 +642,8 @@ void QmlCompiler::compileTree(Object *tree) def.type = QmlInstruction::SetDefault; output->bytecode << def; + output->imports = unit->imports; + if (tree->metatype) static_cast<QMetaObject &>(output->root) = *tree->metaObject(); else diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index c42c2d9..83c415c 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -76,6 +76,7 @@ public: QByteArray name; QUrl url; + QmlEnginePrivate::Imports imports; struct TypeReference { diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index c844a32..e897cce 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -488,6 +488,7 @@ QObject *QmlComponent::beginCreate(QmlContext *context) static_cast<QmlContextPrivate *>(QObjectPrivate::get(context)); QmlContext *ctxt = new QmlContext(context, 0, true); static_cast<QmlContextPrivate*>(ctxt->d_func())->url = d->cc->url; + static_cast<QmlContextPrivate*>(ctxt->d_func())->imports = d->cc->imports; QmlVME vme; QObject *rv = vme.run(ctxt, d->cc, d->start, d->count); diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 84d990c..b305408 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -60,6 +60,7 @@ #include <QtScript/qscriptvalue.h> #include <QtCore/qset.h> #include <private/qguard_p.h> +#include <private/qmlengine_p.h> QT_BEGIN_NAMESPACE @@ -91,6 +92,7 @@ public: QScriptValueList scopeChain; QUrl url; + QmlEnginePrivate::Imports imports; void init(); diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 0d6e281..3d8b2c4 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -181,6 +181,7 @@ void QmlEnginePrivate::init() contextClass = new QmlContextScriptClass(q); objectClass = new QmlObjectScriptClass(q); valueTypeClass = new QmlValueTypeScriptClass(q); + typeNameClass = new QmlTypeNameScriptClass(q); rootContext = new QmlContext(q,true); #ifdef QT_SCRIPTTOOLS_LIB if (qmlDebugger()){ @@ -211,10 +212,22 @@ QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p) { } -//////////////////////////////////////////////////////////////////// -typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache; -Q_GLOBAL_STATIC(FunctionCache, functionCache); +struct QmlTypeNameBridge +{ + QObject *object; + QmlType *type; + QmlEnginePrivate::ImportedNamespace *ns; +}; +Q_DECLARE_METATYPE(QmlTypeNameBridge); + +struct QmlValueTypeReference { + QmlValueType *type; + QGuard<QObject> object; + int property; +}; +Q_DECLARE_METATYPE(QmlValueTypeReference); +//////////////////////////////////////////////////////////////////// QScriptClass::QueryFlags QmlEnginePrivate::queryContext(const QString &propName, uint *id, QmlContext *bindContext) @@ -223,19 +236,32 @@ QmlEnginePrivate::queryContext(const QString &propName, uint *id, *id = resolveData.safetyCheckId; resolveData.clear(); - QScriptClass::QueryFlags rv = 0; QHash<QString, int>::Iterator contextProperty = bindContext->d_func()->propertyNames.find(propName); if (contextProperty != bindContext->d_func()->propertyNames.end()) { - rv |= QScriptClass::HandlesReadAccess; resolveData.context = bindContext; resolveData.contextIndex = *contextProperty; - return rv; + return QScriptClass::HandlesReadAccess; } + QmlType *type = 0; ImportedNamespace *ns = 0; + if (currentExpression && bindContext == currentExpression->context() && + propName.at(0).isUpper() && resolveType(bindContext->d_func()->imports, propName.toUtf8(), &type, 0, 0, 0, &ns)) { + + if (type || ns) { + // Must be either an attached property, or an enum + resolveData.object = bindContext->d_func()->defaultObjects.first(); + resolveData.type = type; + resolveData.ns = ns; + return QScriptClass::HandlesReadAccess; + } + + } + + QScriptClass::QueryFlags rv = 0; for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) { rv = queryObject(propName, id, bindContext->d_func()->defaultObjects.at(ii)); @@ -252,7 +278,14 @@ QmlEnginePrivate::propertyContext(const QScriptString &name, Q_ASSERT(id == resolveData.safetyCheckId); - if (resolveData.context) { + if (resolveData.type || resolveData.ns) { + QmlTypeNameBridge tnb = { + resolveData.object, + resolveData.type, + resolveData.ns + }; + return scriptEngine.newObject(typeNameClass, scriptEngine.newVariant(qVariantFromValue(tnb))); + } else if (resolveData.context) { QmlContext *bindContext = resolveData.context; QmlContextPrivate *contextPrivate = bindContext->d_func(); int index = resolveData.contextIndex; @@ -314,13 +347,13 @@ QmlEnginePrivate::queryObject(const QString &propName, QPair<const QMetaObject *, QString> key = qMakePair(obj->metaObject(), propName); bool isFunction = false; - if (functionCache()->contains(key)) { - isFunction = functionCache()->value(key); + if (functionCache.contains(key)) { + isFunction = functionCache.value(key); } else { QScriptValue sobj = scriptEngine.newQObject(obj); QScriptValue func = sobj.property(propName); isFunction = func.isFunction(); - functionCache()->insert(key, isFunction); + functionCache.insert(key, isFunction); } if (isFunction) { @@ -340,13 +373,6 @@ QmlEnginePrivate::queryObject(const QString &propName, return rv; } -struct QmlValueTypeReference { - QmlValueType *type; - QGuard<QObject> object; - int property; -}; -Q_DECLARE_METATYPE(QmlValueTypeReference); - QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName, QObject *obj, uint id) { @@ -1084,6 +1110,81 @@ void QmlContextScriptClass::setProperty(QScriptValue &object, } ///////////////////////////////////////////////////////////// +QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *engine) +: QmlScriptClass(engine), object(0), type(0) +{ +} + +QmlTypeNameScriptClass::~QmlTypeNameScriptClass() +{ +} + +QmlTypeNameScriptClass::QueryFlags +QmlTypeNameScriptClass::queryProperty(const QScriptValue &scriptObject, + const QScriptString &name, + QueryFlags flags, uint *id) +{ + QmlTypeNameBridge bridge = + qvariant_cast<QmlTypeNameBridge>(scriptObject.data().toVariant()); + + object = 0; + type = 0; + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + + if (bridge.ns) { + QmlType *type = 0; + ep->resolveTypeInNamespace(bridge.ns, name.toString().toUtf8(), + &type, 0, 0, 0); + if (type) { + object = bridge.object; + this->type = type; + return HandlesReadAccess; + } else { + return 0; + } + + } else { + Q_ASSERT(bridge.type); + QString strName = name.toString(); + if (strName.at(0).isUpper()) { + // Must be an enum + // ### Optimize + const char *enumName = strName.toUtf8().constData(); + const QMetaObject *metaObject = bridge.type->baseMetaObject(); + for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { + QMetaEnum e = metaObject->enumerator(ii); + int value = e.keyToValue(enumName); + if (value != -1) { + enumValue = value; + return HandlesReadAccess; + } + } + return 0; + } else { + // Must be an attached property + this->object = qmlAttachedPropertiesObjectById(bridge.type->index(), bridge.object); + Q_ASSERT(this->object); + return ep->queryObject(strName, id, this->object); + } + } +} + +QScriptValue QmlTypeNameScriptClass::property(const QScriptValue &, + const QScriptString &propName, + uint id) +{ + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + if (type) { + QmlTypeNameBridge tnb = { object, type, 0 }; + return ep->scriptEngine.newObject(ep->typeNameClass, ep->scriptEngine.newVariant(qVariantFromValue(tnb))); + } else if (object) { + return ep->propertyObject(propName, object, id); + } else { + return QScriptValue(enumValue); + } +} + +///////////////////////////////////////////////////////////// QmlValueTypeScriptClass::QmlValueTypeScriptClass(QmlEngine *bindEngine) : QmlScriptClass(bindEngine) { diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 451276d..f492ccb 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -82,6 +82,7 @@ class QmlExpression; class QmlBasicScriptNodeCache; class QmlContextScriptClass; class QmlObjectScriptClass; +class QmlTypeNameScriptClass; class QmlValueTypeScriptClass; class QScriptEngineDebugger; class QNetworkReply; @@ -127,16 +128,22 @@ public: QScriptEngineDebugger *debugger; #endif + struct ImportedNamespace; struct ResolveData { ResolveData() : safetyCheckId(0) {} int safetyCheckId; void clear() { - object = 0; context = 0; contextIndex = -1; isFunction = false; + object = 0; context = 0; + type = 0; ns = 0; + contextIndex = -1; isFunction = false; } QObject *object; QmlContext *context; + QmlType *type; + QmlEnginePrivate::ImportedNamespace *ns; + int contextIndex; bool isFunction; QmlMetaProperty property; @@ -144,6 +151,7 @@ public: QmlContextScriptClass *contextClass; QmlObjectScriptClass *objectClass; QmlValueTypeScriptClass *valueTypeClass; + QmlTypeNameScriptClass *typeNameClass; // Used by DOM Core 3 API QScriptClass *nodeListClass; QScriptClass *namedNodeMapClass; @@ -199,6 +207,9 @@ public: } QmlValueTypeFactory valueTypes; + // ### Fixme + typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache; + FunctionCache functionCache; QHash<const QMetaObject *, QmlMetaObjectCache> propertyCache; static QmlMetaObjectCache *cache(QmlEnginePrivate *priv, QObject *obj) { if (!priv || !obj || QObjectPrivate::get(obj)->metaObject) return 0; @@ -219,7 +230,6 @@ public: QmlImportsPrivate *d; }; - struct ImportedNamespace; bool addToImport(Imports*, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const; bool resolveType(const Imports&, const QByteArray& type, QmlType** type_return, QUrl* url_return, @@ -313,6 +323,25 @@ public: const QScriptValue &value); }; +class QmlTypeNameScriptClass : public QmlScriptClass +{ +public: + QmlTypeNameScriptClass(QmlEngine *); + ~QmlTypeNameScriptClass(); + + virtual QueryFlags queryProperty(const QScriptValue &object, + const QScriptString &name, + QueryFlags flags, uint *id); + virtual QScriptValue property(const QScriptValue &object, + const QScriptString &name, + uint id); + +private: + QObject *object; + QmlType *type; + quint32 enumValue; +}; + class QmlValueTypeScriptClass : public QmlScriptClass { public: |