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