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