Clean up declarative includes
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativeengine_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QDECLARATIVEENGINE_P_H
43 #define QDECLARATIVEENGINE_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 "qdeclarativeengine.h"
57
58 #include "qdeclarativetypeloader_p.h"
59 #include "qdeclarativeimport_p.h"
60 #include <private/qpodvector_p.h>
61 #include "qdeclarative.h"
62 #include "qdeclarativevaluetype_p.h"
63 #include "qdeclarativecontext.h"
64 #include "qdeclarativecontext_p.h"
65 #include "qdeclarativeexpression.h"
66 #include "qdeclarativeimageprovider.h"
67 #include "qdeclarativeproperty_p.h"
68 #include "qdeclarativepropertycache_p.h"
69 #include "qdeclarativemetatype_p.h"
70 #include "qdeclarativedirparser_p.h"
71 #include <private/qintrusivelist_p.h>
72
73 #include <QtCore/qlist.h>
74 #include <QtCore/qpair.h>
75 #include <QtCore/qstack.h>
76 #include <QtCore/qmutex.h>
77 #include <QtCore/qstring.h>
78 #include <QtCore/qthread.h>
79
80 #include <private/qobject_p.h>
81
82 #include <private/qv8engine_p.h>
83
84 QT_BEGIN_NAMESPACE
85
86 class QDeclarativeContext;
87 class QDeclarativeEngine;
88 class QDeclarativeContextPrivate;
89 class QDeclarativeExpression;
90 class QDeclarativeImportDatabase;
91 class QNetworkReply;
92 class QNetworkAccessManager;
93 class QDeclarativeNetworkAccessManagerFactory;
94 class QDeclarativeAbstractBinding;
95 class QDeclarativeTypeNameCache;
96 class QDeclarativeComponentAttached;
97 class QDeclarativeCleanup;
98 class QDeclarativeDelayedError;
99 class QDeclarativeWorkerScriptEngine;
100 class QDeclarativeVME;
101 class QDir;
102 class QSGTexture;
103 class QDeclarativeIncubator;
104 class QSGContext;
105
106 class Q_DECLARATIVE_EXPORT QDeclarativeEnginePrivate : public QObjectPrivate
107 {
108     Q_DECLARE_PUBLIC(QDeclarativeEngine)
109 public:
110     QDeclarativeEnginePrivate(QDeclarativeEngine *);
111     ~QDeclarativeEnginePrivate();
112
113     void init();
114
115     struct CapturedProperty {
116         CapturedProperty(QObject *o, int c, int n)
117             : object(o), coreIndex(c), notifier(0), notifyIndex(n) {}
118         CapturedProperty(QDeclarativeNotifier *n)
119             : object(0), coreIndex(-1), notifier(n), notifyIndex(-1) {}
120
121         QObject *object;
122         int coreIndex;
123         QDeclarativeNotifier *notifier;
124         int notifyIndex;
125     };
126     bool captureProperties;
127     QPODVector<CapturedProperty> capturedProperties;
128
129     QDeclarativeContext *rootContext;
130     bool isDebugging;
131
132     bool outputWarningsToStdErr;
133
134     QDeclarativeContextData *sharedContext;
135     QObject *sharedScope;
136
137     // Registered cleanup handlers
138     QDeclarativeCleanup *cleanup;
139
140     // Bindings that have had errors during startup
141     QDeclarativeDelayedError *erroredBindings;
142     int inProgressCreations;
143
144     QV8Engine *v8engine() const { return q_func()->handle(); }
145
146     QDeclarativeWorkerScriptEngine *getWorkerScriptEngine();
147     QDeclarativeWorkerScriptEngine *workerScriptEngine;
148
149     QUrl baseUrl;
150
151     typedef QPair<QDeclarativeGuard<QObject>,int> FinalizeCallback;
152     void registerFinalizeCallback(QObject *obj, int index);
153
154     QDeclarativeVME *activeVME;
155
156     QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
157     QNetworkAccessManager *getNetworkAccessManager() const;
158     mutable QNetworkAccessManager *networkAccessManager;
159     mutable QDeclarativeNetworkAccessManagerFactory *networkAccessManagerFactory;
160
161     QHash<QString,QSharedPointer<QDeclarativeImageProvider> > imageProviders;
162     QDeclarativeImageProvider::ImageType getImageProviderType(const QUrl &url);
163     QSGTexture *getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
164     QImage getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
165     QPixmap getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
166
167     // Scarce resources are "exceptionally high cost" QVariant types where allowing the
168     // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
169     // out-of-resource situations.  When such a resource is passed into JavaScript we
170     // add it to the scarceResources list and it is destroyed when we return from the
171     // JavaScript execution that created it.  The user can prevent this behavior by
172     // calling preserve() on the object which removes it from this scarceResource list.
173     class ScarceResourceData {
174     public:
175         ScarceResourceData(const QVariant &data) : data(data) {}
176         QVariant data;
177         QIntrusiveListNode node;
178     };
179     QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
180     int scarceResourcesRefCount;
181     void referenceScarceResources();
182     void dereferenceScarceResources();
183
184     QDeclarativeTypeLoader typeLoader;
185     QDeclarativeImportDatabase importDatabase;
186
187     QString offlineStoragePath;
188
189     mutable quint32 uniqueId;
190     inline quint32 getUniqueId() const {
191         return uniqueId++;
192     }
193
194     QDeclarativeValueTypeFactory valueTypes;
195
196     // Unfortunate workaround to avoid a circular dependency between 
197     // qdeclarativeengine_p.h and qdeclarativeincubator_p.h
198     struct Incubator {
199         QIntrusiveListNode next;
200         // Unfortunate workaround for MSVC
201         QIntrusiveListNode nextWaitingFor;
202     };
203     QIntrusiveList<Incubator, &Incubator::next> incubatorList;
204     unsigned int incubatorCount;
205     QDeclarativeIncubationController *incubationController;
206     void incubate(QDeclarativeIncubator &, QDeclarativeContextData *);
207
208     // These methods may be called from any thread
209     inline bool isEngineThread() const;
210     inline static bool isEngineThread(const QDeclarativeEngine *);
211     template<typename T>
212     inline void deleteInEngineThread(T *);
213     template<typename T>
214     inline static void deleteInEngineThread(QDeclarativeEngine *, T *);
215
216     // These methods may be called from the loader thread
217     QDeclarativeMetaType::ModuleApiInstance *moduleApiInstance(const QDeclarativeMetaType::ModuleApi &module);
218
219     // These methods may be called from the loader thread
220     inline QDeclarativePropertyCache *cache(QObject *obj);
221     inline QDeclarativePropertyCache *cache(const QMetaObject *);
222     inline QDeclarativePropertyCache *cache(QDeclarativeType *, int, QDeclarativeError &error);
223
224     // These methods may be called from the loader thread
225     bool isQObject(int);
226     QObject *toQObject(const QVariant &, bool *ok = 0) const;
227     QDeclarativeMetaType::TypeCategory typeCategory(int) const;
228     bool isList(int) const;
229     int listType(int) const;
230     const QMetaObject *rawMetaObjectForType(int) const;
231     const QMetaObject *metaObjectForType(int) const;
232     void registerCompositeType(QDeclarativeCompiledData *);
233
234     void sendQuit();
235     void warning(const QDeclarativeError &);
236     void warning(const QList<QDeclarativeError> &);
237     static void warning(QDeclarativeEngine *, const QDeclarativeError &);
238     static void warning(QDeclarativeEngine *, const QList<QDeclarativeError> &);
239     static void warning(QDeclarativeEnginePrivate *, const QDeclarativeError &);
240     static void warning(QDeclarativeEnginePrivate *, const QList<QDeclarativeError> &);
241
242     inline static QV8Engine *getV8Engine(QDeclarativeEngine *e);
243     inline static QDeclarativeEnginePrivate *get(QDeclarativeEngine *e);
244     inline static const QDeclarativeEnginePrivate *get(const QDeclarativeEngine *e);
245     inline static QDeclarativeEnginePrivate *get(QDeclarativeContext *c);
246     inline static QDeclarativeEnginePrivate *get(QDeclarativeContextData *c);
247     inline static QDeclarativeEngine *get(QDeclarativeEnginePrivate *p);
248
249     static QString urlToLocalFileOrQrc(const QUrl& url);
250     static QString urlToLocalFileOrQrc(const QString& url);
251
252     static void registerBaseTypes(const char *uri, int versionMajor, int versionMinor);
253     static void defineModule();
254
255     static bool qml_debugging_enabled;
256
257     QSGContext *sgContext;
258
259     mutable QMutex mutex;
260
261 private:
262     // Locker locks the QDeclarativeEnginePrivate data structures for read and write, if necessary.  
263     // Currently, locking is only necessary if the threaded loader is running concurrently.  If it is 
264     // either idle, or is running with the main thread blocked, no locking is necessary.  This way
265     // we only pay for locking when we have to.
266     // Consequently, this class should only be used to protect simple accesses or modifications of the 
267     // QDeclarativeEnginePrivate structures or operations that can be guarenteed not to start activity
268     // on the loader thread.
269     // The Locker API is identical to QMutexLocker.  Locker reuses the QDeclarativeEnginePrivate::mutex 
270     // QMutex instance and multiple Lockers are recursive in the same thread.
271     class Locker 
272     {
273     public:
274         inline Locker(const QDeclarativeEngine *);
275         inline Locker(const QDeclarativeEnginePrivate *);
276         inline ~Locker();
277
278         inline void unlock();
279         inline void relock();
280
281     private:
282         const QDeclarativeEnginePrivate *m_ep;
283         quint32 m_locked:1;
284     };
285
286     // Must be called locked
287     QDeclarativePropertyCache *createCache(const QMetaObject *);
288     QDeclarativePropertyCache *createCache(QDeclarativeType *, int, QDeclarativeError &error);
289
290     // These members must be protected by a QDeclarativeEnginePrivate::Locker as they are required by
291     // the threaded loader.  Only access them through their respective accessor methods.
292     QHash<QDeclarativeMetaType::ModuleApi, QDeclarativeMetaType::ModuleApiInstance *> moduleApiInstances;
293     QHash<const QMetaObject *, QDeclarativePropertyCache *> propertyCache;
294     QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *> typePropertyCache;
295     QHash<int, int> m_qmlLists;
296     QHash<int, QDeclarativeCompiledData *> m_compositeTypes;
297
298     // These members is protected by the full QDeclarativeEnginePrivate::mutex mutex
299     struct Deletable { Deletable():next(0) {} virtual ~Deletable() {} Deletable *next; };
300     QFieldList<Deletable, &Deletable::next> toDeleteInEngineThread;
301     void doDeleteInEngineThread();
302 };
303
304 QDeclarativeEnginePrivate::Locker::Locker(const QDeclarativeEngine *e)
305 : m_ep(QDeclarativeEnginePrivate::get(e))
306 {
307     relock();
308 }
309
310 QDeclarativeEnginePrivate::Locker::Locker(const QDeclarativeEnginePrivate *e)
311 : m_ep(e), m_locked(false)
312 {
313     relock();
314 }
315
316 QDeclarativeEnginePrivate::Locker::~Locker()
317 {
318     unlock();
319 }
320
321 void QDeclarativeEnginePrivate::Locker::unlock()
322 {
323     if (m_locked) { 
324         m_ep->mutex.unlock();
325         m_locked = false;
326     }
327 }
328
329 void QDeclarativeEnginePrivate::Locker::relock()
330 {
331     Q_ASSERT(!m_locked);
332     if (m_ep->typeLoader.isConcurrent()) {
333         m_ep->mutex.lock();
334         m_locked = true;
335     }
336 }
337
338 /*!
339 Returns true if the calling thread is the QDeclarativeEngine thread.
340 */
341 bool QDeclarativeEnginePrivate::isEngineThread() const
342 {
343     Q_Q(const QDeclarativeEngine);
344     return QThread::currentThread() == q->thread();
345 }
346
347 /*!
348 Returns true if the calling thread is the QDeclarativeEngine \a engine thread.
349 */
350 bool QDeclarativeEnginePrivate::isEngineThread(const QDeclarativeEngine *engine)
351 {
352     Q_ASSERT(engine);
353     return QDeclarativeEnginePrivate::get(engine)->isEngineThread();
354 }
355
356 /*!
357 Delete \a value in the engine thread.  If the calling thread is the engine
358 thread, \a value will be deleted immediately.
359
360 This method should be used for *any* type that has resources that need to
361 be freed in the engine thread.  This is generally types that use V8 handles.
362 As there is some small overhead in checking the current thread, it is best
363 practice to check if any V8 handles actually need to be freed and delete 
364 the instance directly if not.
365 */
366 template<typename T>
367 void QDeclarativeEnginePrivate::deleteInEngineThread(T *value)
368 {
369     Q_Q(QDeclarativeEngine);
370
371     Q_ASSERT(value);
372     if (isEngineThread()) {
373         delete value;
374     } else { 
375         struct I : public Deletable {
376             I(T *value) : value(value) {}
377             ~I() { delete value; }
378             T *value;
379         };
380         I *i = new I(value);
381         mutex.lock();
382         bool wasEmpty = toDeleteInEngineThread.isEmpty();
383         toDeleteInEngineThread.append(i);
384         mutex.unlock();
385         if (wasEmpty)
386             QCoreApplication::postEvent(q, new QEvent(QEvent::User));
387     }
388 }
389
390 /*!
391 Delete \a value in the \a engine thread.  If the calling thread is the engine
392 thread, \a value will be deleted immediately.
393 */
394 template<typename T>
395 void QDeclarativeEnginePrivate::deleteInEngineThread(QDeclarativeEngine *engine, T *value)
396 {
397     Q_ASSERT(engine);
398     QDeclarativeEnginePrivate::get(engine)->deleteInEngineThread<T>(value);
399 }
400
401 /*!
402 Returns a QDeclarativePropertyCache for \a obj if one is available.
403
404 If \a obj is null, being deleted or contains a dynamic meta object 0
405 is returned.
406
407 The returned cache is not referenced, so if it is to be stored, call addref().
408
409 XXX thread There is a potential future race condition in this and all the cache()
410 functions.  As the QDeclarativePropertyCache is returned unreferenced, when called 
411 from the loader thread, it is possible that the cache will have been dereferenced 
412 and deleted before the loader thread has a chance to use or reference it.  This
413 can't currently happen as the cache holds a reference to the 
414 QDeclarativePropertyCache until the QDeclarativeEngine is destroyed.
415 */
416 QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QObject *obj)
417 {
418     if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
419         return 0;
420
421     Locker locker(this);
422     const QMetaObject *mo = obj->metaObject();
423     QDeclarativePropertyCache *rv = propertyCache.value(mo);
424     if (!rv) rv = createCache(mo);
425     return rv;
426 }
427
428 /*!
429 Returns a QDeclarativePropertyCache for \a metaObject.
430
431 As the cache is persisted for the life of the engine, \a metaObject must be
432 a static "compile time" meta-object, or a meta-object that is otherwise known to
433 exist for the lifetime of the QDeclarativeEngine.
434
435 The returned cache is not referenced, so if it is to be stored, call addref().
436 */
437 QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(const QMetaObject *metaObject)
438 {
439     Q_ASSERT(metaObject);
440
441     Locker locker(this);
442     QDeclarativePropertyCache *rv = propertyCache.value(metaObject);
443     if (!rv) rv = createCache(metaObject);
444     return rv;
445 }
446
447 /*!
448 Returns a QDeclarativePropertyCache for \a type with \a minorVersion.
449
450 The returned cache is not referenced, so if it is to be stored, call addref().
451 */
452 QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QDeclarativeType *type, int minorVersion, QDeclarativeError &error)
453 {
454     Q_ASSERT(type);
455
456     if (minorVersion == -1 || !type->containsRevisionedAttributes())
457         return cache(type->metaObject());
458
459     Locker locker(this);
460     QDeclarativePropertyCache *rv = typePropertyCache.value(qMakePair(type, minorVersion));
461     if (!rv) rv = createCache(type, minorVersion, error);
462     return rv;
463 }
464
465 QV8Engine *QDeclarativeEnginePrivate::getV8Engine(QDeclarativeEngine *e) 
466
467     return e->d_func()->v8engine(); 
468 }
469
470 QDeclarativeEnginePrivate *QDeclarativeEnginePrivate::get(QDeclarativeEngine *e) 
471
472     return e->d_func(); 
473 }
474
475 const QDeclarativeEnginePrivate *QDeclarativeEnginePrivate::get(const QDeclarativeEngine *e) 
476
477     return e->d_func(); 
478 }
479
480 QDeclarativeEnginePrivate *QDeclarativeEnginePrivate::get(QDeclarativeContext *c) 
481
482     return (c && c->engine()) ? QDeclarativeEnginePrivate::get(c->engine()) : 0; 
483 }
484
485 QDeclarativeEnginePrivate *QDeclarativeEnginePrivate::get(QDeclarativeContextData *c) 
486
487     return (c && c->engine) ? QDeclarativeEnginePrivate::get(c->engine) : 0; 
488 }
489
490 QDeclarativeEngine *QDeclarativeEnginePrivate::get(QDeclarativeEnginePrivate *p) 
491
492     return p->q_func(); 
493 }
494
495 QT_END_NAMESPACE
496
497 #endif // QDECLARATIVEENGINE_P_H