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