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