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