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