Refactor singleton type registration code
[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   \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     \inmodule QtQml
201
202     Image providers must be registered with the QML engine.  The only information the QML
203     engine knows about image providers is the type of image data they provide.  To use an
204     image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
205     to a QQuickImageProvider pointer.
206
207     \sa QQuickImageProvider, QQuickTextureFactory
208 */
209
210 /*!
211     \enum QQmlImageProviderBase::ImageType
212
213     Defines the type of image supported by this image provider.
214
215     \value Image The Image Provider provides QImage images.
216         The QQuickImageProvider::requestImage() method will be called for all image requests.
217     \value Pixmap The Image Provider provides QPixmap images.
218         The QQuickImageProvider::requestPixmap() method will be called for all image requests.
219     \value Texture The Image Provider provides QSGTextureProvider based images.
220         The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
221 */
222
223 /*!
224     \enum QQmlImageProviderBase::Flag
225
226     Defines specific requirements or features of this image provider.
227
228     \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
229         run in a separate thread, which allows the provider to spend as much time as needed
230         on producing the image without blocking the main thread.
231 */
232
233 /*! \internal */
234 QQmlImageProviderBase::QQmlImageProviderBase()
235 {
236 }
237
238 /*! \internal */
239 QQmlImageProviderBase::~QQmlImageProviderBase()
240 {
241 }
242
243
244 /*!
245 \qmltype Qt
246     \instantiates QQmlEnginePrivate
247   \ingroup qml-utility-elements
248 \brief The QML global Qt object provides useful enums and functions from Qt.
249
250 \keyword QmlGlobalQtObject
251
252 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
253
254 The \c Qt object is a global object with utility functions, properties and enums.
255
256 It is not instantiable; to use it, call the members of the global \c Qt object directly.
257 For example:
258
259 \qml
260 import QtQuick 2.0
261
262 Text {
263     color: Qt.rgba(1, 0, 0, 1)
264     text: Qt.md5("hello, world")
265 }
266 \endqml
267
268
269 \section1 Enums
270
271 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
272 the \l Qt::LeftButton and \l Qt::RightButton enumeration values as \c Qt.LeftButton and \c Qt.RightButton.
273
274
275 \section1 Types
276
277 The Qt object also contains helper functions for creating objects of specific
278 data types. This is primarily useful when setting the properties of an item
279 when the property has one of the following types:
280 \list
281 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
282 \li \c point - use \l{Qt::point()}{Qt.point()}
283 \li \c size - use \l{Qt::size()}{Qt.size()}
284 \endlist
285
286 If the QtQuick module has been imported, the following helper functions for
287 creating objects of specific data types are also available for clients to use:
288 \list
289 \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()}
290 \li \c font - use \l{Qt::font()}{Qt.font()}
291 \li \c vector2d - use \l{Qt::vector2d()}{Qt.vector2d()}
292 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
293 \li \c vector4d - use \l{Qt::vector4d()}{Qt.vector4d()}
294 \li \c quaternion - use \l{Qt::quaternion()}{Qt.quaternion()}
295 \li \c matrix4x4 - use \l{Qt::matrix4x4()}{Qt.matrix4x4()}
296 \endlist
297
298 There are also string based constructors for these types. See \l{qtqml-typesystem-basictypes.html}{QML Basic Types} for more information.
299
300 \section1 Date/Time Formatters
301
302 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
303
304 \list
305     \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
306     \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
307     \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
308 \endlist
309
310 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
311
312
313 \section1 Dynamic Object Creation
314 The following functions on the global object allow you to dynamically create QML
315 items from files or strings. See \l{Dynamic QML Object Creation from JavaScript} for an overview
316 of their use.
317
318 \list
319     \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
320     \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
321 \endlist
322
323
324 \section1 Other Functions
325
326 The following functions are also on the Qt object.
327
328 \list
329     \li \l{Qt::quit()}{Qt.quit()}
330     \li \l{Qt::md5()}{Qt.md5(string)}
331     \li \l{Qt::btoa()}{string Qt.btoa(string)}
332     \li \l{Qt::atob()}{string Qt.atob(string)}
333     \li \l{Qt::binding()}{object Qt.binding(function)}
334     \li \l{Qt::locale()}{object Qt.locale()}
335     \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
336     \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
337     \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
338 \endlist
339 */
340
341 /*!
342     \qmlproperty object Qt::application
343     \since QtQuick 1.1
344
345     The \c application object provides access to global application state
346     properties shared by many QML components.
347
348     Its properties are:
349
350     \table
351     \row
352     \li \c application.active
353     \li
354     This read-only property indicates whether the application is the top-most and focused
355     application, and the user is able to interact with the application. The property
356     is false when the application is in the background, the device keylock or screen
357     saver is active, the screen backlight is turned off, or the global system dialog
358     is being displayed on top of the application. It can be used for stopping and
359     pausing animations, timers and active processing of data in order to save device
360     battery power and free device memory and processor load when the application is not
361     active.
362
363     \row
364     \li \c application.layoutDirection
365     \li
366     This read-only property can be used to query the default layout direction of the
367     application. On system start-up, the default layout direction depends on the
368     application's language. The property has a value of \c Qt.RightToLeft in locales
369     where text and graphic elements are read from right to left, and \c Qt.LeftToRight
370     where the reading direction flows from left to right. You can bind to this
371     property to customize your application layouts to support both layout directions.
372
373     Possible values are:
374
375     \list
376     \li Qt.LeftToRight - Text and graphics elements should be positioned
377                         from left to right.
378     \li Qt.RightToLeft - Text and graphics elements should be positioned
379                         from right to left.
380     \endlist
381
382     \endtable
383
384     The following example uses the \c application object to indicate
385     whether the application is currently active:
386
387     \snippet qml/application.qml document
388 */
389
390 /*!
391     \qmlproperty object Qt::inputMethod
392     \since QtQuick 2.0
393
394     The \c inputMethod object allows access to application's QInputMethod object
395     and all its properties and slots. See the QInputMethod documentation for
396     further details.
397 */
398
399
400 /*!
401 \qmlmethod object Qt::include(string url, jsobject callback)
402
403 Includes another JavaScript file. This method can only be used from within JavaScript files,
404 and not regular QML files.
405
406 This imports all functions from \a url into the current script's namespace.
407
408 Qt.include() returns an object that describes the status of the operation.  The object has
409 a single property, \c {status}, that is set to one of the following values:
410
411 \table
412 \header \li Symbol \li Value \li Description
413 \row \li result.OK \li 0 \li The include completed successfully.
414 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
415 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
416 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
417 An additional \c exception property will be set in this case.
418 \endtable
419
420 The \c status property will be updated as the operation progresses.
421
422 If provided, \a callback is invoked when the operation completes.  The callback is passed
423 the same object as is returned from the Qt.include() call.
424 */
425 // Qt.include() is implemented in qv8include.cpp
426
427
428 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
429 : propertyCapture(0), rootContext(0), isDebugging(false),
430   outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
431   cleanup(0), erroredBindings(0), inProgressCreations(0),
432   workerScriptEngine(0), activeVME(0),
433   networkAccessManager(0), networkAccessManagerFactory(0),
434   scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
435   incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
436 {
437 }
438
439 QQmlEnginePrivate::~QQmlEnginePrivate()
440 {
441     if (inProgressCreations)
442         qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
443
444     while (cleanup) {
445         QQmlCleanup *c = cleanup;
446         cleanup = c->next;
447         if (cleanup) cleanup->prev = &cleanup;
448         c->next = 0;
449         c->prev = 0;
450         c->clear();
451     }
452
453     doDeleteInEngineThread();
454
455     if (incubationController) incubationController->d = 0;
456     incubationController = 0;
457
458     delete rootContext;
459     rootContext = 0;
460
461     for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
462         (*iter)->release();
463     for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
464         (*iter)->release();
465     for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
466         iter.value()->isRegisteredWithEngine = false;
467 }
468
469 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
470 {
471     QObjectPrivate *p = QObjectPrivate::get(o);
472     if (p->declarativeData) {
473         QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
474         if (d->ownContext && d->context) {
475             d->context->destroy();
476             d->context = 0;
477         }
478
479         // Mark this object as in the process of deletion to
480         // prevent it resolving in bindings
481         QQmlData::markAsDeleted(o);
482
483         // Disconnect the notifiers now - during object destruction this would be too late, since
484         // the disconnect call wouldn't be able to call disconnectNotify(), as it isn't possible to
485         // get the metaobject anymore.
486         d->disconnectNotifiers();
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, Singleton Types etc. that
739     // may be required to handle the destruction signal.
740     QQmlContextData::get(rootContext())->emitDestruction();
741
742     // clean up all singleton type instances which we own.
743     // we do this here and not in the private dtor since otherwise a crash can
744     // occur (if we are the QObject parent of the QObject singleton instance)
745     // XXX TODO: performance -- store list of singleton types separately?
746     QList<QQmlType*> singletonTypes = QQmlMetaType::qmlSingletonTypes();
747     foreach (QQmlType *currType, singletonTypes)
748         currType->singletonInstanceInfo()->destroy(this);
749
750     if (d->incubationController)
751         d->incubationController->d = 0;
752 }
753
754 /*! \fn void QQmlEngine::quit()
755     This signal is emitted when the QML loaded by the engine would like to quit.
756  */
757
758 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
759     This signal is emitted when \a warnings messages are generated by QML.
760  */
761
762 /*!
763   Clears the engine's internal component cache.
764
765   This function causes the property metadata of all components previously
766   loaded by the engine to be destroyed.  All previously loaded components and
767   the property bindings for all extant objects created from those components will
768   cease to function.
769
770   This function returns the engine to a state where it does not contain any loaded
771   component data.  This may be useful in order to reload a smaller subset of the
772   previous component set, or to load a new version of a previously loaded component.
773
774   Once the component cache has been cleared, components must be loaded before
775   any new objects can be created.
776
777   \sa trimComponentCache()
778  */
779 void QQmlEngine::clearComponentCache()
780 {
781     Q_D(QQmlEngine);
782     d->typeLoader.clearCache();
783 }
784
785 /*!
786   Trims the engine's internal component cache.
787
788   This function causes the property metadata of any loaded components which are
789   not currently in use to be destroyed.
790
791   A component is considered to be in use if there are any extant instances of
792   the component itself, any instances of other components that use the component,
793   or any objects instantiated by any of those components.
794
795   \sa clearComponentCache()
796  */
797 void QQmlEngine::trimComponentCache()
798 {
799     Q_D(QQmlEngine);
800     d->typeLoader.trimCache();
801 }
802
803 /*!
804   Returns the engine's root context.
805
806   The root context is automatically created by the QQmlEngine.
807   Data that should be available to all QML component instances
808   instantiated by the engine should be put in the root context.
809
810   Additional data that should only be available to a subset of
811   component instances should be added to sub-contexts parented to the
812   root context.
813 */
814 QQmlContext *QQmlEngine::rootContext() const
815 {
816     Q_D(const QQmlEngine);
817     return d->rootContext;
818 }
819
820 /*!
821   Sets the \a factory to use for creating QNetworkAccessManager(s).
822
823   QNetworkAccessManager is used for all network access by QML.  By
824   implementing a factory it is possible to create custom
825   QNetworkAccessManager with specialized caching, proxy and cookie
826   support.
827
828   The factory must be set before executing the engine.
829 */
830 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
831 {
832     Q_D(QQmlEngine);
833     QMutexLocker locker(&d->mutex);
834     d->networkAccessManagerFactory = factory;
835 }
836
837 /*!
838   Returns the current QQmlNetworkAccessManagerFactory.
839
840   \sa setNetworkAccessManagerFactory()
841 */
842 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
843 {
844     Q_D(const QQmlEngine);
845     return d->networkAccessManagerFactory;
846 }
847
848 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
849 {
850     if (activeVME) {
851         activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
852     } else {
853         void *args[] = { 0 };
854         QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
855     }
856 }
857
858 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
859 {
860     QMutexLocker locker(&mutex);
861     QNetworkAccessManager *nam;
862     if (networkAccessManagerFactory) {
863         nam = networkAccessManagerFactory->create(parent);
864     } else {
865         nam = new QNetworkAccessManager(parent);
866     }
867
868     return nam;
869 }
870
871 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
872 {
873     Q_Q(const QQmlEngine);
874     if (!networkAccessManager)
875         networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
876     return networkAccessManager;
877 }
878
879 /*!
880   Returns a common QNetworkAccessManager which can be used by any QML
881   type instantiated by this engine.
882
883   If a QQmlNetworkAccessManagerFactory has been set and a
884   QNetworkAccessManager has not yet been created, the
885   QQmlNetworkAccessManagerFactory will be used to create the
886   QNetworkAccessManager; otherwise the returned QNetworkAccessManager
887   will have no proxy or cache set.
888
889   \sa setNetworkAccessManagerFactory()
890 */
891 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
892 {
893     Q_D(const QQmlEngine);
894     return d->getNetworkAccessManager();
895 }
896
897 /*!
898
899   Sets the \a provider to use for images requested via the \e
900   image: url scheme, with host \a providerId. The QQmlEngine
901   takes ownership of \a provider.
902
903   Image providers enable support for pixmap and threaded image
904   requests. See the QQuickImageProvider documentation for details on
905   implementing and using image providers.
906
907   All required image providers should be added to the engine before any
908   QML sources files are loaded.
909
910   \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
911 */
912 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
913 {
914     Q_D(QQmlEngine);
915     QMutexLocker locker(&d->mutex);
916     d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
917 }
918
919 /*!
920   Returns the image provider set for \a providerId.
921
922   Returns the provider if it was found; otherwise returns 0.
923
924   \sa QQuickImageProvider
925 */
926 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
927 {
928     Q_D(const QQmlEngine);
929     QMutexLocker locker(&d->mutex);
930     return d->imageProviders.value(providerId).data();
931 }
932
933 /*!
934   Removes the image provider for \a providerId.
935
936   \sa addImageProvider(), QQuickImageProvider
937 */
938 void QQmlEngine::removeImageProvider(const QString &providerId)
939 {
940     Q_D(QQmlEngine);
941     QMutexLocker locker(&d->mutex);
942     d->imageProviders.take(providerId);
943 }
944
945 /*!
946   Return the base URL for this engine.  The base URL is only used to
947   resolve components when a relative URL is passed to the
948   QQmlComponent constructor.
949
950   If a base URL has not been explicitly set, this method returns the
951   application's current working directory.
952
953   \sa setBaseUrl()
954 */
955 QUrl QQmlEngine::baseUrl() const
956 {
957     Q_D(const QQmlEngine);
958     if (d->baseUrl.isEmpty()) {
959         return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
960     } else {
961         return d->baseUrl;
962     }
963 }
964
965 /*!
966   Set the  base URL for this engine to \a url.
967
968   \sa baseUrl()
969 */
970 void QQmlEngine::setBaseUrl(const QUrl &url)
971 {
972     Q_D(QQmlEngine);
973     d->baseUrl = url;
974 }
975
976 /*!
977   Returns true if warning messages will be output to stderr in addition
978   to being emitted by the warnings() signal, otherwise false.
979
980   The default value is true.
981 */
982 bool QQmlEngine::outputWarningsToStandardError() const
983 {
984     Q_D(const QQmlEngine);
985     return d->outputWarningsToStdErr;
986 }
987
988 /*!
989   Set whether warning messages will be output to stderr to \a enabled.
990
991   If \a enabled is true, any warning messages generated by QML will be
992   output to stderr and emitted by the warnings() signal.  If \a enabled
993   is false, on the warnings() signal will be emitted.  This allows
994   applications to handle warning output themselves.
995
996   The default value is true.
997 */
998 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
999 {
1000     Q_D(QQmlEngine);
1001     d->outputWarningsToStdErr = enabled;
1002 }
1003
1004 /*!
1005   Returns the QQmlContext for the \a object, or 0 if no
1006   context has been set.
1007
1008   When the QQmlEngine instantiates a QObject, the context is
1009   set automatically.
1010   */
1011 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
1012 {
1013     if(!object)
1014         return 0;
1015
1016     QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
1017
1018     QQmlData *data =
1019         static_cast<QQmlData *>(priv->declarativeData);
1020
1021     if (!data)
1022         return 0;
1023     else if (data->outerContext)
1024         return data->outerContext->asQQmlContext();
1025     else
1026         return 0;
1027 }
1028
1029 /*!
1030   Sets the QQmlContext for the \a object to \a context.
1031   If the \a object already has a context, a warning is
1032   output, but the context is not changed.
1033
1034   When the QQmlEngine instantiates a QObject, the context is
1035   set automatically.
1036  */
1037 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1038 {
1039     if (!object || !context)
1040         return;
1041
1042     QQmlData *data = QQmlData::get(object, true);
1043     if (data->context) {
1044         qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1045         return;
1046     }
1047
1048     QQmlContextData *contextData = QQmlContextData::get(context);
1049     contextData->addObject(object);
1050 }
1051
1052 /*!
1053   \enum QQmlEngine::ObjectOwnership
1054
1055   Ownership controls whether or not QML automatically destroys the
1056   QObject when the object is garbage collected by the JavaScript
1057   engine.  The two ownership options are:
1058
1059   \value CppOwnership The object is owned by C++ code, and will
1060   never be deleted by QML.  The JavaScript destroy() method cannot be
1061   used on objects with CppOwnership.  This option is similar to
1062   QScriptEngine::QtOwnership.
1063
1064   \value JavaScriptOwnership The object is owned by JavaScript.
1065   When the object is returned to QML as the return value of a method
1066   call or property access, QML will track it, and delete the object
1067   if there are no remaining JavaScript references to it and it has no
1068   QObject::parent().  An object tracked by one QQmlEngine
1069   will be deleted during that QQmlEngine's destructor, and thus
1070   JavaScript references between objects with JavaScriptOwnership from
1071   two different engines will not be valid after the deletion of one of
1072   those engines.  This option is similar to QScriptEngine::ScriptOwnership.
1073
1074   Generally an application doesn't need to set an object's ownership
1075   explicitly.  QML uses a heuristic to set the default object
1076   ownership.  By default, an object that is created by QML has
1077   JavaScriptOwnership.  The exception to this are the root objects
1078   created by calling QQmlComponent::create() or
1079   QQmlComponent::beginCreate() which have CppOwnership by
1080   default.  The ownership of these root-level objects is considered to
1081   have been transferred to the C++ caller.
1082
1083   Objects not-created by QML have CppOwnership by default.  The
1084   exception to this is objects returned from a C++ method call.  The
1085   ownership of these objects is passed to JavaScript.
1086
1087   Calling setObjectOwnership() overrides the default ownership
1088   heuristic used by QML.
1089 */
1090
1091 /*!
1092   Sets the \a ownership of \a object.
1093 */
1094 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1095 {
1096     if (!object)
1097         return;
1098
1099     QQmlData *ddata = QQmlData::get(object, true);
1100     if (!ddata)
1101         return;
1102
1103     ddata->indestructible = (ownership == CppOwnership)?true:false;
1104     ddata->explicitIndestructibleSet = true;
1105 }
1106
1107 /*!
1108   Returns the ownership of \a object.
1109 */
1110 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1111 {
1112     if (!object)
1113         return CppOwnership;
1114
1115     QQmlData *ddata = QQmlData::get(object, false);
1116     if (!ddata)
1117         return CppOwnership;
1118     else
1119         return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1120 }
1121
1122 bool QQmlEngine::event(QEvent *e)
1123 {
1124     Q_D(QQmlEngine);
1125     if (e->type() == QEvent::User)
1126         d->doDeleteInEngineThread();
1127
1128     return QJSEngine::event(e);
1129 }
1130
1131 void QQmlEnginePrivate::doDeleteInEngineThread()
1132 {
1133     QFieldList<Deletable, &Deletable::next> list;
1134     mutex.lock();
1135     list.copyAndClear(toDeleteInEngineThread);
1136     mutex.unlock();
1137
1138     while (Deletable *d = list.takeFirst())
1139         delete d;
1140 }
1141
1142 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1143 {
1144     QQmlData *data = QQmlData::get(object);
1145
1146     if (data && data->compiledData && data->deferredIdx) {
1147         QQmlObjectCreatingProfiler prof;
1148         if (prof.enabled) {
1149             QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1150             prof.setTypeName(type ? type->qmlTypeName()
1151                                   : QString::fromUtf8(object->metaObject()->className()));
1152             if (data->outerContext)
1153                 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1154         }
1155         QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1156
1157         QQmlComponentPrivate::ConstructionState state;
1158         QQmlComponentPrivate::beginDeferred(ep, object, &state);
1159
1160         // Release the reference for the deferral action (we still have one from construction)
1161         data->compiledData->release();
1162         data->compiledData = 0;
1163
1164         QQmlComponentPrivate::complete(ep, &state);
1165     }
1166 }
1167
1168 QQmlContext *qmlContext(const QObject *obj)
1169 {
1170     return QQmlEngine::contextForObject(obj);
1171 }
1172
1173 QQmlEngine *qmlEngine(const QObject *obj)
1174 {
1175     QQmlData *data = QQmlData::get(obj, false);
1176     if (!data || !data->context)
1177         return 0;
1178     return data->context->engine;
1179 }
1180
1181 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1182 {
1183     QQmlData *data = QQmlData::get(object);
1184     if (!data)
1185         return 0; // Attached properties are only on objects created by QML
1186
1187     QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1188     if (rv || !create)
1189         return rv;
1190
1191     QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1192     if (!pf)
1193         return 0;
1194
1195     rv = pf(const_cast<QObject *>(object));
1196
1197     if (rv)
1198         data->attachedProperties()->insert(id, rv);
1199
1200     return rv;
1201 }
1202
1203 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1204                                      const QMetaObject *attachedMetaObject, bool create)
1205 {
1206     if (*idCache == -1)
1207         *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1208
1209     if (*idCache == -1 || !object)
1210         return 0;
1211
1212     return qmlAttachedPropertiesObjectById(*idCache, object, create);
1213 }
1214
1215 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1216 {
1217 #ifndef QQML_NO_DEBUG_PROTOCOL
1218     if (!QQmlEnginePrivate::qml_debugging_enabled
1219             && printWarning) {
1220         qDebug("QML debugging is enabled. Only use this in a safe environment.");
1221     }
1222     QQmlEnginePrivate::qml_debugging_enabled = true;
1223 #endif
1224 }
1225
1226
1227 class QQmlDataExtended {
1228 public:
1229     QQmlDataExtended();
1230     ~QQmlDataExtended();
1231
1232     QHash<int, QObject *> attachedProperties;
1233 };
1234
1235 QQmlDataExtended::QQmlDataExtended()
1236 {
1237 }
1238
1239 QQmlDataExtended::~QQmlDataExtended()
1240 {
1241 }
1242
1243 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1244 {
1245     if (endpoint->next)
1246         layout(endpoint->next);
1247
1248     int index = endpoint->sourceSignal;
1249     index = qMin(index, 0xFFFF - 1);
1250
1251     endpoint->next = notifies[index];
1252     if (endpoint->next) endpoint->next->prev = &endpoint->next;
1253     endpoint->prev = &notifies[index];
1254     notifies[index] = endpoint;
1255 }
1256
1257 void QQmlData::NotifyList::layout()
1258 {
1259     Q_ASSERT(maximumTodoIndex >= notifiesSize);
1260
1261     if (todo) {
1262         QQmlNotifierEndpoint **old = notifies;
1263         const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1264         notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1265         const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1266                                sizeof(QQmlNotifierEndpoint*);
1267         memset(notifies + notifiesSize, 0, memsetSize);
1268
1269         if (notifies != old) {
1270             for (int ii = 0; ii < notifiesSize; ++ii)
1271                 if (notifies[ii])
1272                     notifies[ii]->prev = &notifies[ii];
1273         }
1274
1275         notifiesSize = maximumTodoIndex + 1;
1276
1277         layout(todo);
1278     }
1279
1280     maximumTodoIndex = 0;
1281     todo = 0;
1282 }
1283
1284 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1285 {
1286     if (!notifyList) {
1287         notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1288         notifyList->connectionMask = 0;
1289         notifyList->maximumTodoIndex = 0;
1290         notifyList->notifiesSize = 0;
1291         notifyList->todo = 0;
1292         notifyList->notifies = 0;
1293     }
1294
1295     Q_ASSERT(!endpoint->isConnected());
1296
1297     index = qMin(index, 0xFFFF - 1);
1298     notifyList->connectionMask |= (1ULL << quint64(index % 64));
1299
1300     if (index < notifyList->notifiesSize) {
1301
1302         endpoint->next = notifyList->notifies[index];
1303         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1304         endpoint->prev = &notifyList->notifies[index];
1305         notifyList->notifies[index] = endpoint;
1306
1307     } else {
1308         notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1309
1310         endpoint->next = notifyList->todo;
1311         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1312         endpoint->prev = &notifyList->todo;
1313         notifyList->todo = endpoint;
1314     }
1315 }
1316
1317 /*
1318     index MUST in the range returned by QObjectPrivate::signalIndex()
1319     This is different than the index returned by QMetaMethod::methodIndex()
1320 */
1321 bool QQmlData::signalHasEndpoint(int index)
1322 {
1323     return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1324 }
1325
1326 void QQmlData::disconnectNotifiers()
1327 {
1328     if (notifyList) {
1329         while (notifyList->todo)
1330             notifyList->todo->disconnect();
1331         for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1332             while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1333                 ep->disconnect();
1334         }
1335         free(notifyList->notifies);
1336         free(notifyList);
1337         notifyList = 0;
1338     }
1339 }
1340
1341 QHash<int, QObject *> *QQmlData::attachedProperties() const
1342 {
1343     if (!extendedData) extendedData = new QQmlDataExtended;
1344     return &extendedData->attachedProperties;
1345 }
1346
1347 void QQmlData::destroyed(QObject *object)
1348 {
1349     if (nextContextObject)
1350         nextContextObject->prevContextObject = prevContextObject;
1351     if (prevContextObject)
1352         *prevContextObject = nextContextObject;
1353
1354     QQmlAbstractBinding *binding = bindings;
1355     while (binding) {
1356         QQmlAbstractBinding *next = binding->nextBinding();
1357         binding->setAddedToObject(false);
1358         binding->setNextBinding(0);
1359         binding->destroy();
1360         binding = next;
1361     }
1362
1363     if (compiledData) {
1364         compiledData->release();
1365         compiledData = 0;
1366     }
1367
1368     QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1369     while (signalHandler) {
1370         if (signalHandler->isEvaluating()) {
1371             // The object is being deleted during signal handler evaluation.
1372             // This will cause a crash due to invalid memory access when the
1373             // evaluation has completed.
1374             // Abort with a friendly message instead.
1375             QString locationString;
1376             QQmlBoundSignalExpression *expr = signalHandler->expression();
1377             if (expr) {
1378                 QString fileName = expr->sourceFile();
1379                 if (fileName.isEmpty())
1380                     fileName = QStringLiteral("<Unknown File>");
1381                 locationString.append(fileName);
1382                 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1383                 QString source = expr->expression();
1384                 if (source.size() > 100) {
1385                     source.truncate(96);
1386                     source.append(QStringLiteral(" ..."));
1387                 }
1388                 locationString.append(source);
1389             } else {
1390                 locationString = QStringLiteral("<Unknown Location>");
1391             }
1392             qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1393                    "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1394                    "instead), or the application is running a nested event loop.\n"
1395                    "This behavior is NOT supported!\n"
1396                    "%s", object, qPrintable(locationString));
1397         }
1398
1399         QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1400         signalHandler->m_prevSignal = 0;
1401         signalHandler->m_nextSignal = 0;
1402         delete signalHandler;
1403         signalHandler = next;
1404     }
1405
1406     if (bindingBits)
1407         free(bindingBits);
1408
1409     if (propertyCache)
1410         propertyCache->release();
1411
1412     if (ownContext && context)
1413         context->destroy();
1414
1415     while (guards) {
1416         QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1417         *guard = (QObject *)0;
1418         guard->objectDestroyed(object);
1419     }
1420
1421     disconnectNotifiers();
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
1614   The \a path may be a local filesystem directory, a
1615   \l {The Qt Resource System}{Qt Resource} path (\c {:/imports}), a
1616   \l {The Qt Resource System}{Qt Resource} url (\c {qrc:/imports}) or a URL.
1617
1618   The \a path will be converted into canonical form before it
1619   is added to the import path list.
1620
1621   The newly added \a path will be first in the importPathList().
1622
1623   \sa setImportPathList(), {QML Modules}
1624 */
1625 void QQmlEngine::addImportPath(const QString& path)
1626 {
1627     Q_D(QQmlEngine);
1628     d->importDatabase.addImportPath(path);
1629 }
1630
1631 /*!
1632   Returns the list of directories where the engine searches for
1633   installed modules in a URL-based directory structure.
1634
1635   For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1636   imports \c com.mycompany.Feature will cause the QQmlEngine to look
1637   in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1638   provided by that module. A \c qmldir file is required for defining the
1639   type version mapping and possibly QML extensions plugins.
1640
1641   By default, the list contains the directory of the application executable,
1642   paths specified in the \c QML_IMPORT_PATH environment variable,
1643   and the builtin \c ImportsPath from QLibraryInfo.
1644
1645   \sa addImportPath(), setImportPathList()
1646 */
1647 QStringList QQmlEngine::importPathList() const
1648 {
1649     Q_D(const QQmlEngine);
1650     return d->importDatabase.importPathList();
1651 }
1652
1653 /*!
1654   Sets \a paths as the list of directories where the engine searches for
1655   installed modules in a URL-based directory structure.
1656
1657   By default, the list contains the directory of the application executable,
1658   paths specified in the \c QML_IMPORT_PATH environment variable,
1659   and the builtin \c ImportsPath from QLibraryInfo.
1660
1661   \sa importPathList(), addImportPath()
1662   */
1663 void QQmlEngine::setImportPathList(const QStringList &paths)
1664 {
1665     Q_D(QQmlEngine);
1666     d->importDatabase.setImportPathList(paths);
1667 }
1668
1669
1670 /*!
1671   Adds \a path as a directory where the engine searches for
1672   native plugins for imported modules (referenced in the \c qmldir file).
1673
1674   By default, the list contains only \c .,  i.e. the engine searches
1675   in the directory of the \c qmldir file itself.
1676
1677   The newly added \a path will be first in the pluginPathList().
1678
1679   \sa setPluginPathList()
1680 */
1681 void QQmlEngine::addPluginPath(const QString& path)
1682 {
1683     Q_D(QQmlEngine);
1684     d->importDatabase.addPluginPath(path);
1685 }
1686
1687
1688 /*!
1689   Returns the list of directories where the engine searches for
1690   native plugins for imported modules (referenced in the \c qmldir file).
1691
1692   By default, the list contains only \c .,  i.e. the engine searches
1693   in the directory of the \c qmldir file itself.
1694
1695   \sa addPluginPath(), setPluginPathList()
1696 */
1697 QStringList QQmlEngine::pluginPathList() const
1698 {
1699     Q_D(const QQmlEngine);
1700     return d->importDatabase.pluginPathList();
1701 }
1702
1703 /*!
1704   Sets the list of directories where the engine searches for
1705   native plugins for imported modules (referenced in the \c qmldir file)
1706   to \a paths.
1707
1708   By default, the list contains only \c .,  i.e. the engine searches
1709   in the directory of the \c qmldir file itself.
1710
1711   \sa pluginPathList(), addPluginPath()
1712   */
1713 void QQmlEngine::setPluginPathList(const QStringList &paths)
1714 {
1715     Q_D(QQmlEngine);
1716     d->importDatabase.setPluginPathList(paths);
1717 }
1718
1719 /*!
1720   Imports the plugin named \a filePath with the \a uri provided.
1721   Returns true if the plugin was successfully imported; otherwise returns false.
1722
1723   On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1724
1725   The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1726 */
1727 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1728 {
1729     Q_D(QQmlEngine);
1730     return d->importDatabase.importPlugin(filePath, uri, QString(), errors);
1731 }
1732
1733 /*!
1734   \property QQmlEngine::offlineStoragePath
1735   \brief the directory for storing offline user data
1736
1737   Returns the directory where SQL and other offline
1738   storage is placed.
1739
1740   QQuickWebView and the SQL databases created with openDatabase()
1741   are stored here.
1742
1743   The default is QML/OfflineStorage in the platform-standard
1744   user application data directory.
1745
1746   Note that the path may not currently exist on the filesystem, so
1747   callers wanting to \e create new files at this location should create
1748   it first - see QDir::mkpath().
1749 */
1750 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1751 {
1752     Q_D(QQmlEngine);
1753     d->offlineStoragePath = dir;
1754 }
1755
1756 QString QQmlEngine::offlineStoragePath() const
1757 {
1758     Q_D(const QQmlEngine);
1759     return d->offlineStoragePath;
1760 }
1761
1762 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1763 {
1764     Q_Q(QQmlEngine);
1765
1766     if (!mo->superClass()) {
1767         QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1768         propertyCache.insert(mo, rv);
1769         return rv;
1770     } else {
1771         QQmlPropertyCache *super = cache(mo->superClass());
1772         QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1773         propertyCache.insert(mo, rv);
1774         return rv;
1775     }
1776 }
1777
1778 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1779                                                                   QQmlError &error)
1780 {
1781     QList<QQmlType *> types;
1782
1783     int maxMinorVersion = 0;
1784
1785     const QMetaObject *metaObject = type->metaObject();
1786
1787     while (metaObject) {
1788         QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1789                                                             type->majorVersion(), minorVersion);
1790         if (t) {
1791             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1792             types << t;
1793         } else {
1794             types << 0;
1795         }
1796
1797         metaObject = metaObject->superClass();
1798     }
1799
1800     if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1801         c->addref();
1802         typePropertyCache.insert(qMakePair(type, minorVersion), c);
1803         return c;
1804     }
1805
1806     QQmlPropertyCache *raw = cache(type->metaObject());
1807
1808     bool hasCopied = false;
1809
1810     for (int ii = 0; ii < types.count(); ++ii) {
1811         QQmlType *currentType = types.at(ii);
1812         if (!currentType)
1813             continue;
1814
1815         int rev = currentType->metaObjectRevision();
1816         int moIndex = types.count() - 1 - ii;
1817
1818         if (raw->allowedRevisionCache[moIndex] != rev) {
1819             if (!hasCopied) {
1820                 raw = raw->copy();
1821                 hasCopied = true;
1822             }
1823             raw->allowedRevisionCache[moIndex] = rev;
1824         }
1825     }
1826
1827     // Test revision compatibility - the basic rule is:
1828     //    * Anything that is excluded, cannot overload something that is not excluded *
1829
1830     // Signals override:
1831     //    * other signals and methods of the same name.
1832     //    * properties named on<Signal Name>
1833     //    * automatic <property name>Changed notify signals
1834
1835     // Methods override:
1836     //    * other methods of the same name
1837
1838     // Properties override:
1839     //    * other elements of the same name
1840
1841     bool overloadError = false;
1842     QString overloadName;
1843
1844 #if 0
1845     for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1846          !overloadError && iter != raw->stringCache.end();
1847          ++iter) {
1848
1849         QQmlPropertyData *d = *iter;
1850         if (raw->isAllowedInRevision(d))
1851             continue; // Not excluded - no problems
1852
1853         // check that a regular "name" overload isn't happening
1854         QQmlPropertyData *current = d;
1855         while (!overloadError && current) {
1856             current = d->overrideData(current);
1857             if (current && raw->isAllowedInRevision(current))
1858                 overloadError = true;
1859         }
1860     }
1861 #endif
1862
1863     if (overloadError) {
1864         if (hasCopied) raw->release();
1865
1866         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."));
1867         return 0;
1868     }
1869
1870     if (!hasCopied) raw->addref();
1871     typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1872
1873     if (minorVersion != maxMinorVersion) {
1874         raw->addref();
1875         typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1876     }
1877
1878     return raw;
1879 }
1880
1881 bool QQmlEnginePrivate::isQObject(int t)
1882 {
1883     Locker locker(this);
1884     return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1885 }
1886
1887 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1888 {
1889     Locker locker(this);
1890     int t = v.userType();
1891     if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1892         if (ok) *ok = true;
1893         return *(QObject **)(v.constData());
1894     } else {
1895         return QQmlMetaType::toQObject(v, ok);
1896     }
1897 }
1898
1899 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1900 {
1901     Locker locker(this);
1902     if (m_compositeTypes.contains(t))
1903         return QQmlMetaType::Object;
1904     else if (m_qmlLists.contains(t))
1905         return QQmlMetaType::List;
1906     else
1907         return QQmlMetaType::typeCategory(t);
1908 }
1909
1910 bool QQmlEnginePrivate::isList(int t) const
1911 {
1912     Locker locker(this);
1913     return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1914 }
1915
1916 int QQmlEnginePrivate::listType(int t) const
1917 {
1918     Locker locker(this);
1919     QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1920     if (iter != m_qmlLists.end())
1921         return *iter;
1922     else
1923         return QQmlMetaType::listType(t);
1924 }
1925
1926 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1927 {
1928     Locker locker(this);
1929     QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1930     if (iter != m_compositeTypes.end()) {
1931         return QQmlMetaObject((*iter)->rootPropertyCache);
1932     } else {
1933         QQmlType *type = QQmlMetaType::qmlType(t);
1934         return QQmlMetaObject(type?type->baseMetaObject():0);
1935     }
1936 }
1937
1938 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1939 {
1940     Locker locker(this);
1941     QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1942     if (iter != m_compositeTypes.end()) {
1943         return QQmlMetaObject((*iter)->rootPropertyCache);
1944     } else {
1945         QQmlType *type = QQmlMetaType::qmlType(t);
1946         return QQmlMetaObject(type?type->metaObject():0);
1947     }
1948 }
1949
1950 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1951 {
1952     Locker locker(this);
1953     QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1954     if (iter != m_compositeTypes.end()) {
1955         return (*iter)->rootPropertyCache;
1956     } else {
1957         QQmlType *type = QQmlMetaType::qmlType(t);
1958         locker.unlock();
1959         return type?cache(type->metaObject()):0;
1960     }
1961 }
1962
1963 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1964 {
1965     Locker locker(this);
1966     QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1967     if (iter != m_compositeTypes.end()) {
1968         return (*iter)->rootPropertyCache;
1969     } else {
1970         QQmlType *type = QQmlMetaType::qmlType(t);
1971         locker.unlock();
1972         return type?cache(type->baseMetaObject()):0;
1973     }
1974 }
1975
1976 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1977 {
1978     QByteArray name = data->rootPropertyCache->className();
1979
1980     QByteArray ptr = name + '*';
1981     QByteArray lst = "QQmlListProperty<" + name + '>';
1982
1983     int ptr_type = QMetaType::registerNormalizedType(ptr,
1984                                                      qMetaTypeDeleteHelper<QObject*>,
1985                                                      qMetaTypeCreateHelper<QObject*>,
1986                                                      qMetaTypeDestructHelper<QObject*>,
1987                                                      qMetaTypeConstructHelper<QObject*>,
1988                                                      sizeof(QObject*),
1989                                                      static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1990                                                      0);
1991     int lst_type = QMetaType::registerNormalizedType(lst,
1992                                                      qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1993                                                      qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1994                                                      qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1995                                                      qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1996                                                      sizeof(QQmlListProperty<QObject>),
1997                                                      static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
1998                                                      static_cast<QMetaObject*>(0));
1999
2000     data->metaTypeId = ptr_type;
2001     data->listMetaTypeId = lst_type;
2002     data->isRegisteredWithEngine = true;
2003
2004     Locker locker(this);
2005     m_qmlLists.insert(lst_type, ptr_type);
2006     // The QQmlCompiledData is not referenced here, but it is removed from this
2007     // hash in the QQmlCompiledData destructor
2008     m_compositeTypes.insert(ptr_type, data);
2009 }
2010
2011 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
2012 {
2013     int ptr_type = data->metaTypeId;
2014     int lst_type = data->listMetaTypeId;
2015
2016     Locker locker(this);
2017     m_qmlLists.remove(lst_type);
2018     m_compositeTypes.remove(ptr_type);
2019 }
2020
2021 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2022 {
2023     return typeLoader.isTypeLoaded(url);
2024 }
2025
2026 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2027 {
2028     return typeLoader.isScriptLoaded(url);
2029 }
2030
2031 bool QQml_isFileCaseCorrect(const QString &fileName)
2032 {
2033 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2034     QFileInfo info(fileName);
2035     const QString absolute = info.absoluteFilePath();
2036
2037 #if defined(Q_OS_MAC)
2038     const QString canonical = info.canonicalFilePath();
2039 #elif defined(Q_OS_WIN)
2040     wchar_t buffer[1024];
2041
2042     DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2043     if (rv == 0 || rv >= 1024) return true;
2044     rv = ::GetLongPathName(buffer, buffer, 1024);
2045     if (rv == 0 || rv >= 1024) return true;
2046
2047     const QString canonical = QString::fromWCharArray(buffer);
2048 #endif
2049
2050     const int absoluteLength = absolute.length();
2051     const int canonicalLength = canonical.length();
2052
2053     const int length = qMin(absoluteLength, canonicalLength);
2054     for (int ii = 0; ii < length; ++ii) {
2055         const QChar &a = absolute.at(absoluteLength - 1 - ii);
2056         const QChar &c = canonical.at(canonicalLength - 1 - ii);
2057
2058         if (a.toLower() != c.toLower())
2059             return true;
2060         if (a != c)
2061             return false;
2062     }
2063 #else
2064     Q_UNUSED(fileName)
2065 #endif
2066     return true;
2067 }
2068
2069 /*!
2070     \fn QQmlEngine *qmlEngine(const QObject *object)
2071     \relates QQmlEngine
2072
2073     Returns the QQmlEngine associated with \a object, if any.  This is equivalent to
2074     QQmlEngine::contextForObject(object)->engine(), but more efficient.
2075 */
2076
2077 /*!
2078     \fn QQmlContext *qmlContext(const QObject *object)
2079     \relates QQmlEngine
2080
2081     Returns the QQmlContext associated with \a object, if any.  This is equivalent to
2082     QQmlEngine::contextForObject(object).
2083 */
2084
2085 QT_END_NAMESPACE