1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qdeclarativeexpression.h"
43 #include "private/qdeclarativeexpression_p.h"
45 #include "private/qdeclarativeengine_p.h"
46 #include "private/qdeclarativecontext_p.h"
47 #include "private/qdeclarativerewrite_p.h"
48 #include "private/qdeclarativescriptstring_p.h"
49 #include "private/qdeclarativecompiler_p.h"
51 #include <QtCore/qdebug.h>
55 bool QDeclarativeDelayedError::addError(QDeclarativeEnginePrivate *e)
59 if (e->inProgressCreations == 0) return false; // Not in construction
61 if (prevError) return true; // Already in error chain
63 prevError = &e->erroredBindings;
64 nextError = e->erroredBindings;
65 e->erroredBindings = this;
66 if (nextError) nextError->prevError = &nextError;
71 QDeclarativeJavaScriptExpression::QDeclarativeJavaScriptExpression()
72 : m_requiresThisObject(0), m_useSharedContext(0), m_notifyOnValueChanged(0),
73 m_scopeObject(0), m_notifyObject(0), m_notifyIndex(-1)
77 QDeclarativeJavaScriptExpression::~QDeclarativeJavaScriptExpression()
81 QDeclarativeExpressionPrivate::QDeclarativeExpressionPrivate()
82 : expressionFunctionValid(true), extractExpressionFromFunction(false), line(-1), dataRef(0)
86 QDeclarativeExpressionPrivate::~QDeclarativeExpressionPrivate()
88 qPersistentDispose(v8qmlscope);
89 qPersistentDispose(v8function);
90 if (dataRef) dataRef->release();
94 void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QString &expr,
99 QDeclarativeAbstractExpression::setContext(ctxt);
101 expressionFunctionValid = false;
104 void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, v8::Handle<v8::Function> func,
107 QDeclarativeAbstractExpression::setContext(ctxt);
110 v8function = qPersistentNew<v8::Function>(func);
111 setUseSharedContext(false);
112 expressionFunctionValid = true;
113 extractExpressionFromFunction = true;
116 void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QString &expr, bool isRewritten,
117 QObject *me, const QString &srcUrl, int lineNumber)
125 expressionFunctionValid = false;
127 v8function = evalFunction(ctxt, me, expression, url, line, &v8qmlscope);
128 expressionFunctionValid = true;
131 QDeclarativeAbstractExpression::setContext(ctxt);
135 // Callee owns the persistent handle
136 v8::Persistent<v8::Function>
137 QDeclarativeExpressionPrivate::evalFunction(QDeclarativeContextData *ctxt, QObject *scope,
138 const QString &code, const QString &filename, int line,
139 v8::Persistent<v8::Object> *qmlscope)
141 QDeclarativeEngine *engine = ctxt->engine;
142 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
144 // XXX TODO: Implement script caching, like we used to do with QScriptProgram in the
146 v8::HandleScope handle_scope;
147 v8::Context::Scope ctxtscope(ep->v8engine.context());
150 v8::Local<v8::Object> scopeobject = ep->v8engine.qmlScope(ctxt, scope);
151 v8::Local<v8::Script> script = ep->v8engine.qmlModeCompile(code, filename, line);
152 v8::Local<v8::Value> result = script->Run(scopeobject);
153 if (tc.HasCaught()) return v8::Persistent<v8::Function>();
154 if (qmlscope) *qmlscope = qPersistentNew<v8::Object>(scopeobject);
155 return qPersistentNew<v8::Function>(v8::Local<v8::Function>::Cast(result));
159 \class QDeclarativeExpression
161 \brief The QDeclarativeExpression class evaluates JavaScript in a QML context.
163 For example, given a file \c main.qml like this:
169 width: 200; height: 200
173 The following code evaluates a JavaScript expression in the context of the
177 QDeclarativeEngine *engine = new QDeclarativeEngine;
178 QDeclarativeComponent component(engine, QUrl::fromLocalFile("main.qml"));
180 QObject *myObject = component.create();
181 QDeclarativeExpression *expr = new QDeclarativeExpression(engine->rootContext(), myObject, "width * 2");
182 int result = expr->evaluate().toInt(); // result = 400
186 static int QDeclarativeExpression_notifyIdx = -1;
189 Create an invalid QDeclarativeExpression.
191 As the expression will not have an associated QDeclarativeContext, this will be a
192 null expression object and its value will always be an invalid QVariant.
194 QDeclarativeExpression::QDeclarativeExpression()
195 : QObject(*new QDeclarativeExpressionPrivate, 0)
197 Q_D(QDeclarativeExpression);
199 if (QDeclarativeExpression_notifyIdx == -1)
200 QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
201 d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
205 QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt,
206 QObject *object, const QString &expr, bool isRewritten,
207 const QString &url, int lineNumber,
208 QDeclarativeExpressionPrivate &dd)
211 Q_D(QDeclarativeExpression);
212 d->init(ctxt, expr, isRewritten, object, url, lineNumber);
214 if (QDeclarativeExpression_notifyIdx == -1)
215 QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
216 d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
220 Create a QDeclarativeExpression object that is a child of \a parent.
222 The \script provides the expression to be evaluated, the context to evaluate it in,
223 and the scope object to evaluate it with.
225 This constructor is functionally equivalent to the following, but in most cases
228 QDeclarativeExpression expression(script.context(), script.scopeObject(), script.script(), parent);
231 \sa QDeclarativeScriptString
233 QDeclarativeExpression::QDeclarativeExpression(const QDeclarativeScriptString &script, QObject *parent)
234 : QObject(*new QDeclarativeExpressionPrivate, parent)
236 Q_D(QDeclarativeExpression);
237 bool defaultConstruction = false;
239 int id = script.d.data()->bindingId;
241 defaultConstruction = true;
243 QDeclarativeContextData *ctxtdata = QDeclarativeContextData::get(script.context());
245 QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(qmlEngine(script.scopeObject()));
246 QDeclarativeCompiledData *cdata = 0;
247 QDeclarativeTypeData *typeData = 0;
248 if (engine && ctxtdata && !ctxtdata->url.isEmpty()) {
249 typeData = engine->typeLoader.get(ctxtdata->url);
250 cdata = typeData->compiledData();
254 d->init(ctxtdata, cdata->primitives.at(id), cdata, script.scopeObject(),
255 cdata->name, script.d.data()->lineNumber);
257 defaultConstruction = true;
263 if (defaultConstruction)
264 d->init(QDeclarativeContextData::get(script.context()), script.script(), script.scopeObject());
266 if (QDeclarativeExpression_notifyIdx == -1)
267 QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
268 d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
272 Create a QDeclarativeExpression object that is a child of \a parent.
274 The \a expression JavaScript will be executed in the \a ctxt QDeclarativeContext.
275 If specified, the \a scope object's properties will also be in scope during
276 the expression's execution.
278 QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContext *ctxt,
280 const QString &expression,
282 : QObject(*new QDeclarativeExpressionPrivate, parent)
284 Q_D(QDeclarativeExpression);
285 d->init(QDeclarativeContextData::get(ctxt), expression, scope);
287 if (QDeclarativeExpression_notifyIdx == -1)
288 QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
289 d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
295 QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QObject *scope,
296 const QString &expression)
297 : QObject(*new QDeclarativeExpressionPrivate, 0)
299 Q_D(QDeclarativeExpression);
300 d->init(ctxt, expression, scope);
302 if (QDeclarativeExpression_notifyIdx == -1)
303 QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
304 d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
308 QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QObject *scope,
309 const QString &expression, QDeclarativeExpressionPrivate &dd)
312 Q_D(QDeclarativeExpression);
313 d->init(ctxt, expression, scope);
315 if (QDeclarativeExpression_notifyIdx == -1)
316 QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
317 d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
323 To avoid exposing v8 in the public API, functionPtr must be a pointer to a v8::Handle<v8::Function>.
325 v8::Handle<v8::Function> function;
326 new QDeclarativeExpression(ctxt, scope, &function, ...);
328 QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QObject *scope, void *functionPtr,
329 QDeclarativeExpressionPrivate &dd)
332 v8::Handle<v8::Function> function = *(v8::Handle<v8::Function> *)functionPtr;
334 Q_D(QDeclarativeExpression);
335 d->init(ctxt, function, scope);
337 if (QDeclarativeExpression_notifyIdx == -1)
338 QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
340 d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
344 Destroy the QDeclarativeExpression instance.
346 QDeclarativeExpression::~QDeclarativeExpression()
351 Returns the QDeclarativeEngine this expression is associated with, or 0 if there
352 is no association or the QDeclarativeEngine has been destroyed.
354 QDeclarativeEngine *QDeclarativeExpression::engine() const
356 Q_D(const QDeclarativeExpression);
357 return d->context()?d->context()->engine:0;
361 Returns the QDeclarativeContext this expression is associated with, or 0 if there
362 is no association or the QDeclarativeContext has been destroyed.
364 QDeclarativeContext *QDeclarativeExpression::context() const
366 Q_D(const QDeclarativeExpression);
367 QDeclarativeContextData *data = d->context();
368 return data?data->asQDeclarativeContext():0;
372 Returns the expression string.
374 QString QDeclarativeExpression::expression() const
376 Q_D(const QDeclarativeExpression);
377 if (d->extractExpressionFromFunction && context()->engine()) {
378 QV8Engine *v8engine = QDeclarativeEnginePrivate::getV8Engine(context()->engine());
379 v8::HandleScope handle_scope;
380 v8::Context::Scope scope(v8engine->context());
382 return v8engine->toString(v8::Handle<v8::Value>(d->v8function));
384 return d->expression;
388 Set the expression to \a expression.
390 void QDeclarativeExpression::setExpression(const QString &expression)
392 Q_D(QDeclarativeExpression);
394 d->resetNotifyOnValueChanged();
395 d->expression = expression;
396 d->expressionFunctionValid = false;
397 qPersistentDispose(d->v8function);
398 qPersistentDispose(d->v8qmlscope);
401 void QDeclarativeExpressionPrivate::exceptionToError(v8::Handle<v8::Message> message,
402 QDeclarativeError &error)
404 Q_ASSERT(!message.IsEmpty());
406 v8::Handle<v8::Value> name = message->GetScriptResourceName();
407 v8::Handle<v8::String> description = message->Get();
408 int lineNumber = message->GetLineNumber();
410 Q_ASSERT(name->IsString());
412 v8::Local<v8::String> file = name->ToString();
413 if (file->Length() == 0)
414 error.setUrl(QUrl(QLatin1String("<Unknown File>")));
416 error.setUrl(QUrl(QV8Engine::toStringStatic(file)));
418 error.setLine(lineNumber);
421 QString qDescription = QV8Engine::toStringStatic(description);
422 if (qDescription.startsWith(QLatin1String("Uncaught ")))
423 qDescription = qDescription.mid(9 /* strlen("Uncaught ") */);
425 error.setDescription(qDescription);
428 void QDeclarativeJavaScriptExpression::setNotifyOnValueChanged(bool v)
430 m_notifyOnValueChanged = v;
431 if (!v) guardList.clear();
434 void QDeclarativeJavaScriptExpression::resetNotifyOnValueChanged()
439 void QDeclarativeJavaScriptExpression::setNotifyObject(QObject *object, int index)
443 m_notifyObject = object;
444 m_notifyIndex = index;
446 if (!object || index == -1) {
452 v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::Function> function, bool *isUndefined)
454 Q_ASSERT(context() && context()->engine);
455 Q_ASSERT(!notifyOnValueChanged() || (m_notifyObject && m_notifyIndex != -1));
457 if (function.IsEmpty() || function->IsUndefined()) {
458 if (isUndefined) *isUndefined = true;
459 return v8::Local<v8::Value>();
462 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context()->engine);
464 bool lastCaptureProperties = ep->captureProperties;
465 QPODVector<QDeclarativeEnginePrivate::CapturedProperty> lastCapturedProperties;
466 ep->captureProperties = notifyOnValueChanged();
468 if (ep->capturedProperties.count())
469 ep->capturedProperties.copyAndClear(lastCapturedProperties);
471 QDeclarativeContextData *lastSharedContext = 0;
472 QObject *lastSharedScope = 0;
474 bool sharedContext = useSharedContext();
476 // All code that follows must check with watcher before it accesses data members
477 // incase we have been deleted.
478 QDeclarativeDeleteWatcher watcher(this);
481 lastSharedContext = ep->sharedContext;
482 lastSharedScope = ep->sharedScope;
483 ep->sharedContext = context();
484 ep->sharedScope = scopeObject();
487 v8::Local<v8::Value> result;
489 v8::TryCatch try_catch;
490 v8::Handle<v8::Object> This = ep->v8engine.global();
491 if (scopeObject() && requiresThisObject()) {
492 v8::Handle<v8::Value> value = ep->v8engine.newQObject(scopeObject());
493 if (value->IsObject()) This = v8::Handle<v8::Object>::Cast(value);
496 result = function->Call(This, 0, 0);
499 *isUndefined = try_catch.HasCaught() || result->IsUndefined();
501 if (watcher.wasDeleted()) {
502 } else if (try_catch.HasCaught()) {
503 v8::Context::Scope scope(ep->v8engine.context());
504 v8::Local<v8::Message> message = try_catch.Message();
505 if (!message.IsEmpty()) {
506 QDeclarativeExpressionPrivate::exceptionToError(message, error);
508 error = QDeclarativeError();
511 error = QDeclarativeError();
516 ep->sharedContext = lastSharedContext;
517 ep->sharedScope = lastSharedScope;
520 if (!watcher.wasDeleted() && notifyOnValueChanged()) {
521 guardList.updateGuards(m_notifyObject, m_notifyIndex, expressionString(),
522 ep->capturedProperties);
525 if (lastCapturedProperties.count())
526 lastCapturedProperties.copyAndClear(ep->capturedProperties);
528 ep->capturedProperties.clear();
530 ep->captureProperties = lastCaptureProperties;
535 void QDeclarativeJavaScriptExpression::GuardList::updateGuards(QObject *notifyObject, int notifyIndex,
536 const QStringRef &expression,
537 const CapturedProperties &properties)
539 Q_ASSERT(notifyObject);
540 Q_ASSERT(notifyIndex != -1);
542 if (properties.count() == 0) {
547 if (properties.count() != length) {
548 QDeclarativeNotifierEndpoint *newGuardList = new QDeclarativeNotifierEndpoint[properties.count()];
550 for (int ii = 0; ii < qMin(length, properties.count()); ++ii)
551 endpoints[ii].copyAndClear(newGuardList[ii]);
554 endpoints = newGuardList;
555 length = properties.count();
558 bool outputWarningHeader = false;
559 bool noChanges = true;
560 for (int ii = 0; ii < properties.count(); ++ii) {
561 QDeclarativeNotifierEndpoint &guard = endpoints[ii];
562 const QDeclarativeEnginePrivate::CapturedProperty &property = properties.at(ii);
564 guard.target = notifyObject;
565 guard.targetMethod = notifyIndex;
567 if (property.notifier != 0) {
569 if (!noChanges && guard.isConnected(property.notifier)) {
575 bool existing = false;
576 for (int jj = 0; !existing && jj < ii; ++jj)
577 if (endpoints[jj].isConnected(property.notifier))
584 guard.connect(property.notifier);
589 } else if (property.notifyIndex != -1) {
591 if (!noChanges && guard.isConnected(property.object, property.notifyIndex)) {
597 bool existing = false;
598 for (int jj = 0; !existing && jj < ii; ++jj)
599 if (endpoints[jj].isConnected(property.object, property.notifyIndex))
606 guard.connect(property.object, property.notifyIndex);
610 } else if (!expression.isEmpty()) {
611 if (!outputWarningHeader) {
612 outputWarningHeader = true;
613 qWarning() << "QDeclarativeExpression: Expression" << expression
614 << "depends on non-NOTIFYable properties:";
617 const QMetaObject *metaObj = property.object->metaObject();
618 QMetaProperty metaProp = metaObj->property(property.coreIndex);
620 qWarning().nospace() << " " << metaObj->className() << "::" << metaProp.name();
625 // Must be called with a valid handle scope
626 v8::Local<v8::Value> QDeclarativeExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined)
628 if (!expressionFunctionValid) {
629 QDeclarativeRewrite::RewriteBinding rewriteBinding;
630 rewriteBinding.setName(name);
632 const QString code = rewriteBinding(expression, &ok);
633 if (ok) v8function = evalFunction(context(), scopeObject(), code, url, line, &v8qmlscope);
634 setUseSharedContext(false);
635 expressionFunctionValid = true;
639 if (secondaryScope) {
640 v8::Local<v8::Value> result;
641 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context()->engine);
642 QObject *restoreSecondaryScope = 0;
643 restoreSecondaryScope = ep->v8engine.contextWrapper()->setSecondaryScope(v8qmlscope, secondaryScope);
644 result = evaluate(v8function, isUndefined);
645 ep->v8engine.contextWrapper()->setSecondaryScope(v8qmlscope, restoreSecondaryScope);
648 return evaluate(v8function, isUndefined);
652 QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
654 Q_Q(QDeclarativeExpression);
656 if (!context() || !context()->isValid()) {
657 qWarning("QDeclarativeExpression: Attempted to evaluate an expression in an invalid context");
661 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine());
664 ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
667 v8::HandleScope handle_scope;
668 v8::Local<v8::Value> result = v8value(secondaryScope, isUndefined);
669 rv = ep->v8engine.toVariant(result, qMetaTypeId<QList<QObject*> >());
672 ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
678 Evaulates the expression, returning the result of the evaluation,
679 or an invalid QVariant if the expression is invalid or has an error.
681 \a valueIsUndefined is set to true if the expression resulted in an
684 \sa hasError(), error()
686 QVariant QDeclarativeExpression::evaluate(bool *valueIsUndefined)
688 Q_D(QDeclarativeExpression);
689 return d->value(0, valueIsUndefined);
693 Returns true if the valueChanged() signal is emitted when the expression's evaluated
696 bool QDeclarativeExpression::notifyOnValueChanged() const
698 Q_D(const QDeclarativeExpression);
699 return d->notifyOnValueChanged();
703 Sets whether the valueChanged() signal is emitted when the
704 expression's evaluated value changes.
706 If \a notifyOnChange is true, the QDeclarativeExpression will
707 monitor properties involved in the expression's evaluation, and emit
708 QDeclarativeExpression::valueChanged() if they have changed. This
709 allows an application to ensure that any value associated with the
710 result of the expression remains up to date.
712 If \a notifyOnChange is false (default), the QDeclarativeExpression
713 will not montitor properties involved in the expression's
714 evaluation, and QDeclarativeExpression::valueChanged() will never be
715 emitted. This is more efficient if an application wants a "one off"
716 evaluation of the expression.
718 void QDeclarativeExpression::setNotifyOnValueChanged(bool notifyOnChange)
720 Q_D(QDeclarativeExpression);
721 d->setNotifyOnValueChanged(notifyOnChange);
725 Returns the source file URL for this expression. The source location must
726 have been previously set by calling setSourceLocation().
728 QString QDeclarativeExpression::sourceFile() const
730 Q_D(const QDeclarativeExpression);
735 Returns the source file line number for this expression. The source location
736 must have been previously set by calling setSourceLocation().
738 int QDeclarativeExpression::lineNumber() const
740 Q_D(const QDeclarativeExpression);
745 Set the location of this expression to \a line of \a url. This information
746 is used by the script engine.
748 void QDeclarativeExpression::setSourceLocation(const QString &url, int line)
750 Q_D(QDeclarativeExpression);
756 Returns the expression's scope object, if provided, otherwise 0.
758 In addition to data provided by the expression's QDeclarativeContext, the scope
759 object's properties are also in scope during the expression's evaluation.
761 QObject *QDeclarativeExpression::scopeObject() const
763 Q_D(const QDeclarativeExpression);
764 return d->scopeObject();
768 Returns true if the last call to evaluate() resulted in an error,
771 \sa error(), clearError()
773 bool QDeclarativeExpression::hasError() const
775 Q_D(const QDeclarativeExpression);
776 return d->error.isValid();
780 Clear any expression errors. Calls to hasError() following this will
783 \sa hasError(), error()
785 void QDeclarativeExpression::clearError()
787 Q_D(QDeclarativeExpression);
788 d->error = QDeclarativeError();
792 Return any error from the last call to evaluate(). If there was no error,
793 this returns an invalid QDeclarativeError instance.
795 \sa hasError(), clearError()
798 QDeclarativeError QDeclarativeExpression::error() const
800 Q_D(const QDeclarativeExpression);
805 void QDeclarativeExpressionPrivate::_q_notify()
811 \fn void QDeclarativeExpression::valueChanged()
813 Emitted each time the expression value changes from the last time it was
814 evaluated. The expression must have been evaluated at least once (by
815 calling QDeclarativeExpression::evaluate()) before this signal will be emitted.
818 void QDeclarativeExpressionPrivate::emitValueChanged()
820 Q_Q(QDeclarativeExpression);
821 emit q->valueChanged();
824 QDeclarativeAbstractExpression::QDeclarativeAbstractExpression()
825 : m_context(0), m_prevExpression(0), m_nextExpression(0)
829 QDeclarativeAbstractExpression::~QDeclarativeAbstractExpression()
831 if (m_prevExpression) {
832 *m_prevExpression = m_nextExpression;
833 if (m_nextExpression)
834 m_nextExpression->m_prevExpression = m_prevExpression;
838 QDeclarativeContextData *QDeclarativeAbstractExpression::context() const
843 void QDeclarativeAbstractExpression::setContext(QDeclarativeContextData *context)
845 if (m_prevExpression) {
846 *m_prevExpression = m_nextExpression;
847 if (m_nextExpression)
848 m_nextExpression->m_prevExpression = m_prevExpression;
849 m_prevExpression = 0;
850 m_nextExpression = 0;
856 m_nextExpression = m_context->expressions;
857 if (m_nextExpression)
858 m_nextExpression->m_prevExpression = &m_nextExpression;
859 m_prevExpression = &context->expressions;
860 m_context->expressions = this;
864 void QDeclarativeAbstractExpression::refresh()
868 bool QDeclarativeAbstractExpression::isValid() const
870 return m_context != 0;
875 #include <moc_qdeclarativeexpression.cpp>