summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/qml/qmlengine.cpp183
-rw-r--r--src/declarative/qml/qmlengine_p.h21
2 files changed, 123 insertions, 81 deletions
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 9a5efdb..124c8f3 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -208,16 +208,101 @@ QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p)
typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache;
Q_GLOBAL_STATIC(FunctionCache, functionCache);
+QScriptClass::QueryFlags
+QmlEnginePrivate::queryContext(const QString &propName, uint *id,
+ QmlContext *bindContext)
+{
+ resolveData.safetyCheckId++;
+ *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;
+ }
+
+ for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) {
+ rv = queryObject(propName, id,
+ bindContext->d_func()->defaultObjects.at(ii));
+ }
+
+ return rv;
+}
+
+QScriptValue
+QmlEnginePrivate::propertyContext(const QScriptString &name,
+ QmlContext *bindContext,
+ uint id)
+{
+ Q_ASSERT(id == resolveData.safetyCheckId);
+
+
+ if (resolveData.context) {
+ QmlContext *bindContext = resolveData.context;
+ QmlContextPrivate *contextPrivate = bindContext->d_func();
+ int index = resolveData.contextIndex;
+
+ QScriptValue rv;
+ if (index < contextPrivate->idValueCount) {
+ rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(contextPrivate->idValues[index].data())));
+ } else {
+ QVariant value = contextPrivate->propertyValues.at(index);
+ if (QmlMetaType::isObject(value.userType())) {
+ rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(value));
+ } else {
+ rv = scriptEngine.newVariant(value);
+ }
+ }
+ capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, -1, index + contextPrivate->notifyIndex);
+ return rv;
+
+ } else {
+
+ return propertyObject(name, resolveData.object, id);
+
+ }
+
+ return QScriptValue();
+}
+
+void QmlEnginePrivate::setPropertyContext(const QScriptValue &value, uint id)
+{
+ // As context properties cannot be written, we can assume that the
+ // write is a object property write
+ setPropertyObject(value, id);
+}
+
+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);
@@ -232,12 +317,13 @@ QmlEnginePrivate::queryObject(const QString &propName,
}
if (isFunction) {
- *id = QmlScriptClass::FunctionId;
+ resolveData.object = obj;
+ resolveData.isFunction = true;
rv |= QScriptClass::HandlesReadAccess;
- }
+ }
} else {
- *id = QmlScriptClass::PropertyId;
- *id |= prop.save();
+ resolveData.object = obj;
+ resolveData.property = prop;
rv |= QScriptClass::HandlesReadAccess;
if (prop.isWritable())
@@ -257,15 +343,16 @@ Q_DECLARE_METATYPE(QmlValueTypeReference);
QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName,
QObject *obj, uint id)
{
- if (id == QmlScriptClass::FunctionId) {
+ 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 {
- QmlMetaProperty prop;
- prop.restore(id, obj);
- if (!prop.isValid())
- return QScriptValue();
+ const QmlMetaProperty &prop = resolveData.property;
if (prop.needsChangedNotifier())
capturedProperties << CapturedProperty(prop);
@@ -856,23 +943,11 @@ QmlContextScriptClass::queryProperty(const QScriptValue &object,
Q_UNUSED(flags);
QmlContext *bindContext =
static_cast<QmlContext*>(object.data().toQObject());
- QueryFlags rv = 0;
QString propName = name.toString();
- *id = InvalidId;
- if (bindContext->d_func()->propertyNames.contains(propName)) {
- rv |= HandlesReadAccess;
- *id = VariantPropertyId;
- }
-
- for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) {
- rv = QmlEnginePrivate::get(engine)->queryObject(propName, id, bindContext->d_func()->defaultObjects.at(ii));
- if (rv)
- *id |= (ii << 24);
- }
-
- return rv;
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ return ep->queryContext(propName, id, bindContext);
}
QScriptValue QmlContextScriptClass::property(const QScriptValue &object,
@@ -882,46 +957,8 @@ QScriptValue QmlContextScriptClass::property(const QScriptValue &object,
QmlContext *bindContext =
static_cast<QmlContext*>(object.data().toQObject());
- uint basicId = id & QmlScriptClass::ClassIdMask;
-
- QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
-
- switch (basicId) {
- case VariantPropertyId:
- {
- QmlContextPrivate *contextPrivate = bindContext->d_func();
- QString propName = name.toString();
- int index = contextPrivate->propertyNames.value(propName);
-
- QScriptValue rv;
- if (index < contextPrivate->idValueCount) {
- rv = scriptEngine->newObject(ep->objectClass, scriptEngine->newVariant(QVariant::fromValue(contextPrivate->idValues[index].data())));
- } else {
- QVariant value = contextPrivate->propertyValues.at(index);
- if (QmlMetaType::isObject(value.userType())) {
- rv = scriptEngine->newObject(ep->objectClass, scriptEngine->newVariant(value));
- } else {
- rv = scriptEngine->newVariant(value);
- }
- }
- ep->capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, -1, index + bindContext->d_func()->notifyIndex);
- return rv;
- }
- default:
- {
- int objId = (id & ClassIdSelectorMask) >> 24;
- QObject *obj = bindContext->d_func()->defaultObjects.at(objId);
- QScriptValue rv = ep->propertyObject(name, obj,
- id & ~QmlScriptClass::ClassIdSelectorMask);
- if (rv.isValid()) {
- return rv;
- }
- break;
- }
- }
-
- return QScriptValue();
+ return ep->propertyContext(name, bindContext, id);
}
void QmlContextScriptClass::setProperty(QScriptValue &object,
@@ -931,17 +968,7 @@ void QmlContextScriptClass::setProperty(QScriptValue &object,
{
Q_UNUSED(name);
- QmlContext *bindContext =
- static_cast<QmlContext*>(object.data().toQObject());
-
- int objIdx = (id & QmlScriptClass::ClassIdSelectorMask) >> 24;
- QObject *obj = bindContext->d_func()->defaultObjects.at(objIdx);
-
- QmlMetaProperty prop;
- prop.restore(id, obj);
-
- QVariant v = QmlScriptClass::toVariant(engine, value);
- prop.write(v);
+ QmlEnginePrivate::get(engine)->setPropertyContext(value, id);
}
/////////////////////////////////////////////////////////////
@@ -1119,14 +1146,8 @@ void QmlObjectScriptClass::setProperty(QScriptValue &object,
const QScriptValue &value)
{
Q_UNUSED(name);
-
- QObject *obj = object.data().toQObject();
-
- QmlMetaProperty prop;
- prop.restore(id, obj);
-
- QVariant v = QmlScriptClass::toVariant(engine, value);
- prop.write(v);
+ Q_UNUSED(object);
+ QmlEnginePrivate::get(engine)->setPropertyObject(value, id);
}
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index b595e7c..2c7409b 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -97,10 +97,17 @@ public:
void init();
+ QScriptClass::QueryFlags queryContext(const QString &name, uint *id,
+ QmlContext *);
+ QScriptValue propertyContext(const QScriptString &propName, QmlContext *,
+ uint id);
+ void setPropertyContext(const QScriptValue &, uint id);
QScriptClass::QueryFlags queryObject(const QString &name, uint *id,
QObject *);
QScriptValue propertyObject(const QScriptString &propName, QObject *,
uint id = 0);
+ void setPropertyObject(const QScriptValue &, uint id);
+
struct CapturedProperty {
CapturedProperty(QObject *o, int c, int n)
@@ -120,6 +127,20 @@ public:
QScriptEngineDebugger *debugger;
#endif
+ struct ResolveData {
+ ResolveData() : safetyCheckId(0) {}
+ int safetyCheckId;
+
+ void clear() {
+ object = 0; context = 0; contextIndex = -1; isFunction = false;
+ }
+ QObject *object;
+ QmlContext *context;
+
+ int contextIndex;
+ bool isFunction;
+ QmlMetaProperty property;
+ } resolveData;
QmlContextScriptClass *contextClass;
QmlObjectScriptClass *objectClass;
QmlValueTypeScriptClass *valueTypeClass;