summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-07-20 06:06:19 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-07-20 08:33:23 (GMT)
commit86529642cfdc5cc5a94b735042d0807e3b57e9e1 (patch)
tree3df356de955a131abfed2c84db4f91abf639a583 /src
parent275d2a37c0c7179e7f34cc467192a8838705d7c2 (diff)
downloadQt-86529642cfdc5cc5a94b735042d0807e3b57e9e1.zip
Qt-86529642cfdc5cc5a94b735042d0807e3b57e9e1.tar.gz
Qt-86529642cfdc5cc5a94b735042d0807e3b57e9e1.tar.bz2
Rework expression stuff to use a more efficient notify handler
Diffstat (limited to 'src')
-rw-r--r--src/corelib/kernel/qguard.cpp1
-rw-r--r--src/declarative/qml/qmlbasicscript.cpp12
-rw-r--r--src/declarative/qml/qmlbasicscript_p.h3
-rw-r--r--src/declarative/qml/qmlbinding.cpp6
-rw-r--r--src/declarative/qml/qmlbinding.h3
-rw-r--r--src/declarative/qml/qmlbinding_p.h4
-rw-r--r--src/declarative/qml/qmlboundsignal.cpp6
-rw-r--r--src/declarative/qml/qmlboundsignal_p.h2
-rw-r--r--src/declarative/qml/qmlcontext.cpp2
-rw-r--r--src/declarative/qml/qmlexpression.cpp412
-rw-r--r--src/declarative/qml/qmlexpression.h39
-rw-r--r--src/declarative/qml/qmlexpression_p.h81
-rw-r--r--src/declarative/qml/qpodvector_p.h2
13 files changed, 246 insertions, 327 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/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp
index fb52b91..073642f 100644
--- a/src/declarative/qml/qmlbasicscript.cpp
+++ b/src/declarative/qml/qmlbasicscript.cpp
@@ -265,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
@@ -277,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();
}
@@ -504,7 +507,6 @@ QmlBasicScriptCompiler::fetch(int type, const QMetaObject *mo, int idx)
bool QmlBasicScriptCompiler::parseName(AST::Node *node)
{
-
QStringList nameParts;
if (!buildName(nameParts, node))
return false;
@@ -550,6 +552,8 @@ bool QmlBasicScriptCompiler::parseName(AST::Node *node)
return false;
}
+ } else {
+ return false;
}
} else {
diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h
index eacd1d8..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;
diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp
index 6a8a027..e2f4682 100644
--- a/src/declarative/qml/qmlbinding.cpp
+++ b/src/declarative/qml/qmlbinding.cpp
@@ -61,13 +61,15 @@ QmlBindingPrivate::QmlBindingPrivate()
QML_DEFINE_NOCREATE_TYPE(QmlBinding);
QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent)
-: QmlPropertyValueSource(*new QmlBindingPrivate, parent), QmlExpression(ctxt, data, rc, obj)
+: QmlExpression(ctxt, data, rc, obj, *new QmlBindingPrivate)
{
+ setParent(parent);
}
QmlBinding::QmlBinding(const QString &str, QObject *obj, QmlContext *ctxt, QObject *parent)
-: QmlPropertyValueSource(*new QmlBindingPrivate, parent), QmlExpression(ctxt, str, obj)
+: QmlExpression(ctxt, str, obj, *new QmlBindingPrivate)
{
+ setParent(parent);
}
QmlBinding::~QmlBinding()
diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h
index e208277..10d81b8 100644
--- a/src/declarative/qml/qmlbinding.h
+++ b/src/declarative/qml/qmlbinding.h
@@ -57,8 +57,7 @@ QT_MODULE(Declarative)
class QmlExpression;
class QmlContext;
class QmlBindingPrivate;
-class Q_DECLARATIVE_EXPORT QmlBinding : public QmlPropertyValueSource,
- public QmlExpression
+class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression
{
Q_OBJECT
public:
diff --git a/src/declarative/qml/qmlbinding_p.h b/src/declarative/qml/qmlbinding_p.h
index 470a62a..ec1a04a 100644
--- a/src/declarative/qml/qmlbinding_p.h
+++ b/src/declarative/qml/qmlbinding_p.h
@@ -53,13 +53,13 @@
// We mean it.
//
-#include <private/qobject_p.h>
#include <QtDeclarative/qmlbinding.h>
#include <QtDeclarative/qmlmetaproperty.h>
+#include "qmlexpression_p.h"
QT_BEGIN_NAMESPACE
-class QmlBindingPrivate : public QObjectPrivate
+class QmlBindingPrivate : public QmlExpressionPrivate
{
Q_DECLARE_PUBLIC(QmlBinding)
public:
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/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/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/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];
}