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 v8::Local<v8::String> file = name->IsString()?name->ToString():v8::Local<v8::String>();
411 if (file.IsEmpty() || file->Length() == 0)
412 error.setUrl(QUrl(QLatin1String("<Unknown File>")));
414 error.setUrl(QUrl(QV8Engine::toStringStatic(file)));
416 error.setLine(lineNumber);
419 QString qDescription = QV8Engine::toStringStatic(description);
420 if (qDescription.startsWith(QLatin1String("Uncaught ")))
421 qDescription = qDescription.mid(9 /* strlen("Uncaught ") */);
423 error.setDescription(qDescription);
426 void QDeclarativeJavaScriptExpression::setNotifyOnValueChanged(bool v)
428 m_notifyOnValueChanged = v;
429 if (!v) guardList.clear();
432 void QDeclarativeJavaScriptExpression::resetNotifyOnValueChanged()
437 void QDeclarativeJavaScriptExpression::setNotifyObject(QObject *object, int index)
441 m_notifyObject = object;
442 m_notifyIndex = index;
444 if (!object || index == -1) {
450 v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::Function> function, bool *isUndefined)
452 Q_ASSERT(context() && context()->engine);
453 Q_ASSERT(!notifyOnValueChanged() || (m_notifyObject && m_notifyIndex != -1));
455 if (function.IsEmpty() || function->IsUndefined()) {
456 if (isUndefined) *isUndefined = true;
457 return v8::Local<v8::Value>();
460 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context()->engine);
462 bool lastCaptureProperties = ep->captureProperties;
463 QPODVector<QDeclarativeEnginePrivate::CapturedProperty> lastCapturedProperties;
464 ep->captureProperties = notifyOnValueChanged();
466 if (ep->capturedProperties.count())
467 ep->capturedProperties.copyAndClear(lastCapturedProperties);
469 QDeclarativeContextData *lastSharedContext = 0;
470 QObject *lastSharedScope = 0;
472 bool sharedContext = useSharedContext();
474 // All code that follows must check with watcher before it accesses data members
475 // incase we have been deleted.
476 QDeclarativeDeleteWatcher watcher(this);
479 lastSharedContext = ep->sharedContext;
480 lastSharedScope = ep->sharedScope;
481 ep->sharedContext = context();
482 ep->sharedScope = scopeObject();
485 v8::Local<v8::Value> result;
487 v8::TryCatch try_catch;
488 v8::Handle<v8::Object> This = ep->v8engine()->global();
489 if (scopeObject() && requiresThisObject()) {
490 v8::Handle<v8::Value> value = ep->v8engine()->newQObject(scopeObject());
491 if (value->IsObject()) This = v8::Handle<v8::Object>::Cast(value);
494 result = function->Call(This, 0, 0);
497 *isUndefined = try_catch.HasCaught() || result->IsUndefined();
499 if (watcher.wasDeleted()) {
500 } else if (try_catch.HasCaught()) {
501 v8::Context::Scope scope(ep->v8engine()->context());
502 v8::Local<v8::Message> message = try_catch.Message();
503 if (!message.IsEmpty()) {
504 QDeclarativeExpressionPrivate::exceptionToError(message, error);
506 error = QDeclarativeError();
509 error = QDeclarativeError();
514 ep->sharedContext = lastSharedContext;
515 ep->sharedScope = lastSharedScope;
518 if (!watcher.wasDeleted() && notifyOnValueChanged()) {
519 guardList.updateGuards(m_notifyObject, m_notifyIndex, this, ep->capturedProperties);
522 if (lastCapturedProperties.count())
523 lastCapturedProperties.copyAndClear(ep->capturedProperties);
525 ep->capturedProperties.clear();
527 ep->captureProperties = lastCaptureProperties;
532 void QDeclarativeJavaScriptExpression::GuardList::updateGuards(QObject *notifyObject, int notifyIndex,
533 QDeclarativeJavaScriptExpression *expression,
534 const CapturedProperties &properties)
536 Q_ASSERT(notifyObject);
537 Q_ASSERT(notifyIndex != -1);
539 if (properties.count() == 0) {
544 if (properties.count() != length) {
545 QDeclarativeNotifierEndpoint *newGuardList = new QDeclarativeNotifierEndpoint[properties.count()];
547 for (int ii = 0; ii < qMin(length, properties.count()); ++ii)
548 endpoints[ii].copyAndClear(newGuardList[ii]);
551 endpoints = newGuardList;
552 length = properties.count();
555 bool outputWarningHeader = false;
556 bool noChanges = true;
557 for (int ii = 0; ii < properties.count(); ++ii) {
558 QDeclarativeNotifierEndpoint &guard = endpoints[ii];
559 const QDeclarativeEnginePrivate::CapturedProperty &property = properties.at(ii);
561 guard.target = notifyObject;
562 guard.targetMethod = notifyIndex;
564 if (property.notifier != 0) {
566 if (!noChanges && guard.isConnected(property.notifier)) {
572 bool existing = false;
573 for (int jj = 0; !existing && jj < ii; ++jj)
574 if (endpoints[jj].isConnected(property.notifier))
581 guard.connect(property.notifier);
586 } else if (property.notifyIndex != -1) {
588 if (!noChanges && guard.isConnected(property.object, property.notifyIndex)) {
594 bool existing = false;
595 for (int jj = 0; !existing && jj < ii; ++jj)
596 if (endpoints[jj].isConnected(property.object, property.notifyIndex))
603 guard.connect(property.object, property.notifyIndex);
608 if (!outputWarningHeader) {
609 QString e = expression->expressionIdentifier();
610 outputWarningHeader = true;
611 qWarning() << "QDeclarativeExpression: Expression" << qPrintable(e)
612 << "depends on non-NOTIFYable properties:";
615 const QMetaObject *metaObj = property.object->metaObject();
616 QMetaProperty metaProp = metaObj->property(property.coreIndex);
618 qWarning().nospace() << " " << metaObj->className() << "::" << metaProp.name();
623 // Must be called with a valid handle scope
624 v8::Local<v8::Value> QDeclarativeExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined)
626 if (!expressionFunctionValid) {
627 QDeclarativeRewrite::RewriteBinding rewriteBinding;
628 rewriteBinding.setName(name);
630 const QString code = rewriteBinding(expression, &ok);
631 if (ok) v8function = evalFunction(context(), scopeObject(), code, url, line, &v8qmlscope);
632 setUseSharedContext(false);
633 expressionFunctionValid = true;
637 if (secondaryScope) {
638 v8::Local<v8::Value> result;
639 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context()->engine);
640 QObject *restoreSecondaryScope = 0;
641 restoreSecondaryScope = ep->v8engine()->contextWrapper()->setSecondaryScope(v8qmlscope, secondaryScope);
642 result = evaluate(v8function, isUndefined);
643 ep->v8engine()->contextWrapper()->setSecondaryScope(v8qmlscope, restoreSecondaryScope);
646 return evaluate(v8function, isUndefined);
650 QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
652 Q_Q(QDeclarativeExpression);
654 if (!context() || !context()->isValid()) {
655 qWarning("QDeclarativeExpression: Attempted to evaluate an expression in an invalid context");
659 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine());
662 ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
665 v8::HandleScope handle_scope;
666 v8::Context::Scope context_scope(ep->v8engine()->context());
667 v8::Local<v8::Value> result = v8value(secondaryScope, isUndefined);
668 rv = ep->v8engine()->toVariant(result, qMetaTypeId<QList<QObject*> >());
671 ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
677 Evaulates the expression, returning the result of the evaluation,
678 or an invalid QVariant if the expression is invalid or has an error.
680 \a valueIsUndefined is set to true if the expression resulted in an
683 \sa hasError(), error()
685 QVariant QDeclarativeExpression::evaluate(bool *valueIsUndefined)
687 Q_D(QDeclarativeExpression);
688 return d->value(0, valueIsUndefined);
692 Returns true if the valueChanged() signal is emitted when the expression's evaluated
695 bool QDeclarativeExpression::notifyOnValueChanged() const
697 Q_D(const QDeclarativeExpression);
698 return d->notifyOnValueChanged();
702 Sets whether the valueChanged() signal is emitted when the
703 expression's evaluated value changes.
705 If \a notifyOnChange is true, the QDeclarativeExpression will
706 monitor properties involved in the expression's evaluation, and emit
707 QDeclarativeExpression::valueChanged() if they have changed. This
708 allows an application to ensure that any value associated with the
709 result of the expression remains up to date.
711 If \a notifyOnChange is false (default), the QDeclarativeExpression
712 will not montitor properties involved in the expression's
713 evaluation, and QDeclarativeExpression::valueChanged() will never be
714 emitted. This is more efficient if an application wants a "one off"
715 evaluation of the expression.
717 void QDeclarativeExpression::setNotifyOnValueChanged(bool notifyOnChange)
719 Q_D(QDeclarativeExpression);
720 d->setNotifyOnValueChanged(notifyOnChange);
724 Returns the source file URL for this expression. The source location must
725 have been previously set by calling setSourceLocation().
727 QString QDeclarativeExpression::sourceFile() const
729 Q_D(const QDeclarativeExpression);
734 Returns the source file line number for this expression. The source location
735 must have been previously set by calling setSourceLocation().
737 int QDeclarativeExpression::lineNumber() const
739 Q_D(const QDeclarativeExpression);
744 Set the location of this expression to \a line of \a url. This information
745 is used by the script engine.
747 void QDeclarativeExpression::setSourceLocation(const QString &url, int line)
749 Q_D(QDeclarativeExpression);
755 Returns the expression's scope object, if provided, otherwise 0.
757 In addition to data provided by the expression's QDeclarativeContext, the scope
758 object's properties are also in scope during the expression's evaluation.
760 QObject *QDeclarativeExpression::scopeObject() const
762 Q_D(const QDeclarativeExpression);
763 return d->scopeObject();
767 Returns true if the last call to evaluate() resulted in an error,
770 \sa error(), clearError()
772 bool QDeclarativeExpression::hasError() const
774 Q_D(const QDeclarativeExpression);
775 return d->error.isValid();
779 Clear any expression errors. Calls to hasError() following this will
782 \sa hasError(), error()
784 void QDeclarativeExpression::clearError()
786 Q_D(QDeclarativeExpression);
787 d->error = QDeclarativeError();
791 Return any error from the last call to evaluate(). If there was no error,
792 this returns an invalid QDeclarativeError instance.
794 \sa hasError(), clearError()
797 QDeclarativeError QDeclarativeExpression::error() const
799 Q_D(const QDeclarativeExpression);
804 void QDeclarativeExpressionPrivate::_q_notify()
810 \fn void QDeclarativeExpression::valueChanged()
812 Emitted each time the expression value changes from the last time it was
813 evaluated. The expression must have been evaluated at least once (by
814 calling QDeclarativeExpression::evaluate()) before this signal will be emitted.
817 void QDeclarativeExpressionPrivate::emitValueChanged()
819 Q_Q(QDeclarativeExpression);
820 emit q->valueChanged();
823 QDeclarativeAbstractExpression::QDeclarativeAbstractExpression()
824 : m_context(0), m_prevExpression(0), m_nextExpression(0)
828 QDeclarativeAbstractExpression::~QDeclarativeAbstractExpression()
830 if (m_prevExpression) {
831 *m_prevExpression = m_nextExpression;
832 if (m_nextExpression)
833 m_nextExpression->m_prevExpression = m_prevExpression;
837 QDeclarativeContextData *QDeclarativeAbstractExpression::context() const
842 void QDeclarativeAbstractExpression::setContext(QDeclarativeContextData *context)
844 if (m_prevExpression) {
845 *m_prevExpression = m_nextExpression;
846 if (m_nextExpression)
847 m_nextExpression->m_prevExpression = m_prevExpression;
848 m_prevExpression = 0;
849 m_nextExpression = 0;
855 m_nextExpression = m_context->expressions;
856 if (m_nextExpression)
857 m_nextExpression->m_prevExpression = &m_nextExpression;
858 m_prevExpression = &context->expressions;
859 m_context->expressions = this;
863 void QDeclarativeAbstractExpression::refresh()
867 bool QDeclarativeAbstractExpression::isValid() const
869 return m_context != 0;
874 #include <moc_qdeclarativeexpression.cpp>