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