1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
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.
56 #include <private/qtqmlglobal_p.h>
57 #include <private/qobject_p.h>
58 #include <private/qv8_p.h>
62 template <class Key, class T> class QHash;
64 class QQmlCompiledData;
65 class QQmlAbstractBinding;
66 class QQmlAbstractBoundSignal;
68 class QQmlPropertyCache;
69 class QQmlContextData;
71 class QQmlDataExtended;
72 class QQmlNotifierEndpoint;
73 // This class is structured in such a way, that simply zero'ing it is the
74 // default state for elemental object allocations. This is crucial in the
75 // workings of the QQmlInstruction::CreateSimpleObject instruction.
76 // Don't change anything here without first considering that case!
77 class Q_QML_PRIVATE_EXPORT QQmlData : public QAbstractDeclarativeData
81 : ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
82 hasTaintedV8Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
83 hasVMEMetaObject(false), parentFrozen(false), notifyList(0), context(0), outerContext(0),
84 bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0),
85 lineNumber(0), columnNumber(0), compiledData(0), deferredIdx(0), v8objectid(0),
86 propertyCache(0), guards(0), extendedData(0) {
90 static inline void init() {
91 static bool initialized = false;
94 QAbstractDeclarativeData::destroyed = destroyed;
95 QAbstractDeclarativeData::parentChanged = parentChanged;
96 QAbstractDeclarativeData::signalEmitted = signalEmitted;
97 QAbstractDeclarativeData::receivers = receivers;
98 QAbstractDeclarativeData::isSignalConnected = isSignalConnected;
102 static void destroyed(QAbstractDeclarativeData *, QObject *);
103 static void parentChanged(QAbstractDeclarativeData *, QObject *, QObject *);
104 static void signalEmitted(QAbstractDeclarativeData *, QObject *, int, void **);
105 static int receivers(QAbstractDeclarativeData *, const QObject *, int);
106 static bool isSignalConnected(QAbstractDeclarativeData *, const QObject *, int);
108 void destroyed(QObject *);
109 void parentChanged(QObject *, QObject *);
111 void setImplicitDestructible() {
112 if (!explicitIndestructibleSet) indestructible = false;
116 quint32 ownContext:1;
117 quint32 indestructible:1;
118 quint32 explicitIndestructibleSet:1;
119 quint32 hasTaintedV8Object:1;
120 quint32 isQueuedForDeletion:1;
122 * rootObjectInCreation should be true only when creating top level CPP and QML objects,
123 * v8 GC will check this flag, only deletes the objects when rootObjectInCreation is false.
125 quint32 rootObjectInCreation:1;
126 quint32 hasVMEMetaObject:1;
127 quint32 parentFrozen:1;
131 quint64 connectionMask;
133 quint16 maximumTodoIndex;
134 quint16 notifiesSize;
136 QQmlNotifierEndpoint *todo;
137 QQmlNotifierEndpoint**notifies;
140 void layout(QQmlNotifierEndpoint*);
142 NotifyList *notifyList;
144 inline QQmlNotifierEndpoint *notify(int index);
145 void addNotify(int index, QQmlNotifierEndpoint *);
146 int endpointCount(int index);
147 bool signalHasEndpoint(int index);
148 void disconnectNotifiers();
150 // The context that created the C++ object
151 QQmlContextData *context;
152 // The outermost context in which this object lives
153 QQmlContextData *outerContext;
155 QQmlAbstractBinding *bindings;
156 QQmlAbstractBoundSignal *signalHandlers;
158 // Linked list for QQmlContext::contextObjects
159 QQmlData *nextContextObject;
160 QQmlData**prevContextObject;
163 quint32 *bindingBits;
165 inline bool hasBindingBit(int) const;
166 void clearBindingBit(int);
167 void setBindingBit(QObject *obj, int);
169 inline bool hasPendingBindingBit(int) const;
170 void setPendingBindingBit(QObject *obj, int);
171 void clearPendingBindingBit(int);
174 quint16 columnNumber;
176 QQmlCompiledData *compiledData;
177 unsigned int deferredIdx;
180 v8::Persistent<v8::Object> v8object;
182 QQmlPropertyCache *propertyCache;
184 QQmlGuardImpl *guards;
186 static QQmlData *get(const QObject *object, bool create = false) {
187 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
188 if (priv->wasDeleted) {
191 } else if (priv->declarativeData) {
192 return static_cast<QQmlData *>(priv->declarativeData);
194 priv->declarativeData = new QQmlData;
195 return static_cast<QQmlData *>(priv->declarativeData);
201 bool hasExtendedData() const { return extendedData != 0; }
202 QHash<int, QObject *> *attachedProperties() const;
204 static inline bool wasDeleted(QObject *);
206 static void markAsDeleted(QObject *);
207 static void setQueuedForDeletion(QObject *);
209 static inline void flushPendingBinding(QObject *, int coreIndex);
212 // For attachedProperties
213 mutable QQmlDataExtended *extendedData;
215 void flushPendingBindingImpl(int coreIndex);
218 bool QQmlData::wasDeleted(QObject *object)
223 QObjectPrivate *priv = QObjectPrivate::get(object);
224 if (priv->wasDeleted)
227 return priv->declarativeData &&
228 static_cast<QQmlData *>(priv->declarativeData)->isQueuedForDeletion;
231 QQmlNotifierEndpoint *QQmlData::notify(int index)
233 Q_ASSERT(index <= 0xFFFF);
235 if (!notifyList || !(notifyList->connectionMask & (1ULL << quint64(index % 64)))) {
237 } else if (index < notifyList->notifiesSize) {
238 return notifyList->notifies[index];
239 } else if (index <= notifyList->maximumTodoIndex) {
240 notifyList->layout();
243 if (index < notifyList->notifiesSize) {
244 return notifyList->notifies[index];
250 bool QQmlData::hasBindingBit(int coreIndex) const
252 int bit = coreIndex * 2;
253 if (bindingBitsSize > bit)
254 return bindingBits[bit / 32] & (1 << (bit % 32));
259 bool QQmlData::hasPendingBindingBit(int coreIndex) const
261 int bit = coreIndex * 2 + 1;
262 if (bindingBitsSize > bit)
263 return bindingBits[bit / 32] & (1 << (bit % 32));
268 void QQmlData::flushPendingBinding(QObject *o, int coreIndex)
270 QQmlData *data = QQmlData::get(o, false);
271 if (data && data->hasPendingBindingBit(coreIndex))
272 data->flushPendingBindingImpl(coreIndex);
277 #endif // QQMLDATA_P_H