1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
72 #include <private/qqmlboundsignal_p.h>
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtCore/qthread.h>
84 #include <private/qthread_p.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
87 #include <private/qobject_p.h>
88 #include <private/qmetaobject_p.h>
90 #include <private/qqmllocale_p.h>
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
97 #define CSIDL_APPDATA 0x001a // <username>\Application Data
100 Q_DECLARE_METATYPE(QQmlProperty)
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
106 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107 QQmlEnginePrivate::registerQtQuick2Types(uri, versionMajor, versionMinor);
108 QQmlValueTypeFactory::registerValueTypes(uri, versionMajor, versionMinor);
112 \qmlclass QtObject QObject
113 \inqmlmodule QtQuick 2
114 \ingroup qml-utility-elements
116 \brief A basic QML type
118 The QtObject element is a non-visual element which contains only the
121 It can be useful to create a QtObject if you need an extremely
122 lightweight element to enclose a set of custom properties:
124 \snippet qml/qtobject.qml 0
126 It can also be useful for C++ integration, as it is just a plain
127 QObject. See the QObject documentation for further details.
130 \qmlproperty string QtObject::objectName
131 This property holds the QObject::objectName for this specific object instance.
133 This allows a C++ application to locate an item within a QML component
134 using the QObject::findChild() method. For example, the following C++
135 application locates the child \l Rectangle item and dynamically changes its
144 width: 200; height: 200
158 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
161 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
163 item->setProperty("color", QColor(Qt::yellow));
167 bool QQmlEnginePrivate::qml_debugging_enabled = false;
169 // these types are part of the QML language
170 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
172 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
173 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
177 // These QtQuick types' implementation resides in the QtQml module
178 void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
180 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor, "ListElement");
181 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor, "ListModel", new QQuickListModelParser);
182 qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
185 void QQmlEnginePrivate::defineQtQuick2Module()
187 // register the base types into the QtQuick namespace
188 registerBaseTypes("QtQuick",2,0);
190 // register the QtQuick2 types which are implemented in the QtQml module.
191 registerQtQuick2Types("QtQuick",2,0);
192 qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
197 \class QQmlImageProviderBase
198 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
201 Image providers must be registered with the QML engine. The only information the QML
202 engine knows about image providers is the type of image data they provide. To use an
203 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
204 to a QQuickImageProvider pointer.
206 \sa QQuickImageProvider, QQuickTextureFactory
210 \enum QQmlImageProviderBase::ImageType
212 Defines the type of image supported by this image provider.
214 \value Image The Image Provider provides QImage images.
215 The QQuickImageProvider::requestImage() method will be called for all image requests.
216 \value Pixmap The Image Provider provides QPixmap images.
217 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
218 \value Texture The Image Provider provides QSGTextureProvider based images.
219 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
223 \enum QQmlImageProviderBase::Flag
225 Defines specific requirements or features of this image provider.
227 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
228 run in a separate thread, which allows the provider to spend as much time as needed
229 on producing the image without blocking the main thread.
233 QQmlImageProviderBase::QQmlImageProviderBase()
238 QQmlImageProviderBase::~QQmlImageProviderBase()
244 \qmlclass Qt QQmlEnginePrivate
245 \ingroup qml-utility-elements
246 \brief The QML global Qt object provides useful enums and functions from Qt.
248 \keyword QmlGlobalQtObject
250 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
252 The \c Qt object is a global object with utility functions, properties and enums.
254 It is not instantiable; to use it, call the members of the global \c Qt object directly.
261 color: Qt.rgba(1, 0, 0, 1)
262 text: Qt.md5("hello, world")
269 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
270 the \l Qt::LeftButton and \l Qt::RightButton enumeration values as \c Qt.LeftButton and \c Qt.RightButton.
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 bool QQmlData::isSignalConnected(QAbstractDeclarativeData *d, const QObject *, int index)
575 return static_cast<QQmlData *>(d)->signalHasEndpoint(index);
578 int QQmlData::endpointCount(int index)
581 QQmlNotifierEndpoint *ep = notify(index);
592 void QQmlData::markAsDeleted(QObject *o)
594 QQmlData::setQueuedForDeletion(o);
596 QObjectPrivate *p = QObjectPrivate::get(o);
597 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
598 QQmlData::markAsDeleted(*it);
602 void QQmlData::setQueuedForDeletion(QObject *object)
605 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
606 if (!priv->wasDeleted && priv->declarativeData) {
607 QQmlData *ddata = QQmlData::get(object, false);
608 if (ddata->ownContext && ddata->context)
609 ddata->context->emitDestruction();
610 ddata->isQueuedForDeletion = true;
616 void QQmlEnginePrivate::init()
620 static bool firstTime = true;
622 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
623 registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
629 qRegisterMetaType<QVariant>("QVariant");
630 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
631 qRegisterMetaType<QJSValue>("QJSValue");
632 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
633 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
634 qRegisterMetaType<QList<int> >("QList<int>");
635 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
637 v8engine()->setEngine(q);
639 rootContext = new QQmlContext(q,true);
641 if (QCoreApplication::instance()->thread() == q->thread() &&
642 QQmlEngineDebugService::isDebuggingEnabled()) {
644 QQmlEngineDebugService::instance()->addEngine(q);
645 QV8DebugService::initialize(v8engine());
646 QV8ProfilerService::initialize();
647 QQmlProfilerService::initialize();
648 QDebugMessageService::instance();
651 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
652 if (!dataLocation.isEmpty())
653 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
654 + QDir::separator() + QLatin1String("QML")
655 + QDir::separator() + QLatin1String("OfflineStorage");
658 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
661 if (!workerScriptEngine)
662 workerScriptEngine = new QQuickWorkerScriptEngine(q);
663 return workerScriptEngine;
670 \brief The QQmlEngine class provides an environment for instantiating QML components.
673 Each QML component is instantiated in a QQmlContext.
674 QQmlContext's are essential for passing data to QML
675 components. In QML, contexts are arranged hierarchically and this
676 hierarchy is managed by the QQmlEngine.
678 Prior to creating any QML components, an application must have
679 created a QQmlEngine to gain access to a QML context. The
680 following example shows how to create a simple Text item.
684 QQmlComponent component(&engine);
685 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
686 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
688 //add item to view, etc
692 In this case, the Text item will be created in the engine's
693 \l {QQmlEngine::rootContext()}{root context}.
695 Note that the QtQuick 1 version is called QDeclarativeEngine.
697 \sa QQmlComponent, QQmlContext
701 Create a new QQmlEngine with the given \a parent.
703 QQmlEngine::QQmlEngine(QObject *parent)
704 : QJSEngine(*new QQmlEnginePrivate(this), parent)
711 Destroys the QQmlEngine.
713 Any QQmlContext's created on this engine will be
714 invalidated, but not destroyed (unless they are parented to the
717 QQmlEngine::~QQmlEngine()
720 if (d->isDebugging) {
721 QQmlEngineDebugService::instance()->remEngine(this);
724 // Emit onDestruction signals for the root context before
725 // we destroy the contexts, engine, Module APIs etc. that
726 // may be required to handle the destruction signal.
727 QQmlContextData::get(rootContext())->emitDestruction();
729 // if we are the parent of any of the qobject module api instances,
730 // we need to remove them from our internal list, in order to prevent
731 // a segfault in engine private dtor.
732 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
733 QObject *currQObjectApi = 0;
734 QQmlMetaType::ModuleApiInstance *currInstance = 0;
735 foreach (const QQmlMetaType::ModuleApi &key, keys) {
736 currInstance = d->moduleApiInstances.value(key);
737 currQObjectApi = currInstance->qobjectApi;
738 if (this->children().contains(currQObjectApi)) {
739 delete currQObjectApi;
741 d->moduleApiInstances.remove(key);
745 if (d->incubationController)
746 d->incubationController->d = 0;
749 /*! \fn void QQmlEngine::quit()
750 This signal is emitted when the QML loaded by the engine would like to quit.
753 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
754 This signal is emitted when \a warnings messages are generated by QML.
758 Clears the engine's internal component cache.
760 This function causes the property metadata of all components previously
761 loaded by the engine to be destroyed. All previously loaded components and
762 the property bindings for all extant objects created from those components will
765 This function returns the engine to a state where it does not contain any loaded
766 component data. This may be useful in order to reload a smaller subset of the
767 previous component set, or to load a new version of a previously loaded component.
769 Once the component cache has been cleared, components must be loaded before
770 any new objects can be created.
772 \sa trimComponentCache()
774 void QQmlEngine::clearComponentCache()
777 d->typeLoader.clearCache();
781 Trims the engine's internal component cache.
783 This function causes the property metadata of any loaded components which are
784 not currently in use to be destroyed.
786 A component is considered to be in use if there are any extant instances of
787 the component itself, any instances of other components that use the component,
788 or any objects instantiated by any of those components.
790 \sa clearComponentCache()
792 void QQmlEngine::trimComponentCache()
795 d->typeLoader.trimCache();
799 Returns the engine's root context.
801 The root context is automatically created by the QQmlEngine.
802 Data that should be available to all QML component instances
803 instantiated by the engine should be put in the root context.
805 Additional data that should only be available to a subset of
806 component instances should be added to sub-contexts parented to the
809 QQmlContext *QQmlEngine::rootContext() const
811 Q_D(const QQmlEngine);
812 return d->rootContext;
816 Sets the \a factory to use for creating QNetworkAccessManager(s).
818 QNetworkAccessManager is used for all network access by QML. By
819 implementing a factory it is possible to create custom
820 QNetworkAccessManager with specialized caching, proxy and cookie
823 The factory must be set before executing the engine.
825 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
828 QMutexLocker locker(&d->mutex);
829 d->networkAccessManagerFactory = factory;
833 Returns the current QQmlNetworkAccessManagerFactory.
835 \sa setNetworkAccessManagerFactory()
837 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
839 Q_D(const QQmlEngine);
840 return d->networkAccessManagerFactory;
843 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
846 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
848 void *args[] = { 0 };
849 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
853 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
855 QMutexLocker locker(&mutex);
856 QNetworkAccessManager *nam;
857 if (networkAccessManagerFactory) {
858 nam = networkAccessManagerFactory->create(parent);
860 nam = new QNetworkAccessManager(parent);
866 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
868 Q_Q(const QQmlEngine);
869 if (!networkAccessManager)
870 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
871 return networkAccessManager;
875 Returns a common QNetworkAccessManager which can be used by any QML
876 element instantiated by this engine.
878 If a QQmlNetworkAccessManagerFactory has been set and a
879 QNetworkAccessManager has not yet been created, the
880 QQmlNetworkAccessManagerFactory will be used to create the
881 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
882 will have no proxy or cache set.
884 \sa setNetworkAccessManagerFactory()
886 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
888 Q_D(const QQmlEngine);
889 return d->getNetworkAccessManager();
894 Sets the \a provider to use for images requested via the \e
895 image: url scheme, with host \a providerId. The QQmlEngine
896 takes ownership of \a provider.
898 Image providers enable support for pixmap and threaded image
899 requests. See the QQuickImageProvider documentation for details on
900 implementing and using image providers.
902 All required image providers should be added to the engine before any
903 QML sources files are loaded.
905 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
907 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
910 QMutexLocker locker(&d->mutex);
911 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
915 Returns the image provider set for \a providerId.
917 Returns the provider if it was found; otherwise returns 0.
919 \sa QQuickImageProvider
921 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
923 Q_D(const QQmlEngine);
924 QMutexLocker locker(&d->mutex);
925 return d->imageProviders.value(providerId).data();
929 Removes the image provider for \a providerId.
931 \sa addImageProvider(), QQuickImageProvider
933 void QQmlEngine::removeImageProvider(const QString &providerId)
936 QMutexLocker locker(&d->mutex);
937 d->imageProviders.take(providerId);
941 Return the base URL for this engine. The base URL is only used to
942 resolve components when a relative URL is passed to the
943 QQmlComponent constructor.
945 If a base URL has not been explicitly set, this method returns the
946 application's current working directory.
950 QUrl QQmlEngine::baseUrl() const
952 Q_D(const QQmlEngine);
953 if (d->baseUrl.isEmpty()) {
954 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
961 Set the base URL for this engine to \a url.
965 void QQmlEngine::setBaseUrl(const QUrl &url)
972 Returns true if warning messages will be output to stderr in addition
973 to being emitted by the warnings() signal, otherwise false.
975 The default value is true.
977 bool QQmlEngine::outputWarningsToStandardError() const
979 Q_D(const QQmlEngine);
980 return d->outputWarningsToStdErr;
984 Set whether warning messages will be output to stderr to \a enabled.
986 If \a enabled is true, any warning messages generated by QML will be
987 output to stderr and emitted by the warnings() signal. If \a enabled
988 is false, on the warnings() signal will be emitted. This allows
989 applications to handle warning output themselves.
991 The default value is true.
993 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
996 d->outputWarningsToStdErr = enabled;
1000 Returns the QQmlContext for the \a object, or 0 if no
1001 context has been set.
1003 When the QQmlEngine instantiates a QObject, the context is
1006 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
1011 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
1014 static_cast<QQmlData *>(priv->declarativeData);
1018 else if (data->outerContext)
1019 return data->outerContext->asQQmlContext();
1025 Sets the QQmlContext for the \a object to \a context.
1026 If the \a object already has a context, a warning is
1027 output, but the context is not changed.
1029 When the QQmlEngine instantiates a QObject, the context is
1032 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1034 if (!object || !context)
1037 QQmlData *data = QQmlData::get(object, true);
1038 if (data->context) {
1039 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1043 QQmlContextData *contextData = QQmlContextData::get(context);
1044 contextData->addObject(object);
1048 \enum QQmlEngine::ObjectOwnership
1050 Ownership controls whether or not QML automatically destroys the
1051 QObject when the object is garbage collected by the JavaScript
1052 engine. The two ownership options are:
1054 \value CppOwnership The object is owned by C++ code, and will
1055 never be deleted by QML. The JavaScript destroy() method cannot be
1056 used on objects with CppOwnership. This option is similar to
1057 QScriptEngine::QtOwnership.
1059 \value JavaScriptOwnership The object is owned by JavaScript.
1060 When the object is returned to QML as the return value of a method
1061 call or property access, QML will track it, and delete the object
1062 if there are no remaining JavaScript references to it and it has no
1063 QObject::parent(). An object tracked by one QQmlEngine
1064 will be deleted during that QQmlEngine's destructor, and thus
1065 JavaScript references between objects with JavaScriptOwnership from
1066 two different engines will not be valid after the deletion of one of
1067 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1069 Generally an application doesn't need to set an object's ownership
1070 explicitly. QML uses a heuristic to set the default object
1071 ownership. By default, an object that is created by QML has
1072 JavaScriptOwnership. The exception to this are the root objects
1073 created by calling QQmlComponent::create() or
1074 QQmlComponent::beginCreate() which have CppOwnership by
1075 default. The ownership of these root-level objects is considered to
1076 have been transferred to the C++ caller.
1078 Objects not-created by QML have CppOwnership by default. The
1079 exception to this is objects returned from a C++ method call. The
1080 ownership of these objects is passed to JavaScript.
1082 Calling setObjectOwnership() overrides the default ownership
1083 heuristic used by QML.
1087 Sets the \a ownership of \a object.
1089 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1094 QQmlData *ddata = QQmlData::get(object, true);
1098 ddata->indestructible = (ownership == CppOwnership)?true:false;
1099 ddata->explicitIndestructibleSet = true;
1103 Returns the ownership of \a object.
1105 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1108 return CppOwnership;
1110 QQmlData *ddata = QQmlData::get(object, false);
1112 return CppOwnership;
1114 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1117 bool QQmlEngine::event(QEvent *e)
1120 if (e->type() == QEvent::User)
1121 d->doDeleteInEngineThread();
1123 return QJSEngine::event(e);
1126 void QQmlEnginePrivate::doDeleteInEngineThread()
1128 QFieldList<Deletable, &Deletable::next> list;
1130 list.copyAndClear(toDeleteInEngineThread);
1133 while (Deletable *d = list.takeFirst())
1137 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1139 QQmlData *data = QQmlData::get(object);
1141 if (data && data->compiledData && data->deferredIdx) {
1142 QQmlObjectCreatingProfiler prof;
1144 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1145 prof.setTypeName(type ? type->qmlTypeName()
1146 : QString::fromUtf8(object->metaObject()->className()));
1147 if (data->outerContext)
1148 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1150 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1152 QQmlComponentPrivate::ConstructionState state;
1153 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1155 // Release the reference for the deferral action (we still have one from construction)
1156 data->compiledData->release();
1157 data->compiledData = 0;
1159 QQmlComponentPrivate::complete(ep, &state);
1163 QQmlContext *qmlContext(const QObject *obj)
1165 return QQmlEngine::contextForObject(obj);
1168 QQmlEngine *qmlEngine(const QObject *obj)
1170 QQmlData *data = QQmlData::get(obj, false);
1171 if (!data || !data->context)
1173 return data->context->engine;
1176 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1178 QQmlData *data = QQmlData::get(object);
1180 return 0; // Attached properties are only on objects created by QML
1182 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1186 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1190 rv = pf(const_cast<QObject *>(object));
1193 data->attachedProperties()->insert(id, rv);
1198 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1199 const QMetaObject *attachedMetaObject, bool create)
1202 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1204 if (*idCache == -1 || !object)
1207 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1210 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1212 #ifndef QQML_NO_DEBUG_PROTOCOL
1213 if (!QQmlEnginePrivate::qml_debugging_enabled
1215 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1217 QQmlEnginePrivate::qml_debugging_enabled = true;
1222 class QQmlDataExtended {
1225 ~QQmlDataExtended();
1227 QHash<int, QObject *> attachedProperties;
1230 QQmlDataExtended::QQmlDataExtended()
1234 QQmlDataExtended::~QQmlDataExtended()
1238 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1241 layout(endpoint->next);
1243 int index = endpoint->sourceSignal;
1244 index = qMin(index, 0xFFFF - 1);
1246 endpoint->next = notifies[index];
1247 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1248 endpoint->prev = ¬ifies[index];
1249 notifies[index] = endpoint;
1252 void QQmlData::NotifyList::layout()
1254 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1257 QQmlNotifierEndpoint **old = notifies;
1258 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1259 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1260 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1261 sizeof(QQmlNotifierEndpoint*);
1262 memset(notifies + notifiesSize, 0, memsetSize);
1264 if (notifies != old) {
1265 for (int ii = 0; ii < notifiesSize; ++ii)
1267 notifies[ii]->prev = ¬ifies[ii];
1270 notifiesSize = maximumTodoIndex + 1;
1275 maximumTodoIndex = 0;
1279 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1282 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1283 notifyList->connectionMask = 0;
1284 notifyList->maximumTodoIndex = 0;
1285 notifyList->notifiesSize = 0;
1286 notifyList->todo = 0;
1287 notifyList->notifies = 0;
1290 Q_ASSERT(!endpoint->isConnected());
1292 index = qMin(index, 0xFFFF - 1);
1293 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1295 if (index < notifyList->notifiesSize) {
1297 endpoint->next = notifyList->notifies[index];
1298 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1299 endpoint->prev = ¬ifyList->notifies[index];
1300 notifyList->notifies[index] = endpoint;
1303 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1305 endpoint->next = notifyList->todo;
1306 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1307 endpoint->prev = ¬ifyList->todo;
1308 notifyList->todo = endpoint;
1313 index MUST in the range returned by QObjectPrivate::signalIndex()
1314 This is different than the index returned by QMetaMethod::methodIndex()
1316 bool QQmlData::signalHasEndpoint(int index)
1318 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1321 QHash<int, QObject *> *QQmlData::attachedProperties() const
1323 if (!extendedData) extendedData = new QQmlDataExtended;
1324 return &extendedData->attachedProperties;
1327 void QQmlData::destroyed(QObject *object)
1329 if (nextContextObject)
1330 nextContextObject->prevContextObject = prevContextObject;
1331 if (prevContextObject)
1332 *prevContextObject = nextContextObject;
1334 QQmlAbstractBinding *binding = bindings;
1336 QQmlAbstractBinding *next = binding->nextBinding();
1337 binding->setAddedToObject(false);
1338 binding->setNextBinding(0);
1344 compiledData->release();
1348 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1349 while (signalHandler) {
1350 if (signalHandler->isEvaluating()) {
1351 // The object is being deleted during signal handler evaluation.
1352 // This will cause a crash due to invalid memory access when the
1353 // evaluation has completed.
1354 // Abort with a friendly message instead.
1355 QString locationString;
1356 QQmlBoundSignalExpression *expr = signalHandler->expression();
1358 QString fileName = expr->sourceFile();
1359 if (fileName.isEmpty())
1360 fileName = QStringLiteral("<Unknown File>");
1361 locationString.append(fileName);
1362 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1363 QString source = expr->expression();
1364 if (source.size() > 100) {
1365 source.truncate(96);
1366 source.append(QStringLiteral(" ..."));
1368 locationString.append(source);
1370 locationString = QStringLiteral("<Unknown Location>");
1372 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1373 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1374 "instead), or the application is running a nested event loop.\n"
1375 "This behavior is NOT supported!\n"
1376 "%s", object, qPrintable(locationString));
1379 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1380 signalHandler->m_prevSignal = 0;
1381 signalHandler->m_nextSignal = 0;
1382 delete signalHandler;
1383 signalHandler = next;
1390 propertyCache->release();
1392 if (ownContext && context)
1396 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1397 *guard = (QObject *)0;
1398 guard->objectDestroyed(object);
1402 while (notifyList->todo)
1403 notifyList->todo->disconnect();
1404 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1405 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1408 free(notifyList->notifies);
1414 delete extendedData;
1416 // Dispose the handle.
1417 // We don't simply clear it (and wait for next gc cycle to dispose
1418 // via the weak qobject reference callback) as this affects the
1419 // outcomes of v8's gc statistical analysis heuristics, which can
1420 // cause unnecessary growth of the old pointer space js heap area.
1421 qPersistentDispose(v8object);
1427 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1429 void QQmlData::parentChanged(QObject *object, QObject *parent)
1432 if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1436 { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1437 { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1439 qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1440 "User code is attempting to change it to %s.\n"
1441 "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1446 bool QQmlData::hasBindingBit(int bit) const
1448 if (bindingBitsSize > bit)
1449 return bindingBits[bit / 32] & (1 << (bit % 32));
1454 void QQmlData::clearBindingBit(int bit)
1456 if (bindingBitsSize > bit)
1457 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1460 void QQmlData::setBindingBit(QObject *obj, int bit)
1462 if (bindingBitsSize <= bit) {
1463 int props = QQmlMetaObject(obj).propertyCount();
1464 Q_ASSERT(bit < props);
1466 int arraySize = (props + 31) / 32;
1467 int oldArraySize = bindingBitsSize / 32;
1469 bindingBits = (quint32 *)realloc(bindingBits,
1470 arraySize * sizeof(quint32));
1472 memset(bindingBits + oldArraySize,
1474 sizeof(quint32) * (arraySize - oldArraySize));
1476 bindingBitsSize = arraySize * 32;
1479 bindingBits[bit / 32] |= (1 << (bit % 32));
1482 void QQmlEnginePrivate::sendQuit()
1486 if (q->receivers(SIGNAL(quit())) == 0) {
1487 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1491 static void dumpwarning(const QQmlError &error)
1493 QMessageLogger(error.url().toString().toLatin1().constData(),
1494 error.line(), 0).warning().nospace()
1495 << qPrintable(error.toString());
1498 static void dumpwarning(const QList<QQmlError> &errors)
1500 for (int ii = 0; ii < errors.count(); ++ii)
1501 dumpwarning(errors.at(ii));
1504 void QQmlEnginePrivate::warning(const QQmlError &error)
1507 q->warnings(QList<QQmlError>() << error);
1508 if (outputWarningsToStdErr)
1512 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1515 q->warnings(errors);
1516 if (outputWarningsToStdErr)
1517 dumpwarning(errors);
1520 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1523 warning(error->error(q));
1526 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1529 QQmlEnginePrivate::get(engine)->warning(error);
1534 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1537 QQmlEnginePrivate::get(engine)->warning(error);
1542 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1545 QQmlEnginePrivate::get(engine)->warning(error);
1547 dumpwarning(error->error(0));
1550 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1553 engine->warning(error);
1558 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1561 engine->warning(error);
1567 This function should be called prior to evaluation of any js expression,
1568 so that scarce resources are not freed prematurely (eg, if there is a
1569 nested javascript expression).
1571 void QQmlEnginePrivate::referenceScarceResources()
1573 scarceResourcesRefCount += 1;
1577 This function should be called after evaluation of the js expression is
1578 complete, and so the scarce resources may be freed safely.
1580 void QQmlEnginePrivate::dereferenceScarceResources()
1582 Q_ASSERT(scarceResourcesRefCount > 0);
1583 scarceResourcesRefCount -= 1;
1585 // if the refcount is zero, then evaluation of the "top level"
1586 // expression must have completed. We can safely release the
1587 // scarce resources.
1588 if (scarceResourcesRefCount == 0) {
1589 // iterate through the list and release them all.
1590 // note that the actual SRD is owned by the JS engine,
1591 // so we cannot delete the SRD; but we can free the
1592 // memory used by the variant in the SRD.
1593 while (ScarceResourceData *sr = scarceResources.first()) {
1594 sr->data = QVariant();
1595 scarceResources.remove(sr);
1601 Adds \a path as a directory where the engine searches for
1602 installed modules in a URL-based directory structure.
1603 The \a path may be a local filesystem directory or a URL.
1605 The newly added \a path will be first in the importPathList().
1607 \sa setImportPathList(), {QML Modules}
1609 void QQmlEngine::addImportPath(const QString& path)
1612 d->importDatabase.addImportPath(path);
1616 Returns the list of directories where the engine searches for
1617 installed modules in a URL-based directory structure.
1619 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1620 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1621 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1622 provided by that module. A \c qmldir file is required for defining the
1623 type version mapping and possibly QML extensions plugins.
1625 By default, the list contains the directory of the application executable,
1626 paths specified in the \c QML_IMPORT_PATH environment variable,
1627 and the builtin \c ImportsPath from QLibraryInfo.
1629 \sa addImportPath(), setImportPathList()
1631 QStringList QQmlEngine::importPathList() const
1633 Q_D(const QQmlEngine);
1634 return d->importDatabase.importPathList();
1638 Sets \a paths as the list of directories where the engine searches for
1639 installed modules in a URL-based directory structure.
1641 By default, the list contains the directory of the application executable,
1642 paths specified in the \c QML_IMPORT_PATH environment variable,
1643 and the builtin \c ImportsPath from QLibraryInfo.
1645 \sa importPathList(), addImportPath()
1647 void QQmlEngine::setImportPathList(const QStringList &paths)
1650 d->importDatabase.setImportPathList(paths);
1655 Adds \a path as a directory where the engine searches for
1656 native plugins for imported modules (referenced in the \c qmldir file).
1658 By default, the list contains only \c ., i.e. the engine searches
1659 in the directory of the \c qmldir file itself.
1661 The newly added \a path will be first in the pluginPathList().
1663 \sa setPluginPathList()
1665 void QQmlEngine::addPluginPath(const QString& path)
1668 d->importDatabase.addPluginPath(path);
1673 Returns the list of directories 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 \sa addPluginPath(), setPluginPathList()
1681 QStringList QQmlEngine::pluginPathList() const
1683 Q_D(const QQmlEngine);
1684 return d->importDatabase.pluginPathList();
1688 Sets the list of directories where the engine searches for
1689 native plugins for imported modules (referenced in the \c qmldir file)
1692 By default, the list contains only \c ., i.e. the engine searches
1693 in the directory of the \c qmldir file itself.
1695 \sa pluginPathList(), addPluginPath()
1697 void QQmlEngine::setPluginPathList(const QStringList &paths)
1700 d->importDatabase.setPluginPathList(paths);
1704 Imports the plugin named \a filePath with the \a uri provided.
1705 Returns true if the plugin was successfully imported; otherwise returns false.
1707 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1709 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1711 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1714 return d->importDatabase.importPlugin(filePath, uri, errors);
1718 \property QQmlEngine::offlineStoragePath
1719 \brief the directory for storing offline user data
1721 Returns the directory where SQL and other offline
1724 QQuickWebView and the SQL databases created with openDatabase()
1727 The default is QML/OfflineStorage in the platform-standard
1728 user application data directory.
1730 Note that the path may not currently exist on the filesystem, so
1731 callers wanting to \e create new files at this location should create
1732 it first - see QDir::mkpath().
1734 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1737 d->offlineStoragePath = dir;
1740 QString QQmlEngine::offlineStoragePath() const
1742 Q_D(const QQmlEngine);
1743 return d->offlineStoragePath;
1746 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1750 if (!mo->superClass()) {
1751 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1752 propertyCache.insert(mo, rv);
1755 QQmlPropertyCache *super = cache(mo->superClass());
1756 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1757 propertyCache.insert(mo, rv);
1762 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1765 QList<QQmlType *> types;
1767 int maxMinorVersion = 0;
1769 const QMetaObject *metaObject = type->metaObject();
1771 while (metaObject) {
1772 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1773 type->majorVersion(), minorVersion);
1775 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1781 metaObject = metaObject->superClass();
1784 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1786 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1790 QQmlPropertyCache *raw = cache(type->metaObject());
1792 bool hasCopied = false;
1794 for (int ii = 0; ii < types.count(); ++ii) {
1795 QQmlType *currentType = types.at(ii);
1799 int rev = currentType->metaObjectRevision();
1800 int moIndex = types.count() - 1 - ii;
1802 if (raw->allowedRevisionCache[moIndex] != rev) {
1807 raw->allowedRevisionCache[moIndex] = rev;
1811 // Test revision compatibility - the basic rule is:
1812 // * Anything that is excluded, cannot overload something that is not excluded *
1814 // Signals override:
1815 // * other signals and methods of the same name.
1816 // * properties named on<Signal Name>
1817 // * automatic <property name>Changed notify signals
1819 // Methods override:
1820 // * other methods of the same name
1822 // Properties override:
1823 // * other elements of the same name
1825 bool overloadError = false;
1826 QString overloadName;
1829 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1830 !overloadError && iter != raw->stringCache.end();
1833 QQmlPropertyData *d = *iter;
1834 if (raw->isAllowedInRevision(d))
1835 continue; // Not excluded - no problems
1837 // check that a regular "name" overload isn't happening
1838 QQmlPropertyData *current = d;
1839 while (!overloadError && current) {
1840 current = d->overrideData(current);
1841 if (current && raw->isAllowedInRevision(current))
1842 overloadError = true;
1847 if (overloadError) {
1848 if (hasCopied) raw->release();
1850 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."));
1854 if (!hasCopied) raw->addref();
1855 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1857 if (minorVersion != maxMinorVersion) {
1859 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1865 QQmlMetaType::ModuleApiInstance *
1866 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1868 Locker locker(this);
1870 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1872 a = new QQmlMetaType::ModuleApiInstance;
1873 a->scriptCallback = module.script;
1874 a->qobjectCallback = module.qobject;
1875 a->instanceMetaObject = module.instanceMetaObject;
1876 moduleApiInstances.insert(module, a);
1882 bool QQmlEnginePrivate::isQObject(int t)
1884 Locker locker(this);
1885 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1888 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1890 Locker locker(this);
1891 int t = v.userType();
1892 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1894 return *(QObject **)(v.constData());
1896 return QQmlMetaType::toQObject(v, ok);
1900 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1902 Locker locker(this);
1903 if (m_compositeTypes.contains(t))
1904 return QQmlMetaType::Object;
1905 else if (m_qmlLists.contains(t))
1906 return QQmlMetaType::List;
1908 return QQmlMetaType::typeCategory(t);
1911 bool QQmlEnginePrivate::isList(int t) const
1913 Locker locker(this);
1914 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1917 int QQmlEnginePrivate::listType(int t) const
1919 Locker locker(this);
1920 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1921 if (iter != m_qmlLists.end())
1924 return QQmlMetaType::listType(t);
1927 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1929 Locker locker(this);
1930 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1931 if (iter != m_compositeTypes.end()) {
1932 return QQmlMetaObject((*iter)->rootPropertyCache);
1934 QQmlType *type = QQmlMetaType::qmlType(t);
1935 return QQmlMetaObject(type?type->baseMetaObject():0);
1939 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1941 Locker locker(this);
1942 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1943 if (iter != m_compositeTypes.end()) {
1944 return QQmlMetaObject((*iter)->rootPropertyCache);
1946 QQmlType *type = QQmlMetaType::qmlType(t);
1947 return QQmlMetaObject(type?type->metaObject():0);
1951 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1953 Locker locker(this);
1954 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1955 if (iter != m_compositeTypes.end()) {
1956 return (*iter)->rootPropertyCache;
1958 QQmlType *type = QQmlMetaType::qmlType(t);
1960 return type?cache(type->metaObject()):0;
1964 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1966 Locker locker(this);
1967 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1968 if (iter != m_compositeTypes.end()) {
1969 return (*iter)->rootPropertyCache;
1971 QQmlType *type = QQmlMetaType::qmlType(t);
1973 return type?cache(type->baseMetaObject()):0;
1977 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1979 QByteArray name = data->rootPropertyCache->className();
1981 QByteArray ptr = name + '*';
1982 QByteArray lst = "QQmlListProperty<" + name + '>';
1984 int ptr_type = QMetaType::registerNormalizedType(ptr,
1985 qMetaTypeDeleteHelper<QObject*>,
1986 qMetaTypeCreateHelper<QObject*>,
1987 qMetaTypeDestructHelper<QObject*>,
1988 qMetaTypeConstructHelper<QObject*>,
1990 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1992 int lst_type = QMetaType::registerNormalizedType(lst,
1993 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1994 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1995 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1996 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1997 sizeof(QQmlListProperty<QObject>),
1998 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
1999 static_cast<QMetaObject*>(0));
2001 data->metaTypeId = ptr_type;
2002 data->listMetaTypeId = lst_type;
2003 data->isRegisteredWithEngine = true;
2005 Locker locker(this);
2006 m_qmlLists.insert(lst_type, ptr_type);
2007 // The QQmlCompiledData is not referenced here, but it is removed from this
2008 // hash in the QQmlCompiledData destructor
2009 m_compositeTypes.insert(ptr_type, data);
2012 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
2014 int ptr_type = data->metaTypeId;
2015 int lst_type = data->listMetaTypeId;
2017 Locker locker(this);
2018 m_qmlLists.remove(lst_type);
2019 m_compositeTypes.remove(ptr_type);
2022 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2024 return typeLoader.isTypeLoaded(url);
2027 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2029 return typeLoader.isScriptLoaded(url);
2032 bool QQml_isFileCaseCorrect(const QString &fileName)
2034 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2035 QFileInfo info(fileName);
2036 const QString absolute = info.absoluteFilePath();
2038 #if defined(Q_OS_MAC)
2039 const QString canonical = info.canonicalFilePath();
2040 #elif defined(Q_OS_WIN)
2041 wchar_t buffer[1024];
2043 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2044 if (rv == 0 || rv >= 1024) return true;
2045 rv = ::GetLongPathName(buffer, buffer, 1024);
2046 if (rv == 0 || rv >= 1024) return true;
2048 const QString canonical = QString::fromWCharArray(buffer);
2051 const int absoluteLength = absolute.length();
2052 const int canonicalLength = canonical.length();
2054 const int length = qMin(absoluteLength, canonicalLength);
2055 for (int ii = 0; ii < length; ++ii) {
2056 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2057 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2059 if (a.toLower() != c.toLower())
2071 \fn QQmlEngine *qmlEngine(const QObject *object)
2074 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2075 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2079 \fn QQmlContext *qmlContext(const QObject *object)
2082 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2083 QQmlEngine::contextForObject(object).