1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
72 #include <private/qqmlboundsignal_p.h>
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtCore/qthread.h>
84 #include <private/qthread_p.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
87 #include <private/qobject_p.h>
88 #include <private/qmetaobject_p.h>
90 #include <private/qqmllocale_p.h>
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
97 #define CSIDL_APPDATA 0x001a // <username>\Application Data
100 Q_DECLARE_METATYPE(QQmlProperty)
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
106 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107 QQmlEnginePrivate::registerQtQuick2Types(uri, versionMajor, versionMinor);
108 QQmlValueTypeFactory::registerValueTypes(uri, versionMajor, versionMinor);
113 \instantiates QObject
114 \inqmlmodule QtQuick 2
115 \ingroup qml-utility-elements
117 \brief A basic QML type
119 The QtObject type is a non-visual element which contains only the
122 It can be useful to create a QtObject if you need an extremely
123 lightweight type to enclose a set of custom properties:
125 \snippet qml/qtobject.qml 0
127 It can also be useful for C++ integration, as it is just a plain
128 QObject. See the QObject documentation for further details.
131 \qmlproperty string QtObject::objectName
132 This property holds the QObject::objectName for this specific object instance.
134 This allows a C++ application to locate an item within a QML component
135 using the QObject::findChild() method. For example, the following C++
136 application locates the child \l Rectangle item and dynamically changes its
145 width: 200; height: 200
159 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
162 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
164 item->setProperty("color", QColor(Qt::yellow));
168 bool QQmlEnginePrivate::qml_debugging_enabled = false;
170 // these types are part of the QML language
171 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
173 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
174 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
178 // These QtQuick types' implementation resides in the QtQml module
179 void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
181 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor, "ListElement");
182 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor, "ListModel", new QQuickListModelParser);
183 qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
186 void QQmlEnginePrivate::defineQtQuick2Module()
188 // register the base types into the QtQuick namespace
189 registerBaseTypes("QtQuick",2,0);
191 // register the QtQuick2 types which are implemented in the QtQml module.
192 registerQtQuick2Types("QtQuick",2,0);
193 qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
198 \class QQmlImageProviderBase
199 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
202 Image providers must be registered with the QML engine. The only information the QML
203 engine knows about image providers is the type of image data they provide. To use an
204 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
205 to a QQuickImageProvider pointer.
207 \sa QQuickImageProvider, QQuickTextureFactory
211 \enum QQmlImageProviderBase::ImageType
213 Defines the type of image supported by this image provider.
215 \value Image The Image Provider provides QImage images.
216 The QQuickImageProvider::requestImage() method will be called for all image requests.
217 \value Pixmap The Image Provider provides QPixmap images.
218 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
219 \value Texture The Image Provider provides QSGTextureProvider based images.
220 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
224 \enum QQmlImageProviderBase::Flag
226 Defines specific requirements or features of this image provider.
228 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
229 run in a separate thread, which allows the provider to spend as much time as needed
230 on producing the image without blocking the main thread.
234 QQmlImageProviderBase::QQmlImageProviderBase()
239 QQmlImageProviderBase::~QQmlImageProviderBase()
246 \instantiates QQmlEnginePrivate
247 \ingroup qml-utility-elements
248 \brief The QML global Qt object provides useful enums and functions from Qt.
250 \keyword QmlGlobalQtObject
252 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
254 The \c Qt object is a global object with utility functions, properties and enums.
256 It is not instantiable; to use it, call the members of the global \c Qt object directly.
263 color: Qt.rgba(1, 0, 0, 1)
264 text: Qt.md5("hello, world")
271 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
272 the \l Qt::LeftButton and \l Qt::RightButton enumeration values as \c Qt.LeftButton and \c Qt.RightButton.
277 The Qt object also contains helper functions for creating objects of specific
278 data types. This is primarily useful when setting the properties of an item
279 when the property has one of the following types:
281 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
282 \li \c point - use \l{Qt::point()}{Qt.point()}
283 \li \c size - use \l{Qt::size()}{Qt.size()}
286 If the QtQuick module has been imported, the following helper functions for
287 creating objects of specific data types are also available for clients to use:
289 \li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
290 \li \c font - use \l{Qt::font()}{Qt.font()}
291 \li \c vector2d - use \l{Qt::vector2d()}{Qt.vector2d()}
292 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
293 \li \c vector4d - use \l{Qt::vector4d()}{Qt.vector4d()}
294 \li \c quaternion - use \l{Qt::quaternion()}{Qt.quaternion()}
295 \li \c matrix4x4 - use \l{Qt::matrix4x4()}{Qt.matrix4x4()}
298 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
300 \section1 Date/Time Formatters
302 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
305 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
306 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
307 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
310 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
313 \section1 Dynamic Object Creation
314 The following functions on the global object allow you to dynamically create QML
315 items from files or strings. See \l{Dynamic QML Object Creation from JavaScript} for an overview
319 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
320 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
324 \section1 Other Functions
326 The following functions are also on the Qt object.
329 \li \l{Qt::quit()}{Qt.quit()}
330 \li \l{Qt::md5()}{Qt.md5(string)}
331 \li \l{Qt::btoa()}{string Qt.btoa(string)}
332 \li \l{Qt::atob()}{string Qt.atob(string)}
333 \li \l{Qt::binding()}{object Qt.binding(function)}
334 \li \l{Qt::locale()}{object Qt.locale()}
335 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
336 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
337 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
342 \qmlproperty object Qt::application
345 The \c application object provides access to global application state
346 properties shared by many QML components.
352 \li \c application.active
354 This read-only property indicates whether the application is the top-most and focused
355 application, and the user is able to interact with the application. The property
356 is false when the application is in the background, the device keylock or screen
357 saver is active, the screen backlight is turned off, or the global system dialog
358 is being displayed on top of the application. It can be used for stopping and
359 pausing animations, timers and active processing of data in order to save device
360 battery power and free device memory and processor load when the application is not
364 \li \c application.layoutDirection
366 This read-only property can be used to query the default layout direction of the
367 application. On system start-up, the default layout direction depends on the
368 application's language. The property has a value of \c Qt.RightToLeft in locales
369 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
370 where the reading direction flows from left to right. You can bind to this
371 property to customize your application layouts to support both layout directions.
376 \li Qt.LeftToRight - Text and graphics elements should be positioned
378 \li Qt.RightToLeft - Text and graphics elements should be positioned
384 The following example uses the \c application object to indicate
385 whether the application is currently active:
387 \snippet qml/application.qml document
391 \qmlproperty object Qt::inputMethod
394 The \c inputMethod object allows access to application's QInputMethod object
395 and all its properties and slots. See the QInputMethod documentation for
401 \qmlmethod object Qt::include(string url, jsobject callback)
403 Includes another JavaScript file. This method can only be used from within JavaScript files,
404 and not regular QML files.
406 This imports all functions from \a url into the current script's namespace.
408 Qt.include() returns an object that describes the status of the operation. The object has
409 a single property, \c {status}, that is set to one of the following values:
412 \header \li Symbol \li Value \li Description
413 \row \li result.OK \li 0 \li The include completed successfully.
414 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
415 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
416 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
417 An additional \c exception property will be set in this case.
420 The \c status property will be updated as the operation progresses.
422 If provided, \a callback is invoked when the operation completes. The callback is passed
423 the same object as is returned from the Qt.include() call.
425 // Qt.include() is implemented in qv8include.cpp
428 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
429 : propertyCapture(0), rootContext(0), isDebugging(false),
430 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
431 cleanup(0), erroredBindings(0), inProgressCreations(0),
432 workerScriptEngine(0), activeVME(0),
433 networkAccessManager(0), networkAccessManagerFactory(0),
434 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
435 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
439 QQmlEnginePrivate::~QQmlEnginePrivate()
441 if (inProgressCreations)
442 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
445 QQmlCleanup *c = cleanup;
447 if (cleanup) cleanup->prev = &cleanup;
453 doDeleteInEngineThread();
455 if (incubationController) incubationController->d = 0;
456 incubationController = 0;
461 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
463 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
465 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
466 delete (*iter)->qobjectApi;
469 for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
470 iter.value()->isRegisteredWithEngine = false;
473 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
475 QObjectPrivate *p = QObjectPrivate::get(o);
476 if (p->declarativeData) {
477 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
478 if (d->ownContext && d->context) {
479 d->context->destroy();
483 // Mark this object as in the process of deletion to
484 // prevent it resolving in bindings
485 QQmlData::markAsDeleted(o);
489 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
491 static_cast<QQmlData *>(d)->destroyed(o);
494 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
496 static_cast<QQmlData *>(d)->parentChanged(o, p);
499 class QQmlThreadNotifierProxyObject : public QObject
502 QPointer<QObject> target;
504 virtual int qt_metacall(QMetaObject::Call, int methodIndex, void **a) {
508 QMetaMethod method = target->metaObject()->method(methodIndex);
509 Q_ASSERT(method.methodType() == QMetaMethod::Signal);
510 int signalIndex = QMetaObjectPrivate::signalIndex(method);
511 QQmlData *ddata = QQmlData::get(target, false);
512 QQmlNotifierEndpoint *ep = ddata->notify(signalIndex);
513 if (ep) QQmlNotifier::emitNotify(ep, a);
521 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
523 QQmlData *ddata = QQmlData::get(object, false);
524 if (!ddata) return; // Probably being deleted
526 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
527 // that they're exposed to. However, to make writing "worker objects" that calculate data
528 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
529 // QQmlEngine to emit signals from a different thread. These signals are then automatically
530 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
531 // by the qqmlecmascript::threadSignal() autotest.
532 if (ddata->notifyList &&
533 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
535 if (!QObjectPrivate::get(object)->threadData->thread)
538 QMetaMethod m = QMetaObjectPrivate::signal(object->metaObject(), index);
539 QList<QByteArray> parameterTypes = m.parameterTypes();
541 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
542 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
544 types[0] = 0; // return type
545 args[0] = 0; // return value
547 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
548 const QByteArray &typeName = parameterTypes.at(ii);
549 if (typeName.endsWith('*'))
550 types[ii + 1] = QMetaType::VoidStar;
552 types[ii + 1] = QMetaType::type(typeName);
554 if (!types[ii + 1]) {
555 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
556 "(Make sure '%s' is registered using qRegisterMetaType().)",
557 typeName.constData(), typeName.constData());
563 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
566 QMetaCallEvent *ev = new QMetaCallEvent(m.methodIndex(), 0, 0, object, index,
567 parameterTypes.count() + 1, types, args);
569 QQmlThreadNotifierProxyObject *mpo = new QQmlThreadNotifierProxyObject;
570 mpo->target = object;
571 mpo->moveToThread(QObjectPrivate::get(object)->threadData->thread);
572 QCoreApplication::postEvent(mpo, ev);
575 QQmlNotifierEndpoint *ep = ddata->notify(index);
576 if (ep) QQmlNotifier::emitNotify(ep, a);
580 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
582 return static_cast<QQmlData *>(d)->endpointCount(index);
585 bool QQmlData::isSignalConnected(QAbstractDeclarativeData *d, const QObject *, int index)
587 return static_cast<QQmlData *>(d)->signalHasEndpoint(index);
590 int QQmlData::endpointCount(int index)
593 QQmlNotifierEndpoint *ep = notify(index);
604 void QQmlData::markAsDeleted(QObject *o)
606 QQmlData::setQueuedForDeletion(o);
608 QObjectPrivate *p = QObjectPrivate::get(o);
609 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
610 QQmlData::markAsDeleted(*it);
614 void QQmlData::setQueuedForDeletion(QObject *object)
617 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
618 if (!priv->wasDeleted && priv->declarativeData) {
619 QQmlData *ddata = QQmlData::get(object, false);
620 if (ddata->ownContext && ddata->context)
621 ddata->context->emitDestruction();
622 ddata->isQueuedForDeletion = true;
628 void QQmlEnginePrivate::init()
632 static bool firstTime = true;
634 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
635 registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
641 qRegisterMetaType<QVariant>("QVariant");
642 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
643 qRegisterMetaType<QJSValue>("QJSValue");
644 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
645 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
646 qRegisterMetaType<QList<int> >("QList<int>");
647 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
649 v8engine()->setEngine(q);
651 rootContext = new QQmlContext(q,true);
653 if (QCoreApplication::instance()->thread() == q->thread() &&
654 QQmlEngineDebugService::isDebuggingEnabled()) {
656 QQmlEngineDebugService::instance()->addEngine(q);
657 QV8DebugService::initialize(v8engine());
658 QV8ProfilerService::initialize();
659 QQmlProfilerService::initialize();
660 QDebugMessageService::instance();
663 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
664 if (!dataLocation.isEmpty())
665 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
666 + QDir::separator() + QLatin1String("QML")
667 + QDir::separator() + QLatin1String("OfflineStorage");
670 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
673 if (!workerScriptEngine)
674 workerScriptEngine = new QQuickWorkerScriptEngine(q);
675 return workerScriptEngine;
682 \brief The QQmlEngine class provides an environment for instantiating QML components.
685 Each QML component is instantiated in a QQmlContext.
686 QQmlContext's are essential for passing data to QML
687 components. In QML, contexts are arranged hierarchically and this
688 hierarchy is managed by the QQmlEngine.
690 Prior to creating any QML components, an application must have
691 created a QQmlEngine to gain access to a QML context. The
692 following example shows how to create a simple Text item.
696 QQmlComponent component(&engine);
697 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
698 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
700 //add item to view, etc
704 In this case, the Text item will be created in the engine's
705 \l {QQmlEngine::rootContext()}{root context}.
707 Note that the QtQuick 1 version is called QDeclarativeEngine.
709 \sa QQmlComponent, QQmlContext
713 Create a new QQmlEngine with the given \a parent.
715 QQmlEngine::QQmlEngine(QObject *parent)
716 : QJSEngine(*new QQmlEnginePrivate(this), parent)
723 Destroys the QQmlEngine.
725 Any QQmlContext's created on this engine will be
726 invalidated, but not destroyed (unless they are parented to the
729 QQmlEngine::~QQmlEngine()
732 if (d->isDebugging) {
733 QQmlEngineDebugService::instance()->remEngine(this);
736 // Emit onDestruction signals for the root context before
737 // we destroy the contexts, engine, Module APIs etc. that
738 // may be required to handle the destruction signal.
739 QQmlContextData::get(rootContext())->emitDestruction();
741 // if we are the parent of any of the qobject module api instances,
742 // we need to remove them from our internal list, in order to prevent
743 // a segfault in engine private dtor.
744 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
745 QObject *currQObjectApi = 0;
746 QQmlMetaType::ModuleApiInstance *currInstance = 0;
747 foreach (const QQmlMetaType::ModuleApi &key, keys) {
748 currInstance = d->moduleApiInstances.value(key);
749 currQObjectApi = currInstance->qobjectApi;
750 if (this->children().contains(currQObjectApi)) {
751 delete currQObjectApi;
753 d->moduleApiInstances.remove(key);
757 if (d->incubationController)
758 d->incubationController->d = 0;
761 /*! \fn void QQmlEngine::quit()
762 This signal is emitted when the QML loaded by the engine would like to quit.
765 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
766 This signal is emitted when \a warnings messages are generated by QML.
770 Clears the engine's internal component cache.
772 This function causes the property metadata of all components previously
773 loaded by the engine to be destroyed. All previously loaded components and
774 the property bindings for all extant objects created from those components will
777 This function returns the engine to a state where it does not contain any loaded
778 component data. This may be useful in order to reload a smaller subset of the
779 previous component set, or to load a new version of a previously loaded component.
781 Once the component cache has been cleared, components must be loaded before
782 any new objects can be created.
784 \sa trimComponentCache()
786 void QQmlEngine::clearComponentCache()
789 d->typeLoader.clearCache();
793 Trims the engine's internal component cache.
795 This function causes the property metadata of any loaded components which are
796 not currently in use to be destroyed.
798 A component is considered to be in use if there are any extant instances of
799 the component itself, any instances of other components that use the component,
800 or any objects instantiated by any of those components.
802 \sa clearComponentCache()
804 void QQmlEngine::trimComponentCache()
807 d->typeLoader.trimCache();
811 Returns the engine's root context.
813 The root context is automatically created by the QQmlEngine.
814 Data that should be available to all QML component instances
815 instantiated by the engine should be put in the root context.
817 Additional data that should only be available to a subset of
818 component instances should be added to sub-contexts parented to the
821 QQmlContext *QQmlEngine::rootContext() const
823 Q_D(const QQmlEngine);
824 return d->rootContext;
828 Sets the \a factory to use for creating QNetworkAccessManager(s).
830 QNetworkAccessManager is used for all network access by QML. By
831 implementing a factory it is possible to create custom
832 QNetworkAccessManager with specialized caching, proxy and cookie
835 The factory must be set before executing the engine.
837 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
840 QMutexLocker locker(&d->mutex);
841 d->networkAccessManagerFactory = factory;
845 Returns the current QQmlNetworkAccessManagerFactory.
847 \sa setNetworkAccessManagerFactory()
849 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
851 Q_D(const QQmlEngine);
852 return d->networkAccessManagerFactory;
855 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
858 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
860 void *args[] = { 0 };
861 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
865 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
867 QMutexLocker locker(&mutex);
868 QNetworkAccessManager *nam;
869 if (networkAccessManagerFactory) {
870 nam = networkAccessManagerFactory->create(parent);
872 nam = new QNetworkAccessManager(parent);
878 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
880 Q_Q(const QQmlEngine);
881 if (!networkAccessManager)
882 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
883 return networkAccessManager;
887 Returns a common QNetworkAccessManager which can be used by any QML
888 type instantiated by this engine.
890 If a QQmlNetworkAccessManagerFactory has been set and a
891 QNetworkAccessManager has not yet been created, the
892 QQmlNetworkAccessManagerFactory will be used to create the
893 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
894 will have no proxy or cache set.
896 \sa setNetworkAccessManagerFactory()
898 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
900 Q_D(const QQmlEngine);
901 return d->getNetworkAccessManager();
906 Sets the \a provider to use for images requested via the \e
907 image: url scheme, with host \a providerId. The QQmlEngine
908 takes ownership of \a provider.
910 Image providers enable support for pixmap and threaded image
911 requests. See the QQuickImageProvider documentation for details on
912 implementing and using image providers.
914 All required image providers should be added to the engine before any
915 QML sources files are loaded.
917 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
919 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
922 QMutexLocker locker(&d->mutex);
923 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
927 Returns the image provider set for \a providerId.
929 Returns the provider if it was found; otherwise returns 0.
931 \sa QQuickImageProvider
933 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
935 Q_D(const QQmlEngine);
936 QMutexLocker locker(&d->mutex);
937 return d->imageProviders.value(providerId).data();
941 Removes the image provider for \a providerId.
943 \sa addImageProvider(), QQuickImageProvider
945 void QQmlEngine::removeImageProvider(const QString &providerId)
948 QMutexLocker locker(&d->mutex);
949 d->imageProviders.take(providerId);
953 Return the base URL for this engine. The base URL is only used to
954 resolve components when a relative URL is passed to the
955 QQmlComponent constructor.
957 If a base URL has not been explicitly set, this method returns the
958 application's current working directory.
962 QUrl QQmlEngine::baseUrl() const
964 Q_D(const QQmlEngine);
965 if (d->baseUrl.isEmpty()) {
966 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
973 Set the base URL for this engine to \a url.
977 void QQmlEngine::setBaseUrl(const QUrl &url)
984 Returns true if warning messages will be output to stderr in addition
985 to being emitted by the warnings() signal, otherwise false.
987 The default value is true.
989 bool QQmlEngine::outputWarningsToStandardError() const
991 Q_D(const QQmlEngine);
992 return d->outputWarningsToStdErr;
996 Set whether warning messages will be output to stderr to \a enabled.
998 If \a enabled is true, any warning messages generated by QML will be
999 output to stderr and emitted by the warnings() signal. If \a enabled
1000 is false, on the warnings() signal will be emitted. This allows
1001 applications to handle warning output themselves.
1003 The default value is true.
1005 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
1008 d->outputWarningsToStdErr = enabled;
1012 Returns the QQmlContext for the \a object, or 0 if no
1013 context has been set.
1015 When the QQmlEngine instantiates a QObject, the context is
1018 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
1023 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
1026 static_cast<QQmlData *>(priv->declarativeData);
1030 else if (data->outerContext)
1031 return data->outerContext->asQQmlContext();
1037 Sets the QQmlContext for the \a object to \a context.
1038 If the \a object already has a context, a warning is
1039 output, but the context is not changed.
1041 When the QQmlEngine instantiates a QObject, the context is
1044 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1046 if (!object || !context)
1049 QQmlData *data = QQmlData::get(object, true);
1050 if (data->context) {
1051 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1055 QQmlContextData *contextData = QQmlContextData::get(context);
1056 contextData->addObject(object);
1060 \enum QQmlEngine::ObjectOwnership
1062 Ownership controls whether or not QML automatically destroys the
1063 QObject when the object is garbage collected by the JavaScript
1064 engine. The two ownership options are:
1066 \value CppOwnership The object is owned by C++ code, and will
1067 never be deleted by QML. The JavaScript destroy() method cannot be
1068 used on objects with CppOwnership. This option is similar to
1069 QScriptEngine::QtOwnership.
1071 \value JavaScriptOwnership The object is owned by JavaScript.
1072 When the object is returned to QML as the return value of a method
1073 call or property access, QML will track it, and delete the object
1074 if there are no remaining JavaScript references to it and it has no
1075 QObject::parent(). An object tracked by one QQmlEngine
1076 will be deleted during that QQmlEngine's destructor, and thus
1077 JavaScript references between objects with JavaScriptOwnership from
1078 two different engines will not be valid after the deletion of one of
1079 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1081 Generally an application doesn't need to set an object's ownership
1082 explicitly. QML uses a heuristic to set the default object
1083 ownership. By default, an object that is created by QML has
1084 JavaScriptOwnership. The exception to this are the root objects
1085 created by calling QQmlComponent::create() or
1086 QQmlComponent::beginCreate() which have CppOwnership by
1087 default. The ownership of these root-level objects is considered to
1088 have been transferred to the C++ caller.
1090 Objects not-created by QML have CppOwnership by default. The
1091 exception to this is objects returned from a C++ method call. The
1092 ownership of these objects is passed to JavaScript.
1094 Calling setObjectOwnership() overrides the default ownership
1095 heuristic used by QML.
1099 Sets the \a ownership of \a object.
1101 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1106 QQmlData *ddata = QQmlData::get(object, true);
1110 ddata->indestructible = (ownership == CppOwnership)?true:false;
1111 ddata->explicitIndestructibleSet = true;
1115 Returns the ownership of \a object.
1117 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1120 return CppOwnership;
1122 QQmlData *ddata = QQmlData::get(object, false);
1124 return CppOwnership;
1126 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1129 bool QQmlEngine::event(QEvent *e)
1132 if (e->type() == QEvent::User)
1133 d->doDeleteInEngineThread();
1135 return QJSEngine::event(e);
1138 void QQmlEnginePrivate::doDeleteInEngineThread()
1140 QFieldList<Deletable, &Deletable::next> list;
1142 list.copyAndClear(toDeleteInEngineThread);
1145 while (Deletable *d = list.takeFirst())
1149 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1151 QQmlData *data = QQmlData::get(object);
1153 if (data && data->compiledData && data->deferredIdx) {
1154 QQmlObjectCreatingProfiler prof;
1156 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1157 prof.setTypeName(type ? type->qmlTypeName()
1158 : QString::fromUtf8(object->metaObject()->className()));
1159 if (data->outerContext)
1160 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1162 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1164 QQmlComponentPrivate::ConstructionState state;
1165 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1167 // Release the reference for the deferral action (we still have one from construction)
1168 data->compiledData->release();
1169 data->compiledData = 0;
1171 QQmlComponentPrivate::complete(ep, &state);
1175 QQmlContext *qmlContext(const QObject *obj)
1177 return QQmlEngine::contextForObject(obj);
1180 QQmlEngine *qmlEngine(const QObject *obj)
1182 QQmlData *data = QQmlData::get(obj, false);
1183 if (!data || !data->context)
1185 return data->context->engine;
1188 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1190 QQmlData *data = QQmlData::get(object);
1192 return 0; // Attached properties are only on objects created by QML
1194 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1198 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1202 rv = pf(const_cast<QObject *>(object));
1205 data->attachedProperties()->insert(id, rv);
1210 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1211 const QMetaObject *attachedMetaObject, bool create)
1214 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1216 if (*idCache == -1 || !object)
1219 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1222 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1224 #ifndef QQML_NO_DEBUG_PROTOCOL
1225 if (!QQmlEnginePrivate::qml_debugging_enabled
1227 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1229 QQmlEnginePrivate::qml_debugging_enabled = true;
1234 class QQmlDataExtended {
1237 ~QQmlDataExtended();
1239 QHash<int, QObject *> attachedProperties;
1242 QQmlDataExtended::QQmlDataExtended()
1246 QQmlDataExtended::~QQmlDataExtended()
1250 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1253 layout(endpoint->next);
1255 int index = endpoint->sourceSignal;
1256 index = qMin(index, 0xFFFF - 1);
1258 endpoint->next = notifies[index];
1259 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1260 endpoint->prev = ¬ifies[index];
1261 notifies[index] = endpoint;
1264 void QQmlData::NotifyList::layout()
1266 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1269 QQmlNotifierEndpoint **old = notifies;
1270 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1271 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1272 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1273 sizeof(QQmlNotifierEndpoint*);
1274 memset(notifies + notifiesSize, 0, memsetSize);
1276 if (notifies != old) {
1277 for (int ii = 0; ii < notifiesSize; ++ii)
1279 notifies[ii]->prev = ¬ifies[ii];
1282 notifiesSize = maximumTodoIndex + 1;
1287 maximumTodoIndex = 0;
1291 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1294 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1295 notifyList->connectionMask = 0;
1296 notifyList->maximumTodoIndex = 0;
1297 notifyList->notifiesSize = 0;
1298 notifyList->todo = 0;
1299 notifyList->notifies = 0;
1302 Q_ASSERT(!endpoint->isConnected());
1304 index = qMin(index, 0xFFFF - 1);
1305 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1307 if (index < notifyList->notifiesSize) {
1309 endpoint->next = notifyList->notifies[index];
1310 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1311 endpoint->prev = ¬ifyList->notifies[index];
1312 notifyList->notifies[index] = endpoint;
1315 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1317 endpoint->next = notifyList->todo;
1318 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1319 endpoint->prev = ¬ifyList->todo;
1320 notifyList->todo = endpoint;
1325 index MUST in the range returned by QObjectPrivate::signalIndex()
1326 This is different than the index returned by QMetaMethod::methodIndex()
1328 bool QQmlData::signalHasEndpoint(int index)
1330 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1333 QHash<int, QObject *> *QQmlData::attachedProperties() const
1335 if (!extendedData) extendedData = new QQmlDataExtended;
1336 return &extendedData->attachedProperties;
1339 void QQmlData::destroyed(QObject *object)
1341 if (nextContextObject)
1342 nextContextObject->prevContextObject = prevContextObject;
1343 if (prevContextObject)
1344 *prevContextObject = nextContextObject;
1346 QQmlAbstractBinding *binding = bindings;
1348 QQmlAbstractBinding *next = binding->nextBinding();
1349 binding->setAddedToObject(false);
1350 binding->setNextBinding(0);
1356 compiledData->release();
1360 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1361 while (signalHandler) {
1362 if (signalHandler->isEvaluating()) {
1363 // The object is being deleted during signal handler evaluation.
1364 // This will cause a crash due to invalid memory access when the
1365 // evaluation has completed.
1366 // Abort with a friendly message instead.
1367 QString locationString;
1368 QQmlBoundSignalExpression *expr = signalHandler->expression();
1370 QString fileName = expr->sourceFile();
1371 if (fileName.isEmpty())
1372 fileName = QStringLiteral("<Unknown File>");
1373 locationString.append(fileName);
1374 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1375 QString source = expr->expression();
1376 if (source.size() > 100) {
1377 source.truncate(96);
1378 source.append(QStringLiteral(" ..."));
1380 locationString.append(source);
1382 locationString = QStringLiteral("<Unknown Location>");
1384 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1385 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1386 "instead), or the application is running a nested event loop.\n"
1387 "This behavior is NOT supported!\n"
1388 "%s", object, qPrintable(locationString));
1391 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1392 signalHandler->m_prevSignal = 0;
1393 signalHandler->m_nextSignal = 0;
1394 delete signalHandler;
1395 signalHandler = next;
1402 propertyCache->release();
1404 if (ownContext && context)
1408 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1409 *guard = (QObject *)0;
1410 guard->objectDestroyed(object);
1414 while (notifyList->todo)
1415 notifyList->todo->disconnect();
1416 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1417 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1420 free(notifyList->notifies);
1426 delete extendedData;
1428 // Dispose the handle.
1429 // We don't simply clear it (and wait for next gc cycle to dispose
1430 // via the weak qobject reference callback) as this affects the
1431 // outcomes of v8's gc statistical analysis heuristics, which can
1432 // cause unnecessary growth of the old pointer space js heap area.
1433 qPersistentDispose(v8object);
1439 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1441 void QQmlData::parentChanged(QObject *object, QObject *parent)
1444 if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1448 { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1449 { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1451 qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1452 "User code is attempting to change it to %s.\n"
1453 "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1458 bool QQmlData::hasBindingBit(int bit) const
1460 if (bindingBitsSize > bit)
1461 return bindingBits[bit / 32] & (1 << (bit % 32));
1466 void QQmlData::clearBindingBit(int bit)
1468 if (bindingBitsSize > bit)
1469 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1472 void QQmlData::setBindingBit(QObject *obj, int bit)
1474 if (bindingBitsSize <= bit) {
1475 int props = QQmlMetaObject(obj).propertyCount();
1476 Q_ASSERT(bit < props);
1478 int arraySize = (props + 31) / 32;
1479 int oldArraySize = bindingBitsSize / 32;
1481 bindingBits = (quint32 *)realloc(bindingBits,
1482 arraySize * sizeof(quint32));
1484 memset(bindingBits + oldArraySize,
1486 sizeof(quint32) * (arraySize - oldArraySize));
1488 bindingBitsSize = arraySize * 32;
1491 bindingBits[bit / 32] |= (1 << (bit % 32));
1494 void QQmlEnginePrivate::sendQuit()
1498 if (q->receivers(SIGNAL(quit())) == 0) {
1499 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1503 static void dumpwarning(const QQmlError &error)
1505 QMessageLogger(error.url().toString().toLatin1().constData(),
1506 error.line(), 0).warning().nospace()
1507 << qPrintable(error.toString());
1510 static void dumpwarning(const QList<QQmlError> &errors)
1512 for (int ii = 0; ii < errors.count(); ++ii)
1513 dumpwarning(errors.at(ii));
1516 void QQmlEnginePrivate::warning(const QQmlError &error)
1519 q->warnings(QList<QQmlError>() << error);
1520 if (outputWarningsToStdErr)
1524 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1527 q->warnings(errors);
1528 if (outputWarningsToStdErr)
1529 dumpwarning(errors);
1532 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1535 warning(error->error(q));
1538 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1541 QQmlEnginePrivate::get(engine)->warning(error);
1546 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1549 QQmlEnginePrivate::get(engine)->warning(error);
1554 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1557 QQmlEnginePrivate::get(engine)->warning(error);
1559 dumpwarning(error->error(0));
1562 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1565 engine->warning(error);
1570 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1573 engine->warning(error);
1579 This function should be called prior to evaluation of any js expression,
1580 so that scarce resources are not freed prematurely (eg, if there is a
1581 nested javascript expression).
1583 void QQmlEnginePrivate::referenceScarceResources()
1585 scarceResourcesRefCount += 1;
1589 This function should be called after evaluation of the js expression is
1590 complete, and so the scarce resources may be freed safely.
1592 void QQmlEnginePrivate::dereferenceScarceResources()
1594 Q_ASSERT(scarceResourcesRefCount > 0);
1595 scarceResourcesRefCount -= 1;
1597 // if the refcount is zero, then evaluation of the "top level"
1598 // expression must have completed. We can safely release the
1599 // scarce resources.
1600 if (scarceResourcesRefCount == 0) {
1601 // iterate through the list and release them all.
1602 // note that the actual SRD is owned by the JS engine,
1603 // so we cannot delete the SRD; but we can free the
1604 // memory used by the variant in the SRD.
1605 while (ScarceResourceData *sr = scarceResources.first()) {
1606 sr->data = QVariant();
1607 scarceResources.remove(sr);
1613 Adds \a path as a directory where the engine searches for
1614 installed modules in a URL-based directory structure.
1616 The \a path may be a local filesystem directory, a
1617 \l {The Qt Resource System}{Qt Resource} path (\c {:/imports}), a
1618 \l {The Qt Resource System}{Qt Resource} url (\c {qrc:/imports}) or a URL.
1620 The \a path will be converted into canonical form before it
1621 is added to the import path list.
1623 The newly added \a path will be first in the importPathList().
1625 \sa setImportPathList(), {QML Modules}
1627 void QQmlEngine::addImportPath(const QString& path)
1630 d->importDatabase.addImportPath(path);
1634 Returns the list of directories where the engine searches for
1635 installed modules in a URL-based directory structure.
1637 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1638 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1639 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1640 provided by that module. A \c qmldir file is required for defining the
1641 type version mapping and possibly QML extensions plugins.
1643 By default, the list contains the directory of the application executable,
1644 paths specified in the \c QML_IMPORT_PATH environment variable,
1645 and the builtin \c ImportsPath from QLibraryInfo.
1647 \sa addImportPath(), setImportPathList()
1649 QStringList QQmlEngine::importPathList() const
1651 Q_D(const QQmlEngine);
1652 return d->importDatabase.importPathList();
1656 Sets \a paths as the list of directories where the engine searches for
1657 installed modules in a URL-based directory structure.
1659 By default, the list contains the directory of the application executable,
1660 paths specified in the \c QML_IMPORT_PATH environment variable,
1661 and the builtin \c ImportsPath from QLibraryInfo.
1663 \sa importPathList(), addImportPath()
1665 void QQmlEngine::setImportPathList(const QStringList &paths)
1668 d->importDatabase.setImportPathList(paths);
1673 Adds \a path as a directory where the engine searches for
1674 native plugins for imported modules (referenced in the \c qmldir file).
1676 By default, the list contains only \c ., i.e. the engine searches
1677 in the directory of the \c qmldir file itself.
1679 The newly added \a path will be first in the pluginPathList().
1681 \sa setPluginPathList()
1683 void QQmlEngine::addPluginPath(const QString& path)
1686 d->importDatabase.addPluginPath(path);
1691 Returns the list of directories where the engine searches for
1692 native plugins for imported modules (referenced in the \c qmldir file).
1694 By default, the list contains only \c ., i.e. the engine searches
1695 in the directory of the \c qmldir file itself.
1697 \sa addPluginPath(), setPluginPathList()
1699 QStringList QQmlEngine::pluginPathList() const
1701 Q_D(const QQmlEngine);
1702 return d->importDatabase.pluginPathList();
1706 Sets the list of directories where the engine searches for
1707 native plugins for imported modules (referenced in the \c qmldir file)
1710 By default, the list contains only \c ., i.e. the engine searches
1711 in the directory of the \c qmldir file itself.
1713 \sa pluginPathList(), addPluginPath()
1715 void QQmlEngine::setPluginPathList(const QStringList &paths)
1718 d->importDatabase.setPluginPathList(paths);
1722 Imports the plugin named \a filePath with the \a uri provided.
1723 Returns true if the plugin was successfully imported; otherwise returns false.
1725 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1727 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1729 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1732 return d->importDatabase.importPlugin(filePath, uri, QString(), errors);
1736 \property QQmlEngine::offlineStoragePath
1737 \brief the directory for storing offline user data
1739 Returns the directory where SQL and other offline
1742 QQuickWebView and the SQL databases created with openDatabase()
1745 The default is QML/OfflineStorage in the platform-standard
1746 user application data directory.
1748 Note that the path may not currently exist on the filesystem, so
1749 callers wanting to \e create new files at this location should create
1750 it first - see QDir::mkpath().
1752 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1755 d->offlineStoragePath = dir;
1758 QString QQmlEngine::offlineStoragePath() const
1760 Q_D(const QQmlEngine);
1761 return d->offlineStoragePath;
1764 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1768 if (!mo->superClass()) {
1769 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1770 propertyCache.insert(mo, rv);
1773 QQmlPropertyCache *super = cache(mo->superClass());
1774 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1775 propertyCache.insert(mo, rv);
1780 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1783 QList<QQmlType *> types;
1785 int maxMinorVersion = 0;
1787 const QMetaObject *metaObject = type->metaObject();
1789 while (metaObject) {
1790 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1791 type->majorVersion(), minorVersion);
1793 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1799 metaObject = metaObject->superClass();
1802 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1804 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1808 QQmlPropertyCache *raw = cache(type->metaObject());
1810 bool hasCopied = false;
1812 for (int ii = 0; ii < types.count(); ++ii) {
1813 QQmlType *currentType = types.at(ii);
1817 int rev = currentType->metaObjectRevision();
1818 int moIndex = types.count() - 1 - ii;
1820 if (raw->allowedRevisionCache[moIndex] != rev) {
1825 raw->allowedRevisionCache[moIndex] = rev;
1829 // Test revision compatibility - the basic rule is:
1830 // * Anything that is excluded, cannot overload something that is not excluded *
1832 // Signals override:
1833 // * other signals and methods of the same name.
1834 // * properties named on<Signal Name>
1835 // * automatic <property name>Changed notify signals
1837 // Methods override:
1838 // * other methods of the same name
1840 // Properties override:
1841 // * other elements of the same name
1843 bool overloadError = false;
1844 QString overloadName;
1847 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1848 !overloadError && iter != raw->stringCache.end();
1851 QQmlPropertyData *d = *iter;
1852 if (raw->isAllowedInRevision(d))
1853 continue; // Not excluded - no problems
1855 // check that a regular "name" overload isn't happening
1856 QQmlPropertyData *current = d;
1857 while (!overloadError && current) {
1858 current = d->overrideData(current);
1859 if (current && raw->isAllowedInRevision(current))
1860 overloadError = true;
1865 if (overloadError) {
1866 if (hasCopied) raw->release();
1868 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."));
1872 if (!hasCopied) raw->addref();
1873 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1875 if (minorVersion != maxMinorVersion) {
1877 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1883 QQmlMetaType::ModuleApiInstance *
1884 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1886 Locker locker(this);
1888 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1890 a = new QQmlMetaType::ModuleApiInstance;
1891 a->scriptCallback = module.script;
1892 a->qobjectCallback = module.qobject;
1893 a->instanceMetaObject = module.instanceMetaObject;
1894 moduleApiInstances.insert(module, a);
1900 bool QQmlEnginePrivate::isQObject(int t)
1902 Locker locker(this);
1903 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1906 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1908 Locker locker(this);
1909 int t = v.userType();
1910 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1912 return *(QObject **)(v.constData());
1914 return QQmlMetaType::toQObject(v, ok);
1918 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1920 Locker locker(this);
1921 if (m_compositeTypes.contains(t))
1922 return QQmlMetaType::Object;
1923 else if (m_qmlLists.contains(t))
1924 return QQmlMetaType::List;
1926 return QQmlMetaType::typeCategory(t);
1929 bool QQmlEnginePrivate::isList(int t) const
1931 Locker locker(this);
1932 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1935 int QQmlEnginePrivate::listType(int t) const
1937 Locker locker(this);
1938 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1939 if (iter != m_qmlLists.end())
1942 return QQmlMetaType::listType(t);
1945 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1947 Locker locker(this);
1948 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1949 if (iter != m_compositeTypes.end()) {
1950 return QQmlMetaObject((*iter)->rootPropertyCache);
1952 QQmlType *type = QQmlMetaType::qmlType(t);
1953 return QQmlMetaObject(type?type->baseMetaObject():0);
1957 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1959 Locker locker(this);
1960 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1961 if (iter != m_compositeTypes.end()) {
1962 return QQmlMetaObject((*iter)->rootPropertyCache);
1964 QQmlType *type = QQmlMetaType::qmlType(t);
1965 return QQmlMetaObject(type?type->metaObject():0);
1969 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1971 Locker locker(this);
1972 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1973 if (iter != m_compositeTypes.end()) {
1974 return (*iter)->rootPropertyCache;
1976 QQmlType *type = QQmlMetaType::qmlType(t);
1978 return type?cache(type->metaObject()):0;
1982 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1984 Locker locker(this);
1985 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1986 if (iter != m_compositeTypes.end()) {
1987 return (*iter)->rootPropertyCache;
1989 QQmlType *type = QQmlMetaType::qmlType(t);
1991 return type?cache(type->baseMetaObject()):0;
1995 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1997 QByteArray name = data->rootPropertyCache->className();
1999 QByteArray ptr = name + '*';
2000 QByteArray lst = "QQmlListProperty<" + name + '>';
2002 int ptr_type = QMetaType::registerNormalizedType(ptr,
2003 qMetaTypeDeleteHelper<QObject*>,
2004 qMetaTypeCreateHelper<QObject*>,
2005 qMetaTypeDestructHelper<QObject*>,
2006 qMetaTypeConstructHelper<QObject*>,
2008 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
2010 int lst_type = QMetaType::registerNormalizedType(lst,
2011 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
2012 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
2013 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
2014 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
2015 sizeof(QQmlListProperty<QObject>),
2016 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
2017 static_cast<QMetaObject*>(0));
2019 data->metaTypeId = ptr_type;
2020 data->listMetaTypeId = lst_type;
2021 data->isRegisteredWithEngine = true;
2023 Locker locker(this);
2024 m_qmlLists.insert(lst_type, ptr_type);
2025 // The QQmlCompiledData is not referenced here, but it is removed from this
2026 // hash in the QQmlCompiledData destructor
2027 m_compositeTypes.insert(ptr_type, data);
2030 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
2032 int ptr_type = data->metaTypeId;
2033 int lst_type = data->listMetaTypeId;
2035 Locker locker(this);
2036 m_qmlLists.remove(lst_type);
2037 m_compositeTypes.remove(ptr_type);
2040 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2042 return typeLoader.isTypeLoaded(url);
2045 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2047 return typeLoader.isScriptLoaded(url);
2050 bool QQml_isFileCaseCorrect(const QString &fileName)
2052 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2053 QFileInfo info(fileName);
2054 const QString absolute = info.absoluteFilePath();
2056 #if defined(Q_OS_MAC)
2057 const QString canonical = info.canonicalFilePath();
2058 #elif defined(Q_OS_WIN)
2059 wchar_t buffer[1024];
2061 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2062 if (rv == 0 || rv >= 1024) return true;
2063 rv = ::GetLongPathName(buffer, buffer, 1024);
2064 if (rv == 0 || rv >= 1024) return true;
2066 const QString canonical = QString::fromWCharArray(buffer);
2069 const int absoluteLength = absolute.length();
2070 const int canonicalLength = canonical.length();
2072 const int length = qMin(absoluteLength, canonicalLength);
2073 for (int ii = 0; ii < length; ++ii) {
2074 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2075 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2077 if (a.toLower() != c.toLower())
2089 \fn QQmlEngine *qmlEngine(const QObject *object)
2092 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2093 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2097 \fn QQmlContext *qmlContext(const QObject *object)
2100 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2101 QQmlEngine::contextForObject(object).