1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
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 The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
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 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #ifndef QDECLARATIVECONTEXT_P_H
43 #define QDECLARATIVECONTEXT_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 "qdeclarativecontext.h"
57 
58 #include "private/qdeclarativedata_p.h"
59 #include "private/qdeclarativeintegercache_p.h"
60 #include "private/qdeclarativetypenamecache_p.h"
61 #include "private/qdeclarativenotifier_p.h"
62 #include "qdeclarativelist.h"
63 #include "private/qdeclarativeparser_p.h"
64 
65 #include <QtCore/qhash.h>
66 #include <QtScript/qscriptvalue.h>
67 #include <QtCore/qset.h>
68 
69 #include <private/qobject_p.h>
70 #include "private/qdeclarativeguard_p.h"
71 
72 QT_BEGIN_NAMESPACE
73 
74 class QDeclarativeContext;
75 class QDeclarativeExpression;
76 class QDeclarativeEngine;
77 class QDeclarativeExpression;
78 class QDeclarativeExpressionPrivate;
79 class QDeclarativeAbstractExpression;
80 class QDeclarativeCompiledBindings;
81 class QDeclarativeContextData;
82 
83 class QDeclarativeContextPrivate : public QObjectPrivate
84 {
85     Q_DECLARE_PUBLIC(QDeclarativeContext)
86 public:
87     QDeclarativeContextPrivate();
88 
89     QDeclarativeContextData *data;
90 
91     QList<QVariant> propertyValues;
92     int notifyIndex;
93 
get(QDeclarativeContext * context)94     static QDeclarativeContextPrivate *get(QDeclarativeContext *context) {
95         return static_cast<QDeclarativeContextPrivate *>(QObjectPrivate::get(context));
96     }
get(QDeclarativeContextPrivate * context)97     static QDeclarativeContext *get(QDeclarativeContextPrivate *context) {
98         return static_cast<QDeclarativeContext *>(context->q_func());
99     }
100 
101     // Only used for debugging
102     QList<QPointer<QObject> > instances;
103 
104     static int context_count(QDeclarativeListProperty<QObject> *);
105     static QObject *context_at(QDeclarativeListProperty<QObject> *, int);
106 };
107 
108 class QDeclarativeComponentAttached;
109 class QDeclarativeGuardedContextData;
110 class Q_AUTOTEST_EXPORT QDeclarativeContextData
111 {
112 public:
113     QDeclarativeContextData();
114     QDeclarativeContextData(QDeclarativeContext *);
115     void clearContext();
116     void destroy();
117     void invalidate();
118 
isValid()119     inline bool isValid() const {
120         return engine && (!isInternal || !contextObject || !QObjectPrivate::get(contextObject)->wasDeleted);
121     }
122 
123     // My parent context and engine
124     QDeclarativeContextData *parent;
125     QDeclarativeEngine *engine;
126 
127     void setParent(QDeclarativeContextData *);
128     void refreshExpressions();
129 
130     void addObject(QObject *);
131 
132     QUrl resolvedUrl(const QUrl &);
133 
134     // My containing QDeclarativeContext.  If isInternal is true this owns publicContext.
135     // If internal is false publicContext owns this.
136     QDeclarativeContext *asQDeclarativeContext();
137     QDeclarativeContextPrivate *asQDeclarativeContextPrivate();
138     bool isInternal;
139     QDeclarativeContext *publicContext;
140 
141     // Property name cache
142     QDeclarativeIntegerCache *propertyNames;
143 
144     // Context object
145     QObject *contextObject;
146 
147     // Any script blocks that exist on this context
148     QList<QScriptValue> importedScripts;
149     void addImportedScript(const QDeclarativeParser::Object::ScriptBlock &script);
150 
151     // Context base url
152     QUrl url;
153 
154     // List of imports that apply to this context
155     QDeclarativeTypeNameCache *imports;
156 
157     // My children
158     QDeclarativeContextData *childContexts;
159 
160     // My peers in parent's childContexts list
161     QDeclarativeContextData  *nextChild;
162     QDeclarativeContextData **prevChild;
163 
164     // Expressions that use this context
165     QDeclarativeAbstractExpression *expressions;
166 
167     // Doubly-linked list of objects that are owned by this context
168     QDeclarativeData *contextObjects;
169 
170     // Doubly-linked list of context guards (XXX merge with contextObjects)
171     QDeclarativeGuardedContextData *contextGuards;
172 
173     // id guards
174     struct ContextGuard : public QDeclarativeGuard<QObject>
175     {
ContextGuardContextGuard176         ContextGuard() : context(0) {}
177         inline ContextGuard &operator=(QObject *obj)
178         { QDeclarativeGuard<QObject>::operator=(obj); return *this; }
objectDestroyedContextGuard179         virtual void objectDestroyed(QObject *) {
180             if (context->contextObject && !QObjectPrivate::get(context->contextObject)->wasDeleted) bindings.notify();
181         }
182         QDeclarativeContextData *context;
183         QDeclarativeNotifier bindings;
184     };
185     ContextGuard *idValues;
186     int idValueCount;
187     void setIdProperty(int, QObject *);
188     void setIdPropertyData(QDeclarativeIntegerCache *);
189 
190     // Optimized binding pointer
191     QDeclarativeCompiledBindings *optimizedBindings;
192 
193     // Linked contexts. this owns linkedContext.
194     QDeclarativeContextData *linkedContext;
195 
196     // Linked list of uses of the Component attached property in this
197     // context
198     QDeclarativeComponentAttached *componentAttached;
199 
200     // Return the outermost id for obj, if any.
201     QString findObjectId(const QObject *obj) const;
202 
get(QDeclarativeContext * context)203     static QDeclarativeContextData *get(QDeclarativeContext *context) {
204         return QDeclarativeContextPrivate::get(context)->data;
205     }
206 
207 private:
~QDeclarativeContextData()208     ~QDeclarativeContextData() {}
209 };
210 
211 class QDeclarativeGuardedContextData
212 {
213 public:
214     inline QDeclarativeGuardedContextData();
215     inline QDeclarativeGuardedContextData(QDeclarativeContextData *);
216     inline ~QDeclarativeGuardedContextData();
217 
218     inline void setContextData(QDeclarativeContextData *);
219 
220     inline QDeclarativeContextData *contextData();
221 
222     inline operator QDeclarativeContextData*() const { return m_contextData; }
223     inline QDeclarativeContextData* operator->() const { return m_contextData; }
224     inline QDeclarativeGuardedContextData &operator=(QDeclarativeContextData *d);
225 
226 private:
227     QDeclarativeGuardedContextData &operator=(const QDeclarativeGuardedContextData &);
228     QDeclarativeGuardedContextData(const QDeclarativeGuardedContextData &);
229     friend class QDeclarativeContextData;
230 
231     inline void clear();
232 
233     QDeclarativeContextData *m_contextData;
234     QDeclarativeGuardedContextData  *m_next;
235     QDeclarativeGuardedContextData **m_prev;
236 };
237 
QDeclarativeGuardedContextData()238 QDeclarativeGuardedContextData::QDeclarativeGuardedContextData()
239 : m_contextData(0), m_next(0), m_prev(0)
240 {
241 }
242 
QDeclarativeGuardedContextData(QDeclarativeContextData * data)243 QDeclarativeGuardedContextData::QDeclarativeGuardedContextData(QDeclarativeContextData *data)
244 : m_contextData(0), m_next(0), m_prev(0)
245 {
246     setContextData(data);
247 }
248 
~QDeclarativeGuardedContextData()249 QDeclarativeGuardedContextData::~QDeclarativeGuardedContextData()
250 {
251     clear();
252 }
253 
setContextData(QDeclarativeContextData * contextData)254 void QDeclarativeGuardedContextData::setContextData(QDeclarativeContextData *contextData)
255 {
256     clear();
257 
258     if (contextData) {
259         m_contextData = contextData;
260         m_next = contextData->contextGuards;
261         if (m_next) m_next->m_prev = &m_next;
262         m_prev = &contextData->contextGuards;
263         contextData->contextGuards = this;
264     }
265 }
266 
contextData()267 QDeclarativeContextData *QDeclarativeGuardedContextData::contextData()
268 {
269     return m_contextData;
270 }
271 
clear()272 void QDeclarativeGuardedContextData::clear()
273 {
274     if (m_prev) {
275         *m_prev = m_next;
276         if (m_next) m_next->m_prev = m_prev;
277         m_contextData = 0;
278         m_next = 0;
279         m_prev = 0;
280     }
281 }
282 
283 QDeclarativeGuardedContextData &
284 QDeclarativeGuardedContextData::operator=(QDeclarativeContextData *d)
285 {
286     setContextData(d);
287     return *this;
288 }
289 
290 QT_END_NAMESPACE
291 
292 #endif // QDECLARATIVECONTEXT_P_H
293