Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativeengine.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdeclarativeengine_p.h"
43 #include "qdeclarativeengine.h"
44 #include "qdeclarativecomponentattached_p.h"
45
46 #include "qdeclarativecontext_p.h"
47 #include "qdeclarativecompiler_p.h"
48 #include "qdeclarative.h"
49 #include "qdeclarativecontext.h"
50 #include "qdeclarativeexpression.h"
51 #include "qdeclarativecomponent.h"
52 #include "qdeclarativebinding_p_p.h"
53 #include "qdeclarativevme_p.h"
54 #include <private/qdeclarativeenginedebugservice_p.h>
55 #include "qdeclarativestringconverters_p.h"
56 #include "qdeclarativexmlhttprequest_p.h"
57 #include "qdeclarativesqldatabase_p.h"
58 #include "qdeclarativescriptstring.h"
59 #include "qdeclarativeglobal_p.h"
60 #include "qdeclarativelistmodel_p.h"
61 #include "qdeclarativeworkerscript_p.h"
62 #include "qdeclarativecomponent_p.h"
63 #include "qdeclarativenetworkaccessmanagerfactory.h"
64 #include "qdeclarativeimageprovider.h"
65 #include "qdeclarativedirparser_p.h"
66 #include "qdeclarativeextensioninterface.h"
67 #include "qdeclarativelist_p.h"
68 #include "qdeclarativetypenamecache_p.h"
69 #include "qdeclarativenotifier_p.h"
70 #include <private/qdeclarativedebugtrace_p.h>
71 #include <private/qdeclarativeapplication_p.h>
72 #include <private/qv8debugservice_p.h>
73 #include <private/qdebugmessageservice_p.h>
74 #include "qdeclarativeincubator.h"
75 #include <private/qv8profilerservice_p.h>
76
77 #include <QtCore/qstandardpaths.h>
78 #include <QtCore/qsettings.h>
79
80 #include <QtCore/qmetaobject.h>
81 #include <QNetworkAccessManager>
82 #include <QDebug>
83 #include <QMetaObject>
84 #include <QtCore/qcoreapplication.h>
85 #include <QtCore/qdir.h>
86 #include <QtCore/qmutex.h>
87 #include <QtNetwork/qnetworkconfigmanager.h>
88
89 #include <private/qobject_p.h>
90
91 #include <private/qdeclarativelocale_p.h>
92
93 #ifdef Q_OS_WIN // for %APPDATA%
94 #include <qt_windows.h>
95 #include <qlibrary.h>
96 #include <windows.h>
97
98 #define CSIDL_APPDATA           0x001a  // <username>\Application Data
99 #endif
100
101 Q_DECLARE_METATYPE(QDeclarativeProperty)
102
103 QT_BEGIN_NAMESPACE
104
105 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
106 {
107     QDeclarativeEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
108     QDeclarativeValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
109 }
110
111 /*!
112   \qmlclass QtObject QObject
113   \ingroup qml-utility-elements
114   \since 4.7
115   \brief The QtObject element is the most basic element in QML.
116
117   The QtObject element is a non-visual element which contains only the
118   objectName property.
119
120   It can be useful to create a QtObject if you need an extremely
121   lightweight element to enclose a set of custom properties:
122
123   \snippet doc/src/snippets/declarative/qtobject.qml 0
124
125   It can also be useful for C++ integration, as it is just a plain
126   QObject. See the QObject documentation for further details.
127 */
128 /*!
129   \qmlproperty string QtObject::objectName
130   This property holds the QObject::objectName for this specific object instance.
131
132   This allows a C++ application to locate an item within a QML component
133   using the QObject::findChild() method. For example, the following C++
134   application locates the child \l Rectangle item and dynamically changes its
135   \c color value:
136
137     \qml
138     // MyRect.qml
139
140     import QtQuick 1.0
141
142     Item {
143         width: 200; height: 200
144
145         Rectangle {
146             anchors.fill: parent
147             color: "red"
148             objectName: "myRect"
149         }
150     }
151     \endqml
152
153     \code
154     // main.cpp
155
156     QDeclarativeView view;
157     view.setSource(QUrl::fromLocalFile("MyRect.qml"));
158     view.show();
159
160     QDeclarativeItem *item = view.rootObject()->findChild<QDeclarativeItem*>("myRect");
161     if (item)
162         item->setProperty("color", QColor(Qt::yellow));
163     \endcode
164 */
165
166 bool QDeclarativeEnginePrivate::qml_debugging_enabled = false;
167
168 void QDeclarativeEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
169 {
170     qmlRegisterType<QDeclarativeComponent>(uri,versionMajor,versionMinor,"Component");
171     qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
172     qmlRegisterType<QDeclarativeListElement>(uri, versionMajor, versionMinor,"ListElement");
173     qmlRegisterCustomType<QDeclarativeListModel>(uri, versionMajor, versionMinor,"ListModel", new QDeclarativeListModelParser);
174     qmlRegisterType<QDeclarativeWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
175 }
176
177 void QDeclarativeEnginePrivate::defineModule()
178 {
179     registerBaseTypes("QtQuick", 2, 0);
180     qmlRegisterType<QDeclarativeBinding>();
181     qmlRegisterUncreatableType<QDeclarativeApplication>("QtQuick",2,0,"Application", QDeclarativeApplication::tr("Application is an abstract class"));
182     qmlRegisterUncreatableType<QDeclarativeLocale>("QtQuick",2,0,"Locale",QDeclarativeEngine::tr("Locale cannot be instantiated.  Use Qt.locale()"));
183 }
184
185 /*!
186 \qmlclass Qt QDeclarativeEnginePrivate
187   \ingroup qml-utility-elements
188 \brief The QML global Qt object provides useful enums and functions from Qt.
189
190 \keyword QmlGlobalQtObject
191
192 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
193
194 The \c Qt object is a global object with utility functions, properties and enums.
195
196 It is not instantiable; to use it, call the members of the global \c Qt object directly.
197 For example:
198
199 \qml
200 import QtQuick 1.0
201
202 Text {
203     color: Qt.rgba(1, 0, 0, 1)
204     text: Qt.md5("hello, world")
205 }
206 \endqml
207
208
209 \section1 Enums
210
211 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
212 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
213
214
215 \section1 Types
216 The Qt object also contains helper functions for creating objects of specific
217 data types. This is primarily useful when setting the properties of an item
218 when the property has one of the following types:
219
220 \list
221 \o \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
222 \o \c rect - use \l{Qt::rect()}{Qt.rect()}
223 \o \c point - use \l{Qt::point()}{Qt.point()}
224 \o \c size - use \l{Qt::size()}{Qt.size()}
225 \o \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
226 \endlist
227
228 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
229
230 \section1 Date/Time Formatters
231
232 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
233
234 \list
235     \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
236     \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
237     \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
238 \endlist
239
240 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
241
242
243 \section1 Dynamic Object Creation
244 The following functions on the global object allow you to dynamically create QML
245 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
246 of their use.
247
248 \list
249     \o \l{Qt::createComponent()}{object Qt.createComponent(url)}
250     \o \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
251 \endlist
252 */
253
254
255 /*!
256     \qmlproperty object Qt::application
257     \since QtQuick 1.1
258
259     The \c application object provides access to global application state
260     properties shared by many QML components.
261
262     Its properties are:
263
264     \table
265     \row
266     \o \c application.active
267     \o
268     This read-only property indicates whether the application is the top-most and focused
269     application, and the user is able to interact with the application. The property
270     is false when the application is in the background, the device keylock or screen
271     saver is active, the screen backlight is turned off, or the global system dialog
272     is being displayed on top of the application. It can be used for stopping and
273     pausing animations, timers and active processing of data in order to save device
274     battery power and free device memory and processor load when the application is not
275     active.
276
277     \row
278     \o \c application.layoutDirection
279     \o
280     This read-only property can be used to query the default layout direction of the
281     application. On system start-up, the default layout direction depends on the
282     application's language. The property has a value of \c Qt.RightToLeft in locales
283     where text and graphic elements are read from right to left, and \c Qt.LeftToRight
284     where the reading direction flows from left to right. You can bind to this
285     property to customize your application layouts to support both layout directions.
286
287     Possible values are:
288
289     \list
290     \o Qt.LeftToRight - Text and graphics elements should be positioned
291                         from left to right.
292     \o Qt.RightToLeft - Text and graphics elements should be positioned
293                         from right to left.
294     \endlist
295
296     \row
297     \o \c application.inputPanel
298     \o
299     This read-only property allows access to application's QInputPanel object
300     and all its properties and slots. See the QInputPanel documentation for
301     further details.
302     \endtable
303
304     The following example uses the \c application object to indicate
305     whether the application is currently active:
306
307     \snippet doc/src/snippets/declarative/application.qml document
308
309 */
310
311
312 /*!
313 \qmlmethod object Qt::include(string url, jsobject callback)
314
315 Includes another JavaScript file. This method can only be used from within JavaScript files,
316 and not regular QML files.
317
318 This imports all functions from \a url into the current script's namespace.
319
320 Qt.include() returns an object that describes the status of the operation.  The object has
321 a single property, \c {status}, that is set to one of the following values:
322
323 \table
324 \header \o Symbol \o Value \o Description
325 \row \o result.OK \o 0 \o The include completed successfully.
326 \row \o result.LOADING \o 1 \o Data is being loaded from the network.
327 \row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url.
328 \row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code.
329 An additional \c exception property will be set in this case.
330 \endtable
331
332 The \c status property will be updated as the operation progresses.
333
334 If provided, \a callback is invoked when the operation completes.  The callback is passed
335 the same object as is returned from the Qt.include() call.
336 */
337 // Qt.include() is implemented in qv8include.cpp
338
339
340 QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
341 : propertyCapture(0), rootContext(0), isDebugging(false),
342   outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
343   cleanup(0), erroredBindings(0), inProgressCreations(0), 
344   workerScriptEngine(0), activeVME(0),
345   networkAccessManager(0), networkAccessManagerFactory(0),
346   scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
347   incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
348 {
349 }
350
351 QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate()
352 {
353     Q_ASSERT(inProgressCreations == 0);
354
355     while (cleanup) {
356         QDeclarativeCleanup *c = cleanup;
357         cleanup = c->next;
358         if (cleanup) cleanup->prev = &cleanup;
359         c->next = 0;
360         c->prev = 0;
361         c->clear();
362     }
363
364     doDeleteInEngineThread();
365
366     if (incubationController) incubationController->d = 0;
367     incubationController = 0;
368
369     delete rootContext;
370     rootContext = 0;
371
372     for(QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
373         (*iter)->release();
374     for(QHash<const QMetaObject *, QDeclarativePropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
375         (*iter)->release();
376     for(QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
377         (*iter)->release();
378     for(QHash<QDeclarativeMetaType::ModuleApi, QDeclarativeMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
379         delete (*iter)->qobjectApi;
380         delete *iter;
381     }
382 }
383
384 void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *o)
385 {
386     QObjectPrivate *p = QObjectPrivate::get(o);
387     if (p->declarativeData) {
388         QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
389         if (d->ownContext && d->context) {
390             d->context->destroy();
391             d->context = 0;
392         }
393     }
394 }
395
396 void QDeclarativeData::destroyed(QAbstractDeclarativeData *d, QObject *o)
397 {
398     static_cast<QDeclarativeData *>(d)->destroyed(o);
399 }
400
401 void QDeclarativeData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
402 {
403     static_cast<QDeclarativeData *>(d)->parentChanged(o, p);
404 }
405
406 void QDeclarativeData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
407 {
408     static_cast<QDeclarativeData *>(d)->objectNameChanged(o);
409 }
410
411 void QDeclarativeData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
412 {
413     QDeclarativeData *ddata = QDeclarativeData::get(object, false);
414     if (!ddata) return; // Probably being deleted
415
416     QDeclarativeNotifierEndpoint *ep = ddata->notify(index);
417     if (ep) QDeclarativeNotifier::emitNotify(ep);
418 }
419
420 void QDeclarativeEnginePrivate::init()
421 {
422     Q_Q(QDeclarativeEngine);
423
424     static bool firstTime = true;
425     if (firstTime) {
426         qmlRegisterType<QDeclarativeComponent>("QML", 1, 0, "Component");
427
428         firstTime = false;
429     }
430
431     qRegisterMetaType<QVariant>("QVariant");
432     qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString");
433     qRegisterMetaType<QJSValue>("QJSValue");
434     qRegisterMetaType<QDeclarativeComponent::Status>("QDeclarativeComponent::Status");
435     qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
436     qRegisterMetaType<QList<int> >("QList<int>");
437     qRegisterMetaType<QDeclarativeV8Handle>("QDeclarativeV8Handle");
438
439     QDeclarativeData::init();
440
441     v8engine()->setEngine(q);
442
443     rootContext = new QDeclarativeContext(q,true);
444
445     if (QCoreApplication::instance()->thread() == q->thread() &&
446         QDeclarativeEngineDebugService::isDebuggingEnabled()) {
447         isDebugging = true;
448         QDeclarativeEngineDebugService::instance()->addEngine(q);
449         QV8DebugService::initialize(v8engine());
450         QV8ProfilerService::initialize();
451         QDeclarativeDebugTrace::initialize();
452         QDebugMessageService::instance();
453     }
454
455     QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
456     offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
457                          QDir::separator() + QLatin1String("QML") +
458                          QDir::separator() + QLatin1String("OfflineStorage");
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     }
523
524     // if we are the parent of any of the qobject module api instances,
525     // we need to remove them from our internal list, in order to prevent
526     // a segfault in engine private dtor.
527     QList<QDeclarativeMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
528     QObject *currQObjectApi = 0;
529     QDeclarativeMetaType::ModuleApiInstance *currInstance = 0;
530     foreach (const QDeclarativeMetaType::ModuleApi &key, keys) {
531         currInstance = d->moduleApiInstances.value(key);
532         currQObjectApi = currInstance->qobjectApi;
533         if (this->children().contains(currQObjectApi)) {
534             delete currQObjectApi;
535             delete currInstance;
536             d->moduleApiInstances.remove(key);
537         }
538     }
539
540     // ensure we clean up QObjects with JS ownership
541     d->v8engine()->gc();
542
543     if (d->incubationController)
544         d->incubationController->d = 0;
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 QDeclarativeTextureFactory *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, data->columnNumber);
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 |= (1ULL << 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     d->offlineStoragePath = dir;
1549 }
1550
1551 QString QDeclarativeEngine::offlineStoragePath() const
1552 {
1553     Q_D(const QDeclarativeEngine);
1554     return d->offlineStoragePath;
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->copyAndAppend(q, mo);
1583         propertyCache.insert(mo, rv);
1584         return rv;
1585     }
1586 }
1587
1588 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
1589                                                                   QDeclarativeError &error)
1590 {
1591     QList<QDeclarativeType *> types;
1592
1593     int maxMinorVersion = 0;
1594
1595     const QMetaObject *metaObject = type->metaObject();
1596
1597     while (metaObject) {
1598         QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
1599                                                             type->majorVersion(), minorVersion);
1600         if (t) {
1601             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1602             types << t;
1603         } else {
1604             types << 0;
1605         }
1606
1607         metaObject = metaObject->superClass();
1608     }
1609
1610     if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1611         c->addref();
1612         typePropertyCache.insert(qMakePair(type, minorVersion), c);
1613         return c;
1614     }
1615
1616     QDeclarativePropertyCache *raw = cache(type->metaObject());
1617
1618     bool hasCopied = false;
1619
1620     for (int ii = 0; ii < types.count(); ++ii) {
1621         QDeclarativeType *currentType = types.at(ii);
1622         if (!currentType)
1623             continue;
1624
1625         int rev = currentType->metaObjectRevision();
1626         int moIndex = types.count() - 1 - ii;
1627
1628         if (raw->allowedRevisionCache[moIndex] != rev) {
1629             if (!hasCopied) {
1630                 raw = raw->copy();
1631                 hasCopied = true;
1632             }
1633             raw->allowedRevisionCache[moIndex] = rev;
1634         }
1635     }
1636
1637     // Test revision compatibility - the basic rule is:
1638     //    * Anything that is excluded, cannot overload something that is not excluded *
1639
1640     // Signals override:
1641     //    * other signals and methods of the same name.
1642     //    * properties named on<Signal Name>
1643     //    * automatic <property name>Changed notify signals
1644
1645     // Methods override:
1646     //    * other methods of the same name
1647
1648     // Properties override:
1649     //    * other elements of the same name
1650
1651     bool overloadError = false;
1652     QString overloadName;
1653
1654 #if 0
1655     for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1656          !overloadError && iter != raw->stringCache.end();
1657          ++iter) {
1658
1659         QDeclarativePropertyData *d = *iter;
1660         if (raw->isAllowedInRevision(d))
1661             continue; // Not excluded - no problems
1662
1663         // check that a regular "name" overload isn't happening
1664         QDeclarativePropertyData *current = d;
1665         while (!overloadError && current) {
1666             current = d->overrideData(current);
1667             if (current && raw->isAllowedInRevision(current))
1668                 overloadError = true;
1669         }
1670     }
1671 #endif
1672
1673     if (overloadError) {
1674         if (hasCopied) raw->release();
1675
1676         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."));
1677         return 0;
1678     }
1679
1680     if (!hasCopied) raw->addref();
1681     typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1682
1683     if (minorVersion != maxMinorVersion) {
1684         raw->addref();
1685         typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1686     }
1687
1688     return raw;
1689 }
1690
1691 QDeclarativeMetaType::ModuleApiInstance *
1692 QDeclarativeEnginePrivate::moduleApiInstance(const QDeclarativeMetaType::ModuleApi &module)
1693 {
1694     Locker locker(this);
1695
1696     QDeclarativeMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1697     if (!a) {
1698         a = new QDeclarativeMetaType::ModuleApiInstance;
1699         a->scriptCallback = module.script;
1700         a->qobjectCallback = module.qobject;
1701         moduleApiInstances.insert(module, a);
1702     }
1703
1704     return a;
1705 }
1706
1707 bool QDeclarativeEnginePrivate::isQObject(int t)
1708 {
1709     Locker locker(this);
1710     return m_compositeTypes.contains(t) || QDeclarativeMetaType::isQObject(t);
1711 }
1712
1713 QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1714 {
1715     Locker locker(this);
1716     int t = v.userType();
1717     if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1718         if (ok) *ok = true;
1719         return *(QObject **)(v.constData());
1720     } else {
1721         return QDeclarativeMetaType::toQObject(v, ok);
1722     }
1723 }
1724
1725 QDeclarativeMetaType::TypeCategory QDeclarativeEnginePrivate::typeCategory(int t) const
1726 {
1727     Locker locker(this);
1728     if (m_compositeTypes.contains(t))
1729         return QDeclarativeMetaType::Object;
1730     else if (m_qmlLists.contains(t))
1731         return QDeclarativeMetaType::List;
1732     else
1733         return QDeclarativeMetaType::typeCategory(t);
1734 }
1735
1736 bool QDeclarativeEnginePrivate::isList(int t) const
1737 {
1738     Locker locker(this);
1739     return m_qmlLists.contains(t) || QDeclarativeMetaType::isList(t);
1740 }
1741
1742 int QDeclarativeEnginePrivate::listType(int t) const
1743 {
1744     Locker locker(this);
1745     QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1746     if (iter != m_qmlLists.end())
1747         return *iter;
1748     else
1749         return QDeclarativeMetaType::listType(t);
1750 }
1751
1752 const QMetaObject *QDeclarativeEnginePrivate::rawMetaObjectForType(int t) const
1753 {
1754     Locker locker(this);
1755     QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1756     if (iter != m_compositeTypes.end()) {
1757         return (*iter)->root;
1758     } else {
1759         QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1760         return type?type->baseMetaObject():0;
1761     }
1762 }
1763
1764 const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const
1765 {
1766     Locker locker(this);
1767     QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1768     if (iter != m_compositeTypes.end()) {
1769         return (*iter)->root;
1770     } else {
1771         QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1772         return type?type->metaObject():0;
1773     }
1774 }
1775
1776 void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data)
1777 {
1778     QByteArray name = data->root->className();
1779
1780     QByteArray ptr = name + '*';
1781     QByteArray lst = "QDeclarativeListProperty<" + name + '>';
1782
1783     int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1784                                            voidptr_constructor);
1785     int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1786                                            voidptr_constructor);
1787
1788     data->addref();
1789
1790     Locker locker(this);
1791     m_qmlLists.insert(lst_type, ptr_type);
1792     m_compositeTypes.insert(ptr_type, data);
1793 }
1794
1795 bool QDeclarative_isFileCaseCorrect(const QString &fileName)
1796 {
1797 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1798     QFileInfo info(fileName);
1799     const QString absolute = info.absoluteFilePath();
1800
1801 #if defined(Q_OS_MAC)
1802     const QString canonical = info.canonicalFilePath();
1803 #elif defined(Q_OS_WIN)
1804     wchar_t buffer[1024];
1805
1806     DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1807     if (rv == 0 || rv >= 1024) return true;
1808     rv = ::GetLongPathName(buffer, buffer, 1024);
1809     if (rv == 0 || rv >= 1024) return true;
1810
1811     const QString canonical = QString::fromWCharArray(buffer);
1812 #endif
1813
1814     const int absoluteLength = absolute.length();
1815     const int canonicalLength = canonical.length();
1816
1817     const int length = qMin(absoluteLength, canonicalLength);
1818     for (int ii = 0; ii < length; ++ii) {
1819         const QChar &a = absolute.at(absoluteLength - 1 - ii);
1820         const QChar &c = canonical.at(canonicalLength - 1 - ii);
1821
1822         if (a.toLower() != c.toLower())
1823             return true;
1824         if (a != c)
1825             return false;
1826     }
1827 #else
1828     Q_UNUSED(fileName)
1829 #endif
1830     return true;
1831 }
1832
1833 /*!
1834     \fn QDeclarativeEngine *qmlEngine(const QObject *object)
1835     \relates QDeclarativeEngine
1836
1837     Returns the QDeclarativeEngine associated with \a object, if any.  This is equivalent to
1838     QDeclarativeEngine::contextForObject(object)->engine(), but more efficient.
1839 */
1840
1841 /*!
1842     \fn QDeclarativeContext *qmlContext(const QObject *object)
1843     \relates QDeclarativeEngine
1844
1845     Returns the QDeclarativeContext associated with \a object, if any.  This is equivalent to
1846     QDeclarativeEngine::contextForObject(object).
1847 */
1848
1849 QT_END_NAMESPACE