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