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