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