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