From b855240b782395f94315f43ea3e7e182299fac48 Mon Sep 17 00:00:00 2001 From: Matthew Vogt Date: Thu, 16 Feb 2012 14:43:03 +1000 Subject: Rename QDeclarative symbols to QQuick and QQml Symbols beginning with QDeclarative are already exported by the quick1 module. Users can apply the bin/rename-qtdeclarative-symbols.sh script to modify client code using the previous names of the renamed symbols. Task-number: QTBUG-23737 Change-Id: Ifaa482663767634931e8711a8e9bf6e404859e66 Reviewed-by: Martin Jones --- src/qml/qml/qqmlexpression_p.h | 406 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 src/qml/qml/qqmlexpression_p.h (limited to 'src/qml/qml/qqmlexpression_p.h') diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h new file mode 100644 index 0000000000..deca29ab60 --- /dev/null +++ b/src/qml/qml/qqmlexpression_p.h @@ -0,0 +1,406 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLEXPRESSION_P_H +#define QQMLEXPRESSION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qqmlexpression.h" + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QQmlAbstractExpression +{ +public: + QQmlAbstractExpression(); + virtual ~QQmlAbstractExpression(); + + bool isValid() const; + + QQmlContextData *context() const; + void setContext(QQmlContextData *); + + virtual void refresh(); + + class DeleteWatcher { + public: + inline DeleteWatcher(QQmlAbstractExpression *); + inline ~DeleteWatcher(); + inline bool wasDeleted() const; + private: + friend class QQmlAbstractExpression; + QQmlContextData *_c; + QQmlAbstractExpression **_w; + QQmlAbstractExpression *_s; + }; + +private: + friend class QQmlContext; + friend class QQmlContextData; + friend class QQmlContextPrivate; + + QBiPointer m_context; + QQmlAbstractExpression **m_prevExpression; + QQmlAbstractExpression *m_nextExpression; +}; + +class QQmlDelayedError +{ +public: + inline QQmlDelayedError() : nextError(0), prevError(0) {} + inline ~QQmlDelayedError() { removeError(); } + + QQmlError error; + + bool addError(QQmlEnginePrivate *); + + inline void removeError() { + if (!prevError) return; + if (nextError) nextError->prevError = prevError; + *prevError = nextError; + nextError = 0; + prevError = 0; + } + +private: + QQmlDelayedError *nextError; + QQmlDelayedError **prevError; +}; + +class QQmlJavaScriptExpression +{ +public: + // Although this looks crazy, we implement our own "vtable" here, rather than relying on + // C++ virtuals, to save memory. By doing it ourselves, we can overload the storage + // location that is use for the vtable to also store the rarely used delayed error. + // If we use C++ virtuals, we can't do this and it consts us an extra sizeof(void *) in + // memory for every expression. + struct VTable { + QString (*expressionIdentifier)(QQmlJavaScriptExpression *); + void (*expressionChanged)(QQmlJavaScriptExpression *); + }; + + QQmlJavaScriptExpression(VTable *vtable); + + v8::Local evaluate(QQmlContextData *, v8::Handle, + bool *isUndefined); + + inline bool requiresThisObject() const; + inline void setRequiresThisObject(bool v); + inline bool useSharedContext() const; + inline void setUseSharedContext(bool v); + inline bool notifyOnValueChanged() const; + + void setNotifyOnValueChanged(bool v); + void resetNotifyOnValueChanged(); + + inline QObject *scopeObject() const; + inline void setScopeObject(QObject *v); + + class DeleteWatcher { + public: + inline DeleteWatcher(QQmlJavaScriptExpression *); + inline ~DeleteWatcher(); + inline bool wasDeleted() const; + private: + friend class QQmlJavaScriptExpression; + QObject *_c; + QQmlJavaScriptExpression **_w; + QQmlJavaScriptExpression *_s; + }; + + inline bool hasError() const; + inline bool hasDelayedError() const; + QQmlError error() const; + void clearError(); + QQmlDelayedError *delayedError(); + +protected: + ~QQmlJavaScriptExpression(); + +private: + typedef QQmlJavaScriptExpressionGuard Guard; + friend class QQmlJavaScriptExpressionGuard; + + struct GuardCapture : public QQmlEnginePrivate::PropertyCapture { + GuardCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e) + : engine(engine), expression(e), errorString(0) { } + + ~GuardCapture() { + Q_ASSERT(guards.isEmpty()); + Q_ASSERT(errorString == 0); + } + + virtual void captureProperty(QQmlNotifier *); + virtual void captureProperty(QObject *, int, int); + + QQmlEngine *engine; + QQmlJavaScriptExpression *expression; + QFieldList guards; + QStringList *errorString; + }; + + QPointerValuePair m_vtable; + + // We store some flag bits in the following flag pointers. + // m_scopeObject:flag1 - requiresThisObject + // activeGuards:flag1 - notifyOnValueChanged + // activeGuards:flag2 - useSharedContext + QBiPointer m_scopeObject; + QForwardFieldList activeGuards; + + void clearGuards(); +}; + +class QQmlExpression; +class QString; +class Q_QML_PRIVATE_EXPORT QQmlExpressionPrivate : public QObjectPrivate, public QQmlJavaScriptExpression, public QQmlAbstractExpression +{ + Q_DECLARE_PUBLIC(QQmlExpression) +public: + QQmlExpressionPrivate(); + ~QQmlExpressionPrivate(); + + void init(QQmlContextData *, const QString &, QObject *); + void init(QQmlContextData *, v8::Handle, QObject *); + void init(QQmlContextData *, const QString &, bool, QObject *, const QString &, int, int); + void init(QQmlContextData *, const QByteArray &, bool, QObject *, const QString &, int, int); + + QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0); + + v8::Local v8value(QObject *secondaryScope = 0, bool *isUndefined = 0); + + static inline QQmlExpressionPrivate *get(QQmlExpression *expr); + static inline QQmlExpression *get(QQmlExpressionPrivate *expr); + + void _q_notify(); + + static void exceptionToError(v8::Handle, QQmlError &); + static v8::Persistent evalFunction(QQmlContextData *ctxt, QObject *scope, + const QString &code, const QString &filename, + int line, + v8::Persistent *qmlscope = 0); + static v8::Persistent evalFunction(QQmlContextData *ctxt, QObject *scope, + const char *code, int codeLength, + const QString &filename, int line, + v8::Persistent *qmlscope = 0); + + static QQmlExpression *create(QQmlContextData *, QObject *, const QString &, bool, + const QString &, int, int); + + bool expressionFunctionValid:1; + bool expressionFunctionRewritten:1; + bool extractExpressionFromFunction:1; + + // "Inherited" from QQmlJavaScriptExpression + static QString expressionIdentifier(QQmlJavaScriptExpression *); + static void expressionChanged(QQmlJavaScriptExpression *); + virtual void expressionChanged(); + + QString expression; + QByteArray expressionUtf8; + + v8::Persistent v8qmlscope; + v8::Persistent v8function; + + QString url; // This is a QString for a reason. QUrls are slooooooow... + int line; + int column; + QString name; //function name, hint for the debugger + + QQmlRefCount *dataRef; +}; + +QQmlAbstractExpression::DeleteWatcher::DeleteWatcher(QQmlAbstractExpression *e) +: _c(0), _w(0), _s(e) +{ + if (e->m_context.isT1()) { + _w = &_s; + _c = e->m_context.asT1(); + e->m_context = this; + } else { + // Another watcher is already registered + _w = &e->m_context.asT2()->_s; + } +} + +QQmlAbstractExpression::DeleteWatcher::~DeleteWatcher() +{ + Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_context.isT2())); + if (*_w && _s->m_context.asT2() == this) + _s->m_context = _c; +} + +bool QQmlAbstractExpression::DeleteWatcher::wasDeleted() const +{ + return *_w == 0; +} + +QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e) +: _c(0), _w(0), _s(e) +{ + if (e->m_scopeObject.isT1()) { + _w = &_s; + _c = e->m_scopeObject.asT1(); + e->m_scopeObject = this; + } else { + // Another watcher is already registered + _w = &e->m_scopeObject.asT2()->_s; + } +} + +QQmlJavaScriptExpression::DeleteWatcher::~DeleteWatcher() +{ + Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_scopeObject.isT2())); + if (*_w && _s->m_scopeObject.asT2() == this) + _s->m_scopeObject = _c; +} + +bool QQmlJavaScriptExpression::DeleteWatcher::wasDeleted() const +{ + return *_w == 0; +} + +bool QQmlJavaScriptExpression::requiresThisObject() const +{ + return m_scopeObject.flag(); +} + +void QQmlJavaScriptExpression::setRequiresThisObject(bool v) +{ + m_scopeObject.setFlagValue(v); +} + +bool QQmlJavaScriptExpression::useSharedContext() const +{ + return activeGuards.flag2(); +} + +void QQmlJavaScriptExpression::setUseSharedContext(bool v) +{ + activeGuards.setFlag2Value(v); +} + +bool QQmlJavaScriptExpression::notifyOnValueChanged() const +{ + return activeGuards.flag(); +} + +QObject *QQmlJavaScriptExpression::scopeObject() const +{ + if (m_scopeObject.isT1()) return m_scopeObject.asT1(); + else return m_scopeObject.asT2()->_c; +} + +void QQmlJavaScriptExpression::setScopeObject(QObject *v) +{ + if (m_scopeObject.isT1()) m_scopeObject = v; + else m_scopeObject.asT2()->_c = v; +} + +bool QQmlJavaScriptExpression::hasError() const +{ + return m_vtable.hasValue() && m_vtable.constValue()->error.isValid(); +} + +bool QQmlJavaScriptExpression::hasDelayedError() const +{ + return m_vtable.hasValue(); +} + +QQmlExpressionPrivate *QQmlExpressionPrivate::get(QQmlExpression *expr) +{ + return static_cast(QObjectPrivate::get(expr)); +} + +QQmlExpression *QQmlExpressionPrivate::get(QQmlExpressionPrivate *expr) +{ + return expr->q_func(); +} + +QQmlJavaScriptExpressionGuard::QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *e) +: expression(e), next(0) +{ + callback = &endpointCallback; +} + +void QQmlJavaScriptExpressionGuard::endpointCallback(QQmlNotifierEndpoint *e) +{ + QQmlJavaScriptExpression *expression = + static_cast(e)->expression; + + expression->m_vtable->expressionChanged(expression); +} + +QQmlJavaScriptExpressionGuard * +QQmlJavaScriptExpressionGuard::New(QQmlJavaScriptExpression *e, + QQmlEngine *engine) +{ + Q_ASSERT(e); + return QQmlEnginePrivate::get(engine)->jsExpressionGuardPool.New(e); +} + +void QQmlJavaScriptExpressionGuard::Delete() +{ + QRecyclePool::Delete(this); +} + +QT_END_NAMESPACE + +#endif // QQMLEXPRESSION_P_H -- cgit v1.2.3