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