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 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.
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 type 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.
1614 The \a path may be a local filesystem directory, a
1615 \l {The Qt Resource System}{Qt Resource} path (\c {:/imports}), a
1616 \l {The Qt Resource System}{Qt Resource} url (\c {qrc:/imports}) or a URL.
1618 The \a path will be converted into canonical form before it
1619 is added to the import path list.
1621 The newly added \a path will be first in the importPathList().
1623 \sa setImportPathList(), {QML Modules}
1625 void QQmlEngine::addImportPath(const QString& path)
1628 d->importDatabase.addImportPath(path);
1632 Returns the list of directories where the engine searches for
1633 installed modules in a URL-based directory structure.
1635 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1636 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1637 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1638 provided by that module. A \c qmldir file is required for defining the
1639 type version mapping and possibly QML extensions plugins.
1641 By default, the list contains the directory of the application executable,
1642 paths specified in the \c QML_IMPORT_PATH environment variable,
1643 and the builtin \c ImportsPath from QLibraryInfo.
1645 \sa addImportPath(), setImportPathList()
1647 QStringList QQmlEngine::importPathList() const
1649 Q_D(const QQmlEngine);
1650 return d->importDatabase.importPathList();
1654 Sets \a paths as the list of directories where the engine searches for
1655 installed modules in a URL-based directory structure.
1657 By default, the list contains the directory of the application executable,
1658 paths specified in the \c QML_IMPORT_PATH environment variable,
1659 and the builtin \c ImportsPath from QLibraryInfo.
1661 \sa importPathList(), addImportPath()
1663 void QQmlEngine::setImportPathList(const QStringList &paths)
1666 d->importDatabase.setImportPathList(paths);
1671 Adds \a path as a directory where the engine searches for
1672 native plugins for imported modules (referenced in the \c qmldir file).
1674 By default, the list contains only \c ., i.e. the engine searches
1675 in the directory of the \c qmldir file itself.
1677 The newly added \a path will be first in the pluginPathList().
1679 \sa setPluginPathList()
1681 void QQmlEngine::addPluginPath(const QString& path)
1684 d->importDatabase.addPluginPath(path);
1689 Returns the list of directories where the engine searches for
1690 native plugins for imported modules (referenced in the \c qmldir file).
1692 By default, the list contains only \c ., i.e. the engine searches
1693 in the directory of the \c qmldir file itself.
1695 \sa addPluginPath(), setPluginPathList()
1697 QStringList QQmlEngine::pluginPathList() const
1699 Q_D(const QQmlEngine);
1700 return d->importDatabase.pluginPathList();
1704 Sets the list of directories where the engine searches for
1705 native plugins for imported modules (referenced in the \c qmldir file)
1708 By default, the list contains only \c ., i.e. the engine searches
1709 in the directory of the \c qmldir file itself.
1711 \sa pluginPathList(), addPluginPath()
1713 void QQmlEngine::setPluginPathList(const QStringList &paths)
1716 d->importDatabase.setPluginPathList(paths);
1720 Imports the plugin named \a filePath with the \a uri provided.
1721 Returns true if the plugin was successfully imported; otherwise returns false.
1723 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1725 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1727 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1730 return d->importDatabase.importPlugin(filePath, uri, errors);
1734 \property QQmlEngine::offlineStoragePath
1735 \brief the directory for storing offline user data
1737 Returns the directory where SQL and other offline
1740 QQuickWebView and the SQL databases created with openDatabase()
1743 The default is QML/OfflineStorage in the platform-standard
1744 user application data directory.
1746 Note that the path may not currently exist on the filesystem, so
1747 callers wanting to \e create new files at this location should create
1748 it first - see QDir::mkpath().
1750 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1753 d->offlineStoragePath = dir;
1756 QString QQmlEngine::offlineStoragePath() const
1758 Q_D(const QQmlEngine);
1759 return d->offlineStoragePath;
1762 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1766 if (!mo->superClass()) {
1767 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1768 propertyCache.insert(mo, rv);
1771 QQmlPropertyCache *super = cache(mo->superClass());
1772 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1773 propertyCache.insert(mo, rv);
1778 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1781 QList<QQmlType *> types;
1783 int maxMinorVersion = 0;
1785 const QMetaObject *metaObject = type->metaObject();
1787 while (metaObject) {
1788 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1789 type->majorVersion(), minorVersion);
1791 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1797 metaObject = metaObject->superClass();
1800 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1802 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1806 QQmlPropertyCache *raw = cache(type->metaObject());
1808 bool hasCopied = false;
1810 for (int ii = 0; ii < types.count(); ++ii) {
1811 QQmlType *currentType = types.at(ii);
1815 int rev = currentType->metaObjectRevision();
1816 int moIndex = types.count() - 1 - ii;
1818 if (raw->allowedRevisionCache[moIndex] != rev) {
1823 raw->allowedRevisionCache[moIndex] = rev;
1827 // Test revision compatibility - the basic rule is:
1828 // * Anything that is excluded, cannot overload something that is not excluded *
1830 // Signals override:
1831 // * other signals and methods of the same name.
1832 // * properties named on<Signal Name>
1833 // * automatic <property name>Changed notify signals
1835 // Methods override:
1836 // * other methods of the same name
1838 // Properties override:
1839 // * other elements of the same name
1841 bool overloadError = false;
1842 QString overloadName;
1845 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1846 !overloadError && iter != raw->stringCache.end();
1849 QQmlPropertyData *d = *iter;
1850 if (raw->isAllowedInRevision(d))
1851 continue; // Not excluded - no problems
1853 // check that a regular "name" overload isn't happening
1854 QQmlPropertyData *current = d;
1855 while (!overloadError && current) {
1856 current = d->overrideData(current);
1857 if (current && raw->isAllowedInRevision(current))
1858 overloadError = true;
1863 if (overloadError) {
1864 if (hasCopied) raw->release();
1866 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."));
1870 if (!hasCopied) raw->addref();
1871 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1873 if (minorVersion != maxMinorVersion) {
1875 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1881 QQmlMetaType::ModuleApiInstance *
1882 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1884 Locker locker(this);
1886 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1888 a = new QQmlMetaType::ModuleApiInstance;
1889 a->scriptCallback = module.script;
1890 a->qobjectCallback = module.qobject;
1891 a->instanceMetaObject = module.instanceMetaObject;
1892 moduleApiInstances.insert(module, a);
1898 bool QQmlEnginePrivate::isQObject(int t)
1900 Locker locker(this);
1901 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1904 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1906 Locker locker(this);
1907 int t = v.userType();
1908 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1910 return *(QObject **)(v.constData());
1912 return QQmlMetaType::toQObject(v, ok);
1916 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1918 Locker locker(this);
1919 if (m_compositeTypes.contains(t))
1920 return QQmlMetaType::Object;
1921 else if (m_qmlLists.contains(t))
1922 return QQmlMetaType::List;
1924 return QQmlMetaType::typeCategory(t);
1927 bool QQmlEnginePrivate::isList(int t) const
1929 Locker locker(this);
1930 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1933 int QQmlEnginePrivate::listType(int t) const
1935 Locker locker(this);
1936 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1937 if (iter != m_qmlLists.end())
1940 return QQmlMetaType::listType(t);
1943 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1945 Locker locker(this);
1946 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1947 if (iter != m_compositeTypes.end()) {
1948 return QQmlMetaObject((*iter)->rootPropertyCache);
1950 QQmlType *type = QQmlMetaType::qmlType(t);
1951 return QQmlMetaObject(type?type->baseMetaObject():0);
1955 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(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->metaObject():0);
1967 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1969 Locker locker(this);
1970 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1971 if (iter != m_compositeTypes.end()) {
1972 return (*iter)->rootPropertyCache;
1974 QQmlType *type = QQmlMetaType::qmlType(t);
1976 return type?cache(type->metaObject()):0;
1980 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1982 Locker locker(this);
1983 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1984 if (iter != m_compositeTypes.end()) {
1985 return (*iter)->rootPropertyCache;
1987 QQmlType *type = QQmlMetaType::qmlType(t);
1989 return type?cache(type->baseMetaObject()):0;
1993 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1995 QByteArray name = data->rootPropertyCache->className();
1997 QByteArray ptr = name + '*';
1998 QByteArray lst = "QQmlListProperty<" + name + '>';
2000 int ptr_type = QMetaType::registerNormalizedType(ptr,
2001 qMetaTypeDeleteHelper<QObject*>,
2002 qMetaTypeCreateHelper<QObject*>,
2003 qMetaTypeDestructHelper<QObject*>,
2004 qMetaTypeConstructHelper<QObject*>,
2006 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
2008 int lst_type = QMetaType::registerNormalizedType(lst,
2009 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
2010 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
2011 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
2012 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
2013 sizeof(QQmlListProperty<QObject>),
2014 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
2015 static_cast<QMetaObject*>(0));
2017 data->metaTypeId = ptr_type;
2018 data->listMetaTypeId = lst_type;
2019 data->isRegisteredWithEngine = true;
2021 Locker locker(this);
2022 m_qmlLists.insert(lst_type, ptr_type);
2023 // The QQmlCompiledData is not referenced here, but it is removed from this
2024 // hash in the QQmlCompiledData destructor
2025 m_compositeTypes.insert(ptr_type, data);
2028 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
2030 int ptr_type = data->metaTypeId;
2031 int lst_type = data->listMetaTypeId;
2033 Locker locker(this);
2034 m_qmlLists.remove(lst_type);
2035 m_compositeTypes.remove(ptr_type);
2038 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2040 return typeLoader.isTypeLoaded(url);
2043 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2045 return typeLoader.isScriptLoaded(url);
2048 bool QQml_isFileCaseCorrect(const QString &fileName)
2050 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2051 QFileInfo info(fileName);
2052 const QString absolute = info.absoluteFilePath();
2054 #if defined(Q_OS_MAC)
2055 const QString canonical = info.canonicalFilePath();
2056 #elif defined(Q_OS_WIN)
2057 wchar_t buffer[1024];
2059 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2060 if (rv == 0 || rv >= 1024) return true;
2061 rv = ::GetLongPathName(buffer, buffer, 1024);
2062 if (rv == 0 || rv >= 1024) return true;
2064 const QString canonical = QString::fromWCharArray(buffer);
2067 const int absoluteLength = absolute.length();
2068 const int canonicalLength = canonical.length();
2070 const int length = qMin(absoluteLength, canonicalLength);
2071 for (int ii = 0; ii < length; ++ii) {
2072 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2073 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2075 if (a.toLower() != c.toLower())
2087 \fn QQmlEngine *qmlEngine(const QObject *object)
2090 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2091 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2095 \fn QQmlContext *qmlContext(const QObject *object)
2098 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2099 QQmlEngine::contextForObject(object).