1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
72 #include <private/qqmlboundsignal_p.h>
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtCore/qthread.h>
84 #include <private/qthread_p.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
87 #include <private/qobject_p.h>
88 #include <private/qmetaobject_p.h>
90 #include <private/qqmllocale_p.h>
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
97 #define CSIDL_APPDATA 0x001a // <username>\Application Data
100 Q_DECLARE_METATYPE(QQmlProperty)
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
106 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107 QQmlEnginePrivate::registerQtQuick2Types(uri, versionMajor, versionMinor);
108 QQmlValueTypeFactory::registerValueTypes(uri, versionMajor, versionMinor);
113 \instantiates QObject
114 \inqmlmodule QtQuick 2
115 \ingroup qml-utility-elements
116 \brief A basic QML type
118 The QtObject type is a non-visual element which contains only the
121 It can be useful to create a QtObject if you need an extremely
122 lightweight type to enclose a set of custom properties:
124 \snippet qml/qtobject.qml 0
126 It can also be useful for C++ integration, as it is just a plain
127 QObject. See the QObject documentation for further details.
130 \qmlproperty string QtObject::objectName
131 This property holds the QObject::objectName for this specific object instance.
133 This allows a C++ application to locate an item within a QML component
134 using the QObject::findChild() method. For example, the following C++
135 application locates the child \l Rectangle item and dynamically changes its
144 width: 200; height: 200
158 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
161 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
163 item->setProperty("color", QColor(Qt::yellow));
167 bool QQmlEnginePrivate::qml_debugging_enabled = false;
169 // these types are part of the QML language
170 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
172 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
173 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
177 // These QtQuick types' implementation resides in the QtQml module
178 void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
180 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor, "ListElement");
181 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor, "ListModel", new QQuickListModelParser);
182 qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
185 void QQmlEnginePrivate::defineQtQuick2Module()
187 // register the base types into the QtQuick namespace
188 registerBaseTypes("QtQuick",2,0);
190 // register the QtQuick2 types which are implemented in the QtQml module.
191 registerQtQuick2Types("QtQuick",2,0);
192 qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
197 \class QQmlImageProviderBase
198 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
202 Image providers must be registered with the QML engine. The only information the QML
203 engine knows about image providers is the type of image data they provide. To use an
204 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
205 to a QQuickImageProvider pointer.
207 \sa QQuickImageProvider, QQuickTextureFactory
211 \enum QQmlImageProviderBase::ImageType
213 Defines the type of image supported by this image provider.
215 \value Image The Image Provider provides QImage images.
216 The QQuickImageProvider::requestImage() method will be called for all image requests.
217 \value Pixmap The Image Provider provides QPixmap images.
218 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
219 \value Texture The Image Provider provides QSGTextureProvider based images.
220 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
224 \enum QQmlImageProviderBase::Flag
226 Defines specific requirements or features of this image provider.
228 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
229 run in a separate thread, which allows the provider to spend as much time as needed
230 on producing the image without blocking the main thread.
234 QQmlImageProviderBase::QQmlImageProviderBase()
239 QQmlImageProviderBase::~QQmlImageProviderBase()
246 \instantiates QQmlEnginePrivate
247 \ingroup qml-utility-elements
248 \brief The QML global Qt object provides useful enums and functions from Qt.
250 \keyword QmlGlobalQtObject
252 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
254 The \c Qt object is a global object with utility functions, properties and enums.
256 It is not instantiable; to use it, call the members of the global \c Qt object directly.
263 color: Qt.rgba(1, 0, 0, 1)
264 text: Qt.md5("hello, world")
271 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
272 the \l Qt::LeftButton and \l Qt::RightButton enumeration values as \c Qt.LeftButton and \c Qt.RightButton.
277 The Qt object also contains helper functions for creating objects of specific
278 data types. This is primarily useful when setting the properties of an item
279 when the property has one of the following types:
281 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
282 \li \c point - use \l{Qt::point()}{Qt.point()}
283 \li \c size - use \l{Qt::size()}{Qt.size()}
286 If the QtQuick module has been imported, the following helper functions for
287 creating objects of specific data types are also available for clients to use:
289 \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()}
290 \li \c font - use \l{Qt::font()}{Qt.font()}
291 \li \c vector2d - use \l{Qt::vector2d()}{Qt.vector2d()}
292 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
293 \li \c vector4d - use \l{Qt::vector4d()}{Qt.vector4d()}
294 \li \c quaternion - use \l{Qt::quaternion()}{Qt.quaternion()}
295 \li \c matrix4x4 - use \l{Qt::matrix4x4()}{Qt.matrix4x4()}
298 There are also string based constructors for these types. See \l{qtqml-typesystem-basictypes.html}{QML Basic Types} for more information.
300 \section1 Date/Time Formatters
302 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
305 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
306 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
307 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
310 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
313 \section1 Dynamic Object Creation
314 The following functions on the global object allow you to dynamically create QML
315 items from files or strings. See \l{Dynamic QML Object Creation from JavaScript} for an overview
319 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
320 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
324 \section1 Other Functions
326 The following functions are also on the Qt object.
329 \li \l{Qt::quit()}{Qt.quit()}
330 \li \l{Qt::md5()}{Qt.md5(string)}
331 \li \l{Qt::btoa()}{string Qt.btoa(string)}
332 \li \l{Qt::atob()}{string Qt.atob(string)}
333 \li \l{Qt::binding()}{object Qt.binding(function)}
334 \li \l{Qt::locale()}{object Qt.locale()}
335 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
336 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
337 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
342 \qmlproperty object Qt::application
345 The \c application object provides access to global application state
346 properties shared by many QML components.
352 \li \c application.active
354 This read-only property indicates whether the application is the top-most and focused
355 application, and the user is able to interact with the application. The property
356 is false when the application is in the background, the device keylock or screen
357 saver is active, the screen backlight is turned off, or the global system dialog
358 is being displayed on top of the application. It can be used for stopping and
359 pausing animations, timers and active processing of data in order to save device
360 battery power and free device memory and processor load when the application is not
364 \li \c application.layoutDirection
366 This read-only property can be used to query the default layout direction of the
367 application. On system start-up, the default layout direction depends on the
368 application's language. The property has a value of \c Qt.RightToLeft in locales
369 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
370 where the reading direction flows from left to right. You can bind to this
371 property to customize your application layouts to support both layout directions.
376 \li Qt.LeftToRight - Text and graphics elements should be positioned
378 \li Qt.RightToLeft - Text and graphics elements should be positioned
384 The following example uses the \c application object to indicate
385 whether the application is currently active:
387 \snippet qml/application.qml document
391 \qmlproperty object Qt::inputMethod
394 The \c inputMethod object allows access to application's QInputMethod object
395 and all its properties and slots. See the QInputMethod documentation for
401 \qmlmethod object Qt::include(string url, jsobject callback)
403 Includes another JavaScript file. This method can only be used from within JavaScript files,
404 and not regular QML files.
406 This imports all functions from \a url into the current script's namespace.
408 Qt.include() returns an object that describes the status of the operation. The object has
409 a single property, \c {status}, that is set to one of the following values:
412 \header \li Symbol \li Value \li Description
413 \row \li result.OK \li 0 \li The include completed successfully.
414 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
415 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
416 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
417 An additional \c exception property will be set in this case.
420 The \c status property will be updated as the operation progresses.
422 If provided, \a callback is invoked when the operation completes. The callback is passed
423 the same object as is returned from the Qt.include() call.
425 // Qt.include() is implemented in qv8include.cpp
428 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
429 : propertyCapture(0), rootContext(0), isDebugging(false),
430 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
431 cleanup(0), erroredBindings(0), inProgressCreations(0),
432 workerScriptEngine(0), activeVME(0),
433 networkAccessManager(0), networkAccessManagerFactory(0),
434 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
435 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
439 QQmlEnginePrivate::~QQmlEnginePrivate()
441 if (inProgressCreations)
442 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
445 QQmlCleanup *c = cleanup;
447 if (cleanup) cleanup->prev = &cleanup;
453 doDeleteInEngineThread();
455 if (incubationController) incubationController->d = 0;
456 incubationController = 0;
461 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
463 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
465 for (QHash<QQmlMetaType::SingletonType, QQmlMetaType::SingletonInstance *>::Iterator iter = singletonTypeInstances.begin(); iter != singletonTypeInstances.end(); ++iter) {
466 delete (*iter)->qobjectApi;
469 for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
470 iter.value()->isRegisteredWithEngine = false;
473 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
475 QObjectPrivate *p = QObjectPrivate::get(o);
476 if (p->declarativeData) {
477 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
478 if (d->ownContext && d->context) {
479 d->context->destroy();
483 // Mark this object as in the process of deletion to
484 // prevent it resolving in bindings
485 QQmlData::markAsDeleted(o);
487 // Disconnect the notifiers now - during object destruction this would be too late, since
488 // the disconnect call wouldn't be able to call disconnectNotify(), as it isn't possible to
489 // get the metaobject anymore.
490 d->disconnectNotifiers();
494 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
496 static_cast<QQmlData *>(d)->destroyed(o);
499 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
501 static_cast<QQmlData *>(d)->parentChanged(o, p);
504 class QQmlThreadNotifierProxyObject : public QObject
507 QPointer<QObject> target;
509 virtual int qt_metacall(QMetaObject::Call, int methodIndex, void **a) {
513 QMetaMethod method = target->metaObject()->method(methodIndex);
514 Q_ASSERT(method.methodType() == QMetaMethod::Signal);
515 int signalIndex = QMetaObjectPrivate::signalIndex(method);
516 QQmlData *ddata = QQmlData::get(target, false);
517 QQmlNotifierEndpoint *ep = ddata->notify(signalIndex);
518 if (ep) QQmlNotifier::emitNotify(ep, a);
526 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
528 QQmlData *ddata = QQmlData::get(object, false);
529 if (!ddata) return; // Probably being deleted
531 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
532 // that they're exposed to. However, to make writing "worker objects" that calculate data
533 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
534 // QQmlEngine to emit signals from a different thread. These signals are then automatically
535 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
536 // by the qqmlecmascript::threadSignal() autotest.
537 if (ddata->notifyList &&
538 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
540 if (!QObjectPrivate::get(object)->threadData->thread)
543 QMetaMethod m = QMetaObjectPrivate::signal(object->metaObject(), index);
544 QList<QByteArray> parameterTypes = m.parameterTypes();
546 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
547 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
549 types[0] = 0; // return type
550 args[0] = 0; // return value
552 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
553 const QByteArray &typeName = parameterTypes.at(ii);
554 if (typeName.endsWith('*'))
555 types[ii + 1] = QMetaType::VoidStar;
557 types[ii + 1] = QMetaType::type(typeName);
559 if (!types[ii + 1]) {
560 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
561 "(Make sure '%s' is registered using qRegisterMetaType().)",
562 typeName.constData(), typeName.constData());
568 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
571 QMetaCallEvent *ev = new QMetaCallEvent(m.methodIndex(), 0, 0, object, index,
572 parameterTypes.count() + 1, types, args);
574 QQmlThreadNotifierProxyObject *mpo = new QQmlThreadNotifierProxyObject;
575 mpo->target = object;
576 mpo->moveToThread(QObjectPrivate::get(object)->threadData->thread);
577 QCoreApplication::postEvent(mpo, ev);
580 QQmlNotifierEndpoint *ep = ddata->notify(index);
581 if (ep) QQmlNotifier::emitNotify(ep, a);
585 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
587 return static_cast<QQmlData *>(d)->endpointCount(index);
590 bool QQmlData::isSignalConnected(QAbstractDeclarativeData *d, const QObject *, int index)
592 return static_cast<QQmlData *>(d)->signalHasEndpoint(index);
595 int QQmlData::endpointCount(int index)
598 QQmlNotifierEndpoint *ep = notify(index);
609 void QQmlData::markAsDeleted(QObject *o)
611 QQmlData::setQueuedForDeletion(o);
613 QObjectPrivate *p = QObjectPrivate::get(o);
614 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
615 QQmlData::markAsDeleted(*it);
619 void QQmlData::setQueuedForDeletion(QObject *object)
622 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
623 if (!priv->wasDeleted && priv->declarativeData) {
624 QQmlData *ddata = QQmlData::get(object, false);
625 if (ddata->ownContext && ddata->context)
626 ddata->context->emitDestruction();
627 ddata->isQueuedForDeletion = true;
633 void QQmlEnginePrivate::init()
637 static bool firstTime = true;
639 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
640 registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
646 qRegisterMetaType<QVariant>("QVariant");
647 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
648 qRegisterMetaType<QJSValue>("QJSValue");
649 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
650 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
651 qRegisterMetaType<QList<int> >("QList<int>");
652 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
654 v8engine()->setEngine(q);
656 rootContext = new QQmlContext(q,true);
658 if (QCoreApplication::instance()->thread() == q->thread() &&
659 QQmlEngineDebugService::isDebuggingEnabled()) {
661 QQmlEngineDebugService::instance()->addEngine(q);
662 QV8DebugService::initialize(v8engine());
663 QV8ProfilerService::initialize();
664 QQmlProfilerService::initialize();
665 QDebugMessageService::instance();
668 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
669 if (!dataLocation.isEmpty())
670 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
671 + QDir::separator() + QLatin1String("QML")
672 + QDir::separator() + QLatin1String("OfflineStorage");
675 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
678 if (!workerScriptEngine)
679 workerScriptEngine = new QQuickWorkerScriptEngine(q);
680 return workerScriptEngine;
687 \brief The QQmlEngine class provides an environment for instantiating QML components.
690 Each QML component is instantiated in a QQmlContext.
691 QQmlContext's are essential for passing data to QML
692 components. In QML, contexts are arranged hierarchically and this
693 hierarchy is managed by the QQmlEngine.
695 Prior to creating any QML components, an application must have
696 created a QQmlEngine to gain access to a QML context. The
697 following example shows how to create a simple Text item.
701 QQmlComponent component(&engine);
702 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
703 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
705 //add item to view, etc
709 In this case, the Text item will be created in the engine's
710 \l {QQmlEngine::rootContext()}{root context}.
712 Note that the QtQuick 1 version is called QDeclarativeEngine.
714 \sa QQmlComponent, QQmlContext
718 Create a new QQmlEngine with the given \a parent.
720 QQmlEngine::QQmlEngine(QObject *parent)
721 : QJSEngine(*new QQmlEnginePrivate(this), parent)
728 Destroys the QQmlEngine.
730 Any QQmlContext's created on this engine will be
731 invalidated, but not destroyed (unless they are parented to the
734 QQmlEngine::~QQmlEngine()
737 if (d->isDebugging) {
738 QQmlEngineDebugService::instance()->remEngine(this);
741 // Emit onDestruction signals for the root context before
742 // we destroy the contexts, engine, Singleton Types etc. that
743 // may be required to handle the destruction signal.
744 QQmlContextData::get(rootContext())->emitDestruction();
746 // if we are the parent of any of the qobject singleton type instances,
747 // we need to remove them from our internal list, in order to prevent
748 // a segfault in engine private dtor.
749 QList<QQmlMetaType::SingletonType> keys = d->singletonTypeInstances.keys();
750 QObject *currQObjectApi = 0;
751 QQmlMetaType::SingletonInstance *currInstance = 0;
752 foreach (const QQmlMetaType::SingletonType &key, keys) {
753 currInstance = d->singletonTypeInstances.value(key);
754 currQObjectApi = currInstance->qobjectApi;
755 if (this->children().contains(currQObjectApi)) {
756 delete currQObjectApi;
758 d->singletonTypeInstances.remove(key);
762 if (d->incubationController)
763 d->incubationController->d = 0;
766 /*! \fn void QQmlEngine::quit()
767 This signal is emitted when the QML loaded by the engine would like to quit.
770 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
771 This signal is emitted when \a warnings messages are generated by QML.
775 Clears the engine's internal component cache.
777 This function causes the property metadata of all components previously
778 loaded by the engine to be destroyed. All previously loaded components and
779 the property bindings for all extant objects created from those components will
782 This function returns the engine to a state where it does not contain any loaded
783 component data. This may be useful in order to reload a smaller subset of the
784 previous component set, or to load a new version of a previously loaded component.
786 Once the component cache has been cleared, components must be loaded before
787 any new objects can be created.
789 \sa trimComponentCache()
791 void QQmlEngine::clearComponentCache()
794 d->typeLoader.clearCache();
798 Trims the engine's internal component cache.
800 This function causes the property metadata of any loaded components which are
801 not currently in use to be destroyed.
803 A component is considered to be in use if there are any extant instances of
804 the component itself, any instances of other components that use the component,
805 or any objects instantiated by any of those components.
807 \sa clearComponentCache()
809 void QQmlEngine::trimComponentCache()
812 d->typeLoader.trimCache();
816 Returns the engine's root context.
818 The root context is automatically created by the QQmlEngine.
819 Data that should be available to all QML component instances
820 instantiated by the engine should be put in the root context.
822 Additional data that should only be available to a subset of
823 component instances should be added to sub-contexts parented to the
826 QQmlContext *QQmlEngine::rootContext() const
828 Q_D(const QQmlEngine);
829 return d->rootContext;
833 Sets the \a factory to use for creating QNetworkAccessManager(s).
835 QNetworkAccessManager is used for all network access by QML. By
836 implementing a factory it is possible to create custom
837 QNetworkAccessManager with specialized caching, proxy and cookie
840 The factory must be set before executing the engine.
842 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
845 QMutexLocker locker(&d->mutex);
846 d->networkAccessManagerFactory = factory;
850 Returns the current QQmlNetworkAccessManagerFactory.
852 \sa setNetworkAccessManagerFactory()
854 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
856 Q_D(const QQmlEngine);
857 return d->networkAccessManagerFactory;
860 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
863 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
865 void *args[] = { 0 };
866 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
870 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
872 QMutexLocker locker(&mutex);
873 QNetworkAccessManager *nam;
874 if (networkAccessManagerFactory) {
875 nam = networkAccessManagerFactory->create(parent);
877 nam = new QNetworkAccessManager(parent);
883 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
885 Q_Q(const QQmlEngine);
886 if (!networkAccessManager)
887 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
888 return networkAccessManager;
892 Returns a common QNetworkAccessManager which can be used by any QML
893 type instantiated by this engine.
895 If a QQmlNetworkAccessManagerFactory has been set and a
896 QNetworkAccessManager has not yet been created, the
897 QQmlNetworkAccessManagerFactory will be used to create the
898 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
899 will have no proxy or cache set.
901 \sa setNetworkAccessManagerFactory()
903 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
905 Q_D(const QQmlEngine);
906 return d->getNetworkAccessManager();
911 Sets the \a provider to use for images requested via the \e
912 image: url scheme, with host \a providerId. The QQmlEngine
913 takes ownership of \a provider.
915 Image providers enable support for pixmap and threaded image
916 requests. See the QQuickImageProvider documentation for details on
917 implementing and using image providers.
919 All required image providers should be added to the engine before any
920 QML sources files are loaded.
922 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
924 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
927 QMutexLocker locker(&d->mutex);
928 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
932 Returns the image provider set for \a providerId.
934 Returns the provider if it was found; otherwise returns 0.
936 \sa QQuickImageProvider
938 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
940 Q_D(const QQmlEngine);
941 QMutexLocker locker(&d->mutex);
942 return d->imageProviders.value(providerId).data();
946 Removes the image provider for \a providerId.
948 \sa addImageProvider(), QQuickImageProvider
950 void QQmlEngine::removeImageProvider(const QString &providerId)
953 QMutexLocker locker(&d->mutex);
954 d->imageProviders.take(providerId);
958 Return the base URL for this engine. The base URL is only used to
959 resolve components when a relative URL is passed to the
960 QQmlComponent constructor.
962 If a base URL has not been explicitly set, this method returns the
963 application's current working directory.
967 QUrl QQmlEngine::baseUrl() const
969 Q_D(const QQmlEngine);
970 if (d->baseUrl.isEmpty()) {
971 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
978 Set the base URL for this engine to \a url.
982 void QQmlEngine::setBaseUrl(const QUrl &url)
989 Returns true if warning messages will be output to stderr in addition
990 to being emitted by the warnings() signal, otherwise false.
992 The default value is true.
994 bool QQmlEngine::outputWarningsToStandardError() const
996 Q_D(const QQmlEngine);
997 return d->outputWarningsToStdErr;
1001 Set whether warning messages will be output to stderr to \a enabled.
1003 If \a enabled is true, any warning messages generated by QML will be
1004 output to stderr and emitted by the warnings() signal. If \a enabled
1005 is false, on the warnings() signal will be emitted. This allows
1006 applications to handle warning output themselves.
1008 The default value is true.
1010 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
1013 d->outputWarningsToStdErr = enabled;
1017 Returns the QQmlContext for the \a object, or 0 if no
1018 context has been set.
1020 When the QQmlEngine instantiates a QObject, the context is
1023 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
1028 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
1031 static_cast<QQmlData *>(priv->declarativeData);
1035 else if (data->outerContext)
1036 return data->outerContext->asQQmlContext();
1042 Sets the QQmlContext for the \a object to \a context.
1043 If the \a object already has a context, a warning is
1044 output, but the context is not changed.
1046 When the QQmlEngine instantiates a QObject, the context is
1049 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1051 if (!object || !context)
1054 QQmlData *data = QQmlData::get(object, true);
1055 if (data->context) {
1056 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1060 QQmlContextData *contextData = QQmlContextData::get(context);
1061 contextData->addObject(object);
1065 \enum QQmlEngine::ObjectOwnership
1067 Ownership controls whether or not QML automatically destroys the
1068 QObject when the object is garbage collected by the JavaScript
1069 engine. The two ownership options are:
1071 \value CppOwnership The object is owned by C++ code, and will
1072 never be deleted by QML. The JavaScript destroy() method cannot be
1073 used on objects with CppOwnership. This option is similar to
1074 QScriptEngine::QtOwnership.
1076 \value JavaScriptOwnership The object is owned by JavaScript.
1077 When the object is returned to QML as the return value of a method
1078 call or property access, QML will track it, and delete the object
1079 if there are no remaining JavaScript references to it and it has no
1080 QObject::parent(). An object tracked by one QQmlEngine
1081 will be deleted during that QQmlEngine's destructor, and thus
1082 JavaScript references between objects with JavaScriptOwnership from
1083 two different engines will not be valid after the deletion of one of
1084 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1086 Generally an application doesn't need to set an object's ownership
1087 explicitly. QML uses a heuristic to set the default object
1088 ownership. By default, an object that is created by QML has
1089 JavaScriptOwnership. The exception to this are the root objects
1090 created by calling QQmlComponent::create() or
1091 QQmlComponent::beginCreate() which have CppOwnership by
1092 default. The ownership of these root-level objects is considered to
1093 have been transferred to the C++ caller.
1095 Objects not-created by QML have CppOwnership by default. The
1096 exception to this is objects returned from a C++ method call. The
1097 ownership of these objects is passed to JavaScript.
1099 Calling setObjectOwnership() overrides the default ownership
1100 heuristic used by QML.
1104 Sets the \a ownership of \a object.
1106 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1111 QQmlData *ddata = QQmlData::get(object, true);
1115 ddata->indestructible = (ownership == CppOwnership)?true:false;
1116 ddata->explicitIndestructibleSet = true;
1120 Returns the ownership of \a object.
1122 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1125 return CppOwnership;
1127 QQmlData *ddata = QQmlData::get(object, false);
1129 return CppOwnership;
1131 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1134 bool QQmlEngine::event(QEvent *e)
1137 if (e->type() == QEvent::User)
1138 d->doDeleteInEngineThread();
1140 return QJSEngine::event(e);
1143 void QQmlEnginePrivate::doDeleteInEngineThread()
1145 QFieldList<Deletable, &Deletable::next> list;
1147 list.copyAndClear(toDeleteInEngineThread);
1150 while (Deletable *d = list.takeFirst())
1154 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1156 QQmlData *data = QQmlData::get(object);
1158 if (data && data->compiledData && data->deferredIdx) {
1159 QQmlObjectCreatingProfiler prof;
1161 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1162 prof.setTypeName(type ? type->qmlTypeName()
1163 : QString::fromUtf8(object->metaObject()->className()));
1164 if (data->outerContext)
1165 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1167 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1169 QQmlComponentPrivate::ConstructionState state;
1170 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1172 // Release the reference for the deferral action (we still have one from construction)
1173 data->compiledData->release();
1174 data->compiledData = 0;
1176 QQmlComponentPrivate::complete(ep, &state);
1180 QQmlContext *qmlContext(const QObject *obj)
1182 return QQmlEngine::contextForObject(obj);
1185 QQmlEngine *qmlEngine(const QObject *obj)
1187 QQmlData *data = QQmlData::get(obj, false);
1188 if (!data || !data->context)
1190 return data->context->engine;
1193 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1195 QQmlData *data = QQmlData::get(object);
1197 return 0; // Attached properties are only on objects created by QML
1199 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1203 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1207 rv = pf(const_cast<QObject *>(object));
1210 data->attachedProperties()->insert(id, rv);
1215 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1216 const QMetaObject *attachedMetaObject, bool create)
1219 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1221 if (*idCache == -1 || !object)
1224 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1227 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1229 #ifndef QQML_NO_DEBUG_PROTOCOL
1230 if (!QQmlEnginePrivate::qml_debugging_enabled
1232 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1234 QQmlEnginePrivate::qml_debugging_enabled = true;
1239 class QQmlDataExtended {
1242 ~QQmlDataExtended();
1244 QHash<int, QObject *> attachedProperties;
1247 QQmlDataExtended::QQmlDataExtended()
1251 QQmlDataExtended::~QQmlDataExtended()
1255 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1258 layout(endpoint->next);
1260 int index = endpoint->sourceSignal;
1261 index = qMin(index, 0xFFFF - 1);
1263 endpoint->next = notifies[index];
1264 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1265 endpoint->prev = ¬ifies[index];
1266 notifies[index] = endpoint;
1269 void QQmlData::NotifyList::layout()
1271 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1274 QQmlNotifierEndpoint **old = notifies;
1275 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1276 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1277 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1278 sizeof(QQmlNotifierEndpoint*);
1279 memset(notifies + notifiesSize, 0, memsetSize);
1281 if (notifies != old) {
1282 for (int ii = 0; ii < notifiesSize; ++ii)
1284 notifies[ii]->prev = ¬ifies[ii];
1287 notifiesSize = maximumTodoIndex + 1;
1292 maximumTodoIndex = 0;
1296 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1299 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1300 notifyList->connectionMask = 0;
1301 notifyList->maximumTodoIndex = 0;
1302 notifyList->notifiesSize = 0;
1303 notifyList->todo = 0;
1304 notifyList->notifies = 0;
1307 Q_ASSERT(!endpoint->isConnected());
1309 index = qMin(index, 0xFFFF - 1);
1310 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1312 if (index < notifyList->notifiesSize) {
1314 endpoint->next = notifyList->notifies[index];
1315 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1316 endpoint->prev = ¬ifyList->notifies[index];
1317 notifyList->notifies[index] = endpoint;
1320 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1322 endpoint->next = notifyList->todo;
1323 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1324 endpoint->prev = ¬ifyList->todo;
1325 notifyList->todo = endpoint;
1330 index MUST in the range returned by QObjectPrivate::signalIndex()
1331 This is different than the index returned by QMetaMethod::methodIndex()
1333 bool QQmlData::signalHasEndpoint(int index)
1335 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1338 void QQmlData::disconnectNotifiers()
1341 while (notifyList->todo)
1342 notifyList->todo->disconnect();
1343 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1344 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1347 free(notifyList->notifies);
1353 QHash<int, QObject *> *QQmlData::attachedProperties() const
1355 if (!extendedData) extendedData = new QQmlDataExtended;
1356 return &extendedData->attachedProperties;
1359 void QQmlData::destroyed(QObject *object)
1361 if (nextContextObject)
1362 nextContextObject->prevContextObject = prevContextObject;
1363 if (prevContextObject)
1364 *prevContextObject = nextContextObject;
1366 QQmlAbstractBinding *binding = bindings;
1368 QQmlAbstractBinding *next = binding->nextBinding();
1369 binding->setAddedToObject(false);
1370 binding->setNextBinding(0);
1376 compiledData->release();
1380 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1381 while (signalHandler) {
1382 if (signalHandler->isEvaluating()) {
1383 // The object is being deleted during signal handler evaluation.
1384 // This will cause a crash due to invalid memory access when the
1385 // evaluation has completed.
1386 // Abort with a friendly message instead.
1387 QString locationString;
1388 QQmlBoundSignalExpression *expr = signalHandler->expression();
1390 QString fileName = expr->sourceFile();
1391 if (fileName.isEmpty())
1392 fileName = QStringLiteral("<Unknown File>");
1393 locationString.append(fileName);
1394 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1395 QString source = expr->expression();
1396 if (source.size() > 100) {
1397 source.truncate(96);
1398 source.append(QStringLiteral(" ..."));
1400 locationString.append(source);
1402 locationString = QStringLiteral("<Unknown Location>");
1404 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1405 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1406 "instead), or the application is running a nested event loop.\n"
1407 "This behavior is NOT supported!\n"
1408 "%s", object, qPrintable(locationString));
1411 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1412 signalHandler->m_prevSignal = 0;
1413 signalHandler->m_nextSignal = 0;
1414 delete signalHandler;
1415 signalHandler = next;
1422 propertyCache->release();
1424 if (ownContext && context)
1428 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1429 *guard = (QObject *)0;
1430 guard->objectDestroyed(object);
1433 disconnectNotifiers();
1436 delete extendedData;
1438 // Dispose the handle.
1439 // We don't simply clear it (and wait for next gc cycle to dispose
1440 // via the weak qobject reference callback) as this affects the
1441 // outcomes of v8's gc statistical analysis heuristics, which can
1442 // cause unnecessary growth of the old pointer space js heap area.
1443 qPersistentDispose(v8object);
1449 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1451 void QQmlData::parentChanged(QObject *object, QObject *parent)
1454 if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1458 { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1459 { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1461 qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1462 "User code is attempting to change it to %s.\n"
1463 "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1468 bool QQmlData::hasBindingBit(int bit) const
1470 if (bindingBitsSize > bit)
1471 return bindingBits[bit / 32] & (1 << (bit % 32));
1476 void QQmlData::clearBindingBit(int bit)
1478 if (bindingBitsSize > bit)
1479 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1482 void QQmlData::setBindingBit(QObject *obj, int bit)
1484 if (bindingBitsSize <= bit) {
1485 int props = QQmlMetaObject(obj).propertyCount();
1486 Q_ASSERT(bit < props);
1488 int arraySize = (props + 31) / 32;
1489 int oldArraySize = bindingBitsSize / 32;
1491 bindingBits = (quint32 *)realloc(bindingBits,
1492 arraySize * sizeof(quint32));
1494 memset(bindingBits + oldArraySize,
1496 sizeof(quint32) * (arraySize - oldArraySize));
1498 bindingBitsSize = arraySize * 32;
1501 bindingBits[bit / 32] |= (1 << (bit % 32));
1504 void QQmlEnginePrivate::sendQuit()
1508 if (q->receivers(SIGNAL(quit())) == 0) {
1509 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1513 static void dumpwarning(const QQmlError &error)
1515 QMessageLogger(error.url().toString().toLatin1().constData(),
1516 error.line(), 0).warning().nospace()
1517 << qPrintable(error.toString());
1520 static void dumpwarning(const QList<QQmlError> &errors)
1522 for (int ii = 0; ii < errors.count(); ++ii)
1523 dumpwarning(errors.at(ii));
1526 void QQmlEnginePrivate::warning(const QQmlError &error)
1529 q->warnings(QList<QQmlError>() << error);
1530 if (outputWarningsToStdErr)
1534 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1537 q->warnings(errors);
1538 if (outputWarningsToStdErr)
1539 dumpwarning(errors);
1542 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1545 warning(error->error(q));
1548 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1551 QQmlEnginePrivate::get(engine)->warning(error);
1556 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1559 QQmlEnginePrivate::get(engine)->warning(error);
1564 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1567 QQmlEnginePrivate::get(engine)->warning(error);
1569 dumpwarning(error->error(0));
1572 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1575 engine->warning(error);
1580 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1583 engine->warning(error);
1589 This function should be called prior to evaluation of any js expression,
1590 so that scarce resources are not freed prematurely (eg, if there is a
1591 nested javascript expression).
1593 void QQmlEnginePrivate::referenceScarceResources()
1595 scarceResourcesRefCount += 1;
1599 This function should be called after evaluation of the js expression is
1600 complete, and so the scarce resources may be freed safely.
1602 void QQmlEnginePrivate::dereferenceScarceResources()
1604 Q_ASSERT(scarceResourcesRefCount > 0);
1605 scarceResourcesRefCount -= 1;
1607 // if the refcount is zero, then evaluation of the "top level"
1608 // expression must have completed. We can safely release the
1609 // scarce resources.
1610 if (scarceResourcesRefCount == 0) {
1611 // iterate through the list and release them all.
1612 // note that the actual SRD is owned by the JS engine,
1613 // so we cannot delete the SRD; but we can free the
1614 // memory used by the variant in the SRD.
1615 while (ScarceResourceData *sr = scarceResources.first()) {
1616 sr->data = QVariant();
1617 scarceResources.remove(sr);
1623 Adds \a path as a directory where the engine searches for
1624 installed modules in a URL-based directory structure.
1626 The \a path may be a local filesystem directory, a
1627 \l {The Qt Resource System}{Qt Resource} path (\c {:/imports}), a
1628 \l {The Qt Resource System}{Qt Resource} url (\c {qrc:/imports}) or a URL.
1630 The \a path will be converted into canonical form before it
1631 is added to the import path list.
1633 The newly added \a path will be first in the importPathList().
1635 \sa setImportPathList(), {QML Modules}
1637 void QQmlEngine::addImportPath(const QString& path)
1640 d->importDatabase.addImportPath(path);
1644 Returns the list of directories where the engine searches for
1645 installed modules in a URL-based directory structure.
1647 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1648 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1649 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1650 provided by that module. A \c qmldir file is required for defining the
1651 type version mapping and possibly QML extensions plugins.
1653 By default, the list contains the directory of the application executable,
1654 paths specified in the \c QML_IMPORT_PATH environment variable,
1655 and the builtin \c ImportsPath from QLibraryInfo.
1657 \sa addImportPath(), setImportPathList()
1659 QStringList QQmlEngine::importPathList() const
1661 Q_D(const QQmlEngine);
1662 return d->importDatabase.importPathList();
1666 Sets \a paths as the list of directories where the engine searches for
1667 installed modules in a URL-based directory structure.
1669 By default, the list contains the directory of the application executable,
1670 paths specified in the \c QML_IMPORT_PATH environment variable,
1671 and the builtin \c ImportsPath from QLibraryInfo.
1673 \sa importPathList(), addImportPath()
1675 void QQmlEngine::setImportPathList(const QStringList &paths)
1678 d->importDatabase.setImportPathList(paths);
1683 Adds \a path as a directory where the engine searches for
1684 native plugins for imported modules (referenced in the \c qmldir file).
1686 By default, the list contains only \c ., i.e. the engine searches
1687 in the directory of the \c qmldir file itself.
1689 The newly added \a path will be first in the pluginPathList().
1691 \sa setPluginPathList()
1693 void QQmlEngine::addPluginPath(const QString& path)
1696 d->importDatabase.addPluginPath(path);
1701 Returns the list of directories where the engine searches for
1702 native plugins for imported modules (referenced in the \c qmldir file).
1704 By default, the list contains only \c ., i.e. the engine searches
1705 in the directory of the \c qmldir file itself.
1707 \sa addPluginPath(), setPluginPathList()
1709 QStringList QQmlEngine::pluginPathList() const
1711 Q_D(const QQmlEngine);
1712 return d->importDatabase.pluginPathList();
1716 Sets the list of directories where the engine searches for
1717 native plugins for imported modules (referenced in the \c qmldir file)
1720 By default, the list contains only \c ., i.e. the engine searches
1721 in the directory of the \c qmldir file itself.
1723 \sa pluginPathList(), addPluginPath()
1725 void QQmlEngine::setPluginPathList(const QStringList &paths)
1728 d->importDatabase.setPluginPathList(paths);
1732 Imports the plugin named \a filePath with the \a uri provided.
1733 Returns true if the plugin was successfully imported; otherwise returns false.
1735 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1737 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1739 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1742 return d->importDatabase.importPlugin(filePath, uri, QString(), errors);
1746 \property QQmlEngine::offlineStoragePath
1747 \brief the directory for storing offline user data
1749 Returns the directory where SQL and other offline
1752 QQuickWebView and the SQL databases created with openDatabase()
1755 The default is QML/OfflineStorage in the platform-standard
1756 user application data directory.
1758 Note that the path may not currently exist on the filesystem, so
1759 callers wanting to \e create new files at this location should create
1760 it first - see QDir::mkpath().
1762 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1765 d->offlineStoragePath = dir;
1768 QString QQmlEngine::offlineStoragePath() const
1770 Q_D(const QQmlEngine);
1771 return d->offlineStoragePath;
1774 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1778 if (!mo->superClass()) {
1779 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1780 propertyCache.insert(mo, rv);
1783 QQmlPropertyCache *super = cache(mo->superClass());
1784 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1785 propertyCache.insert(mo, rv);
1790 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1793 QList<QQmlType *> types;
1795 int maxMinorVersion = 0;
1797 const QMetaObject *metaObject = type->metaObject();
1799 while (metaObject) {
1800 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1801 type->majorVersion(), minorVersion);
1803 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1809 metaObject = metaObject->superClass();
1812 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1814 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1818 QQmlPropertyCache *raw = cache(type->metaObject());
1820 bool hasCopied = false;
1822 for (int ii = 0; ii < types.count(); ++ii) {
1823 QQmlType *currentType = types.at(ii);
1827 int rev = currentType->metaObjectRevision();
1828 int moIndex = types.count() - 1 - ii;
1830 if (raw->allowedRevisionCache[moIndex] != rev) {
1835 raw->allowedRevisionCache[moIndex] = rev;
1839 // Test revision compatibility - the basic rule is:
1840 // * Anything that is excluded, cannot overload something that is not excluded *
1842 // Signals override:
1843 // * other signals and methods of the same name.
1844 // * properties named on<Signal Name>
1845 // * automatic <property name>Changed notify signals
1847 // Methods override:
1848 // * other methods of the same name
1850 // Properties override:
1851 // * other elements of the same name
1853 bool overloadError = false;
1854 QString overloadName;
1857 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1858 !overloadError && iter != raw->stringCache.end();
1861 QQmlPropertyData *d = *iter;
1862 if (raw->isAllowedInRevision(d))
1863 continue; // Not excluded - no problems
1865 // check that a regular "name" overload isn't happening
1866 QQmlPropertyData *current = d;
1867 while (!overloadError && current) {
1868 current = d->overrideData(current);
1869 if (current && raw->isAllowedInRevision(current))
1870 overloadError = true;
1875 if (overloadError) {
1876 if (hasCopied) raw->release();
1878 error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1Char(' ') + QString::number(type->majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation."));
1882 if (!hasCopied) raw->addref();
1883 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1885 if (minorVersion != maxMinorVersion) {
1887 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1893 QQmlMetaType::SingletonInstance *
1894 QQmlEnginePrivate::singletonTypeInstance(const QQmlMetaType::SingletonType &module)
1896 Locker locker(this);
1898 QQmlMetaType::SingletonInstance *a = singletonTypeInstances.value(module);
1900 a = new QQmlMetaType::SingletonInstance;
1901 a->scriptCallback = module.script;
1902 a->qobjectCallback = module.qobject;
1903 a->instanceMetaObject = module.instanceMetaObject;
1904 singletonTypeInstances.insert(module, a);
1910 bool QQmlEnginePrivate::isQObject(int t)
1912 Locker locker(this);
1913 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1916 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1918 Locker locker(this);
1919 int t = v.userType();
1920 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1922 return *(QObject **)(v.constData());
1924 return QQmlMetaType::toQObject(v, ok);
1928 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1930 Locker locker(this);
1931 if (m_compositeTypes.contains(t))
1932 return QQmlMetaType::Object;
1933 else if (m_qmlLists.contains(t))
1934 return QQmlMetaType::List;
1936 return QQmlMetaType::typeCategory(t);
1939 bool QQmlEnginePrivate::isList(int t) const
1941 Locker locker(this);
1942 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1945 int QQmlEnginePrivate::listType(int t) const
1947 Locker locker(this);
1948 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1949 if (iter != m_qmlLists.end())
1952 return QQmlMetaType::listType(t);
1955 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1957 Locker locker(this);
1958 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1959 if (iter != m_compositeTypes.end()) {
1960 return QQmlMetaObject((*iter)->rootPropertyCache);
1962 QQmlType *type = QQmlMetaType::qmlType(t);
1963 return QQmlMetaObject(type?type->baseMetaObject():0);
1967 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1969 Locker locker(this);
1970 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1971 if (iter != m_compositeTypes.end()) {
1972 return QQmlMetaObject((*iter)->rootPropertyCache);
1974 QQmlType *type = QQmlMetaType::qmlType(t);
1975 return QQmlMetaObject(type?type->metaObject():0);
1979 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1981 Locker locker(this);
1982 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1983 if (iter != m_compositeTypes.end()) {
1984 return (*iter)->rootPropertyCache;
1986 QQmlType *type = QQmlMetaType::qmlType(t);
1988 return type?cache(type->metaObject()):0;
1992 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1994 Locker locker(this);
1995 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1996 if (iter != m_compositeTypes.end()) {
1997 return (*iter)->rootPropertyCache;
1999 QQmlType *type = QQmlMetaType::qmlType(t);
2001 return type?cache(type->baseMetaObject()):0;
2005 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
2007 QByteArray name = data->rootPropertyCache->className();
2009 QByteArray ptr = name + '*';
2010 QByteArray lst = "QQmlListProperty<" + name + '>';
2012 int ptr_type = QMetaType::registerNormalizedType(ptr,
2013 qMetaTypeDeleteHelper<QObject*>,
2014 qMetaTypeCreateHelper<QObject*>,
2015 qMetaTypeDestructHelper<QObject*>,
2016 qMetaTypeConstructHelper<QObject*>,
2018 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
2020 int lst_type = QMetaType::registerNormalizedType(lst,
2021 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
2022 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
2023 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
2024 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
2025 sizeof(QQmlListProperty<QObject>),
2026 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
2027 static_cast<QMetaObject*>(0));
2029 data->metaTypeId = ptr_type;
2030 data->listMetaTypeId = lst_type;
2031 data->isRegisteredWithEngine = true;
2033 Locker locker(this);
2034 m_qmlLists.insert(lst_type, ptr_type);
2035 // The QQmlCompiledData is not referenced here, but it is removed from this
2036 // hash in the QQmlCompiledData destructor
2037 m_compositeTypes.insert(ptr_type, data);
2040 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
2042 int ptr_type = data->metaTypeId;
2043 int lst_type = data->listMetaTypeId;
2045 Locker locker(this);
2046 m_qmlLists.remove(lst_type);
2047 m_compositeTypes.remove(ptr_type);
2050 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2052 return typeLoader.isTypeLoaded(url);
2055 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2057 return typeLoader.isScriptLoaded(url);
2060 bool QQml_isFileCaseCorrect(const QString &fileName)
2062 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2063 QFileInfo info(fileName);
2064 const QString absolute = info.absoluteFilePath();
2066 #if defined(Q_OS_MAC)
2067 const QString canonical = info.canonicalFilePath();
2068 #elif defined(Q_OS_WIN)
2069 wchar_t buffer[1024];
2071 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2072 if (rv == 0 || rv >= 1024) return true;
2073 rv = ::GetLongPathName(buffer, buffer, 1024);
2074 if (rv == 0 || rv >= 1024) return true;
2076 const QString canonical = QString::fromWCharArray(buffer);
2079 const int absoluteLength = absolute.length();
2080 const int canonicalLength = canonical.length();
2082 const int length = qMin(absoluteLength, canonicalLength);
2083 for (int ii = 0; ii < length; ++ii) {
2084 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2085 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2087 if (a.toLower() != c.toLower())
2099 \fn QQmlEngine *qmlEngine(const QObject *object)
2102 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2103 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2107 \fn QQmlContext *qmlContext(const QObject *object)
2110 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2111 QQmlEngine::contextForObject(object).