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. \omitvalue
224 \enum QQmlImageProviderBase::Flag
226 Defines specific requirements or features of this image provider.
228 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
229 run in a separate thread, which allows the provider to spend as much time as needed
230 on producing the image without blocking the main thread.
234 QQmlImageProviderBase::QQmlImageProviderBase()
239 QQmlImageProviderBase::~QQmlImageProviderBase()
246 \instantiates QQmlEnginePrivate
247 \ingroup qml-utility-elements
248 \brief The QML global Qt object provides useful enums and functions from Qt.
250 \keyword QmlGlobalQtObject
252 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
254 The \c Qt object is a global object with utility functions, properties and enums.
256 It is not instantiable; to use it, call the members of the global \c Qt object directly.
263 color: Qt.rgba(1, 0, 0, 1)
264 text: Qt.md5("hello, world")
271 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
272 the \l Qt::LeftButton and \l Qt::RightButton enumeration values as \c Qt.LeftButton and \c Qt.RightButton.
277 The Qt object also contains helper functions for creating objects of specific
278 data types. This is primarily useful when setting the properties of an item
279 when the property has one of the following types:
281 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
282 \li \c point - use \l{Qt::point()}{Qt.point()}
283 \li \c size - use \l{Qt::size()}{Qt.size()}
286 If the QtQuick module has been imported, the following helper functions for
287 creating objects of specific data types are also available for clients to use:
289 \li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
290 \li \c font - use \l{Qt::font()}{Qt.font()}
291 \li \c vector2d - use \l{Qt::vector2d()}{Qt.vector2d()}
292 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
293 \li \c vector4d - use \l{Qt::vector4d()}{Qt.vector4d()}
294 \li \c quaternion - use \l{Qt::quaternion()}{Qt.quaternion()}
295 \li \c matrix4x4 - use \l{Qt::matrix4x4()}{Qt.matrix4x4()}
298 There are also string based constructors for these types. See \l{qtqml-typesystem-basictypes.html}{QML Basic Types} for more information.
300 \section1 Date/Time Formatters
302 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
305 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
306 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
307 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
310 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
313 \section1 Dynamic Object Creation
314 The following functions on the global object allow you to dynamically create QML
315 items from files or strings. See \l{Dynamic QML Object Creation from JavaScript} for an overview
319 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
320 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
324 \section1 Other Functions
326 The following functions are also on the Qt object.
329 \li \l{Qt::quit()}{Qt.quit()}
330 \li \l{Qt::md5()}{Qt.md5(string)}
331 \li \l{Qt::btoa()}{string Qt.btoa(string)}
332 \li \l{Qt::atob()}{string Qt.atob(string)}
333 \li \l{Qt::binding()}{object Qt.binding(function)}
334 \li \l{Qt::locale()}{object Qt.locale()}
335 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
336 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
337 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
342 \qmlproperty object Qt::application
345 The \c application object provides access to global application state
346 properties shared by many QML components.
352 \li \c application.active
354 This read-only property indicates whether the application is the top-most and focused
355 application, and the user is able to interact with the application. The property
356 is false when the application is in the background, the device keylock or screen
357 saver is active, the screen backlight is turned off, or the global system dialog
358 is being displayed on top of the application. It can be used for stopping and
359 pausing animations, timers and active processing of data in order to save device
360 battery power and free device memory and processor load when the application is not
364 \li \c application.layoutDirection
366 This read-only property can be used to query the default layout direction of the
367 application. On system start-up, the default layout direction depends on the
368 application's language. The property has a value of \c Qt.RightToLeft in locales
369 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
370 where the reading direction flows from left to right. You can bind to this
371 property to customize your application layouts to support both layout directions.
376 \li Qt.LeftToRight - Text and graphics elements should be positioned
378 \li Qt.RightToLeft - Text and graphics elements should be positioned
384 The following example uses the \c application object to indicate
385 whether the application is currently active:
387 \snippet qml/application.qml document
391 \qmlproperty object Qt::inputMethod
394 The \c inputMethod object allows access to application's QInputMethod object
395 and all its properties and slots. See the QInputMethod documentation for
401 \qmlmethod object Qt::include(string url, jsobject callback)
403 Includes another JavaScript file. This method can only be used from within JavaScript files,
404 and not regular QML files.
406 This imports all functions from \a url into the current script's namespace.
408 Qt.include() returns an object that describes the status of the operation. The object has
409 a single property, \c {status}, that is set to one of the following values:
412 \header \li Symbol \li Value \li Description
413 \row \li result.OK \li 0 \li The include completed successfully.
414 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
415 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
416 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
417 An additional \c exception property will be set in this case.
420 The \c status property will be updated as the operation progresses.
422 If provided, \a callback is invoked when the operation completes. The callback is passed
423 the same object as is returned from the Qt.include() call.
425 // Qt.include() is implemented in qv8include.cpp
428 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
429 : propertyCapture(0), rootContext(0), isDebugging(false),
430 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
431 cleanup(0), erroredBindings(0), inProgressCreations(0),
432 workerScriptEngine(0), activeVME(0),
433 networkAccessManager(0), networkAccessManagerFactory(0),
434 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
435 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
439 QQmlEnginePrivate::~QQmlEnginePrivate()
441 if (inProgressCreations)
442 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
445 QQmlCleanup *c = cleanup;
447 if (cleanup) cleanup->prev = &cleanup;
453 doDeleteInEngineThread();
455 if (incubationController) incubationController->d = 0;
456 incubationController = 0;
461 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
463 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
465 for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
466 iter.value()->isRegisteredWithEngine = false;
469 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
471 QObjectPrivate *p = QObjectPrivate::get(o);
472 if (p->declarativeData) {
473 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
474 if (d->ownContext && d->context) {
475 d->context->destroy();
479 // Mark this object as in the process of deletion to
480 // prevent it resolving in bindings
481 QQmlData::markAsDeleted(o);
483 // Disconnect the notifiers now - during object destruction this would be too late, since
484 // the disconnect call wouldn't be able to call disconnectNotify(), as it isn't possible to
485 // get the metaobject anymore.
486 d->disconnectNotifiers();
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, Singleton Types etc. that
739 // may be required to handle the destruction signal.
740 QQmlContextData::get(rootContext())->emitDestruction();
742 // clean up all singleton type instances which we own.
743 // we do this here and not in the private dtor since otherwise a crash can
744 // occur (if we are the QObject parent of the QObject singleton instance)
745 // XXX TODO: performance -- store list of singleton types separately?
746 QList<QQmlType*> singletonTypes = QQmlMetaType::qmlSingletonTypes();
747 foreach (QQmlType *currType, singletonTypes)
748 currType->singletonInstanceInfo()->destroy(this);
750 if (d->incubationController)
751 d->incubationController->d = 0;
754 /*! \fn void QQmlEngine::quit()
755 This signal is emitted when the QML loaded by the engine would like to quit.
758 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
759 This signal is emitted when \a warnings messages are generated by QML.
763 Clears the engine's internal component cache.
765 This function causes the property metadata of all components previously
766 loaded by the engine to be destroyed. All previously loaded components and
767 the property bindings for all extant objects created from those components will
770 This function returns the engine to a state where it does not contain any loaded
771 component data. This may be useful in order to reload a smaller subset of the
772 previous component set, or to load a new version of a previously loaded component.
774 Once the component cache has been cleared, components must be loaded before
775 any new objects can be created.
777 \sa trimComponentCache()
779 void QQmlEngine::clearComponentCache()
782 d->typeLoader.clearCache();
786 Trims the engine's internal component cache.
788 This function causes the property metadata of any loaded components which are
789 not currently in use to be destroyed.
791 A component is considered to be in use if there are any extant instances of
792 the component itself, any instances of other components that use the component,
793 or any objects instantiated by any of those components.
795 \sa clearComponentCache()
797 void QQmlEngine::trimComponentCache()
800 d->typeLoader.trimCache();
804 Returns the engine's root context.
806 The root context is automatically created by the QQmlEngine.
807 Data that should be available to all QML component instances
808 instantiated by the engine should be put in the root context.
810 Additional data that should only be available to a subset of
811 component instances should be added to sub-contexts parented to the
814 QQmlContext *QQmlEngine::rootContext() const
816 Q_D(const QQmlEngine);
817 return d->rootContext;
821 Sets the \a factory to use for creating QNetworkAccessManager(s).
823 QNetworkAccessManager is used for all network access by QML. By
824 implementing a factory it is possible to create custom
825 QNetworkAccessManager with specialized caching, proxy and cookie
828 The factory must be set before executing the engine.
830 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
833 QMutexLocker locker(&d->mutex);
834 d->networkAccessManagerFactory = factory;
838 Returns the current QQmlNetworkAccessManagerFactory.
840 \sa setNetworkAccessManagerFactory()
842 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
844 Q_D(const QQmlEngine);
845 return d->networkAccessManagerFactory;
848 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
851 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
853 void *args[] = { 0 };
854 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
858 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
860 QMutexLocker locker(&mutex);
861 QNetworkAccessManager *nam;
862 if (networkAccessManagerFactory) {
863 nam = networkAccessManagerFactory->create(parent);
865 nam = new QNetworkAccessManager(parent);
871 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
873 Q_Q(const QQmlEngine);
874 if (!networkAccessManager)
875 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
876 return networkAccessManager;
880 Returns a common QNetworkAccessManager which can be used by any QML
881 type instantiated by this engine.
883 If a QQmlNetworkAccessManagerFactory has been set and a
884 QNetworkAccessManager has not yet been created, the
885 QQmlNetworkAccessManagerFactory will be used to create the
886 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
887 will have no proxy or cache set.
889 \sa setNetworkAccessManagerFactory()
891 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
893 Q_D(const QQmlEngine);
894 return d->getNetworkAccessManager();
899 Sets the \a provider to use for images requested via the \e
900 image: url scheme, with host \a providerId. The QQmlEngine
901 takes ownership of \a provider.
903 Image providers enable support for pixmap and threaded image
904 requests. See the QQuickImageProvider documentation for details on
905 implementing and using image providers.
907 All required image providers should be added to the engine before any
908 QML sources files are loaded.
910 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
912 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
915 QMutexLocker locker(&d->mutex);
916 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
920 Returns the image provider set for \a providerId.
922 Returns the provider if it was found; otherwise returns 0.
924 \sa QQuickImageProvider
926 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
928 Q_D(const QQmlEngine);
929 QMutexLocker locker(&d->mutex);
930 return d->imageProviders.value(providerId).data();
934 Removes the image provider for \a providerId.
936 \sa addImageProvider(), QQuickImageProvider
938 void QQmlEngine::removeImageProvider(const QString &providerId)
941 QMutexLocker locker(&d->mutex);
942 d->imageProviders.take(providerId);
946 Return the base URL for this engine. The base URL is only used to
947 resolve components when a relative URL is passed to the
948 QQmlComponent constructor.
950 If a base URL has not been explicitly set, this method returns the
951 application's current working directory.
955 QUrl QQmlEngine::baseUrl() const
957 Q_D(const QQmlEngine);
958 if (d->baseUrl.isEmpty()) {
959 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
966 Set the base URL for this engine to \a url.
970 void QQmlEngine::setBaseUrl(const QUrl &url)
977 Returns true if warning messages will be output to stderr in addition
978 to being emitted by the warnings() signal, otherwise false.
980 The default value is true.
982 bool QQmlEngine::outputWarningsToStandardError() const
984 Q_D(const QQmlEngine);
985 return d->outputWarningsToStdErr;
989 Set whether warning messages will be output to stderr to \a enabled.
991 If \a enabled is true, any warning messages generated by QML will be
992 output to stderr and emitted by the warnings() signal. If \a enabled
993 is false, on the warnings() signal will be emitted. This allows
994 applications to handle warning output themselves.
996 The default value is true.
998 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
1001 d->outputWarningsToStdErr = enabled;
1005 Returns the QQmlContext for the \a object, or 0 if no
1006 context has been set.
1008 When the QQmlEngine instantiates a QObject, the context is
1011 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
1016 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
1019 static_cast<QQmlData *>(priv->declarativeData);
1023 else if (data->outerContext)
1024 return data->outerContext->asQQmlContext();
1030 Sets the QQmlContext for the \a object to \a context.
1031 If the \a object already has a context, a warning is
1032 output, but the context is not changed.
1034 When the QQmlEngine instantiates a QObject, the context is
1037 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1039 if (!object || !context)
1042 QQmlData *data = QQmlData::get(object, true);
1043 if (data->context) {
1044 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1048 QQmlContextData *contextData = QQmlContextData::get(context);
1049 contextData->addObject(object);
1053 \enum QQmlEngine::ObjectOwnership
1055 Ownership controls whether or not QML automatically destroys the
1056 QObject when the object is garbage collected by the JavaScript
1057 engine. The two ownership options are:
1059 \value CppOwnership The object is owned by C++ code, and will
1060 never be deleted by QML. The JavaScript destroy() method cannot be
1061 used on objects with CppOwnership. This option is similar to
1062 QScriptEngine::QtOwnership.
1064 \value JavaScriptOwnership The object is owned by JavaScript.
1065 When the object is returned to QML as the return value of a method
1066 call or property access, QML will track it, and delete the object
1067 if there are no remaining JavaScript references to it and it has no
1068 QObject::parent(). An object tracked by one QQmlEngine
1069 will be deleted during that QQmlEngine's destructor, and thus
1070 JavaScript references between objects with JavaScriptOwnership from
1071 two different engines will not be valid after the deletion of one of
1072 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1074 Generally an application doesn't need to set an object's ownership
1075 explicitly. QML uses a heuristic to set the default object
1076 ownership. By default, an object that is created by QML has
1077 JavaScriptOwnership. The exception to this are the root objects
1078 created by calling QQmlComponent::create() or
1079 QQmlComponent::beginCreate() which have CppOwnership by
1080 default. The ownership of these root-level objects is considered to
1081 have been transferred to the C++ caller.
1083 Objects not-created by QML have CppOwnership by default. The
1084 exception to this is objects returned from a C++ method call. The
1085 ownership of these objects is passed to JavaScript.
1087 Calling setObjectOwnership() overrides the default ownership
1088 heuristic used by QML.
1092 Sets the \a ownership of \a object.
1094 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1099 QQmlData *ddata = QQmlData::get(object, true);
1103 ddata->indestructible = (ownership == CppOwnership)?true:false;
1104 ddata->explicitIndestructibleSet = true;
1108 Returns the ownership of \a object.
1110 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1113 return CppOwnership;
1115 QQmlData *ddata = QQmlData::get(object, false);
1117 return CppOwnership;
1119 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1122 bool QQmlEngine::event(QEvent *e)
1125 if (e->type() == QEvent::User)
1126 d->doDeleteInEngineThread();
1128 return QJSEngine::event(e);
1131 void QQmlEnginePrivate::doDeleteInEngineThread()
1133 QFieldList<Deletable, &Deletable::next> list;
1135 list.copyAndClear(toDeleteInEngineThread);
1138 while (Deletable *d = list.takeFirst())
1142 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1144 QQmlData *data = QQmlData::get(object);
1146 if (data && data->compiledData && data->deferredIdx) {
1147 QQmlObjectCreatingProfiler prof;
1149 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1150 prof.setTypeName(type ? type->qmlTypeName()
1151 : QString::fromUtf8(object->metaObject()->className()));
1152 if (data->outerContext)
1153 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1155 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1157 QQmlComponentPrivate::ConstructionState state;
1158 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1160 // Release the reference for the deferral action (we still have one from construction)
1161 data->compiledData->release();
1162 data->compiledData = 0;
1164 QQmlComponentPrivate::complete(ep, &state);
1168 QQmlContext *qmlContext(const QObject *obj)
1170 return QQmlEngine::contextForObject(obj);
1173 QQmlEngine *qmlEngine(const QObject *obj)
1175 QQmlData *data = QQmlData::get(obj, false);
1176 if (!data || !data->context)
1178 return data->context->engine;
1181 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1183 QQmlData *data = QQmlData::get(object);
1185 return 0; // Attached properties are only on objects created by QML
1187 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1191 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1195 rv = pf(const_cast<QObject *>(object));
1198 data->attachedProperties()->insert(id, rv);
1203 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1204 const QMetaObject *attachedMetaObject, bool create)
1207 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1209 if (*idCache == -1 || !object)
1212 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1215 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1217 #ifndef QQML_NO_DEBUG_PROTOCOL
1218 if (!QQmlEnginePrivate::qml_debugging_enabled
1220 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1222 QQmlEnginePrivate::qml_debugging_enabled = true;
1227 class QQmlDataExtended {
1230 ~QQmlDataExtended();
1232 QHash<int, QObject *> attachedProperties;
1235 QQmlDataExtended::QQmlDataExtended()
1239 QQmlDataExtended::~QQmlDataExtended()
1243 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1246 layout(endpoint->next);
1248 int index = endpoint->sourceSignal;
1249 index = qMin(index, 0xFFFF - 1);
1251 endpoint->next = notifies[index];
1252 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1253 endpoint->prev = ¬ifies[index];
1254 notifies[index] = endpoint;
1257 void QQmlData::NotifyList::layout()
1259 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1262 QQmlNotifierEndpoint **old = notifies;
1263 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1264 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1265 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1266 sizeof(QQmlNotifierEndpoint*);
1267 memset(notifies + notifiesSize, 0, memsetSize);
1269 if (notifies != old) {
1270 for (int ii = 0; ii < notifiesSize; ++ii)
1272 notifies[ii]->prev = ¬ifies[ii];
1275 notifiesSize = maximumTodoIndex + 1;
1280 maximumTodoIndex = 0;
1284 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1287 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1288 notifyList->connectionMask = 0;
1289 notifyList->maximumTodoIndex = 0;
1290 notifyList->notifiesSize = 0;
1291 notifyList->todo = 0;
1292 notifyList->notifies = 0;
1295 Q_ASSERT(!endpoint->isConnected());
1297 index = qMin(index, 0xFFFF - 1);
1298 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1300 if (index < notifyList->notifiesSize) {
1302 endpoint->next = notifyList->notifies[index];
1303 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1304 endpoint->prev = ¬ifyList->notifies[index];
1305 notifyList->notifies[index] = endpoint;
1308 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1310 endpoint->next = notifyList->todo;
1311 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1312 endpoint->prev = ¬ifyList->todo;
1313 notifyList->todo = endpoint;
1318 index MUST in the range returned by QObjectPrivate::signalIndex()
1319 This is different than the index returned by QMetaMethod::methodIndex()
1321 bool QQmlData::signalHasEndpoint(int index)
1323 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1326 void QQmlData::disconnectNotifiers()
1329 while (notifyList->todo)
1330 notifyList->todo->disconnect();
1331 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1332 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1335 free(notifyList->notifies);
1341 QHash<int, QObject *> *QQmlData::attachedProperties() const
1343 if (!extendedData) extendedData = new QQmlDataExtended;
1344 return &extendedData->attachedProperties;
1347 void QQmlData::destroyed(QObject *object)
1349 if (nextContextObject)
1350 nextContextObject->prevContextObject = prevContextObject;
1351 if (prevContextObject)
1352 *prevContextObject = nextContextObject;
1354 QQmlAbstractBinding *binding = bindings;
1356 QQmlAbstractBinding *next = binding->nextBinding();
1357 binding->setAddedToObject(false);
1358 binding->setNextBinding(0);
1364 compiledData->release();
1368 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1369 while (signalHandler) {
1370 if (signalHandler->isEvaluating()) {
1371 // The object is being deleted during signal handler evaluation.
1372 // This will cause a crash due to invalid memory access when the
1373 // evaluation has completed.
1374 // Abort with a friendly message instead.
1375 QString locationString;
1376 QQmlBoundSignalExpression *expr = signalHandler->expression();
1378 QString fileName = expr->sourceFile();
1379 if (fileName.isEmpty())
1380 fileName = QStringLiteral("<Unknown File>");
1381 locationString.append(fileName);
1382 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1383 QString source = expr->expression();
1384 if (source.size() > 100) {
1385 source.truncate(96);
1386 source.append(QStringLiteral(" ..."));
1388 locationString.append(source);
1390 locationString = QStringLiteral("<Unknown Location>");
1392 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1393 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1394 "instead), or the application is running a nested event loop.\n"
1395 "This behavior is NOT supported!\n"
1396 "%s", object, qPrintable(locationString));
1399 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1400 signalHandler->m_prevSignal = 0;
1401 signalHandler->m_nextSignal = 0;
1402 delete signalHandler;
1403 signalHandler = next;
1410 propertyCache->release();
1412 if (ownContext && context)
1416 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1417 *guard = (QObject *)0;
1418 guard->objectDestroyed(object);
1421 disconnectNotifiers();
1424 delete extendedData;
1426 // Dispose the handle.
1427 // We don't simply clear it (and wait for next gc cycle to dispose
1428 // via the weak qobject reference callback) as this affects the
1429 // outcomes of v8's gc statistical analysis heuristics, which can
1430 // cause unnecessary growth of the old pointer space js heap area.
1431 qPersistentDispose(v8object);
1437 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1439 void QQmlData::parentChanged(QObject *object, QObject *parent)
1442 if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1446 { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1447 { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1449 qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1450 "User code is attempting to change it to %s.\n"
1451 "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1456 bool QQmlData::hasBindingBit(int bit) const
1458 if (bindingBitsSize > bit)
1459 return bindingBits[bit / 32] & (1 << (bit % 32));
1464 void QQmlData::clearBindingBit(int bit)
1466 if (bindingBitsSize > bit)
1467 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1470 void QQmlData::setBindingBit(QObject *obj, int bit)
1472 if (bindingBitsSize <= bit) {
1473 int props = QQmlMetaObject(obj).propertyCount();
1474 Q_ASSERT(bit < props);
1476 int arraySize = (props + 31) / 32;
1477 int oldArraySize = bindingBitsSize / 32;
1479 bindingBits = (quint32 *)realloc(bindingBits,
1480 arraySize * sizeof(quint32));
1482 memset(bindingBits + oldArraySize,
1484 sizeof(quint32) * (arraySize - oldArraySize));
1486 bindingBitsSize = arraySize * 32;
1489 bindingBits[bit / 32] |= (1 << (bit % 32));
1492 void QQmlEnginePrivate::sendQuit()
1496 if (q->receivers(SIGNAL(quit())) == 0) {
1497 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1501 static void dumpwarning(const QQmlError &error)
1503 QMessageLogger(error.url().toString().toLatin1().constData(),
1504 error.line(), 0).warning().nospace()
1505 << qPrintable(error.toString());
1508 static void dumpwarning(const QList<QQmlError> &errors)
1510 for (int ii = 0; ii < errors.count(); ++ii)
1511 dumpwarning(errors.at(ii));
1514 void QQmlEnginePrivate::warning(const QQmlError &error)
1517 q->warnings(QList<QQmlError>() << error);
1518 if (outputWarningsToStdErr)
1522 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1525 q->warnings(errors);
1526 if (outputWarningsToStdErr)
1527 dumpwarning(errors);
1530 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1533 warning(error->error(q));
1536 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1539 QQmlEnginePrivate::get(engine)->warning(error);
1544 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1547 QQmlEnginePrivate::get(engine)->warning(error);
1552 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1555 QQmlEnginePrivate::get(engine)->warning(error);
1557 dumpwarning(error->error(0));
1560 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1563 engine->warning(error);
1568 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1571 engine->warning(error);
1577 This function should be called prior to evaluation of any js expression,
1578 so that scarce resources are not freed prematurely (eg, if there is a
1579 nested javascript expression).
1581 void QQmlEnginePrivate::referenceScarceResources()
1583 scarceResourcesRefCount += 1;
1587 This function should be called after evaluation of the js expression is
1588 complete, and so the scarce resources may be freed safely.
1590 void QQmlEnginePrivate::dereferenceScarceResources()
1592 Q_ASSERT(scarceResourcesRefCount > 0);
1593 scarceResourcesRefCount -= 1;
1595 // if the refcount is zero, then evaluation of the "top level"
1596 // expression must have completed. We can safely release the
1597 // scarce resources.
1598 if (scarceResourcesRefCount == 0) {
1599 // iterate through the list and release them all.
1600 // note that the actual SRD is owned by the JS engine,
1601 // so we cannot delete the SRD; but we can free the
1602 // memory used by the variant in the SRD.
1603 while (ScarceResourceData *sr = scarceResources.first()) {
1604 sr->data = QVariant();
1605 scarceResources.remove(sr);
1611 Adds \a path as a directory where the engine searches for
1612 installed modules in a URL-based directory structure.
1614 The \a path may be a local filesystem directory, a
1615 \l {The Qt Resource System}{Qt Resource} path (\c {:/imports}), a
1616 \l {The Qt Resource System}{Qt Resource} url (\c {qrc:/imports}) or a URL.
1618 The \a path will be converted into canonical form before it
1619 is added to the import path list.
1621 The newly added \a path will be first in the importPathList().
1623 \sa setImportPathList(), {QML Modules}
1625 void QQmlEngine::addImportPath(const QString& path)
1628 d->importDatabase.addImportPath(path);
1632 Returns the list of directories where the engine searches for
1633 installed modules in a URL-based directory structure.
1635 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1636 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1637 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1638 provided by that module. A \c qmldir file is required for defining the
1639 type version mapping and possibly QML extensions plugins.
1641 By default, the list contains the directory of the application executable,
1642 paths specified in the \c QML_IMPORT_PATH environment variable,
1643 and the builtin \c ImportsPath from QLibraryInfo.
1645 \sa addImportPath(), setImportPathList()
1647 QStringList QQmlEngine::importPathList() const
1649 Q_D(const QQmlEngine);
1650 return d->importDatabase.importPathList();
1654 Sets \a paths as the list of directories where the engine searches for
1655 installed modules in a URL-based directory structure.
1657 By default, the list contains the directory of the application executable,
1658 paths specified in the \c QML_IMPORT_PATH environment variable,
1659 and the builtin \c ImportsPath from QLibraryInfo.
1661 \sa importPathList(), addImportPath()
1663 void QQmlEngine::setImportPathList(const QStringList &paths)
1666 d->importDatabase.setImportPathList(paths);
1671 Adds \a path as a directory where the engine searches for
1672 native plugins for imported modules (referenced in the \c qmldir file).
1674 By default, the list contains only \c ., i.e. the engine searches
1675 in the directory of the \c qmldir file itself.
1677 The newly added \a path will be first in the pluginPathList().
1679 \sa setPluginPathList()
1681 void QQmlEngine::addPluginPath(const QString& path)
1684 d->importDatabase.addPluginPath(path);
1689 Returns the list of directories where the engine searches for
1690 native plugins for imported modules (referenced in the \c qmldir file).
1692 By default, the list contains only \c ., i.e. the engine searches
1693 in the directory of the \c qmldir file itself.
1695 \sa addPluginPath(), setPluginPathList()
1697 QStringList QQmlEngine::pluginPathList() const
1699 Q_D(const QQmlEngine);
1700 return d->importDatabase.pluginPathList();
1704 Sets the list of directories where the engine searches for
1705 native plugins for imported modules (referenced in the \c qmldir file)
1708 By default, the list contains only \c ., i.e. the engine searches
1709 in the directory of the \c qmldir file itself.
1711 \sa pluginPathList(), addPluginPath()
1713 void QQmlEngine::setPluginPathList(const QStringList &paths)
1716 d->importDatabase.setPluginPathList(paths);
1720 Imports the plugin named \a filePath with the \a uri provided.
1721 Returns true if the plugin was successfully imported; otherwise returns false.
1723 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1725 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1727 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1730 return d->importDatabase.importPlugin(filePath, uri, QString(), errors);
1734 \property QQmlEngine::offlineStoragePath
1735 \brief the directory for storing offline user data
1737 Returns the directory where SQL and other offline
1740 QQuickWebView and the SQL databases created with openDatabase()
1743 The default is QML/OfflineStorage in the platform-standard
1744 user application data directory.
1746 Note that the path may not currently exist on the filesystem, so
1747 callers wanting to \e create new files at this location should create
1748 it first - see QDir::mkpath().
1750 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1753 d->offlineStoragePath = dir;
1756 QString QQmlEngine::offlineStoragePath() const
1758 Q_D(const QQmlEngine);
1759 return d->offlineStoragePath;
1762 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1766 if (!mo->superClass()) {
1767 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1768 propertyCache.insert(mo, rv);
1771 QQmlPropertyCache *super = cache(mo->superClass());
1772 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1773 propertyCache.insert(mo, rv);
1778 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1781 QList<QQmlType *> types;
1783 int maxMinorVersion = 0;
1785 const QMetaObject *metaObject = type->metaObject();
1787 while (metaObject) {
1788 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1789 type->majorVersion(), minorVersion);
1791 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1797 metaObject = metaObject->superClass();
1800 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1802 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1806 QQmlPropertyCache *raw = cache(type->metaObject());
1808 bool hasCopied = false;
1810 for (int ii = 0; ii < types.count(); ++ii) {
1811 QQmlType *currentType = types.at(ii);
1815 int rev = currentType->metaObjectRevision();
1816 int moIndex = types.count() - 1 - ii;
1818 if (raw->allowedRevisionCache[moIndex] != rev) {
1823 raw->allowedRevisionCache[moIndex] = rev;
1827 // Test revision compatibility - the basic rule is:
1828 // * Anything that is excluded, cannot overload something that is not excluded *
1830 // Signals override:
1831 // * other signals and methods of the same name.
1832 // * properties named on<Signal Name>
1833 // * automatic <property name>Changed notify signals
1835 // Methods override:
1836 // * other methods of the same name
1838 // Properties override:
1839 // * other elements of the same name
1841 bool overloadError = false;
1842 QString overloadName;
1845 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1846 !overloadError && iter != raw->stringCache.end();
1849 QQmlPropertyData *d = *iter;
1850 if (raw->isAllowedInRevision(d))
1851 continue; // Not excluded - no problems
1853 // check that a regular "name" overload isn't happening
1854 QQmlPropertyData *current = d;
1855 while (!overloadError && current) {
1856 current = d->overrideData(current);
1857 if (current && raw->isAllowedInRevision(current))
1858 overloadError = true;
1863 if (overloadError) {
1864 if (hasCopied) raw->release();
1866 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."));
1870 if (!hasCopied) raw->addref();
1871 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1873 if (minorVersion != maxMinorVersion) {
1875 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1881 bool QQmlEnginePrivate::isQObject(int t)
1883 Locker locker(this);
1884 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1887 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1889 Locker locker(this);
1890 int t = v.userType();
1891 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1893 return *(QObject **)(v.constData());
1895 return QQmlMetaType::toQObject(v, ok);
1899 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1901 Locker locker(this);
1902 if (m_compositeTypes.contains(t))
1903 return QQmlMetaType::Object;
1904 else if (m_qmlLists.contains(t))
1905 return QQmlMetaType::List;
1907 return QQmlMetaType::typeCategory(t);
1910 bool QQmlEnginePrivate::isList(int t) const
1912 Locker locker(this);
1913 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1916 int QQmlEnginePrivate::listType(int t) const
1918 Locker locker(this);
1919 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1920 if (iter != m_qmlLists.end())
1923 return QQmlMetaType::listType(t);
1926 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1928 Locker locker(this);
1929 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1930 if (iter != m_compositeTypes.end()) {
1931 return QQmlMetaObject((*iter)->rootPropertyCache);
1933 QQmlType *type = QQmlMetaType::qmlType(t);
1934 return QQmlMetaObject(type?type->baseMetaObject():0);
1938 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1940 Locker locker(this);
1941 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1942 if (iter != m_compositeTypes.end()) {
1943 return QQmlMetaObject((*iter)->rootPropertyCache);
1945 QQmlType *type = QQmlMetaType::qmlType(t);
1946 return QQmlMetaObject(type?type->metaObject():0);
1950 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1952 Locker locker(this);
1953 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1954 if (iter != m_compositeTypes.end()) {
1955 return (*iter)->rootPropertyCache;
1957 QQmlType *type = QQmlMetaType::qmlType(t);
1959 return type?cache(type->metaObject()):0;
1963 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1965 Locker locker(this);
1966 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1967 if (iter != m_compositeTypes.end()) {
1968 return (*iter)->rootPropertyCache;
1970 QQmlType *type = QQmlMetaType::qmlType(t);
1972 return type?cache(type->baseMetaObject()):0;
1976 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1978 QByteArray name = data->rootPropertyCache->className();
1980 QByteArray ptr = name + '*';
1981 QByteArray lst = "QQmlListProperty<" + name + '>';
1983 int ptr_type = QMetaType::registerNormalizedType(ptr,
1984 qMetaTypeDeleteHelper<QObject*>,
1985 qMetaTypeCreateHelper<QObject*>,
1986 qMetaTypeDestructHelper<QObject*>,
1987 qMetaTypeConstructHelper<QObject*>,
1989 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1991 int lst_type = QMetaType::registerNormalizedType(lst,
1992 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1993 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1994 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1995 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1996 sizeof(QQmlListProperty<QObject>),
1997 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
1998 static_cast<QMetaObject*>(0));
2000 data->metaTypeId = ptr_type;
2001 data->listMetaTypeId = lst_type;
2002 data->isRegisteredWithEngine = true;
2004 Locker locker(this);
2005 m_qmlLists.insert(lst_type, ptr_type);
2006 // The QQmlCompiledData is not referenced here, but it is removed from this
2007 // hash in the QQmlCompiledData destructor
2008 m_compositeTypes.insert(ptr_type, data);
2011 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
2013 int ptr_type = data->metaTypeId;
2014 int lst_type = data->listMetaTypeId;
2016 Locker locker(this);
2017 m_qmlLists.remove(lst_type);
2018 m_compositeTypes.remove(ptr_type);
2021 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2023 return typeLoader.isTypeLoaded(url);
2026 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2028 return typeLoader.isScriptLoaded(url);
2031 bool QQml_isFileCaseCorrect(const QString &fileName)
2033 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2034 QFileInfo info(fileName);
2035 const QString absolute = info.absoluteFilePath();
2037 #if defined(Q_OS_MAC)
2038 const QString canonical = info.canonicalFilePath();
2039 #elif defined(Q_OS_WIN)
2040 wchar_t buffer[1024];
2042 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2043 if (rv == 0 || rv >= 1024) return true;
2044 rv = ::GetLongPathName(buffer, buffer, 1024);
2045 if (rv == 0 || rv >= 1024) return true;
2047 const QString canonical = QString::fromWCharArray(buffer);
2050 const int absoluteLength = absolute.length();
2051 const int canonicalLength = canonical.length();
2053 const int length = qMin(absoluteLength, canonicalLength);
2054 for (int ii = 0; ii < length; ++ii) {
2055 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2056 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2058 if (a.toLower() != c.toLower())
2070 \fn QQmlEngine *qmlEngine(const QObject *object)
2073 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2074 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2078 \fn QQmlContext *qmlContext(const QObject *object)
2081 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2082 QQmlEngine::contextForObject(object).