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