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);
112 \qmlclass QtObject QObject
113 \inqmlmodule QtQuick 2
114 \ingroup qml-utility-elements
116 \brief A basic QML type
118 The QtObject element 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 element 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.
201 Image providers must be registered with the QML engine. The only information the QML
202 engine knows about image providers is the type of image data they provide. To use an
203 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
204 to a QQuickImageProvider pointer.
206 \sa QQuickImageProvider, QQuickTextureFactory
210 \enum QQmlImageProviderBase::ImageType
212 Defines the type of image supported by this image provider.
214 \value Image The Image Provider provides QImage images.
215 The QQuickImageProvider::requestImage() method will be called for all image requests.
216 \value Pixmap The Image Provider provides QPixmap images.
217 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
218 \value Texture The Image Provider provides QSGTextureProvider based images.
219 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
223 \enum QQmlImageProviderBase::Flag
225 Defines specific requirements or features of this image provider.
227 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
228 run in a separate thread, which allows the provider to spend as much time as needed
229 on producing the image without blocking the main thread.
233 QQmlImageProviderBase::QQmlImageProviderBase()
238 QQmlImageProviderBase::~QQmlImageProviderBase()
244 \qmlclass Qt QQmlEnginePrivate
245 \ingroup qml-utility-elements
246 \brief The QML global Qt object provides useful enums and functions from Qt.
248 \keyword QmlGlobalQtObject
250 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
252 The \c Qt object is a global object with utility functions, properties and enums.
254 It is not instantiable; to use it, call the members of the global \c Qt object directly.
261 color: Qt.rgba(1, 0, 0, 1)
262 text: Qt.md5("hello, world")
269 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
270 the \l Qt::LeftButton and \l Qt::RightButton enumeration values as \c Qt.LeftButton and \c Qt.RightButton.
275 The Qt object also contains helper functions for creating objects of specific
276 data types. This is primarily useful when setting the properties of an item
277 when the property has one of the following types:
279 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
280 \li \c point - use \l{Qt::point()}{Qt.point()}
281 \li \c size - use \l{Qt::size()}{Qt.size()}
284 If the QtQuick module has been imported, the following helper functions for
285 creating objects of specific data types are also available for clients to use:
287 \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()}
288 \li \c font - use \l{Qt::font()}{Qt.font()}
289 \li \c vector2d - use \l{Qt::vector2d()}{Qt.vector2d()}
290 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
291 \li \c vector4d - use \l{Qt::vector4d()}{Qt.vector4d()}
292 \li \c quaternion - use \l{Qt::quaternion()}{Qt.quaternion()}
293 \li \c matrix4x4 - use \l{Qt::matrix4x4()}{Qt.matrix4x4()}
296 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
298 \section1 Date/Time Formatters
300 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
303 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
304 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
305 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
308 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
311 \section1 Dynamic Object Creation
312 The following functions on the global object allow you to dynamically create QML
313 items from files or strings. See \l{Dynamic QML Object Creation from JavaScript} for an overview
317 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
318 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
322 \section1 Other Functions
324 The following functions are also on the Qt object.
327 \li \l{Qt::quit()}{Qt.quit()}
328 \li \l{Qt::md5()}{Qt.md5(string)}
329 \li \l{Qt::btoa()}{string Qt.btoa(string)}
330 \li \l{Qt::atob()}{string Qt.atob(string)}
331 \li \l{Qt::binding()}{object Qt.binding(function)}
332 \li \l{Qt::locale()}{object Qt.locale()}
333 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
334 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
335 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
340 \qmlproperty object Qt::application
343 The \c application object provides access to global application state
344 properties shared by many QML components.
350 \li \c application.active
352 This read-only property indicates whether the application is the top-most and focused
353 application, and the user is able to interact with the application. The property
354 is false when the application is in the background, the device keylock or screen
355 saver is active, the screen backlight is turned off, or the global system dialog
356 is being displayed on top of the application. It can be used for stopping and
357 pausing animations, timers and active processing of data in order to save device
358 battery power and free device memory and processor load when the application is not
362 \li \c application.layoutDirection
364 This read-only property can be used to query the default layout direction of the
365 application. On system start-up, the default layout direction depends on the
366 application's language. The property has a value of \c Qt.RightToLeft in locales
367 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
368 where the reading direction flows from left to right. You can bind to this
369 property to customize your application layouts to support both layout directions.
374 \li Qt.LeftToRight - Text and graphics elements should be positioned
376 \li Qt.RightToLeft - Text and graphics elements should be positioned
382 The following example uses the \c application object to indicate
383 whether the application is currently active:
385 \snippet qml/application.qml document
389 \qmlproperty object Qt::inputMethod
392 The \c inputMethod object allows access to application's QInputMethod object
393 and all its properties and slots. See the QInputMethod documentation for
399 \qmlmethod object Qt::include(string url, jsobject callback)
401 Includes another JavaScript file. This method can only be used from within JavaScript files,
402 and not regular QML files.
404 This imports all functions from \a url into the current script's namespace.
406 Qt.include() returns an object that describes the status of the operation. The object has
407 a single property, \c {status}, that is set to one of the following values:
410 \header \li Symbol \li Value \li Description
411 \row \li result.OK \li 0 \li The include completed successfully.
412 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
413 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
414 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
415 An additional \c exception property will be set in this case.
418 The \c status property will be updated as the operation progresses.
420 If provided, \a callback is invoked when the operation completes. The callback is passed
421 the same object as is returned from the Qt.include() call.
423 // Qt.include() is implemented in qv8include.cpp
426 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
427 : propertyCapture(0), rootContext(0), isDebugging(false),
428 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
429 cleanup(0), erroredBindings(0), inProgressCreations(0),
430 workerScriptEngine(0), activeVME(0),
431 networkAccessManager(0), networkAccessManagerFactory(0),
432 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
433 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
437 QQmlEnginePrivate::~QQmlEnginePrivate()
439 if (inProgressCreations)
440 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
443 QQmlCleanup *c = cleanup;
445 if (cleanup) cleanup->prev = &cleanup;
451 doDeleteInEngineThread();
453 if (incubationController) incubationController->d = 0;
454 incubationController = 0;
459 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
461 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
463 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
464 delete (*iter)->qobjectApi;
467 for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
468 iter.value()->isRegisteredWithEngine = false;
471 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
473 QObjectPrivate *p = QObjectPrivate::get(o);
474 if (p->declarativeData) {
475 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
476 if (d->ownContext && d->context) {
477 d->context->destroy();
481 // Mark this object as in the process of deletion to
482 // prevent it resolving in bindings
483 QQmlData::markAsDeleted(o);
487 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
489 static_cast<QQmlData *>(d)->destroyed(o);
492 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
494 static_cast<QQmlData *>(d)->parentChanged(o, p);
497 class QQmlThreadNotifierProxyObject : public QObject
500 QPointer<QObject> target;
502 virtual int qt_metacall(QMetaObject::Call, int methodIndex, void **a) {
506 QMetaMethod method = target->metaObject()->method(methodIndex);
507 Q_ASSERT(method.methodType() == QMetaMethod::Signal);
508 int signalIndex = QMetaObjectPrivate::signalIndex(method);
509 QQmlData *ddata = QQmlData::get(target, false);
510 QQmlNotifierEndpoint *ep = ddata->notify(signalIndex);
511 if (ep) QQmlNotifier::emitNotify(ep, a);
519 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
521 QQmlData *ddata = QQmlData::get(object, false);
522 if (!ddata) return; // Probably being deleted
524 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
525 // that they're exposed to. However, to make writing "worker objects" that calculate data
526 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
527 // QQmlEngine to emit signals from a different thread. These signals are then automatically
528 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
529 // by the qqmlecmascript::threadSignal() autotest.
530 if (ddata->notifyList &&
531 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
533 if (!QObjectPrivate::get(object)->threadData->thread)
536 QMetaMethod m = QMetaObjectPrivate::signal(object->metaObject(), index);
537 QList<QByteArray> parameterTypes = m.parameterTypes();
539 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
540 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
542 types[0] = 0; // return type
543 args[0] = 0; // return value
545 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
546 const QByteArray &typeName = parameterTypes.at(ii);
547 if (typeName.endsWith('*'))
548 types[ii + 1] = QMetaType::VoidStar;
550 types[ii + 1] = QMetaType::type(typeName);
552 if (!types[ii + 1]) {
553 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
554 "(Make sure '%s' is registered using qRegisterMetaType().)",
555 typeName.constData(), typeName.constData());
561 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
564 QMetaCallEvent *ev = new QMetaCallEvent(m.methodIndex(), 0, 0, object, index,
565 parameterTypes.count() + 1, types, args);
567 QQmlThreadNotifierProxyObject *mpo = new QQmlThreadNotifierProxyObject;
568 mpo->target = object;
569 mpo->moveToThread(QObjectPrivate::get(object)->threadData->thread);
570 QCoreApplication::postEvent(mpo, ev);
573 QQmlNotifierEndpoint *ep = ddata->notify(index);
574 if (ep) QQmlNotifier::emitNotify(ep, a);
578 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
580 return static_cast<QQmlData *>(d)->endpointCount(index);
583 bool QQmlData::isSignalConnected(QAbstractDeclarativeData *d, const QObject *, int index)
585 return static_cast<QQmlData *>(d)->signalHasEndpoint(index);
588 int QQmlData::endpointCount(int index)
591 QQmlNotifierEndpoint *ep = notify(index);
602 void QQmlData::markAsDeleted(QObject *o)
604 QQmlData::setQueuedForDeletion(o);
606 QObjectPrivate *p = QObjectPrivate::get(o);
607 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
608 QQmlData::markAsDeleted(*it);
612 void QQmlData::setQueuedForDeletion(QObject *object)
615 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
616 if (!priv->wasDeleted && priv->declarativeData) {
617 QQmlData *ddata = QQmlData::get(object, false);
618 if (ddata->ownContext && ddata->context)
619 ddata->context->emitDestruction();
620 ddata->isQueuedForDeletion = true;
626 void QQmlEnginePrivate::init()
630 static bool firstTime = true;
632 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
633 registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
639 qRegisterMetaType<QVariant>("QVariant");
640 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
641 qRegisterMetaType<QJSValue>("QJSValue");
642 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
643 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
644 qRegisterMetaType<QList<int> >("QList<int>");
645 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
647 v8engine()->setEngine(q);
649 rootContext = new QQmlContext(q,true);
651 if (QCoreApplication::instance()->thread() == q->thread() &&
652 QQmlEngineDebugService::isDebuggingEnabled()) {
654 QQmlEngineDebugService::instance()->addEngine(q);
655 QV8DebugService::initialize(v8engine());
656 QV8ProfilerService::initialize();
657 QQmlProfilerService::initialize();
658 QDebugMessageService::instance();
661 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
662 if (!dataLocation.isEmpty())
663 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
664 + QDir::separator() + QLatin1String("QML")
665 + QDir::separator() + QLatin1String("OfflineStorage");
668 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
671 if (!workerScriptEngine)
672 workerScriptEngine = new QQuickWorkerScriptEngine(q);
673 return workerScriptEngine;
680 \brief The QQmlEngine class provides an environment for instantiating QML components.
683 Each QML component is instantiated in a QQmlContext.
684 QQmlContext's are essential for passing data to QML
685 components. In QML, contexts are arranged hierarchically and this
686 hierarchy is managed by the QQmlEngine.
688 Prior to creating any QML components, an application must have
689 created a QQmlEngine to gain access to a QML context. The
690 following example shows how to create a simple Text item.
694 QQmlComponent component(&engine);
695 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
696 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
698 //add item to view, etc
702 In this case, the Text item will be created in the engine's
703 \l {QQmlEngine::rootContext()}{root context}.
705 Note that the QtQuick 1 version is called QDeclarativeEngine.
707 \sa QQmlComponent, QQmlContext
711 Create a new QQmlEngine with the given \a parent.
713 QQmlEngine::QQmlEngine(QObject *parent)
714 : QJSEngine(*new QQmlEnginePrivate(this), parent)
721 Destroys the QQmlEngine.
723 Any QQmlContext's created on this engine will be
724 invalidated, but not destroyed (unless they are parented to the
727 QQmlEngine::~QQmlEngine()
730 if (d->isDebugging) {
731 QQmlEngineDebugService::instance()->remEngine(this);
734 // Emit onDestruction signals for the root context before
735 // we destroy the contexts, engine, Module APIs etc. that
736 // may be required to handle the destruction signal.
737 QQmlContextData::get(rootContext())->emitDestruction();
739 // if we are the parent of any of the qobject module api instances,
740 // we need to remove them from our internal list, in order to prevent
741 // a segfault in engine private dtor.
742 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
743 QObject *currQObjectApi = 0;
744 QQmlMetaType::ModuleApiInstance *currInstance = 0;
745 foreach (const QQmlMetaType::ModuleApi &key, keys) {
746 currInstance = d->moduleApiInstances.value(key);
747 currQObjectApi = currInstance->qobjectApi;
748 if (this->children().contains(currQObjectApi)) {
749 delete currQObjectApi;
751 d->moduleApiInstances.remove(key);
755 if (d->incubationController)
756 d->incubationController->d = 0;
759 /*! \fn void QQmlEngine::quit()
760 This signal is emitted when the QML loaded by the engine would like to quit.
763 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
764 This signal is emitted when \a warnings messages are generated by QML.
768 Clears the engine's internal component cache.
770 This function causes the property metadata of all components previously
771 loaded by the engine to be destroyed. All previously loaded components and
772 the property bindings for all extant objects created from those components will
775 This function returns the engine to a state where it does not contain any loaded
776 component data. This may be useful in order to reload a smaller subset of the
777 previous component set, or to load a new version of a previously loaded component.
779 Once the component cache has been cleared, components must be loaded before
780 any new objects can be created.
782 \sa trimComponentCache()
784 void QQmlEngine::clearComponentCache()
787 d->typeLoader.clearCache();
791 Trims the engine's internal component cache.
793 This function causes the property metadata of any loaded components which are
794 not currently in use to be destroyed.
796 A component is considered to be in use if there are any extant instances of
797 the component itself, any instances of other components that use the component,
798 or any objects instantiated by any of those components.
800 \sa clearComponentCache()
802 void QQmlEngine::trimComponentCache()
805 d->typeLoader.trimCache();
809 Returns the engine's root context.
811 The root context is automatically created by the QQmlEngine.
812 Data that should be available to all QML component instances
813 instantiated by the engine should be put in the root context.
815 Additional data that should only be available to a subset of
816 component instances should be added to sub-contexts parented to the
819 QQmlContext *QQmlEngine::rootContext() const
821 Q_D(const QQmlEngine);
822 return d->rootContext;
826 Sets the \a factory to use for creating QNetworkAccessManager(s).
828 QNetworkAccessManager is used for all network access by QML. By
829 implementing a factory it is possible to create custom
830 QNetworkAccessManager with specialized caching, proxy and cookie
833 The factory must be set before executing the engine.
835 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
838 QMutexLocker locker(&d->mutex);
839 d->networkAccessManagerFactory = factory;
843 Returns the current QQmlNetworkAccessManagerFactory.
845 \sa setNetworkAccessManagerFactory()
847 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
849 Q_D(const QQmlEngine);
850 return d->networkAccessManagerFactory;
853 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
856 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
858 void *args[] = { 0 };
859 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
863 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
865 QMutexLocker locker(&mutex);
866 QNetworkAccessManager *nam;
867 if (networkAccessManagerFactory) {
868 nam = networkAccessManagerFactory->create(parent);
870 nam = new QNetworkAccessManager(parent);
876 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
878 Q_Q(const QQmlEngine);
879 if (!networkAccessManager)
880 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
881 return networkAccessManager;
885 Returns a common QNetworkAccessManager which can be used by any QML
886 element instantiated by this engine.
888 If a QQmlNetworkAccessManagerFactory has been set and a
889 QNetworkAccessManager has not yet been created, the
890 QQmlNetworkAccessManagerFactory will be used to create the
891 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
892 will have no proxy or cache set.
894 \sa setNetworkAccessManagerFactory()
896 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
898 Q_D(const QQmlEngine);
899 return d->getNetworkAccessManager();
904 Sets the \a provider to use for images requested via the \e
905 image: url scheme, with host \a providerId. The QQmlEngine
906 takes ownership of \a provider.
908 Image providers enable support for pixmap and threaded image
909 requests. See the QQuickImageProvider documentation for details on
910 implementing and using image providers.
912 All required image providers should be added to the engine before any
913 QML sources files are loaded.
915 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
917 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
920 QMutexLocker locker(&d->mutex);
921 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
925 Returns the image provider set for \a providerId.
927 Returns the provider if it was found; otherwise returns 0.
929 \sa QQuickImageProvider
931 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
933 Q_D(const QQmlEngine);
934 QMutexLocker locker(&d->mutex);
935 return d->imageProviders.value(providerId).data();
939 Removes the image provider for \a providerId.
941 \sa addImageProvider(), QQuickImageProvider
943 void QQmlEngine::removeImageProvider(const QString &providerId)
946 QMutexLocker locker(&d->mutex);
947 d->imageProviders.take(providerId);
951 Return the base URL for this engine. The base URL is only used to
952 resolve components when a relative URL is passed to the
953 QQmlComponent constructor.
955 If a base URL has not been explicitly set, this method returns the
956 application's current working directory.
960 QUrl QQmlEngine::baseUrl() const
962 Q_D(const QQmlEngine);
963 if (d->baseUrl.isEmpty()) {
964 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
971 Set the base URL for this engine to \a url.
975 void QQmlEngine::setBaseUrl(const QUrl &url)
982 Returns true if warning messages will be output to stderr in addition
983 to being emitted by the warnings() signal, otherwise false.
985 The default value is true.
987 bool QQmlEngine::outputWarningsToStandardError() const
989 Q_D(const QQmlEngine);
990 return d->outputWarningsToStdErr;
994 Set whether warning messages will be output to stderr to \a enabled.
996 If \a enabled is true, any warning messages generated by QML will be
997 output to stderr and emitted by the warnings() signal. If \a enabled
998 is false, on the warnings() signal will be emitted. This allows
999 applications to handle warning output themselves.
1001 The default value is true.
1003 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
1006 d->outputWarningsToStdErr = enabled;
1010 Returns the QQmlContext for the \a object, or 0 if no
1011 context has been set.
1013 When the QQmlEngine instantiates a QObject, the context is
1016 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
1021 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
1024 static_cast<QQmlData *>(priv->declarativeData);
1028 else if (data->outerContext)
1029 return data->outerContext->asQQmlContext();
1035 Sets the QQmlContext for the \a object to \a context.
1036 If the \a object already has a context, a warning is
1037 output, but the context is not changed.
1039 When the QQmlEngine instantiates a QObject, the context is
1042 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1044 if (!object || !context)
1047 QQmlData *data = QQmlData::get(object, true);
1048 if (data->context) {
1049 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1053 QQmlContextData *contextData = QQmlContextData::get(context);
1054 contextData->addObject(object);
1058 \enum QQmlEngine::ObjectOwnership
1060 Ownership controls whether or not QML automatically destroys the
1061 QObject when the object is garbage collected by the JavaScript
1062 engine. The two ownership options are:
1064 \value CppOwnership The object is owned by C++ code, and will
1065 never be deleted by QML. The JavaScript destroy() method cannot be
1066 used on objects with CppOwnership. This option is similar to
1067 QScriptEngine::QtOwnership.
1069 \value JavaScriptOwnership The object is owned by JavaScript.
1070 When the object is returned to QML as the return value of a method
1071 call or property access, QML will track it, and delete the object
1072 if there are no remaining JavaScript references to it and it has no
1073 QObject::parent(). An object tracked by one QQmlEngine
1074 will be deleted during that QQmlEngine's destructor, and thus
1075 JavaScript references between objects with JavaScriptOwnership from
1076 two different engines will not be valid after the deletion of one of
1077 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1079 Generally an application doesn't need to set an object's ownership
1080 explicitly. QML uses a heuristic to set the default object
1081 ownership. By default, an object that is created by QML has
1082 JavaScriptOwnership. The exception to this are the root objects
1083 created by calling QQmlComponent::create() or
1084 QQmlComponent::beginCreate() which have CppOwnership by
1085 default. The ownership of these root-level objects is considered to
1086 have been transferred to the C++ caller.
1088 Objects not-created by QML have CppOwnership by default. The
1089 exception to this is objects returned from a C++ method call. The
1090 ownership of these objects is passed to JavaScript.
1092 Calling setObjectOwnership() overrides the default ownership
1093 heuristic used by QML.
1097 Sets the \a ownership of \a object.
1099 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1104 QQmlData *ddata = QQmlData::get(object, true);
1108 ddata->indestructible = (ownership == CppOwnership)?true:false;
1109 ddata->explicitIndestructibleSet = true;
1113 Returns the ownership of \a object.
1115 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1118 return CppOwnership;
1120 QQmlData *ddata = QQmlData::get(object, false);
1122 return CppOwnership;
1124 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1127 bool QQmlEngine::event(QEvent *e)
1130 if (e->type() == QEvent::User)
1131 d->doDeleteInEngineThread();
1133 return QJSEngine::event(e);
1136 void QQmlEnginePrivate::doDeleteInEngineThread()
1138 QFieldList<Deletable, &Deletable::next> list;
1140 list.copyAndClear(toDeleteInEngineThread);
1143 while (Deletable *d = list.takeFirst())
1147 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1149 QQmlData *data = QQmlData::get(object);
1151 if (data && data->compiledData && data->deferredIdx) {
1152 QQmlObjectCreatingProfiler prof;
1154 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1155 prof.setTypeName(type ? type->qmlTypeName()
1156 : QString::fromUtf8(object->metaObject()->className()));
1157 if (data->outerContext)
1158 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1160 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1162 QQmlComponentPrivate::ConstructionState state;
1163 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1165 // Release the reference for the deferral action (we still have one from construction)
1166 data->compiledData->release();
1167 data->compiledData = 0;
1169 QQmlComponentPrivate::complete(ep, &state);
1173 QQmlContext *qmlContext(const QObject *obj)
1175 return QQmlEngine::contextForObject(obj);
1178 QQmlEngine *qmlEngine(const QObject *obj)
1180 QQmlData *data = QQmlData::get(obj, false);
1181 if (!data || !data->context)
1183 return data->context->engine;
1186 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1188 QQmlData *data = QQmlData::get(object);
1190 return 0; // Attached properties are only on objects created by QML
1192 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1196 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1200 rv = pf(const_cast<QObject *>(object));
1203 data->attachedProperties()->insert(id, rv);
1208 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1209 const QMetaObject *attachedMetaObject, bool create)
1212 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1214 if (*idCache == -1 || !object)
1217 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1220 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1222 #ifndef QQML_NO_DEBUG_PROTOCOL
1223 if (!QQmlEnginePrivate::qml_debugging_enabled
1225 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1227 QQmlEnginePrivate::qml_debugging_enabled = true;
1232 class QQmlDataExtended {
1235 ~QQmlDataExtended();
1237 QHash<int, QObject *> attachedProperties;
1240 QQmlDataExtended::QQmlDataExtended()
1244 QQmlDataExtended::~QQmlDataExtended()
1248 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1251 layout(endpoint->next);
1253 int index = endpoint->sourceSignal;
1254 index = qMin(index, 0xFFFF - 1);
1256 endpoint->next = notifies[index];
1257 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1258 endpoint->prev = ¬ifies[index];
1259 notifies[index] = endpoint;
1262 void QQmlData::NotifyList::layout()
1264 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1267 QQmlNotifierEndpoint **old = notifies;
1268 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1269 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1270 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1271 sizeof(QQmlNotifierEndpoint*);
1272 memset(notifies + notifiesSize, 0, memsetSize);
1274 if (notifies != old) {
1275 for (int ii = 0; ii < notifiesSize; ++ii)
1277 notifies[ii]->prev = ¬ifies[ii];
1280 notifiesSize = maximumTodoIndex + 1;
1285 maximumTodoIndex = 0;
1289 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1292 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1293 notifyList->connectionMask = 0;
1294 notifyList->maximumTodoIndex = 0;
1295 notifyList->notifiesSize = 0;
1296 notifyList->todo = 0;
1297 notifyList->notifies = 0;
1300 Q_ASSERT(!endpoint->isConnected());
1302 index = qMin(index, 0xFFFF - 1);
1303 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1305 if (index < notifyList->notifiesSize) {
1307 endpoint->next = notifyList->notifies[index];
1308 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1309 endpoint->prev = ¬ifyList->notifies[index];
1310 notifyList->notifies[index] = endpoint;
1313 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1315 endpoint->next = notifyList->todo;
1316 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1317 endpoint->prev = ¬ifyList->todo;
1318 notifyList->todo = endpoint;
1323 index MUST in the range returned by QObjectPrivate::signalIndex()
1324 This is different than the index returned by QMetaMethod::methodIndex()
1326 bool QQmlData::signalHasEndpoint(int index)
1328 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1331 QHash<int, QObject *> *QQmlData::attachedProperties() const
1333 if (!extendedData) extendedData = new QQmlDataExtended;
1334 return &extendedData->attachedProperties;
1337 void QQmlData::destroyed(QObject *object)
1339 if (nextContextObject)
1340 nextContextObject->prevContextObject = prevContextObject;
1341 if (prevContextObject)
1342 *prevContextObject = nextContextObject;
1344 QQmlAbstractBinding *binding = bindings;
1346 QQmlAbstractBinding *next = binding->nextBinding();
1347 binding->setAddedToObject(false);
1348 binding->setNextBinding(0);
1354 compiledData->release();
1358 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1359 while (signalHandler) {
1360 if (signalHandler->isEvaluating()) {
1361 // The object is being deleted during signal handler evaluation.
1362 // This will cause a crash due to invalid memory access when the
1363 // evaluation has completed.
1364 // Abort with a friendly message instead.
1365 QString locationString;
1366 QQmlBoundSignalExpression *expr = signalHandler->expression();
1368 QString fileName = expr->sourceFile();
1369 if (fileName.isEmpty())
1370 fileName = QStringLiteral("<Unknown File>");
1371 locationString.append(fileName);
1372 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1373 QString source = expr->expression();
1374 if (source.size() > 100) {
1375 source.truncate(96);
1376 source.append(QStringLiteral(" ..."));
1378 locationString.append(source);
1380 locationString = QStringLiteral("<Unknown Location>");
1382 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1383 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1384 "instead), or the application is running a nested event loop.\n"
1385 "This behavior is NOT supported!\n"
1386 "%s", object, qPrintable(locationString));
1389 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1390 signalHandler->m_prevSignal = 0;
1391 signalHandler->m_nextSignal = 0;
1392 delete signalHandler;
1393 signalHandler = next;
1400 propertyCache->release();
1402 if (ownContext && context)
1406 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1407 *guard = (QObject *)0;
1408 guard->objectDestroyed(object);
1412 while (notifyList->todo)
1413 notifyList->todo->disconnect();
1414 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1415 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1418 free(notifyList->notifies);
1424 delete extendedData;
1426 // Dispose the handle.
1427 // We don't simply clear it (and wait for next gc cycle to dispose
1428 // via the weak qobject reference callback) as this affects the
1429 // outcomes of v8's gc statistical analysis heuristics, which can
1430 // cause unnecessary growth of the old pointer space js heap area.
1431 qPersistentDispose(v8object);
1437 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1439 void QQmlData::parentChanged(QObject *object, QObject *parent)
1442 if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1446 { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1447 { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1449 qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1450 "User code is attempting to change it to %s.\n"
1451 "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1456 bool QQmlData::hasBindingBit(int bit) const
1458 if (bindingBitsSize > bit)
1459 return bindingBits[bit / 32] & (1 << (bit % 32));
1464 void QQmlData::clearBindingBit(int bit)
1466 if (bindingBitsSize > bit)
1467 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1470 void QQmlData::setBindingBit(QObject *obj, int bit)
1472 if (bindingBitsSize <= bit) {
1473 int props = QQmlMetaObject(obj).propertyCount();
1474 Q_ASSERT(bit < props);
1476 int arraySize = (props + 31) / 32;
1477 int oldArraySize = bindingBitsSize / 32;
1479 bindingBits = (quint32 *)realloc(bindingBits,
1480 arraySize * sizeof(quint32));
1482 memset(bindingBits + oldArraySize,
1484 sizeof(quint32) * (arraySize - oldArraySize));
1486 bindingBitsSize = arraySize * 32;
1489 bindingBits[bit / 32] |= (1 << (bit % 32));
1492 void QQmlEnginePrivate::sendQuit()
1496 if (q->receivers(SIGNAL(quit())) == 0) {
1497 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1501 static void dumpwarning(const QQmlError &error)
1503 QMessageLogger(error.url().toString().toLatin1().constData(),
1504 error.line(), 0).warning().nospace()
1505 << qPrintable(error.toString());
1508 static void dumpwarning(const QList<QQmlError> &errors)
1510 for (int ii = 0; ii < errors.count(); ++ii)
1511 dumpwarning(errors.at(ii));
1514 void QQmlEnginePrivate::warning(const QQmlError &error)
1517 q->warnings(QList<QQmlError>() << error);
1518 if (outputWarningsToStdErr)
1522 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1525 q->warnings(errors);
1526 if (outputWarningsToStdErr)
1527 dumpwarning(errors);
1530 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1533 warning(error->error(q));
1536 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1539 QQmlEnginePrivate::get(engine)->warning(error);
1544 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1547 QQmlEnginePrivate::get(engine)->warning(error);
1552 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1555 QQmlEnginePrivate::get(engine)->warning(error);
1557 dumpwarning(error->error(0));
1560 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1563 engine->warning(error);
1568 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1571 engine->warning(error);
1577 This function should be called prior to evaluation of any js expression,
1578 so that scarce resources are not freed prematurely (eg, if there is a
1579 nested javascript expression).
1581 void QQmlEnginePrivate::referenceScarceResources()
1583 scarceResourcesRefCount += 1;
1587 This function should be called after evaluation of the js expression is
1588 complete, and so the scarce resources may be freed safely.
1590 void QQmlEnginePrivate::dereferenceScarceResources()
1592 Q_ASSERT(scarceResourcesRefCount > 0);
1593 scarceResourcesRefCount -= 1;
1595 // if the refcount is zero, then evaluation of the "top level"
1596 // expression must have completed. We can safely release the
1597 // scarce resources.
1598 if (scarceResourcesRefCount == 0) {
1599 // iterate through the list and release them all.
1600 // note that the actual SRD is owned by the JS engine,
1601 // so we cannot delete the SRD; but we can free the
1602 // memory used by the variant in the SRD.
1603 while (ScarceResourceData *sr = scarceResources.first()) {
1604 sr->data = QVariant();
1605 scarceResources.remove(sr);
1611 Adds \a path as a directory where the engine searches for
1612 installed modules in a URL-based directory structure.
1613 The \a path may be a local filesystem directory or a URL.
1615 The newly added \a path will be first in the importPathList().
1617 \sa setImportPathList(), {QML Modules}
1619 void QQmlEngine::addImportPath(const QString& path)
1622 d->importDatabase.addImportPath(path);
1626 Returns the list of directories where the engine searches for
1627 installed modules in a URL-based directory structure.
1629 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1630 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1631 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1632 provided by that module. A \c qmldir file is required for defining the
1633 type version mapping and possibly QML extensions plugins.
1635 By default, the list contains the directory of the application executable,
1636 paths specified in the \c QML_IMPORT_PATH environment variable,
1637 and the builtin \c ImportsPath from QLibraryInfo.
1639 \sa addImportPath(), setImportPathList()
1641 QStringList QQmlEngine::importPathList() const
1643 Q_D(const QQmlEngine);
1644 return d->importDatabase.importPathList();
1648 Sets \a paths as the list of directories where the engine searches for
1649 installed modules in a URL-based directory structure.
1651 By default, the list contains the directory of the application executable,
1652 paths specified in the \c QML_IMPORT_PATH environment variable,
1653 and the builtin \c ImportsPath from QLibraryInfo.
1655 \sa importPathList(), addImportPath()
1657 void QQmlEngine::setImportPathList(const QStringList &paths)
1660 d->importDatabase.setImportPathList(paths);
1665 Adds \a path as a directory where the engine searches for
1666 native plugins for imported modules (referenced in the \c qmldir file).
1668 By default, the list contains only \c ., i.e. the engine searches
1669 in the directory of the \c qmldir file itself.
1671 The newly added \a path will be first in the pluginPathList().
1673 \sa setPluginPathList()
1675 void QQmlEngine::addPluginPath(const QString& path)
1678 d->importDatabase.addPluginPath(path);
1683 Returns the list of directories 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 \sa addPluginPath(), setPluginPathList()
1691 QStringList QQmlEngine::pluginPathList() const
1693 Q_D(const QQmlEngine);
1694 return d->importDatabase.pluginPathList();
1698 Sets the list of directories where the engine searches for
1699 native plugins for imported modules (referenced in the \c qmldir file)
1702 By default, the list contains only \c ., i.e. the engine searches
1703 in the directory of the \c qmldir file itself.
1705 \sa pluginPathList(), addPluginPath()
1707 void QQmlEngine::setPluginPathList(const QStringList &paths)
1710 d->importDatabase.setPluginPathList(paths);
1714 Imports the plugin named \a filePath with the \a uri provided.
1715 Returns true if the plugin was successfully imported; otherwise returns false.
1717 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1719 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1721 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1724 return d->importDatabase.importPlugin(filePath, uri, errors);
1728 \property QQmlEngine::offlineStoragePath
1729 \brief the directory for storing offline user data
1731 Returns the directory where SQL and other offline
1734 QQuickWebView and the SQL databases created with openDatabase()
1737 The default is QML/OfflineStorage in the platform-standard
1738 user application data directory.
1740 Note that the path may not currently exist on the filesystem, so
1741 callers wanting to \e create new files at this location should create
1742 it first - see QDir::mkpath().
1744 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1747 d->offlineStoragePath = dir;
1750 QString QQmlEngine::offlineStoragePath() const
1752 Q_D(const QQmlEngine);
1753 return d->offlineStoragePath;
1756 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1760 if (!mo->superClass()) {
1761 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1762 propertyCache.insert(mo, rv);
1765 QQmlPropertyCache *super = cache(mo->superClass());
1766 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1767 propertyCache.insert(mo, rv);
1772 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1775 QList<QQmlType *> types;
1777 int maxMinorVersion = 0;
1779 const QMetaObject *metaObject = type->metaObject();
1781 while (metaObject) {
1782 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1783 type->majorVersion(), minorVersion);
1785 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1791 metaObject = metaObject->superClass();
1794 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1796 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1800 QQmlPropertyCache *raw = cache(type->metaObject());
1802 bool hasCopied = false;
1804 for (int ii = 0; ii < types.count(); ++ii) {
1805 QQmlType *currentType = types.at(ii);
1809 int rev = currentType->metaObjectRevision();
1810 int moIndex = types.count() - 1 - ii;
1812 if (raw->allowedRevisionCache[moIndex] != rev) {
1817 raw->allowedRevisionCache[moIndex] = rev;
1821 // Test revision compatibility - the basic rule is:
1822 // * Anything that is excluded, cannot overload something that is not excluded *
1824 // Signals override:
1825 // * other signals and methods of the same name.
1826 // * properties named on<Signal Name>
1827 // * automatic <property name>Changed notify signals
1829 // Methods override:
1830 // * other methods of the same name
1832 // Properties override:
1833 // * other elements of the same name
1835 bool overloadError = false;
1836 QString overloadName;
1839 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1840 !overloadError && iter != raw->stringCache.end();
1843 QQmlPropertyData *d = *iter;
1844 if (raw->isAllowedInRevision(d))
1845 continue; // Not excluded - no problems
1847 // check that a regular "name" overload isn't happening
1848 QQmlPropertyData *current = d;
1849 while (!overloadError && current) {
1850 current = d->overrideData(current);
1851 if (current && raw->isAllowedInRevision(current))
1852 overloadError = true;
1857 if (overloadError) {
1858 if (hasCopied) raw->release();
1860 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."));
1864 if (!hasCopied) raw->addref();
1865 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1867 if (minorVersion != maxMinorVersion) {
1869 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1875 QQmlMetaType::ModuleApiInstance *
1876 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1878 Locker locker(this);
1880 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1882 a = new QQmlMetaType::ModuleApiInstance;
1883 a->scriptCallback = module.script;
1884 a->qobjectCallback = module.qobject;
1885 a->instanceMetaObject = module.instanceMetaObject;
1886 moduleApiInstances.insert(module, a);
1892 bool QQmlEnginePrivate::isQObject(int t)
1894 Locker locker(this);
1895 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1898 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1900 Locker locker(this);
1901 int t = v.userType();
1902 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1904 return *(QObject **)(v.constData());
1906 return QQmlMetaType::toQObject(v, ok);
1910 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1912 Locker locker(this);
1913 if (m_compositeTypes.contains(t))
1914 return QQmlMetaType::Object;
1915 else if (m_qmlLists.contains(t))
1916 return QQmlMetaType::List;
1918 return QQmlMetaType::typeCategory(t);
1921 bool QQmlEnginePrivate::isList(int t) const
1923 Locker locker(this);
1924 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1927 int QQmlEnginePrivate::listType(int t) const
1929 Locker locker(this);
1930 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1931 if (iter != m_qmlLists.end())
1934 return QQmlMetaType::listType(t);
1937 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1939 Locker locker(this);
1940 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1941 if (iter != m_compositeTypes.end()) {
1942 return QQmlMetaObject((*iter)->rootPropertyCache);
1944 QQmlType *type = QQmlMetaType::qmlType(t);
1945 return QQmlMetaObject(type?type->baseMetaObject():0);
1949 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1951 Locker locker(this);
1952 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1953 if (iter != m_compositeTypes.end()) {
1954 return QQmlMetaObject((*iter)->rootPropertyCache);
1956 QQmlType *type = QQmlMetaType::qmlType(t);
1957 return QQmlMetaObject(type?type->metaObject():0);
1961 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1963 Locker locker(this);
1964 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1965 if (iter != m_compositeTypes.end()) {
1966 return (*iter)->rootPropertyCache;
1968 QQmlType *type = QQmlMetaType::qmlType(t);
1970 return type?cache(type->metaObject()):0;
1974 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1976 Locker locker(this);
1977 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1978 if (iter != m_compositeTypes.end()) {
1979 return (*iter)->rootPropertyCache;
1981 QQmlType *type = QQmlMetaType::qmlType(t);
1983 return type?cache(type->baseMetaObject()):0;
1987 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1989 QByteArray name = data->rootPropertyCache->className();
1991 QByteArray ptr = name + '*';
1992 QByteArray lst = "QQmlListProperty<" + name + '>';
1994 int ptr_type = QMetaType::registerNormalizedType(ptr,
1995 qMetaTypeDeleteHelper<QObject*>,
1996 qMetaTypeCreateHelper<QObject*>,
1997 qMetaTypeDestructHelper<QObject*>,
1998 qMetaTypeConstructHelper<QObject*>,
2000 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
2002 int lst_type = QMetaType::registerNormalizedType(lst,
2003 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
2004 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
2005 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
2006 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
2007 sizeof(QQmlListProperty<QObject>),
2008 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
2009 static_cast<QMetaObject*>(0));
2011 data->metaTypeId = ptr_type;
2012 data->listMetaTypeId = lst_type;
2013 data->isRegisteredWithEngine = true;
2015 Locker locker(this);
2016 m_qmlLists.insert(lst_type, ptr_type);
2017 // The QQmlCompiledData is not referenced here, but it is removed from this
2018 // hash in the QQmlCompiledData destructor
2019 m_compositeTypes.insert(ptr_type, data);
2022 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
2024 int ptr_type = data->metaTypeId;
2025 int lst_type = data->listMetaTypeId;
2027 Locker locker(this);
2028 m_qmlLists.remove(lst_type);
2029 m_compositeTypes.remove(ptr_type);
2032 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2034 return typeLoader.isTypeLoaded(url);
2037 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2039 return typeLoader.isScriptLoaded(url);
2042 bool QQml_isFileCaseCorrect(const QString &fileName)
2044 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2045 QFileInfo info(fileName);
2046 const QString absolute = info.absoluteFilePath();
2048 #if defined(Q_OS_MAC)
2049 const QString canonical = info.canonicalFilePath();
2050 #elif defined(Q_OS_WIN)
2051 wchar_t buffer[1024];
2053 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2054 if (rv == 0 || rv >= 1024) return true;
2055 rv = ::GetLongPathName(buffer, buffer, 1024);
2056 if (rv == 0 || rv >= 1024) return true;
2058 const QString canonical = QString::fromWCharArray(buffer);
2061 const int absoluteLength = absolute.length();
2062 const int canonicalLength = canonical.length();
2064 const int length = qMin(absoluteLength, canonicalLength);
2065 for (int ii = 0; ii < length; ++ii) {
2066 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2067 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2069 if (a.toLower() != c.toLower())
2081 \fn QQmlEngine *qmlEngine(const QObject *object)
2084 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2085 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2089 \fn QQmlContext *qmlContext(const QObject *object)
2092 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2093 QQmlEngine::contextForObject(object).