~loic.molinari/+junk/qtdeclarative-shadereffectsource-changes

« back to all changes in this revision

Viewing changes to src/qml/qml/qqmljavascriptexpression_p.h

  • Committer: Loïc Molinari
  • Date: 2012-04-21 17:59:51 UTC
  • Revision ID: loic.molinari@canonical.com-20120421175951-bqx68caaf5zrp76l
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/
 
5
**
 
6
** This file is part of the QtQml module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** GNU Lesser General Public License Usage
 
10
** This file may be used under the terms of the GNU Lesser General Public
 
11
** License version 2.1 as published by the Free Software Foundation and
 
12
** appearing in the file LICENSE.LGPL included in the packaging of this
 
13
** file. Please review the following information to ensure the GNU Lesser
 
14
** General Public License version 2.1 requirements will be met:
 
15
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
16
**
 
17
** In addition, as a special exception, Nokia gives you certain additional
 
18
** rights. These rights are described in the Nokia Qt LGPL Exception
 
19
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
20
**
 
21
** GNU General Public License Usage
 
22
** Alternatively, this file may be used under the terms of the GNU General
 
23
** Public License version 3.0 as published by the Free Software Foundation
 
24
** and appearing in the file LICENSE.GPL included in the packaging of this
 
25
** file. Please review the following information to ensure the GNU General
 
26
** Public License version 3.0 requirements will be met:
 
27
** http://www.gnu.org/copyleft/gpl.html.
 
28
**
 
29
** Other Usage
 
30
** Alternatively, this file may be used in accordance with the terms and
 
31
** conditions contained in a signed written agreement between you and Nokia.
 
32
**
 
33
**
 
34
**
 
35
**
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#ifndef QQMLJAVASCRIPTEXPRESSION_P_H
 
43
#define QQMLJAVASCRIPTEXPRESSION_P_H
 
44
 
 
45
//
 
46
//  W A R N I N G
 
47
//  -------------
 
48
//
 
49
// This file is not part of the Qt API.  It exists purely as an
 
50
// implementation detail.  This header file may change from version to
 
51
// version without notice, or even be removed.
 
52
//
 
53
// We mean it.
 
54
//
 
55
 
 
56
#include <private/qv8_p.h>
 
57
#include <QtCore/qglobal.h>
 
58
#include <QtQml/qqmlerror.h>
 
59
#include <private/qqmlengine_p.h>
 
60
#include <private/qpointervaluepair_p.h>
 
61
 
 
62
QT_BEGIN_NAMESPACE
 
63
 
 
64
class QQmlDelayedError
 
65
{
 
66
public:
 
67
    inline QQmlDelayedError() : nextError(0), prevError(0) {}
 
68
    inline ~QQmlDelayedError() { removeError(); }
 
69
 
 
70
    QQmlError error;
 
71
 
 
72
    bool addError(QQmlEnginePrivate *);
 
73
 
 
74
    inline void removeError() {
 
75
        if (!prevError) return;
 
76
        if (nextError) nextError->prevError = prevError;
 
77
        *prevError = nextError;
 
78
        nextError = 0;
 
79
        prevError = 0;
 
80
    }
 
81
 
 
82
private:
 
83
    QQmlDelayedError  *nextError;
 
84
    QQmlDelayedError **prevError;
 
85
};
 
86
 
 
87
class QQmlJavaScriptExpression
 
