Lazily create QMetaObjects
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlengine.cpp
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 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
45
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
48 #include "qqml.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
72 #include <private/qqmlboundsignal_p.h>
73
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
76
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
79 #include <QDebug>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtCore/qthread.h>
84 #include <private/qthread_p.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
86
87 #include <private/qobject_p.h>
88 #include <private/qmetaobject_p.h>
89
90 #include <private/qqmllocale_p.h>
91
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
94 #include <qlibrary.h>
95 #include <windows.h>
96
97 #define CSIDL_APPDATA           0x001a  // <username>\Application Data
98 #endif
99
100 Q_DECLARE_METATYPE(QQmlProperty)
101
102 QT_BEGIN_NAMESPACE
103
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
105 {
106     QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107     QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
108 }
109
110 /*!
111   \qmlclass QtObject QObject
112   \ingroup qml-utility-elements
113   \since 4.7
114   \brief The QtObject element is the most basic element in QML.
115
116   The QtObject element is a non-visual element which contains only the
117   objectName property.
118
119   It can be useful to create a QtObject if you need an extremely
120   lightweight element to enclose a set of custom properties:
121
122   \snippet doc/snippets/qml/qtobject.qml 0
123
124   It can also be useful for C++ integration, as it is just a plain
125   QObject. See the QObject documentation for further details.
126 */
127 /*!
128   \qmlproperty string QtObject::objectName
129   This property holds the QObject::objectName for this specific object instance.
130
131   This allows a C++ application to locate an item within a QML component
132   using the QObject::findChild() method. For example, the following C++
133   application locates the child \l Rectangle item and dynamically changes its
134   \c color value:
135
136     \qml
137     // MyRect.qml
138
139     import QtQuick 2.0
140
141     Item {
142         width: 200; height: 200
143
144         Rectangle {
145             anchors.fill: parent
146             color: "red"
147             objectName: "myRect"
148         }
149     }
150     \endqml
151
152     \code
153     // main.cpp
154
155     QQuickView view;
156     view.setSource(QUrl::fromLocalFile("MyRect.qml"));
157     view.show();
158
159     QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
160     if (item)
161         item->setProperty("color", QColor(Qt::yellow));
162     \endcode
163 */
164
165 bool QQmlEnginePrivate::qml_debugging_enabled = false;
166
167 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
168 {
169     qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
170     qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
171     qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
172     qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
173     qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
174 }
175
176 void QQmlEnginePrivate::defineModule()
177 {
178     registerBaseTypes("QtQuick", 2, 0);
179     qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated.  Use Qt.locale()"));
180 }
181
182
183 /*!
184     \class QQmlImageProviderBase
185     \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
186     \mainclass
187
188     Image providers must be registered with the QML engine.  The only information the QML
189     engine knows about image providers is the type of image data they provide.  To use an
190     image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
191     to a QQuickImageProvider pointer.
192
193     \sa QQuickImageProvider, QQuickTextureFactory
194 */
195
196 /*!
197     \enum QQmlImageProviderBase::ImageType
198
199     Defines the type of image supported by this image provider.
200
201     \value Image The Image Provider provides QImage images.
202         The QQuickImageProvider::requestImage() method will be called for all image requests.
203     \value Pixmap The Image Provider provides QPixmap images.
204         The QQuickImageProvider::requestPixmap() method will be called for all image requests.
205     \value Texture The Image Provider provides QSGTextureProvider based images.
206         The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
207 */
208
209 /*!
210     \enum QQmlImageProviderBase::Flag
211
212     Defines specific requirements or features of this image provider.
213
214     \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
215         run in a separate thread, which allows the provider to spend as much time as needed
216         on producing the image without blocking the main thread.
217 */
218
219 /*! \internal */
220 QQmlImageProviderBase::QQmlImageProviderBase()
221 {
222 }
223
224 /*! \internal */
225 QQmlImageProviderBase::~QQmlImageProviderBase()
226 {
227 }
228
229
230 /*!
231 \qmlclass Qt QQmlEnginePrivate
232   \ingroup qml-utility-elements
233 \brief The QML global Qt object provides useful enums and functions from Qt.
234
235 \keyword QmlGlobalQtObject
236
237 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
238
239 The \c Qt object is a global object with utility functions, properties and enums.
240
241 It is not instantiable; to use it, call the members of the global \c Qt object directly.
242 For example:
243
244 \qml
245 import QtQuick 2.0
246
247 Text {
248     color: Qt.rgba(1, 0, 0, 1)
249     text: Qt.md5("hello, world")
250 }
251 \endqml
252
253
254 \section1 Enums
255
256 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
257 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
258
259
260 \section1 Types
261 The Qt object also contains helper functions for creating objects of specific
262 data types. This is primarily useful when setting the properties of an item
263 when the property has one of the following types:
264
265 \list
266 \li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
267 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
268 \li \c point - use \l{Qt::point()}{Qt.point()}
269 \li \c size - use \l{Qt::size()}{Qt.size()}
270 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
271 \endlist
272
273 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
274
275 \section1 Date/Time Formatters
276
277 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
278
279 \list
280     \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
281     \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
282     \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
283 \endlist
284
285 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
286
287
288 \section1 Dynamic Object Creation
289 The following functions on the global object allow you to dynamically create QML
290 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
291 of their use.
292
293 \list
294     \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
295     \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
296 \endlist
297
298
299 \section1 Other Functions
300
301 The following functions are also on the Qt object.
302
303 \list
304     \li \l{Qt::quit()}{Qt.quit()}
305     \li \l{Qt::md5()}{Qt.md5(string)}
306     \li \l{Qt::btoa()}{string Qt.btoa(string)}
307     \li \l{Qt::atob()}{string Qt.atob(string)}
308     \li \l{Qt::binding()}{object Qt.binding(function)}
309     \li \l{Qt::locale()}{object Qt.locale()}
310     \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
311     \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
312     \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
313 \endlist
314 */
315
316 /*!
317     \qmlproperty object Qt::application
318     \since QtQuick 1.1
319
320     The \c application object provides access to global application state
321     properties shared by many QML components.
322
323     Its properties are:
324
325     \table
326     \row
327     \li \c application.active
328     \li
329     This read-only property indicates whether the application is the top-most and focused
330     application, and the user is able to interact with the application. The property
331     is false when the application is in the background, the device keylock or screen
332     saver is active, the screen backlight is turned off, or the global system dialog
333     is being displayed on top of the application. It can be used for stopping and
334     pausing animations, timers and active processing of data in order to save device
335     battery power and free device memory and processor load when the application is not
336     active.
337
338     \row
339     \li \c application.layoutDirection
340     \li
341     This read-only property can be used to query the default layout direction of the
342     application. On system start-up, the default layout direction depends on the
343     application's language. The property has a value of \c Qt.RightToLeft in locales
344     where text and graphic elements are read from right to left, and \c Qt.LeftToRight
345     where the reading direction flows from left to right. You can bind to this
346     property to customize your application layouts to support both layout directions.
347
348     Possible values are:
349
350     \list
351     \li Qt.LeftToRight - Text and graphics elements should be positioned
352                         from left to right.
353     \li Qt.RightToLeft - Text and graphics elements should be positioned
354                         from right to left.
355     \endlist
356
357     \endtable
358
359     The following example uses the \c application object to indicate
360     whether the application is currently active:
361
362     \snippet doc/snippets/qml/application.qml document
363 */
364
365 /*!
366     \qmlproperty object Qt::inputMethod
367     \since QtQuick 2.0
368
369     The \c inputMethod object allows access to application's QInputMethod object
370     and all its properties and slots. See the QInputMethod documentation for
371     further details.
372 */
373
374
375 /*!
376 \qmlmethod object Qt::include(string url, jsobject callback)
377
378 Includes another JavaScript file. This method can only be used from within JavaScript files,
379 and not regular QML files.
380
381 This imports all functions from \a url into the current script's namespace.
382
383 Qt.include() returns an object that describes the status of the operation.  The object has
384 a single property, \c {status}, that is set to one of the following values:
385
386 \table
387 \header \li Symbol \li Value \li Description
388 \row \li result.OK \li 0 \li The include completed successfully.
389 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
390 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
391 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
392 An additional \c exception property will be set in this case.
393 \endtable
394
395 The \c status property will be updated as the operation progresses.
396
397 If provided, \a callback is invoked when the operation completes.  The callback is passed
398 the same object as is returned from the Qt.include() call.
399 */
400 // Qt.include() is implemented in qv8include.cpp
401
402
403 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
404 : propertyCapture(0), rootContext(0), isDebugging(false),
405   outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
406   cleanup(0), erroredBindings(0), inProgressCreations(0),
407   workerScriptEngine(0), activeVME(0),
408   networkAccessManager(0), networkAccessManagerFactory(0),
409   scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
410   incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
411 {
412 }
413
414 QQmlEnginePrivate::~QQmlEnginePrivate()
415 {
416     if (inProgressCreations)
417         qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
418
419     while (cleanup) {
420         QQmlCleanup *c = cleanup;
421         cleanup = c->next;
422         if (cleanup) cleanup->prev = &cleanup;
423         c->next = 0;
424         c->prev = 0;
425         c->clear();
426     }
427
428     doDeleteInEngineThread();
429
430     if (incubationController) incubationController->d = 0;
431     incubationController = 0;
432
433     delete rootContext;
434     rootContext = 0;
435
436     for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
437         (*iter)->release();
438     for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
439         (*iter)->release();
440     for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
441         delete (*iter)->qobjectApi;
442         delete *iter;
443     }
444     for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
445         iter.value()->isRegisteredWithEngine = false;
446 }
447
448 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
449 {
450     QObjectPrivate *p = QObjectPrivate::get(o);
451     if (p->declarativeData) {
452         QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
453         if (d->ownContext && d->context) {
454             d->context->destroy();
455             d->context = 0;
456         }
457
458         // Mark this object as in the process of deletion to
459         // prevent it resolving in bindings
460         QQmlData::markAsDeleted(o);
461     }
462 }
463
464 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
465 {
466     static_cast<QQmlData *>(d)->destroyed(o);
467 }
468
469 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
470 {
471     static_cast<QQmlData *>(d)->parentChanged(o, p);
472 }
473
474 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
475 {
476     QQmlData *ddata = QQmlData::get(object, false);
477     if (!ddata) return; // Probably being deleted
478
479     // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
480     // that they're exposed to.  However, to make writing "worker objects" that calculate data
481     // in a separate thread easier, QML allows a QObject that lives in the same thread as the
482     // QQmlEngine to emit signals from a different thread.  These signals are then automatically
483     // marshalled back onto the QObject's thread and handled by QML from there.  This is tested
484     // by the qqmlecmascript::threadSignal() autotest.
485     if (ddata->notifyList &&
486         QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
487
488         QMetaMethod m = object->metaObject()->method(index);
489         QList<QByteArray> parameterTypes = m.parameterTypes();
490
491         int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
492         void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
493
494         types[0] = 0; // return type
495         args[0] = 0; // return value
496
497         for (int ii = 0; ii < parameterTypes.count(); ++ii) {
498             const QByteArray &typeName = parameterTypes.at(ii);
499             if (typeName.endsWith('*'))
500                 types[ii + 1] = QMetaType::VoidStar;
501             else
502                 types[ii + 1] = QMetaType::type(typeName);
503
504             if (!types[ii + 1]) {
505                 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
506                          "(Make sure '%s' is registered using qRegisterMetaType().)",
507                          typeName.constData(), typeName.constData());
508                 free(types);
509                 free(args);
510                 return;
511             }
512
513             args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
514         }
515
516         QMetaCallEvent *ev = new QMetaCallEvent(index, 0, 0, object, index,
517                                                 parameterTypes.count() + 1, types, args);
518         QCoreApplication::postEvent(object, ev);
519
520     } else {
521         QQmlNotifierEndpoint *ep = ddata->notify(index);
522         if (ep) QQmlNotifier::emitNotify(ep, a);
523     }
524 }
525
526 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
527 {
528     return static_cast<QQmlData *>(d)->endpointCount(index);
529 }
530
531 int QQmlData::endpointCount(int index)
532 {
533     int count = 0;
534     QQmlNotifierEndpoint *ep = notify(index);
535     if (!ep)
536         return count;
537     ++count;
538     while (ep->next) {
539         ++count;
540         ep = ep->next;
541     }
542     return count;
543 }
544
545 void QQmlData::markAsDeleted(QObject *o)
546 {
547     QQmlData::setQueuedForDeletion(o);
548
549     QObjectPrivate *p = QObjectPrivate::get(o);
550     for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
551         QQmlData::markAsDeleted(*it);
552     }
553 }
554
555 void QQmlData::setQueuedForDeletion(QObject *object)
556 {
557     if (object) {
558         if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
559             if (!priv->wasDeleted && priv->declarativeData) {
560                 QQmlData *ddata = QQmlData::get(object, false);
561                 if (ddata->ownContext && ddata->context)
562                     ddata->context->emitDestruction();
563                 ddata->isQueuedForDeletion = true;
564             }
565         }
566     }
567 }
568
569 void QQmlEnginePrivate::init()
570 {
571     Q_Q(QQmlEngine);
572
573     static bool firstTime = true;
574     if (firstTime) {
575         qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
576
577         QQmlData::init();
578         firstTime = false;
579     }
580
581     qRegisterMetaType<QVariant>("QVariant");
582     qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
583     qRegisterMetaType<QJSValue>("QJSValue");
584     qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
585     qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
586     qRegisterMetaType<QList<int> >("QList<int>");
587     qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
588
589     v8engine()->setEngine(q);
590
591     rootContext = new QQmlContext(q,true);
592
593     if (QCoreApplication::instance()->thread() == q->thread() &&
594         QQmlEngineDebugService::isDebuggingEnabled()) {
595         isDebugging = true;
596         QQmlEngineDebugService::instance()->addEngine(q);
597         QV8DebugService::initialize(v8engine());
598         QV8ProfilerService::initialize();
599         QQmlProfilerService::initialize();
600         QDebugMessageService::instance();
601     }
602
603     QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
604     if (!dataLocation.isEmpty())
605         offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
606                            + QDir::separator() + QLatin1String("QML")
607                            + QDir::separator() + QLatin1String("OfflineStorage");
608 }
609
610 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
611 {
612     Q_Q(QQmlEngine);
613     if (!workerScriptEngine)
614         workerScriptEngine = new QQuickWorkerScriptEngine(q);
615     return workerScriptEngine;
616 }
617
618 /*!
619   \class QQmlEngine
620   \since 5.0
621   \inmodule QtQml
622   \brief The QQmlEngine class provides an environment for instantiating QML components.
623   \mainclass
624
625   Each QML component is instantiated in a QQmlContext.
626   QQmlContext's are essential for passing data to QML
627   components.  In QML, contexts are arranged hierarchically and this
628   hierarchy is managed by the QQmlEngine.
629
630   Prior to creating any QML components, an application must have
631   created a QQmlEngine to gain access to a QML context.  The
632   following example shows how to create a simple Text item.
633
634   \code
635   QQmlEngine engine;
636   QQmlComponent component(&engine);
637   component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
638   QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
639
640   //add item to view, etc
641   ...
642   \endcode
643
644   In this case, the Text item will be created in the engine's
645   \l {QQmlEngine::rootContext()}{root context}.
646
647   Note that the QtQuick 1 version is called QDeclarativeEngine.
648
649   \sa QQmlComponent, QQmlContext
650 */
651
652 /*!
653   Create a new QQmlEngine with the given \a parent.
654 */
655 QQmlEngine::QQmlEngine(QObject *parent)
656 : QJSEngine(*new QQmlEnginePrivate(this), parent)
657 {
658     Q_D(QQmlEngine);
659     d->init();
660 }
661
662 /*!
663   Destroys the QQmlEngine.
664
665   Any QQmlContext's created on this engine will be
666   invalidated, but not destroyed (unless they are parented to the
667   QQmlEngine object).
668 */
669 QQmlEngine::~QQmlEngine()
670 {
671     Q_D(QQmlEngine);
672     if (d->isDebugging) {
673         QQmlEngineDebugService::instance()->remEngine(this);
674     }
675
676     // Emit onDestruction signals for the root context before
677     // we destroy the contexts, engine, Module APIs etc. that
678     // may be required to handle the destruction signal.
679     QQmlContextData::get(rootContext())->emitDestruction();
680
681     // if we are the parent of any of the qobject module api instances,
682     // we need to remove them from our internal list, in order to prevent
683     // a segfault in engine private dtor.
684     QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
685     QObject *currQObjectApi = 0;
686     QQmlMetaType::ModuleApiInstance *currInstance = 0;
687     foreach (const QQmlMetaType::ModuleApi &key, keys) {
688         currInstance = d->moduleApiInstances.value(key);
689         currQObjectApi = currInstance->qobjectApi;
690         if (this->children().contains(currQObjectApi)) {
691             delete currQObjectApi;
692             delete currInstance;
693             d->moduleApiInstances.remove(key);
694         }
695     }
696
697     if (d->incubationController)
698         d->incubationController->d = 0;
699 }
700
701 /*! \fn void QQmlEngine::quit()
702     This signal is emitted when the QML loaded by the engine would like to quit.
703  */
704
705 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
706     This signal is emitted when \a warnings messages are generated by QML.
707  */
708
709 /*!
710   Clears the engine's internal component cache.
711
712   This function causes the property metadata of all components previously
713   loaded by the engine to be destroyed.  All previously loaded components and
714   the property bindings for all extant objects created from those components will
715   cease to function.
716
717   This function returns the engine to a state where it does not contain any loaded
718   component data.  This may be useful in order to reload a smaller subset of the
719   previous component set, or to load a new version of a previously loaded component.
720
721   Once the component cache has been cleared, components must be loaded before
722   any new objects can be created.
723
724   \sa trimComponentCache()
725  */
726 void QQmlEngine::clearComponentCache()
727 {
728     Q_D(QQmlEngine);
729     d->typeLoader.clearCache();
730 }
731
732 /*!
733   Trims the engine's internal component cache.
734
735   This function causes the property metadata of any loaded components which are
736   not currently in use to be destroyed.
737
738   A component is considered to be in use if there are any extant instances of
739   the component itself, any instances of other components that use the component,
740   or any objects instantiated by any of those components.
741
742   \sa clearComponentCache()
743  */
744 void QQmlEngine::trimComponentCache()
745 {
746     Q_D(QQmlEngine);
747     d->typeLoader.trimCache();
748 }
749
750 /*!
751   Returns the engine's root context.
752
753   The root context is automatically created by the QQmlEngine.
754   Data that should be available to all QML component instances
755   instantiated by the engine should be put in the root context.
756
757   Additional data that should only be available to a subset of
758   component instances should be added to sub-contexts parented to the
759   root context.
760 */
761 QQmlContext *QQmlEngine::rootContext() const
762 {
763     Q_D(const QQmlEngine);
764     return d->rootContext;
765 }
766
767 /*!
768   Sets the \a factory to use for creating QNetworkAccessManager(s).
769
770   QNetworkAccessManager is used for all network access by QML.  By
771   implementing a factory it is possible to create custom
772   QNetworkAccessManager with specialized caching, proxy and cookie
773   support.
774
775   The factory must be set before executing the engine.
776 */
777 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
778 {
779     Q_D(QQmlEngine);
780     QMutexLocker locker(&d->mutex);
781     d->networkAccessManagerFactory = factory;
782 }
783
784 /*!
785   Returns the current QQmlNetworkAccessManagerFactory.
786
787   \sa setNetworkAccessManagerFactory()
788 */
789 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
790 {
791     Q_D(const QQmlEngine);
792     return d->networkAccessManagerFactory;
793 }
794
795 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
796 {
797     if (activeVME) {
798         activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
799     } else {
800         void *args[] = { 0 };
801         QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
802     }
803 }
804
805 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
806 {
807     QMutexLocker locker(&mutex);
808     QNetworkAccessManager *nam;
809     if (networkAccessManagerFactory) {
810         nam = networkAccessManagerFactory->create(parent);
811     } else {
812         nam = new QNetworkAccessManager(parent);
813     }
814
815     return nam;
816 }
817
818 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
819 {
820     Q_Q(const QQmlEngine);
821     if (!networkAccessManager)
822         networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
823     return networkAccessManager;
824 }
825
826 /*!
827   Returns a common QNetworkAccessManager which can be used by any QML
828   element instantiated by this engine.
829
830   If a QQmlNetworkAccessManagerFactory has been set and a
831   QNetworkAccessManager has not yet been created, the
832   QQmlNetworkAccessManagerFactory will be used to create the
833   QNetworkAccessManager; otherwise the returned QNetworkAccessManager
834   will have no proxy or cache set.
835
836   \sa setNetworkAccessManagerFactory()
837 */
838 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
839 {
840     Q_D(const QQmlEngine);
841     return d->getNetworkAccessManager();
842 }
843
844 /*!
845
846   Sets the \a provider to use for images requested via the \e
847   image: url scheme, with host \a providerId. The QQmlEngine
848   takes ownership of \a provider.
849
850   Image providers enable support for pixmap and threaded image
851   requests. See the QQuickImageProvider documentation for details on
852   implementing and using image providers.
853
854   All required image providers should be added to the engine before any
855   QML sources files are loaded.
856
857   \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
858 */
859 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
860 {
861     Q_D(QQmlEngine);
862     QMutexLocker locker(&d->mutex);
863     d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
864 }
865
866 /*!
867   Returns the image provider set for \a providerId.
868
869   Returns the provider if it was found; otherwise returns 0.
870
871   \sa QQuickImageProvider
872 */
873 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
874 {
875     Q_D(const QQmlEngine);
876     QMutexLocker locker(&d->mutex);
877     return d->imageProviders.value(providerId).data();
878 }
879
880 /*!
881   Removes the image provider for \a providerId.
882
883   \sa addImageProvider(), QQuickImageProvider
884 */
885 void QQmlEngine::removeImageProvider(const QString &providerId)
886 {
887     Q_D(QQmlEngine);
888     QMutexLocker locker(&d->mutex);
889     d->imageProviders.take(providerId);
890 }
891
892 /*!
893   Return the base URL for this engine.  The base URL is only used to
894   resolve components when a relative URL is passed to the
895   QQmlComponent constructor.
896
897   If a base URL has not been explicitly set, this method returns the
898   application's current working directory.
899
900   \sa setBaseUrl()
901 */
902 QUrl QQmlEngine::baseUrl() const
903 {
904     Q_D(const QQmlEngine);
905     if (d->baseUrl.isEmpty()) {
906         return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
907     } else {
908         return d->baseUrl;
909     }
910 }
911
912 /*!
913   Set the  base URL for this engine to \a url.
914
915   \sa baseUrl()
916 */
917 void QQmlEngine::setBaseUrl(const QUrl &url)
918 {
919     Q_D(QQmlEngine);
920     d->baseUrl = url;
921 }
922
923 /*!
924   Returns true if warning messages will be output to stderr in addition
925   to being emitted by the warnings() signal, otherwise false.
926
927   The default value is true.
928 */
929 bool QQmlEngine::outputWarningsToStandardError() const
930 {
931     Q_D(const QQmlEngine);
932     return d->outputWarningsToStdErr;
933 }
934
935 /*!
936   Set whether warning messages will be output to stderr to \a enabled.
937
938   If \a enabled is true, any warning messages generated by QML will be
939   output to stderr and emitted by the warnings() signal.  If \a enabled
940   is false, on the warnings() signal will be emitted.  This allows
941   applications to handle warning output themselves.
942
943   The default value is true.
944 */
945 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
946 {
947     Q_D(QQmlEngine);
948     d->outputWarningsToStdErr = enabled;
949 }
950
951 /*!
952   Returns the QQmlContext for the \a object, or 0 if no
953   context has been set.
954
955   When the QQmlEngine instantiates a QObject, the context is
956   set automatically.
957   */
958 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
959 {
960     if(!object)
961         return 0;
962
963     QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
964
965     QQmlData *data =
966         static_cast<QQmlData *>(priv->declarativeData);
967
968     if (!data)
969         return 0;
970     else if (data->outerContext)
971         return data->outerContext->asQQmlContext();
972     else
973         return 0;
974 }
975
976 /*!
977   Sets the QQmlContext for the \a object to \a context.
978   If the \a object already has a context, a warning is
979   output, but the context is not changed.
980
981   When the QQmlEngine instantiates a QObject, the context is
982   set automatically.
983  */
984 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
985 {
986     if (!object || !context)
987         return;
988
989     QQmlData *data = QQmlData::get(object, true);
990     if (data->context) {
991         qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
992         return;
993     }
994
995     QQmlContextData *contextData = QQmlContextData::get(context);
996     contextData->addObject(object);
997 }
998
999 /*!
1000   \enum QQmlEngine::ObjectOwnership
1001
1002   Ownership controls whether or not QML automatically destroys the
1003   QObject when the object is garbage collected by the JavaScript
1004   engine.  The two ownership options are:
1005
1006   \value CppOwnership The object is owned by C++ code, and will
1007   never be deleted by QML.  The JavaScript destroy() method cannot be
1008   used on objects with CppOwnership.  This option is similar to
1009   QScriptEngine::QtOwnership.
1010
1011   \value JavaScriptOwnership The object is owned by JavaScript.
1012   When the object is returned to QML as the return value of a method
1013   call or property access, QML will track it, and delete the object
1014   if there are no remaining JavaScript references to it and it has no
1015   QObject::parent().  An object tracked by one QQmlEngine
1016   will be deleted during that QQmlEngine's destructor, and thus
1017   JavaScript references between objects with JavaScriptOwnership from
1018   two different engines will not be valid after the deletion of one of
1019   those engines.  This option is similar to QScriptEngine::ScriptOwnership.
1020
1021   Generally an application doesn't need to set an object's ownership
1022   explicitly.  QML uses a heuristic to set the default object
1023   ownership.  By default, an object that is created by QML has
1024   JavaScriptOwnership.  The exception to this are the root objects
1025   created by calling QQmlComponent::create() or
1026   QQmlComponent::beginCreate() which have CppOwnership by
1027   default.  The ownership of these root-level objects is considered to
1028   have been transferred to the C++ caller.
1029
1030   Objects not-created by QML have CppOwnership by default.  The
1031   exception to this is objects returned from a C++ method call.  The
1032   ownership of these objects is passed to JavaScript.
1033
1034   Calling setObjectOwnership() overrides the default ownership
1035   heuristic used by QML.
1036 */
1037
1038 /*!
1039   Sets the \a ownership of \a object.
1040 */
1041 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1042 {
1043     if (!object)
1044         return;
1045
1046     QQmlData *ddata = QQmlData::get(object, true);
1047     if (!ddata)
1048         return;
1049
1050     ddata->indestructible = (ownership == CppOwnership)?true:false;
1051     ddata->explicitIndestructibleSet = true;
1052 }
1053
1054 /*!
1055   Returns the ownership of \a object.
1056 */
1057 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1058 {
1059     if (!object)
1060         return CppOwnership;
1061
1062     QQmlData *ddata = QQmlData::get(object, false);
1063     if (!ddata)
1064         return CppOwnership;
1065     else
1066         return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1067 }
1068
1069 bool QQmlEngine::event(QEvent *e)
1070 {
1071     Q_D(QQmlEngine);
1072     if (e->type() == QEvent::User)
1073         d->doDeleteInEngineThread();
1074
1075     return QJSEngine::event(e);
1076 }
1077
1078 void QQmlEnginePrivate::doDeleteInEngineThread()
1079 {
1080     QFieldList<Deletable, &Deletable::next> list;
1081     mutex.lock();
1082     list.copyAndClear(toDeleteInEngineThread);
1083     mutex.unlock();
1084
1085     while (Deletable *d = list.takeFirst())
1086         delete d;
1087 }
1088
1089 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1090 {
1091     QQmlData *data = QQmlData::get(object);
1092
1093     if (data && data->compiledData && data->deferredIdx) {
1094         QQmlObjectCreatingProfiler prof;
1095         if (prof.enabled) {
1096             QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1097             prof.setTypeName(type ? type->qmlTypeName()
1098                                   : QString::fromUtf8(object->metaObject()->className()));
1099             if (data->outerContext)
1100                 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1101         }
1102         QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1103
1104         QQmlComponentPrivate::ConstructionState state;
1105         QQmlComponentPrivate::beginDeferred(ep, object, &state);
1106
1107         // Release the reference for the deferral action (we still have one from construction)
1108         data->compiledData->release();
1109         data->compiledData = 0;
1110
1111         QQmlComponentPrivate::complete(ep, &state);
1112     }
1113 }
1114
1115 QQmlContext *qmlContext(const QObject *obj)
1116 {
1117     return QQmlEngine::contextForObject(obj);
1118 }
1119
1120 QQmlEngine *qmlEngine(const QObject *obj)
1121 {
1122     QQmlData *data = QQmlData::get(obj, false);
1123     if (!data || !data->context)
1124         return 0;
1125     return data->context->engine;
1126 }
1127
1128 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1129 {
1130     QQmlData *data = QQmlData::get(object);
1131     if (!data)
1132         return 0; // Attached properties are only on objects created by QML
1133
1134     QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1135     if (rv || !create)
1136         return rv;
1137
1138     QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1139     if (!pf)
1140         return 0;
1141
1142     rv = pf(const_cast<QObject *>(object));
1143
1144     if (rv)
1145         data->attachedProperties()->insert(id, rv);
1146
1147     return rv;
1148 }
1149
1150 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1151                                      const QMetaObject *attachedMetaObject, bool create)
1152 {
1153     if (*idCache == -1)
1154         *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1155
1156     if (*idCache == -1 || !object)
1157         return 0;
1158
1159     return qmlAttachedPropertiesObjectById(*idCache, object, create);
1160 }
1161
1162 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1163 {
1164 #ifndef QQML_NO_DEBUG_PROTOCOL
1165     if (!QQmlEnginePrivate::qml_debugging_enabled
1166             && printWarning) {
1167         qDebug("QML debugging is enabled. Only use this in a safe environment.");
1168     }
1169     QQmlEnginePrivate::qml_debugging_enabled = true;
1170 #endif
1171 }
1172
1173
1174 class QQmlDataExtended {
1175 public:
1176     QQmlDataExtended();
1177     ~QQmlDataExtended();
1178
1179     QHash<int, QObject *> attachedProperties;
1180 };
1181
1182 QQmlDataExtended::QQmlDataExtended()
1183 {
1184 }
1185
1186 QQmlDataExtended::~QQmlDataExtended()
1187 {
1188 }
1189
1190 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1191 {
1192     if (endpoint->next)
1193         layout(endpoint->next);
1194
1195     int index = endpoint->sourceSignal;
1196     index = qMin(index, 0xFFFF - 1);
1197
1198     endpoint->next = notifies[index];
1199     if (endpoint->next) endpoint->next->prev = &endpoint->next;
1200     endpoint->prev = &notifies[index];
1201     notifies[index] = endpoint;
1202 }
1203
1204 void QQmlData::NotifyList::layout()
1205 {
1206     Q_ASSERT(maximumTodoIndex >= notifiesSize);
1207
1208     if (todo) {
1209         QQmlNotifierEndpoint **old = notifies;
1210         const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1211         notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1212         const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1213                                sizeof(QQmlNotifierEndpoint*);
1214         memset(notifies + notifiesSize, 0, memsetSize);
1215
1216         if (notifies != old) {
1217             for (int ii = 0; ii < notifiesSize; ++ii)
1218                 if (notifies[ii])
1219                     notifies[ii]->prev = &notifies[ii];
1220         }
1221
1222         notifiesSize = maximumTodoIndex + 1;
1223
1224         layout(todo);
1225     }
1226
1227     maximumTodoIndex = 0;
1228     todo = 0;
1229 }
1230
1231 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1232 {
1233     if (!notifyList) {
1234         notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1235         notifyList->connectionMask = 0;
1236         notifyList->maximumTodoIndex = 0;
1237         notifyList->notifiesSize = 0;
1238         notifyList->todo = 0;
1239         notifyList->notifies = 0;
1240     }
1241
1242     Q_ASSERT(!endpoint->isConnected());
1243
1244     index = qMin(index, 0xFFFF - 1);
1245     notifyList->connectionMask |= (1ULL << quint64(index % 64));
1246
1247     if (index < notifyList->notifiesSize) {
1248
1249         endpoint->next = notifyList->notifies[index];
1250         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1251         endpoint->prev = &notifyList->notifies[index];
1252         notifyList->notifies[index] = endpoint;
1253
1254     } else {
1255         notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1256
1257         endpoint->next = notifyList->todo;
1258         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1259         endpoint->prev = &notifyList->todo;
1260         notifyList->todo = endpoint;
1261     }
1262 }
1263
1264 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1265 {
1266     QQmlData *data = QQmlData::get(obj);
1267     return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1268 }
1269
1270 /*
1271     index MUST be the index returned by QMetaMethod::index()
1272     This is different than the index returned by QObjectPrivate::signalIndex()
1273 */
1274 bool QQmlData::signalHasEndpoint(int index)
1275 {
1276     return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1277 }
1278
1279 QHash<int, QObject *> *QQmlData::attachedProperties() const
1280 {
1281     if (!extendedData) extendedData = new QQmlDataExtended;
1282     return &extendedData->attachedProperties;
1283 }
1284
1285 void QQmlData::destroyed(QObject *object)
1286 {
1287     if (nextContextObject)
1288         nextContextObject->prevContextObject = prevContextObject;
1289     if (prevContextObject)
1290         *prevContextObject = nextContextObject;
1291
1292     QQmlAbstractBinding *binding = bindings;
1293     while (binding) {
1294         QQmlAbstractBinding *next = binding->m_nextBinding;
1295         binding->m_prevBinding = 0;
1296         binding->m_nextBinding = 0;
1297         binding->destroy();
1298         binding = next;
1299     }
1300
1301     if (compiledData) {
1302         compiledData->release();
1303         compiledData = 0;
1304     }
1305
1306     QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1307     while (signalHandler) {
1308         if (signalHandler->isEvaluating()) {
1309             // The object is being deleted during signal handler evaluation.
1310             // This will cause a crash due to invalid memory access when the
1311             // evaluation has completed.
1312             // Abort with a friendly message instead.
1313             QString locationString;
1314             QQmlBoundSignalExpression *expr = signalHandler->expression();
1315             if (expr) {
1316                 QString fileName = expr->sourceFile();
1317                 if (fileName.isEmpty())
1318                     fileName = QStringLiteral("<Unknown File>");
1319                 locationString.append(fileName);
1320                 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1321                 QString source = expr->expression();
1322                 if (source.size() > 100) {
1323                     source.truncate(96);
1324                     source.append(QStringLiteral(" ..."));
1325                 }
1326                 locationString.append(source);
1327             } else {
1328                 locationString = QStringLiteral("<Unknown Location>");
1329             }
1330             qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1331                    "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1332                    "instead), or the application is running a nested event loop.\n"
1333                    "This behavior is NOT supported!\n"
1334                    "%s", object, qPrintable(locationString));
1335         }
1336
1337         QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1338         signalHandler->m_prevSignal = 0;
1339         signalHandler->m_nextSignal = 0;
1340         delete signalHandler;
1341         signalHandler = next;
1342     }
1343
1344     if (bindingBits)
1345         free(bindingBits);
1346
1347     if (propertyCache)
1348         propertyCache->release();
1349
1350     if (ownContext && context)
1351         context->destroy();
1352
1353     while (guards) {
1354         QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1355         *guard = (QObject *)0;
1356         guard->objectDestroyed(object);
1357     }
1358
1359     if (notifyList) {
1360         while (notifyList->todo)
1361             notifyList->todo->disconnect();
1362         for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1363             while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1364                 ep->disconnect();
1365         }
1366         free(notifyList->notifies);
1367         free(notifyList);
1368         notifyList = 0;
1369     }
1370
1371     if (extendedData)
1372         delete extendedData;
1373
1374     // Dispose the handle.
1375     // We don't simply clear it (and wait for next gc cycle to dispose
1376     // via the weak qobject reference callback) as this affects the
1377     // outcomes of v8's gc statistical analysis heuristics, which can
1378     // cause unnecessary growth of the old pointer space js heap area.
1379     qPersistentDispose(v8object);
1380
1381     if (ownMemory)
1382         delete this;
1383 }
1384
1385 void QQmlData::parentChanged(QObject *object, QObject *parent)
1386 {
1387     Q_UNUSED(object);
1388     Q_UNUSED(parent);
1389 }
1390
1391 bool QQmlData::hasBindingBit(int bit) const
1392 {
1393     if (bindingBitsSize > bit)
1394         return bindingBits[bit / 32] & (1 << (bit % 32));
1395     else
1396         return false;
1397 }
1398
1399 void QQmlData::clearBindingBit(int bit)
1400 {
1401     if (bindingBitsSize > bit)
1402         bindingBits[bit / 32] &= ~(1 << (bit % 32));
1403 }
1404
1405 void QQmlData::setBindingBit(QObject *obj, int bit)
1406 {
1407     if (bindingBitsSize <= bit) {
1408         int props = QQmlMetaObject(obj).propertyCount();
1409         Q_ASSERT(bit < props);
1410
1411         int arraySize = (props + 31) / 32;
1412         int oldArraySize = bindingBitsSize / 32;
1413
1414         bindingBits = (quint32 *)realloc(bindingBits,
1415                                          arraySize * sizeof(quint32));
1416
1417         memset(bindingBits + oldArraySize,
1418                0x00,
1419                sizeof(quint32) * (arraySize - oldArraySize));
1420
1421         bindingBitsSize = arraySize * 32;
1422     }
1423
1424     bindingBits[bit / 32] |= (1 << (bit % 32));
1425 }
1426
1427 void QQmlEnginePrivate::sendQuit()
1428 {
1429     Q_Q(QQmlEngine);
1430     emit q->quit();
1431     if (q->receivers(SIGNAL(quit())) == 0) {
1432         qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1433     }
1434 }
1435
1436 static void dumpwarning(const QQmlError &error)
1437 {
1438     QMessageLogger(error.url().toString().toLatin1().constData(),
1439                    error.line(), 0).warning().nospace()
1440             << qPrintable(error.toString());
1441 }
1442
1443 static void dumpwarning(const QList<QQmlError> &errors)
1444 {
1445     for (int ii = 0; ii < errors.count(); ++ii)
1446         dumpwarning(errors.at(ii));
1447 }
1448
1449 void QQmlEnginePrivate::warning(const QQmlError &error)
1450 {
1451     Q_Q(QQmlEngine);
1452     q->warnings(QList<QQmlError>() << error);
1453     if (outputWarningsToStdErr)
1454         dumpwarning(error);
1455 }
1456
1457 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1458 {
1459     Q_Q(QQmlEngine);
1460     q->warnings(errors);
1461     if (outputWarningsToStdErr)
1462         dumpwarning(errors);
1463 }
1464
1465 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1466 {
1467     if (engine)
1468         QQmlEnginePrivate::get(engine)->warning(error);
1469     else
1470         dumpwarning(error);
1471 }
1472
1473 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1474 {
1475     if (engine)
1476         QQmlEnginePrivate::get(engine)->warning(error);
1477     else
1478         dumpwarning(error);
1479 }
1480
1481 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1482 {
1483     if (engine)
1484         engine->warning(error);
1485     else
1486         dumpwarning(error);
1487 }
1488
1489 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1490 {
1491     if (engine)
1492         engine->warning(error);
1493     else
1494         dumpwarning(error);
1495 }
1496
1497 /*
1498    This function should be called prior to evaluation of any js expression,
1499    so that scarce resources are not freed prematurely (eg, if there is a
1500    nested javascript expression).
1501  */
1502 void QQmlEnginePrivate::referenceScarceResources()
1503 {
1504     scarceResourcesRefCount += 1;
1505 }
1506
1507 /*
1508    This function should be called after evaluation of the js expression is
1509    complete, and so the scarce resources may be freed safely.
1510  */
1511 void QQmlEnginePrivate::dereferenceScarceResources()
1512 {
1513     Q_ASSERT(scarceResourcesRefCount > 0);
1514     scarceResourcesRefCount -= 1;
1515
1516     // if the refcount is zero, then evaluation of the "top level"
1517     // expression must have completed.  We can safely release the
1518     // scarce resources.
1519     if (scarceResourcesRefCount == 0) {
1520         // iterate through the list and release them all.
1521         // note that the actual SRD is owned by the JS engine,
1522         // so we cannot delete the SRD; but we can free the
1523         // memory used by the variant in the SRD.
1524         while (ScarceResourceData *sr = scarceResources.first()) {
1525             sr->data = QVariant();
1526             scarceResources.remove(sr);
1527         }
1528     }
1529 }
1530
1531 /*!
1532   Adds \a path as a directory where the engine searches for
1533   installed modules in a URL-based directory structure.
1534   The \a path may be a local filesystem directory or a URL.
1535
1536   The newly added \a path will be first in the importPathList().
1537
1538   \sa setImportPathList(), {QML Modules}
1539 */
1540 void QQmlEngine::addImportPath(const QString& path)
1541 {
1542     Q_D(QQmlEngine);
1543     d->importDatabase.addImportPath(path);
1544 }
1545
1546 /*!
1547   Returns the list of directories where the engine searches for
1548   installed modules in a URL-based directory structure.
1549
1550   For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1551   imports \c com.mycompany.Feature will cause the QQmlEngine to look
1552   in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1553   provided by that module. A \c qmldir file is required for defining the
1554   type version mapping and possibly QML extensions plugins.
1555
1556   By default, the list contains the directory of the application executable,
1557   paths specified in the \c QML_IMPORT_PATH environment variable,
1558   and the builtin \c ImportsPath from QLibraryInfo.
1559
1560   \sa addImportPath(), setImportPathList()
1561 */
1562 QStringList QQmlEngine::importPathList() const
1563 {
1564     Q_D(const QQmlEngine);
1565     return d->importDatabase.importPathList();
1566 }
1567
1568 /*!
1569   Sets \a paths as the list of directories where the engine searches for
1570   installed modules in a URL-based directory structure.
1571
1572   By default, the list contains the directory of the application executable,
1573   paths specified in the \c QML_IMPORT_PATH environment variable,
1574   and the builtin \c ImportsPath from QLibraryInfo.
1575
1576   \sa importPathList(), addImportPath()
1577   */
1578 void QQmlEngine::setImportPathList(const QStringList &paths)
1579 {
1580     Q_D(QQmlEngine);
1581     d->importDatabase.setImportPathList(paths);
1582 }
1583
1584
1585 /*!
1586   Adds \a path as a directory where the engine searches for
1587   native plugins for imported modules (referenced in the \c qmldir file).
1588
1589   By default, the list contains only \c .,  i.e. the engine searches
1590   in the directory of the \c qmldir file itself.
1591
1592   The newly added \a path will be first in the pluginPathList().
1593
1594   \sa setPluginPathList()
1595 */
1596 void QQmlEngine::addPluginPath(const QString& path)
1597 {
1598     Q_D(QQmlEngine);
1599     d->importDatabase.addPluginPath(path);
1600 }
1601
1602
1603 /*!
1604   Returns the list of directories where the engine searches for
1605   native plugins for imported modules (referenced in the \c qmldir file).
1606
1607   By default, the list contains only \c .,  i.e. the engine searches
1608   in the directory of the \c qmldir file itself.
1609
1610   \sa addPluginPath(), setPluginPathList()
1611 */
1612 QStringList QQmlEngine::pluginPathList() const
1613 {
1614     Q_D(const QQmlEngine);
1615     return d->importDatabase.pluginPathList();
1616 }
1617
1618 /*!
1619   Sets the list of directories where the engine searches for
1620   native plugins for imported modules (referenced in the \c qmldir file)
1621   to \a paths.
1622
1623   By default, the list contains only \c .,  i.e. the engine searches
1624   in the directory of the \c qmldir file itself.
1625
1626   \sa pluginPathList(), addPluginPath()
1627   */
1628 void QQmlEngine::setPluginPathList(const QStringList &paths)
1629 {
1630     Q_D(QQmlEngine);
1631     d->importDatabase.setPluginPathList(paths);
1632 }
1633
1634 /*!
1635   Imports the plugin named \a filePath with the \a uri provided.
1636   Returns true if the plugin was successfully imported; otherwise returns false.
1637
1638   On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1639
1640   The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1641 */
1642 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1643 {
1644     Q_D(QQmlEngine);
1645     return d->importDatabase.importPlugin(filePath, uri, errors);
1646 }
1647
1648 /*!
1649   Imports the plugin named \a filePath with the \a uri provided.
1650   Returns true if the plugin was successfully imported; otherwise returns false.
1651
1652   On failure and if non-null, *\a errorString will be set to a message describing the failure.
1653
1654   The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1655 */
1656 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1657 {
1658     Q_D(QQmlEngine);
1659     QList<QQmlError> errors;
1660     bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1661     if (!errors.isEmpty()) {
1662         QString builtError;
1663         for (int i = 0; i < errors.size(); ++i) {
1664             builtError = QString(QLatin1String("%1\n        %2"))
1665                     .arg(builtError)
1666                     .arg(errors.at(i).toString());
1667         }
1668         *errorString = builtError;
1669     }
1670     return retn;
1671 }
1672
1673 /*!
1674   \property QQmlEngine::offlineStoragePath
1675   \brief the directory for storing offline user data
1676
1677   Returns the directory where SQL and other offline
1678   storage is placed.
1679
1680   QQuickWebView and the SQL databases created with openDatabase()
1681   are stored here.
1682
1683   The default is QML/OfflineStorage in the platform-standard
1684   user application data directory.
1685
1686   Note that the path may not currently exist on the filesystem, so
1687   callers wanting to \e create new files at this location should create
1688   it first - see QDir::mkpath().
1689 */
1690 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1691 {
1692     Q_D(QQmlEngine);
1693     d->offlineStoragePath = dir;
1694 }
1695
1696 QString QQmlEngine::offlineStoragePath() const
1697 {
1698     Q_D(const QQmlEngine);
1699     return d->offlineStoragePath;
1700 }
1701
1702 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1703 {
1704     Q_Q(QQmlEngine);
1705
1706     if (!mo->superClass()) {
1707         QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1708         propertyCache.insert(mo, rv);
1709         return rv;
1710     } else {
1711         QQmlPropertyCache *super = cache(mo->superClass());
1712         QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1713         propertyCache.insert(mo, rv);
1714         return rv;
1715     }
1716 }
1717
1718 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1719                                                                   QQmlError &error)
1720 {
1721     QList<QQmlType *> types;
1722
1723     int maxMinorVersion = 0;
1724
1725     const QMetaObject *metaObject = type->metaObject();
1726
1727     while (metaObject) {
1728         QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1729                                                             type->majorVersion(), minorVersion);
1730         if (t) {
1731             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1732             types << t;
1733         } else {
1734             types << 0;
1735         }
1736
1737         metaObject = metaObject->superClass();
1738     }
1739
1740     if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1741         c->addref();
1742         typePropertyCache.insert(qMakePair(type, minorVersion), c);
1743         return c;
1744     }
1745
1746     QQmlPropertyCache *raw = cache(type->metaObject());
1747
1748     bool hasCopied = false;
1749
1750     for (int ii = 0; ii < types.count(); ++ii) {
1751         QQmlType *currentType = types.at(ii);
1752         if (!currentType)
1753             continue;
1754
1755         int rev = currentType->metaObjectRevision();
1756         int moIndex = types.count() - 1 - ii;
1757
1758         if (raw->allowedRevisionCache[moIndex] != rev) {
1759             if (!hasCopied) {
1760                 raw = raw->copy();
1761                 hasCopied = true;
1762             }
1763             raw->allowedRevisionCache[moIndex] = rev;
1764         }
1765     }
1766
1767     // Test revision compatibility - the basic rule is:
1768     //    * Anything that is excluded, cannot overload something that is not excluded *
1769
1770     // Signals override:
1771     //    * other signals and methods of the same name.
1772     //    * properties named on<Signal Name>
1773     //    * automatic <property name>Changed notify signals
1774
1775     // Methods override:
1776     //    * other methods of the same name
1777
1778     // Properties override:
1779     //    * other elements of the same name
1780
1781     bool overloadError = false;
1782     QString overloadName;
1783
1784 #if 0
1785     for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1786          !overloadError && iter != raw->stringCache.end();
1787          ++iter) {
1788
1789         QQmlPropertyData *d = *iter;
1790         if (raw->isAllowedInRevision(d))
1791             continue; // Not excluded - no problems
1792
1793         // check that a regular "name" overload isn't happening
1794         QQmlPropertyData *current = d;
1795         while (!overloadError && current) {
1796             current = d->overrideData(current);
1797             if (current && raw->isAllowedInRevision(current))
1798                 overloadError = true;
1799         }
1800     }
1801 #endif
1802
1803     if (overloadError) {
1804         if (hasCopied) raw->release();
1805
1806         error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1Char(' ') + QString::number(type->majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\".  This is an error in the type's implementation."));
1807         return 0;
1808     }
1809
1810     if (!hasCopied) raw->addref();
1811     typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1812
1813     if (minorVersion != maxMinorVersion) {
1814         raw->addref();
1815         typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1816     }
1817
1818     return raw;
1819 }
1820
1821 QQmlMetaType::ModuleApiInstance *
1822 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1823 {
1824     Locker locker(this);
1825
1826     QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1827     if (!a) {
1828         a = new QQmlMetaType::ModuleApiInstance;
1829         a->scriptCallback = module.script;
1830         a->qobjectCallback = module.qobject;
1831         a->instanceMetaObject = module.instanceMetaObject;
1832         moduleApiInstances.insert(module, a);
1833     }
1834
1835     return a;
1836 }
1837
1838 bool QQmlEnginePrivate::isQObject(int t)
1839 {
1840     Locker locker(this);
1841     return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1842 }
1843
1844 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1845 {
1846     Locker locker(this);
1847     int t = v.userType();
1848     if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1849         if (ok) *ok = true;
1850         return *(QObject **)(v.constData());
1851     } else {
1852         return QQmlMetaType::toQObject(v, ok);
1853     }
1854 }
1855
1856 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1857 {
1858     Locker locker(this);
1859     if (m_compositeTypes.contains(t))
1860         return QQmlMetaType::Object;
1861     else if (m_qmlLists.contains(t))
1862         return QQmlMetaType::List;
1863     else
1864         return QQmlMetaType::typeCategory(t);
1865 }
1866
1867 bool QQmlEnginePrivate::isList(int t) const
1868 {
1869     Locker locker(this);
1870     return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1871 }
1872
1873 int QQmlEnginePrivate::listType(int t) const
1874 {
1875     Locker locker(this);
1876     QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1877     if (iter != m_qmlLists.end())
1878         return *iter;
1879     else
1880         return QQmlMetaType::listType(t);
1881 }
1882
1883 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1884 {
1885     Locker locker(this);
1886     QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1887     if (iter != m_compositeTypes.end()) {
1888         return QQmlMetaObject((*iter)->rootPropertyCache);
1889     } else {
1890         QQmlType *type = QQmlMetaType::qmlType(t);
1891         return QQmlMetaObject(type?type->baseMetaObject():0);
1892     }
1893 }
1894
1895 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1896 {
1897     Locker locker(this);
1898     QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1899     if (iter != m_compositeTypes.end()) {
1900         return QQmlMetaObject((*iter)->rootPropertyCache);
1901     } else {
1902         QQmlType *type = QQmlMetaType::qmlType(t);
1903         return QQmlMetaObject(type?type->metaObject():0);
1904     }
1905 }
1906
1907 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1908 {
1909     Locker locker(this);
1910     QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1911     if (iter != m_compositeTypes.end()) {
1912         return (*iter)->rootPropertyCache;
1913     } else {
1914         QQmlType *type = QQmlMetaType::qmlType(t);
1915         locker.unlock();
1916         return type?cache(type->metaObject()):0;
1917     }
1918 }
1919
1920 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1921 {
1922     Locker locker(this);
1923     QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1924     if (iter != m_compositeTypes.end()) {
1925         return (*iter)->rootPropertyCache;
1926     } else {
1927         QQmlType *type = QQmlMetaType::qmlType(t);
1928         locker.unlock();
1929         return type?cache(type->baseMetaObject()):0;
1930     }
1931 }
1932
1933 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1934 {
1935     QByteArray name = data->rootPropertyCache->className();
1936
1937     QByteArray ptr = name + '*';
1938     QByteArray lst = "QQmlListProperty<" + name + '>';
1939
1940     int ptr_type = QMetaType::registerNormalizedType(ptr,
1941                                                      qMetaTypeDeleteHelper<QObject*>,
1942                                                      qMetaTypeCreateHelper<QObject*>,
1943                                                      qMetaTypeDestructHelper<QObject*>,
1944                                                      qMetaTypeConstructHelper<QObject*>,
1945                                                      sizeof(QObject*),
1946                                                      static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1947                                                      0);
1948     int lst_type = QMetaType::registerNormalizedType(lst,
1949                                                      qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1950                                                      qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1951                                                      qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1952                                                      qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1953                                                      sizeof(QQmlListProperty<QObject>),
1954                                                      static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
1955                                                      static_cast<QMetaObject*>(0));
1956
1957     data->metaTypeId = ptr_type;
1958     data->listMetaTypeId = lst_type;
1959     data->isRegisteredWithEngine = true;
1960
1961     Locker locker(this);
1962     m_qmlLists.insert(lst_type, ptr_type);
1963     // The QQmlCompiledData is not referenced here, but it is removed from this
1964     // hash in the QQmlCompiledData destructor
1965     m_compositeTypes.insert(ptr_type, data);
1966 }
1967
1968 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
1969 {
1970     int ptr_type = data->metaTypeId;
1971     int lst_type = data->listMetaTypeId;
1972
1973     Locker locker(this);
1974     m_qmlLists.remove(lst_type);
1975     m_compositeTypes.remove(ptr_type);
1976 }
1977
1978 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
1979 {
1980     return typeLoader.isTypeLoaded(url);
1981 }
1982
1983 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
1984 {
1985     return typeLoader.isScriptLoaded(url);
1986 }
1987
1988 bool QQml_isFileCaseCorrect(const QString &fileName)
1989 {
1990 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1991     QFileInfo info(fileName);
1992     const QString absolute = info.absoluteFilePath();
1993
1994 #if defined(Q_OS_MAC)
1995     const QString canonical = info.canonicalFilePath();
1996 #elif defined(Q_OS_WIN)
1997     wchar_t buffer[1024];
1998
1999     DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2000     if (rv == 0 || rv >= 1024) return true;
2001     rv = ::GetLongPathName(buffer, buffer, 1024);
2002     if (rv == 0 || rv >= 1024) return true;
2003
2004     const QString canonical = QString::fromWCharArray(buffer);
2005 #endif
2006
2007     const int absoluteLength = absolute.length();
2008     const int canonicalLength = canonical.length();
2009
2010     const int length = qMin(absoluteLength, canonicalLength);
2011     for (int ii = 0; ii < length; ++ii) {
2012         const QChar &a = absolute.at(absoluteLength - 1 - ii);
2013         const QChar &c = canonical.at(canonicalLength - 1 - ii);
2014
2015         if (a.toLower() != c.toLower())
2016             return true;
2017         if (a != c)
2018             return false;
2019     }
2020 #else
2021     Q_UNUSED(fileName)
2022 #endif
2023     return true;
2024 }
2025
2026 /*!
2027     \fn QQmlEngine *qmlEngine(const QObject *object)
2028     \relates QQmlEngine
2029
2030     Returns the QQmlEngine associated with \a object, if any.  This is equivalent to
2031     QQmlEngine::contextForObject(object)->engine(), but more efficient.
2032 */
2033
2034 /*!
2035     \fn QQmlContext *qmlContext(const QObject *object)
2036     \relates QQmlEngine
2037
2038     Returns the QQmlContext associated with \a object, if any.  This is equivalent to
2039     QQmlEngine::contextForObject(object).
2040 */
2041
2042 QT_END_NAMESPACE