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