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