1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
72 #include <private/qqmlboundsignal_p.h>
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtCore/qthread.h>
84 #include <private/qthread_p.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
87 #include <private/qobject_p.h>
88 #include <private/qmetaobject_p.h>
90 #include <private/qqmllocale_p.h>
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
97 #define CSIDL_APPDATA 0x001a // <username>\Application Data
100 Q_DECLARE_METATYPE(QQmlProperty)
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
106 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107 QQmlEnginePrivate::registerQtQuick2Types(uri, versionMajor, versionMinor);
108 QQmlValueTypeFactory::registerValueTypes(uri, versionMajor, versionMinor);
112 \qmlclass QtObject QObject
113 \inqmlmodule QtQuick 2
114 \ingroup qml-utility-elements
116 \brief A basic QML type
118 The QtObject element is a non-visual element which contains only the
121 It can be useful to create a QtObject if you need an extremely
122 lightweight element to enclose a set of custom properties:
124 \snippet qml/qtobject.qml 0
126 It can also be useful for C++ integration, as it is just a plain
127 QObject. See the QObject documentation for further details.
130 \qmlproperty string QtObject::objectName
131 This property holds the QObject::objectName for this specific object instance.
133 This allows a C++ application to locate an item within a QML component
134 using the QObject::findChild() method. For example, the following C++
135 application locates the child \l Rectangle item and dynamically changes its
144 width: 200; height: 200
158 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
161 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
163 item->setProperty("color", QColor(Qt::yellow));
167 bool QQmlEnginePrivate::qml_debugging_enabled = false;
169 // these types are part of the QML language
170 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
172 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
173 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
177 // These QtQuick types' implementation resides in the QtQml module
178 void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
180 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor, "ListElement");
181 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor, "ListModel", new QQuickListModelParser);
182 qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
185 void QQmlEnginePrivate::defineQtQuick2Module()
187 // register the base types into the QtQuick namespace
188 registerBaseTypes("QtQuick",2,0);
190 // register the QtQuick2 types which are implemented in the QtQml module.
191 registerQtQuick2Types("QtQuick",2,0);
192 qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
197 \class QQmlImageProviderBase
198 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
201 Image providers must be registered with the QML engine. The only information the QML
202 engine knows about image providers is the type of image data they provide. To use an
203 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
204 to a QQuickImageProvider pointer.
206 \sa QQuickImageProvider, QQuickTextureFactory
210 \enum QQmlImageProviderBase::ImageType
212 Defines the type of image supported by this image provider.
214 \value Image The Image Provider provides QImage images.
215 The QQuickImageProvider::requestImage() method will be called for all image requests.
216 \value Pixmap The Image Provider provides QPixmap images.
217 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
218 \value Texture The Image Provider provides QSGTextureProvider based images.
219 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
223 \enum QQmlImageProviderBase::Flag
225 Defines specific requirements or features of this image provider.
227 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
228 run in a separate thread, which allows the provider to spend as much time as needed
229 on producing the image without blocking the main thread.
233 QQmlImageProviderBase::QQmlImageProviderBase()
238 QQmlImageProviderBase::~QQmlImageProviderBase()
244 \qmlclass Qt QQmlEnginePrivate
245 \ingroup qml-utility-elements
246 \brief The QML global Qt object provides useful enums and functions from Qt.
248 \keyword QmlGlobalQtObject
250 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
252 The \c Qt object is a global object with utility functions, properties and enums.
254 It is not instantiable; to use it, call the members of the global \c Qt object directly.
261 color: Qt.rgba(1, 0, 0, 1)
262 text: Qt.md5("hello, world")
269 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
270 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
274 The Qt object also contains helper functions for creating objects of specific
275 data types. This is primarily useful when setting the properties of an item
276 when the property has one of the following types:
279 \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()}
280 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
281 \li \c point - use \l{Qt::point()}{Qt.point()}
282 \li \c size - use \l{Qt::size()}{Qt.size()}
283 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
286 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
288 \section1 Date/Time Formatters
290 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
293 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
294 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
295 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
298 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
301 \section1 Dynamic Object Creation
302 The following functions on the global object allow you to dynamically create QML
303 items from files or strings. See \l{Dynamic QML Object Creation from JavaScript} for an overview
307 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
308 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
312 \section1 Other Functions
314 The following functions are also on the Qt object.
317 \li \l{Qt::quit()}{Qt.quit()}
318 \li \l{Qt::md5()}{Qt.md5(string)}
319 \li \l{Qt::btoa()}{string Qt.btoa(string)}
320 \li \l{Qt::atob()}{string Qt.atob(string)}
321 \li \l{Qt::binding()}{object Qt.binding(function)}
322 \li \l{Qt::locale()}{object Qt.locale()}
323 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
324 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
325 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
330 \qmlproperty object Qt::application
333 The \c application object provides access to global application state
334 properties shared by many QML components.
340 \li \c application.active
342 This read-only property indicates whether the application is the top-most and focused
343 application, and the user is able to interact with the application. The property
344 is false when the application is in the background, the device keylock or screen
345 saver is active, the screen backlight is turned off, or the global system dialog
346 is being displayed on top of the application. It can be used for stopping and
347 pausing animations, timers and active processing of data in order to save device
348 battery power and free device memory and processor load when the application is not
352 \li \c application.layoutDirection
354 This read-only property can be used to query the default layout direction of the
355 application. On system start-up, the default layout direction depends on the
356 application's language. The property has a value of \c Qt.RightToLeft in locales
357 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
358 where the reading direction flows from left to right. You can bind to this
359 property to customize your application layouts to support both layout directions.
364 \li Qt.LeftToRight - Text and graphics elements should be positioned
366 \li Qt.RightToLeft - Text and graphics elements should be positioned
372 The following example uses the \c application object to indicate
373 whether the application is currently active:
375 \snippet qml/application.qml document
379 \qmlproperty object Qt::inputMethod
382 The \c inputMethod object allows access to application's QInputMethod object
383 and all its properties and slots. See the QInputMethod documentation for
389 \qmlmethod object Qt::include(string url, jsobject callback)
391 Includes another JavaScript file. This method can only be used from within JavaScript files,
392 and not regular QML files.
394 This imports all functions from \a url into the current script's namespace.
396 Qt.include() returns an object that describes the status of the operation. The object has
397 a single property, \c {status}, that is set to one of the following values:
400 \header \li Symbol \li Value \li Description
401 \row \li result.OK \li 0 \li The include completed successfully.
402 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
403 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
404 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
405 An additional \c exception property will be set in this case.
408 The \c status property will be updated as the operation progresses.
410 If provided, \a callback is invoked when the operation completes. The callback is passed
411 the same object as is returned from the Qt.include() call.
413 // Qt.include() is implemented in qv8include.cpp
416 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
417 : propertyCapture(0), rootContext(0), isDebugging(false),
418 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
419 cleanup(0), erroredBindings(0), inProgressCreations(0),
420 workerScriptEngine(0), activeVME(0),
421 networkAccessManager(0), networkAccessManagerFactory(0),
422 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
423 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
427 QQmlEnginePrivate::~QQmlEnginePrivate()
429 if (inProgressCreations)
430 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
433 QQmlCleanup *c = cleanup;
435 if (cleanup) cleanup->prev = &cleanup;
441 doDeleteInEngineThread();
443 if (incubationController) incubationController->d = 0;
444 incubationController = 0;
449 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
451 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
453 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
454 delete (*iter)->qobjectApi;
457 for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
458 iter.value()->isRegisteredWithEngine = false;
461 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
463 QObjectPrivate *p = QObjectPrivate::get(o);
464 if (p->declarativeData) {
465 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
466 if (d->ownContext && d->context) {
467 d->context->destroy();
471 // Mark this object as in the process of deletion to
472 // prevent it resolving in bindings
473 QQmlData::markAsDeleted(o);
477 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
479 static_cast<QQmlData *>(d)->destroyed(o);
482 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
484 static_cast<QQmlData *>(d)->parentChanged(o, p);
487 class QQmlThreadNotifierProxyObject : public QObject
490 QPointer<QObject> target;
492 virtual int qt_metacall(QMetaObject::Call, int methodIndex, void **a) {
496 QMetaMethod method = target->metaObject()->method(methodIndex);
497 Q_ASSERT(method.methodType() == QMetaMethod::Signal);
498 int signalIndex = QMetaObjectPrivate::signalIndex(method);
499 QQmlData *ddata = QQmlData::get(target, false);
500 QQmlNotifierEndpoint *ep = ddata->notify(signalIndex);
501 if (ep) QQmlNotifier::emitNotify(ep, a);
509 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
511 QQmlData *ddata = QQmlData::get(object, false);
512 if (!ddata) return; // Probably being deleted
514 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
515 // that they're exposed to. However, to make writing "worker objects" that calculate data
516 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
517 // QQmlEngine to emit signals from a different thread. These signals are then automatically
518 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
519 // by the qqmlecmascript::threadSignal() autotest.
520 if (ddata->notifyList &&
521 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
523 if (!QObjectPrivate::get(object)->threadData->thread)
526 QMetaMethod m = QMetaObjectPrivate::signal(object->metaObject(), index);
527 QList<QByteArray> parameterTypes = m.parameterTypes();
529 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
530 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
532 types[0] = 0; // return type
533 args[0] = 0; // return value
535 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
536 const QByteArray &typeName = parameterTypes.at(ii);
537 if (typeName.endsWith('*'))
538 types[ii + 1] = QMetaType::VoidStar;
540 types[ii + 1] = QMetaType::type(typeName);
542 if (!types[ii + 1]) {
543 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
544 "(Make sure '%s' is registered using qRegisterMetaType().)",
545 typeName.constData(), typeName.constData());
551 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
554 QMetaCallEvent *ev = new QMetaCallEvent(m.methodIndex(), 0, 0, object, index,
555 parameterTypes.count() + 1, types, args);
557 QQmlThreadNotifierProxyObject *mpo = new QQmlThreadNotifierProxyObject;
558 mpo->target = object;
559 mpo->moveToThread(QObjectPrivate::get(object)->threadData->thread);
560 QCoreApplication::postEvent(mpo, ev);
563 QQmlNotifierEndpoint *ep = ddata->notify(index);
564 if (ep) QQmlNotifier::emitNotify(ep, a);
568 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
570 return static_cast<QQmlData *>(d)->endpointCount(index);
573 int QQmlData::endpointCount(int index)
576 QQmlNotifierEndpoint *ep = notify(index);
587 void QQmlData::markAsDeleted(QObject *o)
589 QQmlData::setQueuedForDeletion(o);
591 QObjectPrivate *p = QObjectPrivate::get(o);
592 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
593 QQmlData::markAsDeleted(*it);
597 void QQmlData::setQueuedForDeletion(QObject *object)
600 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
601 if (!priv->wasDeleted && priv->declarativeData) {
602 QQmlData *ddata = QQmlData::get(object, false);
603 if (ddata->ownContext && ddata->context)
604 ddata->context->emitDestruction();
605 ddata->isQueuedForDeletion = true;
611 void QQmlEnginePrivate::init()
615 static bool firstTime = true;
617 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
618 registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
624 qRegisterMetaType<QVariant>("QVariant");
625 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
626 qRegisterMetaType<QJSValue>("QJSValue");
627 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
628 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
629 qRegisterMetaType<QList<int> >("QList<int>");
630 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
632 v8engine()->setEngine(q);
634 rootContext = new QQmlContext(q,true);
636 if (QCoreApplication::instance()->thread() == q->thread() &&
637 QQmlEngineDebugService::isDebuggingEnabled()) {
639 QQmlEngineDebugService::instance()->addEngine(q);
640 QV8DebugService::initialize(v8engine());
641 QV8ProfilerService::initialize();
642 QQmlProfilerService::initialize();
643 QDebugMessageService::instance();
646 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
647 if (!dataLocation.isEmpty())
648 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
649 + QDir::separator() + QLatin1String("QML")
650 + QDir::separator() + QLatin1String("OfflineStorage");
653 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
656 if (!workerScriptEngine)
657 workerScriptEngine = new QQuickWorkerScriptEngine(q);
658 return workerScriptEngine;
665 \brief The QQmlEngine class provides an environment for instantiating QML components.
668 Each QML component is instantiated in a QQmlContext.
669 QQmlContext's are essential for passing data to QML
670 components. In QML, contexts are arranged hierarchically and this
671 hierarchy is managed by the QQmlEngine.
673 Prior to creating any QML components, an application must have
674 created a QQmlEngine to gain access to a QML context. The
675 following example shows how to create a simple Text item.
679 QQmlComponent component(&engine);
680 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
681 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
683 //add item to view, etc
687 In this case, the Text item will be created in the engine's
688 \l {QQmlEngine::rootContext()}{root context}.
690 Note that the QtQuick 1 version is called QDeclarativeEngine.
692 \sa QQmlComponent, QQmlContext
696 Create a new QQmlEngine with the given \a parent.
698 QQmlEngine::QQmlEngine(QObject *parent)
699 : QJSEngine(*new QQmlEnginePrivate(this), parent)
706 Destroys the QQmlEngine.
708 Any QQmlContext's created on this engine will be
709 invalidated, but not destroyed (unless they are parented to the
712 QQmlEngine::~QQmlEngine()
715 if (d->isDebugging) {
716 QQmlEngineDebugService::instance()->remEngine(this);
719 // Emit onDestruction signals for the root context before
720 // we destroy the contexts, engine, Module APIs etc. that
721 // may be required to handle the destruction signal.
722 QQmlContextData::get(rootContext())->emitDestruction();
724 // if we are the parent of any of the qobject module api instances,
725 // we need to remove them from our internal list, in order to prevent
726 // a segfault in engine private dtor.
727 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
728 QObject *currQObjectApi = 0;
729 QQmlMetaType::ModuleApiInstance *currInstance = 0;
730 foreach (const QQmlMetaType::ModuleApi &key, keys) {
731 currInstance = d->moduleApiInstances.value(key);
732 currQObjectApi = currInstance->qobjectApi;
733 if (this->children().contains(currQObjectApi)) {
734 delete currQObjectApi;
736 d->moduleApiInstances.remove(key);
740 if (d->incubationController)
741 d->incubationController->d = 0;
744 /*! \fn void QQmlEngine::quit()
745 This signal is emitted when the QML loaded by the engine would like to quit.
748 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
749 This signal is emitted when \a warnings messages are generated by QML.
753 Clears the engine's internal component cache.
755 This function causes the property metadata of all components previously
756 loaded by the engine to be destroyed. All previously loaded components and
757 the property bindings for all extant objects created from those components will
760 This function returns the engine to a state where it does not contain any loaded
761 component data. This may be useful in order to reload a smaller subset of the
762 previous component set, or to load a new version of a previously loaded component.
764 Once the component cache has been cleared, components must be loaded before
765 any new objects can be created.
767 \sa trimComponentCache()
769 void QQmlEngine::clearComponentCache()
772 d->typeLoader.clearCache();
776 Trims the engine's internal component cache.
778 This function causes the property metadata of any loaded components which are
779 not currently in use to be destroyed.
781 A component is considered to be in use if there are any extant instances of
782 the component itself, any instances of other components that use the component,
783 or any objects instantiated by any of those components.
785 \sa clearComponentCache()
787 void QQmlEngine::trimComponentCache()
790 d->typeLoader.trimCache();
794 Returns the engine's root context.
796 The root context is automatically created by the QQmlEngine.
797 Data that should be available to all QML component instances
798 instantiated by the engine should be put in the root context.
800 Additional data that should only be available to a subset of
801 component instances should be added to sub-contexts parented to the
804 QQmlContext *QQmlEngine::rootContext() const
806 Q_D(const QQmlEngine);
807 return d->rootContext;
811 Sets the \a factory to use for creating QNetworkAccessManager(s).
813 QNetworkAccessManager is used for all network access by QML. By
814 implementing a factory it is possible to create custom
815 QNetworkAccessManager with specialized caching, proxy and cookie
818 The factory must be set before executing the engine.
820 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
823 QMutexLocker locker(&d->mutex);
824 d->networkAccessManagerFactory = factory;
828 Returns the current QQmlNetworkAccessManagerFactory.
830 \sa setNetworkAccessManagerFactory()
832 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
834 Q_D(const QQmlEngine);
835 return d->networkAccessManagerFactory;
838 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
841 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
843 void *args[] = { 0 };
844 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
848 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
850 QMutexLocker locker(&mutex);
851 QNetworkAccessManager *nam;
852 if (networkAccessManagerFactory) {
853 nam = networkAccessManagerFactory->create(parent);
855 nam = new QNetworkAccessManager(parent);
861 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
863 Q_Q(const QQmlEngine);
864 if (!networkAccessManager)
865 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
866 return networkAccessManager;
870 Returns a common QNetworkAccessManager which can be used by any QML
871 element instantiated by this engine.
873 If a QQmlNetworkAccessManagerFactory has been set and a
874 QNetworkAccessManager has not yet been created, the
875 QQmlNetworkAccessManagerFactory will be used to create the
876 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
877 will have no proxy or cache set.
879 \sa setNetworkAccessManagerFactory()
881 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
883 Q_D(const QQmlEngine);
884 return d->getNetworkAccessManager();
889 Sets the \a provider to use for images requested via the \e
890 image: url scheme, with host \a providerId. The QQmlEngine
891 takes ownership of \a provider.
893 Image providers enable support for pixmap and threaded image
894 requests. See the QQuickImageProvider documentation for details on
895 implementing and using image providers.
897 All required image providers should be added to the engine before any
898 QML sources files are loaded.
900 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
902 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
905 QMutexLocker locker(&d->mutex);
906 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
910 Returns the image provider set for \a providerId.
912 Returns the provider if it was found; otherwise returns 0.
914 \sa QQuickImageProvider
916 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
918 Q_D(const QQmlEngine);
919 QMutexLocker locker(&d->mutex);
920 return d->imageProviders.value(providerId).data();
924 Removes the image provider for \a providerId.
926 \sa addImageProvider(), QQuickImageProvider
928 void QQmlEngine::removeImageProvider(const QString &providerId)
931 QMutexLocker locker(&d->mutex);
932 d->imageProviders.take(providerId);
936 Return the base URL for this engine. The base URL is only used to
937 resolve components when a relative URL is passed to the
938 QQmlComponent constructor.
940 If a base URL has not been explicitly set, this method returns the
941 application's current working directory.
945 QUrl QQmlEngine::baseUrl() const
947 Q_D(const QQmlEngine);
948 if (d->baseUrl.isEmpty()) {
949 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
956 Set the base URL for this engine to \a url.
960 void QQmlEngine::setBaseUrl(const QUrl &url)
967 Returns true if warning messages will be output to stderr in addition
968 to being emitted by the warnings() signal, otherwise false.
970 The default value is true.
972 bool QQmlEngine::outputWarningsToStandardError() const
974 Q_D(const QQmlEngine);
975 return d->outputWarningsToStdErr;
979 Set whether warning messages will be output to stderr to \a enabled.
981 If \a enabled is true, any warning messages generated by QML will be
982 output to stderr and emitted by the warnings() signal. If \a enabled
983 is false, on the warnings() signal will be emitted. This allows
984 applications to handle warning output themselves.
986 The default value is true.
988 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
991 d->outputWarningsToStdErr = enabled;
995 Returns the QQmlContext for the \a object, or 0 if no
996 context has been set.
998 When the QQmlEngine instantiates a QObject, the context is
1001 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
1006 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
1009 static_cast<QQmlData *>(priv->declarativeData);
1013 else if (data->outerContext)
1014 return data->outerContext->asQQmlContext();
1020 Sets the QQmlContext for the \a object to \a context.
1021 If the \a object already has a context, a warning is
1022 output, but the context is not changed.
1024 When the QQmlEngine instantiates a QObject, the context is
1027 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1029 if (!object || !context)
1032 QQmlData *data = QQmlData::get(object, true);
1033 if (data->context) {
1034 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1038 QQmlContextData *contextData = QQmlContextData::get(context);
1039 contextData->addObject(object);
1043 \enum QQmlEngine::ObjectOwnership
1045 Ownership controls whether or not QML automatically destroys the
1046 QObject when the object is garbage collected by the JavaScript
1047 engine. The two ownership options are:
1049 \value CppOwnership The object is owned by C++ code, and will
1050 never be deleted by QML. The JavaScript destroy() method cannot be
1051 used on objects with CppOwnership. This option is similar to
1052 QScriptEngine::QtOwnership.
1054 \value JavaScriptOwnership The object is owned by JavaScript.
1055 When the object is returned to QML as the return value of a method
1056 call or property access, QML will track it, and delete the object
1057 if there are no remaining JavaScript references to it and it has no
1058 QObject::parent(). An object tracked by one QQmlEngine
1059 will be deleted during that QQmlEngine's destructor, and thus
1060 JavaScript references between objects with JavaScriptOwnership from
1061 two different engines will not be valid after the deletion of one of
1062 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1064 Generally an application doesn't need to set an object's ownership
1065 explicitly. QML uses a heuristic to set the default object
1066 ownership. By default, an object that is created by QML has
1067 JavaScriptOwnership. The exception to this are the root objects
1068 created by calling QQmlComponent::create() or
1069 QQmlComponent::beginCreate() which have CppOwnership by
1070 default. The ownership of these root-level objects is considered to
1071 have been transferred to the C++ caller.
1073 Objects not-created by QML have CppOwnership by default. The
1074 exception to this is objects returned from a C++ method call. The
1075 ownership of these objects is passed to JavaScript.
1077 Calling setObjectOwnership() overrides the default ownership
1078 heuristic used by QML.
1082 Sets the \a ownership of \a object.
1084 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1089 QQmlData *ddata = QQmlData::get(object, true);
1093 ddata->indestructible = (ownership == CppOwnership)?true:false;
1094 ddata->explicitIndestructibleSet = true;
1098 Returns the ownership of \a object.
1100 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1103 return CppOwnership;
1105 QQmlData *ddata = QQmlData::get(object, false);
1107 return CppOwnership;
1109 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1112 bool QQmlEngine::event(QEvent *e)
1115 if (e->type() == QEvent::User)
1116 d->doDeleteInEngineThread();
1118 return QJSEngine::event(e);
1121 void QQmlEnginePrivate::doDeleteInEngineThread()
1123 QFieldList<Deletable, &Deletable::next> list;
1125 list.copyAndClear(toDeleteInEngineThread);
1128 while (Deletable *d = list.takeFirst())
1132 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1134 QQmlData *data = QQmlData::get(object);
1136 if (data && data->compiledData && data->deferredIdx) {
1137 QQmlObjectCreatingProfiler prof;
1139 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1140 prof.setTypeName(type ? type->qmlTypeName()
1141 : QString::fromUtf8(object->metaObject()->className()));
1142 if (data->outerContext)
1143 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1145 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1147 QQmlComponentPrivate::ConstructionState state;
1148 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1150 // Release the reference for the deferral action (we still have one from construction)
1151 data->compiledData->release();
1152 data->compiledData = 0;
1154 QQmlComponentPrivate::complete(ep, &state);
1158 QQmlContext *qmlContext(const QObject *obj)
1160 return QQmlEngine::contextForObject(obj);
1163 QQmlEngine *qmlEngine(const QObject *obj)
1165 QQmlData *data = QQmlData::get(obj, false);
1166 if (!data || !data->context)
1168 return data->context->engine;
1171 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1173 QQmlData *data = QQmlData::get(object);
1175 return 0; // Attached properties are only on objects created by QML
1177 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1181 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1185 rv = pf(const_cast<QObject *>(object));
1188 data->attachedProperties()->insert(id, rv);
1193 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1194 const QMetaObject *attachedMetaObject, bool create)
1197 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1199 if (*idCache == -1 || !object)
1202 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1205 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1207 #ifndef QQML_NO_DEBUG_PROTOCOL
1208 if (!QQmlEnginePrivate::qml_debugging_enabled
1210 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1212 QQmlEnginePrivate::qml_debugging_enabled = true;
1217 class QQmlDataExtended {
1220 ~QQmlDataExtended();
1222 QHash<int, QObject *> attachedProperties;
1225 QQmlDataExtended::QQmlDataExtended()
1229 QQmlDataExtended::~QQmlDataExtended()
1233 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1236 layout(endpoint->next);
1238 int index = endpoint->sourceSignal;
1239 index = qMin(index, 0xFFFF - 1);
1241 endpoint->next = notifies[index];
1242 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1243 endpoint->prev = ¬ifies[index];
1244 notifies[index] = endpoint;
1247 void QQmlData::NotifyList::layout()
1249 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1252 QQmlNotifierEndpoint **old = notifies;
1253 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1254 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1255 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1256 sizeof(QQmlNotifierEndpoint*);
1257 memset(notifies + notifiesSize, 0, memsetSize);
1259 if (notifies != old) {
1260 for (int ii = 0; ii < notifiesSize; ++ii)
1262 notifies[ii]->prev = ¬ifies[ii];
1265 notifiesSize = maximumTodoIndex + 1;
1270 maximumTodoIndex = 0;
1274 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1277 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1278 notifyList->connectionMask = 0;
1279 notifyList->maximumTodoIndex = 0;
1280 notifyList->notifiesSize = 0;
1281 notifyList->todo = 0;
1282 notifyList->notifies = 0;
1285 Q_ASSERT(!endpoint->isConnected());
1287 index = qMin(index, 0xFFFF - 1);
1288 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1290 if (index < notifyList->notifiesSize) {
1292 endpoint->next = notifyList->notifies[index];
1293 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1294 endpoint->prev = ¬ifyList->notifies[index];
1295 notifyList->notifies[index] = endpoint;
1298 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1300 endpoint->next = notifyList->todo;
1301 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1302 endpoint->prev = ¬ifyList->todo;
1303 notifyList->todo = endpoint;
1307 bool QQml_isSignalConnected(QObject *obj, int signal_index)
1309 QQmlData *data = QQmlData::get(obj);
1310 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(signal_index));
1314 index MUST in the range returned by QObjectPrivate::signalIndex()
1315 This is different than the index returned by QMetaMethod::methodIndex()
1317 bool QQmlData::signalHasEndpoint(int index)
1319 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1322 QHash<int, QObject *> *QQmlData::attachedProperties() const
1324 if (!extendedData) extendedData = new QQmlDataExtended;
1325 return &extendedData->attachedProperties;
1328 void QQmlData::destroyed(QObject *object)
1330 if (nextContextObject)
1331 nextContextObject->prevContextObject = prevContextObject;
1332 if (prevContextObject)
1333 *prevContextObject = nextContextObject;
1335 QQmlAbstractBinding *binding = bindings;
1337 QQmlAbstractBinding *next = binding->nextBinding();
1338 binding->setAddedToObject(false);
1339 binding->setNextBinding(0);
1345 compiledData->release();
1349 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1350 while (signalHandler) {
1351 if (signalHandler->isEvaluating()) {
1352 // The object is being deleted during signal handler evaluation.
1353 // This will cause a crash due to invalid memory access when the
1354 // evaluation has completed.
1355 // Abort with a friendly message instead.
1356 QString locationString;
1357 QQmlBoundSignalExpression *expr = signalHandler->expression();
1359 QString fileName = expr->sourceFile();
1360 if (fileName.isEmpty())
1361 fileName = QStringLiteral("<Unknown File>");
1362 locationString.append(fileName);
1363 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1364 QString source = expr->expression();
1365 if (source.size() > 100) {
1366 source.truncate(96);
1367 source.append(QStringLiteral(" ..."));
1369 locationString.append(source);
1371 locationString = QStringLiteral("<Unknown Location>");
1373 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1374 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1375 "instead), or the application is running a nested event loop.\n"
1376 "This behavior is NOT supported!\n"
1377 "%s", object, qPrintable(locationString));
1380 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1381 signalHandler->m_prevSignal = 0;
1382 signalHandler->m_nextSignal = 0;
1383 delete signalHandler;
1384 signalHandler = next;
1391 propertyCache->release();
1393 if (ownContext && context)
1397 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1398 *guard = (QObject *)0;
1399 guard->objectDestroyed(object);
1403 while (notifyList->todo)
1404 notifyList->todo->disconnect();
1405 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1406 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1409 free(notifyList->notifies);
1415 delete extendedData;
1417 // Dispose the handle.
1418 // We don't simply clear it (and wait for next gc cycle to dispose
1419 // via the weak qobject reference callback) as this affects the
1420 // outcomes of v8's gc statistical analysis heuristics, which can
1421 // cause unnecessary growth of the old pointer space js heap area.
1422 qPersistentDispose(v8object);
1428 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1430 void QQmlData::parentChanged(QObject *object, QObject *parent)
1433 if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1437 { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1438 { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1440 qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1441 "User code is attempting to change it to %s.\n"
1442 "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1447 bool QQmlData::hasBindingBit(int bit) const
1449 if (bindingBitsSize > bit)
1450 return bindingBits[bit / 32] & (1 << (bit % 32));
1455 void QQmlData::clearBindingBit(int bit)
1457 if (bindingBitsSize > bit)
1458 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1461 void QQmlData::setBindingBit(QObject *obj, int bit)
1463 if (bindingBitsSize <= bit) {
1464 int props = QQmlMetaObject(obj).propertyCount();
1465 Q_ASSERT(bit < props);
1467 int arraySize = (props + 31) / 32;
1468 int oldArraySize = bindingBitsSize / 32;
1470 bindingBits = (quint32 *)realloc(bindingBits,
1471 arraySize * sizeof(quint32));
1473 memset(bindingBits + oldArraySize,
1475 sizeof(quint32) * (arraySize - oldArraySize));
1477 bindingBitsSize = arraySize * 32;
1480 bindingBits[bit / 32] |= (1 << (bit % 32));
1483 void QQmlEnginePrivate::sendQuit()
1487 if (q->receivers(SIGNAL(quit())) == 0) {
1488 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1492 static void dumpwarning(const QQmlError &error)
1494 QMessageLogger(error.url().toString().toLatin1().constData(),
1495 error.line(), 0).warning().nospace()
1496 << qPrintable(error.toString());
1499 static void dumpwarning(const QList<QQmlError> &errors)
1501 for (int ii = 0; ii < errors.count(); ++ii)
1502 dumpwarning(errors.at(ii));
1505 void QQmlEnginePrivate::warning(const QQmlError &error)
1508 q->warnings(QList<QQmlError>() << error);
1509 if (outputWarningsToStdErr)
1513 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1516 q->warnings(errors);
1517 if (outputWarningsToStdErr)
1518 dumpwarning(errors);
1521 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1524 warning(error->error(q));
1527 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1530 QQmlEnginePrivate::get(engine)->warning(error);
1535 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1538 QQmlEnginePrivate::get(engine)->warning(error);
1543 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1546 QQmlEnginePrivate::get(engine)->warning(error);
1548 dumpwarning(error->error(0));
1551 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1554 engine->warning(error);
1559 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1562 engine->warning(error);
1568 This function should be called prior to evaluation of any js expression,
1569 so that scarce resources are not freed prematurely (eg, if there is a
1570 nested javascript expression).
1572 void QQmlEnginePrivate::referenceScarceResources()
1574 scarceResourcesRefCount += 1;
1578 This function should be called after evaluation of the js expression is
1579 complete, and so the scarce resources may be freed safely.
1581 void QQmlEnginePrivate::dereferenceScarceResources()
1583 Q_ASSERT(scarceResourcesRefCount > 0);
1584 scarceResourcesRefCount -= 1;
1586 // if the refcount is zero, then evaluation of the "top level"
1587 // expression must have completed. We can safely release the
1588 // scarce resources.
1589 if (scarceResourcesRefCount == 0) {
1590 // iterate through the list and release them all.
1591 // note that the actual SRD is owned by the JS engine,
1592 // so we cannot delete the SRD; but we can free the
1593 // memory used by the variant in the SRD.
1594 while (ScarceResourceData *sr = scarceResources.first()) {
1595 sr->data = QVariant();
1596 scarceResources.remove(sr);
1602 Adds \a path as a directory where the engine searches for
1603 installed modules in a URL-based directory structure.
1604 The \a path may be a local filesystem directory or a URL.
1606 The newly added \a path will be first in the importPathList().
1608 \sa setImportPathList(), {QML Modules}
1610 void QQmlEngine::addImportPath(const QString& path)
1613 d->importDatabase.addImportPath(path);
1617 Returns the list of directories where the engine searches for
1618 installed modules in a URL-based directory structure.
1620 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1621 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1622 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1623 provided by that module. A \c qmldir file is required for defining the
1624 type version mapping and possibly QML extensions plugins.
1626 By default, the list contains the directory of the application executable,
1627 paths specified in the \c QML_IMPORT_PATH environment variable,
1628 and the builtin \c ImportsPath from QLibraryInfo.
1630 \sa addImportPath(), setImportPathList()
1632 QStringList QQmlEngine::importPathList() const
1634 Q_D(const QQmlEngine);
1635 return d->importDatabase.importPathList();
1639 Sets \a paths as the list of directories where the engine searches for
1640 installed modules in a URL-based directory structure.
1642 By default, the list contains the directory of the application executable,
1643 paths specified in the \c QML_IMPORT_PATH environment variable,
1644 and the builtin \c ImportsPath from QLibraryInfo.
1646 \sa importPathList(), addImportPath()
1648 void QQmlEngine::setImportPathList(const QStringList &paths)
1651 d->importDatabase.setImportPathList(paths);
1656 Adds \a path as a directory where the engine searches for
1657 native plugins for imported modules (referenced in the \c qmldir file).
1659 By default, the list contains only \c ., i.e. the engine searches
1660 in the directory of the \c qmldir file itself.
1662 The newly added \a path will be first in the pluginPathList().
1664 \sa setPluginPathList()
1666 void QQmlEngine::addPluginPath(const QString& path)
1669 d->importDatabase.addPluginPath(path);
1674 Returns the list of directories where the engine searches for
1675 native plugins for imported modules (referenced in the \c qmldir file).
1677 By default, the list contains only \c ., i.e. the engine searches
1678 in the directory of the \c qmldir file itself.
1680 \sa addPluginPath(), setPluginPathList()
1682 QStringList QQmlEngine::pluginPathList() const
1684 Q_D(const QQmlEngine);
1685 return d->importDatabase.pluginPathList();
1689 Sets the list of directories where the engine searches for
1690 native plugins for imported modules (referenced in the \c qmldir file)
1693 By default, the list contains only \c ., i.e. the engine searches
1694 in the directory of the \c qmldir file itself.
1696 \sa pluginPathList(), addPluginPath()
1698 void QQmlEngine::setPluginPathList(const QStringList &paths)
1701 d->importDatabase.setPluginPathList(paths);
1705 Imports the plugin named \a filePath with the \a uri provided.
1706 Returns true if the plugin was successfully imported; otherwise returns false.
1708 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1710 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1712 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1715 return d->importDatabase.importPlugin(filePath, uri, errors);
1719 \property QQmlEngine::offlineStoragePath
1720 \brief the directory for storing offline user data
1722 Returns the directory where SQL and other offline
1725 QQuickWebView and the SQL databases created with openDatabase()
1728 The default is QML/OfflineStorage in the platform-standard
1729 user application data directory.
1731 Note that the path may not currently exist on the filesystem, so
1732 callers wanting to \e create new files at this location should create
1733 it first - see QDir::mkpath().
1735 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1738 d->offlineStoragePath = dir;
1741 QString QQmlEngine::offlineStoragePath() const
1743 Q_D(const QQmlEngine);
1744 return d->offlineStoragePath;
1747 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1751 if (!mo->superClass()) {
1752 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1753 propertyCache.insert(mo, rv);
1756 QQmlPropertyCache *super = cache(mo->superClass());
1757 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1758 propertyCache.insert(mo, rv);
1763 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1766 QList<QQmlType *> types;
1768 int maxMinorVersion = 0;
1770 const QMetaObject *metaObject = type->metaObject();
1772 while (metaObject) {
1773 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1774 type->majorVersion(), minorVersion);
1776 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1782 metaObject = metaObject->superClass();
1785 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1787 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1791 QQmlPropertyCache *raw = cache(type->metaObject());
1793 bool hasCopied = false;
1795 for (int ii = 0; ii < types.count(); ++ii) {
1796 QQmlType *currentType = types.at(ii);
1800 int rev = currentType->metaObjectRevision();
1801 int moIndex = types.count() - 1 - ii;
1803 if (raw->allowedRevisionCache[moIndex] != rev) {
1808 raw->allowedRevisionCache[moIndex] = rev;
1812 // Test revision compatibility - the basic rule is:
1813 // * Anything that is excluded, cannot overload something that is not excluded *
1815 // Signals override:
1816 // * other signals and methods of the same name.
1817 // * properties named on<Signal Name>
1818 // * automatic <property name>Changed notify signals
1820 // Methods override:
1821 // * other methods of the same name
1823 // Properties override:
1824 // * other elements of the same name
1826 bool overloadError = false;
1827 QString overloadName;
1830 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1831 !overloadError && iter != raw->stringCache.end();
1834 QQmlPropertyData *d = *iter;
1835 if (raw->isAllowedInRevision(d))
1836 continue; // Not excluded - no problems
1838 // check that a regular "name" overload isn't happening
1839 QQmlPropertyData *current = d;
1840 while (!overloadError && current) {
1841 current = d->overrideData(current);
1842 if (current && raw->isAllowedInRevision(current))
1843 overloadError = true;
1848 if (overloadError) {
1849 if (hasCopied) raw->release();
1851 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."));
1855 if (!hasCopied) raw->addref();
1856 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1858 if (minorVersion != maxMinorVersion) {
1860 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1866 QQmlMetaType::ModuleApiInstance *
1867 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1869 Locker locker(this);
1871 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1873 a = new QQmlMetaType::ModuleApiInstance;
1874 a->scriptCallback = module.script;
1875 a->qobjectCallback = module.qobject;
1876 a->instanceMetaObject = module.instanceMetaObject;
1877 moduleApiInstances.insert(module, a);
1883 bool QQmlEnginePrivate::isQObject(int t)
1885 Locker locker(this);
1886 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1889 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1891 Locker locker(this);
1892 int t = v.userType();
1893 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1895 return *(QObject **)(v.constData());
1897 return QQmlMetaType::toQObject(v, ok);
1901 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1903 Locker locker(this);
1904 if (m_compositeTypes.contains(t))
1905 return QQmlMetaType::Object;
1906 else if (m_qmlLists.contains(t))
1907 return QQmlMetaType::List;
1909 return QQmlMetaType::typeCategory(t);
1912 bool QQmlEnginePrivate::isList(int t) const
1914 Locker locker(this);
1915 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1918 int QQmlEnginePrivate::listType(int t) const
1920 Locker locker(this);
1921 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1922 if (iter != m_qmlLists.end())
1925 return QQmlMetaType::listType(t);
1928 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1930 Locker locker(this);
1931 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1932 if (iter != m_compositeTypes.end()) {
1933 return QQmlMetaObject((*iter)->rootPropertyCache);
1935 QQmlType *type = QQmlMetaType::qmlType(t);
1936 return QQmlMetaObject(type?type->baseMetaObject():0);
1940 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1942 Locker locker(this);
1943 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1944 if (iter != m_compositeTypes.end()) {
1945 return QQmlMetaObject((*iter)->rootPropertyCache);
1947 QQmlType *type = QQmlMetaType::qmlType(t);
1948 return QQmlMetaObject(type?type->metaObject():0);
1952 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1954 Locker locker(this);
1955 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1956 if (iter != m_compositeTypes.end()) {
1957 return (*iter)->rootPropertyCache;
1959 QQmlType *type = QQmlMetaType::qmlType(t);
1961 return type?cache(type->metaObject()):0;
1965 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1967 Locker locker(this);
1968 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1969 if (iter != m_compositeTypes.end()) {
1970 return (*iter)->rootPropertyCache;
1972 QQmlType *type = QQmlMetaType::qmlType(t);
1974 return type?cache(type->baseMetaObject()):0;
1978 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1980 QByteArray name = data->rootPropertyCache->className();
1982 QByteArray ptr = name + '*';
1983 QByteArray lst = "QQmlListProperty<" + name + '>';
1985 int ptr_type = QMetaType::registerNormalizedType(ptr,
1986 qMetaTypeDeleteHelper<QObject*>,
1987 qMetaTypeCreateHelper<QObject*>,
1988 qMetaTypeDestructHelper<QObject*>,
1989 qMetaTypeConstructHelper<QObject*>,
1991 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1993 int lst_type = QMetaType::registerNormalizedType(lst,
1994 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1995 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1996 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1997 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1998 sizeof(QQmlListProperty<QObject>),
1999 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
2000 static_cast<QMetaObject*>(0));
2002 data->metaTypeId = ptr_type;
2003 data->listMetaTypeId = lst_type;
2004 data->isRegisteredWithEngine = true;
2006 Locker locker(this);
2007 m_qmlLists.insert(lst_type, ptr_type);
2008 // The QQmlCompiledData is not referenced here, but it is removed from this
2009 // hash in the QQmlCompiledData destructor
2010 m_compositeTypes.insert(ptr_type, data);
2013 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
2015 int ptr_type = data->metaTypeId;
2016 int lst_type = data->listMetaTypeId;
2018 Locker locker(this);
2019 m_qmlLists.remove(lst_type);
2020 m_compositeTypes.remove(ptr_type);
2023 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2025 return typeLoader.isTypeLoaded(url);
2028 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2030 return typeLoader.isScriptLoaded(url);
2033 bool QQml_isFileCaseCorrect(const QString &fileName)
2035 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2036 QFileInfo info(fileName);
2037 const QString absolute = info.absoluteFilePath();
2039 #if defined(Q_OS_MAC)
2040 const QString canonical = info.canonicalFilePath();
2041 #elif defined(Q_OS_WIN)
2042 wchar_t buffer[1024];
2044 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2045 if (rv == 0 || rv >= 1024) return true;
2046 rv = ::GetLongPathName(buffer, buffer, 1024);
2047 if (rv == 0 || rv >= 1024) return true;
2049 const QString canonical = QString::fromWCharArray(buffer);
2052 const int absoluteLength = absolute.length();
2053 const int canonicalLength = canonical.length();
2055 const int length = qMin(absoluteLength, canonicalLength);
2056 for (int ii = 0; ii < length; ++ii) {
2057 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2058 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2060 if (a.toLower() != c.toLower())
2072 \fn QQmlEngine *qmlEngine(const QObject *object)
2075 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2076 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2080 \fn QQmlContext *qmlContext(const QObject *object)
2083 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2084 QQmlEngine::contextForObject(object).