a128cd9055383d15c9739daabf58ec308ceb8320
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlpropertycache_p.h
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 QQMLPROPERTYCACHE_P_H
43 #define QQMLPROPERTYCACHE_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/qqmlrefcount_p.h>
57 #include "qqmlcleanup_p.h"
58 #include "qqmlnotifier_p.h"
59
60 #include <private/qhashedstring_p.h>
61 #include <QtCore/qvarlengtharray.h>
62 #include <QtCore/qvector.h>
63
64 QT_BEGIN_NAMESPACE
65
66 class QV8Engine;
67 class QMetaProperty;
68 class QV8QObjectWrapper;
69 class QQmlEngine;
70 class QQmlPropertyData;
71 class QQmlAccessors;
72 class QQmlPropertyCacheMethodArguments;
73
74 // We have this somewhat awful split between RawData and Data so that RawData can be
75 // used in unions.  In normal code, you should always use Data which initializes RawData
76 // to an invalid state on construction.
77 class QQmlPropertyRawData
78 {
79 public:
80     enum Flag {
81         NoFlags           = 0x00000000,
82         ValueTypeFlagMask = 0x0000FFFF, // Flags in valueTypeFlags must fit in this mask
83
84         // Can apply to all properties, except IsFunction
85         IsConstant         = 0x00000001, // Has CONST flag
86         IsWritable         = 0x00000002, // Has WRITE function
87         IsResettable       = 0x00000004, // Has RESET function
88         IsAlias            = 0x00000008, // Is a QML alias to another property
89         IsFinal            = 0x00000010, // Has FINAL flag
90         IsDirect           = 0x00000020, // Exists on a C++ QMetaObject
91         HasAccessors       = 0x00000040, // Has property accessors
92
93         // These are mutualy exclusive
94         IsFunction         = 0x00000080, // Is an invokable
95         IsQObjectDerived   = 0x00000100, // Property type is a QObject* derived type
96         IsEnumType         = 0x00000200, // Property type is an enum
97         IsQList            = 0x00000400, // Property type is a QML list
98         IsQmlBinding       = 0x00000800, // Property type is a QQmlBinding*
99         IsQJSValue         = 0x00001000, // Property type is a QScriptValue
100         IsV8Handle         = 0x00002000, // Property type is a QQmlV8Handle
101         IsVMEProperty      = 0x00004000, // Property type is a "var" property of VMEMO
102         IsValueTypeVirtual = 0x00008000, // Property is a value type "virtual" property
103         IsQVariant         = 0x00010000, // Property is a QVariant
104
105         // Apply only to IsFunctions
106         IsVMEFunction      = 0x00020000, // Function was added by QML
107         HasArguments       = 0x00040000, // Function takes arguments
108         IsSignal           = 0x00080000, // Function is a signal
109         IsVMESignal        = 0x00100000, // Signal was added by QML
110         IsV8Function       = 0x00200000, // Function takes QQmlV8Function* args
111         IsSignalHandler    = 0x00400000, // Function is a signal handler
112         IsOverload         = 0x00800000, // Function is an overload of another function
113
114         // Internal QQmlPropertyCache flags
115         NotFullyResolved   = 0x01000000  // True if the type data is to be lazily resolved
116     };
117     Q_DECLARE_FLAGS(Flags, Flag)
118
119     Flags getFlags() const { return Flag(flags); }
120     void setFlags(Flags f) { flags = f; }
121
122     bool isValid() const { return coreIndex != -1; }
123
124     bool isConstant() const { return flags & IsConstant; }
125     bool isWritable() const { return flags & IsWritable; }
126     bool isResettable() const { return flags & IsResettable; }
127     bool isAlias() const { return flags & IsAlias; }
128     bool isFinal() const { return flags & IsFinal; }
129     bool isDirect() const { return flags & IsDirect; }
130     bool hasAccessors() const { return flags & HasAccessors; }
131     bool isFunction() const { return flags & IsFunction; }
132     bool isQObject() const { return flags & IsQObjectDerived; }
133     bool isEnum() const { return flags & IsEnumType; }
134     bool isQList() const { return flags & IsQList; }
135     bool isQmlBinding() const { return flags & IsQmlBinding; }
136     bool isQJSValue() const { return flags & IsQJSValue; }
137     bool isV8Handle() const { return flags & IsV8Handle; }
138     bool isVMEProperty() const { return flags & IsVMEProperty; }
139     bool isValueTypeVirtual() const { return flags & IsValueTypeVirtual; }
140     bool isQVariant() const { return flags & IsQVariant; }
141     bool isVMEFunction() const { return flags & IsVMEFunction; }
142     bool hasArguments() const { return flags & HasArguments; }
143     bool isSignal() const { return flags & IsSignal; }
144     bool isVMESignal() const { return flags & IsVMESignal; }
145     bool isV8Function() const { return flags & IsV8Function; }
146     bool isSignalHandler() const { return flags & IsSignalHandler; }
147     bool isOverload() const { return flags & IsOverload; }
148
149     bool hasOverride() const { return !(flags & IsValueTypeVirtual) &&
150                                       !(flags & HasAccessors) &&
151                                       overrideIndex >= 0; }
152     bool hasRevision() const { return !(flags & HasAccessors) && revision != 0; }
153
154     // Returns -1 if not a value type virtual property
155     inline int getValueTypeCoreIndex() const;
156
157     // Returns the "encoded" index for use with bindings.  Encoding is:
158     //     coreIndex | (valueTypeCoreIndex << 24)
159     inline int encodedIndex() const;
160
161     union {
162         int propType;             // When !NotFullyResolved
163         const char *propTypeName; // When NotFullyResolved
164     };
165     int coreIndex;
166     union {
167         int notifyIndex;  // When !IsFunction
168         void *arguments;  // When IsFunction && HasArguments
169     };
170
171     union {
172         struct { // When !HasAccessors
173             qint16 revision;
174             qint16 metaObjectOffset;
175
176             union {
177                 struct { // When IsValueTypeVirtual
178                     quint16 valueTypeFlags; // flags of the access property on the value type proxy
179                                             // object
180                     quint8 valueTypePropType; // The QVariant::Type of access property on the value
181                                               // type proxy object
182                     quint8 valueTypeCoreIndex; // The prop index of the access property on the value
183                                                // type proxy object
184                 };
185
186                 struct { // When !IsValueTypeVirtual
187                     uint overrideIndexIsProperty : 1;
188                     signed int overrideIndex : 31;
189                 };
190             };
191         };
192         struct { // When HasAccessors
193             QQmlAccessors *accessors;
194             intptr_t accessorData;
195         };
196     };
197
198 private:
199     friend class QQmlPropertyData;
200     friend class QQmlPropertyCache;
201     quint32 flags;
202 };
203 Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyRawData::Flags);
204
205 class QQmlPropertyData : public QQmlPropertyRawData
206 {
207 public:
208     inline QQmlPropertyData();
209     inline QQmlPropertyData(const QQmlPropertyRawData &);
210
211     inline bool operator==(const QQmlPropertyRawData &);
212
213     static Flags flagsForProperty(const QMetaProperty &, QQmlEngine *engine = 0);
214     void load(const QMetaProperty &, QQmlEngine *engine = 0);
215     void load(const QMetaMethod &);
216     QString name(QObject *);
217     QString name(const QMetaObject *);
218
219 private:
220     friend class QQmlPropertyCache;
221     void lazyLoad(const QMetaProperty &, QQmlEngine *engine = 0);
222     void lazyLoad(const QMetaMethod &);
223     bool notFullyResolved() const { return flags & NotFullyResolved; }
224 };
225
226 class Q_QML_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup
227 {
228 public:
229     QQmlPropertyCache(QQmlEngine *);
230     QQmlPropertyCache(QQmlEngine *, const QMetaObject *);
231     virtual ~QQmlPropertyCache();
232
233     void update(QQmlEngine *, const QMetaObject *);
234
235     QQmlPropertyCache *copy();
236
237     QQmlPropertyCache *copyAndAppend(QQmlEngine *, const QMetaObject *,
238                 QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
239                 QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
240                 QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
241     QQmlPropertyCache *copyAndAppend(QQmlEngine *, const QMetaObject *, int revision,
242                 QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
243                 QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
244                 QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
245
246     void append(QQmlEngine *, const QMetaObject *,
247                 QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
248                 QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
249                 QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
250     void append(QQmlEngine *, const QMetaObject *, int revision,
251                 QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
252                 QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
253                 QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
254
255     inline QQmlPropertyData *property(const QHashedV8String &) const;
256     QQmlPropertyData *property(const QHashedStringRef &) const;
257     QQmlPropertyData *property(const QHashedCStringRef &) const;
258     QQmlPropertyData *property(const QString &) const;
259     QQmlPropertyData *property(int) const;
260     QQmlPropertyData *method(int) const;
261     QStringList propertyNames() const;
262
263     inline QQmlPropertyData *overrideData(QQmlPropertyData *) const;
264     inline bool isAllowedInRevision(QQmlPropertyData *) const;
265
266     inline QQmlEngine *qmlEngine() const;
267     static QQmlPropertyData *property(QQmlEngine *, QObject *, const QString &,
268                                               QQmlPropertyData &);
269     static QQmlPropertyData *property(QQmlEngine *, QObject *, const QHashedV8String &,
270                                               QQmlPropertyData &);
271     static int *methodParameterTypes(QObject *, int index, QVarLengthArray<int, 9> &dummy,
272                                      QByteArray *unknownTypeError);
273
274     static bool isDynamicMetaObject(const QMetaObject *);
275 protected:
276     virtual void destroy();
277     virtual void clear();
278
279 private:
280     friend class QQmlEnginePrivate;
281     friend class QV8QObjectWrapper;
282
283     inline QQmlPropertyCache *copy(int reserve);
284
285     // Implemented in v8/qv8qobjectwrapper.cpp
286     v8::Local<v8::Object> newQObject(QObject *, QV8Engine *);
287
288     typedef QVector<QQmlPropertyData> IndexCache;
289     typedef QStringHash<QQmlPropertyData *> StringCache;
290     typedef QVector<int> AllowedRevisionCache;
291
292     void resolve(QQmlPropertyData *) const;
293     void updateRecur(QQmlEngine *, const QMetaObject *);
294
295     QQmlEngine *engine;
296     
297     QQmlPropertyCache *parent;
298     int propertyIndexCacheStart;
299     int methodIndexCacheStart;
300     int signalHanderIndexCacheStart;
301
302     IndexCache propertyIndexCache;
303     IndexCache methodIndexCache;
304     IndexCache signalHandlerIndexCache;
305     StringCache stringCache;
306     AllowedRevisionCache allowedRevisionCache;
307     v8::Persistent<v8::Function> constructor;
308
309     const QMetaObject *metaObject;
310     QQmlPropertyCacheMethodArguments *argumentsCache;
311 };
312   
313 QQmlPropertyData::QQmlPropertyData()
314 {
315     propType = 0;
316     coreIndex = -1;
317     notifyIndex = -1;
318     overrideIndexIsProperty = false;
319     overrideIndex = -1;
320     revision = 0;
321     metaObjectOffset = -1; 
322     flags = 0;
323 }
324
325 QQmlPropertyData::QQmlPropertyData(const QQmlPropertyRawData &d)
326 {
327     *(static_cast<QQmlPropertyRawData *>(this)) = d;
328 }
329
330 bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other)
331 {
332     return flags == other.flags &&
333            propType == other.propType &&
334            coreIndex == other.coreIndex &&
335            notifyIndex == other.notifyIndex &&
336            revision == other.revision &&
337            (!isValueTypeVirtual() || 
338             (valueTypeCoreIndex == other.valueTypeCoreIndex && 
339              valueTypePropType == other.valueTypePropType));
340 }
341
342 int QQmlPropertyRawData::getValueTypeCoreIndex() const
343 {
344     return isValueTypeVirtual()?valueTypeCoreIndex:-1;
345 }
346
347 int QQmlPropertyRawData::encodedIndex() const
348 {
349     return isValueTypeVirtual()?(coreIndex | (valueTypeCoreIndex << 24)):coreIndex;
350 }
351
352 QQmlPropertyData *
353 QQmlPropertyCache::overrideData(QQmlPropertyData *data) const
354 {
355     if (!data->hasOverride())
356         return 0;
357
358     if (data->overrideIndexIsProperty)
359         return property(data->overrideIndex);
360     else
361         return method(data->overrideIndex);
362 }
363
364 bool QQmlPropertyCache::isAllowedInRevision(QQmlPropertyData *data) const
365 {
366     return (data->hasAccessors() || (data->metaObjectOffset == -1 && data->revision == 0)) ||
367            (allowedRevisionCache[data->metaObjectOffset] >= data->revision);
368 }
369
370 QQmlEngine *QQmlPropertyCache::qmlEngine() const
371 {
372     return engine;
373 }
374
375 QQmlPropertyData *QQmlPropertyCache::property(const QHashedV8String &str) const
376 {
377     QQmlPropertyData **rv = stringCache.value(str);
378     if (rv && (*rv)->notFullyResolved()) resolve(*rv);
379     return rv?*rv:0;
380 }
381
382 QT_END_NAMESPACE
383
384 #endif // QQMLPROPERTYCACHE_P_H