summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-09-03 00:14:54 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-09-03 00:14:54 (GMT)
commitb9c834048d6dc6e04567c1c73212ecb1b9c96664 (patch)
tree223b1d3d101883dabadadbf68b020808de56399e /src/declarative/qml
parentdc26066be54bed3d508b460db1cc8d8b4b68cc1f (diff)
downloadQt-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.cpp2
-rw-r--r--src/declarative/qml/qmlcompiler_p.h1
-rw-r--r--src/declarative/qml/qmlcomponent.cpp1
-rw-r--r--src/declarative/qml/qmlcontext_p.h2
-rw-r--r--src/declarative/qml/qmlengine.cpp135
-rw-r--r--src/declarative/qml/qmlengine_p.h33
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: