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 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
111 \qmlclass QtObject QObject
112 \inqmlmodule QtQuick 2
113 \ingroup qml-utility-elements
115 \brief A basic QML type
117 The QtObject element is a non-visual element which contains only the
120 It can be useful to create a QtObject if you need an extremely
121 lightweight element to enclose a set of custom properties:
123 \snippet qml/qtobject.qml 0
125 It can also be useful for C++ integration, as it is just a plain
126 QObject. See the QObject documentation for further details.
129 \qmlproperty string QtObject::objectName
130 This property holds the QObject::objectName for this specific object instance.
132 This allows a C++ application to locate an item within a QML component
133 using the QObject::findChild() method. For example, the following C++
134 application locates the child \l Rectangle item and dynamically changes its
143 width: 200; height: 200
157 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
160 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
162 item->setProperty("color", QColor(Qt::yellow));
166 bool QQmlEnginePrivate::qml_debugging_enabled = false;
168 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
170 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
171 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
172 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
173 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
174 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
177 void QQmlEnginePrivate::defineModule()
179 registerBaseTypes("QtQuick", 2, 0);
180 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
185 \class QQmlImageProviderBase
186 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
189 Image providers must be registered with the QML engine. The only information the QML
190 engine knows about image providers is the type of image data they provide. To use an
191 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
192 to a QQuickImageProvider pointer.
194 \sa QQuickImageProvider, QQuickTextureFactory
198 \enum QQmlImageProviderBase::ImageType
200 Defines the type of image supported by this image provider.
202 \value Image The Image Provider provides QImage images.
203 The QQuickImageProvider::requestImage() method will be called for all image requests.
204 \value Pixmap The Image Provider provides QPixmap images.
205 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
206 \value Texture The Image Provider provides QSGTextureProvider based images.
207 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
211 \enum QQmlImageProviderBase::Flag
213 Defines specific requirements or features of this image provider.
215 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
216 run in a separate thread, which allows the provider to spend as much time as needed
217 on producing the image without blocking the main thread.
221 QQmlImageProviderBase::QQmlImageProviderBase()
226 QQmlImageProviderBase::~QQmlImageProviderBase()
232 \qmlclass Qt QQmlEnginePrivate
233 \ingroup qml-utility-elements
234 \brief The QML global Qt object provides useful enums and functions from Qt.
236 \keyword QmlGlobalQtObject
238 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
240 The \c Qt object is a global object with utility functions, properties and enums.
242 It is not instantiable; to use it, call the members of the global \c Qt object directly.
249 color: Qt.rgba(1, 0, 0, 1)
250 text: Qt.md5("hello, world")
257 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
258 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
262 The Qt object also contains helper functions for creating objects of specific
263 data types. This is primarily useful when setting the properties of an item
264 when the property has one of the following types:
267 \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()}
268 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
269 \li \c point - use \l{Qt::point()}{Qt.point()}
270 \li \c size - use \l{Qt::size()}{Qt.size()}
271 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
274 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
276 \section1 Date/Time Formatters
278 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
281 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
282 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
283 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
286 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
289 \section1 Dynamic Object Creation
290 The following functions on the global object allow you to dynamically create QML
291 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
295 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
296 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
300 \section1 Other Functions
302 The following functions are also on the Qt object.
305 \li \l{Qt::quit()}{Qt.quit()}
306 \li \l{Qt::md5()}{Qt.md5(string)}
307 \li \l{Qt::btoa()}{string Qt.btoa(string)}
308 \li \l{Qt::atob()}{string Qt.atob(string)}
309 \li \l{Qt::binding()}{object Qt.binding(function)}
310 \li \l{Qt::locale()}{object Qt.locale()}
311 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
312 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
313 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
318 \qmlproperty object Qt::application
321 The \c application object provides access to global application state
322 properties shared by many QML components.
328 \li \c application.active
330 This read-only property indicates whether the application is the top-most and focused
331 application, and the user is able to interact with the application. The property
332 is false when the application is in the background, the device keylock or screen
333 saver is active, the screen backlight is turned off, or the global system dialog
334 is being displayed on top of the application. It can be used for stopping and
335 pausing animations, timers and active processing of data in order to save device
336 battery power and free device memory and processor load when the application is not
340 \li \c application.layoutDirection
342 This read-only property can be used to query the default layout direction of the
343 application. On system start-up, the default layout direction depends on the
344 application's language. The property has a value of \c Qt.RightToLeft in locales
345 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
346 where the reading direction flows from left to right. You can bind to this
347 property to customize your application layouts to support both layout directions.
352 \li Qt.LeftToRight - Text and graphics elements should be positioned
354 \li Qt.RightToLeft - Text and graphics elements should be positioned
360 The following example uses the \c application object to indicate
361 whether the application is currently active:
363 \snippet qml/application.qml document
367 \qmlproperty object Qt::inputMethod
370 The \c inputMethod object allows access to application's QInputMethod object
371 and all its properties and slots. See the QInputMethod documentation for
377 \qmlmethod object Qt::include(string url, jsobject callback)
379 Includes another JavaScript file. This method can only be used from within JavaScript files,
380 and not regular QML files.
382 This imports all functions from \a url into the current script's namespace.
384 Qt.include() returns an object that describes the status of the operation. The object has
385 a single property, \c {status}, that is set to one of the following values:
388 \header \li Symbol \li Value \li Description
389 \row \li result.OK \li 0 \li The include completed successfully.
390 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
391 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
392 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
393 An additional \c exception property will be set in this case.
396 The \c status property will be updated as the operation progresses.
398 If provided, \a callback is invoked when the operation completes. The callback is passed
399 the same object as is returned from the Qt.include() call.
401 // Qt.include() is implemented in qv8include.cpp
404 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
405 : propertyCapture(0), rootContext(0), isDebugging(false),
406 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
407 cleanup(0), erroredBindings(0), inProgressCreations(0),
408 workerScriptEngine(0), activeVME(0),
409 networkAccessManager(0), networkAccessManagerFactory(0),
410 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
411 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
415 QQmlEnginePrivate::~QQmlEnginePrivate()
417 if (inProgressCreations)
418 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
421 QQmlCleanup *c = cleanup;
423 if (cleanup) cleanup->prev = &cleanup;
429 doDeleteInEngineThread();
431 if (incubationController) incubationController->d = 0;
432 incubationController = 0;
437 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
439 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
441 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
442 delete (*iter)->qobjectApi;
445 for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
446 iter.value()->isRegisteredWithEngine = false;
449 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
451 QObjectPrivate *p = QObjectPrivate::get(o);
452 if (p->declarativeData) {
453 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
454 if (d->ownContext && d->context) {
455 d->context->destroy();
459 // Mark this object as in the process of deletion to
460 // prevent it resolving in bindings
461 QQmlData::markAsDeleted(o);
465 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
467 static_cast<QQmlData *>(d)->destroyed(o);
470 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
472 static_cast<QQmlData *>(d)->parentChanged(o, p);
475 class QQmlThreadNotifierProxyObject : public QObject
478 QPointer<QObject> target;
480 virtual int qt_metacall(QMetaObject::Call, int id, void **a) {
484 QQmlData *ddata = QQmlData::get(target, false);
485 QQmlNotifierEndpoint *ep = ddata->notify(id);
486 if (ep) QQmlNotifier::emitNotify(ep, a);
494 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
496 QQmlData *ddata = QQmlData::get(object, false);
497 if (!ddata) return; // Probably being deleted
499 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
500 // that they're exposed to. However, to make writing "worker objects" that calculate data
501 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
502 // QQmlEngine to emit signals from a different thread. These signals are then automatically
503 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
504 // by the qqmlecmascript::threadSignal() autotest.
505 if (ddata->notifyList &&
506 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
508 if (!QObjectPrivate::get(object)->threadData->thread)
511 QMetaMethod m = object->metaObject()->method(index);
512 QList<QByteArray> parameterTypes = m.parameterTypes();
514 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
515 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
517 types[0] = 0; // return type
518 args[0] = 0; // return value
520 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
521 const QByteArray &typeName = parameterTypes.at(ii);
522 if (typeName.endsWith('*'))
523 types[ii + 1] = QMetaType::VoidStar;
525 types[ii + 1] = QMetaType::type(typeName);
527 if (!types[ii + 1]) {
528 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
529 "(Make sure '%s' is registered using qRegisterMetaType().)",
530 typeName.constData(), typeName.constData());
536 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
539 QMetaCallEvent *ev = new QMetaCallEvent(index, 0, 0, object, index,
540 parameterTypes.count() + 1, types, args);
542 QQmlThreadNotifierProxyObject *mpo = new QQmlThreadNotifierProxyObject;
543 mpo->target = object;
544 mpo->moveToThread(QObjectPrivate::get(object)->threadData->thread);
545 QCoreApplication::postEvent(mpo, ev);
548 QQmlNotifierEndpoint *ep = ddata->notify(index);
549 if (ep) QQmlNotifier::emitNotify(ep, a);
553 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
555 return static_cast<QQmlData *>(d)->endpointCount(index);
558 int QQmlData::endpointCount(int index)
561 QQmlNotifierEndpoint *ep = notify(index);
572 void QQmlData::markAsDeleted(QObject *o)
574 QQmlData::setQueuedForDeletion(o);
576 QObjectPrivate *p = QObjectPrivate::get(o);
577 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
578 QQmlData::markAsDeleted(*it);
582 void QQmlData::setQueuedForDeletion(QObject *object)
585 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
586 if (!priv->wasDeleted && priv->declarativeData) {
587 QQmlData *ddata = QQmlData::get(object, false);
588 if (ddata->ownContext && ddata->context)
589 ddata->context->emitDestruction();
590 ddata->isQueuedForDeletion = true;
596 void QQmlEnginePrivate::init()
600 static bool firstTime = true;
602 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
608 qRegisterMetaType<QVariant>("QVariant");
609 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
610 qRegisterMetaType<QJSValue>("QJSValue");
611 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
612 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
613 qRegisterMetaType<QList<int> >("QList<int>");
614 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
616 v8engine()->setEngine(q);
618 rootContext = new QQmlContext(q,true);
620 if (QCoreApplication::instance()->thread() == q->thread() &&
621 QQmlEngineDebugService::isDebuggingEnabled()) {
623 QQmlEngineDebugService::instance()->addEngine(q);
624 QV8DebugService::initialize(v8engine());
625 QV8ProfilerService::initialize();
626 QQmlProfilerService::initialize();
627 QDebugMessageService::instance();
630 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
631 if (!dataLocation.isEmpty())
632 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
633 + QDir::separator() + QLatin1String("QML")
634 + QDir::separator() + QLatin1String("OfflineStorage");
637 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
640 if (!workerScriptEngine)
641 workerScriptEngine = new QQuickWorkerScriptEngine(q);
642 return workerScriptEngine;
649 \brief The QQmlEngine class provides an environment for instantiating QML components.
652 Each QML component is instantiated in a QQmlContext.
653 QQmlContext's are essential for passing data to QML
654 components. In QML, contexts are arranged hierarchically and this
655 hierarchy is managed by the QQmlEngine.
657 Prior to creating any QML components, an application must have
658 created a QQmlEngine to gain access to a QML context. The
659 following example shows how to create a simple Text item.
663 QQmlComponent component(&engine);
664 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
665 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
667 //add item to view, etc
671 In this case, the Text item will be created in the engine's
672 \l {QQmlEngine::rootContext()}{root context}.
674 Note that the QtQuick 1 version is called QDeclarativeEngine.
676 \sa QQmlComponent, QQmlContext
680 Create a new QQmlEngine with the given \a parent.
682 QQmlEngine::QQmlEngine(QObject *parent)
683 : QJSEngine(*new QQmlEnginePrivate(this), parent)
690 Destroys the QQmlEngine.
692 Any QQmlContext's created on this engine will be
693 invalidated, but not destroyed (unless they are parented to the
696 QQmlEngine::~QQmlEngine()
699 if (d->isDebugging) {
700 QQmlEngineDebugService::instance()->remEngine(this);
703 // Emit onDestruction signals for the root context before
704 // we destroy the contexts, engine, Module APIs etc. that
705 // may be required to handle the destruction signal.
706 QQmlContextData::get(rootContext())->emitDestruction();
708 // if we are the parent of any of the qobject module api instances,
709 // we need to remove them from our internal list, in order to prevent
710 // a segfault in engine private dtor.
711 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
712 QObject *currQObjectApi = 0;
713 QQmlMetaType::ModuleApiInstance *currInstance = 0;
714 foreach (const QQmlMetaType::ModuleApi &key, keys) {
715 currInstance = d->moduleApiInstances.value(key);
716 currQObjectApi = currInstance->qobjectApi;
717 if (this->children().contains(currQObjectApi)) {
718 delete currQObjectApi;
720 d->moduleApiInstances.remove(key);
724 if (d->incubationController)
725 d->incubationController->d = 0;
728 /*! \fn void QQmlEngine::quit()
729 This signal is emitted when the QML loaded by the engine would like to quit.
732 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
733 This signal is emitted when \a warnings messages are generated by QML.
737 Clears the engine's internal component cache.
739 This function causes the property metadata of all components previously
740 loaded by the engine to be destroyed. All previously loaded components and
741 the property bindings for all extant objects created from those components will
744 This function returns the engine to a state where it does not contain any loaded
745 component data. This may be useful in order to reload a smaller subset of the
746 previous component set, or to load a new version of a previously loaded component.
748 Once the component cache has been cleared, components must be loaded before
749 any new objects can be created.
751 \sa trimComponentCache()
753 void QQmlEngine::clearComponentCache()
756 d->typeLoader.clearCache();
760 Trims the engine's internal component cache.
762 This function causes the property metadata of any loaded components which are
763 not currently in use to be destroyed.
765 A component is considered to be in use if there are any extant instances of
766 the component itself, any instances of other components that use the component,
767 or any objects instantiated by any of those components.
769 \sa clearComponentCache()
771 void QQmlEngine::trimComponentCache()
774 d->typeLoader.trimCache();
778 Returns the engine's root context.
780 The root context is automatically created by the QQmlEngine.
781 Data that should be available to all QML component instances
782 instantiated by the engine should be put in the root context.
784 Additional data that should only be available to a subset of
785 component instances should be added to sub-contexts parented to the
788 QQmlContext *QQmlEngine::rootContext() const
790 Q_D(const QQmlEngine);
791 return d->rootContext;
795 Sets the \a factory to use for creating QNetworkAccessManager(s).
797 QNetworkAccessManager is used for all network access by QML. By
798 implementing a factory it is possible to create custom
799 QNetworkAccessManager with specialized caching, proxy and cookie
802 The factory must be set before executing the engine.
804 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
807 QMutexLocker locker(&d->mutex);
808 d->networkAccessManagerFactory = factory;
812 Returns the current QQmlNetworkAccessManagerFactory.
814 \sa setNetworkAccessManagerFactory()
816 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
818 Q_D(const QQmlEngine);
819 return d->networkAccessManagerFactory;
822 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
825 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
827 void *args[] = { 0 };
828 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
832 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
834 QMutexLocker locker(&mutex);
835 QNetworkAccessManager *nam;
836 if (networkAccessManagerFactory) {
837 nam = networkAccessManagerFactory->create(parent);
839 nam = new QNetworkAccessManager(parent);
845 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
847 Q_Q(const QQmlEngine);
848 if (!networkAccessManager)
849 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
850 return networkAccessManager;
854 Returns a common QNetworkAccessManager which can be used by any QML
855 element instantiated by this engine.
857 If a QQmlNetworkAccessManagerFactory has been set and a
858 QNetworkAccessManager has not yet been created, the
859 QQmlNetworkAccessManagerFactory will be used to create the
860 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
861 will have no proxy or cache set.
863 \sa setNetworkAccessManagerFactory()
865 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
867 Q_D(const QQmlEngine);
868 return d->getNetworkAccessManager();
873 Sets the \a provider to use for images requested via the \e
874 image: url scheme, with host \a providerId. The QQmlEngine
875 takes ownership of \a provider.
877 Image providers enable support for pixmap and threaded image
878 requests. See the QQuickImageProvider documentation for details on
879 implementing and using image providers.
881 All required image providers should be added to the engine before any
882 QML sources files are loaded.
884 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
886 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
889 QMutexLocker locker(&d->mutex);
890 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
894 Returns the image provider set for \a providerId.
896 Returns the provider if it was found; otherwise returns 0.
898 \sa QQuickImageProvider
900 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
902 Q_D(const QQmlEngine);
903 QMutexLocker locker(&d->mutex);
904 return d->imageProviders.value(providerId).data();
908 Removes the image provider for \a providerId.
910 \sa addImageProvider(), QQuickImageProvider
912 void QQmlEngine::removeImageProvider(const QString &providerId)
915 QMutexLocker locker(&d->mutex);
916 d->imageProviders.take(providerId);
920 Return the base URL for this engine. The base URL is only used to
921 resolve components when a relative URL is passed to the
922 QQmlComponent constructor.
924 If a base URL has not been explicitly set, this method returns the
925 application's current working directory.
929 QUrl QQmlEngine::baseUrl() const
931 Q_D(const QQmlEngine);
932 if (d->baseUrl.isEmpty()) {
933 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
940 Set the base URL for this engine to \a url.
944 void QQmlEngine::setBaseUrl(const QUrl &url)
951 Returns true if warning messages will be output to stderr in addition
952 to being emitted by the warnings() signal, otherwise false.
954 The default value is true.
956 bool QQmlEngine::outputWarningsToStandardError() const
958 Q_D(const QQmlEngine);
959 return d->outputWarningsToStdErr;
963 Set whether warning messages will be output to stderr to \a enabled.
965 If \a enabled is true, any warning messages generated by QML will be
966 output to stderr and emitted by the warnings() signal. If \a enabled
967 is false, on the warnings() signal will be emitted. This allows
968 applications to handle warning output themselves.
970 The default value is true.
972 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
975 d->outputWarningsToStdErr = enabled;
979 Returns the QQmlContext for the \a object, or 0 if no
980 context has been set.
982 When the QQmlEngine instantiates a QObject, the context is
985 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
990 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
993 static_cast<QQmlData *>(priv->declarativeData);
997 else if (data->outerContext)
998 return data->outerContext->asQQmlContext();
1004 Sets the QQmlContext for the \a object to \a context.
1005 If the \a object already has a context, a warning is
1006 output, but the context is not changed.
1008 When the QQmlEngine instantiates a QObject, the context is
1011 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1013 if (!object || !context)
1016 QQmlData *data = QQmlData::get(object, true);
1017 if (data->context) {
1018 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1022 QQmlContextData *contextData = QQmlContextData::get(context);
1023 contextData->addObject(object);
1027 \enum QQmlEngine::ObjectOwnership
1029 Ownership controls whether or not QML automatically destroys the
1030 QObject when the object is garbage collected by the JavaScript
1031 engine. The two ownership options are:
1033 \value CppOwnership The object is owned by C++ code, and will
1034 never be deleted by QML. The JavaScript destroy() method cannot be
1035 used on objects with CppOwnership. This option is similar to
1036 QScriptEngine::QtOwnership.
1038 \value JavaScriptOwnership The object is owned by JavaScript.
1039 When the object is returned to QML as the return value of a method
1040 call or property access, QML will track it, and delete the object
1041 if there are no remaining JavaScript references to it and it has no
1042 QObject::parent(). An object tracked by one QQmlEngine
1043 will be deleted during that QQmlEngine's destructor, and thus
1044 JavaScript references between objects with JavaScriptOwnership from
1045 two different engines will not be valid after the deletion of one of
1046 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1048 Generally an application doesn't need to set an object's ownership
1049 explicitly. QML uses a heuristic to set the default object
1050 ownership. By default, an object that is created by QML has
1051 JavaScriptOwnership. The exception to this are the root objects
1052 created by calling QQmlComponent::create() or
1053 QQmlComponent::beginCreate() which have CppOwnership by
1054 default. The ownership of these root-level objects is considered to
1055 have been transferred to the C++ caller.
1057 Objects not-created by QML have CppOwnership by default. The
1058 exception to this is objects returned from a C++ method call. The
1059 ownership of these objects is passed to JavaScript.
1061 Calling setObjectOwnership() overrides the default ownership
1062 heuristic used by QML.
1066 Sets the \a ownership of \a object.
1068 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1073 QQmlData *ddata = QQmlData::get(object, true);
1077 ddata->indestructible = (ownership == CppOwnership)?true:false;
1078 ddata->explicitIndestructibleSet = true;
1082 Returns the ownership of \a object.
1084 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1087 return CppOwnership;
1089 QQmlData *ddata = QQmlData::get(object, false);
1091 return CppOwnership;
1093 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1096 bool QQmlEngine::event(QEvent *e)
1099 if (e->type() == QEvent::User)
1100 d->doDeleteInEngineThread();
1102 return QJSEngine::event(e);
1105 void QQmlEnginePrivate::doDeleteInEngineThread()
1107 QFieldList<Deletable, &Deletable::next> list;
1109 list.copyAndClear(toDeleteInEngineThread);
1112 while (Deletable *d = list.takeFirst())
1116 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1118 QQmlData *data = QQmlData::get(object);
1120 if (data && data->compiledData && data->deferredIdx) {
1121 QQmlObjectCreatingProfiler prof;
1123 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1124 prof.setTypeName(type ? type->qmlTypeName()
1125 : QString::fromUtf8(object->metaObject()->className()));
1126 if (data->outerContext)
1127 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1129 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1131 QQmlComponentPrivate::ConstructionState state;
1132 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1134 // Release the reference for the deferral action (we still have one from construction)
1135 data->compiledData->release();
1136 data->compiledData = 0;
1138 QQmlComponentPrivate::complete(ep, &state);
1142 QQmlContext *qmlContext(const QObject *obj)
1144 return QQmlEngine::contextForObject(obj);
1147 QQmlEngine *qmlEngine(const QObject *obj)
1149 QQmlData *data = QQmlData::get(obj, false);
1150 if (!data || !data->context)
1152 return data->context->engine;
1155 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1157 QQmlData *data = QQmlData::get(object);
1159 return 0; // Attached properties are only on objects created by QML
1161 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1165 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1169 rv = pf(const_cast<QObject *>(object));
1172 data->attachedProperties()->insert(id, rv);
1177 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1178 const QMetaObject *attachedMetaObject, bool create)
1181 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1183 if (*idCache == -1 || !object)
1186 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1189 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1191 #ifndef QQML_NO_DEBUG_PROTOCOL
1192 if (!QQmlEnginePrivate::qml_debugging_enabled
1194 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1196 QQmlEnginePrivate::qml_debugging_enabled = true;
1201 class QQmlDataExtended {
1204 ~QQmlDataExtended();
1206 QHash<int, QObject *> attachedProperties;
1209 QQmlDataExtended::QQmlDataExtended()
1213 QQmlDataExtended::~QQmlDataExtended()
1217 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1220 layout(endpoint->next);
1222 int index = endpoint->sourceSignal;
1223 index = qMin(index, 0xFFFF - 1);
1225 endpoint->next = notifies[index];
1226 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1227 endpoint->prev = ¬ifies[index];
1228 notifies[index] = endpoint;
1231 void QQmlData::NotifyList::layout()
1233 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1236 QQmlNotifierEndpoint **old = notifies;
1237 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1238 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1239 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1240 sizeof(QQmlNotifierEndpoint*);
1241 memset(notifies + notifiesSize, 0, memsetSize);
1243 if (notifies != old) {
1244 for (int ii = 0; ii < notifiesSize; ++ii)
1246 notifies[ii]->prev = ¬ifies[ii];
1249 notifiesSize = maximumTodoIndex + 1;
1254 maximumTodoIndex = 0;
1258 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1261 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1262 notifyList->connectionMask = 0;
1263 notifyList->maximumTodoIndex = 0;
1264 notifyList->notifiesSize = 0;
1265 notifyList->todo = 0;
1266 notifyList->notifies = 0;
1269 Q_ASSERT(!endpoint->isConnected());
1271 index = qMin(index, 0xFFFF - 1);
1272 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1274 if (index < notifyList->notifiesSize) {
1276 endpoint->next = notifyList->notifies[index];
1277 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1278 endpoint->prev = ¬ifyList->notifies[index];
1279 notifyList->notifies[index] = endpoint;
1282 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1284 endpoint->next = notifyList->todo;
1285 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1286 endpoint->prev = ¬ifyList->todo;
1287 notifyList->todo = endpoint;
1291 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1293 QQmlData *data = QQmlData::get(obj);
1294 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1298 index MUST be the index returned by QMetaMethod::index()
1299 This is different than the index returned by QObjectPrivate::signalIndex()
1301 bool QQmlData::signalHasEndpoint(int index)
1303 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1306 QHash<int, QObject *> *QQmlData::attachedProperties() const
1308 if (!extendedData) extendedData = new QQmlDataExtended;
1309 return &extendedData->attachedProperties;
1312 void QQmlData::destroyed(QObject *object)
1314 if (nextContextObject)
1315 nextContextObject->prevContextObject = prevContextObject;
1316 if (prevContextObject)
1317 *prevContextObject = nextContextObject;
1319 QQmlAbstractBinding *binding = bindings;
1321 QQmlAbstractBinding *next = binding->nextBinding();
1322 binding->setAddedToObject(false);
1323 binding->setNextBinding(0);
1329 compiledData->release();
1333 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1334 while (signalHandler) {
1335 if (signalHandler->isEvaluating()) {
1336 // The object is being deleted during signal handler evaluation.
1337 // This will cause a crash due to invalid memory access when the
1338 // evaluation has completed.
1339 // Abort with a friendly message instead.
1340 QString locationString;
1341 QQmlBoundSignalExpression *expr = signalHandler->expression();
1343 QString fileName = expr->sourceFile();
1344 if (fileName.isEmpty())
1345 fileName = QStringLiteral("<Unknown File>");
1346 locationString.append(fileName);
1347 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1348 QString source = expr->expression();
1349 if (source.size() > 100) {
1350 source.truncate(96);
1351 source.append(QStringLiteral(" ..."));
1353 locationString.append(source);
1355 locationString = QStringLiteral("<Unknown Location>");
1357 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1358 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1359 "instead), or the application is running a nested event loop.\n"
1360 "This behavior is NOT supported!\n"
1361 "%s", object, qPrintable(locationString));
1364 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1365 signalHandler->m_prevSignal = 0;
1366 signalHandler->m_nextSignal = 0;
1367 delete signalHandler;
1368 signalHandler = next;
1375 propertyCache->release();
1377 if (ownContext && context)
1381 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1382 *guard = (QObject *)0;
1383 guard->objectDestroyed(object);
1387 while (notifyList->todo)
1388 notifyList->todo->disconnect();
1389 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1390 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1393 free(notifyList->notifies);
1399 delete extendedData;
1401 // Dispose the handle.
1402 // We don't simply clear it (and wait for next gc cycle to dispose
1403 // via the weak qobject reference callback) as this affects the
1404 // outcomes of v8's gc statistical analysis heuristics, which can
1405 // cause unnecessary growth of the old pointer space js heap area.
1406 qPersistentDispose(v8object);
1412 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1414 void QQmlData::parentChanged(QObject *object, QObject *parent)
1417 if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1421 { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1422 { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1424 qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1425 "User code is attempting to change it to %s.\n"
1426 "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1431 bool QQmlData::hasBindingBit(int bit) const
1433 if (bindingBitsSize > bit)
1434 return bindingBits[bit / 32] & (1 << (bit % 32));
1439 void QQmlData::clearBindingBit(int bit)
1441 if (bindingBitsSize > bit)
1442 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1445 void QQmlData::setBindingBit(QObject *obj, int bit)
1447 if (bindingBitsSize <= bit) {
1448 int props = QQmlMetaObject(obj).propertyCount();
1449 Q_ASSERT(bit < props);
1451 int arraySize = (props + 31) / 32;
1452 int oldArraySize = bindingBitsSize / 32;
1454 bindingBits = (quint32 *)realloc(bindingBits,
1455 arraySize * sizeof(quint32));
1457 memset(bindingBits + oldArraySize,
1459 sizeof(quint32) * (arraySize - oldArraySize));
1461 bindingBitsSize = arraySize * 32;
1464 bindingBits[bit / 32] |= (1 << (bit % 32));
1467 void QQmlEnginePrivate::sendQuit()
1471 if (q->receivers(SIGNAL(quit())) == 0) {
1472 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1476 static void dumpwarning(const QQmlError &error)
1478 QMessageLogger(error.url().toString().toLatin1().constData(),
1479 error.line(), 0).warning().nospace()
1480 << qPrintable(error.toString());
1483 static void dumpwarning(const QList<QQmlError> &errors)
1485 for (int ii = 0; ii < errors.count(); ++ii)
1486 dumpwarning(errors.at(ii));
1489 void QQmlEnginePrivate::warning(const QQmlError &error)
1492 q->warnings(QList<QQmlError>() << error);
1493 if (outputWarningsToStdErr)
1497 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1500 q->warnings(errors);
1501 if (outputWarningsToStdErr)
1502 dumpwarning(errors);
1505 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1508 warning(error->error(q));
1511 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1514 QQmlEnginePrivate::get(engine)->warning(error);
1519 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1522 QQmlEnginePrivate::get(engine)->warning(error);
1527 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1530 QQmlEnginePrivate::get(engine)->warning(error);
1532 dumpwarning(error->error(0));
1535 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1538 engine->warning(error);
1543 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1546 engine->warning(error);
1552 This function should be called prior to evaluation of any js expression,
1553 so that scarce resources are not freed prematurely (eg, if there is a
1554 nested javascript expression).
1556 void QQmlEnginePrivate::referenceScarceResources()
1558 scarceResourcesRefCount += 1;
1562 This function should be called after evaluation of the js expression is
1563 complete, and so the scarce resources may be freed safely.
1565 void QQmlEnginePrivate::dereferenceScarceResources()
1567 Q_ASSERT(scarceResourcesRefCount > 0);
1568 scarceResourcesRefCount -= 1;
1570 // if the refcount is zero, then evaluation of the "top level"
1571 // expression must have completed. We can safely release the
1572 // scarce resources.
1573 if (scarceResourcesRefCount == 0) {
1574 // iterate through the list and release them all.
1575 // note that the actual SRD is owned by the JS engine,
1576 // so we cannot delete the SRD; but we can free the
1577 // memory used by the variant in the SRD.
1578 while (ScarceResourceData *sr = scarceResources.first()) {
1579 sr->data = QVariant();
1580 scarceResources.remove(sr);
1586 Adds \a path as a directory where the engine searches for
1587 installed modules in a URL-based directory structure.
1588 The \a path may be a local filesystem directory or a URL.
1590 The newly added \a path will be first in the importPathList().
1592 \sa setImportPathList(), {QML Modules}
1594 void QQmlEngine::addImportPath(const QString& path)
1597 d->importDatabase.addImportPath(path);
1601 Returns the list of directories where the engine searches for
1602 installed modules in a URL-based directory structure.
1604 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1605 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1606 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1607 provided by that module. A \c qmldir file is required for defining the
1608 type version mapping and possibly QML extensions plugins.
1610 By default, the list contains the directory of the application executable,
1611 paths specified in the \c QML_IMPORT_PATH environment variable,
1612 and the builtin \c ImportsPath from QLibraryInfo.
1614 \sa addImportPath(), setImportPathList()
1616 QStringList QQmlEngine::importPathList() const
1618 Q_D(const QQmlEngine);
1619 return d->importDatabase.importPathList();
1623 Sets \a paths as the list of directories where the engine searches for
1624 installed modules in a URL-based directory structure.
1626 By default, the list contains the directory of the application executable,
1627 paths specified in the \c QML_IMPORT_PATH environment variable,
1628 and the builtin \c ImportsPath from QLibraryInfo.
1630 \sa importPathList(), addImportPath()
1632 void QQmlEngine::setImportPathList(const QStringList &paths)
1635 d->importDatabase.setImportPathList(paths);
1640 Adds \a path as a directory where the engine searches for
1641 native plugins for imported modules (referenced in the \c qmldir file).
1643 By default, the list contains only \c ., i.e. the engine searches
1644 in the directory of the \c qmldir file itself.
1646 The newly added \a path will be first in the pluginPathList().
1648 \sa setPluginPathList()
1650 void QQmlEngine::addPluginPath(const QString& path)
1653 d->importDatabase.addPluginPath(path);
1658 Returns the list of directories where the engine searches for
1659 native plugins for imported modules (referenced in the \c qmldir file).
1661 By default, the list contains only \c ., i.e. the engine searches
1662 in the directory of the \c qmldir file itself.
1664 \sa addPluginPath(), setPluginPathList()
1666 QStringList QQmlEngine::pluginPathList() const
1668 Q_D(const QQmlEngine);
1669 return d->importDatabase.pluginPathList();
1673 Sets the list of directories where the engine searches for
1674 native plugins for imported modules (referenced in the \c qmldir file)
1677 By default, the list contains only \c ., i.e. the engine searches
1678 in the directory of the \c qmldir file itself.
1680 \sa pluginPathList(), addPluginPath()
1682 void QQmlEngine::setPluginPathList(const QStringList &paths)
1685 d->importDatabase.setPluginPathList(paths);
1689 Imports the plugin named \a filePath with the \a uri provided.
1690 Returns true if the plugin was successfully imported; otherwise returns false.
1692 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1694 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1696 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1699 return d->importDatabase.importPlugin(filePath, uri, errors);
1703 \property QQmlEngine::offlineStoragePath
1704 \brief the directory for storing offline user data
1706 Returns the directory where SQL and other offline
1709 QQuickWebView and the SQL databases created with openDatabase()
1712 The default is QML/OfflineStorage in the platform-standard
1713 user application data directory.
1715 Note that the path may not currently exist on the filesystem, so
1716 callers wanting to \e create new files at this location should create
1717 it first - see QDir::mkpath().
1719 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1722 d->offlineStoragePath = dir;
1725 QString QQmlEngine::offlineStoragePath() const
1727 Q_D(const QQmlEngine);
1728 return d->offlineStoragePath;
1731 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1735 if (!mo->superClass()) {
1736 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1737 propertyCache.insert(mo, rv);
1740 QQmlPropertyCache *super = cache(mo->superClass());
1741 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1742 propertyCache.insert(mo, rv);
1747 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1750 QList<QQmlType *> types;
1752 int maxMinorVersion = 0;
1754 const QMetaObject *metaObject = type->metaObject();
1756 while (metaObject) {
1757 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1758 type->majorVersion(), minorVersion);
1760 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1766 metaObject = metaObject->superClass();
1769 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1771 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1775 QQmlPropertyCache *raw = cache(type->metaObject());
1777 bool hasCopied = false;
1779 for (int ii = 0; ii < types.count(); ++ii) {
1780 QQmlType *currentType = types.at(ii);
1784 int rev = currentType->metaObjectRevision();
1785 int moIndex = types.count() - 1 - ii;
1787 if (raw->allowedRevisionCache[moIndex] != rev) {
1792 raw->allowedRevisionCache[moIndex] = rev;
1796 // Test revision compatibility - the basic rule is:
1797 // * Anything that is excluded, cannot overload something that is not excluded *
1799 // Signals override:
1800 // * other signals and methods of the same name.
1801 // * properties named on<Signal Name>
1802 // * automatic <property name>Changed notify signals
1804 // Methods override:
1805 // * other methods of the same name
1807 // Properties override:
1808 // * other elements of the same name
1810 bool overloadError = false;
1811 QString overloadName;
1814 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1815 !overloadError && iter != raw->stringCache.end();
1818 QQmlPropertyData *d = *iter;
1819 if (raw->isAllowedInRevision(d))
1820 continue; // Not excluded - no problems
1822 // check that a regular "name" overload isn't happening
1823 QQmlPropertyData *current = d;
1824 while (!overloadError && current) {
1825 current = d->overrideData(current);
1826 if (current && raw->isAllowedInRevision(current))
1827 overloadError = true;
1832 if (overloadError) {
1833 if (hasCopied) raw->release();
1835 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."));
1839 if (!hasCopied) raw->addref();
1840 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1842 if (minorVersion != maxMinorVersion) {
1844 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1850 QQmlMetaType::ModuleApiInstance *
1851 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1853 Locker locker(this);
1855 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1857 a = new QQmlMetaType::ModuleApiInstance;
1858 a->scriptCallback = module.script;
1859 a->qobjectCallback = module.qobject;
1860 a->instanceMetaObject = module.instanceMetaObject;
1861 moduleApiInstances.insert(module, a);
1867 bool QQmlEnginePrivate::isQObject(int t)
1869 Locker locker(this);
1870 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1873 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1875 Locker locker(this);
1876 int t = v.userType();
1877 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1879 return *(QObject **)(v.constData());
1881 return QQmlMetaType::toQObject(v, ok);
1885 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1887 Locker locker(this);
1888 if (m_compositeTypes.contains(t))
1889 return QQmlMetaType::Object;
1890 else if (m_qmlLists.contains(t))
1891 return QQmlMetaType::List;
1893 return QQmlMetaType::typeCategory(t);
1896 bool QQmlEnginePrivate::isList(int t) const
1898 Locker locker(this);
1899 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1902 int QQmlEnginePrivate::listType(int t) const
1904 Locker locker(this);
1905 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1906 if (iter != m_qmlLists.end())
1909 return QQmlMetaType::listType(t);
1912 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1914 Locker locker(this);
1915 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1916 if (iter != m_compositeTypes.end()) {
1917 return QQmlMetaObject((*iter)->rootPropertyCache);
1919 QQmlType *type = QQmlMetaType::qmlType(t);
1920 return QQmlMetaObject(type?type->baseMetaObject():0);
1924 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1926 Locker locker(this);
1927 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1928 if (iter != m_compositeTypes.end()) {
1929 return QQmlMetaObject((*iter)->rootPropertyCache);
1931 QQmlType *type = QQmlMetaType::qmlType(t);
1932 return QQmlMetaObject(type?type->metaObject():0);
1936 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1938 Locker locker(this);
1939 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1940 if (iter != m_compositeTypes.end()) {
1941 return (*iter)->rootPropertyCache;
1943 QQmlType *type = QQmlMetaType::qmlType(t);
1945 return type?cache(type->metaObject()):0;
1949 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1951 Locker locker(this);
1952 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1953 if (iter != m_compositeTypes.end()) {
1954 return (*iter)->rootPropertyCache;
1956 QQmlType *type = QQmlMetaType::qmlType(t);
1958 return type?cache(type->baseMetaObject()):0;
1962 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1964 QByteArray name = data->rootPropertyCache->className();
1966 QByteArray ptr = name + '*';
1967 QByteArray lst = "QQmlListProperty<" + name + '>';
1969 int ptr_type = QMetaType::registerNormalizedType(ptr,
1970 qMetaTypeDeleteHelper<QObject*>,
1971 qMetaTypeCreateHelper<QObject*>,
1972 qMetaTypeDestructHelper<QObject*>,
1973 qMetaTypeConstructHelper<QObject*>,
1975 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1977 int lst_type = QMetaType::registerNormalizedType(lst,
1978 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1979 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1980 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1981 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1982 sizeof(QQmlListProperty<QObject>),
1983 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
1984 static_cast<QMetaObject*>(0));
1986 data->metaTypeId = ptr_type;
1987 data->listMetaTypeId = lst_type;
1988 data->isRegisteredWithEngine = true;
1990 Locker locker(this);
1991 m_qmlLists.insert(lst_type, ptr_type);
1992 // The QQmlCompiledData is not referenced here, but it is removed from this
1993 // hash in the QQmlCompiledData destructor
1994 m_compositeTypes.insert(ptr_type, data);
1997 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
1999 int ptr_type = data->metaTypeId;
2000 int lst_type = data->listMetaTypeId;
2002 Locker locker(this);
2003 m_qmlLists.remove(lst_type);
2004 m_compositeTypes.remove(ptr_type);
2007 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2009 return typeLoader.isTypeLoaded(url);
2012 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2014 return typeLoader.isScriptLoaded(url);
2017 bool QQml_isFileCaseCorrect(const QString &fileName)
2019 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2020 QFileInfo info(fileName);
2021 const QString absolute = info.absoluteFilePath();
2023 #if defined(Q_OS_MAC)
2024 const QString canonical = info.canonicalFilePath();
2025 #elif defined(Q_OS_WIN)
2026 wchar_t buffer[1024];
2028 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2029 if (rv == 0 || rv >= 1024) return true;
2030 rv = ::GetLongPathName(buffer, buffer, 1024);
2031 if (rv == 0 || rv >= 1024) return true;
2033 const QString canonical = QString::fromWCharArray(buffer);
2036 const int absoluteLength = absolute.length();
2037 const int canonicalLength = canonical.length();
2039 const int length = qMin(absoluteLength, canonicalLength);
2040 for (int ii = 0; ii < length; ++ii) {
2041 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2042 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2044 if (a.toLower() != c.toLower())
2056 \fn QQmlEngine *qmlEngine(const QObject *object)
2059 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2060 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2064 \fn QQmlContext *qmlContext(const QObject *object)
2067 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2068 QQmlEngine::contextForObject(object).