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