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