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