Docs - add missing images and code, clean up sections
[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 C++ method calls; in these cases,
1086   the ownership of the returned objects will be set to JavaScriptOwnerShip.
1087   Note this applies only to explicit invocations of Q_INVOKABLE methods or slots,
1088   and not to property getter invocations.
1089
1090   Calling setObjectOwnership() overrides the default ownership
1091   heuristic used by QML.
1092 */
1093
1094 /*!
1095   Sets the \a ownership of \a object.
1096 */
1097 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1098 {
1099     if (!object)
1100         return;
1101
1102     QQmlData *ddata = QQmlData::get(object, true);
1103     if (!ddata)
1104         return;
1105
1106     ddata->indestructible = (ownership == CppOwnership)?true:false;
1107     ddata->explicitIndestructibleSet = true;
1108 }
1109
1110 /*!
1111   Returns the ownership of \a object.
1112 */
1113 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1114 {
1115     if (!object)
1116         return CppOwnership;
1117
1118     QQmlData *ddata = QQmlData::get(object, false);
1119     if (!ddata)
1120         return CppOwnership;
1121     else
1122         return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1123 }
1124
1125 bool QQmlEngine::event(QEvent *e)
1126 {
1127     Q_D(QQmlEngine);
1128     if (e->type() == QEvent::User)
1129         d->doDeleteInEngineThread();
1130
1131     return QJSEngine::event(e);
1132 }
1133
1134 void QQmlEnginePrivate::doDeleteInEngineThread()
1135 {
1136     QFieldList<Deletable, &Deletable::next> list;
1137     mutex.lock();
1138     list.copyAndClear(toDeleteInEngineThread);
1139     mutex.unlock();
1140
1141     while (Deletable *d = list.takeFirst())
1142         delete d;
1143 }
1144
1145 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1146 {
1147     QQmlData *data = QQmlData::get(object);
1148
1149     if (data && data->compiledData && data->deferredIdx) {
1150         QQmlObjectCreatingProfiler prof;
1151         if (prof.enabled) {
1152             QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1153             prof.setTypeName(type ? type->qmlTypeName()
1154                                   : QString::fromUtf8(object->metaObject()->className()));
1155             if (data->outerContext)
1156                 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1157         }
1158         QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1159
1160         QQmlComponentPrivate::ConstructionState state;
1161         QQmlComponentPrivate::beginDeferred(ep, object, &state);
1162
1163         // Release the reference for the deferral action (we still have one from construction)
1164         data->compiledData->release();
1165         data->compiledData = 0;
1166
1167         QQmlComponentPrivate::complete(ep, &state);
1168     }
1169 }
1170
1171 QQmlContext *qmlContext(const QObject *obj)
1172 {
1173     return QQmlEngine::contextForObject(obj);
1174 }
1175
1176 QQmlEngine *qmlEngine(const QObject *obj)
1177 {
1178     QQmlData *data = QQmlData::get(obj, false);
1179     if (!data || !data->context)
1180         return 0;
1181     return data->context->engine;
1182 }
1183
1184 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1185 {
1186     QQmlData *data = QQmlData::get(object);
1187     if (!data)
1188         return 0; // Attached properties are only on objects created by QML
1189
1190     QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1191     if (rv || !create)
1192         return rv;
1193
1194     QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1195     if (!pf)
1196         return 0;
1197
1198     rv = pf(const_cast<QObject *>(object));
1199
1200     if (rv)
1201         data->attachedProperties()->insert(id, rv);
1202
1203     return rv;
1204 }
1205
1206 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1207                                      const QMetaObject *attachedMetaObject, bool create)
1208 {
1209     if (*idCache == -1)
1210         *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1211
1212     if (*idCache == -1 || !object)
1213         return 0;
1214
1215     return qmlAttachedPropertiesObjectById(*idCache, object, create);
1216 }
1217
1218 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1219 {
1220 #ifndef QQML_NO_DEBUG_PROTOCOL
1221     if (!QQmlEnginePrivate::qml_debugging_enabled
1222             && printWarning) {
1223         qDebug("QML debugging is enabled. Only use this in a safe environment.");
1224     }
1225     QQmlEnginePrivate::qml_debugging_enabled = true;
1226 #endif
1227 }
1228
1229
1230 class QQmlDataExtended {
1231 public:
1232     QQmlDataExtended();
1233     ~QQmlDataExtended();
1234
1235     QHash<int, QObject *> attachedProperties;
1236 };
1237
1238 QQmlDataExtended::QQmlDataExtended()
1239 {
1240 }
1241
1242 QQmlDataExtended::~QQmlDataExtended()
1243 {
1244 }
1245
1246 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1247 {
1248     if (endpoint->next)
1249         layout(endpoint->next);
1250
1251     int index = endpoint->sourceSignal;
1252     index = qMin(index, 0xFFFF - 1);
1253
1254     endpoint->next = notifies[index];
1255     if (endpoint->next) endpoint->next->prev = &endpoint->next;
1256     endpoint->prev = &notifies[index];
1257     notifies[index] = endpoint;
1258 }
1259
1260 void QQmlData::NotifyList::layout()
1261 {
1262     Q_ASSERT(maximumTodoIndex >= notifiesSize);
1263
1264     if (todo) {
1265         QQmlNotifierEndpoint **old = notifies;
1266         const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1267         notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1268         const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1269                                sizeof(QQmlNotifierEndpoint*);
1270         memset(notifies + notifiesSize, 0, memsetSize);
1271
1272         if (notifies != old) {
1273             for (int ii = 0; ii < notifiesSize; ++ii)
1274                 if (notifies[ii])
1275                     notifies[ii]->prev = &notifies[ii];
1276         }
1277
1278         notifiesSize = maximumTodoIndex + 1;
1279
1280         layout(todo);
1281     }
1282
1283     maximumTodoIndex = 0;
1284     todo = 0;
1285 }
1286
1287 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1288 {
1289     if (!notifyList) {
1290         notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1291         notifyList->connectionMask = 0;
1292         notifyList->maximumTodoIndex = 0;
1293         notifyList->notifiesSize = 0;
1294         notifyList->todo = 0;
1295         notifyList->notifies = 0;
1296     }
1297
1298     Q_ASSERT(!endpoint->isConnected());
1299
1300     index = qMin(index, 0xFFFF - 1);
1301     notifyList->connectionMask |= (1ULL << quint64(index % 64));
1302
1303     if (index < notifyList->notifiesSize) {
1304
1305         endpoint->next = notifyList->notifies[index];
1306         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1307         endpoint->prev = &notifyList->notifies[index];
1308         notifyList->notifies[index] = endpoint;
1309
1310     } else {
1311         notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1312
1313         endpoint->next = notifyList->todo;
1314         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1315         endpoint->prev = &notifyList->todo;
1316         notifyList->todo = endpoint;
1317     }
1318 }
1319
1320 /*
1321     index MUST in the range returned by QObjectPrivate::signalIndex()
1322     This is different than the index returned by QMetaMethod::methodIndex()
1323 */
1324 bool QQmlData::signalHasEndpoint(int index)
1325 {
1326     return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1327 }
1328
1329 void QQmlData::disconnectNotifiers()
1330 {
1331     if (notifyList) {
1332         while (notifyList->todo)
1333             notifyList->todo->disconnect();
1334         for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1335             while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1336                 ep->disconnect();
1337         }
1338         free(notifyList->notifies);
1339         free(notifyList);
1340         notifyList = 0;
1341     }
1342 }
1343
1344 QHash<int, QObject *> *QQmlData::attachedProperties() const
1345 {
1346     if (!extendedData) extendedData = new QQmlDataExtended;
1347     return &extendedData->attachedProperties;
1348 }
1349
1350 void QQmlData::destroyed(QObject *object)
1351 {
1352     if (nextContextObject)
1353         nextContextObject->prevContextObject = prevContextObject;
1354     if (prevContextObject)
1355         *prevContextObject = nextContextObject;
1356
1357     QQmlAbstractBinding *binding = bindings;
1358     while (binding) {
1359         QQmlAbstractBinding *next = binding->nextBinding();
1360         binding->setAddedToObject(false);
1361         binding->setNextBinding(0);
1362         binding->destroy();
1363         binding = next;
1364     }
1365
1366     if (compiledData) {
1367         compiledData->release();
1368         compiledData = 0;
1369     }
1370
1371     QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1372     while (signalHandler) {
1373         if (signalHandler->isEvaluating()) {
1374             // The object is being deleted during signal handler evaluation.
1375             // This will cause a crash due to invalid memory access when the
1376             // evaluation has completed.
1377             // Abort with a friendly message instead.
1378             QString locationString;
1379             QQmlBoundSignalExpression *expr = signalHandler->expression();
1380             if (expr) {
1381                 QString fileName = expr->sourceFile();
1382                 if (fileName.isEmpty())
1383                     fileName = QStringLiteral("<Unknown File>");
1384                 locationString.append(fileName);
1385                 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1386                 QString source = expr->expression();
1387                 if (source.size() > 100) {
1388                     source.truncate(96);
1389                     source.append(QStringLiteral(" ..."));
1390                 }
1391                 locationString.append(source);
1392             } else {
1393                 locationString = QStringLiteral("<Unknown Location>");
1394             }
1395             qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1396                    "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1397                    "instead), or the application is running a nested event loop.\n"
1398                    "This behavior is NOT supported!\n"
1399                    "%s", object, qPrintable(locationString));
1400         }
1401
1402         QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1403         signalHandler->m_prevSignal = 0;
1404         signalHandler->m_nextSignal = 0;
1405         delete signalHandler;
1406         signalHandler = next;
1407     }
1408
1409     if (bindingBits)
1410         free(bindingBits);
1411
1412     if (propertyCache)
1413         propertyCache->release();
1414
1415     if (ownContext && context)
1416         context->destroy();
1417
1418     while (guards) {
1419         QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1420         *guard = (QObject *)0;
1421         guard->objectDestroyed(object);
1422     }
1423
1424     disconnectNotifiers();
1425
1426     if (extendedData)
1427         delete extendedData;
1428
1429     // Dispose the handle.
1430     // We don't simply clear it (and wait for next gc cycle to dispose
1431     // via the weak qobject reference callback) as this affects the
1432     // outcomes of v8's gc statistical analysis heuristics, which can
1433     // cause unnecessary growth of the old pointer space js heap area.
1434     qPersistentDispose(v8object);
1435
1436     if (ownMemory)
1437         delete this;
1438 }
1439
1440 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1441
1442 void QQmlData::parentChanged(QObject *object, QObject *parent)
1443 {
1444     if (parentTest()) {
1445         if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1446             QString on;
1447             QString pn;
1448
1449             { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1450             { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1451
1452             qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1453                    "User code is attempting to change it to %s.\n"
1454                    "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1455         }
1456     }
1457 }
1458
1459 bool QQmlData::hasBindingBit(int bit) const
1460 {
1461     if (bindingBitsSize > bit)
1462         return bindingBits[bit / 32] & (1 << (bit % 32));
1463     else
1464         return false;
1465 }
1466
1467 void QQmlData::clearBindingBit(int bit)
1468 {
1469     if (bindingBitsSize > bit)
1470         bindingBits[bit / 32] &= ~(1 << (bit % 32));
1471 }
1472
1473 void QQmlData::setBindingBit(QObject *obj, int bit)
1474 {
1475     if (bindingBitsSize <= bit) {
1476         int props = QQmlMetaObject(obj).propertyCount();
1477         Q_ASSERT(bit < props);
1478
1479         int arraySize = (props + 31) / 32;
1480         int oldArraySize = bindingBitsSize / 32;
1481
1482         bindingBits = (quint32 *)realloc(bindingBits,
1483                                          arraySize * sizeof(quint32));
1484
1485         memset(bindingBits + oldArraySize,
1486                0x00,
1487                sizeof(quint32) * (arraySize - oldArraySize));
1488
1489         bindingBitsSize = arraySize * 32;
1490     }
1491
1492     bindingBits[bit / 32] |= (1 << (bit % 32));
1493 }
1494
1495 void QQmlEnginePrivate::sendQuit()
1496 {
1497     Q_Q(QQmlEngine);
1498     emit q->quit();
1499     if (q->receivers(SIGNAL(quit())) == 0) {
1500         qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1501     }
1502 }
1503
1504 static void dumpwarning(const QQmlError &error)
1505 {
1506     QMessageLogger(error.url().toString().toLatin1().constData(),
1507                    error.line(), 0).warning().nospace()
1508             << qPrintable(error.toString());
1509 }
1510
1511 static void dumpwarning(const QList<QQmlError> &errors)
1512 {
1513     for (int ii = 0; ii < errors.count(); ++ii)
1514         dumpwarning(errors.at(ii));
1515 }
1516
1517 void QQmlEnginePrivate::warning(const QQmlError &error)
1518 {
1519     Q_Q(QQmlEngine);
1520     q->warnings(QList<QQmlError>() << error);
1521     if (outputWarningsToStdErr)
1522         dumpwarning(error);
1523 }
1524
1525 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1526 {
1527     Q_Q(QQmlEngine);
1528     q->warnings(errors);
1529     if (outputWarningsToStdErr)
1530         dumpwarning(errors);
1531 }
1532
1533 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1534 {
1535     Q_Q(QQmlEngine);
1536     warning(error->error(q));
1537 }
1538
1539 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1540 {
1541     if (engine)
1542         QQmlEnginePrivate::get(engine)->warning(error);
1543     else
1544         dumpwarning(error);
1545 }
1546
1547 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1548 {
1549     if (engine)
1550         QQmlEnginePrivate::get(engine)->warning(error);
1551     else
1552         dumpwarning(error);
1553 }
1554
1555 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1556 {
1557     if (engine)
1558         QQmlEnginePrivate::get(engine)->warning(error);
1559     else
1560         dumpwarning(error->error(0));
1561 }
1562
1563 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1564 {
1565     if (engine)
1566         engine->warning(error);
1567     else
1568         dumpwarning(error);
1569 }
1570
1571 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1572 {
1573     if (engine)
1574         engine->warning(error);
1575     else
1576         dumpwarning(error);
1577 }
1578
1579 /*
1580    This function should be called prior to evaluation of any js expression,
1581    so that scarce resources are not freed prematurely (eg, if there is a
1582    nested javascript expression).
1583  */
1584 void QQmlEnginePrivate::referenceScarceResources()
1585 {
1586     scarceResourcesRefCount += 1;
1587 }
1588
1589 /*
1590    This function should be called after evaluation of the js expression is
1591    complete, and so the scarce resources may be freed safely.
1592  */
1593 void QQmlEnginePrivate::dereferenceScarceResources()
1594 {
1595     Q_ASSERT(scarceResourcesRefCount > 0);
1596     scarceResourcesRefCount -= 1;
1597
1598     // if the refcount is zero, then evaluation of the "top level"
1599     // expression must have completed.  We can safely release the
1600     // scarce resources.
1601     if (scarceResourcesRefCount == 0) {
1602         // iterate through the list and release them all.
1603         // note that the actual SRD is owned by the JS engine,
1604         // so we cannot delete the SRD; but we can free the
1605         // memory used by the variant in the SRD.
1606         while (ScarceResourceData *sr = scarceResources.first()) {
1607             sr->data = QVariant();
1608             scarceResources.remove(sr);
1609         }
1610     }
1611 }
1612
1613 /*!
1614   Adds \a path as a directory where the engine searches for
1615   installed modules in a URL-based directory structure.
1616
1617   The \a path may be a local filesystem directory, a
1618   \l {The Qt Resource System}{Qt Resource} path (\c {:/imports}), a
1619   \l {The Qt Resource System}{Qt Resource} url (\c {qrc:/imports}) or a URL.
1620
1621   The \a path will be converted into canonical form before it
1622   is added to the import path list.
1623
1624   The newly added \a path will be first in the importPathList().
1625
1626   \sa setImportPathList(), {QML Modules}
1627 */
1628 void QQmlEngine::addImportPath(const QString& path)
1629 {
1630     Q_D(QQmlEngine);
1631     d->importDatabase.addImportPath(path);
1632 }
1633
1634 /*!
1635   Returns the list of directories where the engine searches for
1636   installed modules in a URL-based directory structure.
1637
1638   For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1639   imports \c com.mycompany.Feature will cause the QQmlEngine to look
1640   in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1641   provided by that module. A \c qmldir file is required for defining the
1642   type version mapping and possibly QML extensions plugins.
1643
1644   By default, the list contains the directory of the application executable,
1645   paths specified in the \c QML_IMPORT_PATH environment variable,
1646   and the builtin \c ImportsPath from QLibraryInfo.
1647
1648   \sa addImportPath(), setImportPathList()
1649 */
1650 QStringList QQmlEngine::importPathList() const
1651 {
1652     Q_D(const QQmlEngine);
1653     return d->importDatabase.importPathList();
1654 }
1655
1656 /*!
1657   Sets \a paths as the list of directories where the engine searches for
1658   installed modules in a URL-based directory structure.
1659
1660   By default, the list contains the directory of the application executable,
1661   paths specified in the \c QML_IMPORT_PATH environment variable,
1662   and the builtin \c ImportsPath from QLibraryInfo.
1663
1664   \sa importPathList(), addImportPath()
1665   */
1666 void QQmlEngine::setImportPathList(const QStringList &paths)
1667 {
1668     Q_D(QQmlEngine);
1669     d->importDatabase.setImportPathList(paths);
1670 }
1671
1672
1673 /*!
1674   Adds \a path as a directory 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   The newly added \a path will be first in the pluginPathList().
1681
1682   \sa setPluginPathList()
1683 */
1684 void QQmlEngine::addPluginPath(const QString& path)
1685 {
1686     Q_D(QQmlEngine);
1687     d->importDatabase.addPluginPath(path);
1688 }
1689
1690
1691 /*!
1692   Returns the list of directories where the engine searches for
1693   native plugins for imported modules (referenced in the \c qmldir file).
1694
1695   By default, the list contains only \c .,  i.e. the engine searches
1696   in the directory of the \c qmldir file itself.
1697
1698   \sa addPluginPath(), setPluginPathList()
1699 */
1700 QStringList QQmlEngine::pluginPathList() const
1701 {
1702     Q_D(const QQmlEngine);
1703     return d->importDatabase.pluginPathList();
1704 }
1705
1706 /*!
1707   Sets the list of directories where the engine searches for
1708   native plugins for imported modules (referenced in the \c qmldir file)
1709   to \a paths.
1710
1711   By default, the list contains only \c .,  i.e. the engine searches
1712   in the directory of the \c qmldir file itself.
1713
1714   \sa pluginPathList(), addPluginPath()
1715   */
1716 void QQmlEngine::setPluginPathList(const QStringList &paths)
1717 {
1718     Q_D(QQmlEngine);
1719     d->importDatabase.setPluginPathList(paths);
1720 }
1721
1722 /*!
1723   Imports the plugin named \a filePath with the \a uri provided.
1724   Returns true if the plugin was successfully imported; otherwise returns false.
1725
1726   On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1727
1728   The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1729 */
1730 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1731 {
1732     Q_D(QQmlEngine);
1733     return d->importDatabase.importPlugin(filePath, uri, QString(), errors);
1734 }
1735
1736 /*!
1737   \property QQmlEngine::offlineStoragePath
1738   \brief the directory for storing offline user data
1739
1740   Returns the directory where SQL and other offline
1741   storage is placed.
1742
1743   QQuickWebView and the SQL databases created with openDatabase()
1744   are stored here.
1745
1746   The default is QML/OfflineStorage in the platform-standard
1747   user application data directory.
1748
1749   Note that the path may not currently exist on the filesystem, so
1750   callers wanting to \e create new files at this location should create
1751   it first - see QDir::mkpath().
1752 */
1753 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1754 {
1755     Q_D(QQmlEngine);
1756     d->offlineStoragePath = dir;
1757 }
1758
1759 QString QQmlEngine::offlineStoragePath() const
1760 {
1761     Q_D(const QQmlEngine);
1762     return d->offlineStoragePath;
1763 }
1764
1765 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1766 {
1767     Q_Q(QQmlEngine);
1768
1769     if (!mo->superClass()) {
1770         QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1771         propertyCache.insert(mo, rv);
1772         return rv;
1773     } else {
1774         QQmlPropertyCache *super = cache(mo->superClass());
1775         QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1776         propertyCache.insert(mo, rv);
1777         return rv;
1778     }
1779 }
1780
1781 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1782                                                                   QQmlError &error)
1783 {
1784     QList<QQmlType *> types;
1785
1786     int maxMinorVersion = 0;
1787
1788     const QMetaObject *metaObject = type->metaObject();
1789
1790     while (metaObject) {
1791         QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1792                                                             type->majorVersion(), minorVersion);
1793         if (t) {
1794             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1795             types << t;
1796         } else {
1797             types << 0;
1798         }
1799
1800         metaObject = metaObject->superClass();
1801     }
1802
1803     if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1804         c->addref();
1805         typePropertyCache.insert(qMakePair(type, minorVersion), c);
1806         return c;
1807     }
1808
1809     QQmlPropertyCache *raw = cache(type->metaObject());
1810
1811     bool hasCopied = false;
1812
1813     for (int ii = 0; ii < types.count(); ++ii) {
1814         QQmlType *currentType = types.at(ii);
1815         if (!currentType)
1816             continue;
1817
1818         int rev = currentType->metaObjectRevision();
1819         int moIndex = types.count() - 1 - ii;
1820
1821         if (raw->allowedRevisionCache[moIndex] != rev) {
1822             if (!hasCopied) {
1823                 raw = raw->copy();
1824                 hasCopied = true;
1825             }
1826             raw->allowedRevisionCache[moIndex] = rev;
1827         }
1828     }
1829
1830     // Test revision compatibility - the basic rule is:
1831     //    * Anything that is excluded, cannot overload something that is not excluded *
1832
1833     // Signals override:
1834     //    * other signals and methods of the same name.
1835     //    * properties named on<Signal Name>
1836     //    * automatic <property name>Changed notify signals
1837
1838     // Methods override:
1839     //    * other methods of the same name
1840
1841     // Properties override:
1842     //    * other elements of the same name
1843
1844     bool overloadError = false;
1845     QString overloadName;
1846
1847 #if 0
1848     for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1849          !overloadError && iter != raw->stringCache.end();
1850          ++iter) {
1851
1852         QQmlPropertyData *d = *iter;
1853         if (raw->isAllowedInRevision(d))
1854             continue; // Not excluded - no problems
1855
1856         // check that a regular "name" overload isn't happening
1857         QQmlPropertyData *current = d;
1858         while (!overloadError && current) {
1859             current = d->overrideData(current);
1860             if (current && raw->isAllowedInRevision(current))
1861                 overloadError = true;
1862         }
1863     }
1864 #endif
1865
1866     if (overloadError) {
1867         if (hasCopied) raw->release();
1868
1869         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."));
1870         return 0;
1871     }
1872
1873     if (!hasCopied) raw->addref();
1874     typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1875
1876     if (minorVersion != maxMinorVersion) {
1877         raw->addref();
1878         typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1879     }
1880
1881     return raw;
1882 }
1883
1884 bool QQmlEnginePrivate::isQObject(int t)
1885 {
1886     Locker locker(this);
1887     return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1888 }
1889
1890 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1891 {
1892     Locker locker(this);
1893     int t = v.userType();
1894     if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1895         if (ok) *ok = true;
1896         return *(QObject **)(v.constData());
1897     } else {
1898         return QQmlMetaType::toQObject(v, ok);
1899     }
1900 }
1901
1902 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1903 {
1904     Locker locker(this);
1905     if (m_compositeTypes.contains(t))
1906         return QQmlMetaType::Object;
1907     else if (m_qmlLists.contains(t))
1908         return QQmlMetaType::List;
1909     else
1910         return QQmlMetaType::typeCategory(t);
1911 }
1912
1913 bool QQmlEnginePrivate::isList(int t) const
1914 {
1915     Locker locker(this);
1916     return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1917 }
1918
1919 int QQmlEnginePrivate::listType(int t) const
1920 {
1921     Locker locker(this);
1922     QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1923     if (iter != m_qmlLists.end())
1924         return *iter;
1925     else
1926         return QQmlMetaType::listType(t);
1927 }
1928
1929 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1930 {
1931     Locker locker(this);
1932     QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1933     if (iter != m_compositeTypes.end()) {
1934         return QQmlMetaObject((*iter)->rootPropertyCache);
1935     } else {
1936         QQmlType *type = QQmlMetaType::qmlType(t);
1937         return QQmlMetaObject(type?type->baseMetaObject():0);
1938     }
1939 }
1940
1941 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1942 {
1943     Locker locker(this);
1944     QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1945     if (iter != m_compositeTypes.end()) {
1946         return QQmlMetaObject((*iter)->rootPropertyCache);
1947     } else {
1948         QQmlType *type = QQmlMetaType::qmlType(t);
1949         return QQmlMetaObject(type?type->metaObject():0);
1950     }
1951 }
1952
1953 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1954 {
1955     Locker locker(this);
1956     QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1957     if (iter != m_compositeTypes.end()) {
1958         return (*iter)->rootPropertyCache;
1959     } else {
1960         QQmlType *type = QQmlMetaType::qmlType(t);
1961         locker.unlock();
1962         return type?cache(type->metaObject()):0;
1963     }
1964 }
1965
1966 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1967 {
1968     Locker locker(this);
1969     QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1970     if (iter != m_compositeTypes.end()) {
1971         return (*iter)->rootPropertyCache;
1972     } else {
1973         QQmlType *type = QQmlMetaType::qmlType(t);
1974         locker.unlock();
1975         return type?cache(type->baseMetaObject()):0;
1976     }
1977 }
1978
1979 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1980 {
1981     QByteArray name = data->rootPropertyCache->className();
1982
1983     QByteArray ptr = name + '*';
1984     QByteArray lst = "QQmlListProperty<" + name + '>';
1985
1986     int ptr_type = QMetaType::registerNormalizedType(ptr,
1987                                                      qMetaTypeDeleteHelper<QObject*>,
1988                                                      qMetaTypeCreateHelper<QObject*>,
1989                                                      qMetaTypeDestructHelper<QObject*>,
1990                                                      qMetaTypeConstructHelper<QObject*>,
1991                                                      sizeof(QObject*),
1992                                                      static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1993                                                      0);
1994     int lst_type = QMetaType::registerNormalizedType(lst,
1995                                                      qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1996                                                      qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1997                                                      qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1998                                                      qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1999                                                      sizeof(QQmlListProperty<QObject>),
2000                                                      static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
2001                                                      static_cast<QMetaObject*>(0));
2002
2003     data->metaTypeId = ptr_type;
2004     data->listMetaTypeId = lst_type;
2005     data->isRegisteredWithEngine = true;
2006
2007     Locker locker(this);
2008     m_qmlLists.insert(lst_type, ptr_type);
2009     // The QQmlCompiledData is not referenced here, but it is removed from this
2010     // hash in the QQmlCompiledData destructor
2011     m_compositeTypes.insert(ptr_type, data);
2012 }
2013
2014 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
2015 {
2016     int ptr_type = data->metaTypeId;
2017     int lst_type = data->listMetaTypeId;
2018
2019     Locker locker(this);
2020     m_qmlLists.remove(lst_type);
2021     m_compositeTypes.remove(ptr_type);
2022 }
2023
2024 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2025 {
2026     return typeLoader.isTypeLoaded(url);
2027 }
2028
2029 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2030 {
2031     return typeLoader.isScriptLoaded(url);
2032 }
2033
2034 bool QQml_isFileCaseCorrect(const QString &fileName)
2035 {
2036 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2037     QFileInfo info(fileName);
2038     const QString absolute = info.absoluteFilePath();
2039
2040 #if defined(Q_OS_MAC)
2041     const QString canonical = info.canonicalFilePath();
2042 #elif defined(Q_OS_WIN)
2043     wchar_t buffer[1024];
2044
2045     DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2046     if (rv == 0 || rv >= 1024) return true;
2047     rv = ::GetLongPathName(buffer, buffer, 1024);
2048     if (rv == 0 || rv >= 1024) return true;
2049
2050     const QString canonical = QString::fromWCharArray(buffer);
2051 #endif
2052
2053     const int absoluteLength = absolute.length();
2054     const int canonicalLength = canonical.length();
2055
2056     const int length = qMin(absoluteLength, canonicalLength);
2057     for (int ii = 0; ii < length; ++ii) {
2058         const QChar &a = absolute.at(absoluteLength - 1 - ii);
2059         const QChar &c = canonical.at(canonicalLength - 1 - ii);
2060
2061         if (a.toLower() != c.toLower())
2062             return true;
2063         if (a != c)
2064             return false;
2065     }
2066 #else
2067     Q_UNUSED(fileName)
2068 #endif
2069     return true;
2070 }
2071
2072 /*!
2073     \fn QQmlEngine *qmlEngine(const QObject *object)
2074     \relates QQmlEngine
2075
2076     Returns the QQmlEngine associated with \a object, if any.  This is equivalent to
2077     QQmlEngine::contextForObject(object)->engine(), but more efficient.
2078 */
2079
2080 /*!
2081     \fn QQmlContext *qmlContext(const QObject *object)
2082     \relates QQmlEngine
2083
2084     Returns the QQmlContext associated with \a object, if any.  This is equivalent to
2085     QQmlEngine::contextForObject(object).
2086 */
2087
2088 QT_END_NAMESPACE