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