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