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