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