diff options
55 files changed, 808 insertions, 848 deletions
diff --git a/src/corelib/kernel/qguard.cpp b/src/corelib/kernel/qguard.cpp index c61be00..ae4f3a5 100644 --- a/src/corelib/kernel/qguard.cpp +++ b/src/corelib/kernel/qguard.cpp @@ -19,6 +19,7 @@ void q_guard_addGuard(QGuard<QObject> *g) void q_guard_removeGuard(QGuard<QObject> *g) { + if (g->next) g->next->prev = g->prev; *g->prev = g->next; g->next = 0; g->prev = 0; diff --git a/src/declarative/fx/qfxanchors.cpp b/src/declarative/fx/qfxanchors.cpp index e1b450d..350cbc0 100644 --- a/src/declarative/fx/qfxanchors.cpp +++ b/src/declarative/fx/qfxanchors.cpp @@ -44,7 +44,6 @@ #include "qfxitem_p.h" #include <QDebug> #include <QtDeclarative/qmlinfo.h> -#include <QtDeclarative/qmlbindablevalue.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/fx/qfxpathview.cpp b/src/declarative/fx/qfxpathview.cpp index f940f68..3c61050 100644 --- a/src/declarative/fx/qfxpathview.cpp +++ b/src/declarative/fx/qfxpathview.cpp @@ -42,7 +42,6 @@ #include <math.h> #include <QDebug> #include <QEvent> -#include "qmlbindablevalue.h" #include "qmlstate.h" #include "qlistmodelinterface.h" #include "qmlopenmetaobject.h" diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp index a3dca79e..42b8d2c 100644 --- a/src/declarative/fx/qfxwebview.cpp +++ b/src/declarative/fx/qfxwebview.cpp @@ -53,7 +53,6 @@ #include <QtWebKit/QWebElement> #include "qml.h" -#include "qmlbindablevalue.h" #include "qmlengine.h" #include "qmlstate.h" #include "qfxtransform.h" diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index eecf8cd..b3fa063 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -3,7 +3,7 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlvmemetaobject.cpp \ qml/qmlengine.cpp \ qml/qmlexpression.cpp \ - qml/qmlbindablevalue.cpp \ + qml/qmlbinding.cpp \ qml/qmlmetaproperty.cpp \ qml/qmlcomponent.cpp \ qml/qmlcontext.cpp \ @@ -33,8 +33,8 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlinstruction_p.h \ qml/qmlvmemetaobject_p.h \ qml/qml.h \ - qml/qmlbindablevalue.h \ - qml/qmlbindablevalue_p.h \ + qml/qmlbinding.h \ + qml/qmlbinding_p.h \ qml/qmlmetaproperty.h \ qml/qmlcomponent.h \ qml/qmlcomponent_p.h \ diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index 40ffffe..073642f 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -56,13 +56,10 @@ using namespace QmlJS; struct ScriptInstruction { enum { - Load, // fetch - Fetch, // fetch - LoadIdObject, // fetch FetchConstant, // constant - FetchD0Constant, // constant - FetchD1Constant, // constant + FetchContextConstant, // constant + FetchRootConstant, // constant Equals, // NA @@ -88,8 +85,6 @@ struct ScriptInstruction { }; }; -DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS); - class QmlBasicScriptPrivate { public: @@ -120,60 +115,6 @@ public: } }; -QDebug operator<<(QDebug lhs, const QmlBasicScriptNodeCache &rhs) -{ - switch(rhs.type) { - case QmlBasicScriptNodeCache::Invalid: - lhs << "Invalid"; - break; - case QmlBasicScriptNodeCache::Core: - lhs << "Core" << rhs.object << rhs.core; - break; - case QmlBasicScriptNodeCache::Attached: - lhs << "Attached" << rhs.object << rhs.attached; - break; - case QmlBasicScriptNodeCache::SignalProperty: - lhs << "SignalProperty" << rhs.object << rhs.core; - break; - case QmlBasicScriptNodeCache::Variant: - lhs << "Variant" << rhs.context; - break; - } - - return lhs; -} - -void QmlBasicScriptNodeCache::clear() -{ - object = 0; - metaObject = 0; - type = Invalid; -} - -static QVariant toObjectOrVariant(const QVariant &v) -{ - switch(v.userType()) { - case QVariant::String: - case QVariant::UInt: - case QVariant::Int: - case QMetaType::Float: - case QVariant::Double: - case QVariant::Color: - case QVariant::Bool: - default: - { - if (v.type() == QVariant::UserType) { - QObject *o = QmlMetaType::toQObject(v); - if (o) - return qVariantFromValue(o); - else - return v; - } - return v; - } - } -} - static QVariant fetch_value(QObject *o, int idx, int type) { if (!o) @@ -259,26 +200,6 @@ static QVariant fetch_value(QObject *o, int idx, int type) }; } -QVariant QmlBasicScriptNodeCache::value(const char *) const -{ - //QFxPerfTimer<QFxPerf::BasicScriptValue> pt; - switch(type) { - case Invalid: - break; - case Core: - return fetch_value(object, core, coreType); - break; - case Attached: - return qVariantFromValue(static_cast<QObject *>(attached)); - break; - case SignalProperty: - break; - case Variant: - return context->propertyValues[contextIndex]; - }; - return QVariant(); -} - struct QmlBasicScriptCompiler { QmlBasicScriptCompiler() @@ -298,7 +219,11 @@ struct QmlBasicScriptCompiler bool tryConstant(QmlJS::AST::Node *); bool parseConstant(QmlJS::AST::Node *); bool tryName(QmlJS::AST::Node *); - bool parseName(QmlJS::AST::Node *, QmlParser::Object ** = 0); + bool parseName(QmlJS::AST::Node *); + + bool buildName(QStringList &, QmlJS::AST::Node *); + const QMetaObject *fetch(int type, const QMetaObject *, int idx); + bool tryBinaryExpression(QmlJS::AST::Node *); bool compileBinaryExpression(QmlJS::AST::Node *); @@ -340,7 +265,7 @@ QmlBasicScript::QmlBasicScript() } /*! - Create a new QmlBasicScript instance from saved \a data. + Load the QmlBasicScript instance with saved \a data. \a data \b must be data previously acquired from calling compileData() on a previously created QmlBasicScript instance. Any other data will almost @@ -352,9 +277,12 @@ QmlBasicScript::QmlBasicScript() If \a owner is set, it is referenced on creation and dereferenced on destruction of this instance. */ -QmlBasicScript::QmlBasicScript(const char *data, QmlRefCount *owner) -: flags(0), d((QmlBasicScriptPrivate *)data), rc(owner) + +void QmlBasicScript::load(const char *data, QmlRefCount *owner) { + clear(); + d = (QmlBasicScriptPrivate *)data; + rc = owner; if (rc) rc->addref(); } @@ -374,11 +302,7 @@ QByteArray QmlBasicScript::expression() const */ QmlBasicScript::~QmlBasicScript() { - if (flags & QmlBasicScriptPrivate::OwnData) - free(d); - if (rc) rc->release(); - d = 0; - rc = 0; + clear(); } /*! @@ -401,24 +325,14 @@ void QmlBasicScript::clear() */ void *QmlBasicScript::newScriptState() { - if (!d) { - return 0; - } else { - void *rv = ::malloc(d->stateSize * sizeof(QmlBasicScriptNodeCache)); - ::memset(rv, 0, d->stateSize * sizeof(QmlBasicScriptNodeCache)); - return rv; - } + return 0; } /*! Delete the \a data previously allocated by newScriptState(). */ -void QmlBasicScript::deleteScriptState(void *data) +void QmlBasicScript::deleteScriptState(void *) { - if (!data) return; - Q_ASSERT(d); - clearCache(data); - free(data); } /*! @@ -430,18 +344,21 @@ void QmlBasicScript::dump() return; qWarning() << d->instructionCount << "instructions:"; - const char *data = d->data(); for (int ii = 0; ii < d->instructionCount; ++ii) { const ScriptInstruction &instr = d->instructions()[ii]; switch(instr.type) { - case ScriptInstruction::Load: - qWarning().nospace() << "LOAD\t\t" << instr.fetch.idx << "\t\t" - << QByteArray(data + instr.fetch.idx); + case ScriptInstruction::LoadIdObject: + qWarning().nospace() << "LOAD_ID_OBJECT"; break; - case ScriptInstruction::Fetch: - qWarning().nospace() << "FETCH\t\t" << instr.fetch.idx << "\t\t" - << QByteArray(data + instr.fetch.idx); + case ScriptInstruction::FetchConstant: + qWarning().nospace() << "FETCH_CONSTANT"; + break; + case ScriptInstruction::FetchContextConstant: + qWarning().nospace() << "FETCH_CONTEXT_CONSTANT"; + break; + case ScriptInstruction::FetchRootConstant: + qWarning().nospace() << "FETCH_ROOT_CONSTANT"; break; case ScriptInstruction::Equals: qWarning().nospace() << "EQUALS"; @@ -552,101 +469,121 @@ bool QmlBasicScriptCompiler::tryName(QmlJS::AST::Node *node) node->kind == AST::Node::Kind_FieldMemberExpression; } -bool QmlBasicScriptCompiler::parseName(AST::Node *node, - QmlParser::Object **type) +bool QmlBasicScriptCompiler::buildName(QStringList &name, + QmlJS::AST::Node *node) { - bool load = false; - QmlParser::Object *loadedType = 0; - QString name; if (node->kind == AST::Node::Kind_IdentifierExpression) { - name = static_cast<AST::IdentifierExpression *>(node)->name->asString(); - load = true; + name << static_cast<AST::IdentifierExpression*>(node)->name->asString(); } else if (node->kind == AST::Node::Kind_FieldMemberExpression) { - AST::FieldMemberExpression *expr = static_cast<AST::FieldMemberExpression *>(node); + AST::FieldMemberExpression *expr = + static_cast<AST::FieldMemberExpression *>(node); - if (!parseName(expr->base, &loadedType)) + if (!buildName(name, expr->base)) return false; - name = expr->name->asString(); + name << expr->name->asString(); } else { return false; } + return true; +} + +const QMetaObject * +QmlBasicScriptCompiler::fetch(int type, const QMetaObject *mo, int idx) +{ ScriptInstruction instr; - if (load) { + (int &)instr.type = type; + instr.constant.idx = idx; + QMetaProperty prop = mo->property(idx); + if (prop.isConstant()) + instr.constant.notify = 0; + else + instr.constant.notify = prop.notifySignalIndex(); + instr.constant.type = prop.userType(); + bytecode << instr; + return QmlMetaType::metaObjectForType(prop.userType()); +} + +bool QmlBasicScriptCompiler::parseName(AST::Node *node) +{ + QStringList nameParts; + if (!buildName(nameParts, node)) + return false; - if (ids.contains(name)) { - instr.type = ScriptInstruction::LoadIdObject; - instr.fetch.idx = ids.value(name)->idIndex; + QmlParser::Object *absType = 0; + const QMetaObject *metaType = 0; - if (type) - *type = ids.value(name); + for (int ii = 0; ii < nameParts.count(); ++ii) { + const QString &name = nameParts.at(ii); - } else { - int d0Idx = context->metaObject()->indexOfProperty(name.toUtf8().constData()); - int d1Idx = -1; - if (d0Idx == -1) - d1Idx = component->metaObject()->indexOfProperty(name.toUtf8().constData()); - if (d0Idx != -1) { - - instr.type = ScriptInstruction::FetchD0Constant; - instr.constant.idx = d0Idx; - QMetaProperty prop = context->metaObject()->property(d0Idx); - if (prop.isConstant()) - instr.constant.notify = 0; - else - instr.constant.notify = prop.notifySignalIndex(); - instr.constant.type = prop.userType(); - - } else if (d1Idx != -1) { - - instr.type = ScriptInstruction::FetchD1Constant; - instr.constant.idx = d1Idx; - QMetaProperty prop = component->metaObject()->property(d1Idx); - if (prop.isConstant()) - instr.constant.notify = 0; - else - instr.constant.notify = prop.notifySignalIndex(); - instr.constant.type = prop.userType(); - - } else { - - int nref = data.count(); - data.append(name.toUtf8()); - data.append('\0'); - instr.type = ScriptInstruction::Load; - instr.fetch.idx = nref; - ++stateSize; + // We don't handle signal properties + if (name.length() > 2 && name.startsWith(QLatin1String("on")) && + name.at(2).isUpper()) + return false; + if (ii == 0) { + + if (0) { + // ### - Must test for an attached type name + } else if (ids.contains(name)) { + ScriptInstruction instr; + instr.type = ScriptInstruction::LoadIdObject; + instr.fetch.idx = ids.value(name)->idIndex; + bytecode << instr; + absType = ids.value(name); + } else if(name.at(0).isLower()) { + + QByteArray utf8Name = name.toUtf8(); + const char *cname = utf8Name.constData(); + + int d0Idx = context->metaObject()->indexOfProperty(cname); + int d1Idx = -1; + if (d0Idx == -1) + d1Idx = component->metaObject()->indexOfProperty(cname); + + if (d0Idx != -1) { + metaType = fetch(ScriptInstruction::FetchContextConstant, + context->metaObject(), d0Idx); + } else if(d1Idx != -1) { + metaType = fetch(ScriptInstruction::FetchRootConstant, + component->metaObject(), d1Idx); + } else { + return false; + } + + } else { + return false; } - } + } else { - } else { + if (!name.at(0).isLower()) + return false; - int idx = -1; - if (loadedType) - idx = loadedType->metaObject()->indexOfProperty(name.toUtf8().constData()); - if (idx != -1) { - instr.type = ScriptInstruction::FetchConstant; - instr.constant.idx = idx; - QMetaProperty prop = loadedType->metaObject()->property(idx); - if (prop.isConstant()) - instr.constant.notify = 0; + const QMetaObject *mo = 0; + if (absType) + mo = absType->metaObject(); + else if(metaType) + mo = metaType; else - instr.constant.notify = prop.notifySignalIndex(); - instr.constant.type = prop.userType(); - } else { - int nref = data.count(); - data.append(name.toUtf8()); - data.append('\0'); - instr.type = ScriptInstruction::Fetch; - instr.fetch.idx = nref; - ++stateSize; - } + return false; + + QByteArray utf8Name = name.toUtf8(); + const char *cname = utf8Name.constData(); + int idx = mo->indexOfProperty(cname); + if (idx == -1) + return false; + + if (absType || mo->property(idx).isFinal()) { + absType = 0; metaType = 0; + metaType = fetch(ScriptInstruction::FetchConstant, mo, idx); + } else { + return false; + } + } } - bytecode.append(instr); return true; } @@ -699,44 +636,6 @@ bool QmlBasicScriptCompiler::compileBinaryExpression(AST::Node *node) } /*! - \internal -*/ -void QmlBasicScript::clearCache(void *voidCache) -{ - QmlBasicScriptNodeCache *dataCache = - reinterpret_cast<QmlBasicScriptNodeCache *>(voidCache); - - for (int ii = 0; ii < d->stateSize; ++ii) { - if (!dataCache[ii].isCore() && !dataCache[ii].isVariant() && - dataCache[ii].object) { - QMetaObject::removeGuard(&dataCache[ii].object); - dataCache[ii].object = 0; - } - dataCache[ii].clear(); - } -} - -void QmlBasicScript::guard(QmlBasicScriptNodeCache &n) -{ - if (n.object) { - if (n.isVariant()) { - } else if (n.isCore()) { - n.metaObject = - n.object->metaObject(); - } else { - QMetaObject::addGuard(&n.object); - } - } -} - -bool QmlBasicScript::valid(QmlBasicScriptNodeCache &n, QObject *obj) -{ - return n.object == obj && - (!n.isCore() || obj->metaObject() == n.metaObject); -} - - -/*! \enum QmlBasicScript::CacheState \value NoChange The query has not change. Any previous monitoring is still valid. @@ -753,31 +652,17 @@ bool QmlBasicScript::valid(QmlBasicScriptNodeCache &n, QObject *obj) */ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *cached) { + Q_UNUSED(voidCache); if (!isValid()) return QVariant(); QmlContextPrivate *contextPrivate = context->d_func(); QmlEnginePrivate *enginePrivate = context->engine()->d_func(); - QmlBasicScriptNodeCache *dataCache = - reinterpret_cast<QmlBasicScriptNodeCache *>(voidCache); - int dataCacheItem; - QStack<QVariant> stack; - bool resetting = false; - bool hasReset = false; - - const char *data = d->data(); - - if (dataCache[0].type == QmlBasicScriptNodeCache::Invalid) { - resetting = true; - hasReset = true; - } - CacheState state = NoChange; - dataCacheItem = 0; for (int idx = 0; idx < d->instructionCount; ++idx) { const ScriptInstruction &instr = d->instructions()[idx]; @@ -791,7 +676,7 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c } break; - case ScriptInstruction::FetchD0Constant: + case ScriptInstruction::FetchContextConstant: { QObject *obj = contextPrivate->defaultObjects.at(0); @@ -803,7 +688,7 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c } break; - case ScriptInstruction::FetchD1Constant: + case ScriptInstruction::FetchRootConstant: { QObject *obj = contextPrivate->defaultObjects.at(1); @@ -828,64 +713,14 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c } break; - case ScriptInstruction::Load: // either an object or a property - case ScriptInstruction::Fetch: // can only be a property - { - const char *id = data + instr.fetch.idx; - QmlBasicScriptNodeCache &n = dataCache[dataCacheItem]; - - if (instr.type == ScriptInstruction::Load) { - - if (n.type == QmlBasicScriptNodeCache::Invalid || state == Reset) { - context->engine()->d_func()->loadCache(n, QLatin1String(id), static_cast<QmlContextPrivate*>(context->d_ptr)); - if (state != Reset) - state = Incremental; - } - - if(!n.isValid()) - qWarning("ReferenceError: %s is not defined", id); - - } else { // instr.type == ScriptInstruction::Fetch - - QVariant o = stack.pop(); - QObject *obj = qvariant_cast<QObject *>(o); - if (!obj) { - if (n.type == QmlBasicScriptNodeCache::Invalid) { - if (scriptWarnings()) - qWarning() << "QmlBasicScript: Unable to convert" << o; - *cached = state; - return QVariant(); - } else { - clearCache(dataCache); - *cached = Reset; - CacheState dummy; - return run(context, voidCache, &dummy); - } - } else if (n.type == QmlBasicScriptNodeCache::Invalid || state == Reset) { - context->engine()->d_func()->fetchCache(n, QLatin1String(id), obj); - guard(n); - if (state != Reset) - state = Incremental; - } else if (!valid(n, obj)) { - clearCache(dataCache); - *cached = Reset; - CacheState dummy; - return run(context, voidCache, &dummy); - } - - } - - QVariant var = n.value(id); - stack.push(var); - ++dataCacheItem; - } - break; case ScriptInstruction::Int: stack.push(QVariant(instr.integer.value)); break; + case ScriptInstruction::Bool: stack.push(QVariant(instr.boolean.value)); break; + case ScriptInstruction::Equals: { QVariant rhs = stack.pop(); @@ -899,7 +734,7 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c } } - *cached = state; + *cached = Reset; if (stack.isEmpty()) return QVariant(); @@ -927,23 +762,4 @@ unsigned int QmlBasicScript::compileDataSize() const return 0; } -bool QmlBasicScript::isSingleLoad() const -{ - if (!d) - return false; - - return d->instructionCount == 1 && - d->instructions()[0].type == ScriptInstruction::Load; -} - -QByteArray QmlBasicScript::singleLoadTarget() const -{ - if (!isSingleLoad()) - return QByteArray(); - - // We know there is one instruction and it is a load - return QByteArray(d->data() + d->instructions()[0].fetch.idx); -} - - QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h index 77d59eb..539227f 100644 --- a/src/declarative/qml/qmlbasicscript_p.h +++ b/src/declarative/qml/qmlbasicscript_p.h @@ -70,9 +70,10 @@ class QmlBasicScript { public: QmlBasicScript(); - QmlBasicScript(const char *, QmlRefCount * = 0); ~QmlBasicScript(); + void load(const char *, QmlRefCount * = 0); + // Always 4-byte aligned const char *compileData() const; unsigned int compileDataSize() const; @@ -100,50 +101,12 @@ public: enum CacheState { NoChange, Incremental, Reset }; QVariant run(QmlContext *, void *, CacheState *); - // Optimization opportunities - bool isSingleLoad() const; - QByteArray singleLoadTarget() const; - private: int flags; QmlBasicScriptPrivate *d; QmlRefCount *rc; - - void clearCache(void *); - void guard(QmlBasicScriptNodeCache &); - bool valid(QmlBasicScriptNodeCache &, QObject *); }; -class QmlContextPrivate; -class QDebug; -class QmlBasicScriptNodeCache -{ -public: - QObject *object; - const QMetaObject *metaObject; - enum { Invalid, - Core, - Attached, - SignalProperty, - 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 isVariant() const { return type == Variant; } - void clear(); - QVariant value(const char *) const; -}; - -QDebug operator<<(QDebug, const QmlBasicScriptNodeCache &); - QT_END_NAMESPACE QT_END_HEADER diff --git a/src/declarative/qml/qmlbindablevalue.cpp b/src/declarative/qml/qmlbinding.cpp index 6dda5e3..e2f4682 100644 --- a/src/declarative/qml/qmlbindablevalue.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -40,8 +40,8 @@ ****************************************************************************/ #include <qml.h> -#include "qmlbindablevalue.h" -#include "qmlbindablevalue_p.h" +#include "qmlbinding.h" +#include "qmlbinding_p.h" #include <qmlcontext.h> #include <qmlinfo.h> #include <QVariant> @@ -54,46 +54,48 @@ QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS); -QmlBindableValuePrivate::QmlBindableValuePrivate() +QmlBindingPrivate::QmlBindingPrivate() : inited(false), updating(false), enabled(true), mePtr(0) { } -QML_DEFINE_NOCREATE_TYPE(QmlBindableValue); -QmlBindableValue::QmlBindableValue(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent) -: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent), QmlExpression(ctxt, data, rc, obj) +QML_DEFINE_NOCREATE_TYPE(QmlBinding); +QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent) +: QmlExpression(ctxt, data, rc, obj, *new QmlBindingPrivate) { + setParent(parent); } -QmlBindableValue::QmlBindableValue(const QString &str, QObject *obj, QmlContext *ctxt, QObject *parent) -: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent), QmlExpression(ctxt, str, obj) +QmlBinding::QmlBinding(const QString &str, QObject *obj, QmlContext *ctxt, QObject *parent) +: QmlExpression(ctxt, str, obj, *new QmlBindingPrivate) { + setParent(parent); } -QmlBindableValue::~QmlBindableValue() +QmlBinding::~QmlBinding() { - Q_D(QmlBindableValue); + Q_D(QmlBinding); if(d->mePtr) *(d->mePtr) = 0; } -void QmlBindableValue::setTarget(const QmlMetaProperty &prop) +void QmlBinding::setTarget(const QmlMetaProperty &prop) { - Q_D(QmlBindableValue); + Q_D(QmlBinding); d->property = prop; update(); } -QmlMetaProperty QmlBindableValue::property() const +QmlMetaProperty QmlBinding::property() const { - Q_D(const QmlBindableValue); + Q_D(const QmlBinding); return d->property; } -void QmlBindableValue::init() +void QmlBinding::init() { - Q_D(QmlBindableValue); + Q_D(QmlBinding); if (d->inited) return; @@ -101,24 +103,24 @@ void QmlBindableValue::init() update(); } -void QmlBindableValue::setExpression(const QString &expr) +void QmlBinding::setExpression(const QString &expr) { QmlExpression::setExpression(expr); update(); } -void QmlBindableValue::forceUpdate() +void QmlBinding::forceUpdate() { - Q_D(QmlBindableValue); + Q_D(QmlBinding); if (!d->inited) init(); else update(); } -void QmlBindableValue::update() +void QmlBinding::update() { - Q_D(QmlBindableValue); + Q_D(QmlBinding); #ifdef Q_ENABLE_PERFORMANCE_LOG QFxPerfTimer<QFxPerf::BindableValueUpdate> bu; @@ -135,7 +137,7 @@ void QmlBindableValue::update() Q_ASSERT(idx != -1); void *a[1]; - QmlBindableValue *t = this; + QmlBinding *t = this; a[0] = (void *)&t; QMetaObject::metacall(d->property.object(), QMetaObject::WriteProperty, @@ -164,21 +166,21 @@ void QmlBindableValue::update() } } -void QmlBindableValue::valueChanged() +void QmlBinding::valueChanged() { update(); } -void QmlBindableValue::setEnabled(bool e) +void QmlBinding::setEnabled(bool e) { - Q_D(QmlBindableValue); + Q_D(QmlBinding); d->enabled = e; setTrackChange(e); } -bool QmlBindableValue::enabled() const +bool QmlBinding::enabled() const { - Q_D(const QmlBindableValue); + Q_D(const QmlBinding); return d->enabled; } diff --git a/src/declarative/qml/qmlbindablevalue.h b/src/declarative/qml/qmlbinding.h index 12da9f6..10d81b8 100644 --- a/src/declarative/qml/qmlbindablevalue.h +++ b/src/declarative/qml/qmlbinding.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QMLBINDABLEVALUE_H -#define QMLBINDABLEVALUE_H +#ifndef QMLBINDING_H +#define QMLBINDING_H #include <QtCore/QObject> #include <QtDeclarative/qfxglobal.h> @@ -56,15 +56,14 @@ QT_MODULE(Declarative) class QmlExpression; class QmlContext; -class QmlBindableValuePrivate; -class Q_DECLARATIVE_EXPORT QmlBindableValue : public QmlPropertyValueSource, - public QmlExpression +class QmlBindingPrivate; +class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression { Q_OBJECT public: - QmlBindableValue(const QString &, QObject *, QmlContext *, QObject *parent=0); - QmlBindableValue(void *, QmlRefCount *, QObject *, QmlContext *, QObject *parent); - ~QmlBindableValue(); + QmlBinding(const QString &, QObject *, QmlContext *, QObject *parent=0); + QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, QObject *parent); + ~QmlBinding(); virtual void setTarget(const QmlMetaProperty &); QmlMetaProperty property() const; @@ -86,13 +85,13 @@ protected: virtual void valueChanged(); private: - Q_DECLARE_PRIVATE(QmlBindableValue) + Q_DECLARE_PRIVATE(QmlBinding) }; QT_END_NAMESPACE -QML_DECLARE_TYPE(QmlBindableValue) +QML_DECLARE_TYPE(QmlBinding) QT_END_HEADER -#endif // QMLBINDABLEVALUE_H +#endif // QMLBINDING_H diff --git a/src/declarative/qml/qmlbindablevalue_p.h b/src/declarative/qml/qmlbinding_p.h index a37b2c0..ec1a04a 100644 --- a/src/declarative/qml/qmlbindablevalue_p.h +++ b/src/declarative/qml/qmlbinding_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QMLBINDABLEVALUE_P_H -#define QMLBINDABLEVALUE_P_H +#ifndef QMLBINDING_P_H +#define QMLBINDING_P_H // // W A R N I N G @@ -53,17 +53,17 @@ // We mean it. // -#include <private/qobject_p.h> -#include <QtDeclarative/qmlbindablevalue.h> +#include <QtDeclarative/qmlbinding.h> #include <QtDeclarative/qmlmetaproperty.h> +#include "qmlexpression_p.h" QT_BEGIN_NAMESPACE -class QmlBindableValuePrivate : public QObjectPrivate +class QmlBindingPrivate : public QmlExpressionPrivate { - Q_DECLARE_PUBLIC(QmlBindableValue) + Q_DECLARE_PUBLIC(QmlBinding) public: - QmlBindableValuePrivate(); + QmlBindingPrivate(); bool inited:1; bool updating:1; @@ -71,9 +71,9 @@ public: QmlMetaProperty property; - QmlBindableValue **mePtr; + QmlBinding **mePtr; }; QT_END_NAMESPACE -#endif // QMLBINDABLEVALUE_P_H +#endif // QMLBINDING_P_H diff --git a/src/declarative/qml/qmlboundsignal.cpp b/src/declarative/qml/qmlboundsignal.cpp index 9779e46..9af4003 100644 --- a/src/declarative/qml/qmlboundsignal.cpp +++ b/src/declarative/qml/qmlboundsignal.cpp @@ -53,14 +53,14 @@ QT_BEGIN_NAMESPACE int QmlBoundSignal::evaluateIdx = -1; QmlBoundSignal::QmlBoundSignal(QmlContext *ctxt, const QString &val, QObject *me, int idx, QObject *parent) -: QmlExpressionObject(ctxt, val, me, false), _idx(idx) +: QmlExpression(ctxt, val, me), _idx(idx) { - // A cached evaluation of the QmlExpressionObject::value() slot index. + // A cached evaluation of the QmlExpression::value() slot index. // // This is thread safe. Although it may be updated by two threads, they // will both set it to the same value - so the worst thing that can happen // is that they both do the work to figure it out. Boo hoo. - if (evaluateIdx == -1) evaluateIdx = QmlExpressionObject::staticMetaObject.indexOfMethod("value()"); + if (evaluateIdx == -1) evaluateIdx = QmlExpression::staticMetaObject.indexOfMethod("value()"); setTrackChange(false); QFx_setParent_noEvent(this, parent); diff --git a/src/declarative/qml/qmlboundsignal_p.h b/src/declarative/qml/qmlboundsignal_p.h index 39c0c46..de8f91d 100644 --- a/src/declarative/qml/qmlboundsignal_p.h +++ b/src/declarative/qml/qmlboundsignal_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE -class QmlBoundSignal : public QmlExpressionObject +class QmlBoundSignal : public QmlExpression { Q_OBJECT public: diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index c7d45fd..4e39d7f 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -51,7 +51,7 @@ #include <QStringList> #include <qmlengine.h> #include <QFileInfo> -#include <qmlbindablevalue.h> +#include "qmlbinding.h" #include <QtCore/qdebug.h> #include <QApplication> @@ -578,7 +578,7 @@ void QmlComponent::completeCreate() QFxPerfTimer<QFxPerf::BindInit> bi; #endif for (int ii = 0; ii < d->bindValues.count(); ++ii) { - QmlEnginePrivate::SimpleList<QmlBindableValue> bv = + QmlEnginePrivate::SimpleList<QmlBinding> bv = d->bindValues.at(ii); for (int jj = 0; jj < bv.count; ++jj) { if(bv.at(jj)) diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h index 25af342..a7a3230 100644 --- a/src/declarative/qml/qmlcomponent_p.h +++ b/src/declarative/qml/qmlcomponent_p.h @@ -88,7 +88,7 @@ public: int count; QmlCompiledData *cc; - QList<QmlEnginePrivate::SimpleList<QmlBindableValue> > bindValues; + QList<QmlEnginePrivate::SimpleList<QmlBinding> > bindValues; QList<QmlEnginePrivate::SimpleList<QmlParserStatus> > parserStatus; bool completePending; diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 5bc70bc..bc2e6bf 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -292,7 +292,7 @@ QmlContext::~QmlContext() d->childExpressions.begin(); iter != d->childExpressions.end(); ++iter) { - (*iter)->d->ctxt = 0; + (*iter)->d_func()->ctxt = 0; } for (int ii = 0; ii < d->contextObjects.count(); ++ii) { diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index a6f5b28..8b21290 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -72,7 +72,7 @@ #include <QtCore/qdir.h> #include <qmlcomponent.h> #include "private/qmlmetaproperty_p.h" -#include <private/qmlbindablevalue_p.h> +#include <private/qmlbinding_p.h> #include <private/qmlvme_p.h> #include <private/qmlenginedebug_p.h> @@ -118,13 +118,13 @@ QmlEnginePrivate::~QmlEnginePrivate() clear(parserStatus[ii]); } -void QmlEnginePrivate::clear(SimpleList<QmlBindableValue> &bvs) +void QmlEnginePrivate::clear(SimpleList<QmlBinding> &bvs) { for (int ii = 0; ii < bvs.count; ++ii) { - QmlBindableValue *bv = bvs.at(ii); + QmlBinding *bv = bvs.at(ii); if(bv) { - QmlBindableValuePrivate *p = - static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bv)); + QmlBindingPrivate *p = + static_cast<QmlBindingPrivate *>(QObjectPrivate::get(bv)); p->mePtr = 0; } } @@ -254,74 +254,6 @@ QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName, return QScriptValue(); } -//////////////////////////////////////////////////////////////////// - -bool QmlEnginePrivate::fetchCache(QmlBasicScriptNodeCache &cache, const QString &propName, QObject *obj) -{ - QmlMetaProperty prop(obj, propName); - - if (!prop.isValid()) - return false; - - if (prop.needsChangedNotifier()) - capturedProperties << CapturedProperty(prop); - - if (prop.type() & QmlMetaProperty::Attached) { - - cache.object = obj; - cache.type = QmlBasicScriptNodeCache::Attached; - cache.attached = prop.d->attachedObject(); - return true; - - } else if (prop.type() & QmlMetaProperty::Property) { - - cache.object = obj; - cache.type = QmlBasicScriptNodeCache::Core; - cache.core = prop.property().propertyIndex(); - cache.coreType = prop.propertyType(); - return true; - - } else if (prop.type() & QmlMetaProperty::SignalProperty) { - - cache.object = obj; - cache.type = QmlBasicScriptNodeCache::SignalProperty; - cache.core = prop.coreIndex(); - return true; - - } - - return false; -} - -bool QmlEnginePrivate::loadCache(QmlBasicScriptNodeCache &cache, const QString &propName, QmlContextPrivate *context) -{ - while(context) { - - QHash<QString, int>::ConstIterator iter = - context->propertyNames.find(propName); - if (iter != context->propertyNames.end()) { - cache.object = 0; - cache.type = QmlBasicScriptNodeCache::Variant; - cache.context = context; - cache.contextIndex = *iter; - capturedProperties << CapturedProperty(context->q_ptr, -1, *iter + context->notifyIndex); - return true; - } - - foreach(QObject *obj, context->defaultObjects) { - if (fetchCache(cache, propName, obj)) - return true; - } - - if (context->parent) - context = context->parent->d_func(); - else - context = 0; - } - return false; -} - - /*! \class QmlEngine \brief The QmlEngine class provides an environment for instantiating QML components. diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index f459dc5..47d2397 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -93,11 +93,10 @@ public: void init(); - bool fetchCache(QmlBasicScriptNodeCache &cache, const QString &propName, QObject *); - bool loadCache(QmlBasicScriptNodeCache &cache, const QString &propName, QmlContextPrivate *context); - - QScriptClass::QueryFlags queryObject(const QString &name, uint *id, QObject *); - QScriptValue propertyObject(const QScriptString &propName, QObject *, uint id = 0); + QScriptClass::QueryFlags queryObject(const QString &name, uint *id, + QObject *); + QScriptValue propertyObject(const QScriptString &propName, QObject *, + uint id = 0); struct CapturedProperty { CapturedProperty(QObject *o, int c, int n) @@ -152,10 +151,10 @@ public: } }; - static void clear(SimpleList<QmlBindableValue> &); + static void clear(SimpleList<QmlBinding> &); static void clear(SimpleList<QmlParserStatus> &); - QList<SimpleList<QmlBindableValue> > bindValues; + QList<SimpleList<QmlBinding> > bindValues; QList<SimpleList<QmlParserStatus> > parserStatus; QmlComponent *rootComponent; diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 2aa1a8a..b4f57eb 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -50,53 +50,72 @@ Q_DECLARE_METATYPE(QList<QObject *>); QT_BEGIN_NAMESPACE -DEFINE_BOOL_CONFIG_OPTION(qmlDebugger, QML_DEBUGGER) - -QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b) -: q(b), ctxt(0), expressionFunctionValid(false), sseData(0), proxy(0), me(0), trackChange(false), line(-1), id(0), log(0) +QmlExpressionPrivate::QmlExpressionPrivate() +: ctxt(0), expressionFunctionValid(false), sseData(0), me(0), trackChange(true), line(-1), id(0), guardList(0), guardListLength(0) { } -QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, void *expr, QmlRefCount *rc) -: q(b), ctxt(0), expressionFunctionValid(false), sse((const char *)expr, rc), sseData(0), proxy(0), me(0), trackChange(true), line(-1), id(0), log(0) +void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr, + QObject *me) { + Q_Q(QmlExpression); + + expression = expr; + + this->ctxt = ctxt; + if (ctxt && ctxt->engine()) + id = ctxt->engine()->d_func()->getUniqueId(); + if (ctxt) + ctxt->d_func()->childExpressions.insert(q); + this->me = me; } -QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, const QString &expr) -: q(b), ctxt(0), expression(expr), expressionFunctionValid(false), sseData(0), proxy(0), me(0), trackChange(true), line(-1), id(0), log(0) +void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, + QObject *me) { + Q_Q(QmlExpression); + + sse.load((const char *)expr, rc); + + this->ctxt = ctxt; + if (ctxt && ctxt->engine()) + id = ctxt->engine()->d_func()->getUniqueId(); + if (ctxt) + ctxt->d_func()->childExpressions.insert(q); + this->me = me; } QmlExpressionPrivate::~QmlExpressionPrivate() { sse.deleteScriptState(sseData); sseData = 0; - delete proxy; - delete log; + if (guardList) { delete [] guardList; guardList = 0; } } /*! + \class QmlExpression + \brief The QmlExpression class evaluates ECMAScript in a QML context. +*/ + +/*! Create an invalid QmlExpression. As the expression will not have an associated QmlContext, this will be a null expression object and its value will always be an invalid QVariant. */ QmlExpression::QmlExpression() -: d(new QmlExpressionPrivate(this)) +: QObject(*new QmlExpressionPrivate, 0) { } -/*! \internal */ +/*! \internal */ QmlExpression::QmlExpression(QmlContext *ctxt, void *expr, - QmlRefCount *rc, QObject *me) -: d(new QmlExpressionPrivate(this, expr, rc)) + QmlRefCount *rc, QObject *me, + QmlExpressionPrivate &dd) +: QObject(dd, 0) { - d->ctxt = ctxt; - if(ctxt && ctxt->engine()) - d->id = ctxt->engine()->d_func()->getUniqueId(); - if(ctxt) - ctxt->d_func()->childExpressions.insert(this); - d->me = me; + Q_D(QmlExpression); + d->init(ctxt, expr, rc, me); } /*! @@ -108,14 +127,19 @@ QmlExpression::QmlExpression(QmlContext *ctxt, void *expr, */ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression, QObject *scope) -: d(new QmlExpressionPrivate(this, expression)) +: QObject(*new QmlExpressionPrivate, 0) +{ + Q_D(QmlExpression); + d->init(ctxt, expression, scope); +} + +/*! \internal */ +QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression, + QObject *scope, QmlExpressionPrivate &dd) +: QObject(dd, 0) { - d->ctxt = ctxt; - if(ctxt && ctxt->engine()) - d->id = ctxt->engine()->d_func()->getUniqueId(); - if(ctxt) - ctxt->d_func()->childExpressions.insert(this); - d->me = scope; + Q_D(QmlExpression); + d->init(ctxt, expression, scope); } /*! @@ -123,9 +147,9 @@ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression, */ QmlExpression::~QmlExpression() { + Q_D(QmlExpression); if (d->ctxt) d->ctxt->d_func()->childExpressions.remove(this); - delete d; d = 0; } /*! @@ -134,6 +158,7 @@ QmlExpression::~QmlExpression() */ QmlEngine *QmlExpression::engine() const { + Q_D(const QmlExpression); return d->ctxt?d->ctxt->engine():0; } @@ -143,6 +168,7 @@ QmlEngine *QmlExpression::engine() const */ QmlContext *QmlExpression::context() const { + Q_D(const QmlExpression); return d->ctxt; } @@ -151,6 +177,7 @@ QmlContext *QmlExpression::context() const */ QString QmlExpression::expression() const { + Q_D(const QmlExpression); if (d->sse.isValid()) return QLatin1String(d->sse.expression()); else @@ -170,12 +197,13 @@ void QmlExpression::clearExpression() */ void QmlExpression::setExpression(const QString &expression) { + Q_D(QmlExpression); if (d->sseData) { d->sse.deleteScriptState(d->sseData); d->sseData = 0; } - delete d->proxy; d->proxy = 0; + d->clearGuards(); d->expression = expression; d->expressionFunctionValid = false; @@ -184,18 +212,6 @@ void QmlExpression::setExpression(const QString &expression) d->sse.clear(); } -/*! - Called by QmlExpression each time the expression value changes from the - last time it was evaluated. The expression must have been evaluated at - least once (by calling QmlExpression::value()) before this callback will - be made. - - The default implementation does nothing. -*/ -void QmlExpression::valueChanged() -{ -} - QVariant QmlExpressionPrivate::evalSSE(QmlBasicScript::CacheState &cacheState) { #ifdef Q_ENABLE_PERFORMANCE_LOG @@ -318,6 +334,8 @@ QVariant QmlExpressionPrivate::evalQtScript() */ QVariant QmlExpression::value() { + Q_D(QmlExpression); + QVariant rv; if (!d->ctxt || !engine() || (!d->sse.isValid() && d->expression.isEmpty())) return rv; @@ -340,87 +358,10 @@ QVariant QmlExpression::value() ep->currentExpression = lastCurrentExpression; - if (cacheState != QmlBasicScript::NoChange) { - if (cacheState != QmlBasicScript::Incremental && d->proxy) { - delete d->proxy; - d->proxy = 0; - } - - if (trackChange() && ep->capturedProperties.count()) { - if (!d->proxy) - d->proxy = new QmlExpressionBindProxy(this); - - static int changedIndex = -1; - if (changedIndex == -1) - changedIndex = QmlExpressionBindProxy::staticMetaObject.indexOfSlot("changed()"); - - if(qmlDebugger()) { - QmlExpressionLog log; - log.setTime(engine()->d_func()->getUniqueId()); - log.setExpression(expression()); - log.setResult(rv); - - for (int ii = 0; ii < ep->capturedProperties.count(); ++ii) { - const QmlEnginePrivate::CapturedProperty &prop = - ep->capturedProperties.at(ii); - - if (prop.notifyIndex != -1) { - QMetaObject::connect(prop.object, prop.notifyIndex, - d->proxy, changedIndex); - } else { - const QMetaObject *metaObj = prop.object->metaObject(); - QMetaProperty metaProp = - metaObj->property(prop.coreIndex); - - QString warn = QLatin1String("Expression depends on non-NOTIFYable property: ") + - QLatin1String(metaObj->className()) + - QLatin1String("::") + - QLatin1String(metaProp.name()); - log.addWarning(warn); - } - } - d->addLog(log); - - } else { - bool outputWarningHeader = false; - for (int ii = 0; ii < ep->capturedProperties.count(); ++ii) { - const QmlEnginePrivate::CapturedProperty &prop = - ep->capturedProperties.at(ii); - - if (prop.notifyIndex != -1) { - QMetaObject::connect(prop.object, prop.notifyIndex, - d->proxy, changedIndex); - } else { - if (!outputWarningHeader) { - outputWarningHeader = true; - qWarning() << "QmlExpression: Expression" << expression() << "depends on non-NOTIFYable properties:"; - } - - const QMetaObject *metaObj = prop.object->metaObject(); - QMetaProperty metaProp = - metaObj->property(prop.coreIndex); - - qWarning().nospace() << " " << metaObj->className() - << "::" << metaProp.name(); - } - } - } - } else { - QmlExpressionLog log; - log.setTime(engine()->d_func()->getUniqueId()); - log.setExpression(expression()); - log.setResult(rv); - d->addLog(log); - } - - } else { - if(qmlDebugger()) { - QmlExpressionLog log; - log.setTime(engine()->d_func()->getUniqueId()); - log.setExpression(expression()); - log.setResult(rv); - d->addLog(log); - } + if ((!trackChange() || !ep->capturedProperties.count()) && d->guardList) { + d->clearGuards(); + } else if(trackChange()) { + d->updateGuards(ep->capturedProperties); } ep->capturedProperties.clear(); @@ -435,7 +376,8 @@ QVariant QmlExpression::value() */ bool QmlExpression::isConstant() const { - return d->proxy == 0; + Q_D(const QmlExpression); + return !d->guardList; } /*! @@ -443,6 +385,7 @@ bool QmlExpression::isConstant() const */ bool QmlExpression::trackChange() const { + Q_D(const QmlExpression); return d->trackChange; } @@ -463,6 +406,7 @@ bool QmlExpression::trackChange() const */ void QmlExpression::setTrackChange(bool trackChange) { + Q_D(QmlExpression); d->trackChange = trackChange; } @@ -472,6 +416,7 @@ void QmlExpression::setTrackChange(bool trackChange) */ void QmlExpression::setSourceLocation(const QUrl &fileName, int line) { + Q_D(QmlExpression); d->fileName = fileName; d->line = line; } @@ -484,6 +429,7 @@ void QmlExpression::setSourceLocation(const QUrl &fileName, int line) */ QObject *QmlExpression::scopeObject() const { + Q_D(const QmlExpression); return d->me; } @@ -492,144 +438,138 @@ QObject *QmlExpression::scopeObject() const */ quint32 QmlExpression::id() const { + Q_D(const QmlExpression); return d->id; } -/*! - \class QmlExpression - \brief The QmlExpression class evaluates ECMAScript in a QML context. -*/ - -/*! - \class QmlExpressionObject - \brief The QmlExpressionObject class extends QmlExpression with signals and slots. - - To remain as lightweight as possible, QmlExpression does not inherit QObject - and consequently cannot use signals or slots. For the cases where this is - more convenient in an application, QmlExpressionObject can be used instead. - - QmlExpressionObject behaves identically to QmlExpression, except that the - QmlExpressionObject::value() method is a slot, and the - QmlExpressionObject::valueChanged() callback is a signal. -*/ -/*! - Create a QmlExpression with the specified \a parent. - - As the expression will not have an associated QmlContext, this will be a - null expression object and its value will always be an invalid QVariant. -*/ -QmlExpressionObject::QmlExpressionObject(QObject *parent) -: QObject(parent) -{ -} - -/*! - Create a QmlExpressionObject with the specified \a parent. - - The \a expression ECMAScript will be executed in the \a ctxt QmlContext. - If specified, the \a scope object's properties will also be in scope during - the expression's execution. -*/ -QmlExpressionObject::QmlExpressionObject(QmlContext *ctxt, const QString &expression, QObject *scope, QObject *parent) -: QObject(parent), QmlExpression(ctxt, expression, scope) -{ -} - -/*! \internal */ -QmlExpressionObject::QmlExpressionObject(QmlContext *ctxt, void *d, QmlRefCount *rc, QObject *me) -: QmlExpression(ctxt, d, rc, me) +/*! \internal */ +void QmlExpression::__q_notify() { + valueChanged(); } -/*! - Returns the value of the expression, or an invalid QVariant if the - expression is invalid or has an error. -*/ -QVariant QmlExpressionObject::value() +void QmlExpressionPrivate::clearGuards() { - return QmlExpression::value(); -} - -/*! - \fn void QmlExpressionObject::valueChanged() + Q_Q(QmlExpression); - Emitted each time the expression value changes from the last time it was - evaluated. The expression must have been evaluated at least once (by - calling QmlExpressionObject::value()) before this signal will be emitted. -*/ + static int notifyIdx = -1; + if (notifyIdx == -1) + notifyIdx = + QmlExpression::staticMetaObject.indexOfMethod("__q_notify()"); -void QmlExpressionPrivate::addLog(const QmlExpressionLog &l) -{ - if (!log) - log = new QList<QmlExpressionLog>(); - log->append(l); -} + for (int ii = 0; ii < guardListLength; ++ii) { + if (guardList[ii].data()) { + QMetaObject::disconnect(guardList[ii].data(), + guardList[ii].notifyIndex, + q, notifyIdx); + } + } -QmlExpressionLog::QmlExpressionLog() -{ + delete [] guardList; guardList = 0; + guardListLength = 0; } -QmlExpressionLog::QmlExpressionLog(const QmlExpressionLog &o) -: m_time(o.m_time), - m_expression(o.m_expression), - m_result(o.m_result), - m_warnings(o.m_warnings) +void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties) { -} + Q_Q(QmlExpression); -QmlExpressionLog::~QmlExpressionLog() -{ -} + static int notifyIdx = -1; + if (notifyIdx == -1) + notifyIdx = + QmlExpression::staticMetaObject.indexOfMethod("__q_notify()"); -QmlExpressionLog &QmlExpressionLog::operator=(const QmlExpressionLog &o) -{ - m_time = o.m_time; - m_expression = o.m_expression; - m_result = o.m_result; - m_warnings = o.m_warnings; - return *this; -} + SignalGuard *newGuardList = 0; + + if (properties.count() != guardListLength) + newGuardList = new SignalGuard[properties.count()]; -void QmlExpressionLog::setTime(quint32 time) -{ - m_time = time; -} + bool outputWarningHeader = false; + int hit = 0; + for (int ii = 0; ii < properties.count(); ++ii) { + const QmlEnginePrivate::CapturedProperty &property = properties.at(ii); -quint32 QmlExpressionLog::time() const -{ - return m_time; -} + bool needGuard = true; + if (ii >= guardListLength) { + // New guard + } else if(guardList[ii].data() == property.object && + guardList[ii].notifyIndex == property.notifyIndex) { + // Cache hit + if (!guardList[ii].isDuplicate || + (guardList[ii].isDuplicate && hit == ii)) { + needGuard = false; + ++hit; + } + } else if(guardList[ii].data()) { + // Cache miss + QMetaObject::disconnect(guardList[ii].data(), + guardList[ii].notifyIndex, + q, notifyIdx); + } + /* else { + // Cache miss, but nothing to do + } */ + + if (needGuard) { + if (!newGuardList) { + newGuardList = new SignalGuard[properties.count()]; + for (int jj = 0; jj < ii; ++jj) + newGuardList[jj] = guardList[jj]; + } -QString QmlExpressionLog::expression() const -{ - return m_expression; -} + if (property.notifyIndex != -1) { + bool existing = false; + for (int jj = 0; !existing && jj < ii; ++jj) + existing = newGuardList[jj].data() == property.object && + newGuardList[jj].notifyIndex == property.notifyIndex; + + newGuardList[ii] = property.object; + newGuardList[ii].notifyIndex = property.notifyIndex; + if (existing) + newGuardList[ii].isDuplicate = true; + else + QMetaObject::connect(property.object, property.notifyIndex, + q, notifyIdx); + } else { + if (!outputWarningHeader) { + outputWarningHeader = true; + qWarning() << "QmlExpression: Expression" << q->expression() + << "depends on non-NOTIFYable properties:"; + } -void QmlExpressionLog::setExpression(const QString &e) -{ - m_expression = e; -} + const QMetaObject *metaObj = property.object->metaObject(); + QMetaProperty metaProp = metaObj->property(property.coreIndex); -QStringList QmlExpressionLog::warnings() const -{ - return m_warnings; -} + qWarning().nospace() << " " << metaObj->className() + << "::" << metaProp.name(); + } + } else if (newGuardList) { + newGuardList[ii] = guardList[ii]; + } + } -void QmlExpressionLog::addWarning(const QString &w) -{ - m_warnings << w; -} + for (int ii = properties.count(); ii < guardListLength; ++ii) { + if (guardList[ii].data()) { + QMetaObject::disconnect(guardList[ii].data(), + guardList[ii].notifyIndex, + q, notifyIdx); + } + } -QVariant QmlExpressionLog::result() const -{ - return m_result; + if (newGuardList) { + if (guardList) delete [] guardList; + guardList = newGuardList; + guardListLength = properties.count(); + } + //qWarning() << hit << properties.count() << q->expression(); } -void QmlExpressionLog::setResult(const QVariant &r) -{ - m_result = r; -} +/*! + \fn void QmlExpression::valueChanged() + Emitted each time the expression value changes from the last time it was + evaluated. The expression must have been evaluated at least once (by + calling QmlExpression::value()) before this signal will be emitted. +*/ QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h index 3d8f8df..6db6ef9 100644 --- a/src/declarative/qml/qmlexpression.h +++ b/src/declarative/qml/qmlexpression.h @@ -57,12 +57,12 @@ class QmlEngine; class QmlContext; class QmlExpressionPrivate; class QmlBasicScript; -class Q_DECLARATIVE_EXPORT QmlExpression +class Q_DECLARATIVE_EXPORT QmlExpression : public QObject { + Q_OBJECT public: QmlExpression(); QmlExpression(QmlContext *, const QString &, QObject *); - QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me); virtual ~QmlExpression(); QmlEngine *engine() const; @@ -71,7 +71,6 @@ public: QString expression() const; void clearExpression(); virtual void setExpression(const QString &); - QVariant value(); bool isConstant() const; bool trackChange() const; @@ -82,31 +81,27 @@ public: QObject *scopeObject() const; quint32 id() const; -protected: + +public Q_SLOTS: + QVariant value(); + +Q_SIGNALS: virtual void valueChanged(); +protected: + QmlExpression(QmlContext *, const QString &, QObject *, + QmlExpressionPrivate &dd); + QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me, + QmlExpressionPrivate &dd); + +private Q_SLOTS: + void __q_notify(); + private: + Q_DECLARE_PRIVATE(QmlExpression) friend class QmlExpressionBindProxy; friend class QmlDebugger; friend class QmlContext; - QmlExpressionPrivate *d; -}; - -// LK: can't we merge with QmlExpression???? -class Q_DECLARATIVE_EXPORT QmlExpressionObject : public QObject, - public QmlExpression -{ - Q_OBJECT -public: - QmlExpressionObject(QObject *parent = 0); - QmlExpressionObject(QmlContext *, const QString &, QObject *scope, QObject *parent = 0); - QmlExpressionObject(QmlContext *, void *, QmlRefCount *, QObject *); - -public Q_SLOTS: - QVariant value(); - -Q_SIGNALS: - void valueChanged(); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h index 09745a3..41b7749 100644 --- a/src/declarative/qml/qmlexpression_p.h +++ b/src/declarative/qml/qmlexpression_p.h @@ -55,23 +55,24 @@ #include "qmlbasicscript_p.h" #include "qmlexpression.h" +#include "qmlengine_p.h" +#include <private/qguard_p.h> #include <QtScript/qscriptvalue.h> QT_BEGIN_NAMESPACE class QmlExpression; class QString; -class QmlExpressionLog; -class QmlExpressionBindProxy; -class QmlExpressionPrivate +class QmlExpressionPrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QmlExpression) public: - QmlExpressionPrivate(QmlExpression *); - QmlExpressionPrivate(QmlExpression *, const QString &expr); - QmlExpressionPrivate(QmlExpression *, void *expr, QmlRefCount *rc); + QmlExpressionPrivate(); ~QmlExpressionPrivate(); - QmlExpression *q; + void init(QmlContext *, const QString &, QObject *); + void init(QmlContext *, void *, QmlRefCount *, QObject *); + QmlContext *ctxt; QString expression; bool expressionFunctionValid; @@ -79,7 +80,6 @@ public: QmlBasicScript sse; void *sseData; - QmlExpressionBindProxy *proxy; QObject *me; bool trackChange; @@ -88,53 +88,30 @@ public: quint32 id; - void addLog(const QmlExpressionLog &); - QList<QmlExpressionLog> *log; - QVariant evalSSE(QmlBasicScript::CacheState &cacheState); QVariant evalQtScript(); -}; - -class QmlExpressionBindProxy : public QObject -{ -Q_OBJECT -public: - QmlExpressionBindProxy(QmlExpression *be) - :e(be) { } - -private: - QmlExpression *e; - -private Q_SLOTS: - void changed() { e->valueChanged(); } -}; - -class QmlExpressionLog -{ -public: - QmlExpressionLog(); - QmlExpressionLog(const QmlExpressionLog &); - ~QmlExpressionLog(); - - QmlExpressionLog &operator=(const QmlExpressionLog &); - - void setTime(quint32); - quint32 time() const; - - QString expression() const; - void setExpression(const QString &); - - QStringList warnings() const; - void addWarning(const QString &); - - QVariant result() const; - void setResult(const QVariant &); -private: - quint32 m_time; - QString m_expression; - QVariant m_result; - QStringList m_warnings; + struct SignalGuard : public QGuard<QObject> { + SignalGuard() : isDuplicate(false), notifyIndex(-1) {} + + SignalGuard &operator=(QObject *obj) { + QGuard<QObject>::operator=(obj); + return *this; + } + SignalGuard &operator=(const SignalGuard &o) { + QGuard<QObject>::operator=(o); + isDuplicate = o.isDuplicate; + notifyIndex = o.notifyIndex; + return *this; + } + + bool isDuplicate:1; + int notifyIndex:31; + }; + SignalGuard *guardList; + int guardListLength; + void updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties); + void clearGuards(); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index dea3467..daa4242 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -44,7 +44,7 @@ #include <qml.h> #include <private/qfxperf_p.h> #include <QStringList> -#include <qmlbindablevalue.h> +#include "qmlbinding.h" #include <qmlcontext.h> #include "qmlboundsignal_p.h" #include <math.h> @@ -260,7 +260,7 @@ QmlMetaProperty::QmlMetaProperty(const QmlMetaProperty &other) \value Unknown The category is unknown. This will never be returned from propertyCategory() \value InvalidProperty The property is invalid. - \value Bindable The property is a QmlBindableValue. + \value Bindable The property is a QmlBinding. \value List The property is a QList pointer \value QmlList The property is a QmlList pointer \value Object The property is a QObject derived type pointer @@ -294,7 +294,7 @@ QmlMetaPropertyPrivate::propertyCategory() const int type = propertyType(); if (type == QmlMetaProperty::Invalid) category = QmlMetaProperty::InvalidProperty; - else if (type == qMetaTypeId<QmlBindableValue *>()) + else if (type == qMetaTypeId<QmlBinding *>()) category = QmlMetaProperty::Bindable; else if (QmlMetaType::isList(type)) category = QmlMetaProperty::List; @@ -323,7 +323,7 @@ QmlMetaProperty::propertyCategory(const QMetaProperty &prop) else type = prop.type(); - if (type == qMetaTypeId<QmlBindableValue *>()) + if (type == qMetaTypeId<QmlBinding *>()) return Bindable; else if (QmlMetaType::isList(type)) return List; @@ -510,7 +510,7 @@ QMetaProperty QmlMetaProperty::property() const Returns the binding associated with this property, or 0 if no binding exists. */ -QmlBindableValue *QmlMetaProperty::binding() const +QmlBinding *QmlMetaProperty::binding() const { if (!isProperty() || type() & Attached) return 0; @@ -519,8 +519,8 @@ QmlBindableValue *QmlMetaProperty::binding() const for (QObjectList::ConstIterator iter = children.begin(); iter != children.end(); ++iter) { QObject *child = *iter; - if (child->metaObject() == &QmlBindableValue::staticMetaObject) { - QmlBindableValue *v = static_cast<QmlBindableValue *>(child); + if (child->metaObject() == &QmlBinding::staticMetaObject) { + QmlBinding *v = static_cast<QmlBinding *>(child); if (v->property() == *this) return v; } @@ -535,7 +535,7 @@ QmlBindableValue *QmlMetaProperty::binding() const \a binding will be enabled, and the returned binding (if any) will be disabled. */ -QmlBindableValue *QmlMetaProperty::setBinding(QmlBindableValue *binding) const +QmlBinding *QmlMetaProperty::setBinding(QmlBinding *binding) const { if (!isProperty() || type() & Attached) return 0; @@ -544,8 +544,8 @@ QmlBindableValue *QmlMetaProperty::setBinding(QmlBindableValue *binding) const for (QObjectList::ConstIterator iter = children.begin(); iter != children.end(); ++iter) { QObject *child = *iter; - if (child->metaObject() == &QmlBindableValue::staticMetaObject) { - QmlBindableValue *v = static_cast<QmlBindableValue *>(child); + if (child->metaObject() == &QmlBinding::staticMetaObject) { + QmlBinding *v = static_cast<QmlBinding *>(child); if (v->property() == *this && v->enabled()) { v->setEnabled(false); diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h index 688c4fd..fdcf9be 100644 --- a/src/declarative/qml/qmlmetaproperty.h +++ b/src/declarative/qml/qmlmetaproperty.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QObject; -class QmlBindableValue; +class QmlBinding; class QStringList; class QVariant; struct QMetaObject; @@ -121,8 +121,8 @@ public: QMetaProperty property() const; - QmlBindableValue *binding() const; - QmlBindableValue *setBinding(QmlBindableValue *) const; + QmlBinding *binding() const; + QmlBinding *setBinding(QmlBinding *) const; static QmlMetaProperty createProperty(QObject *, const QString &); diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index 8eb58c8..9eed3f1 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -47,7 +47,6 @@ #include <QSizeF> #include <QRectF> #include <private/qmlvme_p.h> -#include <qmlbindablevalue.h> #include <private/qfxperf_p.h> #include <qml.h> #include "private/qmlcomponent_p.h" diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index f468cd0..58b8689 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -57,13 +57,13 @@ #include <qmlengine.h> #include <qmlcontext.h> #include <qmlcomponent.h> -#include <qmlbindablevalue.h> +#include <qmlbinding.h> #include <private/qmlengine_p.h> #include <private/qmlcomponent_p.h> #include "private/qmlvmemetaobject_p.h" #include <QtCore/qdebug.h> #include <QtCore/qvarlengtharray.h> -#include <private/qmlbindablevalue_p.h> +#include <private/qmlbinding_p.h> QT_BEGIN_NAMESPACE @@ -137,7 +137,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData const QList<float> &floatData = comp->floatData; - QmlEnginePrivate::SimpleList<QmlBindableValue> bindValues; + QmlEnginePrivate::SimpleList<QmlBinding> bindValues; QmlEnginePrivate::SimpleList<QmlParserStatus> parserStatus; QStack<ListInstance> qliststack; @@ -153,7 +153,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData case QmlInstruction::Init: { if (instr.init.bindingsSize) - bindValues = QmlEnginePrivate::SimpleList<QmlBindableValue>(instr.init.bindingsSize); + bindValues = QmlEnginePrivate::SimpleList<QmlBinding>(instr.init.bindingsSize); if (instr.init.parserStatusSize) parserStatus = QmlEnginePrivate::SimpleList<QmlParserStatus>(instr.init.parserStatusSize); } @@ -540,10 +540,10 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData QmlMetaProperty mp(target, instr.assignBinding.property, (QmlMetaProperty::PropertyCategory)instr.assignBinding.category); - QmlBindableValue *bind = new QmlBindableValue((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, 0); + QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, 0); bindValues.append(bind); - QmlBindableValuePrivate *p = - static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bind)); + QmlBindingPrivate *p = + static_cast<QmlBindingPrivate *>(QObjectPrivate::get(bind)); p->mePtr = &bindValues.values[bindValues.count - 1]; QFx_setParent_noEvent(bind, target); @@ -560,10 +560,10 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData QmlMetaProperty mp(target, instr.assignBinding.property, (QmlMetaProperty::PropertyCategory)instr.assignBinding.category); - QmlBindableValue *bind = new QmlBindableValue(primitives.at(instr.assignBinding.value), context, ctxt); + QmlBinding *bind = new QmlBinding(primitives.at(instr.assignBinding.value), context, ctxt); bindValues.append(bind); - QmlBindableValuePrivate *p = - static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bind)); + QmlBindingPrivate *p = + static_cast<QmlBindingPrivate *>(QObjectPrivate::get(bind)); p->mePtr = &bindValues.values[bindValues.count - 1]; QFx_setParent_noEvent(bind, target); diff --git a/src/declarative/qml/qpodvector_p.h b/src/declarative/qml/qpodvector_p.h index 101c62d..e74f9f6 100644 --- a/src/declarative/qml/qpodvector_p.h +++ b/src/declarative/qml/qpodvector_p.h @@ -64,7 +64,7 @@ public: QPODVector() : m_count(0), m_capacity(0), m_data(0) {} - const T &at(int idx) { + const T &at(int idx) const { return m_data[idx]; } diff --git a/src/declarative/util/qfxperf.cpp b/src/declarative/util/qfxperf.cpp index db56b37..f768827 100644 --- a/src/declarative/util/qfxperf.cpp +++ b/src/declarative/util/qfxperf.cpp @@ -51,7 +51,7 @@ Q_DEFINE_PERFORMANCE_LOG(QFxPerf, "QFx") { Q_DEFINE_PERFORMANCE_METRIC(BindValue, "BindValue execution") Q_DEFINE_PERFORMANCE_METRIC(BindValueSSE, "BindValue execution SSE") Q_DEFINE_PERFORMANCE_METRIC(BindValueQt, "BindValue execution QtScript") - Q_DEFINE_PERFORMANCE_METRIC(BindableValueUpdate, "QmlBindableValue::update") + Q_DEFINE_PERFORMANCE_METRIC(BindableValueUpdate, "QmlBinding::update") Q_DEFINE_PERFORMANCE_METRIC(PixmapLoad, "Pixmap loading") Q_DEFINE_PERFORMANCE_METRIC(FontDatabase, "Font database creation") Q_DEFINE_PERFORMANCE_METRIC(QFxPathViewPathCache, "FX Items: QFxPathView: Path cache") diff --git a/src/declarative/util/qfxview.cpp b/src/declarative/util/qfxview.cpp index d83de28..96d9e8e 100644 --- a/src/declarative/util/qfxview.cpp +++ b/src/declarative/util/qfxview.cpp @@ -51,7 +51,6 @@ #include "qboxlayout.h" #include "qbasictimer.h" -#include "qmlbindablevalue.h" #include "qml.h" #include "qfxitem.h" #include "private/qperformancelog_p.h" diff --git a/src/declarative/util/qmlbind.cpp b/src/declarative/util/qmlbind.cpp index bb342bc..7493b12 100644 --- a/src/declarative/util/qmlbind.cpp +++ b/src/declarative/util/qmlbind.cpp @@ -39,7 +39,6 @@ ** ****************************************************************************/ -#include <qmlbindablevalue.h> #include <QtDeclarative/qmlengine.h> #include <QtDeclarative/qmlcontext.h> #include <private/qobject_p.h> diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index 8edd871..0c167c0 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -46,7 +46,6 @@ #include <private/qmlparser_p.h> #include "qmlopenmetaobject.h" #include <qmlcontext.h> -#include <qmlbindablevalue.h> #include "qmllistmodel.h" Q_DECLARE_METATYPE(QListModelInterface *) diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp index 8d03804..7199341 100644 --- a/src/declarative/util/qmlscript.cpp +++ b/src/declarative/util/qmlscript.cpp @@ -39,7 +39,6 @@ ** ****************************************************************************/ -#include <qmlbindablevalue.h> #include <QtDeclarative/qmlengine.h> #include <QtDeclarative/qmlcontext.h> #include <private/qobject_p.h> diff --git a/src/declarative/util/qmlsetproperties.cpp b/src/declarative/util/qmlsetproperties.cpp index 6464e33..ffd1e6a 100644 --- a/src/declarative/util/qmlsetproperties.cpp +++ b/src/declarative/util/qmlsetproperties.cpp @@ -47,7 +47,7 @@ #include <private/qmlcustomparser_p.h> #include <private/qmlparser_p.h> #include <QtDeclarative/qmlexpression.h> -#include <QtDeclarative/qmlbindablevalue.h> +#include <QtDeclarative/qmlbinding.h> QT_BEGIN_NAMESPACE @@ -334,7 +334,7 @@ QmlSetProperties::ActionList QmlSetProperties::actions() if (d->isExplicit) { a.toValue = d->expressions.at(ii).second->value(); } else { - a.toBinding = new QmlBindableValue(d->expressions.at(ii).second->expression(), object(), qmlContext(this)); + a.toBinding = new QmlBinding(d->expressions.at(ii).second->expression(), object(), qmlContext(this)); a.toBinding->setTarget(prop); } diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp index e3cff38..73ea9c2 100644 --- a/src/declarative/util/qmlstate.cpp +++ b/src/declarative/util/qmlstate.cpp @@ -42,7 +42,7 @@ #include "qmltransition.h" #include "qmlstategroup.h" #include "qmlstate_p.h" -#include "qmlbindablevalue.h" +#include "qmlbinding.h" #include "qmlstateoperations.h" #include "qmlanimation.h" #include "qmlanimation_p.h" @@ -175,13 +175,13 @@ bool QmlState::isWhenKnown() const This should be set to an expression that evaluates to true when you want the state to be applied. */ -QmlBindableValue *QmlState::when() const +QmlBinding *QmlState::when() const { Q_D(const QmlState); return d->when; } -void QmlState::setWhen(QmlBindableValue *when) +void QmlState::setWhen(QmlBinding *when) { Q_D(QmlState); d->when = when; diff --git a/src/declarative/util/qmlstate.h b/src/declarative/util/qmlstate.h index 7532430..90649a1 100644 --- a/src/declarative/util/qmlstate.h +++ b/src/declarative/util/qmlstate.h @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class ActionEvent; -class QmlBindableValue; +class QmlBinding; class Action { public: @@ -68,8 +68,8 @@ public: QVariant fromValue; QVariant toValue; - QmlBindableValue *fromBinding; - QmlBindableValue *toBinding; + QmlBinding *fromBinding; + QmlBinding *toBinding; ActionEvent *event; QObject *specifiedObject; @@ -111,7 +111,7 @@ class Q_DECLARATIVE_EXPORT QmlState : public QObject Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName) - Q_PROPERTY(QmlBindableValue *when READ when WRITE setWhen) + Q_PROPERTY(QmlBinding *when READ when WRITE setWhen) Q_PROPERTY(QString extends READ extends WRITE setExtends) Q_PROPERTY(QmlList<QmlStateOperation *>* operations READ operations) Q_CLASSINFO("DefaultProperty", "operations") @@ -123,11 +123,11 @@ public: QString name() const; void setName(const QString &); - /*'when' is a QmlBindableValue to limit state changes oscillation + /*'when' is a QmlBinding to limit state changes oscillation due to the unpredictable order of evaluation of bound expressions*/ bool isWhenKnown() const; - QmlBindableValue *when() const; - void setWhen(QmlBindableValue *); + QmlBinding *when() const; + void setWhen(QmlBinding *); QString extends() const; void setExtends(const QString &); diff --git a/src/declarative/util/qmlstate_p.h b/src/declarative/util/qmlstate_p.h index 414ec08..73e2377 100644 --- a/src/declarative/util/qmlstate_p.h +++ b/src/declarative/util/qmlstate_p.h @@ -80,7 +80,7 @@ public: QmlMetaProperty property; QVariant value; - QmlBindableValue *binding; + QmlBinding *binding; QObject *specifiedObject; QString specifiedProperty; }; @@ -96,7 +96,7 @@ public: typedef QList<SimpleAction> SimpleActionList; QString name; - QmlBindableValue *when; + QmlBinding *when; QmlConcreteList<QmlStateOperation *> operations; QmlTransitionManager transitionManager; diff --git a/src/declarative/util/qmlstategroup.cpp b/src/declarative/util/qmlstategroup.cpp index 2b1cf7d..946569c 100644 --- a/src/declarative/util/qmlstategroup.cpp +++ b/src/declarative/util/qmlstategroup.cpp @@ -40,9 +40,9 @@ ****************************************************************************/ #include "private/qobject_p.h" -#include "qmlbindablevalue.h" #include "qmlstategroup.h" #include "qmltransition.h" +#include <QtDeclarative/qmlbinding.h> #include <QtCore/qdebug.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/util/qmlstateoperations.cpp b/src/declarative/util/qmlstateoperations.cpp index 5bb2cb6..8d6abe6 100644 --- a/src/declarative/util/qmlstateoperations.cpp +++ b/src/declarative/util/qmlstateoperations.cpp @@ -42,7 +42,7 @@ #include <private/qobject_p.h> #include <qml.h> #include <QtDeclarative/qmlcontext.h> -#include "qmlbindablevalue.h" +#include <QtDeclarative/qmlexpression.h> #include "qmlstateoperations.h" #include <QtCore/qdebug.h> #include <QtDeclarative/qmlinfo.h> diff --git a/src/declarative/util/qmltransition.cpp b/src/declarative/util/qmltransition.cpp index d793c7d..dffa6b5 100644 --- a/src/declarative/util/qmltransition.cpp +++ b/src/declarative/util/qmltransition.cpp @@ -42,7 +42,6 @@ #include "qmlstate.h" #include "qmlstategroup.h" #include "qmlstate_p.h" -#include "qmlbindablevalue.h" #include "qmlstateoperations.h" #include "qmlanimation.h" #include "qmlanimation_p.h" diff --git a/src/declarative/util/qmltransitionmanager.cpp b/src/declarative/util/qmltransitionmanager.cpp index ba4e160..6f1a8e3 100644 --- a/src/declarative/util/qmltransitionmanager.cpp +++ b/src/declarative/util/qmltransitionmanager.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include <QtDeclarative/qmlbindablevalue.h> +#include <QtDeclarative/qmlbinding.h> #include <private/qmltransitionmanager_p.h> #include <private/qmlstate_p.h> diff --git a/tests/benchmarks/declarative/binding/binding.pro b/tests/benchmarks/declarative/binding/binding.pro new file mode 100644 index 0000000..26ee4fa --- /dev/null +++ b/tests/benchmarks/declarative/binding/binding.pro @@ -0,0 +1,8 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_binding +QT += declarative + +SOURCES += tst_binding.cpp testtypes.cpp +HEADERS += testtypes.h + diff --git a/tests/benchmarks/declarative/binding/idproperty.txt b/tests/benchmarks/declarative/binding/idproperty.txt new file mode 100644 index 0000000..0a98e0d --- /dev/null +++ b/tests/benchmarks/declarative/binding/idproperty.txt @@ -0,0 +1,7 @@ +MyQmlObject { + id: MyObject + + MyQmlObject { + result: ### + } +} diff --git a/tests/benchmarks/declarative/binding/localproperty.txt b/tests/benchmarks/declarative/binding/localproperty.txt new file mode 100644 index 0000000..4694d99 --- /dev/null +++ b/tests/benchmarks/declarative/binding/localproperty.txt @@ -0,0 +1,3 @@ +MyQmlObject { + result: ### +} diff --git a/tests/benchmarks/declarative/binding/objectproperty.txt b/tests/benchmarks/declarative/binding/objectproperty.txt new file mode 100644 index 0000000..597c965 --- /dev/null +++ b/tests/benchmarks/declarative/binding/objectproperty.txt @@ -0,0 +1,5 @@ +MyQmlObject { + id: MyObject + + result: ### +} diff --git a/tests/benchmarks/declarative/binding/testtypes.cpp b/tests/benchmarks/declarative/binding/testtypes.cpp new file mode 100644 index 0000000..60e69e2 --- /dev/null +++ b/tests/benchmarks/declarative/binding/testtypes.cpp @@ -0,0 +1,3 @@ +#include "testtypes.h" + +QML_DEFINE_TYPE(MyQmlObject, MyQmlObject); diff --git a/tests/benchmarks/declarative/binding/testtypes.h b/tests/benchmarks/declarative/binding/testtypes.h new file mode 100644 index 0000000..20bf5f7 --- /dev/null +++ b/tests/benchmarks/declarative/binding/testtypes.h @@ -0,0 +1,41 @@ +#ifndef TESTTYPES_H +#define TESTTYPES_H + +#include <QtCore/qobject.h> +#include <QtDeclarative/qml.h> + +class MyQmlObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(int result READ result WRITE setResult); + Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged); + Q_PROPERTY(MyQmlObject *object READ object WRITE setObject NOTIFY objectChanged); + Q_PROPERTY(QmlList<QObject *> *data READ data); + Q_CLASSINFO("DefaultProperty", "data"); +public: + MyQmlObject() : m_result(0), m_value(0), m_object(0) {} + + int result() const { return m_result; } + void setResult(int r) { m_result = r; } + + int value() const { return m_value; } + void setValue(int v) { m_value = v; emit valueChanged(); } + + QmlList<QObject *> *data() { return &m_data; } + + MyQmlObject *object() const { return m_object; } + void setObject(MyQmlObject *o) { m_object = o; emit objectChanged(); } + +signals: + void valueChanged(); + void objectChanged(); + +private: + QmlConcreteList<QObject *> m_data; + int m_result; + int m_value; + MyQmlObject *m_object; +}; +QML_DECLARE_TYPE(MyQmlObject); + +#endif // TESTTYPES_H diff --git a/tests/benchmarks/declarative/binding/tst_binding.cpp b/tests/benchmarks/declarative/binding/tst_binding.cpp new file mode 100644 index 0000000..e593382 --- /dev/null +++ b/tests/benchmarks/declarative/binding/tst_binding.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +****************************************************************************/ + +#include <qtest.h> +#include <QmlEngine> +#include <QmlComponent> +#include <QFile> +#include <QDebug> +#include "testtypes.h" + +//TESTED_FILES= + +class tst_binding : public QObject +{ + Q_OBJECT + +public: + tst_binding(); + virtual ~tst_binding(); + +public slots: + void init(); + void cleanup(); + +private slots: + void objectproperty_data(); + void objectproperty(); + void basicproperty_data(); + void basicproperty(); + +private: + QmlEngine engine; +}; + +tst_binding::tst_binding() +{ +} + +tst_binding::~tst_binding() +{ +} + +void tst_binding::init() +{ +} + +void tst_binding::cleanup() +{ +} + +#define COMPONENT(filename, binding) \ + QmlComponent c(&engine); \ + { \ + QFile f(filename); \ + QVERIFY(f.open(QIODevice::ReadOnly)); \ + QByteArray data = f.readAll(); \ + data.replace("###", binding.toUtf8()); \ + c.setData(data, QUrl()); \ + QVERIFY(c.isReady()); \ + } + +void tst_binding::objectproperty_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("binding"); + + QTest::newRow("object.value") << "objectproperty.txt" << "object.value"; + QTest::newRow("object.value + 10") << "objectproperty.txt" << "object.value + 10"; +} + +void tst_binding::objectproperty() +{ + QFETCH(QString, file); + QFETCH(QString, binding); + + COMPONENT(file, binding); + + MyQmlObject object1; + MyQmlObject object2; + + MyQmlObject *object = qobject_cast<MyQmlObject *>(c.create()); + QVERIFY(object != 0); + object->setObject(&object2); + + QBENCHMARK { + object->setObject(&object1); + object->setObject(&object2); + } +} + +void tst_binding::basicproperty_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("binding"); + + QTest::newRow("value") << "localproperty.txt" << "value"; + QTest::newRow("value + 10") << "localproperty.txt" << "value + 10"; + QTest::newRow("value + value + 10") << "localproperty.txt" << "value + value + 10"; + + QTest::newRow("MyObject.value") << "idproperty.txt" << "MyObject.value"; + QTest::newRow("MyObject.value + 10") << "idproperty.txt" << "MyObject.value + 10"; + QTest::newRow("MyObject.value + MyObject.value + 10") << "idproperty.txt" << "MyObject.value + MyObject.value + 10"; +} + +void tst_binding::basicproperty() +{ + QFETCH(QString, file); + QFETCH(QString, binding); + + COMPONENT(file, binding); + + MyQmlObject *object = qobject_cast<MyQmlObject *>(c.create()); + QVERIFY(object != 0); + object->setValue(10); + + QBENCHMARK { + object->setValue(1); + } +} + +QTEST_MAIN(tst_binding) +#include "tst_binding.moc" diff --git a/tests/benchmarks/declarative/qmlcomponent/myqmlobject.txt b/tests/benchmarks/declarative/qmlcomponent/myqmlobject.txt new file mode 100644 index 0000000..05ed87a --- /dev/null +++ b/tests/benchmarks/declarative/qmlcomponent/myqmlobject.txt @@ -0,0 +1 @@ +MyQmlObject {} diff --git a/tests/benchmarks/declarative/qmlcomponent/myqmlobject_binding.txt b/tests/benchmarks/declarative/qmlcomponent/myqmlobject_binding.txt new file mode 100644 index 0000000..4dfa7c3 --- /dev/null +++ b/tests/benchmarks/declarative/qmlcomponent/myqmlobject_binding.txt @@ -0,0 +1,4 @@ +MyQmlObject { + result: value +} + diff --git a/tests/benchmarks/declarative/qmlcomponent/object.txt b/tests/benchmarks/declarative/qmlcomponent/object.txt new file mode 100644 index 0000000..7dc75192 --- /dev/null +++ b/tests/benchmarks/declarative/qmlcomponent/object.txt @@ -0,0 +1 @@ +Object {} diff --git a/tests/benchmarks/declarative/qmlcomponent/qmlcomponent.pro b/tests/benchmarks/declarative/qmlcomponent/qmlcomponent.pro new file mode 100644 index 0000000..5f0cbe6 --- /dev/null +++ b/tests/benchmarks/declarative/qmlcomponent/qmlcomponent.pro @@ -0,0 +1,8 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qmlcomponent +QT += declarative + +SOURCES += tst_qmlcomponent.cpp testtypes.cpp +HEADERS += testtypes.h + diff --git a/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.2.txt b/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.2.txt new file mode 100644 index 0000000..d59104d --- /dev/null +++ b/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.2.txt @@ -0,0 +1,13 @@ +Object { + property int a + property bool b + property double c + property real d + property string e + property url f + property color g + property date h + property var i + property variant j +} + diff --git a/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.txt b/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.txt new file mode 100644 index 0000000..d9eb708 --- /dev/null +++ b/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.txt @@ -0,0 +1,3 @@ +Object { + property int a +} diff --git a/tests/benchmarks/declarative/qmlcomponent/testtypes.cpp b/tests/benchmarks/declarative/qmlcomponent/testtypes.cpp new file mode 100644 index 0000000..60e69e2 --- /dev/null +++ b/tests/benchmarks/declarative/qmlcomponent/testtypes.cpp @@ -0,0 +1,3 @@ +#include "testtypes.h" + +QML_DEFINE_TYPE(MyQmlObject, MyQmlObject); diff --git a/tests/benchmarks/declarative/qmlcomponent/testtypes.h b/tests/benchmarks/declarative/qmlcomponent/testtypes.h new file mode 100644 index 0000000..20bf5f7 --- /dev/null +++ b/tests/benchmarks/declarative/qmlcomponent/testtypes.h @@ -0,0 +1,41 @@ +#ifndef TESTTYPES_H +#define TESTTYPES_H + +#include <QtCore/qobject.h> +#include <QtDeclarative/qml.h> + +class MyQmlObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(int result READ result WRITE setResult); + Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged); + Q_PROPERTY(MyQmlObject *object READ object WRITE setObject NOTIFY objectChanged); + Q_PROPERTY(QmlList<QObject *> *data READ data); + Q_CLASSINFO("DefaultProperty", "data"); +public: + MyQmlObject() : m_result(0), m_value(0), m_object(0) {} + + int result() const { return m_result; } + void setResult(int r) { m_result = r; } + + int value() const { return m_value; } + void setValue(int v) { m_value = v; emit valueChanged(); } + + QmlList<QObject *> *data() { return &m_data; } + + MyQmlObject *object() const { return m_object; } + void setObject(MyQmlObject *o) { m_object = o; emit objectChanged(); } + +signals: + void valueChanged(); + void objectChanged(); + +private: + QmlConcreteList<QObject *> m_data; + int m_result; + int m_value; + MyQmlObject *m_object; +}; +QML_DECLARE_TYPE(MyQmlObject); + +#endif // TESTTYPES_H diff --git a/tests/benchmarks/declarative/qmlcomponent/tst_qmlcomponent.cpp b/tests/benchmarks/declarative/qmlcomponent/tst_qmlcomponent.cpp new file mode 100644 index 0000000..1920bf2 --- /dev/null +++ b/tests/benchmarks/declarative/qmlcomponent/tst_qmlcomponent.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +****************************************************************************/ + +#include <qtest.h> +#include <QmlEngine> +#include <QmlComponent> +#include <QFile> +#include <QDebug> +#include "testtypes.h" + +//TESTED_FILES= + + +class tst_qmlcomponent : public QObject +{ + Q_OBJECT + +public: + tst_qmlcomponent(); + virtual ~tst_qmlcomponent(); + +public slots: + void init(); + void cleanup(); + +private slots: + void creation_data(); + void creation(); + +private: + QmlEngine engine; +}; + +tst_qmlcomponent::tst_qmlcomponent() +{ +} + +tst_qmlcomponent::~tst_qmlcomponent() +{ +} + +void tst_qmlcomponent::init() +{ +} + +void tst_qmlcomponent::cleanup() +{ +} + +void tst_qmlcomponent::creation_data() +{ + QTest::addColumn<QString>("file"); + + QTest::newRow("Object") << "object.txt"; + QTest::newRow("MyQmlObject") << "myqmlobject.txt"; + QTest::newRow("MyQmlObject: basic binding") << "myqmlobject_binding.txt"; + QTest::newRow("Synthesized properties") << "synthesized_properties.txt"; + QTest::newRow("Synthesized properties.2") << "synthesized_properties.2.txt"; +} + +void tst_qmlcomponent::creation() +{ + QFETCH(QString, file); + + QmlComponent c(&engine, file); + QVERIFY(c.isReady()); + + QBENCHMARK { + QObject *obj = c.create(); + delete obj; + } +} + +QTEST_MAIN(tst_qmlcomponent) +#include "tst_qmlcomponent.moc" diff --git a/tools/qmlviewer/qmlviewer.cpp b/tools/qmlviewer/qmlviewer.cpp index 8f99206..7844b5a 100644 --- a/tools/qmlviewer/qmlviewer.cpp +++ b/tools/qmlviewer/qmlviewer.cpp @@ -13,7 +13,6 @@ #include <qfxview.h> -#include "qmlbindablevalue.h" #include "qmlviewer.h" #include <QtDeclarative/qmlcontext.h> #include <QtDeclarative/qmlengine.h> |