1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
72 #include <private/qqmlboundsignal_p.h>
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtCore/qthread.h>
84 #include <private/qthread_p.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
87 #include <private/qobject_p.h>
88 #include <private/qmetaobject_p.h>
90 #include <private/qqmllocale_p.h>
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
97 #define CSIDL_APPDATA 0x001a // <username>\Application Data
100 Q_DECLARE_METATYPE(QQmlProperty)
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
106 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107 QQmlEnginePrivate::registerQtQuick2Types(uri, versionMajor, versionMinor);
108 QQmlValueTypeFactory::registerValueTypes(uri, versionMajor, versionMinor);
113 \instantiates QObject
114 \inqmlmodule QtQuick 2
115 \ingroup qml-utility-elements
116 \brief A basic QML type
118 The QtObject type is a non-visual element which contains only the
121 It can be useful to create a QtObject if you need an extremely
122 lightweight type to enclose a set of custom properties:
124 \snippet qml/qtobject.qml 0
126 It can also be useful for C++ integration, as it is just a plain
127 QObject. See the QObject documentation for further details.
130 \qmlproperty string QtObject::objectName
131 This property holds the QObject::objectName for this specific object instance.
133 This allows a C++ application to locate an item within a QML component
134 using the QObject::findChild() method. For example, the following C++
135 application locates the child \l Rectangle item and dynamically changes its
144 width: 200; height: 200
158 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
161 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
163 item->setProperty("color", QColor(Qt::yellow));
167 bool QQmlEnginePrivate::qml_debugging_enabled = false;
169 // these types are part of the QML language
170 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
172 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
173 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
177 // These QtQuick types' implementation resides in the QtQml module
178 void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
180 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor, "ListElement");
181 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor, "ListModel", new QQuickListModelParser);
182 qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
185 void QQmlEnginePrivate::defineQtQuick2Module()
187 // register the base types into the QtQuick namespace
188 registerBaseTypes("QtQuick",2,0);
190 // register the QtQuick2 types which are implemented in the QtQml module.
191 registerQtQuick2Types("QtQuick",2,0);
192 qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
197 \class QQmlImageProviderBase
198 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
202 Image providers must be registered with the QML engine. The only information the QML
203 engine knows about image providers is the type of image data they provide. To use an
204 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
205 to a QQuickImageProvider pointer.
207 \sa QQuickImageProvider, QQuickTextureFactory
211 \enum QQmlImageProviderBase::ImageType
213 Defines the type of image supported by this image provider.
215 \value Image The Image Provider provides QImage images.
216 The QQuickImageProvider::requestImage() method will be called for all image requests.
217 \value Pixmap The Image Provider provides QPixmap images.
218 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
219 \value Texture The Image Provider provides QSGTextureProvider based images.
220 The QQuickImageProvider::requestTexture() method will be called for all image requests.
225 \enum QQmlImageProviderBase::Flag
227 Defines specific requirements or features of this image provider.
229 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
230 run in a separate thread, which allows the provider to spend as much time as needed
231 on producing the image without blocking the main thread.
235 QQmlImageProviderBase::QQmlImageProviderBase()
240 QQmlImageProviderBase::~QQmlImageProviderBase()
247 \instantiates QQmlEnginePrivate
248 \ingroup qml-utility-elements
249 \brief The QML global Qt object provides useful enums and functions from Qt.
251 \keyword QmlGlobalQtObject
253 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
255 The \c Qt object is a global object with utility functions, properties and enums.
257 It is not instantiable; to use it, call the members of the global \c Qt object directly.
264 color: Qt.rgba(1, 0, 0, 1)
265 text: Qt.md5("hello, world")
272 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
273 the \l Qt::LeftButton and \l Qt::RightButton enumeration values as \c Qt.LeftButton and \c Qt.RightButton.
278 The Qt object also contains helper functions for creating objects of specific
279 data types. This is primarily useful when setting the properties of an item
280 when the property has one of the following types:
282 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
283 \li \c point - use \l{Qt::point()}{Qt.point()}
284 \li \c size - use \l{Qt::size()}{Qt.size()}
287 If the QtQuick module has been imported, the following helper functions for
288 creating objects of specific data types are also available for clients to use:
290 \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()}
291 \li \c font - use \l{Qt::font()}{Qt.font()}
292 \li \c vector2d - use \l{Qt::vector2d()}{Qt.vector2d()}
293 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
294 \li \c vector4d - use \l{Qt::vector4d()}{Qt.vector4d()}
295 \li \c quaternion - use \l{Qt::quaternion()}{Qt.quaternion()}
296 \li \c matrix4x4 - use \l{Qt::matrix4x4()}{Qt.matrix4x4()}
299 There are also string based constructors for these types. See \l{qtqml-typesystem-basictypes.html}{QML Basic Types} for more information.
301 \section1 Date/Time Formatters
303 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
306 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
307 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
308 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
311 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
314 \section1 Dynamic Object Creation
315 The following functions on the global object allow you to dynamically create QML
316 items from files or strings. See \l{Dynamic QML Object Creation from JavaScript} for an overview
320 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
321 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
325 \section1 Other Functions
327 The following functions are also on the Qt object.
330 \li \l{Qt::quit()}{Qt.quit()}
331 \li \l{Qt::md5()}{Qt.md5(string)}
332 \li \l{Qt::btoa()}{string Qt.btoa(string)}
333 \li \l{Qt::atob()}{string Qt.atob(string)}
334 \li \l{Qt::binding()}{object Qt.binding(function)}
335 \li \l{Qt::locale()}{object Qt.locale()}
336 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
337 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
338 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
343 \qmlproperty object Qt::application
346 The \c application object provides access to global application state
347 properties shared by many QML components.
353 \li \c application.active
355 This read-only property indicates whether the application is the top-most and focused
356 application, and the user is able to interact with the application. The property
357 is false when the application is in the background, the device keylock or screen
358 saver is active, the screen backlight is turned off, or the global system dialog
359 is being displayed on top of the application. It can be used for stopping and
360 pausing animations, timers and active processing of data in order to save device
361 battery power and free device memory and processor load when the application is not
365 \li \c application.layoutDirection
367 This read-only property can be used to query the default layout direction of the
368 application. On system start-up, the default layout direction depends on the
369 application's language. The property has a value of \c Qt.RightToLeft in locales
370 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
371 where the reading direction flows from left to right. You can bind to this
372 property to customize your application layouts to support both layout directions.
377 \li Qt.LeftToRight - Text and graphics elements should be positioned
379 \li Qt.RightToLeft - Text and graphics elements should be positioned
385 The following example uses the \c application object to indicate
386 whether the application is currently active:
388 \snippet qml/application.qml document
392 \qmlproperty object Qt::inputMethod
395 The \c inputMethod object allows access to application's QInputMethod object
396 and all its properties and slots. See the QInputMethod documentation for
402 \qmlmethod object Qt::include(string url, jsobject callback)
404 Includes another JavaScript file. This method can only be used from within JavaScript files,
405 and not regular QML files.
407 This imports all functions from \a url into the current script's namespace.
409 Qt.include() returns an object that describes the status of the operation. The object has
410 a single property, \c {status}, that is set to one of the following values:
413 \header \li Symbol \li Value \li Description
414 \row \li result.OK \li 0 \li The include completed successfully.
415 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
416 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
417 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
418 An additional \c exception property will be set in this case.
421 The \c status property will be updated as the operation progresses.
423 If provided, \a callback is invoked when the operation completes. The callback is passed
424 the same object as is returned from the Qt.include() call.
426 // Qt.include() is implemented in qv8include.cpp
429 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
430 : propertyCapture(0), rootContext(0), isDebugging(false),
431 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
432 cleanup(0), erroredBindings(0), inProgressCreations(0),
433 workerScriptEngine(0), activeVME(0),
434 networkAccessManager(0), networkAccessManagerFactory(0),
435 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
436 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
440 QQmlEnginePrivate::~QQmlEnginePrivate()
442 if (inProgressCreations)
443 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
446 QQmlCleanup *c = cleanup;
448 if (cleanup) cleanup->prev = &cleanup;
454 doDeleteInEngineThread();
456 if (incubationController) incubationController->d = 0;
457 incubationController = 0;
462 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
464 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
466 for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
467 iter.value()->isRegisteredWithEngine = false;
470 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
472 QObjectPrivate *p = QObjectPrivate::get(o);
473 if (p->declarativeData) {
474 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
475 if (d->ownContext && d->context) {
476 d->context->destroy();
480 // Mark this object as in the process of deletion to
481 // prevent it resolving in bindings
482 QQmlData::markAsDeleted(o);
484 // Disconnect the notifiers now - during object destruction this would be too late, since
485 // the disconnect call wouldn't be able to call disconnectNotify(), as it isn't possible to
486 // get the metaobject anymore.
487 d->disconnectNotifiers();
491 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
493 static_cast<QQmlData *>(d)->destroyed(o);
496 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
498 static_cast<QQmlData *>(d)->parentChanged(o, p);
501 class QQmlThreadNotifierProxyObject : public QObject
504 QPointer<QObject> target;
506 virtual int qt_metacall(QMetaObject::Call, int methodIndex, void **a) {
510 QMetaMethod method = target->metaObject()->method(methodIndex);
511 Q_ASSERT(method.methodType() == QMetaMethod::Signal);
512 int signalIndex = QMetaObjectPrivate::signalIndex(method);
513 QQmlData *ddata = QQmlData::get(target, false);
514 QQmlNotifierEndpoint *ep = ddata->notify(signalIndex);
515 if (ep) QQmlNotifier::emitNotify(ep, a);
523 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
525 QQmlData *ddata = QQmlData::get(object, false);
526 if (!ddata) return; // Probably being deleted
528 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
529 // that they're exposed to. However, to make writing "worker objects" that calculate data
530 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
531 // QQmlEngine to emit signals from a different thread. These signals are then automatically
532 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
533 // by the qqmlecmascript::threadSignal() autotest.
534 if (ddata->notifyList &&
535 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
537 if (!QObjectPrivate::get(object)->threadData->thread)
540 QMetaMethod m = QMetaObjectPrivate::signal(object->metaObject(), index);
541 QList<QByteArray> parameterTypes = m.parameterTypes();
543 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
544 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
546 types[0] = 0; // return type
547 args[0] = 0; // return value
549 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
550 const QByteArray &typeName = parameterTypes.at(ii);
551 if (typeName.endsWith('*'))
552 types[ii + 1] = QMetaType::VoidStar;
554 types[ii + 1] = QMetaType::type(typeName);
556 if (!types[ii + 1]) {
557 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
558 "(Make sure '%s' is registered using qRegisterMetaType().)",
559 typeName.constData(), typeName.constData());
565 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
568 QMetaCallEvent *ev = new QMetaCallEvent(m.methodIndex(), 0, 0, object, index,
569 parameterTypes.count() + 1, types, args);
571 QQmlThreadNotifierProxyObject *mpo = new QQmlThreadNotifierProxyObject;
572 mpo->target = object;
573 mpo->moveToThread(QObjectPrivate::get(object)->threadData->thread);
574 QCoreApplication::postEvent(mpo, ev);
577 QQmlNotifierEndpoint *ep = ddata->notify(index);
578 if (ep) QQmlNotifier::emitNotify(ep, a);
582 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
584 return static_cast<QQmlData *>(d)->endpointCount(index);
587 bool QQmlData::isSignalConnected(QAbstractDeclarativeData *d, const QObject *, int index)
589 return static_cast<QQmlData *>(d)->signalHasEndpoint(index);
592 int QQmlData::endpointCount(int index)
595 QQmlNotifierEndpoint *ep = notify(index);
606 void QQmlData::markAsDeleted(QObject *o)
608 QQmlData::setQueuedForDeletion(o);
610 QObjectPrivate *p = QObjectPrivate::get(o);
611 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
612 QQmlData::markAsDeleted(*it);
616 void QQmlData::setQueuedForDeletion(QObject *object)
619 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
620 if (!priv->wasDeleted && priv->declarativeData) {
621 QQmlData *ddata = QQmlData::get(object, false);
622 if (ddata->ownContext && ddata->context)
623 ddata->context->emitDestruction();
624 ddata->isQueuedForDeletion = true;
630 void QQmlEnginePrivate::init()
634 static bool firstTime = true;
636 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
637 registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
643 qRegisterMetaType<QVariant>("QVariant");
644 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
645 qRegisterMetaType<QJSValue>("QJSValue");
646 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
647 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
648 qRegisterMetaType<QList<int> >("QList<int>");
649 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
651 v8engine()->setEngine(q);
653 rootContext = new QQmlContext(q,true);
655 if (QCoreApplication::instance()->thread() == q->thread() &&
656 QQmlEngineDebugService::isDebuggingEnabled()) {
658 QQmlEngineDebugService::instance()->addEngine(q);
659 QV8DebugService::initialize(v8engine());
660 QV8ProfilerService::initialize();
661 QQmlProfilerService::initialize();
662 QDebugMessageService::instance();
665 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
666 if (!dataLocation.isEmpty())
667 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
668 + QDir::separator() + QLatin1String("QML")
669 + QDir::separator() + QLatin1String("OfflineStorage");
672 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
675 if (!workerScriptEngine)
676 workerScriptEngine = new QQuickWorkerScriptEngine(q);
677 return workerScriptEngine;
684 \brief The QQmlEngine class provides an environment for instantiating QML components.
687 Each QML component is instantiated in a QQmlContext.
688 QQmlContext's are essential for passing data to QML
689 components. In QML, contexts are arranged hierarchically and this
690 hierarchy is managed by the QQmlEngine.
692 Prior to creating any QML components, an application must have
693 created a QQmlEngine to gain access to a QML context. The
694 following example shows how to create a simple Text item.
698 QQmlComponent component(&engine);
699 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
700 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
702 //add item to view, etc
706 In this case, the Text item will be created in the engine's
707 \l {QQmlEngine::rootContext()}{root context}.
709 Note that the QtQuick 1 version is called QDeclarativeEngine.
711 \sa QQmlComponent, QQmlContext
715 Create a new QQmlEngine with the given \a parent.
717 QQmlEngine::QQmlEngine(QObject *parent)
718 : QJSEngine(*new QQmlEnginePrivate(this), parent)
725 Destroys the QQmlEngine.
727 Any QQmlContext's created on this engine will be
728 invalidated, but not destroyed (unless they are parented to the
731 QQmlEngine::~QQmlEngine()
734 if (d->isDebugging) {
735 QQmlEngineDebugService::instance()->remEngine(this);
738 // Emit onDestruction signals for the root context before
739 // we destroy the contexts, engine, Singleton Types etc. that
740 // may be required to handle the destruction signal.
741 QQmlContextData::get(rootContext())->emitDestruction();
743 // clean up all singleton type instances which we own.
744 // we do this here and not in the private dtor since otherwise a crash can
745 // occur (if we are the QObject parent of the QObject singleton instance)
746 // XXX TODO: performance -- store list of singleton types separately?
747 QList<QQmlType*> singletonTypes = QQmlMetaType::qmlSingletonTypes();
748 foreach (QQmlType *currType, singletonTypes)
749 currType->singletonInstanceInfo()->destroy(this);
751 if (d->incubationController)
752 d->incubationController->d = 0;
755 /*! \fn void QQmlEngine::quit()
756 This signal is emitted when the QML loaded by the engine would like to quit.
759 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
760 This signal is emitted when \a warnings messages are generated by QML.
764 Clears the engine's internal component cache.
766 This function causes the property metadata of all components previously
767 loaded by the engine to be destroyed. All previously loaded components and
768 the property bindings for all extant objects created from those components will
771 This function returns the engine to a state where it does not contain any loaded
772 component data. This may be useful in order to reload a smaller subset of the
773 previous component set, or to load a new version of a previously loaded component.
775 Once the component cache has been cleared, components must be loaded before
776 any new objects can be created.
778 \sa trimComponentCache()
780 void QQmlEngine::clearComponentCache()
783 d->typeLoader.clearCache();
787 Trims the engine's internal component cache.
789 This function causes the property metadata of any loaded components which are
790 not currently in use to be destroyed.
792 A component is considered to be in use if there are any extant instances of
793 the component itself, any instances of other components that use the component,
794 or any objects instantiated by any of those components.
796 \sa clearComponentCache()
798 void QQmlEngine::trimComponentCache()
801 d->typeLoader.trimCache();
805 Returns the engine's root context.
807 The root context is automatically created by the QQmlEngine.
808 Data that should be available to all QML component instances
809 instantiated by the engine should be put in the root context.
811 Additional data that should only be available to a subset of
812 component instances should be added to sub-contexts parented to the
815 QQmlContext *QQmlEngine::rootContext() const
817 Q_D(const QQmlEngine);
818 return d->rootContext;
822 Sets the \a factory to use for creating QNetworkAccessManager(s).
824 QNetworkAccessManager is used for all network access by QML. By
825 implementing a factory it is possible to create custom
826 QNetworkAccessManager with specialized caching, proxy and cookie
829 The factory must be set before executing the engine.
831 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
834 QMutexLocker locker(&d->mutex);
835 d->networkAccessManagerFactory = factory;
839 Returns the current QQmlNetworkAccessManagerFactory.
841 \sa setNetworkAccessManagerFactory()
843 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
845 Q_D(const QQmlEngine);
846 return d->networkAccessManagerFactory;
849 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
852 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
854 void *args[] = { 0 };
855 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
859 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
861 QMutexLocker locker(&mutex);
862 QNetworkAccessManager *nam;
863 if (networkAccessManagerFactory) {
864 nam = networkAccessManagerFactory->create(parent);
866 nam = new QNetworkAccessManager(parent);
872 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
874 Q_Q(const QQmlEngine);
875 if (!networkAccessManager)
876 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
877 return networkAccessManager;
881 Returns a common QNetworkAccessManager which can be used by any QML
882 type instantiated by this engine.
884 If a QQmlNetworkAccessManagerFactory has been set and a
885 QNetworkAccessManager has not yet been created, the
886 QQmlNetworkAccessManagerFactory will be used to create the
887 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
888 will have no proxy or cache set.
890 \sa setNetworkAccessManagerFactory()
892 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
894 Q_D(const QQmlEngine);
895 return d->getNetworkAccessManager();
900 Sets the \a provider to use for images requested via the \e
901 image: url scheme, with host \a providerId. The QQmlEngine
902 takes ownership of \a provider.
904 Image providers enable support for pixmap and threaded image
905 requests. See the QQuickImageProvider documentation for details on
906 implementing and using image providers.
908 All required image providers should be added to the engine before any
909 QML sources files are loaded.
911 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
913 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
916 QMutexLocker locker(&d->mutex);
917 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
921 Returns the image provider set for \a providerId.
923 Returns the provider if it was found; otherwise returns 0.
925 \sa QQuickImageProvider
927 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
929 Q_D(const QQmlEngine);
930 QMutexLocker locker(&d->mutex);
931 return d->imageProviders.value(providerId).data();
935 Removes the image provider for \a providerId.
937 \sa addImageProvider(), QQuickImageProvider
939 void QQmlEngine::removeImageProvider(const QString &providerId)
942 QMutexLocker locker(&d->mutex);
943 d->imageProviders.take(providerId);
947 Return the base URL for this engine. The base URL is only used to
948 resolve components when a relative URL is passed to the
949 QQmlComponent constructor.
951 If a base URL has not been explicitly set, this method returns the
952 application's current working directory.
956 QUrl QQmlEngine::baseUrl() const
958 Q_D(const QQmlEngine);
959 if (d->baseUrl.isEmpty()) {
960 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
967 Set the base URL for this engine to \a url.
971 void QQmlEngine::setBaseUrl(const QUrl &url)
978 Returns true if warning messages will be output to stderr in addition
979 to being emitted by the warnings() signal, otherwise false.
981 The default value is true.
983 bool QQmlEngine::outputWarningsToStandardError() const
985 Q_D(const QQmlEngine);
986 return d->outputWarningsToStdErr;
990 Set whether warning messages will be output to stderr to \a enabled.
992 If \a enabled is true, any warning messages generated by QML will be
993 output to stderr and emitted by the warnings() signal. If \a enabled
994 is false, on the warnings() signal will be emitted. This allows
995 applications to handle warning output themselves.
997 The default value is true.
999 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
1002 d->outputWarningsToStdErr = enabled;
1006 Returns the QQmlContext for the \a object, or 0 if no
1007 context has been set.
1009 When the QQmlEngine instantiates a QObject, the context is
1012 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
1017 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
1020 static_cast<QQmlData *>(priv->declarativeData);
1024 else if (data->outerContext)
1025 return data->outerContext->asQQmlContext();
1031 Sets the QQmlContext for the \a object to \a context.
1032 If the \a object already has a context, a warning is
1033 output, but the context is not changed.
1035 When the QQmlEngine instantiates a QObject, the context is
1038 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1040 if (!object || !context)
1043 QQmlData *data = QQmlData::get(object, true);
1044 if (data->context) {
1045 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1049 QQmlContextData *contextData = QQmlContextData::get(context);
1050 contextData->addObject(object);
1054 \enum QQmlEngine::ObjectOwnership
1056 Ownership controls whether or not QML automatically destroys the
1057 QObject when the object is garbage collected by the JavaScript
1058 engine. The two ownership options are:
1060 \value CppOwnership The object is owned by C++ code, and will
1061 never be deleted by QML. The JavaScript destroy() method cannot be
1062 used on objects with CppOwnership. This option is similar to
1063 QScriptEngine::QtOwnership.
1065 \value JavaScriptOwnership The object is owned by JavaScript.
1066 When the object is returned to QML as the return value of a method
1067 call or property access, QML will track it, and delete the object
1068 if there are no remaining JavaScript references to it and it has no
1069 QObject::parent(). An object tracked by one QQmlEngine
1070 will be deleted during that QQmlEngine's destructor, and thus
1071 JavaScript references between objects with JavaScriptOwnership from
1072 two different engines will not be valid after the deletion of one of
1073 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1075 Generally an application doesn't need to set an object's ownership
1076 explicitly. QML uses a heuristic to set the default object
1077 ownership. By default, an object that is created by QML has
1078 JavaScriptOwnership. The exception to this are the root objects
1079 created by calling QQmlComponent::create() or
1080 QQmlComponent::beginCreate() which have CppOwnership by
1081 default. The ownership of these root-level objects is considered to
1082 have been transferred to the C++ caller.
1084 Objects not-created by QML have CppOwnership by default. The
1085 exception to this is objects returned from a C++ method call. The
1086 ownership of these objects is passed to JavaScript.
1088 Calling setObjectOwnership() overrides the default ownership
1089 heuristic used by QML.
1093 Sets the \a ownership of \a object.
1095 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1100 QQmlData *ddata = QQmlData::get(object, true);
1104 ddata->indestructible = (ownership == CppOwnership)?true:false;
1105 ddata->explicitIndestructibleSet = true;
1109 Returns the ownership of \a object.
1111 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1114 return CppOwnership;
1116 QQmlData *ddata = QQmlData::get(object, false);
1118 return CppOwnership;
1120 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1123 bool QQmlEngine::event(QEvent *e)
1126 if (e->type() == QEvent::User)
1127 d->doDeleteInEngineThread();
1129 return QJSEngine::event(e);
1132 void QQmlEnginePrivate::doDeleteInEngineThread()
1134 QFieldList<Deletable, &Deletable::next> list;
1136 list.copyAndClear(toDeleteInEngineThread);
1139 while (Deletable *d = list.takeFirst())
1143 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1145 QQmlData *data = QQmlData::get(object);
1147 if (data && data->compiledData && data->deferredIdx) {
1148 QQmlObjectCreatingProfiler prof;
1150 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1151 prof.setTypeName(type ? type->qmlTypeName()
1152 : QString::fromUtf8(object->metaObject()->className()));
1153 if (data->outerContext)
1154 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1156 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1158 QQmlComponentPrivate::ConstructionState state;
1159 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1161 // Release the reference for the deferral action (we still have one from construction)
1162 data->compiledData->release();
1163 data->compiledData = 0;
1165 QQmlComponentPrivate::complete(ep, &state);
1169 QQmlContext *qmlContext(const QObject *obj)
1171 return QQmlEngine::contextForObject(obj);
1174 QQmlEngine *qmlEngine(const QObject *obj)
1176 QQmlData *data = QQmlData::get(obj, false);
1177 if (!data || !data->context)
1179 return data->context->engine;
1182 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1184 QQmlData *data = QQmlData::get(object);
1186 return 0; // Attached properties are only on objects created by QML
1188 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1192 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1196 rv = pf(const_cast<QObject *>(object));
1199 data->attachedProperties()->insert(id, rv);
1204 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1205 const QMetaObject *attachedMetaObject, bool create)
1208 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1210 if (*idCache == -1 || !object)
1213 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1216 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1218 #ifndef QQML_NO_DEBUG_PROTOCOL
1219 if (!QQmlEnginePrivate::qml_debugging_enabled
1221 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1223 QQmlEnginePrivate::qml_debugging_enabled = true;
1228 class QQmlDataExtended {
1231 ~QQmlDataExtended();
1233 QHash<int, QObject *> attachedProperties;
1236 QQmlDataExtended::QQmlDataExtended()
1240 QQmlDataExtended::~QQmlDataExtended()
1244 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1247 layout(endpoint->next);
1249 int index = endpoint->sourceSignal;
1250 index = qMin(index, 0xFFFF - 1);
1252 endpoint->next = notifies[index];
1253 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1254 endpoint->prev = ¬ifies[index];
1255 notifies[index] = endpoint;
1258 void QQmlData::NotifyList::layout()
1260 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1263 QQmlNotifierEndpoint **old = notifies;
1264 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1265 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1266 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1267 sizeof(QQmlNotifierEndpoint*);
1268 memset(notifies + notifiesSize, 0, memsetSize);
1270 if (notifies != old) {
1271 for (int ii = 0; ii < notifiesSize; ++ii)
1273 notifies[ii]->prev = ¬ifies[ii];
1276 notifiesSize = maximumTodoIndex + 1;
1281 maximumTodoIndex = 0;
1285 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1288 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1289 notifyList->connectionMask = 0;
1290 notifyList->maximumTodoIndex = 0;
1291 notifyList->notifiesSize = 0;
1292 notifyList->todo = 0;
1293 notifyList->notifies = 0;
1296 Q_ASSERT(!endpoint->isConnected());
1298 index = qMin(index, 0xFFFF - 1);
1299 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1301 if (index < notifyList->notifiesSize) {
1303 endpoint->next = notifyList->notifies[index];
1304 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1305 endpoint->prev = ¬ifyList->notifies[index];
1306 notifyList->notifies[index] = endpoint;
1309 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1311 endpoint->next = notifyList->todo;
1312 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1313 endpoint->prev = ¬ifyList->todo;
1314 notifyList->todo = endpoint;
1319 index MUST in the range returned by QObjectPrivate::signalIndex()
1320 This is different than the index returned by QMetaMethod::methodIndex()
1322 bool QQmlData::signalHasEndpoint(int index)
1324 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1327 void QQmlData::disconnectNotifiers()
1330 while (notifyList->todo)
1331 notifyList->todo->disconnect();
1332 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1333 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1336 free(notifyList->notifies);
1342 QHash<int, QObject *> *QQmlData::attachedProperties() const
1344 if (!extendedData) extendedData = new QQmlDataExtended;
1345 return &extendedData->attachedProperties;
1348 void QQmlData::destroyed(QObject *object)
1350 if (nextContextObject)
1351 nextContextObject->prevContextObject = prevContextObject;
1352 if (prevContextObject)
1353 *prevContextObject = nextContextObject;
1355 QQmlAbstractBinding *binding = bindings;
1357 QQmlAbstractBinding *next = binding->nextBinding();
1358 binding->setAddedToObject(false);
1359 binding->setNextBinding(0);
1365 compiledData->release();
1369 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1370 while (signalHandler) {
1371 if (signalHandler->isEvaluating()) {
1372 // The object is being deleted during signal handler evaluation.
1373 // This will cause a crash due to invalid memory access when the
1374 // evaluation has completed.
1375 // Abort with a friendly message instead.
1376 QString locationString;
1377 QQmlBoundSignalExpression *expr = signalHandler->expression();
1379 QString fileName = expr->sourceFile();
1380 if (fileName.isEmpty())
1381 fileName = QStringLiteral("<Unknown File>");
1382 locationString.append(fileName);
1383 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1384 QString source = expr->expression();
1385 if (source.size() > 100) {
1386 source.truncate(96);
1387 source.append(QStringLiteral(" ..."));
1389 locationString.append(source);
1391 locationString = QStringLiteral("<Unknown Location>");
1393 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1394 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1395 "instead), or the application is running a nested event loop.\n"
1396 "This behavior is NOT supported!\n"
1397 "%s", object, qPrintable(locationString));
1400 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1401 signalHandler->m_prevSignal = 0;
1402 signalHandler->m_nextSignal = 0;
1403 delete signalHandler;
1404 signalHandler = next;
1411 propertyCache->release();
1413 if (ownContext && context)
1417 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1418 *guard = (QObject *)0;
1419 guard->objectDestroyed(object);
1422 disconnectNotifiers();
1425 delete extendedData;
1427 // Dispose the handle.
1428 // We don't simply clear it (and wait for next gc cycle to dispose
1429 // via the weak qobject reference callback) as this affects the
1430 // outcomes of v8's gc statistical analysis heuristics, which can
1431 // cause unnecessary growth of the old pointer space js heap area.
1432 qPersistentDispose(v8object);
1438 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1440 void QQmlData::parentChanged(QObject *object, QObject *parent)
1443 if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1447 { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1448 { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1450 qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1451 "User code is attempting to change it to %s.\n"
1452 "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1457 bool QQmlData::hasBindingBit(int bit) const
1459 if (bindingBitsSize > bit)
1460 return bindingBits[bit / 32] & (1 << (bit % 32));
1465 void QQmlData::clearBindingBit(int bit)
1467 if (bindingBitsSize > bit)
1468 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1471 void QQmlData::setBindingBit(QObject *obj, int bit)
1473 if (bindingBitsSize <= bit) {
1474 int props = QQmlMetaObject(obj).propertyCount();
1475 Q_ASSERT(bit < props);
1477 int arraySize = (props + 31) / 32;
1478 int oldArraySize = bindingBitsSize / 32;
1480 bindingBits = (quint32 *)realloc(bindingBits,
1481 arraySize * sizeof(quint32));
1483 memset(bindingBits + oldArraySize,
1485 sizeof(quint32) * (arraySize - oldArraySize));
1487 bindingBitsSize = arraySize * 32;
1490 bindingBits[bit / 32] |= (1 << (bit % 32));
1493 void QQmlEnginePrivate::sendQuit()
1497 if (q->receivers(SIGNAL(quit())) == 0) {
1498 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1502 static void dumpwarning(const QQmlError &error)
1504 QMessageLogger(error.url().toString().toLatin1().constData(),
1505 error.line(), 0).warning().nospace()
1506 << qPrintable(error.toString());
1509 static void dumpwarning(const QList<QQmlError> &errors)
1511 for (int ii = 0; ii < errors.count(); ++ii)
1512 dumpwarning(errors.at(ii));
1515 void QQmlEnginePrivate::warning(const QQmlError &error)
1518 q->warnings(QList<QQmlError>() << error);
1519 if (outputWarningsToStdErr)
1523 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1526 q->warnings(errors);
1527 if (outputWarningsToStdErr)
1528 dumpwarning(errors);
1531 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1534 warning(error->error(q));
1537 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1540 QQmlEnginePrivate::get(engine)->warning(error);
1545 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1548 QQmlEnginePrivate::get(engine)->warning(error);
1553 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1556 QQmlEnginePrivate::get(engine)->warning(error);
1558 dumpwarning(error->error(0));
1561 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1564 engine->warning(error);
1569 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1572 engine->warning(error);
1578 This function should be called prior to evaluation of any js expression,
1579 so that scarce resources are not freed prematurely (eg, if there is a
1580 nested javascript expression).
1582 void QQmlEnginePrivate::referenceScarceResources()
1584 scarceResourcesRefCount += 1;
1588 This function should be called after evaluation of the js expression is
1589 complete, and so the scarce resources may be freed safely.
1591 void QQmlEnginePrivate::dereferenceScarceResources()
1593 Q_ASSERT(scarceResourcesRefCount > 0);
1594 scarceResourcesRefCount -= 1;
1596 // if the refcount is zero, then evaluation of the "top level"
1597 // expression must have completed. We can safely release the
1598 // scarce resources.
1599 if (scarceResourcesRefCount == 0) {
1600 // iterate through the list and release them all.
1601 // note that the actual SRD is owned by the JS engine,
1602 // so we cannot delete the SRD; but we can free the
1603 // memory used by the variant in the SRD.
1604 while (ScarceResourceData *sr = scarceResources.first()) {
1605 sr->data = QVariant();
1606 scarceResources.remove(sr);
1612 Adds \a path as a directory where the engine searches for
1613 installed modules in a URL-based directory structure.
1615 The \a path may be a local filesystem directory, a
1616 \l {The Qt Resource System}{Qt Resource} path (\c {:/imports}), a
1617 \l {The Qt Resource System}{Qt Resource} url (\c {qrc:/imports}) or a URL.
1619 The \a path will be converted into canonical form before it
1620 is added to the import path list.
1622 The newly added \a path will be first in the importPathList().
1624 \sa setImportPathList(), {QML Modules}
1626 void QQmlEngine::addImportPath(const QString& path)
1629 d->importDatabase.addImportPath(path);
1633 Returns the list of directories where the engine searches for
1634 installed modules in a URL-based directory structure.
1636 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1637 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1638 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1639 provided by that module. A \c qmldir file is required for defining the
1640 type version mapping and possibly QML extensions plugins.
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 addImportPath(), setImportPathList()
1648 QStringList QQmlEngine::importPathList() const
1650 Q_D(const QQmlEngine);
1651 return d->importDatabase.importPathList();
1655 Sets \a paths as the list of directories where the engine searches for
1656 installed modules in a URL-based directory structure.
1658 By default, the list contains the directory of the application executable,
1659 paths specified in the \c QML_IMPORT_PATH environment variable,
1660 and the builtin \c ImportsPath from QLibraryInfo.
1662 \sa importPathList(), addImportPath()
1664 void QQmlEngine::setImportPathList(const QStringList &paths)
1667 d->importDatabase.setImportPathList(paths);
1672 Adds \a path as a directory where the engine searches for
1673 native plugins for imported modules (referenced in the \c qmldir file).
1675 By default, the list contains only \c ., i.e. the engine searches
1676 in the directory of the \c qmldir file itself.
1678 The newly added \a path will be first in the pluginPathList().
1680 \sa setPluginPathList()
1682 void QQmlEngine::addPluginPath(const QString& path)
1685 d->importDatabase.addPluginPath(path);
1690 Returns the list of directories where the engine searches for
1691 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 addPluginPath(), setPluginPathList()
1698 QStringList QQmlEngine::pluginPathList() const
1700 Q_D(const QQmlEngine);
1701 return d->importDatabase.pluginPathList();
1705 Sets the list of directories where the engine searches for
1706 native plugins for imported modules (referenced in the \c qmldir file)
1709 By default, the list contains only \c ., i.e. the engine searches
1710 in the directory of the \c qmldir file itself.
1712 \sa pluginPathList(), addPluginPath()
1714 void QQmlEngine::setPluginPathList(const QStringList &paths)
1717 d->importDatabase.setPluginPathList(paths);
1721 Imports the plugin named \a filePath with the \a uri provided.
1722 Returns true if the plugin was successfully imported; otherwise returns false.
1724 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1726 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1728 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1731 return d->importDatabase.importPlugin(filePath, uri, QString(), errors);
1735 \property QQmlEngine::offlineStoragePath
1736 \brief the directory for storing offline user data
1738 Returns the directory where SQL and other offline
1741 QQuickWebView and the SQL databases created with openDatabase()
1744 The default is QML/OfflineStorage in the platform-standard
1745 user application data directory.
1747 Note that the path may not currently exist on the filesystem, so
1748 callers wanting to \e create new files at this location should create
1749 it first - see QDir::mkpath().
1751 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1754 d->offlineStoragePath = dir;
1757 QString QQmlEngine::offlineStoragePath() const
1759 Q_D(const QQmlEngine);
1760 return d->offlineStoragePath;
1763 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1767 if (!mo->superClass()) {
1768 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1769 propertyCache.insert(mo, rv);
1772 QQmlPropertyCache *super = cache(mo->superClass());
1773 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1774 propertyCache.insert(mo, rv);
1779 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1782 QList<QQmlType *> types;
1784 int maxMinorVersion = 0;
1786 const QMetaObject *metaObject = type->metaObject();
1788 while (metaObject) {
1789 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1790 type->majorVersion(), minorVersion);
1792 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1798 metaObject = metaObject->superClass();
1801 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1803 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1807 QQmlPropertyCache *raw = cache(type->metaObject());
1809 bool hasCopied = false;
1811 for (int ii = 0; ii < types.count(); ++ii) {
1812 QQmlType *currentType = types.at(ii);
1816 int rev = currentType->metaObjectRevision();
1817 int moIndex = types.count() - 1 - ii;
1819 if (raw->allowedRevisionCache[moIndex] != rev) {
1824 raw->allowedRevisionCache[moIndex] = rev;
1828 // Test revision compatibility - the basic rule is:
1829 // * Anything that is excluded, cannot overload something that is not excluded *
1831 // Signals override:
1832 // * other signals and methods of the same name.
1833 // * properties named on<Signal Name>
1834 // * automatic <property name>Changed notify signals
1836 // Methods override:
1837 // * other methods of the same name
1839 // Properties override:
1840 // * other elements of the same name
1842 bool overloadError = false;
1843 QString overloadName;
1846 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1847 !overloadError && iter != raw->stringCache.end();
1850 QQmlPropertyData *d = *iter;
1851 if (raw->isAllowedInRevision(d))
1852 continue; // Not excluded - no problems
1854 // check that a regular "name" overload isn't happening
1855 QQmlPropertyData *current = d;
1856 while (!overloadError && current) {
1857 current = d->overrideData(current);
1858 if (current && raw->isAllowedInRevision(current))
1859 overloadError = true;
1864 if (overloadError) {
1865 if (hasCopied) raw->release();
1867 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."));
1871 if (!hasCopied) raw->addref();
1872 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1874 if (minorVersion != maxMinorVersion) {
1876 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
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).