source: trunk/src/declarative/qml/qdeclarativeexpression.cpp@ 900

Last change on this file since 900 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 26.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtDeclarative module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdeclarativeexpression.h"
43#include "private/qdeclarativeexpression_p.h"
44
45#include "private/qdeclarativeengine_p.h"
46#include "private/qdeclarativecontext_p.h"
47#include "private/qdeclarativerewrite_p.h"
48#include "private/qdeclarativecompiler_p.h"
49#include "private/qdeclarativeglobalscriptclass_p.h"
50
51#include <QtCore/qdebug.h>
52#include <QtScript/qscriptprogram.h>
53
54#include <private/qscriptdeclarativeclass_p.h>
55
56QT_BEGIN_NAMESPACE
57
58bool QDeclarativeDelayedError::addError(QDeclarativeEnginePrivate *e)
59{
60 if (!e) return false;
61
62 if (e->inProgressCreations == 0) return false; // Not in construction
63
64 if (prevError) return true; // Already in error chain
65
66 prevError = &e->erroredBindings;
67 nextError = e->erroredBindings;
68 e->erroredBindings = this;
69 if (nextError) nextError->prevError = &nextError;
70
71 return true;
72}
73
74QDeclarativeQtScriptExpression::QDeclarativeQtScriptExpression()
75: dataRef(0), expressionFunctionMode(ExplicitContext), scopeObject(0), trackChange(false),
76 guardList(0), guardListLength(0), guardObject(0), guardObjectNotifyIndex(-1), deleted(0)
77{
78}
79
80QDeclarativeQtScriptExpression::~QDeclarativeQtScriptExpression()
81{
82 if (guardList) { delete [] guardList; guardList = 0; }
83 if (dataRef) dataRef->release();
84 if (deleted) *deleted = true;
85}
86
87QDeclarativeExpressionPrivate::QDeclarativeExpressionPrivate()
88: expressionFunctionValid(true), line(-1)
89{
90}
91
92QDeclarativeExpressionPrivate::~QDeclarativeExpressionPrivate()
93{
94}
95
96void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QString &expr,
97 QObject *me)
98{
99 expression = expr;
100
101 QDeclarativeAbstractExpression::setContext(ctxt);
102 scopeObject = me;
103 expressionFunctionValid = false;
104}
105
106void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *expr,
107 QDeclarativeRefCount *rc,
108 QObject *me, const QString &srcUrl, int lineNumber)
109{
110 url = srcUrl;
111 line = lineNumber;
112
113 if (dataRef) dataRef->release();
114 dataRef = rc;
115 if (dataRef) dataRef->addref();
116
117 quint32 *exprData = (quint32 *)expr;
118 QDeclarativeCompiledData *dd = (QDeclarativeCompiledData *)rc;
119
120 expression = QString::fromRawData((QChar *)(exprData + 2), exprData[1]);
121
122 int progIdx = *(exprData);
123 bool isSharedProgram = progIdx & 0x80000000;
124 progIdx &= 0x7FFFFFFF;
125
126 QDeclarativeEngine *engine = ctxt->engine;
127 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
128 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
129
130 if (isSharedProgram) {
131
132 if (!dd->cachedClosures.at(progIdx)) {
133 QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
134 scriptContext->pushScope(ep->contextClass->newSharedContext());
135 scriptContext->pushScope(ep->globalClass->staticGlobalObject());
136 dd->cachedClosures[progIdx] = new QScriptValue(scriptEngine->evaluate(expression, url, line));
137 scriptEngine->popContext();
138 }
139
140 expressionFunction = *dd->cachedClosures.at(progIdx);
141 expressionFunctionMode = SharedContext;
142 expressionFunctionValid = true;
143
144 } else {
145
146 if (!dd->cachedPrograms.at(progIdx)) {
147 dd->cachedPrograms[progIdx] = new QScriptProgram(expression, url, line);
148 }
149
150 expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx),
151 &expressionContext);
152
153 expressionFunctionMode = ExplicitContext;
154 expressionFunctionValid = true;
155 }
156
157 QDeclarativeAbstractExpression::setContext(ctxt);
158 scopeObject = me;
159}
160
161QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContextData *context, QObject *object,
162 const QString &program, const QString &fileName,
163 int lineNumber, QScriptValue *contextObject)
164{
165 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
166 QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine);
167 if (contextObject) {
168 *contextObject = ep->contextClass->newContext(context, object);
169 scriptContext->pushScope(*contextObject);
170 } else {
171 scriptContext->pushScope(ep->contextClass->newContext(context, object));
172 }
173 scriptContext->pushScope(ep->globalClass->staticGlobalObject());
174 QScriptValue rv = ep->scriptEngine.evaluate(program, fileName, lineNumber);
175 ep->scriptEngine.popContext();
176 return rv;
177}
178
179QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContextData *context, QObject *object,
180 const QScriptProgram &program,
181 QScriptValue *contextObject)
182{
183 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
184 QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine);
185 if (contextObject) {
186 *contextObject = ep->contextClass->newContext(context, object);
187 scriptContext->pushScope(*contextObject);
188 } else {
189 scriptContext->pushScope(ep->contextClass->newContext(context, object));
190 }
191 scriptContext->pushScope(ep->globalClass->staticGlobalObject());
192 QScriptValue rv = ep->scriptEngine.evaluate(program);
193 ep->scriptEngine.popContext();
194 return rv;
195}
196
197/*!
198 \class QDeclarativeExpression
199 \since 4.7
200 \brief The QDeclarativeExpression class evaluates JavaScript in a QML context.
201
202 For example, given a file \c main.qml like this:
203
204 \qml
205 import QtQuick 1.0
206
207 Item {
208 width: 200; height: 200
209 }
210 \endqml
211
212 The following code evaluates a JavaScript expression in the context of the
213 above QML:
214
215 \code
216 QDeclarativeEngine *engine = new QDeclarativeEngine;
217 QDeclarativeComponent component(engine, QUrl::fromLocalFile("main.qml"));
218
219 QObject *myObject = component.create();
220 QDeclarativeExpression *expr = new QDeclarativeExpression(engine->rootContext(), myObject, "width * 2");
221 int result = expr->evaluate().toInt(); // result = 400
222 \endcode
223*/
224
225static int QDeclarativeExpression_notifyIdx = -1;
226
227/*!
228 Create an invalid QDeclarativeExpression.
229
230 As the expression will not have an associated QDeclarativeContext, this will be a
231 null expression object and its value will always be an invalid QVariant.
232 */
233QDeclarativeExpression::QDeclarativeExpression()
234: QObject(*new QDeclarativeExpressionPrivate, 0)
235{
236 Q_D(QDeclarativeExpression);
237
238 if (QDeclarativeExpression_notifyIdx == -1)
239 QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
240 d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
241}
242
243/*! \internal */
244QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, void *expr,
245 QDeclarativeRefCount *rc, QObject *me,
246 const QString &url, int lineNumber,
247 QDeclarativeExpressionPrivate &dd)
248: QObject(dd, 0)
249{
250 Q_D(QDeclarativeExpression);
251 d->init(ctxt, expr, rc, me, url, lineNumber);
252
253 if (QDeclarativeExpression_notifyIdx == -1)
254 QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
255 d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
256}
257
258/*!
259 Create a QDeclarativeExpression object that is a child of \a parent.
260
261 The \a expression JavaScript will be executed in the \a ctxt QDeclarativeContext.
262 If specified, the \a scope object's properties will also be in scope during
263 the expression's execution.
264*/
265QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContext *ctxt,
266 QObject *scope,
267 const QString &expression,
268 QObject *parent)
269: QObject(*new QDeclarativeExpressionPrivate, parent)
270{
271 Q_D(QDeclarativeExpression);
272 d->init(QDeclarativeContextData::get(ctxt), expression, scope);
273
274 if (QDeclarativeExpression_notifyIdx == -1)
275 QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
276 d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
277}
278
279/*!
280 \internal
281*/
282QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QObject *scope,
283 const QString &expression)
284: QObject(*new QDeclarativeExpressionPrivate, 0)
285{
286 Q_D(QDeclarativeExpression);
287 d->init(ctxt, expression, scope);
288
289 if (QDeclarativeExpression_notifyIdx == -1)
290 QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
291 d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
292}
293
294/*! \internal */
295QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QObject *scope,
296 const QString &expression, QDeclarativeExpressionPrivate &dd)
297: QObject(dd, 0)
298{
299 Q_D(QDeclarativeExpression);
300 d->init(ctxt, expression, scope);
301
302 if (QDeclarativeExpression_notifyIdx == -1)
303 QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
304 d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
305}
306
307/*!
308 Destroy the QDeclarativeExpression instance.
309*/
310QDeclarativeExpression::~QDeclarativeExpression()
311{
312}
313
314/*!
315 Returns the QDeclarativeEngine this expression is associated with, or 0 if there
316 is no association or the QDeclarativeEngine has been destroyed.
317*/
318QDeclarativeEngine *QDeclarativeExpression::engine() const
319{
320 Q_D(const QDeclarativeExpression);
321 return d->context()?d->context()->engine:0;
322}
323
324/*!
325 Returns the QDeclarativeContext this expression is associated with, or 0 if there
326 is no association or the QDeclarativeContext has been destroyed.
327*/
328QDeclarativeContext *QDeclarativeExpression::context() const
329{
330 Q_D(const QDeclarativeExpression);
331 QDeclarativeContextData *data = d->context();
332 return data?data->asQDeclarativeContext():0;
333}
334
335/*!
336 Returns the expression string.
337*/
338QString QDeclarativeExpression::expression() const
339{
340 Q_D(const QDeclarativeExpression);
341 return d->expression;
342}
343
344/*!
345 Set the expression to \a expression.
346*/
347void QDeclarativeExpression::setExpression(const QString &expression)
348{
349 Q_D(QDeclarativeExpression);
350
351 d->resetNotifyOnChange();
352 d->expression = expression;
353 d->expressionFunctionValid = false;
354 d->expressionFunction = QScriptValue();
355}
356
357void QDeclarativeExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine,
358 QDeclarativeError &error)
359{
360 if (scriptEngine->hasUncaughtException() &&
361 scriptEngine->uncaughtException().isError()) {
362
363 QString fileName;
364 int lineNumber = scriptEngine->uncaughtExceptionLineNumber();
365
366 QScriptValue exception = scriptEngine->uncaughtException();
367 QLatin1String fileNameProp("fileName");
368
369 if (!exception.property(fileNameProp).toString().isEmpty()){
370 fileName = exception.property(fileNameProp).toString();
371 } else {
372 fileName = QLatin1String("<Unknown File>");
373 }
374
375 error.setUrl(QUrl(fileName));
376 error.setLine(lineNumber);
377 error.setColumn(-1);
378 error.setDescription(exception.toString());
379 } else {
380 error = QDeclarativeError();
381 }
382}
383
384bool QDeclarativeQtScriptExpression::notifyOnValueChange() const
385{
386 return trackChange;
387}
388
389void QDeclarativeQtScriptExpression::setNotifyOnValueChange(bool notify)
390{
391 trackChange = notify;
392 if (!notify && guardList)
393 clearGuards();
394}
395
396void QDeclarativeQtScriptExpression::resetNotifyOnChange()
397{
398 clearGuards();
399}
400
401void QDeclarativeQtScriptExpression::setNotifyObject(QObject *object, int notifyIndex)
402{
403 if (guardList) clearGuards();
404
405 if (!object || notifyIndex == -1) {
406 guardObject = 0;
407 notifyIndex = -1;
408 } else {
409 guardObject = object;
410 guardObjectNotifyIndex = notifyIndex;
411
412 }
413}
414
415QScriptValue QDeclarativeQtScriptExpression::scriptValue(QObject *secondaryScope, bool *isUndefined)
416{
417 Q_ASSERT(context() && context()->engine);
418 Q_ASSERT(!trackChange || (guardObject && guardObjectNotifyIndex != -1));
419
420 if (!expressionFunction.isValid()) {
421 if (isUndefined) *isUndefined = true;
422 return QScriptValue();
423 }
424
425 DeleteWatcher watcher(this);
426
427 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context()->engine);
428
429 bool lastCaptureProperties = ep->captureProperties;
430 QPODVector<QDeclarativeEnginePrivate::CapturedProperty> lastCapturedProperties;
431 ep->captureProperties = trackChange;
432 ep->capturedProperties.copyAndClear(lastCapturedProperties);
433
434 QScriptValue value = eval(secondaryScope, isUndefined);
435
436 if (!watcher.wasDeleted() && trackChange) {
437 if (ep->capturedProperties.count() == 0) {
438
439 if (guardList) clearGuards();
440
441 } else {
442
443 updateGuards(ep->capturedProperties);
444
445 }
446 }
447
448 lastCapturedProperties.copyAndClear(ep->capturedProperties);
449 ep->captureProperties = lastCaptureProperties;
450
451 return value;
452}
453
454QScriptValue QDeclarativeQtScriptExpression::eval(QObject *secondaryScope, bool *isUndefined)
455{
456 Q_ASSERT(context() && context()->engine);
457
458 DeleteWatcher watcher(this);
459
460 QDeclarativeEngine *engine = context()->engine;
461 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
462
463 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
464
465 QDeclarativeContextData *oldSharedContext = 0;
466 QObject *oldSharedScope = 0;
467 QObject *oldOverride = 0;
468 bool isShared = (expressionFunctionMode == SharedContext);
469
470 if (isShared) {
471 oldSharedContext = ep->sharedContext;
472 oldSharedScope = ep->sharedScope;
473 ep->sharedContext = context();
474 ep->sharedScope = scopeObject;
475 } else {
476 oldOverride = ep->contextClass->setOverrideObject(expressionContext, secondaryScope);
477 }
478
479 QScriptValue svalue = expressionFunction.call(); // This could cause this to be deleted
480
481 if (isShared) {
482 ep->sharedContext = oldSharedContext;
483 ep->sharedScope = oldSharedScope;
484 } else if (!watcher.wasDeleted()) {
485 ep->contextClass->setOverrideObject(expressionContext, oldOverride);
486 }
487
488 if (isUndefined)
489 *isUndefined = svalue.isUndefined() || scriptEngine->hasUncaughtException();
490
491 // Handle exception
492 if (scriptEngine->hasUncaughtException()) {
493 if (!watcher.wasDeleted())
494 QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
495
496 scriptEngine->clearExceptions();
497 return QScriptValue();
498 } else {
499 if (!watcher.wasDeleted())
500 error = QDeclarativeError();
501
502 return svalue;
503 }
504}
505
506void QDeclarativeQtScriptExpression::updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties)
507{
508 Q_ASSERT(guardObject);
509 Q_ASSERT(guardObjectNotifyIndex != -1);
510
511 if (properties.count() != guardListLength) {
512 QDeclarativeNotifierEndpoint *newGuardList = new QDeclarativeNotifierEndpoint[properties.count()];
513
514 for (int ii = 0; ii < qMin(guardListLength, properties.count()); ++ii)
515 guardList[ii].copyAndClear(newGuardList[ii]);
516
517 delete [] guardList;
518 guardList = newGuardList;
519 guardListLength = properties.count();
520 }
521
522 bool outputWarningHeader = false;
523 bool noChanges = true;
524 for (int ii = 0; ii < properties.count(); ++ii) {
525 QDeclarativeNotifierEndpoint &guard = guardList[ii];
526 const QDeclarativeEnginePrivate::CapturedProperty &property = properties.at(ii);
527
528 guard.target = guardObject;
529 guard.targetMethod = guardObjectNotifyIndex;
530
531 if (property.notifier != 0) {
532
533 if (!noChanges && guard.isConnected(property.notifier)) {
534 // Nothing to do
535
536 } else {
537 noChanges = false;
538
539 bool existing = false;
540 for (int jj = 0; !existing && jj < ii; ++jj)
541 if (guardList[jj].isConnected(property.notifier))
542 existing = true;
543
544 if (existing) {
545 // duplicate
546 guard.disconnect();
547 } else {
548 guard.connect(property.notifier);
549 }
550 }
551
552
553 } else if (property.notifyIndex != -1) {
554
555 if (!noChanges && guard.isConnected(property.object, property.notifyIndex)) {
556 // Nothing to do
557
558 } else {
559 noChanges = false;
560
561 bool existing = false;
562 for (int jj = 0; !existing && jj < ii; ++jj)
563 if (guardList[jj].isConnected(property.object, property.notifyIndex))
564 existing = true;
565
566 if (existing) {
567 // duplicate
568 guard.disconnect();
569 } else {
570 guard.connect(property.object, property.notifyIndex);
571 }
572 }
573
574 } else {
575 if (!outputWarningHeader) {
576 outputWarningHeader = true;
577 qWarning() << "QDeclarativeExpression: Expression" << expression
578 << "depends on non-NOTIFYable properties:";
579 }
580
581 const QMetaObject *metaObj = property.object->metaObject();
582 QMetaProperty metaProp = metaObj->property(property.coreIndex);
583
584 qWarning().nospace() << " " << metaObj->className() << "::" << metaProp.name();
585 }
586 }
587}
588
589QScriptValue QDeclarativeExpressionPrivate::scriptValue(QObject *secondaryScope, bool *isUndefined)
590{
591 if (!expressionFunctionValid) {
592 QDeclarativeEngine *engine = context()->engine;
593 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
594
595 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
596
597 QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
598 expressionContext = ep->contextClass->newContext(context(), scopeObject);
599 scriptContext->pushScope(expressionContext);
600 scriptContext->pushScope(ep->globalClass->staticGlobalObject());
601
602 QDeclarativeRewrite::RewriteBinding rewriteBinding;
603 rewriteBinding.setName(name);
604 bool ok = true;
605 const QString code = rewriteBinding(expression, &ok);
606 if (ok)
607 expressionFunction = scriptEngine->evaluate(code, url, line);
608
609 scriptEngine->popContext();
610 expressionFunctionMode = ExplicitContext;
611 expressionFunctionValid = true;
612 }
613
614 return QDeclarativeQtScriptExpression::scriptValue(secondaryScope, isUndefined);
615}
616
617QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
618{
619 Q_Q(QDeclarativeExpression);
620
621 if (!context() || !context()->isValid()) {
622 qWarning("QDeclarativeExpression: Attempted to evaluate an expression in an invalid context");
623 return QVariant();
624 }
625
626 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine());
627
628 return ep->scriptValueToVariant(scriptValue(secondaryScope, isUndefined), qMetaTypeId<QList<QObject*> >());
629}
630
631/*!
632 Evaulates the expression, returning the result of the evaluation,
633 or an invalid QVariant if the expression is invalid or has an error.
634
635 \a valueIsUndefined is set to true if the expression resulted in an
636 undefined value.
637
638 \sa hasError(), error()
639*/
640QVariant QDeclarativeExpression::evaluate(bool *valueIsUndefined)
641{
642 Q_D(QDeclarativeExpression);
643 return d->value(0, valueIsUndefined);
644}
645
646/*!
647Returns true if the valueChanged() signal is emitted when the expression's evaluated
648value changes.
649*/
650bool QDeclarativeExpression::notifyOnValueChanged() const
651{
652 Q_D(const QDeclarativeExpression);
653 return d->notifyOnValueChange();
654}
655
656/*!
657 Sets whether the valueChanged() signal is emitted when the
658 expression's evaluated value changes.
659
660 If \a notifyOnChange is true, the QDeclarativeExpression will
661 monitor properties involved in the expression's evaluation, and emit
662 QDeclarativeExpression::valueChanged() if they have changed. This
663 allows an application to ensure that any value associated with the
664 result of the expression remains up to date.
665
666 If \a notifyOnChange is false (default), the QDeclarativeExpression
667 will not montitor properties involved in the expression's
668 evaluation, and QDeclarativeExpression::valueChanged() will never be
669 emitted. This is more efficient if an application wants a "one off"
670 evaluation of the expression.
671*/
672void QDeclarativeExpression::setNotifyOnValueChanged(bool notifyOnChange)
673{
674 Q_D(QDeclarativeExpression);
675 d->setNotifyOnValueChange(notifyOnChange);
676}
677
678/*!
679 Returns the source file URL for this expression. The source location must
680 have been previously set by calling setSourceLocation().
681*/
682QString QDeclarativeExpression::sourceFile() const
683{
684 Q_D(const QDeclarativeExpression);
685 return d->url;
686}
687
688/*!
689 Returns the source file line number for this expression. The source location
690 must have been previously set by calling setSourceLocation().
691*/
692int QDeclarativeExpression::lineNumber() const
693{
694 Q_D(const QDeclarativeExpression);
695 return d->line;
696}
697
698/*!
699 Set the location of this expression to \a line of \a url. This information
700 is used by the script engine.
701*/
702void QDeclarativeExpression::setSourceLocation(const QString &url, int line)
703{
704 Q_D(QDeclarativeExpression);
705 d->url = url;
706 d->line = line;
707}
708
709/*!
710 Returns the expression's scope object, if provided, otherwise 0.
711
712 In addition to data provided by the expression's QDeclarativeContext, the scope
713 object's properties are also in scope during the expression's evaluation.
714*/
715QObject *QDeclarativeExpression::scopeObject() const
716{
717 Q_D(const QDeclarativeExpression);
718 return d->scopeObject;
719}
720
721/*!
722 Returns true if the last call to evaluate() resulted in an error,
723 otherwise false.
724
725 \sa error(), clearError()
726*/
727bool QDeclarativeExpression::hasError() const
728{
729 Q_D(const QDeclarativeExpression);
730 return d->error.isValid();
731}
732
733/*!
734 Clear any expression errors. Calls to hasError() following this will
735 return false.
736
737 \sa hasError(), error()
738*/
739void QDeclarativeExpression::clearError()
740{
741 Q_D(QDeclarativeExpression);
742 d->error = QDeclarativeError();
743}
744
745/*!
746 Return any error from the last call to evaluate(). If there was no error,
747 this returns an invalid QDeclarativeError instance.
748
749 \sa hasError(), clearError()
750*/
751
752QDeclarativeError QDeclarativeExpression::error() const
753{
754 Q_D(const QDeclarativeExpression);
755 return d->error;
756}
757
758/*! \internal */
759void QDeclarativeExpressionPrivate::_q_notify()
760{
761 emitValueChanged();
762}
763
764void QDeclarativeQtScriptExpression::clearGuards()
765{
766 delete [] guardList;
767 guardList = 0;
768 guardListLength = 0;
769}
770
771/*!
772 \fn void QDeclarativeExpression::valueChanged()
773
774 Emitted each time the expression value changes from the last time it was
775 evaluated. The expression must have been evaluated at least once (by
776 calling QDeclarativeExpression::evaluate()) before this signal will be emitted.
777*/
778
779void QDeclarativeExpressionPrivate::emitValueChanged()
780{
781 Q_Q(QDeclarativeExpression);
782 emit q->valueChanged();
783}
784
785QDeclarativeAbstractExpression::QDeclarativeAbstractExpression()
786: m_context(0), m_prevExpression(0), m_nextExpression(0)
787{
788}
789
790QDeclarativeAbstractExpression::~QDeclarativeAbstractExpression()
791{
792 if (m_prevExpression) {
793 *m_prevExpression = m_nextExpression;
794 if (m_nextExpression)
795 m_nextExpression->m_prevExpression = m_prevExpression;
796 }
797}
798
799QDeclarativeContextData *QDeclarativeAbstractExpression::context() const
800{
801 return m_context;
802}
803
804void QDeclarativeAbstractExpression::setContext(QDeclarativeContextData *context)
805{
806 if (m_prevExpression) {
807 *m_prevExpression = m_nextExpression;
808 if (m_nextExpression)
809 m_nextExpression->m_prevExpression = m_prevExpression;
810 m_prevExpression = 0;
811 m_nextExpression = 0;
812 }
813
814 m_context = context;
815
816 if (m_context) {
817 m_nextExpression = m_context->expressions;
818 if (m_nextExpression)
819 m_nextExpression->m_prevExpression = &m_nextExpression;
820 m_prevExpression = &context->expressions;
821 m_context->expressions = this;
822 }
823}
824
825void QDeclarativeAbstractExpression::refresh()
826{
827}
828
829bool QDeclarativeAbstractExpression::isValid() const
830{
831 return m_context != 0;
832}
833
834QT_END_NAMESPACE
835
836#include <moc_qdeclarativeexpression.cpp>
Note: See TracBrowser for help on using the repository browser.