summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-05-11 05:15:16 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-05-11 06:35:01 (GMT)
commit3f85913faf5694e4a0ebd612921e4eeeb4fc9e25 (patch)
tree339cf55530a27d136a3801f30ed0e7d559188bfb /src
parent010dae33653c76359e857aadfbdfeb4841c01d2f (diff)
downloadQt-3f85913faf5694e4a0ebd612921e4eeeb4fc9e25.zip
Qt-3f85913faf5694e4a0ebd612921e4eeeb4fc9e25.tar.gz
Qt-3f85913faf5694e4a0ebd612921e4eeeb4fc9e25.tar.bz2
Reevaluate expressions when context properties change
Diffstat (limited to 'src')
-rw-r--r--src/declarative/qml/qmlcontext.cpp64
-rw-r--r--src/declarative/qml/qmlcontext_p.h6
-rw-r--r--src/declarative/qml/qmlengine.cpp89
-rw-r--r--src/declarative/qml/qmlengine_p.h13
-rw-r--r--src/declarative/qml/script/qmlbasicscript.cpp19
-rw-r--r--src/declarative/qml/script/qmlbasicscript_p.h8
6 files changed, 129 insertions, 70 deletions
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index df5f90e..91bf1c0 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -44,6 +44,7 @@
#include <private/qmlengine_p.h>
#include <qmlengine.h>
#include <qscriptengine.h>
+#include <QtCore/qvarlengtharray.h>
#include <qdebug.h>
@@ -53,7 +54,8 @@
QT_BEGIN_NAMESPACE
QmlContextPrivate::QmlContextPrivate()
- : parent(0), engine(0), highPriorityCount(0), startLine(-1), endLine(-1)
+: parent(0), engine(0), notifyIndex(-1), highPriorityCount(0),
+ startLine(-1), endLine(-1)
{
}
@@ -65,21 +67,26 @@ void QmlContextPrivate::dump()
void QmlContextPrivate::dump(int depth)
{
QByteArray ba(depth * 4, ' ');
- qWarning() << ba << properties.keys();
- qWarning() << ba << variantProperties.keys();
if (parent)
parent->d_func()->dump(depth + 1);
}
void QmlContextPrivate::destroyed(QObject *obj)
{
+ Q_Q(QmlContext);
+
defaultObjects.removeAll(obj);
- for (QHash<QString, QObject *>::Iterator iter = properties.begin();
- iter != properties.end(); ) {
- if (*iter == obj)
- iter = properties.erase(iter);
- else
- ++iter;
+
+ QVariant variantObject = QVariant::fromValue(obj);
+ QVarLengthArray<int> notifies;
+ for (int ii = 0; ii < propertyValues.count(); ++ii) {
+ if (propertyValues.at(ii) == variantObject) {
+ propertyValues[ii] = QVariant();
+ notifies.append(ii);
+ }
+ }
+ for (int ii = 0; ii < notifies.count(); ++ii) {
+ QMetaObject::activate(q, notifies[ii] + notifyIndex, 0);
}
}
@@ -314,7 +321,22 @@ void QmlContext::addDefaultObject(QObject *object)
void QmlContext::setContextProperty(const QString &name, const QVariant &value)
{
Q_D(QmlContext);
- d->variantProperties.insert(name, value);
+ if (d->notifyIndex == -1)
+ d->notifyIndex = this->metaObject()->methodCount();
+
+ if (QmlMetaType::isObject(value.userType())) {
+ QObject *o = QmlMetaType::toQObject(value);
+ setContextProperty(name, o);
+ } else {
+ QHash<QString, int>::ConstIterator iter = d->propertyNames.find(name);
+ if(iter == d->propertyNames.end()) {
+ d->propertyNames.insert(name, d->propertyValues.count());
+ d->propertyValues.append(value);
+ } else {
+ d->propertyValues[*iter] = value;
+ QMetaObject::activate(this, *iter + d->notifyIndex, 0);
+ }
+ }
}
/*!
@@ -325,8 +347,26 @@ void QmlContext::setContextProperty(const QString &name, const QVariant &value)
void QmlContext::setContextProperty(const QString &name, QObject *value)
{
Q_D(QmlContext);
- d->properties.insert(name, value);
- QObject::connect(value, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+ if (d->notifyIndex == -1)
+ d->notifyIndex = this->metaObject()->methodCount();
+
+ QObject::connect(value, SIGNAL(destroyed(QObject*)),
+ this, SLOT(objectDestroyed(QObject*)));
+
+ QHash<QString, int>::ConstIterator iter = d->propertyNames.find(name);
+ if(iter == d->propertyNames.end()) {
+ d->propertyNames.insert(name, d->propertyValues.count());
+ d->propertyValues.append(QVariant::fromValue(value));
+ } else {
+ int idx = *iter;
+ if (QmlMetaType::isObject(d->propertyValues.at(idx).userType())) {
+ QObject *old = QmlMetaType::toQObject(d->propertyValues.at(idx));
+ QObject::disconnect(old, SIGNAL(destroyed(QObject*)),
+ this, SLOT(objectDestroyed(QObject*)));
+ }
+ d->propertyValues[*iter] = QVariant::fromValue(value);
+ QMetaObject::activate(this, *iter + d->notifyIndex, 0);
+ }
}
/*!
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
index f527bb8..6f1e486 100644
--- a/src/declarative/qml/qmlcontext_p.h
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -64,8 +64,10 @@ public:
QmlContext *parent;
QmlEngine *engine;
- QHash<QString, QObject *> properties;
- QHash<QString, QVariant> variantProperties;
+
+ QHash<QString, int> propertyNames;
+ QList<QVariant> propertyValues;
+ int notifyIndex;
QObjectList defaultObjects;
int highPriorityCount;
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index c39a0d5..fb4cedf 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -211,6 +211,30 @@ QmlContext *QmlEnginePrivate::setCurrentBindContext(QmlContext *c)
return old;
}
+QmlEnginePrivate::CapturedProperty::CapturedProperty(QObject *obj, int n)
+: object(obj), notifyIndex(n)
+{
+}
+
+QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p)
+: object(p.object()), name(p.name()), notifyIndex(p.property().notifySignalIndex())
+{
+}
+
+QmlEnginePrivate::CapturedProperty::CapturedProperty(const CapturedProperty &o)
+: object(o.object), name(o.name), notifyIndex(o.notifyIndex)
+{
+}
+
+QmlEnginePrivate::CapturedProperty &
+QmlEnginePrivate::CapturedProperty::operator=(const CapturedProperty &o)
+{
+ object = o.object;
+ name = o.name;
+ notifyIndex = o.notifyIndex;
+ return *this;
+}
+
////////////////////////////////////////////////////////////////////
typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache;
Q_GLOBAL_STATIC(FunctionCache, functionCache);
@@ -268,7 +292,8 @@ QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName,
return scriptEngine.newVariant(qVariantFromValue(prop));
} else {
QVariant var = prop.read();
- capturedProperties << prop;
+ if (prop.needsChangedNotifier())
+ capturedProperties << CapturedProperty(prop);
QObject *varobj = QmlMetaType::toQObject(var);
if (!varobj)
varobj = qvariant_cast<QObject *>(var);
@@ -318,7 +343,8 @@ bool QmlEnginePrivate::fetchCache(QmlBasicScriptNodeCache &cache, const QString
if (!prop.isValid())
return false;
- capturedProperties << prop;
+ if (prop.needsChangedNotifier())
+ capturedProperties << CapturedProperty(prop);
if (prop.type() & QmlMetaProperty::Attached) {
@@ -357,16 +383,15 @@ bool QmlEnginePrivate::fetchCache(QmlBasicScriptNodeCache &cache, const QString
bool QmlEnginePrivate::loadCache(QmlBasicScriptNodeCache &cache, const QString &propName, QmlContextPrivate *context)
{
while(context) {
- if (context->variantProperties.contains(propName)) {
+
+ QHash<QString, int>::ConstIterator iter =
+ context->propertyNames.find(propName);
+ if (iter != context->propertyNames.end()) {
cache.object = 0;
cache.type = QmlBasicScriptNodeCache::Variant;
cache.context = context;
- return true;
- }
-
- if (context->properties.contains(propName)) {
- cache.object = context->properties[propName];
- cache.type = QmlBasicScriptNodeCache::Explicit;
+ cache.contextIndex = *iter;
+ capturedProperties << CapturedProperty(context->q_ptr, *iter + context->notifyIndex);
return true;
}
@@ -1045,13 +1070,14 @@ QVariant QmlExpression::value()
log.setResult(rv);
for (int ii = 0; ii < ep->capturedProperties.count(); ++ii) {
- const QmlMetaProperty &prop =
+ const QmlEnginePrivate::CapturedProperty &prop =
ep->capturedProperties.at(ii);
- if (prop.hasChangedNotifier()) {
- prop.connectNotifier(d->proxy, changedIndex);
- } else if (prop.needsChangedNotifier()) {
- QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: [") + QLatin1String(prop.object()->metaObject()->className()) + QLatin1String("].") + prop.name();
+ if (prop.notifyIndex != -1) {
+ QMetaObject::connect(prop.object, prop.notifyIndex,
+ d->proxy, changedIndex);
+ } else {
+ QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: [") + QLatin1String(prop.object->metaObject()->className()) + QLatin1String("].") + prop.name;
log.addWarning(warn);
}
}
@@ -1059,11 +1085,12 @@ QVariant QmlExpression::value()
} else {
for (int ii = 0; ii < ep->capturedProperties.count(); ++ii) {
- const QmlMetaProperty &prop =
+ const QmlEnginePrivate::CapturedProperty &prop =
ep->capturedProperties.at(ii);
- if (prop.hasChangedNotifier())
- prop.connectNotifier(d->proxy, changedIndex);
+ if (prop.notifyIndex != -1)
+ QMetaObject::connect(prop.object, prop.notifyIndex,
+ d->proxy, changedIndex);
}
}
} else {
@@ -1254,13 +1281,10 @@ QmlContextScriptClass::queryProperty(const QScriptValue &object,
#endif
*id = InvalidId;
- if (bindContext->d_func()->variantProperties.contains(propName)) {
+ if (bindContext->d_func()->propertyNames.contains(propName)) {
rv |= HandlesReadAccess;
*id = VariantPropertyId;
- } else if (bindContext->d_func()->properties.contains(propName)) {
- rv |= HandlesReadAccess;
- *id = ObjectListPropertyId;
- }
+ }
for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) {
rv = engine->d_func()->queryObject(propName, id,
@@ -1295,22 +1319,19 @@ QScriptValue QmlContextScriptClass::property(const QScriptValue &object,
case VariantPropertyId:
{
QString propName = name.toString();
- QScriptValue rv = scriptEngine->newVariant(bindContext->d_func()->variantProperties[propName]);
+ int index = bindContext->d_func()->propertyNames.value(propName);
+ QVariant value = bindContext->d_func()->propertyValues.at(index);
#ifdef PROPERTY_DEBUG
qWarning() << "Context Property: Resolved property" << propName
<< "to context variant property list" << bindContext <<". Value:" << rv.toVariant();
#endif
- return rv;
- }
- case ObjectListPropertyId:
- {
- QString propName = name.toString();
- QObject *o = bindContext->d_func()->properties[propName];
- QScriptValue rv = scriptEngine->newObject(engine->d_func()->objectClass, scriptEngine->newVariant(QVariant::fromValue(o)));
-#ifdef PROPERTY_DEBUG
- qWarning() << "Context Property: Resolved property" << propName
- << "to context object property list" << bindContext <<". Value:" << rv.toVariant();
-#endif
+ QScriptValue rv;
+ if (QmlMetaType::isObject(value.userType())) {
+ rv = scriptEngine->newObject(engine->d_func()->objectClass, scriptEngine->newVariant(value));
+ } else {
+ rv = scriptEngine->newVariant(value);
+ }
+ engine->d_func()->capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, index + bindContext->d_func()->notifyIndex);
return rv;
}
default:
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 9402fa9..7578fdf 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -89,7 +89,17 @@ public:
QScriptClass::QueryFlags queryObject(const QString &name, uint *id, QObject *);
QScriptValue propertyObject(const QScriptString &propName, QObject *, uint id = 0);
- QList<QmlMetaProperty> capturedProperties;
+ struct CapturedProperty {
+ CapturedProperty(QObject *, int);
+ CapturedProperty(const QmlMetaProperty &);
+ CapturedProperty(const CapturedProperty &);
+ CapturedProperty &operator=(const CapturedProperty &);
+
+ QObject *object;
+ QString name;
+ int notifyIndex;
+ };
+ QList<CapturedProperty> capturedProperties;
QmlContext *rootContext;
QmlContext *currentBindContext;
@@ -172,7 +182,6 @@ public:
{
InvalidId = -1,
- ObjectListPropertyId = 0xC0000000,
FunctionId = 0x80000000,
VariantPropertyId = 0x40000000,
PropertyId = 0x00000000,
diff --git a/src/declarative/qml/script/qmlbasicscript.cpp b/src/declarative/qml/script/qmlbasicscript.cpp
index 129db7e..e0a668a 100644
--- a/src/declarative/qml/script/qmlbasicscript.cpp
+++ b/src/declarative/qml/script/qmlbasicscript.cpp
@@ -72,15 +72,9 @@ QDebug operator<<(QDebug lhs, const QmlBasicScriptNodeCache &rhs)
case QmlBasicScriptNodeCache::SignalProperty:
lhs << "SignalProperty" << rhs.object << rhs.core;
break;
- case QmlBasicScriptNodeCache::Explicit:
- lhs << "Explicit" << rhs.object;
- break;
case QmlBasicScriptNodeCache::Variant:
lhs << "Variant" << rhs.context;
break;
- case QmlBasicScriptNodeCache::ScriptValue:
- lhs << "ScriptValue" << rhs.context;
- break;
}
return lhs;
@@ -210,15 +204,8 @@ QVariant QmlBasicScriptNodeCache::value(const char *name) const
break;
case SignalProperty:
break;
- case Explicit:
- return qVariantFromValue(object);
- break;
case Variant:
- return toObjectOrVariant(context->variantProperties[QLatin1String(name)]);
- break;
- case ScriptValue:
- return qVariantFromValue(context->properties[QLatin1String(name)]);
- break;
+ return context->propertyValues[contextIndex];
};
return QVariant();
}
@@ -705,7 +692,7 @@ void QmlBasicScript::clearCache(void *voidCache)
reinterpret_cast<QmlBasicScriptNodeCache *>(voidCache);
for (int ii = 0; ii < d->stateSize; ++ii) {
- if (!dataCache[ii].isCore() && !dataCache[ii].isExplicit() &&
+ if (!dataCache[ii].isCore() && !dataCache[ii].isVariant() &&
dataCache[ii].object) {
QMetaObject::removeGuard(&dataCache[ii].object);
dataCache[ii].object = 0;
@@ -717,7 +704,7 @@ void QmlBasicScript::clearCache(void *voidCache)
void QmlBasicScript::guard(QmlBasicScriptNodeCache &n)
{
if (n.object) {
- if (n.isExplicit()) {
+ if (n.isVariant()) {
} else if (n.isCore()) {
n.metaObject =
n.object->metaObject();
diff --git a/src/declarative/qml/script/qmlbasicscript_p.h b/src/declarative/qml/script/qmlbasicscript_p.h
index fb9951e..3b7e966 100644
--- a/src/declarative/qml/script/qmlbasicscript_p.h
+++ b/src/declarative/qml/script/qmlbasicscript_p.h
@@ -29,19 +29,19 @@ public:
Attached,
Signal,
SignalProperty,
- Explicit,
- Variant,
- ScriptValue } type;
+ Variant
+ } type;
union {
int core;
QObject *attached;
QmlContextPrivate *context;
};
int coreType;
+ int contextIndex;
bool isValid() const { return type != Invalid; }
bool isCore() const { return type == Core; }
- bool isExplicit() const { return type == Explicit; }
+ bool isVariant() const { return type == Variant; }
void clear();
QVariant value(const char *) const;
};