8fdc7b1c22135c73a413105ac32fa03cfaf0ecdd
[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 <QtWidgets/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<QScriptValue>("QScriptValue");
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     // Init V8 data
453     v8engine.init(q);
454
455     rootContext = new QDeclarativeContext(q,true);
456
457     if (QCoreApplication::instance()->thread() == q->thread() &&
458         QDeclarativeEngineDebugServer::isDebuggingEnabled()) {
459         isDebugging = true;
460         QDeclarativeEngineDebugServer::instance()->addEngine(q);
461         QJSDebugService::instance()->addEngine(q);
462     }
463 }
464
465 QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine()
466 {
467     Q_Q(QDeclarativeEngine);
468     if (!workerScriptEngine)
469         workerScriptEngine = new QDeclarativeWorkerScriptEngine(q);
470     return workerScriptEngine;
471 }
472
473 /*!
474   \class QDeclarativeEngine
475   \since 4.7
476   \brief The QDeclarativeEngine class provides an environment for instantiating QML components.
477   \mainclass
478
479   Each QML component is instantiated in a QDeclarativeContext.
480   QDeclarativeContext's are essential for passing data to QML
481   components.  In QML, contexts are arranged hierarchically and this
482   hierarchy is managed by the QDeclarativeEngine.
483
484   Prior to creating any QML components, an application must have
485   created a QDeclarativeEngine to gain access to a QML context.  The
486   following example shows how to create a simple Text item.
487
488   \code
489   QDeclarativeEngine engine;
490   QDeclarativeComponent component(&engine);
491   component.setData("import QtQuick 1.0\nText { text: \"Hello world!\" }", QUrl());
492   QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create());
493
494   //add item to view, etc
495   ...
496   \endcode
497
498   In this case, the Text item will be created in the engine's
499   \l {QDeclarativeEngine::rootContext()}{root context}.
500
501   \sa QDeclarativeComponent QDeclarativeContext
502 */
503
504 /*!
505   Create a new QDeclarativeEngine with the given \a parent.
506 */
507 QDeclarativeEngine::QDeclarativeEngine(QObject *parent)
508 : QObject(*new QDeclarativeEnginePrivate(this), parent)
509 {
510     Q_D(QDeclarativeEngine);
511     d->init();
512 }
513
514 /*!
515   Destroys the QDeclarativeEngine.
516
517   Any QDeclarativeContext's created on this engine will be
518   invalidated, but not destroyed (unless they are parented to the
519   QDeclarativeEngine object).
520 */
521 QDeclarativeEngine::~QDeclarativeEngine()
522 {
523     Q_D(QDeclarativeEngine);
524     if (d->isDebugging)
525         QDeclarativeEngineDebugServer::instance()->remEngine(this);
526
527     // if we are the parent of any of the qobject module api instances,
528     // we need to remove them from our internal list, in order to prevent
529     // a segfault in engine private dtor.
530     QList<QDeclarativeMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
531     QObject *currQObjectApi = 0;
532     QDeclarativeMetaType::ModuleApiInstance *currInstance = 0;
533     foreach (const QDeclarativeMetaType::ModuleApi &key, keys) {
534         currInstance = d->moduleApiInstances.value(key);
535         currQObjectApi = currInstance->qobjectApi;
536         if (this->children().contains(currQObjectApi)) {
537             delete currQObjectApi;
538             delete currInstance;
539             d->moduleApiInstances.remove(key);
540         }
541     }
542 }
543
544 /*! \fn void QDeclarativeEngine::quit()
545     This signal is emitted when the QML loaded by the engine would like to quit.
546  */
547
548 /*! \fn void QDeclarativeEngine::warnings(const QList<QDeclarativeError> &warnings)
549     This signal is emitted when \a warnings messages are generated by QML.
550  */
551
552 /*!
553   Clears the engine's internal component cache.
554
555   Normally the QDeclarativeEngine caches components loaded from qml
556   files.  This method clears this cache and forces the component to be
557   reloaded.
558  */
559 void QDeclarativeEngine::clearComponentCache()
560 {
561     Q_D(QDeclarativeEngine);
562     d->typeLoader.clearCache();
563 }
564
565 /*!
566   Returns the engine's root context.
567
568   The root context is automatically created by the QDeclarativeEngine.
569   Data that should be available to all QML component instances
570   instantiated by the engine should be put in the root context.
571
572   Additional data that should only be available to a subset of
573   component instances should be added to sub-contexts parented to the
574   root context.
575 */
576 QDeclarativeContext *QDeclarativeEngine::rootContext() const
577 {
578     Q_D(const QDeclarativeEngine);
579     return d->rootContext;
580 }
581
582 /*!
583   Sets the \a factory to use for creating QNetworkAccessManager(s).
584
585   QNetworkAccessManager is used for all network access by QML.  By
586   implementing a factory it is possible to create custom
587   QNetworkAccessManager with specialized caching, proxy and cookie
588   support.
589
590   The factory must be set before executing the engine.
591 */
592 void QDeclarativeEngine::setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *factory)
593 {
594     Q_D(QDeclarativeEngine);
595     QMutexLocker locker(&d->mutex);
596     d->networkAccessManagerFactory = factory;
597 }
598
599 /*!
600   Returns the current QDeclarativeNetworkAccessManagerFactory.
601
602   \sa setNetworkAccessManagerFactory()
603 */
604 QDeclarativeNetworkAccessManagerFactory *QDeclarativeEngine::networkAccessManagerFactory() const
605 {
606     Q_D(const QDeclarativeEngine);
607     return d->networkAccessManagerFactory;
608 }
609
610 QNetworkAccessManager *QDeclarativeEnginePrivate::createNetworkAccessManager(QObject *parent) const
611 {
612     QMutexLocker locker(&mutex);
613     QNetworkAccessManager *nam;
614     if (networkAccessManagerFactory) {
615         nam = networkAccessManagerFactory->create(parent);
616     } else {
617         nam = new QNetworkAccessManager(parent);
618     }
619
620     return nam;
621 }
622
623 QNetworkAccessManager *QDeclarativeEnginePrivate::getNetworkAccessManager() const
624 {
625     Q_Q(const QDeclarativeEngine);
626     if (!networkAccessManager)
627         networkAccessManager = createNetworkAccessManager(const_cast<QDeclarativeEngine*>(q));
628     return networkAccessManager;
629 }
630
631 /*!
632   Returns a common QNetworkAccessManager which can be used by any QML
633   element instantiated by this engine.
634
635   If a QDeclarativeNetworkAccessManagerFactory has been set and a
636   QNetworkAccessManager has not yet been created, the
637   QDeclarativeNetworkAccessManagerFactory will be used to create the
638   QNetworkAccessManager; otherwise the returned QNetworkAccessManager
639   will have no proxy or cache set.
640
641   \sa setNetworkAccessManagerFactory()
642 */
643 QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
644 {
645     Q_D(const QDeclarativeEngine);
646     return d->getNetworkAccessManager();
647 }
648
649 /*!
650
651   Sets the \a provider to use for images requested via the \e
652   image: url scheme, with host \a providerId. The QDeclarativeEngine
653   takes ownership of \a provider.
654
655   Image providers enable support for pixmap and threaded image
656   requests. See the QDeclarativeImageProvider documentation for details on
657   implementing and using image providers.
658
659   All required image providers should be added to the engine before any
660   QML sources files are loaded.
661
662   \sa removeImageProvider()
663 */
664 void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativeImageProvider *provider)
665 {
666     Q_D(QDeclarativeEngine);
667     QMutexLocker locker(&d->mutex);
668     d->imageProviders.insert(providerId.toLower(), QSharedPointer<QDeclarativeImageProvider>(provider));
669 }
670
671 /*!
672   Returns the QDeclarativeImageProvider set for \a providerId.
673 */
674 QDeclarativeImageProvider *QDeclarativeEngine::imageProvider(const QString &providerId) const
675 {
676     Q_D(const QDeclarativeEngine);
677     QMutexLocker locker(&d->mutex);
678     return d->imageProviders.value(providerId).data();
679 }
680
681 /*!
682   Removes the QDeclarativeImageProvider for \a providerId.
683
684   Returns the provider if it was found; otherwise returns 0.
685
686   \sa addImageProvider()
687 */
688 void QDeclarativeEngine::removeImageProvider(const QString &providerId)
689 {
690     Q_D(QDeclarativeEngine);
691     QMutexLocker locker(&d->mutex);
692     d->imageProviders.take(providerId);
693 }
694
695 QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProviderType(const QUrl &url)
696 {
697     QMutexLocker locker(&mutex);
698     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
699     locker.unlock();
700     if (provider)
701         return provider->imageType();
702     return QDeclarativeImageProvider::Invalid;
703 }
704
705 QSGTexture *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
706 {
707     QMutexLocker locker(&mutex);
708     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
709     locker.unlock();
710     if (provider) {
711         QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
712         return provider->requestTexture(imageId, size, req_size);
713     }
714     return 0;
715 }
716
717 QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
718 {
719     QMutexLocker locker(&mutex);
720     QImage image;
721     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
722     locker.unlock();
723     if (provider) {
724         QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
725         image = provider->requestImage(imageId, size, req_size);
726     }
727     return image;
728 }
729
730 QPixmap QDeclarativeEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
731 {
732     QMutexLocker locker(&mutex);
733     QPixmap pixmap;
734     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
735     locker.unlock();
736     if (provider) {
737         QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
738         pixmap = provider->requestPixmap(imageId, size, req_size);
739     }
740     return pixmap;
741 }
742
743 /*!
744   Return the base URL for this engine.  The base URL is only used to
745   resolve components when a relative URL is passed to the
746   QDeclarativeComponent constructor.
747
748   If a base URL has not been explicitly set, this method returns the
749   application's current working directory.
750
751   \sa setBaseUrl()
752 */
753 QUrl QDeclarativeEngine::baseUrl() const
754 {
755     Q_D(const QDeclarativeEngine);
756     if (d->baseUrl.isEmpty()) {
757         return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
758     } else {
759         return d->baseUrl;
760     }
761 }
762
763 /*!
764   Set the  base URL for this engine to \a url.
765
766   \sa baseUrl()
767 */
768 void QDeclarativeEngine::setBaseUrl(const QUrl &url)
769 {
770     Q_D(QDeclarativeEngine);
771     d->baseUrl = url;
772 }
773
774 /*!
775   Returns true if warning messages will be output to stderr in addition
776   to being emitted by the warnings() signal, otherwise false.
777
778   The default value is true.
779 */
780 bool QDeclarativeEngine::outputWarningsToStandardError() const
781 {
782     Q_D(const QDeclarativeEngine);
783     return d->outputWarningsToStdErr;
784 }
785
786 /*!
787   Set whether warning messages will be output to stderr to \a enabled.
788
789   If \a enabled is true, any warning messages generated by QML will be
790   output to stderr and emitted by the warnings() signal.  If \a enabled
791   is false, on the warnings() signal will be emitted.  This allows
792   applications to handle warning output themselves.
793
794   The default value is true.
795 */
796 void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled)
797 {
798     Q_D(QDeclarativeEngine);
799     d->outputWarningsToStdErr = enabled;
800 }
801
802 /*!
803   Attempt to free unused memory.
804 */
805 void QDeclarativeEngine::collectGarbage()
806 {
807     QV8Engine::gc();
808 }
809
810 /*!
811   Returns the QDeclarativeContext for the \a object, or 0 if no
812   context has been set.
813
814   When the QDeclarativeEngine instantiates a QObject, the context is
815   set automatically.
816   */
817 QDeclarativeContext *QDeclarativeEngine::contextForObject(const QObject *object)
818 {
819     if(!object)
820         return 0;
821
822     QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
823
824     QDeclarativeData *data =
825         static_cast<QDeclarativeData *>(priv->declarativeData);
826
827     if (!data)
828         return 0;
829     else if (data->outerContext)
830         return data->outerContext->asQDeclarativeContext();
831     else
832         return 0;
833 }
834
835 /*!
836   Sets the QDeclarativeContext for the \a object to \a context.
837   If the \a object already has a context, a warning is
838   output, but the context is not changed.
839
840   When the QDeclarativeEngine instantiates a QObject, the context is
841   set automatically.
842  */
843 void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContext *context)
844 {
845     if (!object || !context)
846         return;
847
848     QDeclarativeData *data = QDeclarativeData::get(object, true);
849     if (data->context) {
850         qWarning("QDeclarativeEngine::setContextForObject(): Object already has a QDeclarativeContext");
851         return;
852     }
853
854     QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
855     contextData->addObject(object);
856 }
857
858 /*!
859   \enum QDeclarativeEngine::ObjectOwnership
860
861   Ownership controls whether or not QML automatically destroys the
862   QObject when the object is garbage collected by the JavaScript
863   engine.  The two ownership options are:
864
865   \value CppOwnership The object is owned by C++ code, and will
866   never be deleted by QML.  The JavaScript destroy() method cannot be
867   used on objects with CppOwnership.  This option is similar to
868   QScriptEngine::QtOwnership.
869
870   \value JavaScriptOwnership The object is owned by JavaScript.
871   When the object is returned to QML as the return value of a method
872   call or property access, QML will delete the object if there are no
873   remaining JavaScript references to it and it has no
874   QObject::parent().  This option is similar to
875   QScriptEngine::ScriptOwnership.
876
877   Generally an application doesn't need to set an object's ownership
878   explicitly.  QML uses a heuristic to set the default object
879   ownership.  By default, an object that is created by QML has
880   JavaScriptOwnership.  The exception to this are the root objects
881   created by calling QDeclarativeCompnent::create() or
882   QDeclarativeComponent::beginCreate() which have CppOwnership by
883   default.  The ownership of these root-level objects is considered to
884   have been transferred to the C++ caller.
885
886   Objects not-created by QML have CppOwnership by default.  The
887   exception to this is objects returned from a C++ method call.  The
888   ownership of these objects is passed to JavaScript.
889
890   Calling setObjectOwnership() overrides the default ownership
891   heuristic used by QML.
892 */
893
894 /*!
895   Sets the \a ownership of \a object.
896 */
897 void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
898 {
899     if (!object)
900         return;
901
902     QDeclarativeData *ddata = QDeclarativeData::get(object, true);
903     if (!ddata)
904         return;
905
906     ddata->indestructible = (ownership == CppOwnership)?true:false;
907     ddata->explicitIndestructibleSet = true;
908 }
909
910 /*!
911   Returns the ownership of \a object.
912 */
913 QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object)
914 {
915     if (!object)
916         return CppOwnership;
917
918     QDeclarativeData *ddata = QDeclarativeData::get(object, false);
919     if (!ddata)
920         return CppOwnership;
921     else
922         return ddata->indestructible?CppOwnership:JavaScriptOwnership;
923 }
924
925 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
926 {
927     QDeclarativeData *data = QDeclarativeData::get(object);
928
929     if (data && data->deferredComponent) {
930         if (QDeclarativeDebugService::isDebuggingEnabled()) {
931             QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
932             QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
933             QString typeName = type ? QLatin1String(type->qmlTypeName()) : QString::fromLatin1(object->metaObject()->className());
934             QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, typeName);
935             if (data->outerContext)
936                 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, data->outerContext->url, data->lineNumber);
937         }
938         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine);
939
940         QDeclarativeComponentPrivate::ConstructionState state;
941         QDeclarativeComponentPrivate::beginDeferred(ep, object, &state);
942
943         data->deferredComponent->release();
944         data->deferredComponent = 0;
945
946         QDeclarativeComponentPrivate::complete(ep, &state);
947         QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
948     }
949 }
950
951 QDeclarativeContext *qmlContext(const QObject *obj)
952 {
953     return QDeclarativeEngine::contextForObject(obj);
954 }
955
956 QDeclarativeEngine *qmlEngine(const QObject *obj)
957 {
958     QDeclarativeContext *context = QDeclarativeEngine::contextForObject(obj);
959     return context?context->engine():0;
960 }
961
962 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
963 {
964     QDeclarativeData *data = QDeclarativeData::get(object);
965     if (!data)
966         return 0; // Attached properties are only on objects created by QML
967
968     QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
969     if (rv || !create)
970         return rv;
971
972     QDeclarativeAttachedPropertiesFunc pf = QDeclarativeMetaType::attachedPropertiesFuncById(id);
973     if (!pf)
974         return 0;
975
976     rv = pf(const_cast<QObject *>(object));
977
978     if (rv)
979         data->attachedProperties()->insert(id, rv);
980
981     return rv;
982 }
983
984 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
985                                      const QMetaObject *attachedMetaObject, bool create)
986 {
987     if (*idCache == -1)
988         *idCache = QDeclarativeMetaType::attachedPropertiesFuncId(attachedMetaObject);
989
990     if (*idCache == -1 || !object)
991         return 0;
992
993     return qmlAttachedPropertiesObjectById(*idCache, object, create);
994 }
995
996 class QDeclarativeDataExtended {
997 public:
998     QDeclarativeDataExtended();
999     ~QDeclarativeDataExtended();
1000
1001     QHash<int, QObject *> attachedProperties;
1002     QDeclarativeNotifier objectNameNotifier;
1003 };
1004
1005 QDeclarativeDataExtended::QDeclarativeDataExtended()
1006 {
1007 }
1008
1009 QDeclarativeDataExtended::~QDeclarativeDataExtended()
1010 {
1011 }
1012
1013 QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const
1014 {
1015     if (!extendedData) extendedData = new QDeclarativeDataExtended;
1016     return &extendedData->objectNameNotifier;
1017 }
1018
1019 QHash<int, QObject *> *QDeclarativeData::attachedProperties() const
1020 {
1021     if (!extendedData) extendedData = new QDeclarativeDataExtended;
1022     return &extendedData->attachedProperties;
1023 }
1024
1025 void QDeclarativeData::destroyed(QObject *object)
1026 {
1027     if (deferredComponent)
1028         deferredComponent->release();
1029
1030     if (nextContextObject)
1031         nextContextObject->prevContextObject = prevContextObject;
1032     if (prevContextObject)
1033         *prevContextObject = nextContextObject;
1034
1035     QDeclarativeAbstractBinding *binding = bindings;
1036     while (binding) {
1037         QDeclarativeAbstractBinding *next = binding->m_nextBinding;
1038         binding->m_prevBinding = 0;
1039         binding->m_nextBinding = 0;
1040         binding->destroy();
1041         binding = next;
1042     }
1043
1044     if (bindingBits)
1045         free(bindingBits);
1046
1047     if (propertyCache)
1048         propertyCache->release();
1049
1050     if (ownContext && context)
1051         context->destroy();
1052
1053     while (guards) {
1054         QDeclarativeGuard<QObject> *guard = static_cast<QDeclarativeGuard<QObject> *>(guards);
1055         *guard = (QObject *)0;
1056         guard->objectDestroyed(object);
1057     }
1058
1059     if (extendedData)
1060         delete extendedData;
1061
1062     v8object.Clear(); // The WeakReference handler will clean the actual handle
1063
1064     if (ownMemory)
1065         delete this;
1066 }
1067
1068 void QDeclarativeData::parentChanged(QObject *object, QObject *parent)
1069 {
1070     Q_UNUSED(object);
1071     Q_UNUSED(parent);
1072 }
1073
1074 void QDeclarativeData::objectNameChanged(QObject *)
1075 {
1076     if (extendedData) objectNameNotifier()->notify();
1077 }
1078
1079 bool QDeclarativeData::hasBindingBit(int bit) const
1080 {
1081     if (bindingBitsSize > bit)
1082         return bindingBits[bit / 32] & (1 << (bit % 32));
1083     else
1084         return false;
1085 }
1086
1087 void QDeclarativeData::clearBindingBit(int bit)
1088 {
1089     if (bindingBitsSize > bit)
1090         bindingBits[bit / 32] &= ~(1 << (bit % 32));
1091 }
1092
1093 void QDeclarativeData::setBindingBit(QObject *obj, int bit)
1094 {
1095     if (bindingBitsSize <= bit) {
1096         int props = obj->metaObject()->propertyCount();
1097         Q_ASSERT(bit < props);
1098
1099         int arraySize = (props + 31) / 32;
1100         int oldArraySize = bindingBitsSize / 32;
1101
1102         bindingBits = (quint32 *)realloc(bindingBits,
1103                                          arraySize * sizeof(quint32));
1104
1105         memset(bindingBits + oldArraySize,
1106                0x00,
1107                sizeof(quint32) * (arraySize - oldArraySize));
1108
1109         bindingBitsSize = arraySize * 32;
1110     }
1111
1112     bindingBits[bit / 32] |= (1 << (bit % 32));
1113 }
1114
1115 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1116 {
1117     if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1118         if (url.authority().isEmpty())
1119             return QLatin1Char(':') + url.path();
1120         return QString();
1121     }
1122     return url.toLocalFile();
1123 }
1124
1125 void QDeclarativeEnginePrivate::sendQuit()
1126 {
1127     Q_Q(QDeclarativeEngine);
1128     emit q->quit();
1129     if (q->receivers(SIGNAL(quit())) == 0) {
1130         qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it.");
1131     }
1132 }
1133
1134 static void dumpwarning(const QDeclarativeError &error)
1135 {
1136     qWarning().nospace() << qPrintable(error.toString());
1137 }
1138
1139 static void dumpwarning(const QList<QDeclarativeError> &errors)
1140 {
1141     for (int ii = 0; ii < errors.count(); ++ii)
1142         dumpwarning(errors.at(ii));
1143 }
1144
1145 void QDeclarativeEnginePrivate::warning(const QDeclarativeError &error)
1146 {
1147     Q_Q(QDeclarativeEngine);
1148     q->warnings(QList<QDeclarativeError>() << error);
1149     if (outputWarningsToStdErr)
1150         dumpwarning(error);
1151 }
1152
1153 void QDeclarativeEnginePrivate::warning(const QList<QDeclarativeError> &errors)
1154 {
1155     Q_Q(QDeclarativeEngine);
1156     q->warnings(errors);
1157     if (outputWarningsToStdErr)
1158         dumpwarning(errors);
1159 }
1160
1161 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QDeclarativeError &error)
1162 {
1163     if (engine)
1164         QDeclarativeEnginePrivate::get(engine)->warning(error);
1165     else
1166         dumpwarning(error);
1167 }
1168
1169 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QList<QDeclarativeError> &error)
1170 {
1171     if (engine)
1172         QDeclarativeEnginePrivate::get(engine)->warning(error);
1173     else
1174         dumpwarning(error);
1175 }
1176
1177 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QDeclarativeError &error)
1178 {
1179     if (engine)
1180         engine->warning(error);
1181     else
1182         dumpwarning(error);
1183 }
1184
1185 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QList<QDeclarativeError> &error)
1186 {
1187     if (engine)
1188         engine->warning(error);
1189     else
1190         dumpwarning(error);
1191 }
1192
1193 /*
1194    This function should be called prior to evaluation of any js expression,
1195    so that scarce resources are not freed prematurely (eg, if there is a
1196    nested javascript expression).
1197  */
1198 void QDeclarativeEnginePrivate::referenceScarceResources()
1199 {
1200     scarceResourcesRefCount += 1;
1201 }
1202
1203 /*
1204    This function should be called after evaluation of the js expression is
1205    complete, and so the scarce resources may be freed safely.
1206  */
1207 void QDeclarativeEnginePrivate::dereferenceScarceResources()
1208 {
1209     Q_ASSERT(scarceResourcesRefCount > 0);
1210     scarceResourcesRefCount -= 1;
1211
1212     // if the refcount is zero, then evaluation of the "top level"
1213     // expression must have completed.  We can safely release the
1214     // scarce resources.
1215     if (scarceResourcesRefCount == 0) {
1216         // iterate through the list and release them all.
1217         // note that the actual SRD is owned by the JS engine,
1218         // so we cannot delete the SRD; but we can free the
1219         // memory used by the variant in the SRD.
1220         while (ScarceResourceData *sr = scarceResources.first()) {
1221             sr->data = QVariant();
1222             scarceResources.remove(sr);
1223         }
1224     }
1225 }
1226
1227 /*!
1228   Adds \a path as a directory where the engine searches for
1229   installed modules in a URL-based directory structure.
1230   The \a path may be a local filesystem directory or a URL.
1231
1232   The newly added \a path will be first in the importPathList().
1233
1234   \sa setImportPathList(), {QML Modules}
1235 */
1236 void QDeclarativeEngine::addImportPath(const QString& path)
1237 {
1238     Q_D(QDeclarativeEngine);
1239     d->importDatabase.addImportPath(path);
1240 }
1241
1242 /*!
1243   Returns the list of directories where the engine searches for
1244   installed modules in a URL-based directory structure.
1245
1246   For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1247   imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look
1248   in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1249   provided by that module. A \c qmldir file is required for defining the
1250   type version mapping and possibly declarative extensions plugins.
1251
1252   By default, the list contains the directory of the application executable,
1253   paths specified in the \c QML_IMPORT_PATH environment variable,
1254   and the builtin \c ImportsPath from QLibraryInfo.
1255
1256   \sa addImportPath() setImportPathList()
1257 */
1258 QStringList QDeclarativeEngine::importPathList() const
1259 {
1260     Q_D(const QDeclarativeEngine);
1261     return d->importDatabase.importPathList();
1262 }
1263
1264 /*!
1265   Sets \a paths as the list of directories where the engine searches for
1266   installed modules in a URL-based directory structure.
1267
1268   By default, the list contains the directory of the application executable,
1269   paths specified in the \c QML_IMPORT_PATH environment variable,
1270   and the builtin \c ImportsPath from QLibraryInfo.
1271
1272   \sa importPathList() addImportPath()
1273   */
1274 void QDeclarativeEngine::setImportPathList(const QStringList &paths)
1275 {
1276     Q_D(QDeclarativeEngine);
1277     d->importDatabase.setImportPathList(paths);
1278 }
1279
1280
1281 /*!
1282   Adds \a path as a directory where the engine searches for
1283   native plugins for imported modules (referenced in the \c qmldir file).
1284
1285   By default, the list contains only \c .,  i.e. the engine searches
1286   in the directory of the \c qmldir file itself.
1287
1288   The newly added \a path will be first in the pluginPathList().
1289
1290   \sa setPluginPathList()
1291 */
1292 void QDeclarativeEngine::addPluginPath(const QString& path)
1293 {
1294     Q_D(QDeclarativeEngine);
1295     d->importDatabase.addPluginPath(path);
1296 }
1297
1298
1299 /*!
1300   Returns the list of directories where the engine searches for
1301   native plugins for imported modules (referenced in the \c qmldir file).
1302
1303   By default, the list contains only \c .,  i.e. the engine searches
1304   in the directory of the \c qmldir file itself.
1305
1306   \sa addPluginPath() setPluginPathList()
1307 */
1308 QStringList QDeclarativeEngine::pluginPathList() const
1309 {
1310     Q_D(const QDeclarativeEngine);
1311     return d->importDatabase.pluginPathList();
1312 }
1313
1314 /*!
1315   Sets the list of directories where the engine searches for
1316   native plugins for imported modules (referenced in the \c qmldir file)
1317   to \a paths.
1318
1319   By default, the list contains only \c .,  i.e. the engine searches
1320   in the directory of the \c qmldir file itself.
1321
1322   \sa pluginPathList() addPluginPath()
1323   */
1324 void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
1325 {
1326     Q_D(QDeclarativeEngine);
1327     d->importDatabase.setPluginPathList(paths);
1328 }
1329
1330 /*!
1331   Imports the plugin named \a filePath with the \a uri provided.
1332   Returns true if the plugin was successfully imported; otherwise returns false.
1333
1334   On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1335
1336   The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1337 */
1338 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
1339 {
1340     Q_D(QDeclarativeEngine);
1341     return d->importDatabase.importPlugin(filePath, uri, errors);
1342 }
1343
1344 /*!
1345   Imports the plugin named \a filePath with the \a uri provided.
1346   Returns true if the plugin was successfully imported; otherwise returns false.
1347
1348   On failure and if non-null, *\a errorString will be set to a message describing the failure.
1349
1350   The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1351 */
1352 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1353 {
1354     Q_D(QDeclarativeEngine);
1355     QList<QDeclarativeError> errors;
1356     bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1357     if (!errors.isEmpty()) {
1358         QString builtError;
1359         for (int i = 0; i < errors.size(); ++i) {
1360             builtError = QString(QLatin1String("%1\n        %2"))
1361                     .arg(builtError)
1362                     .arg(errors.at(i).toString());
1363         }
1364         *errorString = builtError;
1365     }
1366     return retn;
1367 }
1368
1369 /*!
1370   \property QDeclarativeEngine::offlineStoragePath
1371   \brief the directory for storing offline user data
1372
1373   Returns the directory where SQL and other offline
1374   storage is placed.
1375
1376   QDeclarativeWebView and the SQL databases created with openDatabase()
1377   are stored here.
1378
1379   The default is QML/OfflineStorage in the platform-standard
1380   user application data directory.
1381
1382   Note that the path may not currently exist on the filesystem, so
1383   callers wanting to \e create new files at this location should create
1384   it first - see QDir::mkpath().
1385 */
1386 void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
1387 {
1388     Q_D(QDeclarativeEngine);
1389     qt_qmlsqldatabase_setOfflineStoragePath(&d->v8engine, dir);
1390 }
1391
1392 QString QDeclarativeEngine::offlineStoragePath() const
1393 {
1394     Q_D(const QDeclarativeEngine);
1395     return qt_qmlsqldatabase_getOfflineStoragePath(&d->v8engine);
1396 }
1397
1398 static void voidptr_destructor(void *v)
1399 {
1400     void **ptr = (void **)v;
1401     delete ptr;
1402 }
1403
1404 static void *voidptr_constructor(const void *v)
1405 {
1406     if (!v) {
1407         return new void*;
1408     } else {
1409         return new void*(*(void **)v);
1410     }
1411 }
1412
1413 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo)
1414 {
1415     Q_Q(QDeclarativeEngine);
1416
1417     if (!mo->superClass()) {
1418         QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo);
1419         propertyCache.insert(mo, rv);
1420         return rv;
1421     } else {
1422         QDeclarativePropertyCache *super = cache(mo->superClass());
1423         QDeclarativePropertyCache *rv = super->copy();
1424         rv->append(q, mo);
1425         propertyCache.insert(mo, rv);
1426         return rv;
1427     }
1428 }
1429
1430 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
1431                                                                   QDeclarativeError &error)
1432 {
1433     QList<QDeclarativeType *> types;
1434
1435     int maxMinorVersion = 0;
1436
1437     const QMetaObject *metaObject = type->metaObject();
1438     while (metaObject) {
1439         QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
1440                                                             type->majorVersion(), minorVersion);
1441         if (t) {
1442             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1443             types << t;
1444         } else {
1445             types << 0;
1446         }
1447
1448         metaObject = metaObject->superClass();
1449     }
1450
1451     if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1452         c->addref();
1453         typePropertyCache.insert(qMakePair(type, minorVersion), c);
1454         return c;
1455     }
1456
1457     QDeclarativePropertyCache *raw = cache(type->metaObject());
1458
1459     bool hasCopied = false;
1460
1461     for (int ii = 0; ii < types.count(); ++ii) {
1462         QDeclarativeType *currentType = types.at(ii);
1463         if (!currentType)
1464             continue;
1465
1466         int rev = currentType->metaObjectRevision();
1467         int moIndex = types.count() - 1 - ii;
1468
1469         if (raw->allowedRevisionCache[moIndex] != rev) {
1470             if (!hasCopied) {
1471                 raw = raw->copy();
1472                 hasCopied = true;
1473             }
1474             raw->allowedRevisionCache[moIndex] = rev;
1475         }
1476     }
1477
1478     // Test revision compatibility - the basic rule is:
1479     //    * Anything that is excluded, cannot overload something that is not excluded *
1480
1481     // Signals override:
1482     //    * other signals and methods of the same name.
1483     //    * properties named on<Signal Name>
1484     //    * automatic <property name>Changed notify signals
1485
1486     // Methods override:
1487     //    * other methods of the same name
1488
1489     // Properties override:
1490     //    * other elements of the same name
1491
1492     bool overloadError = false;
1493     QString overloadName;
1494
1495 #if 0
1496     for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1497          !overloadError && iter != raw->stringCache.end();
1498          ++iter) {
1499
1500         QDeclarativePropertyCache::Data *d = *iter;
1501         if (raw->isAllowedInRevision(d))
1502             continue; // Not excluded - no problems
1503
1504         // check that a regular "name" overload isn't happening
1505         QDeclarativePropertyCache::Data *current = d;
1506         while (!overloadError && current) {
1507             current = d->overrideData(current);
1508             if (current && raw->isAllowedInRevision(current))
1509                 overloadError = true;
1510         }
1511     }
1512 #endif
1513
1514     if (overloadError) {
1515         if (hasCopied) raw->release();
1516
1517         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."));
1518         return 0;
1519     }
1520
1521     if (!hasCopied) raw->addref();
1522     typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1523
1524     if (minorVersion != maxMinorVersion) {
1525         raw->addref();
1526         typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1527     }
1528
1529     return raw;
1530 }
1531
1532 void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data)
1533 {
1534     QByteArray name = data->root->className();
1535
1536     QByteArray ptr = name + '*';
1537     QByteArray lst = "QDeclarativeListProperty<" + name + '>';
1538
1539     int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1540                                            voidptr_constructor);
1541     int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1542                                            voidptr_constructor);
1543
1544     m_qmlLists.insert(lst_type, ptr_type);
1545     m_compositeTypes.insert(ptr_type, data);
1546     data->addref();
1547 }
1548
1549 bool QDeclarativeEnginePrivate::isList(int t) const
1550 {
1551     return m_qmlLists.contains(t) || QDeclarativeMetaType::isList(t);
1552 }
1553
1554 int QDeclarativeEnginePrivate::listType(int t) const
1555 {
1556     QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1557     if (iter != m_qmlLists.end())
1558         return *iter;
1559     else
1560         return QDeclarativeMetaType::listType(t);
1561 }
1562
1563 bool QDeclarativeEnginePrivate::isQObject(int t)
1564 {
1565     return m_compositeTypes.contains(t) || QDeclarativeMetaType::isQObject(t);
1566 }
1567
1568 QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1569 {
1570     int t = v.userType();
1571     if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1572         if (ok) *ok = true;
1573         return *(QObject **)(v.constData());
1574     } else {
1575         return QDeclarativeMetaType::toQObject(v, ok);
1576     }
1577 }
1578
1579 QDeclarativeMetaType::TypeCategory QDeclarativeEnginePrivate::typeCategory(int t) const
1580 {
1581     if (m_compositeTypes.contains(t))
1582         return QDeclarativeMetaType::Object;
1583     else if (m_qmlLists.contains(t))
1584         return QDeclarativeMetaType::List;
1585     else
1586         return QDeclarativeMetaType::typeCategory(t);
1587 }
1588
1589 const QMetaObject *QDeclarativeEnginePrivate::rawMetaObjectForType(int t) const
1590 {
1591     QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1592     if (iter != m_compositeTypes.end()) {
1593         return (*iter)->root;
1594     } else {
1595         QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1596         return type?type->baseMetaObject():0;
1597     }
1598 }
1599
1600 const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const
1601 {
1602     QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1603     if (iter != m_compositeTypes.end()) {
1604         return (*iter)->root;
1605     } else {
1606         QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1607         return type?type->metaObject():0;
1608     }
1609 }
1610
1611 bool QDeclarative_isFileCaseCorrect(const QString &fileName)
1612 {
1613 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
1614     QFileInfo info(fileName);
1615
1616     QString absolute = info.absoluteFilePath();
1617
1618 #if defined(Q_OS_MAC)
1619     QString canonical = info.canonicalFilePath();
1620 #elif defined(Q_OS_WIN32)
1621     wchar_t buffer[1024];
1622
1623     DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1624     if (rv == 0 || rv >= 1024) return true;
1625     rv = ::GetLongPathName(buffer, buffer, 1024);
1626     if (rv == 0 || rv >= 1024) return true;
1627
1628     QString canonical((QChar *)buffer);
1629 #endif
1630
1631     int absoluteLength = absolute.length();
1632     int canonicalLength = canonical.length();
1633
1634     int length = qMin(absoluteLength, canonicalLength);
1635     for (int ii = 0; ii < length; ++ii) {
1636         const QChar &a = absolute.at(absoluteLength - 1 - ii);
1637         const QChar &c = canonical.at(canonicalLength - 1 - ii);
1638
1639         if (a.toLower() != c.toLower())
1640             return true;
1641         if (a != c)
1642             return false;
1643     }
1644 #else
1645     Q_UNUSED(fileName)
1646 #endif
1647     return true;
1648 }
1649
1650 QT_END_NAMESPACE