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