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