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