diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-10-02 07:09:09 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-10-05 02:40:47 (GMT) |
commit | 3490b478ed02859f0355438efba900cd853e9c13 (patch) | |
tree | f554feca685671aef6775da255150a122597c258 | |
parent | b3605d7f45c1cdb61bbd2a572e58bd29aaea6956 (diff) | |
download | Qt-3490b478ed02859f0355438efba900cd853e9c13.zip Qt-3490b478ed02859f0355438efba900cd853e9c13.tar.gz Qt-3490b478ed02859f0355438efba900cd853e9c13.tar.bz2 |
Reenable types/enums and move scripts into an isolated scope
26 files changed, 922 insertions, 383 deletions
diff --git a/demos/declarative/samegame/content/samegame.js b/demos/declarative/samegame/content/samegame.js index 09057eb..7deafde 100755 --- a/demos/declarative/samegame/content/samegame.js +++ b/demos/declarative/samegame/content/samegame.js @@ -22,6 +22,11 @@ function timeStr(msecs) { return ret; } +function getTileSize() +{ + return tileSize; +} + function initBoard() { for(var i = 0; i<maxIndex; i++){ diff --git a/demos/declarative/samegame/samegame.qml b/demos/declarative/samegame/samegame.qml index ede4362..2d00208 100644 --- a/demos/declarative/samegame/samegame.qml +++ b/demos/declarative/samegame/samegame.qml @@ -23,8 +23,8 @@ Rectangle { property int score: 0 z: 20; anchors.centerIn: parent - width: parent.width - (parent.width % tileSize); - height: parent.height - (parent.height % tileSize); + width: parent.width - (parent.width % getTileSize()); + height: parent.height - (parent.height % getTileSize()); MouseRegion { id: gameMR diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index eb761e3..e46dd3f 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -37,9 +37,12 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlwatcher.cpp \ qml/qmlpropertycache.cpp \ qml/qmlintegercache.cpp \ + qml/qmltypenamecache.cpp \ qml/qmlobjectscriptclass.cpp \ qml/qmlcontextscriptclass.cpp \ - qml/qmlglobalscriptclass.cpp + qml/qmlglobalscriptclass.cpp \ + qml/qmlvaluetypescriptclass.cpp \ + qml/qmltypenamescriptclass.cpp HEADERS += qml/qmlparser_p.h \ qml/qmlinstruction_p.h \ @@ -94,9 +97,12 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlwatcher_p.h \ qml/qmlpropertycache_p.h \ qml/qmlintegercache_p.h \ + qml/qmltypenamecache_p.h \ qml/qmlobjectscriptclass_p.h \ qml/qmlcontextscriptclass_p.h \ - qml/qmlglobalscriptclass_p.h + qml/qmlglobalscriptclass_p.h \ + qml/qmlvaluetypescriptclass_p.h \ + qml/qmltypenamescriptclass_p.h # for qtscript debugger contains(QT_CONFIG, scripttools):QT += scripttools diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp index a603d4e..8c3c355 100644 --- a/src/declarative/qml/qmlcompileddata.cpp +++ b/src/declarative/qml/qmlcompileddata.cpp @@ -150,6 +150,7 @@ int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l) } QmlCompiledData::QmlCompiledData() +: importCache(0) { } @@ -163,6 +164,9 @@ QmlCompiledData::~QmlCompiledData() for (int ii = 0; ii < propertyCaches.count(); ++ii) propertyCaches.at(ii)->release(); + if (importCache) + importCache->release(); + qDeleteAll(programs); } diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 5cb2158..4b5c5bf 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -644,6 +644,7 @@ void QmlCompiler::compileTree(Object *tree) output->bytecode << def; output->imports = unit->imports; + output->importCache = output->imports.cache(engine); Q_ASSERT(tree->metatype); static_cast<QMetaObject &>(output->root) = *tree->metaObject(); diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 1cb66c7..fd361fd 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -64,6 +64,7 @@ #include <private/qbitfield_p.h> #include <private/qmlpropertycache_p.h> #include <private/qmlintegercache_p.h> +#include <private/qmltypenamecache_p.h> QT_BEGIN_NAMESPACE @@ -81,6 +82,7 @@ public: QByteArray name; QUrl url; QmlEnginePrivate::Imports imports; + QmlTypeNameCache *importCache; struct TypeReference { diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index fedc2da..5b1cbeb 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -517,7 +517,8 @@ QmlComponentPrivate::beginCreate(QmlContext *context, const QBitField &bindings) static_cast<QmlContextPrivate *>(QObjectPrivate::get(context)); QmlContext *ctxt = new QmlContext(context, 0, true); static_cast<QmlContextPrivate*>(ctxt->d_func())->url = cc->url; - static_cast<QmlContextPrivate*>(ctxt->d_func())->imports = cc->imports; + static_cast<QmlContextPrivate*>(ctxt->d_func())->imports = cc->importCache; + cc->importCache->addref(); QmlVME vme; QObject *rv = vme.run(ctxt, cc, start, count, bindings); diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 5e74d1a..968597c 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE QmlContextPrivate::QmlContextPrivate() : parent(0), engine(0), isInternal(false), propertyNames(0), notifyIndex(-1), - highPriorityCount(0), expressions(0), idValues(0), idValueCount(0) + highPriorityCount(0), imports(0), expressions(0), idValues(0), idValueCount(0) { } @@ -307,6 +307,9 @@ QmlContext::~QmlContext() if (d->propertyNames) d->propertyNames->release(); + + if (d->imports) + d->imports->release(); } void QmlContextPrivate::invalidateEngines() diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 64faa6d..8fd2e92 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -62,6 +62,7 @@ #include <private/qguard_p.h> #include <private/qmlengine_p.h> #include <private/qmlintegercache_p.h> +#include <private/qmltypenamecache_p.h> QT_BEGIN_NAMESPACE @@ -93,8 +94,11 @@ public: QScriptValueList scopeChain; + QList<QScriptValue> scripts; + QUrl url; - QmlEnginePrivate::Imports imports; + + QmlTypeNameCache *imports; void init(); diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index baea60a..d8ae4f0 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -42,6 +42,7 @@ #include "qmlcontextscriptclass_p.h" #include <private/qmlengine_p.h> #include <private/qmlcontext_p.h> +#include <private/qmltypenamescriptclass_p.h> QT_BEGIN_NAMESPACE @@ -56,7 +57,7 @@ struct ContextData { */ QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine) : QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), - lastPropertyIndex(-1), lastDefaultObject(-1) + lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) { } @@ -76,21 +77,32 @@ QmlContextScriptClass::queryProperty(const Object &object, const Identifier &nam QScriptClass::QueryFlags flags) { Q_UNUSED(flags); + + lastPropertyIndex = -1; + lastDefaultObject = -1; + lastData = 0; + QmlContext *bindContext = ((ContextData *)object)->context.data(); if (!bindContext) return 0; QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); - - lastPropertyIndex = -1; - lastDefaultObject = -1; lastPropertyIndex = cp->propertyNames?cp->propertyNames->value(name):-1; if (lastPropertyIndex != -1) return QScriptClass::HandlesReadAccess; // ### Check for attached properties + if (ep->currentExpression && cp->imports && bindContext == ep->currentExpression->context()) { + QmlTypeNameCache::Data *data = cp->imports->data(name); + + if (data) { + lastData = data; + return QScriptClass::HandlesReadAccess; + } + } + #if 0 QmlType *type = 0; ImportedNamespace *ns = 0; if (currentExpression && bindContext == currentExpression->context() && @@ -117,6 +129,11 @@ QmlContextScriptClass::queryProperty(const Object &object, const Identifier &nam } } + for (int ii = 0; ii < cp->scripts.count(); ++ii) { + lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); + if (lastFunction.isValid()) + return QScriptClass::HandlesReadAccess; + } return 0; } @@ -145,7 +162,14 @@ QScriptValue QmlContextScriptClass::property(const Object &object, const Identif } #endif - if (lastPropertyIndex != -1) { + if (lastData) { + + if (lastData->type) + return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type); + else + return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->typeNamespace); + + } else if (lastPropertyIndex != -1) { QScriptValue rv; if (lastPropertyIndex < cp->idValueCount) { @@ -161,15 +185,18 @@ QScriptValue QmlContextScriptClass::property(const Object &object, const Identif } ep->capturedProperties << - QmlEnginePrivate::CapturedProperty(bindContext, -1, - lastPropertyIndex + cp->notifyIndex); + QmlEnginePrivate::CapturedProperty(bindContext, -1, lastPropertyIndex + cp->notifyIndex); return rv; - } else { + } else if(lastDefaultObject != -1) { // Default object property return ep->objectClass->property(cp->defaultObjects.at(lastDefaultObject), name); + } else { + + return lastFunction; + } } diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h index 9ef090d..a00e567 100644 --- a/src/declarative/qml/qmlcontextscriptclass_p.h +++ b/src/declarative/qml/qmlcontextscriptclass_p.h @@ -55,6 +55,7 @@ #include <QtScript/qscriptclass.h> #include <private/qscriptdeclarativeclass_p.h> +#include <private/qmltypenamecache_p.h> QT_BEGIN_NAMESPACE @@ -77,8 +78,10 @@ protected: private: QmlEngine *engine; + QmlTypeNameCache::Data *lastData; int lastPropertyIndex; int lastDefaultObject; + QScriptValue lastFunction; uint m_id; }; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 4afd245..e67e42f 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -85,6 +85,7 @@ #include <private/qmlstringconverters_p.h> #include <private/qmlxmlhttprequest_p.h> #include <private/qmlsqldatabase_p.h> +#include <private/qmltypenamescriptclass_p.h> #ifdef Q_OS_WIN // for %APPDATA% #include "qt_windows.h" @@ -274,114 +275,6 @@ QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p) { } -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); - -void QmlEnginePrivate::setPropertyObject(const QScriptValue &value, uint id) -{ - Q_ASSERT(id == resolveData.safetyCheckId); - Q_Q(QmlEngine); - - resolveData.property.write(QmlScriptClass::toVariant(q, value)); -} - -QScriptClass::QueryFlags -QmlEnginePrivate::queryObject(const QString &propName, - uint *id, QObject *obj) -{ - resolveData.safetyCheckId++; - *id = resolveData.safetyCheckId; - resolveData.clear(); - - QScriptClass::QueryFlags rv = 0; - - QmlContext *ctxt = QmlEngine::contextForObject(obj); - if (!ctxt) - ctxt = rootContext; - QmlMetaProperty prop(obj, propName, ctxt); - - if (prop.type() == QmlMetaProperty::Invalid) { - QPair<const QMetaObject *, QString> key = - qMakePair(obj->metaObject(), propName); - bool isFunction = false; - 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); - } - - if (isFunction) { - resolveData.object = obj; - resolveData.isFunction = true; - rv |= QScriptClass::HandlesReadAccess; - } - } else { - resolveData.object = obj; - resolveData.property = prop; - - rv |= QScriptClass::HandlesReadAccess; - if (prop.isWritable()) - rv |= QScriptClass::HandlesWriteAccess; - } - - return rv; -} - -QScriptValue QmlEnginePrivate::propertyObject(const QString &propName, - QObject *obj, uint id) -{ - Q_ASSERT(id == resolveData.safetyCheckId); - Q_ASSERT(resolveData.object); - - if (resolveData.isFunction) { - // ### Optimize - QScriptValue sobj = scriptEngine.newQObject(obj); - QScriptValue func = sobj.property(propName); - return func; - } else { - const QmlMetaProperty &prop = resolveData.property; - - if (prop.needsChangedNotifier()) - capturedProperties << CapturedProperty(prop); - - int propType = prop.propertyType(); - if (propType < QVariant::UserType && valueTypes[propType]) { - QmlValueTypeReference ref; - ref.type = valueTypes[propType]; - ref.object = obj; - ref.property = prop.coreIndex(); - return scriptEngine.newObject(valueTypeClass, scriptEngine.newVariant(QVariant::fromValue(ref))); - } - - QVariant var = prop.read(); - QObject *varobj = (propType < QVariant::UserType)?0:QmlMetaType::toQObject(var); - if (!varobj) - varobj = qvariant_cast<QObject *>(var); - if (varobj) { - return objectClass->newQObject(varobj); - } else { - return qScriptValueFromValue(&scriptEngine, var); - } - } - - return QScriptValue(); -} - /*! \class QmlEngine \brief The QmlEngine class provides an environment for instantiating QML components. @@ -1039,6 +932,35 @@ QScriptValue QmlEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine) return qScriptValueFromValue(engine, qVariantFromValue(finalColor)); } + +QScriptValue QmlEnginePrivate::scriptValueFromVariant(const QVariant &val) +{ + if (QmlMetaType::isObject(val.userType())) { + QObject *rv = *(QObject **)val.constData(); + return objectClass->newQObject(rv); + } else { + return qScriptValueFromValue(&scriptEngine, val); + } +} + +QVariant QmlEnginePrivate::scriptValueToVariant(const QScriptValue &val) +{ + QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val); + if (dc == objectClass) + return QVariant::fromValue(objectClass->toQObject(val)); + else if (dc == contextClass) + return QVariant(); + + QScriptClass *sc = val.scriptClass(); + if (!sc) { + return val.toVariant(); + } else if (sc == valueTypeClass) { + return valueTypeClass->toVariant(val); + } else { + return QVariant(); + } +} + QmlScriptClass::QmlScriptClass(QmlEngine *bindengine) : QScriptClass(QmlEnginePrivate::getScriptEngine(bindengine)), engine(bindengine) @@ -1060,175 +982,13 @@ QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val) if (!sc) { return val.toVariant(); } else if (sc == ep->valueTypeClass) { - QmlValueTypeReference ref = - qvariant_cast<QmlValueTypeReference>(val.data().toVariant()); - - if (!ref.object) - return QVariant(); - - QMetaProperty p = ref.object->metaObject()->property(ref.property); - return p.read(ref.object); + return ep->valueTypeClass->toVariant(val); } return QVariant(); } ///////////////////////////////////////////////////////////// -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) -{ - Q_UNUSED(flags); - - 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); - if (!this->object) - return 0; - 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) -{ -} - -QmlValueTypeScriptClass::~QmlValueTypeScriptClass() -{ -} - -QmlValueTypeScriptClass::QueryFlags -QmlValueTypeScriptClass::queryProperty(const QScriptValue &object, - const QScriptString &name, - QueryFlags flags, uint *id) -{ - Q_UNUSED(flags); - QmlValueTypeReference ref = - qvariant_cast<QmlValueTypeReference>(object.data().toVariant()); - - if (!ref.object) - return 0; - - QByteArray propName = name.toString().toUtf8(); - - int idx = ref.type->metaObject()->indexOfProperty(propName.constData()); - if (idx == -1) - return 0; - *id = idx; - - QMetaProperty prop = ref.object->metaObject()->property(idx); - - QmlValueTypeScriptClass::QueryFlags rv = - QmlValueTypeScriptClass::HandlesReadAccess; - if (prop.isWritable()) - rv |= QmlValueTypeScriptClass::HandlesWriteAccess; - - return rv; -} - -QScriptValue QmlValueTypeScriptClass::property(const QScriptValue &object, - const QScriptString &name, - uint id) -{ - Q_UNUSED(name); - QmlValueTypeReference ref = - qvariant_cast<QmlValueTypeReference>(object.data().toVariant()); - - if (!ref.object) - return QScriptValue(); - - ref.type->read(ref.object, ref.property); - - QMetaProperty p = ref.type->metaObject()->property(id); - QVariant rv = p.read(ref.type); - - return static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine))->scriptEngine.newVariant(rv); -} - -void QmlValueTypeScriptClass::setProperty(QScriptValue &object, - const QScriptString &name, - uint id, - const QScriptValue &value) -{ - Q_UNUSED(name); - QmlValueTypeReference ref = - qvariant_cast<QmlValueTypeReference>(object.data().toVariant()); - - if (!ref.object) - return; - - QVariant v = QmlScriptClass::toVariant(engine, value); - - ref.type->read(ref.object, ref.property); - QMetaProperty p = ref.type->metaObject()->property(id); - p.write(ref.type, v); - ref.type->write(ref.object, ref.property); -} - struct QmlEnginePrivate::ImportedNamespace { QStringList urls; QList<int> majversions; @@ -1395,6 +1155,7 @@ public: int ref; private: + friend class QmlEnginePrivate::Imports; QmlEnginePrivate::ImportedNamespace unqualifiedset; QHash<QString,QmlEnginePrivate::ImportedNamespace* > set; }; @@ -1425,6 +1186,80 @@ QmlEnginePrivate::Imports::~Imports() delete d; } +#include <QtDeclarative/qmlmetatype.h> +#include <private/qmltypenamecache_p.h> +static QmlTypeNameCache *cacheForNamespace(QmlEngine *engine, const QmlEnginePrivate::ImportedNamespace &set, QmlTypeNameCache *cache) +{ + if (!cache) + cache = new QmlTypeNameCache(engine); + + QList<QmlType *> types = QmlMetaType::qmlTypes(); + + for (int ii = 0; ii < set.urls.count(); ++ii) { + if (!set.isBuiltin.at(ii)) + continue; + + QByteArray base = set.urls.at(ii).toUtf8() + "/"; + int major = set.majversions.at(ii); + int minor = set.minversions.at(ii); + + foreach (QmlType *type, types) { + if (type->qmlTypeName().startsWith(base) && + type->qmlTypeName().lastIndexOf('/') == (base.length() - 1) && + type->majorVersion() == major && type->minMinorVersion() <= minor && + type->maxMinorVersion() >= minor) { + + QString name = QString::fromUtf8(type->qmlTypeName().mid(base.length())); + + cache->add(name, type); + } + } + } + + return cache; +} + +QmlTypeNameCache *QmlEnginePrivate::Imports::cache(QmlEngine *engine) const +{ + const QmlEnginePrivate::ImportedNamespace &set = d->unqualifiedset; + + QmlTypeNameCache *cache = new QmlTypeNameCache(engine); + + for (QHash<QString,QmlEnginePrivate::ImportedNamespace* >::ConstIterator iter = d->set.begin(); + iter != d->set.end(); ++iter) { + + QmlTypeNameCache::Data *d = cache->data(iter.key()); + if (d) { + if (!d->typeNamespace) + cacheForNamespace(engine, *(*iter), d->typeNamespace); + } else { + QmlTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0); + cache->add(iter.key(), nc); + nc->release(); + } + } + + cacheForNamespace(engine, set, cache); + + return cache; +} + +/* +QStringList QmlEnginePrivate::Imports::unqualifiedSet() const +{ + QStringList rv; + + const QmlEnginePrivate::ImportedNamespace &set = d->unqualifiedset; + + for (int ii = 0; ii < set.urls.count(); ++ii) { + if (set.isBuiltin.at(ii)) + rv << set.urls.at(ii); + } + + return rv; +} +*/ + /*! Sets the base URL to be used for all relative file imports added. */ diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 231388d..7978023 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -75,6 +75,7 @@ #include <private/qmlpropertycache_p.h> #include <private/qmlobjectscriptclass_p.h> #include <private/qmlcontextscriptclass_p.h> +#include <private/qmlvaluetypescriptclass_p.h> QT_BEGIN_NAMESPACE @@ -92,6 +93,8 @@ class QNetworkReply; class QNetworkAccessManager; class QmlAbstractBinding; class QScriptDeclarativeClass; +class QmlTypeNameScriptClass; +class QmlTypeNameCache; class QmlEnginePrivate : public QObjectPrivate { @@ -102,13 +105,6 @@ public: void init(); - QScriptClass::QueryFlags queryObject(const QString &name, uint *id, - QObject *); - QScriptValue propertyObject(const QString &propName, QObject *, - uint id = 0); - void setPropertyObject(const QScriptValue &, uint id); - - struct CapturedProperty { CapturedProperty(QObject *o, int c, int n) : object(o), coreIndex(c), notifyIndex(n) {} @@ -128,25 +124,6 @@ public: #endif struct ImportedNamespace; - struct ResolveData { - ResolveData() : safetyCheckId(0) {} - int safetyCheckId; - - void clear() { - 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; - } resolveData; QmlContextScriptClass *contextClass; QmlObjectScriptClass *objectClass; QmlValueTypeScriptClass *valueTypeClass; @@ -211,9 +188,6 @@ public: } QmlValueTypeFactory valueTypes; - // ### Fixme - typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache; - FunctionCache functionCache; QHash<const QMetaObject *, QmlPropertyCache *> propertyCache; QmlPropertyCache *cache(QObject *obj) { @@ -228,6 +202,7 @@ public: return rv; } + // ### This whole class is embarrassing struct Imports { Imports(); ~Imports(); @@ -237,6 +212,8 @@ public: void setBaseUrl(const QUrl& url); QUrl baseUrl() const; + QmlTypeNameCache *cache(QmlEngine *) const; + private: friend class QmlEnginePrivate; QmlImportsPrivate *d; @@ -261,6 +238,9 @@ public: QHash<int, int> m_qmlLists; QHash<int, QmlCompiledData *> m_compositeTypes; + QScriptValue scriptValueFromVariant(const QVariant &); + QVariant scriptValueToVariant(const QScriptValue &); + static QScriptValue qmlScriptObject(QObject*, QmlEngine*); static QScriptValue createComponent(QScriptContext*, QScriptEngine*); static QScriptValue createQmlObject(QScriptContext*, QScriptEngine*); @@ -292,43 +272,6 @@ protected: QmlEngine *engine; }; -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: - QmlValueTypeScriptClass(QmlEngine *); - ~QmlValueTypeScriptClass(); - - virtual QueryFlags queryProperty(const QScriptValue &object, - const QScriptString &name, - QueryFlags flags, uint *id); - virtual QScriptValue property(const QScriptValue &object, - const QScriptString &name, - uint id); - virtual void setProperty(QScriptValue &object, - const QScriptString &name, - uint id, - const QScriptValue &value); -}; - QT_END_NAMESPACE #endif // QMLENGINE_P_H diff --git a/src/declarative/qml/qmlintegercache.cpp b/src/declarative/qml/qmlintegercache.cpp index 1bc4086..564faaa 100644 --- a/src/declarative/qml/qmlintegercache.cpp +++ b/src/declarative/qml/qmlintegercache.cpp @@ -62,9 +62,7 @@ void QmlIntegerCache::add(const QString &id, int value) QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); // ### use contextClass - QScriptDeclarativeClass::PersistentIdentifier<Data> *d = - enginePriv->objectClass->createPersistentIdentifier<Data>(id); - d->value = value; + Data *d = new Data(enginePriv->objectClass->createPersistentIdentifier(id), value); stringCache.insert(id, d); identifierCache.insert(d->identifier, d); diff --git a/src/declarative/qml/qmlintegercache_p.h b/src/declarative/qml/qmlintegercache_p.h index fda80c6..e11e0be 100644 --- a/src/declarative/qml/qmlintegercache_p.h +++ b/src/declarative/qml/qmlintegercache_p.h @@ -74,12 +74,15 @@ public: static QmlIntegerCache *createForEnums(QmlType *, QmlEngine *); private: - struct Data { + struct Data : public QScriptDeclarativeClass::PersistentIdentifier { + Data(const QScriptDeclarativeClass::PersistentIdentifier &i, int v) + : QScriptDeclarativeClass::PersistentIdentifier(i), value(v) {} + int value; }; - typedef QHash<QString, QScriptDeclarativeClass::PersistentIdentifier<Data> *> StringCache; - typedef QHash<QScriptDeclarativeClass::Identifier, QScriptDeclarativeClass::PersistentIdentifier<Data> *> IdentifierCache; + typedef QHash<QString, Data *> StringCache; + typedef QHash<QScriptDeclarativeClass::Identifier, Data *> IdentifierCache; StringCache stringCache; IdentifierCache identifierCache; diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index bb5f191..6a34a2f 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -64,14 +64,13 @@ QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine) QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(bindEngine); m_destroy = scriptEngine->newFunction(destroy); - m_destroyId = createPersistentIdentifier<Dummy>(QLatin1String("destroy")); + m_destroyId = createPersistentIdentifier(QLatin1String("destroy")); m_toString = scriptEngine->newFunction(tostring); - m_toStringId = createPersistentIdentifier<Dummy>(QLatin1String("toString")); + m_toStringId = createPersistentIdentifier(QLatin1String("toString")); } QmlObjectScriptClass::~QmlObjectScriptClass() { - delete m_destroyId; } QScriptValue QmlObjectScriptClass::newQObject(QObject *object) @@ -100,8 +99,8 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, Q_UNUSED(flags); lastData = 0; - if (name == m_destroyId->identifier || - name == m_toStringId->identifier) + if (name == m_destroyId.identifier || + name == m_toStringId.identifier) return QScriptClass::HandlesReadAccess; if (!obj) @@ -140,9 +139,9 @@ QScriptValue QmlObjectScriptClass::property(const Object &object, const Identifi QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name) { - if (name == m_destroyId->identifier) + if (name == m_destroyId.identifier) return m_destroy; - else if (name == m_toStringId->identifier) + else if (name == m_toStringId.identifier) return m_toString; Q_ASSERT(lastData); @@ -156,6 +155,11 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name QScriptValue sobj = scriptEngine->newQObject(obj); return sobj.property(toString(name)); } else { + if (lastData->propType < QVariant::UserType) { + QmlValueType *valueType = enginePriv->valueTypes[lastData->propType]; + if (valueType) + return enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType); + } QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) { @@ -167,7 +171,7 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name QObject *rv = *(QObject **)var.constData(); return newQObject(rv); } else { - return qScriptValueFromValue(scriptEngine, var); + return enginePriv->scriptValueFromVariant(var); } } @@ -250,5 +254,5 @@ QScriptValue QmlObjectScriptClass::destroy(QScriptContext *context, QScriptEngin return engine->nullValue(); } - QT_END_NAMESPACE + diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h index cd67fac..c86abdb 100644 --- a/src/declarative/qml/qmlobjectscriptclass_p.h +++ b/src/declarative/qml/qmlobjectscriptclass_p.h @@ -86,13 +86,11 @@ protected: virtual void destroyed(const Object &); private: - uint m_id; QmlPropertyCache::Data *lastData; QmlPropertyCache::Data local; - struct Dummy {}; - PersistentIdentifier<Dummy> *m_destroyId; - PersistentIdentifier<Dummy> *m_toStringId; + PersistentIdentifier m_destroyId; + PersistentIdentifier m_toStringId; QScriptValue m_destroy; QScriptValue m_toString; diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index cc4c2ab..d7b087b 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -155,8 +155,8 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject QMetaProperty p = metaObject->property(ii); QString propName = QLatin1String(p.name()); - QScriptDeclarativeClass::PersistentIdentifier<RData> *data = - enginePriv->objectClass->createPersistentIdentifier<RData>(propName); + RData *data = new RData; + data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName); data->load(p); @@ -166,7 +166,7 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject continue; cache->stringCache.insert(propName, data); - cache->identifierCache.insert(data->identifier, data); + cache->identifierCache.insert(data->identifier.identifier, data); data->addref(); data->addref(); } @@ -183,13 +183,13 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject if (cache->stringCache.contains(methodName)) continue; - QScriptDeclarativeClass::PersistentIdentifier<RData> *data = - enginePriv->objectClass->createPersistentIdentifier<RData>(methodName); + RData *data = new RData; + data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName); data->load(m); cache->stringCache.insert(methodName, data); - cache->identifierCache.insert(data->identifier, data); + cache->identifierCache.insert(data->identifier.identifier, data); data->addref(); data->addref(); } diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index 82b8737..f1b1219 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -113,11 +113,13 @@ public: Data *property(int) const; private: - struct RData : public Data, public QmlRefCount {}; + struct RData : public Data, public QmlRefCount { + QScriptDeclarativeClass::PersistentIdentifier identifier; + }; - typedef QVector<QScriptDeclarativeClass::PersistentIdentifier<RData> *> IndexCache; - typedef QHash<QString, QScriptDeclarativeClass::PersistentIdentifier<RData> *> StringCache; - typedef QHash<QScriptDeclarativeClass::Identifier, QScriptDeclarativeClass::PersistentIdentifier<RData> *> IdentifierCache; + typedef QVector<RData *> IndexCache; + typedef QHash<QString, RData *> StringCache; + typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache; IndexCache indexCache; StringCache stringCache; diff --git a/src/declarative/qml/qmltypenamecache.cpp b/src/declarative/qml/qmltypenamecache.cpp new file mode 100644 index 0000000..2b0f2c9 --- /dev/null +++ b/src/declarative/qml/qmltypenamecache.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmltypenamecache_p.h" + +QT_BEGIN_NAMESPACE + +QmlTypeNameCache::QmlTypeNameCache(QmlEngine *e) +: engine(e) +{ +} + +QmlTypeNameCache::~QmlTypeNameCache() +{ + qDeleteAll(stringCache); +} + +void QmlTypeNameCache::add(const QString &name, QmlType *type) +{ + if (stringCache.contains(name)) + return; + + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + + RData *data = new RData; + // ### Use typename class + data->identifier = ep->objectClass->createPersistentIdentifier(name); + data->type = type; + stringCache.insert(name, data); + identifierCache.insert(data->identifier.identifier, data); +} + +void QmlTypeNameCache::add(const QString &name, QmlTypeNameCache *typeNamespace) +{ + if (stringCache.contains(name)) + return; + + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + + RData *data = new RData; + // ### Use typename class + data->identifier = ep->objectClass->createPersistentIdentifier(name); + data->typeNamespace = typeNamespace; + stringCache.insert(name, data); + identifierCache.insert(data->identifier.identifier, data); + typeNamespace->addref(); +} + +QmlTypeNameCache::Data *QmlTypeNameCache::data(const QString &id) const +{ + return stringCache.value(id); +} + +QT_END_NAMESPACE + diff --git a/src/declarative/qml/qmltypenamecache_p.h b/src/declarative/qml/qmltypenamecache_p.h new file mode 100644 index 0000000..6022b43 --- /dev/null +++ b/src/declarative/qml/qmltypenamecache_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLTYPENAMECACHE_P_H +#define QMLTYPENAMECACHE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qmlrefcount_p.h> +#include <private/qscriptdeclarativeclass_p.h> +#include <private/qmlengine_p.h> + +QT_BEGIN_NAMESPACE + +class QmlType; +class QmlEngine; +class QmlTypeNameCache : public QmlRefCount +{ +public: + QmlTypeNameCache(QmlEngine *); + virtual ~QmlTypeNameCache(); + + struct Data { + inline Data(); + inline ~Data(); + QmlType *type; + QmlTypeNameCache *typeNamespace; + }; + + void add(const QString &, QmlType *); + void add(const QString &, QmlTypeNameCache *); + + Data *data(const QString &) const; + inline Data *data(const QScriptDeclarativeClass::Identifier &id) const; + +private: + struct RData : public Data { + QScriptDeclarativeClass::PersistentIdentifier identifier; + }; + typedef QHash<QString, RData *> StringCache; + typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache; + + StringCache stringCache; + IdentifierCache identifierCache; + QmlEngine *engine; +}; + +QmlTypeNameCache::Data::Data() +: type(0), typeNamespace(0) +{ +} + +QmlTypeNameCache::Data::~Data() +{ + if (typeNamespace) typeNamespace->release(); +} + +QmlTypeNameCache::Data *QmlTypeNameCache::data(const QScriptDeclarativeClass::Identifier &id) const +{ + return identifierCache.value(id); +} + +QT_END_NAMESPACE + +#endif // QMLTYPENAMECACHE_P_H + diff --git a/src/declarative/qml/qmltypenamescriptclass.cpp b/src/declarative/qml/qmltypenamescriptclass.cpp new file mode 100644 index 0000000..29e2978 --- /dev/null +++ b/src/declarative/qml/qmltypenamescriptclass.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmltypenamescriptclass_p.h" +#include <private/qmlengine_p.h> +#include <private/qmltypenamecache_p.h> + +QT_BEGIN_NAMESPACE + +struct TypeNameData { + TypeNameData(QObject *o, QmlType *t) : object(o), type(t), typeNamespace(0) {} + TypeNameData(QObject *o, QmlTypeNameCache *n) : object(o), type(0), typeNamespace(n) { + if (typeNamespace) typeNamespace->addref(); + } + ~TypeNameData() { + if (typeNamespace) typeNamespace->release(); + } + + QObject *object; + QmlType *type; + QmlTypeNameCache *typeNamespace; +}; + +QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *bindEngine) +: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), + engine(bindEngine), object(0), type(0) +{ +} + +QmlTypeNameScriptClass::~QmlTypeNameScriptClass() +{ +} + +QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlType *type) +{ + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + + return QScriptDeclarativeClass::newObject(scriptEngine, this, (Object)new TypeNameData(object, type)); +} + +QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlTypeNameCache *ns) +{ + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + + return QScriptDeclarativeClass::newObject(scriptEngine, this, (Object)new TypeNameData(object, ns)); +} + + +QScriptClass::QueryFlags +QmlTypeNameScriptClass::queryProperty(const Object &obj, const Identifier &name, + QScriptClass::QueryFlags flags) +{ + Q_UNUSED(flags); + + TypeNameData *data = (TypeNameData *)obj; + + object = 0; + type = 0; + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + + if (data->typeNamespace) { + + QmlTypeNameCache::Data *d = data->typeNamespace->data(name); + if (d && d->type) { + type = d->type; + return QScriptClass::HandlesReadAccess; + } else { + return 0; + } + + } else { + Q_ASSERT(data->type); + + QString strName = toString(name); + + if (strName.at(0).isUpper()) { + // Must be an enum + // ### Optimize + const char *enumName = strName.toUtf8().constData(); + const QMetaObject *metaObject = data->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 QScriptClass::HandlesReadAccess; + } + } + return 0; + } else { + // Must be an attached property + object = qmlAttachedPropertiesObjectById(data->type->index(), data->object); + if (!object) return 0; + return ep->objectClass->queryProperty(object, name, flags); + } + } +} + +QScriptValue QmlTypeNameScriptClass::property(const Object &obj, const Identifier &name) +{ + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + if (type) { + return newObject(object, type); + } else if (object) { + return ep->objectClass->property(((TypeNameData *)obj)->object, name); + } else { + return QScriptValue(enumValue); + } +} + +void QmlTypeNameScriptClass::setProperty(const Object &o, const Identifier &n, const QScriptValue &v) +{ + Q_ASSERT(object); + Q_ASSERT(!type); + + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + ep->objectClass->setProperty(((TypeNameData *)o)->object, n, v); +} + +QT_END_NAMESPACE + diff --git a/src/declarative/qml/qmltypenamescriptclass_p.h b/src/declarative/qml/qmltypenamescriptclass_p.h new file mode 100644 index 0000000..c642ea4 --- /dev/null +++ b/src/declarative/qml/qmltypenamescriptclass_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLTYPENAMESCRIPTCLASS_P_H +#define QMLTYPENAMESCRIPTCLASS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +#include <QtScript/qscriptclass.h> +#include <private/qscriptdeclarativeclass_p.h> +#include <private/qmlengine_p.h> + +QT_BEGIN_NAMESPACE + +class QmlEngine; +class QmlType; +class QmlTypeNameCache; +class QmlTypeNameScriptClass : public QScriptDeclarativeClass +{ +public: + QmlTypeNameScriptClass(QmlEngine *); + ~QmlTypeNameScriptClass(); + + QScriptValue newObject(QObject *, QmlType *); + QScriptValue newObject(QObject *, QmlTypeNameCache *); + +protected: + virtual QScriptClass::QueryFlags queryProperty(const Object &, const Identifier &, + QScriptClass::QueryFlags flags); + + virtual QScriptValue property(const Object &, const Identifier &); + virtual void setProperty(const Object &, const Identifier &name, const QScriptValue &); + +private: + QmlEngine *engine; + QObject *object; + QmlType *type; + quint32 enumValue; +}; + +QT_END_NAMESPACE + +#endif // QMLTYPENAMESCRIPTCLASS_P_H + diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp new file mode 100644 index 0000000..da6c73d --- /dev/null +++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlvaluetypescriptclass_p.h" +#include <private/qmlengine_p.h> + +QT_BEGIN_NAMESPACE + +struct QmlValueTypeReference { + QmlValueType *type; + QGuard<QObject> object; + int property; +}; +Q_DECLARE_METATYPE(QmlValueTypeReference); + +QmlValueTypeScriptClass::QmlValueTypeScriptClass(QmlEngine *bindEngine) +: QScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine) +{ +} + +QmlValueTypeScriptClass::~QmlValueTypeScriptClass() +{ +} + +QScriptValue QmlValueTypeScriptClass::newObject(QObject *object, int coreIndex, QmlValueType *type) +{ + QmlValueTypeReference ref = { type, object, coreIndex }; + return QScriptValue(); +} + +QmlValueTypeScriptClass::QueryFlags +QmlValueTypeScriptClass::queryProperty(const QScriptValue &object, + const QScriptString &name, + QueryFlags flags, uint *id) +{ + Q_UNUSED(flags); + QmlValueTypeReference ref = + qvariant_cast<QmlValueTypeReference>(object.data().toVariant()); + + if (!ref.object) + return 0; + + QByteArray propName = name.toString().toUtf8(); + + int idx = ref.type->metaObject()->indexOfProperty(propName.constData()); + if (idx == -1) + return 0; + *id = idx; + + QMetaProperty prop = ref.object->metaObject()->property(idx); + + QmlValueTypeScriptClass::QueryFlags rv = + QmlValueTypeScriptClass::HandlesReadAccess; + if (prop.isWritable()) + rv |= QmlValueTypeScriptClass::HandlesWriteAccess; + + return rv; +} + +QScriptValue QmlValueTypeScriptClass::property(const QScriptValue &object, + const QScriptString &name, + uint id) +{ + Q_UNUSED(name); + QmlValueTypeReference ref = + qvariant_cast<QmlValueTypeReference>(object.data().toVariant()); + + if (!ref.object) + return QScriptValue(); + + ref.type->read(ref.object, ref.property); + + QMetaProperty p = ref.type->metaObject()->property(id); + QVariant rv = p.read(ref.type); + + return static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine))->scriptEngine.newVariant(rv); +} + +void QmlValueTypeScriptClass::setProperty(QScriptValue &object, + const QScriptString &name, + uint id, + const QScriptValue &value) +{ + Q_UNUSED(name); + QmlValueTypeReference ref = + qvariant_cast<QmlValueTypeReference>(object.data().toVariant()); + + if (!ref.object) + return; + + QVariant v = QmlScriptClass::toVariant(engine, value); + + ref.type->read(ref.object, ref.property); + QMetaProperty p = ref.type->metaObject()->property(id); + p.write(ref.type, v); + ref.type->write(ref.object, ref.property); +} + +QVariant QmlValueTypeScriptClass::toVariant(const QScriptValue &val) +{ + QmlValueTypeReference ref = + qvariant_cast<QmlValueTypeReference>(val.data().toVariant()); + + if (!ref.object) + return QVariant(); + + QMetaProperty p = ref.object->metaObject()->property(ref.property); + return p.read(ref.object); +} + +QT_END_NAMESPACE + diff --git a/src/declarative/qml/qmlvaluetypescriptclass_p.h b/src/declarative/qml/qmlvaluetypescriptclass_p.h new file mode 100644 index 0000000..d656a22 --- /dev/null +++ b/src/declarative/qml/qmlvaluetypescriptclass_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLVALUETYPESCRIPTCLASS_P_H +#define QMLVALUETYPESCRIPTCLASS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +#include <QtScript/qscriptclass.h> +#include <private/qscriptdeclarativeclass_p.h> + +QT_BEGIN_NAMESPACE + +class QmlEngine; +class QmlValueType; +class QmlValueTypeScriptClass : public QScriptClass +{ +public: + QmlValueTypeScriptClass(QmlEngine *); + ~QmlValueTypeScriptClass(); + + QScriptValue newObject(QObject *object, int coreIndex, QmlValueType *); + + virtual QueryFlags queryProperty(const QScriptValue &object, + const QScriptString &name, + QueryFlags flags, uint *id); + virtual QScriptValue property(const QScriptValue &object, + const QScriptString &name, + uint id); + virtual void setProperty(QScriptValue &object, + const QScriptString &name, + uint id, + const QScriptValue &value); + + QVariant toVariant(const QScriptValue &); +private: + QmlEngine *engine; +}; + +QT_END_NAMESPACE + +#endif // QMLVALUETYPESCRIPTCLASS_P_H + diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp index de2128d..2031a54 100644 --- a/src/declarative/util/qmlscript.cpp +++ b/src/declarative/util/qmlscript.cpp @@ -179,10 +179,14 @@ void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &s QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QScriptContext *scriptContext = scriptEngine->pushContext(); - for (int i = context->d_func()->scopeChain.size() - 1; i > -1; --i) { + for (int i = context->d_func()->scopeChain.size() - 1; i >= 0; --i) { scriptContext->pushScope(context->d_func()->scopeChain.at(i)); } - scriptContext->setActivationObject(context->d_func()->scopeChain.at(0)); + + QScriptValue scope = scriptEngine->newObject(); + scriptContext->pushScope(scope); + + scriptContext->setActivationObject(scope); QScriptValue val = scriptEngine->evaluate(script, source); if (scriptEngine->hasUncaughtException()) { @@ -200,6 +204,8 @@ void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &s } scriptEngine->popContext(); + + context->d_func()->scripts.append(scope); } QT_END_NAMESPACE |