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