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