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