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