diff options
Diffstat (limited to 'src/declarative')
-rw-r--r-- | src/declarative/qml/qmlcontext.cpp | 64 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext_p.h | 6 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine.cpp | 89 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine_p.h | 13 | ||||
-rw-r--r-- | src/declarative/qml/script/qmlbasicscript.cpp | 19 | ||||
-rw-r--r-- | src/declarative/qml/script/qmlbasicscript_p.h | 8 |
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; }; |