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