Declarative: Fix MSVC and g++ warnings
[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/qsgitemsmodule_p.h>
87 #include <private/qsgparticlesmodule_p.h>
88
89 #ifdef Q_OS_WIN // for %APPDATA%
90 #include <qt_windows.h>
91 #include <qlibrary.h>
92 #include <windows.h>
93
94 #define CSIDL_APPDATA           0x001a  // <username>\Application Data
95 #endif
96
97 Q_DECLARE_METATYPE(QDeclarativeProperty)
98
99 QT_BEGIN_NAMESPACE
100
101 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
102 {
103     QDeclarativeEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
104     QDeclarativeValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
105     QDeclarativeUtilModule::registerBaseTypes(uri, versionMajor, versionMinor);
106 }
107
108 /*!
109   \qmlclass QtObject QObject
110   \ingroup qml-utility-elements
111   \since 4.7
112   \brief The QtObject element is the most basic element in QML.
113
114   The QtObject element is a non-visual element which contains only the
115   objectName property.
116
117   It can be useful to create a QtObject if you need an extremely
118   lightweight element to enclose a set of custom properties:
119
120   \snippet doc/src/snippets/declarative/qtobject.qml 0
121
122   It can also be useful for C++ integration, as it is just a plain
123   QObject. See the QObject documentation for further details.
124 */
125 /*!
126   \qmlproperty string 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 : captureProperties(false), 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         QSGItemsModule::defineModule();
348         QSGParticlesModule::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
547 /*! \fn void QDeclarativeEngine::quit()
548     This signal is emitted when the QML loaded by the engine would like to quit.
549  */
550
551 /*! \fn void QDeclarativeEngine::warnings(const QList<QDeclarativeError> &warnings)
552     This signal is emitted when \a warnings messages are generated by QML.
553  */
554
555 /*!
556   Clears the engine's internal component cache.
557
558   Normally the QDeclarativeEngine caches components loaded from qml
559   files.  This method clears this cache and forces the component to be
560   reloaded.
561  */
562 void QDeclarativeEngine::clearComponentCache()
563 {
564     Q_D(QDeclarativeEngine);
565     d->typeLoader.clearCache();
566 }
567
568 /*!
569   Returns the engine's root context.
570
571   The root context is automatically created by the QDeclarativeEngine.
572   Data that should be available to all QML component instances
573   instantiated by the engine should be put in the root context.
574
575   Additional data that should only be available to a subset of
576   component instances should be added to sub-contexts parented to the
577   root context.
578 */
579 QDeclarativeContext *QDeclarativeEngine::rootContext() const
580 {
581     Q_D(const QDeclarativeEngine);
582     return d->rootContext;
583 }
584
585 /*!
586   Sets the \a factory to use for creating QNetworkAccessManager(s).
587
588   QNetworkAccessManager is used for all network access by QML.  By
589   implementing a factory it is possible to create custom
590   QNetworkAccessManager with specialized caching, proxy and cookie
591   support.
592
593   The factory must be set before executing the engine.
594 */
595 void QDeclarativeEngine::setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *factory)
596 {
597     Q_D(QDeclarativeEngine);
598     QMutexLocker locker(&d->mutex);
599     d->networkAccessManagerFactory = factory;
600 }
601
602 /*!
603   Returns the current QDeclarativeNetworkAccessManagerFactory.
604
605   \sa setNetworkAccessManagerFactory()
606 */
607 QDeclarativeNetworkAccessManagerFactory *QDeclarativeEngine::networkAccessManagerFactory() const
608 {
609     Q_D(const QDeclarativeEngine);
610     return d->networkAccessManagerFactory;
611 }
612
613 void QDeclarativeEnginePrivate::registerFinalizeCallback(QObject *obj, int index) 
614 {
615     if (activeVME) {
616         activeVME->finalizeCallbacks.append(qMakePair(QDeclarativeGuard<QObject>(obj), index));
617     } else {
618         void *args[] = { 0 };
619         QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
620     }
621 }
622
623 QNetworkAccessManager *QDeclarativeEnginePrivate::createNetworkAccessManager(QObject *parent) const
624 {
625     QMutexLocker locker(&mutex);
626     QNetworkAccessManager *nam;
627     if (networkAccessManagerFactory) {
628         nam = networkAccessManagerFactory->create(parent);
629     } else {
630         nam = new QNetworkAccessManager(parent);
631     }
632
633     return nam;
634 }
635
636 QNetworkAccessManager *QDeclarativeEnginePrivate::getNetworkAccessManager() const
637 {
638     Q_Q(const QDeclarativeEngine);
639     if (!networkAccessManager)
640         networkAccessManager = createNetworkAccessManager(const_cast<QDeclarativeEngine*>(q));
641     return networkAccessManager;
642 }
643
644 /*!
645   Returns a common QNetworkAccessManager which can be used by any QML
646   element instantiated by this engine.
647
648   If a QDeclarativeNetworkAccessManagerFactory has been set and a
649   QNetworkAccessManager has not yet been created, the
650   QDeclarativeNetworkAccessManagerFactory will be used to create the
651   QNetworkAccessManager; otherwise the returned QNetworkAccessManager
652   will have no proxy or cache set.
653
654   \sa setNetworkAccessManagerFactory()
655 */
656 QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
657 {
658     Q_D(const QDeclarativeEngine);
659     return d->getNetworkAccessManager();
660 }
661
662 /*!
663
664   Sets the \a provider to use for images requested via the \e
665   image: url scheme, with host \a providerId. The QDeclarativeEngine
666   takes ownership of \a provider.
667
668   Image providers enable support for pixmap and threaded image
669   requests. See the QDeclarativeImageProvider documentation for details on
670   implementing and using image providers.
671
672   All required image providers should be added to the engine before any
673   QML sources files are loaded.
674
675   \sa removeImageProvider()
676 */
677 void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativeImageProvider *provider)
678 {
679     Q_D(QDeclarativeEngine);
680     QMutexLocker locker(&d->mutex);
681     d->imageProviders.insert(providerId.toLower(), QSharedPointer<QDeclarativeImageProvider>(provider));
682 }
683
684 /*!
685   Returns the QDeclarativeImageProvider set for \a providerId.
686
687   Returns the provider if it was found; otherwise returns 0.
688 */
689 QDeclarativeImageProvider *QDeclarativeEngine::imageProvider(const QString &providerId) const
690 {
691     Q_D(const QDeclarativeEngine);
692     QMutexLocker locker(&d->mutex);
693     return d->imageProviders.value(providerId).data();
694 }
695
696 /*!
697   Removes the QDeclarativeImageProvider for \a providerId.
698
699   \sa addImageProvider()
700 */
701 void QDeclarativeEngine::removeImageProvider(const QString &providerId)
702 {
703     Q_D(QDeclarativeEngine);
704     QMutexLocker locker(&d->mutex);
705     d->imageProviders.take(providerId);
706 }
707
708 QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProviderType(const QUrl &url)
709 {
710     QMutexLocker locker(&mutex);
711     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
712     locker.unlock();
713     if (provider)
714         return provider->imageType();
715     return QDeclarativeImageProvider::Invalid;
716 }
717
718 QSGTexture *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
719 {
720     QMutexLocker locker(&mutex);
721     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
722     locker.unlock();
723     if (provider) {
724         QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
725         return provider->requestTexture(imageId, size, req_size);
726     }
727     return 0;
728 }
729
730 QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
731 {
732     QMutexLocker locker(&mutex);
733     QImage image;
734     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
735     locker.unlock();
736     if (provider) {
737         QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
738         image = provider->requestImage(imageId, size, req_size);
739     }
740     return image;
741 }
742
743 QPixmap QDeclarativeEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
744 {
745     QMutexLocker locker(&mutex);
746     QPixmap pixmap;
747     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
748     locker.unlock();
749     if (provider) {
750         QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
751         pixmap = provider->requestPixmap(imageId, size, req_size);
752     }
753     return pixmap;
754 }
755
756 /*!
757   Return the base URL for this engine.  The base URL is only used to
758   resolve components when a relative URL is passed to the
759   QDeclarativeComponent constructor.
760
761   If a base URL has not been explicitly set, this method returns the
762   application's current working directory.
763
764   \sa setBaseUrl()
765 */
766 QUrl QDeclarativeEngine::baseUrl() const
767 {
768     Q_D(const QDeclarativeEngine);
769     if (d->baseUrl.isEmpty()) {
770         return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
771     } else {
772         return d->baseUrl;
773     }
774 }
775
776 /*!
777   Set the  base URL for this engine to \a url.
778
779   \sa baseUrl()
780 */
781 void QDeclarativeEngine::setBaseUrl(const QUrl &url)
782 {
783     Q_D(QDeclarativeEngine);
784     d->baseUrl = url;
785 }
786
787 /*!
788   Returns true if warning messages will be output to stderr in addition
789   to being emitted by the warnings() signal, otherwise false.
790
791   The default value is true.
792 */
793 bool QDeclarativeEngine::outputWarningsToStandardError() const
794 {
795     Q_D(const QDeclarativeEngine);
796     return d->outputWarningsToStdErr;
797 }
798
799 /*!
800   Set whether warning messages will be output to stderr to \a enabled.
801
802   If \a enabled is true, any warning messages generated by QML will be
803   output to stderr and emitted by the warnings() signal.  If \a enabled
804   is false, on the warnings() signal will be emitted.  This allows
805   applications to handle warning output themselves.
806
807   The default value is true.
808 */
809 void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled)
810 {
811     Q_D(QDeclarativeEngine);
812     d->outputWarningsToStdErr = enabled;
813 }
814
815 /*!
816   Attempt to free unused memory.
817 */
818 void QDeclarativeEngine::collectGarbage()
819 {
820     QV8Engine::gc();
821 }
822
823 /*!
824   Returns the QDeclarativeContext for the \a object, or 0 if no
825   context has been set.
826
827   When the QDeclarativeEngine instantiates a QObject, the context is
828   set automatically.
829   */
830 QDeclarativeContext *QDeclarativeEngine::contextForObject(const QObject *object)
831 {
832     if(!object)
833         return 0;
834
835     QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
836
837     QDeclarativeData *data =
838         static_cast<QDeclarativeData *>(priv->declarativeData);
839
840     if (!data)
841         return 0;
842     else if (data->outerContext)
843         return data->outerContext->asQDeclarativeContext();
844     else
845         return 0;
846 }
847
848 /*!
849   Sets the QDeclarativeContext for the \a object to \a context.
850   If the \a object already has a context, a warning is
851   output, but the context is not changed.
852
853   When the QDeclarativeEngine instantiates a QObject, the context is
854   set automatically.
855  */
856 void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContext *context)
857 {
858     if (!object || !context)
859         return;
860
861     QDeclarativeData *data = QDeclarativeData::get(object, true);
862     if (data->context) {
863         qWarning("QDeclarativeEngine::setContextForObject(): Object already has a QDeclarativeContext");
864         return;
865     }
866
867     QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
868     contextData->addObject(object);
869 }
870
871 /*!
872   \enum QDeclarativeEngine::ObjectOwnership
873
874   Ownership controls whether or not QML automatically destroys the
875   QObject when the object is garbage collected by the JavaScript
876   engine.  The two ownership options are:
877
878   \value CppOwnership The object is owned by C++ code, and will
879   never be deleted by QML.  The JavaScript destroy() method cannot be
880   used on objects with CppOwnership.  This option is similar to
881   QScriptEngine::QtOwnership.
882
883   \value JavaScriptOwnership The object is owned by JavaScript.
884   When the object is returned to QML as the return value of a method
885   call or property access, QML will delete the object if there are no
886   remaining JavaScript references to it and it has no
887   QObject::parent().  This option is similar to
888   QScriptEngine::ScriptOwnership.
889
890   Generally an application doesn't need to set an object's ownership
891   explicitly.  QML uses a heuristic to set the default object
892   ownership.  By default, an object that is created by QML has
893   JavaScriptOwnership.  The exception to this are the root objects
894   created by calling QDeclarativeCompnent::create() or
895   QDeclarativeComponent::beginCreate() which have CppOwnership by
896   default.  The ownership of these root-level objects is considered to
897   have been transferred to the C++ caller.
898
899   Objects not-created by QML have CppOwnership by default.  The
900   exception to this is objects returned from a C++ method call.  The
901   ownership of these objects is passed to JavaScript.
902
903   Calling setObjectOwnership() overrides the default ownership
904   heuristic used by QML.
905 */
906
907 /*!
908   Sets the \a ownership of \a object.
909 */
910 void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
911 {
912     if (!object)
913         return;
914
915     QDeclarativeData *ddata = QDeclarativeData::get(object, true);
916     if (!ddata)
917         return;
918
919     ddata->indestructible = (ownership == CppOwnership)?true:false;
920     ddata->explicitIndestructibleSet = true;
921 }
922
923 /*!
924   Returns the ownership of \a object.
925 */
926 QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object)
927 {
928     if (!object)
929         return CppOwnership;
930
931     QDeclarativeData *ddata = QDeclarativeData::get(object, false);
932     if (!ddata)
933         return CppOwnership;
934     else
935         return ddata->indestructible?CppOwnership:JavaScriptOwnership;
936 }
937
938 bool QDeclarativeEngine::event(QEvent *e)
939 {
940     Q_D(QDeclarativeEngine);
941     if (e->type() == QEvent::User) 
942         d->doDeleteInEngineThread();
943
944     return QJSEngine::event(e);
945 }
946
947 void QDeclarativeEnginePrivate::doDeleteInEngineThread()
948 {
949     QFieldList<Deletable, &Deletable::next> list;
950     mutex.lock();
951     list.copyAndClear(toDeleteInEngineThread);
952     mutex.unlock();
953
954     while (Deletable *d = list.takeFirst())
955         delete d;
956 }
957
958 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
959 {
960     QDeclarativeData *data = QDeclarativeData::get(object);
961
962     if (data && data->deferredComponent) {
963         if (QDeclarativeDebugService::isDebuggingEnabled()) {
964             QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
965             QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
966             QString typeName = type ? type->qmlTypeName() : QString::fromUtf8(object->metaObject()->className());
967             QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, typeName);
968             if (data->outerContext)
969                 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, data->outerContext->url, data->lineNumber);
970         }
971         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine);
972
973         QDeclarativeComponentPrivate::ConstructionState state;
974         QDeclarativeComponentPrivate::beginDeferred(ep, object, &state);
975
976         data->deferredComponent->release();
977         data->deferredComponent = 0;
978
979         QDeclarativeComponentPrivate::complete(ep, &state);
980         QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
981     }
982 }
983
984 QDeclarativeContext *qmlContext(const QObject *obj)
985 {
986     return QDeclarativeEngine::contextForObject(obj);
987 }
988
989 QDeclarativeEngine *qmlEngine(const QObject *obj)
990 {
991     QDeclarativeData *data = QDeclarativeData::get(obj, false);
992     if (!data || !data->context)
993         return 0;
994     return data->context->engine;
995 }
996
997 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
998 {
999     QDeclarativeData *data = QDeclarativeData::get(object);
1000     if (!data)
1001         return 0; // Attached properties are only on objects created by QML
1002
1003     QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1004     if (rv || !create)
1005         return rv;
1006
1007     QDeclarativeAttachedPropertiesFunc pf = QDeclarativeMetaType::attachedPropertiesFuncById(id);
1008     if (!pf)
1009         return 0;
1010
1011     rv = pf(const_cast<QObject *>(object));
1012
1013     if (rv)
1014         data->attachedProperties()->insert(id, rv);
1015
1016     return rv;
1017 }
1018
1019 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1020                                      const QMetaObject *attachedMetaObject, bool create)
1021 {
1022     if (*idCache == -1)
1023         *idCache = QDeclarativeMetaType::attachedPropertiesFuncId(attachedMetaObject);
1024
1025     if (*idCache == -1 || !object)
1026         return 0;
1027
1028     return qmlAttachedPropertiesObjectById(*idCache, object, create);
1029 }
1030
1031 QDeclarativeDebuggingEnabler::QDeclarativeDebuggingEnabler()
1032 {
1033 #ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
1034     if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
1035         qWarning("Qml debugging is enabled. Only use this in a safe environment!");
1036     }
1037     QDeclarativeEnginePrivate::qml_debugging_enabled = true;
1038 #endif
1039 }
1040
1041
1042 class QDeclarativeDataExtended {
1043 public:
1044     QDeclarativeDataExtended();
1045     ~QDeclarativeDataExtended();
1046
1047     QHash<int, QObject *> attachedProperties;
1048     QDeclarativeNotifier objectNameNotifier;
1049 };
1050
1051 QDeclarativeDataExtended::QDeclarativeDataExtended()
1052 {
1053 }
1054
1055 QDeclarativeDataExtended::~QDeclarativeDataExtended()
1056 {
1057 }
1058
1059 void QDeclarativeData::NotifyList::layout(QDeclarativeNotifierEndpoint *endpoint)
1060 {
1061     if (endpoint->next)
1062         layout(endpoint->next);
1063
1064     int index = endpoint->sourceSignal;
1065     index = qMin(index, 0xFFFF - 1);
1066
1067     endpoint->next = notifies[index];
1068     if (endpoint->next) endpoint->next->prev = &endpoint->next;
1069     endpoint->prev = &notifies[index];
1070     notifies[index] = endpoint;
1071 }
1072
1073 void QDeclarativeData::NotifyList::layout()
1074 {
1075     Q_ASSERT(maximumTodoIndex >= notifiesSize);
1076
1077     if (todo) {
1078         QDeclarativeNotifierEndpoint **old = notifies;
1079         const int reallocSize = (maximumTodoIndex + 1) * sizeof(QDeclarativeNotifierEndpoint*);
1080         notifies = (QDeclarativeNotifierEndpoint**)realloc(notifies, reallocSize);
1081         const int memsetSize = (maximumTodoIndex - notifiesSize + 1) * 
1082                                sizeof(QDeclarativeNotifierEndpoint*);
1083         memset(notifies + notifiesSize, 0, memsetSize);
1084
1085         if (notifies != old) {
1086             for (int ii = 0; ii < notifiesSize; ++ii)
1087                 if (notifies[ii]) 
1088                     notifies[ii]->prev = &notifies[ii];
1089         }
1090
1091         notifiesSize = maximumTodoIndex + 1;
1092
1093         layout(todo);
1094     }
1095
1096     maximumTodoIndex = 0;
1097     todo = 0;
1098 }
1099
1100 void QDeclarativeData::addNotify(int index, QDeclarativeNotifierEndpoint *endpoint)
1101 {
1102     if (!notifyList) {
1103         notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1104         notifyList->connectionMask = 0;
1105         notifyList->maximumTodoIndex = 0;
1106         notifyList->notifiesSize = 0;
1107         notifyList->todo = 0;
1108         notifyList->notifies = 0;
1109     }
1110
1111     Q_ASSERT(!endpoint->isConnected());
1112
1113     index = qMin(index, 0xFFFF - 1);
1114     notifyList->connectionMask |= (1 << (quint64(index) % 64));
1115
1116     if (index < notifyList->notifiesSize) {
1117
1118         endpoint->next = notifyList->notifies[index];
1119         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1120         endpoint->prev = &notifyList->notifies[index];
1121         notifyList->notifies[index] = endpoint;
1122
1123     } else {
1124         notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1125
1126         endpoint->next = notifyList->todo;
1127         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1128         endpoint->prev = &notifyList->todo;
1129         notifyList->todo = endpoint;
1130     }
1131 }
1132
1133 QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const
1134 {
1135     if (!extendedData) extendedData = new QDeclarativeDataExtended;
1136     return &extendedData->objectNameNotifier;
1137 }
1138
1139 QHash<int, QObject *> *QDeclarativeData::attachedProperties() const
1140 {
1141     if (!extendedData) extendedData = new QDeclarativeDataExtended;
1142     return &extendedData->attachedProperties;
1143 }
1144
1145 void QDeclarativeData::destroyed(QObject *object)
1146 {
1147     if (deferredComponent)
1148         deferredComponent->release();
1149
1150     if (nextContextObject)
1151         nextContextObject->prevContextObject = prevContextObject;
1152     if (prevContextObject)
1153         *prevContextObject = nextContextObject;
1154
1155     QDeclarativeAbstractBinding *binding = bindings;
1156     while (binding) {
1157         QDeclarativeAbstractBinding *next = binding->m_nextBinding;
1158         binding->m_prevBinding = 0;
1159         binding->m_nextBinding = 0;
1160         binding->destroy();
1161         binding = next;
1162     }
1163
1164     if (bindingBits)
1165         free(bindingBits);
1166
1167     if (propertyCache)
1168         propertyCache->release();
1169
1170     if (ownContext && context)
1171         context->destroy();
1172
1173     while (guards) {
1174         QDeclarativeGuard<QObject> *guard = static_cast<QDeclarativeGuard<QObject> *>(guards);
1175         *guard = (QObject *)0;
1176         guard->objectDestroyed(object);
1177     }
1178
1179     if (notifyList) {
1180         while (notifyList->todo)
1181             notifyList->todo->disconnect();
1182         for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1183             while (QDeclarativeNotifierEndpoint *ep = notifyList->notifies[ii])
1184                 ep->disconnect();
1185         }
1186         free(notifyList->notifies);
1187         free(notifyList);
1188     }
1189
1190     if (extendedData)
1191         delete extendedData;
1192
1193     v8object.Clear(); // The WeakReference handler will clean the actual handle
1194
1195     if (ownMemory)
1196         delete this;
1197 }
1198
1199 void QDeclarativeData::parentChanged(QObject *object, QObject *parent)
1200 {
1201     Q_UNUSED(object);
1202     Q_UNUSED(parent);
1203 }
1204
1205 void QDeclarativeData::objectNameChanged(QObject *)
1206 {
1207     if (extendedData) objectNameNotifier()->notify();
1208 }
1209
1210 bool QDeclarativeData::hasBindingBit(int bit) const
1211 {
1212     if (bindingBitsSize > bit)
1213         return bindingBits[bit / 32] & (1 << (bit % 32));
1214     else
1215         return false;
1216 }
1217
1218 void QDeclarativeData::clearBindingBit(int bit)
1219 {
1220     if (bindingBitsSize > bit)
1221         bindingBits[bit / 32] &= ~(1 << (bit % 32));
1222 }
1223
1224 void QDeclarativeData::setBindingBit(QObject *obj, int bit)
1225 {
1226     if (bindingBitsSize <= bit) {
1227         int props = obj->metaObject()->propertyCount();
1228         Q_ASSERT(bit < props);
1229
1230         int arraySize = (props + 31) / 32;
1231         int oldArraySize = bindingBitsSize / 32;
1232
1233         bindingBits = (quint32 *)realloc(bindingBits,
1234                                          arraySize * sizeof(quint32));
1235
1236         memset(bindingBits + oldArraySize,
1237                0x00,
1238                sizeof(quint32) * (arraySize - oldArraySize));
1239
1240         bindingBitsSize = arraySize * 32;
1241     }
1242
1243     bindingBits[bit / 32] |= (1 << (bit % 32));
1244 }
1245
1246 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1247 {
1248     if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1249         if (url.authority().isEmpty())
1250             return QLatin1Char(':') + url.path();
1251         return QString();
1252     }
1253     return url.toLocalFile();
1254 }
1255
1256
1257 static QString toLocalFile(const QString &url)
1258 {
1259     if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1260         return QString();
1261
1262     QString file = url.mid(7);
1263
1264     //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1265
1266     // magic for drives on windows
1267     if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1268         file.remove(0, 1);
1269
1270     return file;
1271 }
1272
1273 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1274 {
1275     if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1276         if (url.length() > 4)
1277             return QLatin1Char(':') + url.mid(4);
1278         return QString();
1279     }
1280
1281     return toLocalFile(url);
1282 }
1283
1284 void QDeclarativeEnginePrivate::sendQuit()
1285 {
1286     Q_Q(QDeclarativeEngine);
1287     emit q->quit();
1288     if (q->receivers(SIGNAL(quit())) == 0) {
1289         qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it.");
1290     }
1291 }
1292
1293 static void dumpwarning(const QDeclarativeError &error)
1294 {
1295     qWarning().nospace() << qPrintable(error.toString());
1296 }
1297
1298 static void dumpwarning(const QList<QDeclarativeError> &errors)
1299 {
1300     for (int ii = 0; ii < errors.count(); ++ii)
1301         dumpwarning(errors.at(ii));
1302 }
1303
1304 void QDeclarativeEnginePrivate::warning(const QDeclarativeError &error)
1305 {
1306     Q_Q(QDeclarativeEngine);
1307     q->warnings(QList<QDeclarativeError>() << error);
1308     if (outputWarningsToStdErr)
1309         dumpwarning(error);
1310 }
1311
1312 void QDeclarativeEnginePrivate::warning(const QList<QDeclarativeError> &errors)
1313 {
1314     Q_Q(QDeclarativeEngine);
1315     q->warnings(errors);
1316     if (outputWarningsToStdErr)
1317         dumpwarning(errors);
1318 }
1319
1320 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QDeclarativeError &error)
1321 {
1322     if (engine)
1323         QDeclarativeEnginePrivate::get(engine)->warning(error);
1324     else
1325         dumpwarning(error);
1326 }
1327
1328 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QList<QDeclarativeError> &error)
1329 {
1330     if (engine)
1331         QDeclarativeEnginePrivate::get(engine)->warning(error);
1332     else
1333         dumpwarning(error);
1334 }
1335
1336 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QDeclarativeError &error)
1337 {
1338     if (engine)
1339         engine->warning(error);
1340     else
1341         dumpwarning(error);
1342 }
1343
1344 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QList<QDeclarativeError> &error)
1345 {
1346     if (engine)
1347         engine->warning(error);
1348     else
1349         dumpwarning(error);
1350 }
1351
1352 /*
1353    This function should be called prior to evaluation of any js expression,
1354    so that scarce resources are not freed prematurely (eg, if there is a
1355    nested javascript expression).
1356  */
1357 void QDeclarativeEnginePrivate::referenceScarceResources()
1358 {
1359     scarceResourcesRefCount += 1;
1360 }
1361
1362 /*
1363    This function should be called after evaluation of the js expression is
1364    complete, and so the scarce resources may be freed safely.
1365  */
1366 void QDeclarativeEnginePrivate::dereferenceScarceResources()
1367 {
1368     Q_ASSERT(scarceResourcesRefCount > 0);
1369     scarceResourcesRefCount -= 1;
1370
1371     // if the refcount is zero, then evaluation of the "top level"
1372     // expression must have completed.  We can safely release the
1373     // scarce resources.
1374     if (scarceResourcesRefCount == 0) {
1375         // iterate through the list and release them all.
1376         // note that the actual SRD is owned by the JS engine,
1377         // so we cannot delete the SRD; but we can free the
1378         // memory used by the variant in the SRD.
1379         while (ScarceResourceData *sr = scarceResources.first()) {
1380             sr->data = QVariant();
1381             scarceResources.remove(sr);
1382         }
1383     }
1384 }
1385
1386 /*!
1387   Adds \a path as a directory where the engine searches for
1388   installed modules in a URL-based directory structure.
1389   The \a path may be a local filesystem directory or a URL.
1390
1391   The newly added \a path will be first in the importPathList().
1392
1393   \sa setImportPathList(), {QML Modules}
1394 */
1395 void QDeclarativeEngine::addImportPath(const QString& path)
1396 {
1397     Q_D(QDeclarativeEngine);
1398     d->importDatabase.addImportPath(path);
1399 }
1400
1401 /*!
1402   Returns the list of directories where the engine searches for
1403   installed modules in a URL-based directory structure.
1404
1405   For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1406   imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look
1407   in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1408   provided by that module. A \c qmldir file is required for defining the
1409   type version mapping and possibly declarative extensions plugins.
1410
1411   By default, the list contains the directory of the application executable,
1412   paths specified in the \c QML_IMPORT_PATH environment variable,
1413   and the builtin \c ImportsPath from QLibraryInfo.
1414
1415   \sa addImportPath() setImportPathList()
1416 */
1417 QStringList QDeclarativeEngine::importPathList() const
1418 {
1419     Q_D(const QDeclarativeEngine);
1420     return d->importDatabase.importPathList();
1421 }
1422
1423 /*!
1424   Sets \a paths as the list of directories where the engine searches for
1425   installed modules in a URL-based directory structure.
1426
1427   By default, the list contains the directory of the application executable,
1428   paths specified in the \c QML_IMPORT_PATH environment variable,
1429   and the builtin \c ImportsPath from QLibraryInfo.
1430
1431   \sa importPathList() addImportPath()
1432   */
1433 void QDeclarativeEngine::setImportPathList(const QStringList &paths)
1434 {
1435     Q_D(QDeclarativeEngine);
1436     d->importDatabase.setImportPathList(paths);
1437 }
1438
1439
1440 /*!
1441   Adds \a path as a directory where the engine searches for
1442   native plugins for imported modules (referenced in the \c qmldir file).
1443
1444   By default, the list contains only \c .,  i.e. the engine searches
1445   in the directory of the \c qmldir file itself.
1446
1447   The newly added \a path will be first in the pluginPathList().
1448
1449   \sa setPluginPathList()
1450 */
1451 void QDeclarativeEngine::addPluginPath(const QString& path)
1452 {
1453     Q_D(QDeclarativeEngine);
1454     d->importDatabase.addPluginPath(path);
1455 }
1456
1457
1458 /*!
1459   Returns the list of directories where the engine searches for
1460   native plugins for imported modules (referenced in the \c qmldir file).
1461
1462   By default, the list contains only \c .,  i.e. the engine searches
1463   in the directory of the \c qmldir file itself.
1464
1465   \sa addPluginPath() setPluginPathList()
1466 */
1467 QStringList QDeclarativeEngine::pluginPathList() const
1468 {
1469     Q_D(const QDeclarativeEngine);
1470     return d->importDatabase.pluginPathList();
1471 }
1472
1473 /*!
1474   Sets the list of directories where the engine searches for
1475   native plugins for imported modules (referenced in the \c qmldir file)
1476   to \a paths.
1477
1478   By default, the list contains only \c .,  i.e. the engine searches
1479   in the directory of the \c qmldir file itself.
1480
1481   \sa pluginPathList() addPluginPath()
1482   */
1483 void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
1484 {
1485     Q_D(QDeclarativeEngine);
1486     d->importDatabase.setPluginPathList(paths);
1487 }
1488
1489 /*!
1490   Imports the plugin named \a filePath with the \a uri provided.
1491   Returns true if the plugin was successfully imported; otherwise returns false.
1492
1493   On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1494
1495   The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1496 */
1497 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
1498 {
1499     Q_D(QDeclarativeEngine);
1500     return d->importDatabase.importPlugin(filePath, uri, errors);
1501 }
1502
1503 /*!
1504   Imports the plugin named \a filePath with the \a uri provided.
1505   Returns true if the plugin was successfully imported; otherwise returns false.
1506
1507   On failure and if non-null, *\a errorString will be set to a message describing the failure.
1508
1509   The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1510 */
1511 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1512 {
1513     Q_D(QDeclarativeEngine);
1514     QList<QDeclarativeError> errors;
1515     bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1516     if (!errors.isEmpty()) {
1517         QString builtError;
1518         for (int i = 0; i < errors.size(); ++i) {
1519             builtError = QString(QLatin1String("%1\n        %2"))
1520                     .arg(builtError)
1521                     .arg(errors.at(i).toString());
1522         }
1523         *errorString = builtError;
1524     }
1525     return retn;
1526 }
1527
1528 /*!
1529   \property QDeclarativeEngine::offlineStoragePath
1530   \brief the directory for storing offline user data
1531
1532   Returns the directory where SQL and other offline
1533   storage is placed.
1534
1535   QDeclarativeWebView and the SQL databases created with openDatabase()
1536   are stored here.
1537
1538   The default is QML/OfflineStorage in the platform-standard
1539   user application data directory.
1540
1541   Note that the path may not currently exist on the filesystem, so
1542   callers wanting to \e create new files at this location should create
1543   it first - see QDir::mkpath().
1544 */
1545 void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
1546 {
1547     Q_D(QDeclarativeEngine);
1548     qt_qmlsqldatabase_setOfflineStoragePath(d->v8engine(), dir);
1549 }
1550
1551 QString QDeclarativeEngine::offlineStoragePath() const
1552 {
1553     Q_D(const QDeclarativeEngine);
1554     return qt_qmlsqldatabase_getOfflineStoragePath(d->v8engine());
1555 }
1556
1557 static void voidptr_destructor(void *v)
1558 {
1559     void **ptr = (void **)v;
1560     delete ptr;
1561 }
1562
1563 static void *voidptr_constructor(const void *v)
1564 {
1565     if (!v) {
1566         return new void*;
1567     } else {
1568         return new void*(*(void **)v);
1569     }
1570 }
1571
1572 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo)
1573 {
1574     Q_Q(QDeclarativeEngine);
1575
1576     if (!mo->superClass()) {
1577         QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo);
1578         propertyCache.insert(mo, rv);
1579         return rv;
1580     } else {
1581         QDeclarativePropertyCache *super = cache(mo->superClass());
1582         QDeclarativePropertyCache *rv = super->copy(mo->propertyCount() + mo->methodCount() - 
1583                                                     mo->superClass()->propertyCount() - 
1584                                                     mo->superClass()->methodCount());
1585         rv->append(q, mo);
1586         propertyCache.insert(mo, rv);
1587         return rv;
1588     }
1589 }
1590
1591 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
1592                                                                   QDeclarativeError &error)
1593 {
1594     QList<QDeclarativeType *> types;
1595
1596     int maxMinorVersion = 0;
1597
1598     const QMetaObject *metaObject = type->metaObject();
1599
1600     while (metaObject) {
1601         QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
1602                                                             type->majorVersion(), minorVersion);
1603         if (t) {
1604             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1605             types << t;
1606         } else {
1607             types << 0;
1608         }
1609
1610         metaObject = metaObject->superClass();
1611     }
1612
1613     if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1614         c->addref();
1615         typePropertyCache.insert(qMakePair(type, minorVersion), c);
1616         return c;
1617     }
1618
1619     QDeclarativePropertyCache *raw = cache(type->metaObject());
1620
1621     bool hasCopied = false;
1622
1623     for (int ii = 0; ii < types.count(); ++ii) {
1624         QDeclarativeType *currentType = types.at(ii);
1625         if (!currentType)
1626             continue;
1627
1628         int rev = currentType->metaObjectRevision();
1629         int moIndex = types.count() - 1 - ii;
1630
1631         if (raw->allowedRevisionCache[moIndex] != rev) {
1632             if (!hasCopied) {
1633                 raw = raw->copy();
1634                 hasCopied = true;
1635             }
1636             raw->allowedRevisionCache[moIndex] = rev;
1637         }
1638     }
1639
1640     // Test revision compatibility - the basic rule is:
1641     //    * Anything that is excluded, cannot overload something that is not excluded *
1642
1643     // Signals override:
1644     //    * other signals and methods of the same name.
1645     //    * properties named on<Signal Name>
1646     //    * automatic <property name>Changed notify signals
1647
1648     // Methods override:
1649     //    * other methods of the same name
1650
1651     // Properties override:
1652     //    * other elements of the same name
1653
1654     bool overloadError = false;
1655     QString overloadName;
1656
1657 #if 0
1658     for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1659          !overloadError && iter != raw->stringCache.end();
1660          ++iter) {
1661
1662         QDeclarativePropertyCache::Data *d = *iter;
1663         if (raw->isAllowedInRevision(d))
1664             continue; // Not excluded - no problems
1665
1666         // check that a regular "name" overload isn't happening
1667         QDeclarativePropertyCache::Data *current = d;
1668         while (!overloadError && current) {
1669             current = d->overrideData(current);
1670             if (current && raw->isAllowedInRevision(current))
1671                 overloadError = true;
1672         }
1673     }
1674 #endif
1675
1676     if (overloadError) {
1677         if (hasCopied) raw->release();
1678
1679         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."));
1680         return 0;
1681     }
1682
1683     if (!hasCopied) raw->addref();
1684     typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1685
1686     if (minorVersion != maxMinorVersion) {
1687         raw->addref();
1688         typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1689     }
1690
1691     return raw;
1692 }
1693
1694 QDeclarativeMetaType::ModuleApiInstance *
1695 QDeclarativeEnginePrivate::moduleApiInstance(const QDeclarativeMetaType::ModuleApi &module)
1696 {
1697     Locker locker(this);
1698
1699     QDeclarativeMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1700     if (!a) {
1701         a = new QDeclarativeMetaType::ModuleApiInstance;
1702         a->scriptCallback = module.script;
1703         a->qobjectCallback = module.qobject;
1704         moduleApiInstances.insert(module, a);
1705     }
1706
1707     return a;
1708 }
1709
1710 bool QDeclarativeEnginePrivate::isQObject(int t)
1711 {
1712     Locker locker(this);
1713     return m_compositeTypes.contains(t) || QDeclarativeMetaType::isQObject(t);
1714 }
1715
1716 QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1717 {
1718     Locker locker(this);
1719     int t = v.userType();
1720     if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1721         if (ok) *ok = true;
1722         return *(QObject **)(v.constData());
1723     } else {
1724         return QDeclarativeMetaType::toQObject(v, ok);
1725     }
1726 }
1727
1728 QDeclarativeMetaType::TypeCategory QDeclarativeEnginePrivate::typeCategory(int t) const
1729 {
1730     Locker locker(this);
1731     if (m_compositeTypes.contains(t))
1732         return QDeclarativeMetaType::Object;
1733     else if (m_qmlLists.contains(t))
1734         return QDeclarativeMetaType::List;
1735     else
1736         return QDeclarativeMetaType::typeCategory(t);
1737 }
1738
1739 bool QDeclarativeEnginePrivate::isList(int t) const
1740 {
1741     Locker locker(this);
1742     return m_qmlLists.contains(t) || QDeclarativeMetaType::isList(t);
1743 }
1744
1745 int QDeclarativeEnginePrivate::listType(int t) const
1746 {
1747     Locker locker(this);
1748     QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1749     if (iter != m_qmlLists.end())
1750         return *iter;
1751     else
1752         return QDeclarativeMetaType::listType(t);
1753 }
1754
1755 const QMetaObject *QDeclarativeEnginePrivate::rawMetaObjectForType(int t) const
1756 {
1757     Locker locker(this);
1758     QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1759     if (iter != m_compositeTypes.end()) {
1760         return (*iter)->root;
1761     } else {
1762         QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1763         return type?type->baseMetaObject():0;
1764     }
1765 }
1766
1767 const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const
1768 {
1769     Locker locker(this);
1770     QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1771     if (iter != m_compositeTypes.end()) {
1772         return (*iter)->root;
1773     } else {
1774         QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1775         return type?type->metaObject():0;
1776     }
1777 }
1778
1779 void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data)
1780 {
1781     QByteArray name = data->root->className();
1782
1783     QByteArray ptr = name + '*';
1784     QByteArray lst = "QDeclarativeListProperty<" + name + '>';
1785
1786     int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1787                                            voidptr_constructor);
1788     int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1789                                            voidptr_constructor);
1790
1791     data->addref();
1792
1793     Locker locker(this);
1794     m_qmlLists.insert(lst_type, ptr_type);
1795     m_compositeTypes.insert(ptr_type, data);
1796 }
1797
1798 bool QDeclarative_isFileCaseCorrect(const QString &fileName)
1799 {
1800 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
1801     QFileInfo info(fileName);
1802
1803     QString absolute = info.absoluteFilePath();
1804
1805 #if defined(Q_OS_MAC)
1806     QString canonical = info.canonicalFilePath();
1807 #elif defined(Q_OS_WIN32)
1808     wchar_t buffer[1024];
1809
1810     DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1811     if (rv == 0 || rv >= 1024) return true;
1812     rv = ::GetLongPathName(buffer, buffer, 1024);
1813     if (rv == 0 || rv >= 1024) return true;
1814
1815     QString canonical((QChar *)buffer);
1816 #endif
1817
1818     int absoluteLength = absolute.length();
1819     int canonicalLength = canonical.length();
1820
1821     int length = qMin(absoluteLength, canonicalLength);
1822     for (int ii = 0; ii < length; ++ii) {
1823         const QChar &a = absolute.at(absoluteLength - 1 - ii);
1824         const QChar &c = canonical.at(canonicalLength - 1 - ii);
1825
1826         if (a.toLower() != c.toLower())
1827             return true;
1828         if (a != c)
1829             return false;
1830     }
1831 #else
1832     Q_UNUSED(fileName)
1833 #endif
1834     return true;
1835 }
1836
1837 /*!
1838     \fn QDeclarativeEngine *qmlEngine(const QObject *object)
1839     \relates QDeclarativeEngine
1840
1841     Returns the QDeclarativeEngine associated with \a object, if any.  This is equivalent to
1842     QDeclarativeEngine::contextForObject(object)->engine(), but more efficient.
1843 */
1844
1845 /*!
1846     \fn QDeclarativeContext *qmlContext(const QObject *object)
1847     \relates QDeclarativeEngine
1848
1849     Returns the QDeclarativeContext associated with \a object, if any.  This is equivalent to
1850     QDeclarativeEngine::contextForObject(object).
1851 */
1852
1853 QT_END_NAMESPACE