88
{
 
89
public:
 
90
    // Although this looks crazy, we implement our own "vtable" here, rather than relying on
 
91
    // C++ virtuals, to save memory.  By doing it ourselves, we can overload the storage
 
92
    // location that is use for the vtable to also store the rarely used delayed error.
 
93
    // If we use C++ virtuals, we can't do this and it consts us an extra sizeof(void *) in
 
94
    // memory for every expression.
 
95
    struct VTable {
 
96
        QString (*expressionIdentifier)(QQmlJavaScriptExpression *);
 
97
        void (*expressionChanged)(QQmlJavaScriptExpression *);
 
98
    };
 
99
 
 
100
    QQmlJavaScriptExpression(VTable *vtable);
 
101
 
 
102
    v8::Local<v8::Value> evaluate(QQmlContextData *, v8::Handle<v8::Function>,
 
103
                                  bool *isUndefined);
 
104
 
 
105
    inline bool requiresThisObject() const;
 
106
    inline void setRequiresThisObject(bool v);
 
107
    inline bool useSharedContext() const;
 
108
    inline void setUseSharedContext(bool v);
 
109
    inline bool notifyOnValueChanged() const;
 
110
 
 
111
    void setNotifyOnValueChanged(bool v);
 
112
    void resetNotifyOnValueChanged();
 
113
 
 
114
    inline QObject *scopeObject() const;
 
115
    inline void setScopeObject(QObject *v);
 
116
 
 
117
    class DeleteWatcher {
 
118
    public:
 
119
        inline DeleteWatcher(QQmlJavaScriptExpression *);
 
120
        inline ~DeleteWatcher();
 
121
        inline bool wasDeleted() const;
 
122
    private:
 
123
        friend class QQmlJavaScriptExpression;
 
124
        QObject *_c;
 
125
        QQmlJavaScriptExpression **_w;
 
126
        QQmlJavaScriptExpression *_s;
 
127
    };
 
128
 
 
129
    inline bool hasError() const;
 
130
    inline bool hasDelayedError() const;
 
131
    QQmlError error() const;
 
132
    void clearError();
 
133
    QQmlDelayedError *delayedError();
 
134
 
 
135
    static void exceptionToError(v8::Handle<v8::Message>, QQmlError &);
 
136
    static v8::Persistent<v8::Function> evalFunction(QQmlContextData *ctxt, QObject *scope,
 
137
                                                     const QString &code, const QString &filename,
 
138
                                                     int line,
 
139
                                                     v8::Persistent<v8::Object> *qmlscope = 0);
 
140
    static v8::Persistent<v8::Function> evalFunction(QQmlContextData *ctxt, QObject *scope,
 
141
                                                     const char *code, int codeLength,
 
142
                                                     const QString &filename, int line,
 
143
                                                     v8::Persistent<v8::Object> *qmlscope = 0);
 
144
protected:
 
145
    ~QQmlJavaScriptExpression();
 
146
 
 
147
private:
 
148
    typedef QQmlJavaScriptExpressionGuard Guard;
 
149
    friend class QQmlJavaScriptExpressionGuard;
 
150
 
 
151
    struct GuardCapture : public QQmlEnginePrivate::PropertyCapture {
 
152
        GuardCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e)
 
153
        : engine(engine), expression(e), errorString(0) { }
 
154
 
 
155
        ~GuardCapture()  {
 
156
            Q_ASSERT(guards.isEmpty());
 
157
            Q_ASSERT(errorString == 0);
 
158
        }
 
159
 
 
160
        virtual void captureProperty(QQmlNotifier *);
 
161
        virtual void captureProperty(QObject *, int, int);
 
162
 
 
163
        QQmlEngine *engine;
 
164
        QQmlJavaScriptExpression *expression;
 
165
        QFieldList<Guard, &Guard::next> guards;
 
166
        QStringList *errorString;
 
167
    };
 
168
 
 
169
    QPointerValuePair<VTable, QQmlDelayedError> m_vtable;
 
170
 
 
171
    // We store some flag bits in the following flag pointers.
 
172
    //    m_scopeObject:flag1 - requiresThisObject
 
173
    //    activeGuards:flag1  - notifyOnValueChanged
 
174
    //    activeGuards:flag2  - useSharedContext
 
175
    QBiPointer<QObject, DeleteWatcher> m_scopeObject;
 
176
    QForwardFieldList<Guard, &Guard::next> activeGuards;
 
177
 
 
178
    void clearGuards();
 
179
};
 
180
 
 
181
QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e)
 
182
: _c(0), _w(0), _s(e)
 
