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