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