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