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