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