1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
72 #include <private/qqmlboundsignal_p.h>
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtCore/qthread.h>
84 #include <private/qthread_p.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
87 #include <private/qobject_p.h>
88 #include <private/qmetaobject_p.h>
90 #include <private/qqmllocale_p.h>
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
97 #define CSIDL_APPDATA 0x001a // <username>\Application Data
100 Q_DECLARE_METATYPE(QQmlProperty)
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
106 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107 QQmlEnginePrivate::registerQtQuick2Types(uri, versionMajor, versionMinor);
108 QQmlValueTypeFactory::registerValueTypes(uri, versionMajor, versionMinor);
113 \instantiates QObject
114 \inqmlmodule QtQuick 2
115 \ingroup qml-utility-elements
117 \brief A basic QML type
119 The QtObject type is a non-visual element which contains only the
122 It can be useful to create a QtObject if you need an extremely
123 lightweight type to enclose a set of custom properties:
125 \snippet qml/qtobject.qml 0
127 It can also be useful for C++ integration, as it is just a plain
128 QObject. See the QObject documentation for further details.
131 \qmlproperty string QtObject::objectName
132 This property holds the QObject::objectName for this specific object instance.
134 This allows a C++ application to locate an item within a QML component
135 using the QObject::findChild() method. For example, the following C++
136 application locates the child \l Rectangle item and dynamically changes its
145 width: 200; height: 200
159 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
162 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
164 item->setProperty("color", QColor(Qt::yellow));
168 bool QQmlEnginePrivate::qml_debugging_enabled = false;
170 // these types are part of the QML language
171 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
173 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
174 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
178 // These QtQuick types' implementation resides in the QtQml module
179 void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
181 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor, "ListElement");
182 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor, "ListModel", new QQuickListModelParser);
183 qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
186 void QQmlEnginePrivate::defineQtQuick2Module()
188 // register the base types into the QtQuick namespace
189 registerBaseTypes("QtQuick",2,0);
191 // register the QtQuick2 types which are implemented in the QtQml module.
192 registerQtQuick2Types("QtQuick",2,0);
193 qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
198 \class QQmlImageProviderBase
199 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
203 Image providers must be registered with the QML engine. The only information the QML
204 engine knows about image providers is the type of image data they provide. To use an
205 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
206 to a QQuickImageProvider pointer.
208 \sa QQuickImageProvider, QQuickTextureFactory
212 \enum QQmlImageProviderBase::ImageType
214 Defines the type of image supported by this image provider.
216 \value Image The Image Provider provides QImage images.
217 The QQuickImageProvider::requestImage() method will be called for all image requests.
218 \value Pixmap The Image Provider provides QPixmap images.
219 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
220 \value Texture The Image Provider provides QSGTextureProvider based images.
221 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
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<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
467 delete (*iter)->qobjectApi;
470 for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
471 iter.value()->isRegisteredWithEngine = false;
474 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
476 QObjectPrivate *p = QObjectPrivate::get(o);
477 if (p->declarativeData) {
478 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
479 if (d->ownContext && d->context) {
480 d->context->destroy();
484 // Mark this object as in the process of deletion to
485 // prevent it resolving in bindings
486 QQmlData::markAsDeleted(o);
490 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
492 static_cast<QQmlData *>(d)->destroyed(o);
495 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
497 static_cast<QQmlData *>(d)->parentChanged(o, p);
500 class QQmlThreadNotifierProxyObject : public QObject
503 QPointer<QObject> target;
505 virtual int qt_metacall(QMetaObject::Call, int methodIndex, void **a) {
509 QMetaMethod method = target->metaObject()->method(methodIndex);
510 Q_ASSERT(method.methodType() == QMetaMethod::Signal);
511 int signalIndex = QMetaObjectPrivate::signalIndex(method);
512 QQmlData *ddata = QQmlData::get(target, false);
513 QQmlNotifierEndpoint *ep = ddata->notify(signalIndex);
514 if (ep) QQmlNotifier::emitNotify(ep, a);
522 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
524 QQmlData *ddata = QQmlData::get(object, false);
525 if (!ddata) return; // Probably being deleted
527 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
528 // that they're exposed to. However, to make writing "worker objects" that calculate data
529 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
530 // QQmlEngine to emit signals from a different thread. These signals are then automatically
531 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
532 // by the qqmlecmascript::threadSignal() autotest.
533 if (ddata->notifyList &&
534 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
536 if (!QObjectPrivate::get(object)->threadData->thread)
539 QMetaMethod m = QMetaObjectPrivate::signal(object->metaObject(), index);
540 QList<QByteArray> parameterTypes = m.parameterTypes();
542 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
543 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
545 types[0] = 0; // return type
546 args[0] = 0; // return value
548 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
549 const QByteArray &typeName = parameterTypes.at(ii);
550 if (typeName.endsWith('*'))
551 types[ii + 1] = QMetaType::VoidStar;
553 types[ii + 1] = QMetaType::type(typeName);
555 if (!types[ii + 1]) {
556 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
557 "(Make sure '%s' is registered using qRegisterMetaType().)",
558 typeName.constData(), typeName.constData());
564 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
567 QMetaCallEvent *ev = new QMetaCallEvent(m.methodIndex(), 0, 0, object, index,
568 parameterTypes.count() + 1, types, args);
570 QQmlThreadNotifierProxyObject *mpo = new QQmlThreadNotifierProxyObject;
571 mpo->target = object;
572 mpo->moveToThread(QObjectPrivate::get(object)->threadData->thread);
573 QCoreApplication::postEvent(mpo, ev);
576 QQmlNotifierEndpoint *ep = ddata->notify(index);
577 if (ep) QQmlNotifier::emitNotify(ep, a);
581 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
583 return static_cast<QQmlData *>(d)->endpointCount(index);
586 bool QQmlData::isSignalConnected(QAbstractDeclarativeData *d, const QObject *, int index)
588 return static_cast<QQmlData *>(d)->signalHasEndpoint(index);
591 int QQmlData::endpointCount(int index)
594 QQmlNotifierEndpoint *ep = notify(index);
605 void QQmlData::markAsDeleted(QObject *o)
607 QQmlData::setQueuedForDeletion(o);
609 QObjectPrivate *p = QObjectPrivate::get(o);
610 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
611 QQmlData::markAsDeleted(*it);
615 void QQmlData::setQueuedForDeletion(QObject *object)
618 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
619 if (!priv->wasDeleted && priv->declarativeData) {
620 QQmlData *ddata = QQmlData::get(object, false);
621 if (ddata->ownContext && ddata->context)
622 ddata->context->emitDestruction();
623 ddata->isQueuedForDeletion = true;
629 void QQmlEnginePrivate::init()
633 static bool firstTime = true;
635 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
636 registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
642 qRegisterMetaType<QVariant>("QVariant");
643 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
644 qRegisterMetaType<QJSValue>("QJSValue");
645 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
646 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
647 qRegisterMetaType<QList<int> >("QList<int>");
648 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
650 v8engine()->setEngine(q);
652 rootContext = new QQmlContext(q,true);
654 if (QCoreApplication::instance()->thread() == q->thread() &&
655 QQmlEngineDebugService::isDebuggingEnabled()) {
657 QQmlEngineDebugService::instance()->addEngine(q);
658 QV8DebugService::initialize(v8engine());
659 QV8ProfilerService::initialize();
660 QQmlProfilerService::initialize();
661 QDebugMessageService::instance();
664 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
665 if (!dataLocation.isEmpty())
666 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
667 + QDir::separator() + QLatin1String("QML")
668 + QDir::separator() + QLatin1String("OfflineStorage");
671 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
674 if (!workerScriptEngine)
675 workerScriptEngine = new QQuickWorkerScriptEngine(q);
676 return workerScriptEngine;
683 \brief The QQmlEngine class provides an environment for instantiating QML components.
686 Each QML component is instantiated in a QQmlContext.
687 QQmlContext's are essential for passing data to QML
688 components. In QML, contexts are arranged hierarchically and this
689 hierarchy is managed by the QQmlEngine.
691 Prior to creating any QML components, an application must have
692 created a QQmlEngine to gain access to a QML context. The
693 following example shows how to create a simple Text item.
697 QQmlComponent component(&engine);
698 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
699 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
701 //add item to view, etc
705 In this case, the Text item will be created in the engine's
706 \l {QQmlEngine::rootContext()}{root context}.
708 Note that the QtQuick 1 version is called QDeclarativeEngine.
710 \sa QQmlComponent, QQmlContext
714 Create a new QQmlEngine with the given \a parent.
716 QQmlEngine::QQmlEngine(QObject *parent)
717 : QJSEngine(*new QQmlEnginePrivate(this), parent)
724 Destroys the QQmlEngine.
726 Any QQmlContext's created on this engine will be
727 invalidated, but not destroyed (unless they are parented to the
730 QQmlEngine::~QQmlEngine()
733 if (d->isDebugging) {
734 QQmlEngineDebugService::instance()->remEngine(this);
737 // Emit onDestruction signals for the root context before
738 // we destroy the contexts, engine, Module APIs etc. that
739 // may be required to handle the destruction signal.
740 QQmlContextData::get(rootContext())->emitDestruction();
742 // if we are the parent of any of the qobject module api instances,
743 // we need to remove them from our internal list, in order to prevent
744 // a segfault in engine private dtor.
745 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
746 QObject *currQObjectApi = 0;
747 QQmlMetaType::ModuleApiInstance *currInstance = 0;
748 foreach (const QQmlMetaType::ModuleApi &key, keys) {
749 currInstance = d->moduleApiInstances.value(key);
750 currQObjectApi = currInstance->qobjectApi;
751 if (this->children().contains(currQObjectApi)) {
752 delete currQObjectApi;
754 d->moduleApiInstances.remove(key);
758 if (d->incubationController)
759 d->incubationController->d = 0;
762 /*! \fn void QQmlEngine::quit()
763 This signal is emitted when the QML loaded by the engine would like to quit.
766 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
767 This signal is emitted when \a warnings messages are generated by QML.
771 Clears the engine's internal component cache.
773 This function causes the property metadata of all components previously
774 loaded by the engine to be destroyed. All previously loaded components and
775 the property bindings for all extant objects created from those components will
778 This function returns the engine to a state where it does not contain any loaded
779 component data. This may be useful in order to reload a smaller subset of the
780 previous component set, or to load a new version of a previously loaded component.
782 Once the component cache has been cleared, components must be loaded before
783 any new objects can be created.
785 \sa trimComponentCache()
787 void QQmlEngine::clearComponentCache()
790 d->typeLoader.clearCache();
794 Trims the engine's internal component cache.
796 This function causes the property metadata of any loaded components which are
797 not currently in use to be destroyed.
799 A component is considered to be in use if there are any extant instances of
800 the component itself, any instances of other components that use the component,
801 or any objects instantiated by any of those components.
803 \sa clearComponentCache()
805 void QQmlEngine::trimComponentCache()
808 d->typeLoader.trimCache();
812 Returns the engine's root context.
814 The root context is automatically created by the QQmlEngine.
815 Data that should be available to all QML component instances
816 instantiated by the engine should be put in the root context.
818 Additional data that should only be available to a subset of
819 component instances should be added to sub-contexts parented to the
822 QQmlContext *QQmlEngine::rootContext() const
824 Q_D(const QQmlEngine);
825 return d->rootContext;
829 Sets the \a factory to use for creating QNetworkAccessManager(s).
831 QNetworkAccessManager is used for all network access by QML. By
832 implementing a factory it is possible to create custom
833 QNetworkAccessManager with specialized caching, proxy and cookie
836 The factory must be set before executing the engine.
838 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
841 QMutexLocker locker(&d->mutex);
842 d->networkAccessManagerFactory = factory;
846 Returns the current QQmlNetworkAccessManagerFactory.
848 \sa setNetworkAccessManagerFactory()
850 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
852 Q_D(const QQmlEngine);
853 return d->networkAccessManagerFactory;
856 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
859 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
861 void *args[] = { 0 };
862 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
866 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
868 QMutexLocker locker(&mutex);
869 QNetworkAccessManager *nam;
870 if (networkAccessManagerFactory) {
871 nam = networkAccessManagerFactory->create(parent);
873 nam = new QNetworkAccessManager(parent);
879 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
881 Q_Q(const QQmlEngine);
882 if (!networkAccessManager)
883 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
884 return networkAccessManager;
888 Returns a common QNetworkAccessManager which can be used by any QML
889 type instantiated by this engine.
891 If a QQmlNetworkAccessManagerFactory has been set and a
892 QNetworkAccessManager has not yet been created, the
893 QQmlNetworkAccessManagerFactory will be used to create the
894 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
895 will have no proxy or cache set.
897 \sa setNetworkAccessManagerFactory()
899 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
901 Q_D(const QQmlEngine);
902 return d->getNetworkAccessManager();
907 Sets the \a provider to use for images requested via the \e
908 image: url scheme, with host \a providerId. The QQmlEngine
909 takes ownership of \a provider.
911 Image providers enable support for pixmap and threaded image
912 requests. See the QQuickImageProvider documentation for details on
913 implementing and using image providers.
915 All required image providers should be added to the engine before any
916 QML sources files are loaded.
918 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
920 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
923 QMutexLocker locker(&d->mutex);
924 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
928 Returns the image provider set for \a providerId.
930 Returns the provider if it was found; otherwise returns 0.
932 \sa QQuickImageProvider
934 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
936 Q_D(const QQmlEngine);
937 QMutexLocker locker(&d->mutex);
938 return d->imageProviders.value(providerId).data();
942 Removes the image provider for \a providerId.
944 \sa addImageProvider(), QQuickImageProvider
946 void QQmlEngine::removeImageProvider(const QString &providerId)
949 QMutexLocker locker(&d->mutex);
950 d->imageProviders.take(providerId);
954 Return the base URL for this engine. The base URL is only used to
955 resolve components when a relative URL is passed to the
956 QQmlComponent constructor.
958 If a base URL has not been explicitly set, this method returns the
959 application's current working directory.
963 QUrl QQmlEngine::baseUrl() const
965 Q_D(const QQmlEngine);
966 if (d->baseUrl.isEmpty()) {
967 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
974 Set the base URL for this engine to \a url.
978 void QQmlEngine::setBaseUrl(const QUrl &url)
985 Returns true if warning messages will be output to stderr in addition
986 to being emitted by the warnings() signal, otherwise false.
988 The default value is true.
990 bool QQmlEngine::outputWarningsToStandardError() const
992 Q_D(const QQmlEngine);
993 return d->outputWarningsToStdErr;
997 Set whether warning messages will be output to stderr to \a enabled.
999 If \a enabled is true, any warning messages generated by QML will be
1000 output to stderr and emitted by the warnings() signal. If \a enabled
1001 is false, on the warnings() signal will be emitted. This allows
1002 applications to handle warning output themselves.
1004 The default value is true.
1006 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
1009 d->outputWarningsToStdErr = enabled;
1013 Returns the QQmlContext for the \a object, or 0 if no
1014 context has been set.
1016 When the QQmlEngine instantiates a QObject, the context is
1019 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
1024 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
1027 static_cast<QQmlData *>(priv->declarativeData);
1031 else if (data->outerContext)
1032 return data->outerContext->asQQmlContext();
1038 Sets the QQmlContext for the \a object to \a context.
1039 If the \a object already has a context, a warning is
1040 output, but the context is not changed.
1042 When the QQmlEngine instantiates a QObject, the context is
1045 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1047 if (!object || !context)
1050 QQmlData *data = QQmlData::get(object, true);
1051 if (data->context) {
1052 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1056 QQmlContextData *contextData = QQmlContextData::get(context);
1057 contextData->addObject(object);
1061 \enum QQmlEngine::ObjectOwnership
1063 Ownership controls whether or not QML automatically destroys the
1064 QObject when the object is garbage collected by the JavaScript
1065 engine. The two ownership options are:
1067 \value CppOwnership The object is owned by C++ code, and will
1068 never be deleted by QML. The JavaScript destroy() method cannot be
1069 used on objects with CppOwnership. This option is similar to
1070 QScriptEngine::QtOwnership.
1072 \value JavaScriptOwnership The object is owned by JavaScript.
1073 When the object is returned to QML as the return value of a method
1074 call or property access, QML will track it, and delete the object
1075 if there are no remaining JavaScript references to it and it has no
1076 QObject::parent(). An object tracked by one QQmlEngine
1077 will be deleted during that QQmlEngine's destructor, and thus
1078 JavaScript references between objects with JavaScriptOwnership from
1079 two different engines will not be valid after the deletion of one of
1080 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1082 Generally an application doesn't need to set an object's ownership
1083 explicitly. QML uses a heuristic to set the default object
1084 ownership. By default, an object that is created by QML has
1085 JavaScriptOwnership. The exception to this are the root objects
1086 created by calling QQmlComponent::create() or
1087 QQmlComponent::beginCreate() which have CppOwnership by
1088 default. The ownership of these root-level objects is considered to
1089 have been transferred to the C++ caller.
1091 Objects not-created by QML have CppOwnership by default. The
1092 exception to this is objects returned from a C++ method call. The
1093 ownership of these objects is passed to JavaScript.
1095 Calling setObjectOwnership() overrides the default ownership
1096 heuristic used by QML.
1100 Sets the \a ownership of \a object.
1102 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1107 QQmlData *ddata = QQmlData::get(object, true);
1111 ddata->indestructible = (ownership == CppOwnership)?true:false;
1112 ddata->explicitIndestructibleSet = true;
1116 Returns the ownership of \a object.
1118 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1121 return CppOwnership;
1123 QQmlData *ddata = QQmlData::get(object, false);
1125 return CppOwnership;
1127 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1130 bool QQmlEngine::event(QEvent *e)
1133 if (e->type() == QEvent::User)
1134 d->doDeleteInEngineThread();
1136 return QJSEngine::event(e);
1139 void QQmlEnginePrivate::doDeleteInEngineThread()
1141 QFieldList<Deletable, &Deletable::next> list;
1143 list.copyAndClear(toDeleteInEngineThread);
1146 while (Deletable *d = list.takeFirst())
1150 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1152 QQmlData *data = QQmlData::get(object);
1154 if (data && data->compiledData && data->deferredIdx) {
1155 QQmlObjectCreatingProfiler prof;
1157 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1158 prof.setTypeName(type ? type->qmlTypeName()
1159 : QString::fromUtf8(object->metaObject()->className()));
1160 if (data->outerContext)
1161 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1163 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1165 QQmlComponentPrivate::ConstructionState state;
1166 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1168 // Release the reference for the deferral action (we still have one from construction)
1169 data->compiledData->release();
1170 data->compiledData = 0;
1172 QQmlComponentPrivate::complete(ep, &state);
1176 QQmlContext *qmlContext(const QObject *obj)
1178 return QQmlEngine::contextForObject(obj);
1181 QQmlEngine *qmlEngine(const QObject *obj)
1183 QQmlData *data = QQmlData::get(obj, false);
1184 if (!data || !data->context)
1186 return data->context->engine;
1189 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1191 QQmlData *data = QQmlData::get(object);
1193 return 0; // Attached properties are only on objects created by QML
1195 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1199 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1203 rv = pf(const_cast<QObject *>(object));
1206 data->attachedProperties()->insert(id, rv);
1211 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1212 const QMetaObject *attachedMetaObject, bool create)
1215 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1217 if (*idCache == -1 || !object)
1220 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1223 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1225 #ifndef QQML_NO_DEBUG_PROTOCOL
1226 if (!QQmlEnginePrivate::qml_debugging_enabled
1228 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1230 QQmlEnginePrivate::qml_debugging_enabled = true;
1235 class QQmlDataExtended {
1238 ~QQmlDataExtended();
1240 QHash<int, QObject *> attachedProperties;
1243 QQmlDataExtended::QQmlDataExtended()
1247 QQmlDataExtended::~QQmlDataExtended()
1251 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1254 layout(endpoint->next);
1256 int index = endpoint->sourceSignal;
1257 index = qMin(index, 0xFFFF - 1);
1259 endpoint->next = notifies[index];
1260 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1261 endpoint->prev = ¬ifies[index];
1262 notifies[index] = endpoint;
1265 void QQmlData::NotifyList::layout()
1267 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1270 QQmlNotifierEndpoint **old = notifies;
1271 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1272 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1273 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1274 sizeof(QQmlNotifierEndpoint*);
1275 memset(notifies + notifiesSize, 0, memsetSize);
1277 if (notifies != old) {
1278 for (int ii = 0; ii < notifiesSize; ++ii)
1280 notifies[ii]->prev = ¬ifies[ii];
1283 notifiesSize = maximumTodoIndex + 1;
1288 maximumTodoIndex = 0;
1292 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1295 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1296 notifyList->connectionMask = 0;
1297 notifyList->maximumTodoIndex = 0;
1298 notifyList->notifiesSize = 0;
1299 notifyList->todo = 0;
1300 notifyList->notifies = 0;
1303 Q_ASSERT(!endpoint->isConnected());
1305 index = qMin(index, 0xFFFF - 1);
1306 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1308 if (index < notifyList->notifiesSize) {
1310 endpoint->next = notifyList->notifies[index];
1311 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1312 endpoint->prev = ¬ifyList->notifies[index];
1313 notifyList->notifies[index] = endpoint;
1316 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1318 endpoint->next = notifyList->todo;
1319 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1320 endpoint->prev = ¬ifyList->todo;
1321 notifyList->todo = endpoint;
1326 index MUST in the range returned by QObjectPrivate::signalIndex()
1327 This is different than the index returned by QMetaMethod::methodIndex()
1329 bool QQmlData::signalHasEndpoint(int index)
1331 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1334 QHash<int, QObject *> *QQmlData::attachedProperties() const
1336 if (!extendedData) extendedData = new QQmlDataExtended;
1337 return &extendedData->attachedProperties;
1340 void QQmlData::destroyed(QObject *object)
1342 if (nextContextObject)
1343 nextContextObject->prevContextObject = prevContextObject;
1344 if (prevContextObject)
1345 *prevContextObject = nextContextObject;
1347 QQmlAbstractBinding *binding = bindings;
1349 QQmlAbstractBinding *next = binding->nextBinding();
1350 binding->setAddedToObject(false);
1351 binding->setNextBinding(0);
1357 compiledData->release();
1361 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1362 while (signalHandler) {
1363 if (signalHandler->isEvaluating()) {
1364 // The object is being deleted during signal handler evaluation.
1365 // This will cause a crash due to invalid memory access when the
1366 // evaluation has completed.
1367 // Abort with a friendly message instead.
1368 QString locationString;
1369 QQmlBoundSignalExpression *expr = signalHandler->expression();
1371 QString fileName = expr->sourceFile();
1372 if (fileName.isEmpty())
1373 fileName = QStringLiteral("<Unknown File>");
1374 locationString.append(fileName);
1375 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1376 QString source = expr->expression();
1377 if (source.size() > 100) {
1378 source.truncate(96);
1379 source.append(QStringLiteral(" ..."));
1381 locationString.append(source);
1383 locationString = QStringLiteral("<Unknown Location>");
1385 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1386 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1387 "instead), or the application is running a nested event loop.\n"
1388 "This behavior is NOT supported!\n"
1389 "%s", object, qPrintable(locationString));
1392 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1393 signalHandler->m_prevSignal = 0;
1394 signalHandler->m_nextSignal = 0;
1395 delete signalHandler;
1396 signalHandler = next;
1403 propertyCache->release();
1405 if (ownContext && context)
1409 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1410 *guard = (QObject *)0;
1411 guard->objectDestroyed(object);
1415 while (notifyList->todo)
1416 notifyList->todo->disconnect();
1417 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1418 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1421 free(notifyList->notifies);
1427 delete extendedData;
1429 // Dispose the handle.
1430 // We don't simply clear it (and wait for next gc cycle to dispose
1431 // via the weak qobject reference callback) as this affects the
1432 // outcomes of v8's gc statistical analysis heuristics, which can
1433 // cause unnecessary growth of the old pointer space js heap area.
1434 qPersistentDispose(v8object);
1440 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1442 void QQmlData::parentChanged(QObject *object, QObject *parent)
1445 if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1449 { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1450 { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1452 qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1453 "User code is attempting to change it to %s.\n"
1454 "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1459 bool QQmlData::hasBindingBit(int bit) const
1461 if (bindingBitsSize > bit)
1462 return bindingBits[bit / 32] & (1 << (bit % 32));
1467 void QQmlData::clearBindingBit(int bit)
1469 if (bindingBitsSize > bit)
1470 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1473 void QQmlData::setBindingBit(QObject *obj, int bit)
1475 if (bindingBitsSize <= bit) {
1476 int props = QQmlMetaObject(obj).propertyCount();
1477 Q_ASSERT(bit < props);
1479 int arraySize = (props + 31) / 32;
1480 int oldArraySize = bindingBitsSize / 32;
1482 bindingBits = (quint32 *)realloc(bindingBits,
1483 arraySize * sizeof(quint32));
1485 memset(bindingBits + oldArraySize,
1487 sizeof(quint32) * (arraySize - oldArraySize));
1489 bindingBitsSize = arraySize * 32;
1492 bindingBits[bit / 32] |= (1 << (bit % 32));
1495 void QQmlEnginePrivate::sendQuit()
1499 if (q->receivers(SIGNAL(quit())) == 0) {
1500 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1504 static void dumpwarning(const QQmlError &error)
1506 QMessageLogger(error.url().toString().toLatin1().constData(),
1507 error.line(), 0).warning().nospace()
1508 << qPrintable(error.toString());
1511 static void dumpwarning(const QList<QQmlError> &errors)
1513 for (int ii = 0; ii < errors.count(); ++ii)
1514 dumpwarning(errors.at(ii));
1517 void QQmlEnginePrivate::warning(const QQmlError &error)
1520 q->warnings(QList<QQmlError>() << error);
1521 if (outputWarningsToStdErr)
1525 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1528 q->warnings(errors);
1529 if (outputWarningsToStdErr)
1530 dumpwarning(errors);
1533 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1536 warning(error->error(q));
1539 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1542 QQmlEnginePrivate::get(engine)->warning(error);
1547 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1550 QQmlEnginePrivate::get(engine)->warning(error);
1555 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1558 QQmlEnginePrivate::get(engine)->warning(error);
1560 dumpwarning(error->error(0));
1563 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1566 engine->warning(error);
1571 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1574 engine->warning(error);
1580 This function should be called prior to evaluation of any js expression,
1581 so that scarce resources are not freed prematurely (eg, if there is a
1582 nested javascript expression).
1584 void QQmlEnginePrivate::referenceScarceResources()
1586 scarceResourcesRefCount += 1;
1590 This function should be called after evaluation of the js expression is
1591 complete, and so the scarce resources may be freed safely.
1593 void QQmlEnginePrivate::dereferenceScarceResources()
1595 Q_ASSERT(scarceResourcesRefCount > 0);
1596 scarceResourcesRefCount -= 1;
1598 // if the refcount is zero, then evaluation of the "top level"
1599 // expression must have completed. We can safely release the
1600 // scarce resources.
1601 if (scarceResourcesRefCount == 0) {
1602 // iterate through the list and release them all.
1603 // note that the actual SRD is owned by the JS engine,
1604 // so we cannot delete the SRD; but we can free the
1605 // memory used by the variant in the SRD.
1606 while (ScarceResourceData *sr = scarceResources.first()) {
1607 sr->data = QVariant();
1608 scarceResources.remove(sr);
1614 Adds \a path as a directory where the engine searches for
1615 installed modules in a URL-based directory structure.
1617 The \a path may be a local filesystem directory, a
1618 \l {The Qt Resource System}{Qt Resource} path (\c {:/imports}), a
1619 \l {The Qt Resource System}{Qt Resource} url (\c {qrc:/imports}) or a URL.
1621 The \a path will be converted into canonical form before it
1622 is added to the import path list.
1624 The newly added \a path will be first in the importPathList().
1626 \sa setImportPathList(), {QML Modules}
1628 void QQmlEngine::addImportPath(const QString& path)
1631 d->importDatabase.addImportPath(path);
1635 Returns the list of directories where the engine searches for
1636 installed modules in a URL-based directory structure.
1638 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1639 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1640 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1641 provided by that module. A \c qmldir file is required for defining the
1642 type version mapping and possibly QML extensions plugins.
1644 By default, the list contains the directory of the application executable,
1645 paths specified in the \c QML_IMPORT_PATH environment variable,
1646 and the builtin \c ImportsPath from QLibraryInfo.
1648 \sa addImportPath(), setImportPathList()
1650 QStringList QQmlEngine::importPathList() const
1652 Q_D(const QQmlEngine);
1653 return d->importDatabase.importPathList();
1657 Sets \a paths as the list of directories where the engine searches for
1658 installed modules in a URL-based directory structure.
1660 By default, the list contains the directory of the application executable,
1661 paths specified in the \c QML_IMPORT_PATH environment variable,
1662 and the builtin \c ImportsPath from QLibraryInfo.
1664 \sa importPathList(), addImportPath()
1666 void QQmlEngine::setImportPathList(const QStringList &paths)
1669 d->importDatabase.setImportPathList(paths);
1674 Adds \a path as a directory where the engine searches for
1675 native plugins for imported modules (referenced in the \c qmldir file).
1677 By default, the list contains only \c ., i.e. the engine searches
1678 in the directory of the \c qmldir file itself.
1680 The newly added \a path will be first in the pluginPathList().
1682 \sa setPluginPathList()
1684 void QQmlEngine::addPluginPath(const QString& path)
1687 d->importDatabase.addPluginPath(path);
1692 Returns the list of directories where the engine searches for
1693 native plugins for imported modules (referenced in the \c qmldir file).
1695 By default, the list contains only \c ., i.e. the engine searches
1696 in the directory of the \c qmldir file itself.
1698 \sa addPluginPath(), setPluginPathList()
1700 QStringList QQmlEngine::pluginPathList() const
1702 Q_D(const QQmlEngine);
1703 return d->importDatabase.pluginPathList();
1707 Sets the list of directories where the engine searches for
1708 native plugins for imported modules (referenced in the \c qmldir file)
1711 By default, the list contains only \c ., i.e. the engine searches
1712 in the directory of the \c qmldir file itself.
1714 \sa pluginPathList(), addPluginPath()
1716 void QQmlEngine::setPluginPathList(const QStringList &paths)
1719 d->importDatabase.setPluginPathList(paths);
1723 Imports the plugin named \a filePath with the \a uri provided.
1724 Returns true if the plugin was successfully imported; otherwise returns false.
1726 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1728 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1730 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1733 return d->importDatabase.importPlugin(filePath, uri, QString(), errors);
1737 \property QQmlEngine::offlineStoragePath
1738 \brief the directory for storing offline user data
1740 Returns the directory where SQL and other offline
1743 QQuickWebView and the SQL databases created with openDatabase()
1746 The default is QML/OfflineStorage in the platform-standard
1747 user application data directory.
1749 Note that the path may not currently exist on the filesystem, so
1750 callers wanting to \e create new files at this location should create
1751 it first - see QDir::mkpath().
1753 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1756 d->offlineStoragePath = dir;
1759 QString QQmlEngine::offlineStoragePath() const
1761 Q_D(const QQmlEngine);
1762 return d->offlineStoragePath;
1765 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1769 if (!mo->superClass()) {
1770 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1771 propertyCache.insert(mo, rv);
1774 QQmlPropertyCache *super = cache(mo->superClass());
1775 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1776 propertyCache.insert(mo, rv);
1781 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1784 QList<QQmlType *> types;
1786 int maxMinorVersion = 0;
1788 const QMetaObject *metaObject = type->metaObject();
1790 while (metaObject) {
1791 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1792 type->majorVersion(), minorVersion);
1794 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1800 metaObject = metaObject->superClass();
1803 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1805 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1809 QQmlPropertyCache *raw = cache(type->metaObject());
1811 bool hasCopied = false;
1813 for (int ii = 0; ii < types.count(); ++ii) {
1814 QQmlType *currentType = types.at(ii);
1818 int rev = currentType->metaObjectRevision();
1819 int moIndex = types.count() - 1 - ii;
1821 if (raw->allowedRevisionCache[moIndex] != rev) {
1826 raw->allowedRevisionCache[moIndex] = rev;
1830 // Test revision compatibility - the basic rule is:
1831 // * Anything that is excluded, cannot overload something that is not excluded *
1833 // Signals override:
1834 // * other signals and methods of the same name.
1835 // * properties named on<Signal Name>
1836 // * automatic <property name>Changed notify signals
1838 // Methods override:
1839 // * other methods of the same name
1841 // Properties override:
1842 // * other elements of the same name
1844 bool overloadError = false;
1845 QString overloadName;
1848 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1849 !overloadError && iter != raw->stringCache.end();
1852 QQmlPropertyData *d = *iter;
1853 if (raw->isAllowedInRevision(d))
1854 continue; // Not excluded - no problems
1856 // check that a regular "name" overload isn't happening
1857 QQmlPropertyData *current = d;
1858 while (!overloadError && current) {
1859 current = d->overrideData(current);
1860 if (current && raw->isAllowedInRevision(current))
1861 overloadError = true;
1866 if (overloadError) {
1867 if (hasCopied) raw->release();
1869 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."));
1873 if (!hasCopied) raw->addref();
1874 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1876 if (minorVersion != maxMinorVersion) {
1878 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1884 QQmlMetaType::ModuleApiInstance *
1885 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1887 Locker locker(this);
1889 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1891 a = new QQmlMetaType::ModuleApiInstance;
1892 a->scriptCallback = module.script;
1893 a->qobjectCallback = module.qobject;
1894 a->instanceMetaObject = module.instanceMetaObject;
1895 moduleApiInstances.insert(module, a);
1901 bool QQmlEnginePrivate::isQObject(int t)
1903 Locker locker(this);
1904 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1907 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1909 Locker locker(this);
1910 int t = v.userType();
1911 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1913 return *(QObject **)(v.constData());
1915 return QQmlMetaType::toQObject(v, ok);
1919 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1921 Locker locker(this);
1922 if (m_compositeTypes.contains(t))
1923 return QQmlMetaType::Object;
1924 else if (m_qmlLists.contains(t))
1925 return QQmlMetaType::List;
1927 return QQmlMetaType::typeCategory(t);
1930 bool QQmlEnginePrivate::isList(int t) const
1932 Locker locker(this);
1933 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1936 int QQmlEnginePrivate::listType(int t) const
1938 Locker locker(this);
1939 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1940 if (iter != m_qmlLists.end())
1943 return QQmlMetaType::listType(t);
1946 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1948 Locker locker(this);
1949 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1950 if (iter != m_compositeTypes.end()) {
1951 return QQmlMetaObject((*iter)->rootPropertyCache);
1953 QQmlType *type = QQmlMetaType::qmlType(t);
1954 return QQmlMetaObject(type?type->baseMetaObject():0);
1958 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1960 Locker locker(this);
1961 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1962 if (iter != m_compositeTypes.end()) {
1963 return QQmlMetaObject((*iter)->rootPropertyCache);
1965 QQmlType *type = QQmlMetaType::qmlType(t);
1966 return QQmlMetaObject(type?type->metaObject():0);
1970 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1972 Locker locker(this);
1973 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1974 if (iter != m_compositeTypes.end()) {
1975 return (*iter)->rootPropertyCache;
1977 QQmlType *type = QQmlMetaType::qmlType(t);
1979 return type?cache(type->metaObject()):0;
1983 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1985 Locker locker(this);
1986 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1987 if (iter != m_compositeTypes.end()) {
1988 return (*iter)->rootPropertyCache;
1990 QQmlType *type = QQmlMetaType::qmlType(t);
1992 return type?cache(type->baseMetaObject()):0;
1996 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1998 QByteArray name = data->rootPropertyCache->className();
2000 QByteArray ptr = name + '*';
2001 QByteArray lst = "QQmlListProperty<" + name + '>';
2003 int ptr_type = QMetaType::registerNormalizedType(ptr,
2004 qMetaTypeDeleteHelper<QObject*>,
2005 qMetaTypeCreateHelper<QObject*>,
2006 qMetaTypeDestructHelper<QObject*>,
2007 qMetaTypeConstructHelper<QObject*>,
2009 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
2011 int lst_type = QMetaType::registerNormalizedType(lst,
2012 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
2013 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
2014 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
2015 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
2016 sizeof(QQmlListProperty<QObject>),
2017 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
2018 static_cast<QMetaObject*>(0));
2020 data->metaTypeId = ptr_type;
2021 data->listMetaTypeId = lst_type;
2022 data->isRegisteredWithEngine = true;
2024 Locker locker(this);
2025 m_qmlLists.insert(lst_type, ptr_type);
2026 // The QQmlCompiledData is not referenced here, but it is removed from this
2027 // hash in the QQmlCompiledData destructor
2028 m_compositeTypes.insert(ptr_type, data);
2031 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
2033 int ptr_type = data->metaTypeId;
2034 int lst_type = data->listMetaTypeId;
2036 Locker locker(this);
2037 m_qmlLists.remove(lst_type);
2038 m_compositeTypes.remove(ptr_type);
2041 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2043 return typeLoader.isTypeLoaded(url);
2046 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2048 return typeLoader.isScriptLoaded(url);
2051 bool QQml_isFileCaseCorrect(const QString &fileName)
2053 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2054 QFileInfo info(fileName);
2055 const QString absolute = info.absoluteFilePath();
2057 #if defined(Q_OS_MAC)
2058 const QString canonical = info.canonicalFilePath();
2059 #elif defined(Q_OS_WIN)
2060 wchar_t buffer[1024];
2062 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2063 if (rv == 0 || rv >= 1024) return true;
2064 rv = ::GetLongPathName(buffer, buffer, 1024);
2065 if (rv == 0 || rv >= 1024) return true;
2067 const QString canonical = QString::fromWCharArray(buffer);
2070 const int absoluteLength = absolute.length();
2071 const int canonicalLength = canonical.length();
2073 const int length = qMin(absoluteLength, canonicalLength);
2074 for (int ii = 0; ii < length; ++ii) {
2075 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2076 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2078 if (a.toLower() != c.toLower())
2090 \fn QQmlEngine *qmlEngine(const QObject *object)
2093 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2094 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2098 \fn QQmlContext *qmlContext(const QObject *object)
2101 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2102 QQmlEngine::contextForObject(object).