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