183
{
 
184
    if (e->m_scopeObject.isT1()) {
 
185
        _w = &_s;
 
186
        _c = e->m_scopeObject.asT1();
 
187
        e->m_scopeObject = this;
 
188
    } else {
 
189
        // Another watcher is already registered
 
190
        _w = &e->m_scopeObject.asT2()->_s;
 
191
    }
 
192
}
 
193
 
 
194
QQmlJavaScriptExpression::DeleteWatcher::~DeleteWatcher()
 
195
{
 
196
    Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_scopeObject.isT2()));
 
197
    if (*_w && _s->m_scopeObject.asT2() == this)
 
198
        _s->m_scopeObject = _c;
 
199
}
 
200
 
 
201
bool QQmlJavaScriptExpression::DeleteWatcher::wasDeleted() const
 
202
{
 
203
    return *_w == 0;
 
204
}
 
205
 
 
206
bool QQmlJavaScriptExpression::requiresThisObject() const
 
207
{
 
208
    return m_scopeObject.flag();
 
209
}
 
210
 
 
211
void QQmlJavaScriptExpression::setRequiresThisObject(bool v)
 
212
{
 
213
    m_scopeObject.setFlagValue(v);
 
214
}
 
215
 
 
216
bool QQmlJavaScriptExpression::useSharedContext() const
 
217
{
 
218
    return activeGuards.flag2();
 
219
}
 
220
 
 
221
void QQmlJavaScriptExpression::setUseSharedContext(bool v)
 
222
{
 
223
    activeGuards.setFlag2Value(v);
 
224
}
 
225
 
 
226
bool QQmlJavaScriptExpression::notifyOnValueChanged() const
 
227
{
 
228
    return activeGuards.flag();
 
229
}
 
230
 
 
231
QObject *QQmlJavaScriptExpression::scopeObject() const
 
232
{
 
233
    if (m_scopeObject.isT1()) return m_scopeObject.asT1();
 
234
    else return m_scopeObject.asT2()->_c;
 
235
}
 
236
 
 
237
void QQmlJavaScriptExpression::setScopeObject(QObject *v)
 
238
{
 
239
    if (m_scopeObject.isT1()) m_scopeObject = v;
 
240
    else m_scopeObject.asT2()->_c = v;
 
241
}
 
242
 
 
243
bool QQmlJavaScriptExpression::hasError() const
 
244
{
 
245
    return m_vtable.hasValue() && m_vtable.constValue()->error.isValid();
 
246
}
 
247
 
 
248
bool QQmlJavaScriptExpression::hasDelayedError() const
 
249
{
 
250
    return m_vtable.hasValue();
 
251
}
 
252
 
 
253
QQmlJavaScriptExpressionGuard::QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *e)
 
254
: expression(e), next(0)
 
255
{
 
256
    callback = &endpointCallback;
 
257
}
 
258
 
 
259
void QQmlJavaScriptExpressionGuard::endpointCallback(QQmlNotifierEndpoint *e)
 
260
{
 
261
    QQmlJavaScriptExpression *expression =
 
262
        static_cast<QQmlJavaScriptExpressionGuard *>(e)->expression;
 
263
 
 
264
    expression->m_vtable->expressionChanged(expression);
 
265
}
 
266
 
 
267
QQmlJavaScriptExpressionGuard *
 
268
QQmlJavaScriptExpressionGuard::New(QQmlJavaScriptExpression *e,
 
269
                                           QQmlEngine *engine)
 
270
{
 
271
    Q_ASSERT(e);
 
272
    return QQmlEnginePrivate::get(engine)->jsExpressionGuardPool.New(e);
 
273
}
 
274
 
 
275
void QQmlJavaScriptExpressionGuard::Delete()
 
276
{
 
277
    QRecyclePool<QQmlJavaScriptExpressionGuard>::Delete(this);
 
278
}
 
279
 
 
280
 
 
281
QT_END_NAMESPACE
 
282
 
 
283
#endif // QQMLJAVASCRIPTEXPRESSION_P_H