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