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 \ingroup qml-utility-elements
114 \brief The QtObject element is the most basic element in QML.
116 The QtObject element is a non-visual element which contains only the
119 It can be useful to create a QtObject if you need an extremely
120 lightweight element to enclose a set of custom properties:
122 \snippet doc/snippets/qml/qtobject.qml 0
124 It can also be useful for C++ integration, as it is just a plain
125 QObject. See the QObject documentation for further details.
128 \qmlproperty string QtObject::objectName
129 This property holds the QObject::objectName for this specific object instance.
131 This allows a C++ application to locate an item within a QML component
132 using the QObject::findChild() method. For example, the following C++
133 application locates the child \l Rectangle item and dynamically changes its
142 width: 200; height: 200
156 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
159 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
161 item->setProperty("color", QColor(Qt::yellow));
165 bool QQmlEnginePrivate::qml_debugging_enabled = false;
167 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
169 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
170 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
171 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
172 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
173 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
176 void QQmlEnginePrivate::defineModule()
178 registerBaseTypes("QtQuick", 2, 0);
179 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
184 \class QQmlImageProviderBase
185 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
188 Image providers must be registered with the QML engine. The only information the QML
189 engine knows about image providers is the type of image data they provide. To use an
190 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
191 to a QQuickImageProvider pointer.
193 \sa QQuickImageProvider, QQuickTextureFactory
197 \enum QQmlImageProviderBase::ImageType
199 Defines the type of image supported by this image provider.
201 \value Image The Image Provider provides QImage images.
202 The QQuickImageProvider::requestImage() method will be called for all image requests.
203 \value Pixmap The Image Provider provides QPixmap images.
204 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
205 \value Texture The Image Provider provides QSGTextureProvider based images.
206 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
210 \enum QQmlImageProviderBase::Flag
212 Defines specific requirements or features of this image provider.
214 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
215 run in a separate thread, which allows the provider to spend as much time as needed
216 on producing the image without blocking the main thread.
220 QQmlImageProviderBase::QQmlImageProviderBase()
225 QQmlImageProviderBase::~QQmlImageProviderBase()
231 \qmlclass Qt QQmlEnginePrivate
232 \ingroup qml-utility-elements
233 \brief The QML global Qt object provides useful enums and functions from Qt.
235 \keyword QmlGlobalQtObject
237 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
239 The \c Qt object is a global object with utility functions, properties and enums.
241 It is not instantiable; to use it, call the members of the global \c Qt object directly.
248 color: Qt.rgba(1, 0, 0, 1)
249 text: Qt.md5("hello, world")
256 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
257 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
261 The Qt object also contains helper functions for creating objects of specific
262 data types. This is primarily useful when setting the properties of an item
263 when the property has one of the following types:
266 \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()}
267 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
268 \li \c point - use \l{Qt::point()}{Qt.point()}
269 \li \c size - use \l{Qt::size()}{Qt.size()}
270 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
273 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
275 \section1 Date/Time Formatters
277 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
280 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
281 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
282 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
285 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
288 \section1 Dynamic Object Creation
289 The following functions on the global object allow you to dynamically create QML
290 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
294 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
295 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
299 \section1 Other Functions
301 The following functions are also on the Qt object.
304 \li \l{Qt::quit()}{Qt.quit()}
305 \li \l{Qt::md5()}{Qt.md5(string)}
306 \li \l{Qt::btoa()}{string Qt.btoa(string)}
307 \li \l{Qt::atob()}{string Qt.atob(string)}
308 \li \l{Qt::binding()}{object Qt.binding(function)}
309 \li \l{Qt::locale()}{object Qt.locale()}
310 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
311 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
312 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
317 \qmlproperty object Qt::application
320 The \c application object provides access to global application state
321 properties shared by many QML components.
327 \li \c application.active
329 This read-only property indicates whether the application is the top-most and focused
330 application, and the user is able to interact with the application. The property
331 is false when the application is in the background, the device keylock or screen
332 saver is active, the screen backlight is turned off, or the global system dialog
333 is being displayed on top of the application. It can be used for stopping and
334 pausing animations, timers and active processing of data in order to save device
335 battery power and free device memory and processor load when the application is not
339 \li \c application.layoutDirection
341 This read-only property can be used to query the default layout direction of the
342 application. On system start-up, the default layout direction depends on the
343 application's language. The property has a value of \c Qt.RightToLeft in locales
344 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
345 where the reading direction flows from left to right. You can bind to this
346 property to customize your application layouts to support both layout directions.
351 \li Qt.LeftToRight - Text and graphics elements should be positioned
353 \li Qt.RightToLeft - Text and graphics elements should be positioned
357 The following example uses the \c application object to indicate
358 whether the application is currently active:
360 \snippet doc/snippets/qml/application.qml document
362 \qmlproperty object Qt::inputMethod
365 The \c inputMethod object allows access to application's QInputMethod object
366 and all its properties and slots. See the QInputMethod documentation for
372 \qmlmethod object Qt::include(string url, jsobject callback)
374 Includes another JavaScript file. This method can only be used from within JavaScript files,
375 and not regular QML files.
377 This imports all functions from \a url into the current script's namespace.
379 Qt.include() returns an object that describes the status of the operation. The object has
380 a single property, \c {status}, that is set to one of the following values:
383 \header \li Symbol \li Value \li Description
384 \row \li result.OK \li 0 \li The include completed successfully.
385 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
386 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
387 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
388 An additional \c exception property will be set in this case.
391 The \c status property will be updated as the operation progresses.
393 If provided, \a callback is invoked when the operation completes. The callback is passed
394 the same object as is returned from the Qt.include() call.
396 // Qt.include() is implemented in qv8include.cpp
399 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
400 : propertyCapture(0), rootContext(0), isDebugging(false),
401 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
402 cleanup(0), erroredBindings(0), inProgressCreations(0),
403 workerScriptEngine(0), activeVME(0),
404 networkAccessManager(0), networkAccessManagerFactory(0),
405 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
406 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
410 QQmlEnginePrivate::~QQmlEnginePrivate()
412 if (inProgressCreations)
413 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
416 QQmlCleanup *c = cleanup;
418 if (cleanup) cleanup->prev = &cleanup;
424 doDeleteInEngineThread();
426 if (incubationController) incubationController->d = 0;
427 incubationController = 0;
432 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
434 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
436 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
438 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
439 delete (*iter)->qobjectApi;
444 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
446 QObjectPrivate *p = QObjectPrivate::get(o);
447 if (p->declarativeData) {
448 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
449 if (d->ownContext && d->context) {
450 d->context->destroy();
454 // Mark this object as in the process of deletion to
455 // prevent it resolving in bindings
456 QQmlData::markAsDeleted(o);
460 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
462 static_cast<QQmlData *>(d)->destroyed(o);
465 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
467 static_cast<QQmlData *>(d)->parentChanged(o, p);
470 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
472 QQmlData *ddata = QQmlData::get(object, false);
473 if (!ddata) return; // Probably being deleted
475 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
476 // that they're exposed to. However, to make writing "worker objects" that calculate data
477 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
478 // QQmlEngine to emit signals from a different thread. These signals are then automatically
479 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
480 // by the qqmlecmascript::threadSignal() autotest.
481 if (ddata->notifyList &&
482 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
484 QMetaMethod m = object->metaObject()->method(index);
485 QList<QByteArray> parameterTypes = m.parameterTypes();
487 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
488 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
490 types[0] = 0; // return type
491 args[0] = 0; // return value
493 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
494 const QByteArray &typeName = parameterTypes.at(ii);
495 if (typeName.endsWith('*'))
496 types[ii + 1] = QMetaType::VoidStar;
498 types[ii + 1] = QMetaType::type(typeName);
500 if (!types[ii + 1]) {
501 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
502 "(Make sure '%s' is registered using qRegisterMetaType().)",
503 typeName.constData(), typeName.constData());
509 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
512 QMetaCallEvent *ev = new QMetaCallEvent(index, 0, 0, object, index,
513 parameterTypes.count() + 1, types, args);
514 QCoreApplication::postEvent(object, ev);
517 QQmlNotifierEndpoint *ep = ddata->notify(index);
518 if (ep) QQmlNotifier::emitNotify(ep, a);
522 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
524 return static_cast<QQmlData *>(d)->endpointCount(index);
527 int QQmlData::endpointCount(int index)
530 QQmlNotifierEndpoint *ep = notify(index);
541 void QQmlData::markAsDeleted(QObject *o)
543 QQmlData::setQueuedForDeletion(o);
545 QObjectPrivate *p = QObjectPrivate::get(o);
546 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
547 QQmlData::markAsDeleted(*it);
551 void QQmlData::setQueuedForDeletion(QObject *object)
554 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
555 if (!priv->wasDeleted && priv->declarativeData) {
556 QQmlData *ddata = QQmlData::get(object, false);
557 if (ddata->ownContext && ddata->context)
558 ddata->context->emitDestruction();
559 ddata->isQueuedForDeletion = true;
565 void QQmlEnginePrivate::init()
569 static bool firstTime = true;
571 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
577 qRegisterMetaType<QVariant>("QVariant");
578 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
579 qRegisterMetaType<QJSValue>("QJSValue");
580 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
581 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
582 qRegisterMetaType<QList<int> >("QList<int>");
583 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
585 v8engine()->setEngine(q);
587 rootContext = new QQmlContext(q,true);
589 if (QCoreApplication::instance()->thread() == q->thread() &&
590 QQmlEngineDebugService::isDebuggingEnabled()) {
592 QQmlEngineDebugService::instance()->addEngine(q);
593 QV8DebugService::initialize(v8engine());
594 QV8ProfilerService::initialize();
595 QQmlProfilerService::initialize();
596 QDebugMessageService::instance();
599 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
600 if (!dataLocation.isEmpty())
601 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
602 + QDir::separator() + QLatin1String("QML")
603 + QDir::separator() + QLatin1String("OfflineStorage");
606 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
609 if (!workerScriptEngine)
610 workerScriptEngine = new QQuickWorkerScriptEngine(q);
611 return workerScriptEngine;
618 \brief The QQmlEngine class provides an environment for instantiating QML components.
621 Each QML component is instantiated in a QQmlContext.
622 QQmlContext's are essential for passing data to QML
623 components. In QML, contexts are arranged hierarchically and this
624 hierarchy is managed by the QQmlEngine.
626 Prior to creating any QML components, an application must have
627 created a QQmlEngine to gain access to a QML context. The
628 following example shows how to create a simple Text item.
632 QQmlComponent component(&engine);
633 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
634 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
636 //add item to view, etc
640 In this case, the Text item will be created in the engine's
641 \l {QQmlEngine::rootContext()}{root context}.
643 Note that the QtQuick 1 version is called QDeclarativeEngine.
645 \sa QQmlComponent, QQmlContext
649 Create a new QQmlEngine with the given \a parent.
651 QQmlEngine::QQmlEngine(QObject *parent)
652 : QJSEngine(*new QQmlEnginePrivate(this), parent)
659 Destroys the QQmlEngine.
661 Any QQmlContext's created on this engine will be
662 invalidated, but not destroyed (unless they are parented to the
665 QQmlEngine::~QQmlEngine()
668 if (d->isDebugging) {
669 QQmlEngineDebugService::instance()->remEngine(this);
672 // Emit onDestruction signals for the root context before
673 // we destroy the contexts, engine, Module APIs etc. that
674 // may be required to handle the destruction signal.
675 QQmlContextData::get(rootContext())->emitDestruction();
677 // if we are the parent of any of the qobject module api instances,
678 // we need to remove them from our internal list, in order to prevent
679 // a segfault in engine private dtor.
680 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
681 QObject *currQObjectApi = 0;
682 QQmlMetaType::ModuleApiInstance *currInstance = 0;
683 foreach (const QQmlMetaType::ModuleApi &key, keys) {
684 currInstance = d->moduleApiInstances.value(key);
685 currQObjectApi = currInstance->qobjectApi;
686 if (this->children().contains(currQObjectApi)) {
687 delete currQObjectApi;
689 d->moduleApiInstances.remove(key);
693 if (d->incubationController)
694 d->incubationController->d = 0;
697 /*! \fn void QQmlEngine::quit()
698 This signal is emitted when the QML loaded by the engine would like to quit.
701 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
702 This signal is emitted when \a warnings messages are generated by QML.
706 Clears the engine's internal component cache.
708 This function causes the property metadata of all components previously
709 loaded by the engine to be destroyed. All previously loaded components and
710 the property bindings for all extant objects created from those components will
713 This function returns the engine to a state where it does not contain any loaded
714 component data. This may be useful in order to reload a smaller subset of the
715 previous component set, or to load a new version of a previously loaded component.
717 Once the component cache has been cleared, components must be loaded before
718 any new objects can be created.
720 void QQmlEngine::clearComponentCache()
723 d->typeLoader.clearCache();
727 Returns the engine's root context.
729 The root context is automatically created by the QQmlEngine.
730 Data that should be available to all QML component instances
731 instantiated by the engine should be put in the root context.
733 Additional data that should only be available to a subset of
734 component instances should be added to sub-contexts parented to the
737 QQmlContext *QQmlEngine::rootContext() const
739 Q_D(const QQmlEngine);
740 return d->rootContext;
744 Sets the \a factory to use for creating QNetworkAccessManager(s).
746 QNetworkAccessManager is used for all network access by QML. By
747 implementing a factory it is possible to create custom
748 QNetworkAccessManager with specialized caching, proxy and cookie
751 The factory must be set before executing the engine.
753 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
756 QMutexLocker locker(&d->mutex);
757 d->networkAccessManagerFactory = factory;
761 Returns the current QQmlNetworkAccessManagerFactory.
763 \sa setNetworkAccessManagerFactory()
765 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
767 Q_D(const QQmlEngine);
768 return d->networkAccessManagerFactory;
771 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
774 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
776 void *args[] = { 0 };
777 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
781 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
783 QMutexLocker locker(&mutex);
784 QNetworkAccessManager *nam;
785 if (networkAccessManagerFactory) {
786 nam = networkAccessManagerFactory->create(parent);
788 nam = new QNetworkAccessManager(parent);
794 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
796 Q_Q(const QQmlEngine);
797 if (!networkAccessManager)
798 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
799 return networkAccessManager;
803 Returns a common QNetworkAccessManager which can be used by any QML
804 element instantiated by this engine.
806 If a QQmlNetworkAccessManagerFactory has been set and a
807 QNetworkAccessManager has not yet been created, the
808 QQmlNetworkAccessManagerFactory will be used to create the
809 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
810 will have no proxy or cache set.
812 \sa setNetworkAccessManagerFactory()
814 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
816 Q_D(const QQmlEngine);
817 return d->getNetworkAccessManager();
822 Sets the \a provider to use for images requested via the \e
823 image: url scheme, with host \a providerId. The QQmlEngine
824 takes ownership of \a provider.
826 Image providers enable support for pixmap and threaded image
827 requests. See the QQuickImageProvider documentation for details on
828 implementing and using image providers.
830 All required image providers should be added to the engine before any
831 QML sources files are loaded.
833 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
835 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
838 QMutexLocker locker(&d->mutex);
839 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
843 Returns the image provider set for \a providerId.
845 Returns the provider if it was found; otherwise returns 0.
847 \sa QQuickImageProvider
849 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
851 Q_D(const QQmlEngine);
852 QMutexLocker locker(&d->mutex);
853 return d->imageProviders.value(providerId).data();
857 Removes the image provider for \a providerId.
859 \sa addImageProvider(), QQuickImageProvider
861 void QQmlEngine::removeImageProvider(const QString &providerId)
864 QMutexLocker locker(&d->mutex);
865 d->imageProviders.take(providerId);
869 Return the base URL for this engine. The base URL is only used to
870 resolve components when a relative URL is passed to the
871 QQmlComponent constructor.
873 If a base URL has not been explicitly set, this method returns the
874 application's current working directory.
878 QUrl QQmlEngine::baseUrl() const
880 Q_D(const QQmlEngine);
881 if (d->baseUrl.isEmpty()) {
882 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
889 Set the base URL for this engine to \a url.
893 void QQmlEngine::setBaseUrl(const QUrl &url)
900 Returns true if warning messages will be output to stderr in addition
901 to being emitted by the warnings() signal, otherwise false.
903 The default value is true.
905 bool QQmlEngine::outputWarningsToStandardError() const
907 Q_D(const QQmlEngine);
908 return d->outputWarningsToStdErr;
912 Set whether warning messages will be output to stderr to \a enabled.
914 If \a enabled is true, any warning messages generated by QML will be
915 output to stderr and emitted by the warnings() signal. If \a enabled
916 is false, on the warnings() signal will be emitted. This allows
917 applications to handle warning output themselves.
919 The default value is true.
921 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
924 d->outputWarningsToStdErr = enabled;
928 Attempt to free unused memory.
930 void QQmlEngine::collectGarbage()
936 Returns the QQmlContext for the \a object, or 0 if no
937 context has been set.
939 When the QQmlEngine instantiates a QObject, the context is
942 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
947 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
950 static_cast<QQmlData *>(priv->declarativeData);
954 else if (data->outerContext)
955 return data->outerContext->asQQmlContext();
961 Sets the QQmlContext for the \a object to \a context.
962 If the \a object already has a context, a warning is
963 output, but the context is not changed.
965 When the QQmlEngine instantiates a QObject, the context is
968 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
970 if (!object || !context)
973 QQmlData *data = QQmlData::get(object, true);
975 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
979 QQmlContextData *contextData = QQmlContextData::get(context);
980 contextData->addObject(object);
984 \enum QQmlEngine::ObjectOwnership
986 Ownership controls whether or not QML automatically destroys the
987 QObject when the object is garbage collected by the JavaScript
988 engine. The two ownership options are:
990 \value CppOwnership The object is owned by C++ code, and will
991 never be deleted by QML. The JavaScript destroy() method cannot be
992 used on objects with CppOwnership. This option is similar to
993 QScriptEngine::QtOwnership.
995 \value JavaScriptOwnership The object is owned by JavaScript.
996 When the object is returned to QML as the return value of a method
997 call or property access, QML will track it, and delete the object
998 if there are no remaining JavaScript references to it and it has no
999 QObject::parent(). An object tracked by one QQmlEngine
1000 will be deleted during that QQmlEngine's destructor, and thus
1001 JavaScript references between objects with JavaScriptOwnership from
1002 two different engines will not be valid after the deletion of one of
1003 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1005 Generally an application doesn't need to set an object's ownership
1006 explicitly. QML uses a heuristic to set the default object
1007 ownership. By default, an object that is created by QML has
1008 JavaScriptOwnership. The exception to this are the root objects
1009 created by calling QQmlComponent::create() or
1010 QQmlComponent::beginCreate() which have CppOwnership by
1011 default. The ownership of these root-level objects is considered to
1012 have been transferred to the C++ caller.
1014 Objects not-created by QML have CppOwnership by default. The
1015 exception to this is objects returned from a C++ method call. The
1016 ownership of these objects is passed to JavaScript.
1018 Calling setObjectOwnership() overrides the default ownership
1019 heuristic used by QML.
1023 Sets the \a ownership of \a object.
1025 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1030 QQmlData *ddata = QQmlData::get(object, true);
1034 ddata->indestructible = (ownership == CppOwnership)?true:false;
1035 ddata->explicitIndestructibleSet = true;
1039 Returns the ownership of \a object.
1041 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1044 return CppOwnership;
1046 QQmlData *ddata = QQmlData::get(object, false);
1048 return CppOwnership;
1050 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1053 bool QQmlEngine::event(QEvent *e)
1056 if (e->type() == QEvent::User)
1057 d->doDeleteInEngineThread();
1059 return QJSEngine::event(e);
1062 void QQmlEnginePrivate::doDeleteInEngineThread()
1064 QFieldList<Deletable, &Deletable::next> list;
1066 list.copyAndClear(toDeleteInEngineThread);
1069 while (Deletable *d = list.takeFirst())
1073 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1075 QQmlData *data = QQmlData::get(object);
1077 if (data && data->deferredComponent) {
1078 QQmlObjectCreatingProfiler prof;
1080 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1081 prof.setTypeName(type ? type->qmlTypeName()
1082 : QString::fromUtf8(object->metaObject()->className()));
1083 if (data->outerContext)
1084 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1086 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1088 QQmlComponentPrivate::ConstructionState state;
1089 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1091 data->deferredComponent->release();
1092 data->deferredComponent = 0;
1094 QQmlComponentPrivate::complete(ep, &state);
1098 QQmlContext *qmlContext(const QObject *obj)
1100 return QQmlEngine::contextForObject(obj);
1103 QQmlEngine *qmlEngine(const QObject *obj)
1105 QQmlData *data = QQmlData::get(obj, false);
1106 if (!data || !data->context)
1108 return data->context->engine;
1111 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1113 QQmlData *data = QQmlData::get(object);
1115 return 0; // Attached properties are only on objects created by QML
1117 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1121 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1125 rv = pf(const_cast<QObject *>(object));
1128 data->attachedProperties()->insert(id, rv);
1133 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1134 const QMetaObject *attachedMetaObject, bool create)
1137 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1139 if (*idCache == -1 || !object)
1142 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1145 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1147 #ifndef QQML_NO_DEBUG_PROTOCOL
1148 if (!QQmlEnginePrivate::qml_debugging_enabled
1150 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1152 QQmlEnginePrivate::qml_debugging_enabled = true;
1157 class QQmlDataExtended {
1160 ~QQmlDataExtended();
1162 QHash<int, QObject *> attachedProperties;
1165 QQmlDataExtended::QQmlDataExtended()
1169 QQmlDataExtended::~QQmlDataExtended()
1173 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1176 layout(endpoint->next);
1178 int index = endpoint->sourceSignal;
1179 index = qMin(index, 0xFFFF - 1);
1181 endpoint->next = notifies[index];
1182 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1183 endpoint->prev = ¬ifies[index];
1184 notifies[index] = endpoint;
1187 void QQmlData::NotifyList::layout()
1189 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1192 QQmlNotifierEndpoint **old = notifies;
1193 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1194 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1195 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1196 sizeof(QQmlNotifierEndpoint*);
1197 memset(notifies + notifiesSize, 0, memsetSize);
1199 if (notifies != old) {
1200 for (int ii = 0; ii < notifiesSize; ++ii)
1202 notifies[ii]->prev = ¬ifies[ii];
1205 notifiesSize = maximumTodoIndex + 1;
1210 maximumTodoIndex = 0;
1214 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1217 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1218 notifyList->connectionMask = 0;
1219 notifyList->maximumTodoIndex = 0;
1220 notifyList->notifiesSize = 0;
1221 notifyList->todo = 0;
1222 notifyList->notifies = 0;
1225 Q_ASSERT(!endpoint->isConnected());
1227 index = qMin(index, 0xFFFF - 1);
1228 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1230 if (index < notifyList->notifiesSize) {
1232 endpoint->next = notifyList->notifies[index];
1233 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1234 endpoint->prev = ¬ifyList->notifies[index];
1235 notifyList->notifies[index] = endpoint;
1238 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1240 endpoint->next = notifyList->todo;
1241 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1242 endpoint->prev = ¬ifyList->todo;
1243 notifyList->todo = endpoint;
1247 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1249 QQmlData *data = QQmlData::get(obj);
1250 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1254 index MUST be the index returned by QMetaMethod::index()
1255 This is different than the index returned by QObjectPrivate::signalIndex()
1257 bool QQmlData::signalHasEndpoint(int index)
1259 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1262 QHash<int, QObject *> *QQmlData::attachedProperties() const
1264 if (!extendedData) extendedData = new QQmlDataExtended;
1265 return &extendedData->attachedProperties;
1268 void QQmlData::destroyed(QObject *object)
1270 if (deferredComponent)
1271 deferredComponent->release();
1273 if (nextContextObject)
1274 nextContextObject->prevContextObject = prevContextObject;
1275 if (prevContextObject)
1276 *prevContextObject = nextContextObject;
1278 QQmlAbstractBinding *binding = bindings;
1280 QQmlAbstractBinding *next = binding->m_nextBinding;
1281 binding->m_prevBinding = 0;
1282 binding->m_nextBinding = 0;
1287 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1288 while (signalHandler) {
1289 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1290 signalHandler->m_prevSignal = 0;
1291 signalHandler->m_nextSignal = 0;
1292 delete signalHandler;
1293 signalHandler = next;
1300 propertyCache->release();
1302 if (ownContext && context)
1306 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1307 *guard = (QObject *)0;
1308 guard->objectDestroyed(object);
1312 while (notifyList->todo)
1313 notifyList->todo->disconnect();
1314 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1315 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1318 free(notifyList->notifies);
1324 delete extendedData;
1326 // Dispose the handle.
1327 // We don't simply clear it (and wait for next gc cycle to dispose
1328 // via the weak qobject reference callback) as this affects the
1329 // outcomes of v8's gc statistical analysis heuristics, which can
1330 // cause unnecessary growth of the old pointer space js heap area.
1331 qPersistentDispose(v8object);
1337 void QQmlData::parentChanged(QObject *object, QObject *parent)
1343 bool QQmlData::hasBindingBit(int bit) const
1345 if (bindingBitsSize > bit)
1346 return bindingBits[bit / 32] & (1 << (bit % 32));
1351 void QQmlData::clearBindingBit(int bit)
1353 if (bindingBitsSize > bit)
1354 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1357 void QQmlData::setBindingBit(QObject *obj, int bit)
1359 if (bindingBitsSize <= bit) {
1360 int props = obj->metaObject()->propertyCount();
1361 Q_ASSERT(bit < props);
1363 int arraySize = (props + 31) / 32;
1364 int oldArraySize = bindingBitsSize / 32;
1366 bindingBits = (quint32 *)realloc(bindingBits,
1367 arraySize * sizeof(quint32));
1369 memset(bindingBits + oldArraySize,
1371 sizeof(quint32) * (arraySize - oldArraySize));
1373 bindingBitsSize = arraySize * 32;
1376 bindingBits[bit / 32] |= (1 << (bit % 32));
1379 void QQmlEnginePrivate::sendQuit()
1383 if (q->receivers(SIGNAL(quit())) == 0) {
1384 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1388 static void dumpwarning(const QQmlError &error)
1390 QMessageLogger(error.url().toString().toLatin1().constData(),
1391 error.line(), 0).warning().nospace()
1392 << qPrintable(error.toString());
1395 static void dumpwarning(const QList<QQmlError> &errors)
1397 for (int ii = 0; ii < errors.count(); ++ii)
1398 dumpwarning(errors.at(ii));
1401 void QQmlEnginePrivate::warning(const QQmlError &error)
1404 q->warnings(QList<QQmlError>() << error);
1405 if (outputWarningsToStdErr)
1409 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1412 q->warnings(errors);
1413 if (outputWarningsToStdErr)
1414 dumpwarning(errors);
1417 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1420 QQmlEnginePrivate::get(engine)->warning(error);
1425 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1428 QQmlEnginePrivate::get(engine)->warning(error);
1433 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1436 engine->warning(error);
1441 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1444 engine->warning(error);
1450 This function should be called prior to evaluation of any js expression,
1451 so that scarce resources are not freed prematurely (eg, if there is a
1452 nested javascript expression).
1454 void QQmlEnginePrivate::referenceScarceResources()
1456 scarceResourcesRefCount += 1;
1460 This function should be called after evaluation of the js expression is
1461 complete, and so the scarce resources may be freed safely.
1463 void QQmlEnginePrivate::dereferenceScarceResources()
1465 Q_ASSERT(scarceResourcesRefCount > 0);
1466 scarceResourcesRefCount -= 1;
1468 // if the refcount is zero, then evaluation of the "top level"
1469 // expression must have completed. We can safely release the
1470 // scarce resources.
1471 if (scarceResourcesRefCount == 0) {
1472 // iterate through the list and release them all.
1473 // note that the actual SRD is owned by the JS engine,
1474 // so we cannot delete the SRD; but we can free the
1475 // memory used by the variant in the SRD.
1476 while (ScarceResourceData *sr = scarceResources.first()) {
1477 sr->data = QVariant();
1478 scarceResources.remove(sr);
1484 Adds \a path as a directory where the engine searches for
1485 installed modules in a URL-based directory structure.
1486 The \a path may be a local filesystem directory or a URL.
1488 The newly added \a path will be first in the importPathList().
1490 \sa setImportPathList(), {QML Modules}
1492 void QQmlEngine::addImportPath(const QString& path)
1495 d->importDatabase.addImportPath(path);
1499 Returns the list of directories where the engine searches for
1500 installed modules in a URL-based directory structure.
1502 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1503 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1504 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1505 provided by that module. A \c qmldir file is required for defining the
1506 type version mapping and possibly QML extensions plugins.
1508 By default, the list contains the directory of the application executable,
1509 paths specified in the \c QML_IMPORT_PATH environment variable,
1510 and the builtin \c ImportsPath from QLibraryInfo.
1512 \sa addImportPath(), setImportPathList()
1514 QStringList QQmlEngine::importPathList() const
1516 Q_D(const QQmlEngine);
1517 return d->importDatabase.importPathList();
1521 Sets \a paths as the list of directories where the engine searches for
1522 installed modules in a URL-based directory structure.
1524 By default, the list contains the directory of the application executable,
1525 paths specified in the \c QML_IMPORT_PATH environment variable,
1526 and the builtin \c ImportsPath from QLibraryInfo.
1528 \sa importPathList(), addImportPath()
1530 void QQmlEngine::setImportPathList(const QStringList &paths)
1533 d->importDatabase.setImportPathList(paths);
1538 Adds \a path as a directory where the engine searches for
1539 native plugins for imported modules (referenced in the \c qmldir file).
1541 By default, the list contains only \c ., i.e. the engine searches
1542 in the directory of the \c qmldir file itself.
1544 The newly added \a path will be first in the pluginPathList().
1546 \sa setPluginPathList()
1548 void QQmlEngine::addPluginPath(const QString& path)
1551 d->importDatabase.addPluginPath(path);
1556 Returns the list of directories where the engine searches for
1557 native plugins for imported modules (referenced in the \c qmldir file).
1559 By default, the list contains only \c ., i.e. the engine searches
1560 in the directory of the \c qmldir file itself.
1562 \sa addPluginPath(), setPluginPathList()
1564 QStringList QQmlEngine::pluginPathList() const
1566 Q_D(const QQmlEngine);
1567 return d->importDatabase.pluginPathList();
1571 Sets the list of directories where the engine searches for
1572 native plugins for imported modules (referenced in the \c qmldir file)
1575 By default, the list contains only \c ., i.e. the engine searches
1576 in the directory of the \c qmldir file itself.
1578 \sa pluginPathList(), addPluginPath()
1580 void QQmlEngine::setPluginPathList(const QStringList &paths)
1583 d->importDatabase.setPluginPathList(paths);
1587 Imports the plugin named \a filePath with the \a uri provided.
1588 Returns true if the plugin was successfully imported; otherwise returns false.
1590 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1592 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1594 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1597 return d->importDatabase.importPlugin(filePath, uri, errors);
1601 Imports the plugin named \a filePath with the \a uri provided.
1602 Returns true if the plugin was successfully imported; otherwise returns false.
1604 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1606 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1608 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1611 QList<QQmlError> errors;
1612 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1613 if (!errors.isEmpty()) {
1615 for (int i = 0; i < errors.size(); ++i) {
1616 builtError = QString(QLatin1String("%1\n %2"))
1618 .arg(errors.at(i).toString());
1620 *errorString = builtError;
1626 \property QQmlEngine::offlineStoragePath
1627 \brief the directory for storing offline user data
1629 Returns the directory where SQL and other offline
1632 QQuickWebView and the SQL databases created with openDatabase()
1635 The default is QML/OfflineStorage in the platform-standard
1636 user application data directory.
1638 Note that the path may not currently exist on the filesystem, so
1639 callers wanting to \e create new files at this location should create
1640 it first - see QDir::mkpath().
1642 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1645 d->offlineStoragePath = dir;
1648 QString QQmlEngine::offlineStoragePath() const
1650 Q_D(const QQmlEngine);
1651 return d->offlineStoragePath;
1654 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1658 if (!mo->superClass()) {
1659 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1660 propertyCache.insert(mo, rv);
1663 QQmlPropertyCache *super = cache(mo->superClass());
1664 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1665 propertyCache.insert(mo, rv);
1670 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1673 QList<QQmlType *> types;
1675 int maxMinorVersion = 0;
1677 const QMetaObject *metaObject = type->metaObject();
1679 while (metaObject) {
1680 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1681 type->majorVersion(), minorVersion);
1683 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1689 metaObject = metaObject->superClass();
1692 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1694 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1698 QQmlPropertyCache *raw = cache(type->metaObject());
1700 bool hasCopied = false;
1702 for (int ii = 0; ii < types.count(); ++ii) {
1703 QQmlType *currentType = types.at(ii);
1707 int rev = currentType->metaObjectRevision();
1708 int moIndex = types.count() - 1 - ii;
1710 if (raw->allowedRevisionCache[moIndex] != rev) {
1715 raw->allowedRevisionCache[moIndex] = rev;
1719 // Test revision compatibility - the basic rule is:
1720 // * Anything that is excluded, cannot overload something that is not excluded *
1722 // Signals override:
1723 // * other signals and methods of the same name.
1724 // * properties named on<Signal Name>
1725 // * automatic <property name>Changed notify signals
1727 // Methods override:
1728 // * other methods of the same name
1730 // Properties override:
1731 // * other elements of the same name
1733 bool overloadError = false;
1734 QString overloadName;
1737 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1738 !overloadError && iter != raw->stringCache.end();
1741 QQmlPropertyData *d = *iter;
1742 if (raw->isAllowedInRevision(d))
1743 continue; // Not excluded - no problems
1745 // check that a regular "name" overload isn't happening
1746 QQmlPropertyData *current = d;
1747 while (!overloadError && current) {
1748 current = d->overrideData(current);
1749 if (current && raw->isAllowedInRevision(current))
1750 overloadError = true;
1755 if (overloadError) {
1756 if (hasCopied) raw->release();
1758 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."));
1762 if (!hasCopied) raw->addref();
1763 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1765 if (minorVersion != maxMinorVersion) {
1767 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1773 QQmlMetaType::ModuleApiInstance *
1774 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1776 Locker locker(this);
1778 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1780 a = new QQmlMetaType::ModuleApiInstance;
1781 a->scriptCallback = module.script;
1782 a->qobjectCallback = module.qobject;
1783 a->instanceMetaObject = module.instanceMetaObject;
1784 moduleApiInstances.insert(module, a);
1790 bool QQmlEnginePrivate::isQObject(int t)
1792 Locker locker(this);
1793 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1796 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1798 Locker locker(this);
1799 int t = v.userType();
1800 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1802 return *(QObject **)(v.constData());
1804 return QQmlMetaType::toQObject(v, ok);
1808 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1810 Locker locker(this);
1811 if (m_compositeTypes.contains(t))
1812 return QQmlMetaType::Object;
1813 else if (m_qmlLists.contains(t))
1814 return QQmlMetaType::List;
1816 return QQmlMetaType::typeCategory(t);
1819 bool QQmlEnginePrivate::isList(int t) const
1821 Locker locker(this);
1822 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1825 int QQmlEnginePrivate::listType(int t) const
1827 Locker locker(this);
1828 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1829 if (iter != m_qmlLists.end())
1832 return QQmlMetaType::listType(t);
1835 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1837 Locker locker(this);
1838 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1839 if (iter != m_compositeTypes.end()) {
1840 return (*iter)->root;
1842 QQmlType *type = QQmlMetaType::qmlType(t);
1843 return type?type->baseMetaObject():0;
1847 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1849 Locker locker(this);
1850 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1851 if (iter != m_compositeTypes.end()) {
1852 return (*iter)->root;
1854 QQmlType *type = QQmlMetaType::qmlType(t);
1855 return type?type->metaObject():0;
1859 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1861 QByteArray name = data->root->className();
1863 QByteArray ptr = name + '*';
1864 QByteArray lst = "QQmlListProperty<" + name + '>';
1866 int ptr_type = QMetaType::registerNormalizedType(ptr,
1867 qMetaTypeDeleteHelper<QObject*>,
1868 qMetaTypeCreateHelper<QObject*>,
1869 qMetaTypeDestructHelper<QObject*>,
1870 qMetaTypeConstructHelper<QObject*>,
1872 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1874 int lst_type = QMetaType::registerNormalizedType(lst,
1875 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1876 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1877 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1878 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1879 sizeof(QQmlListProperty<QObject>),
1880 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
1881 static_cast<QMetaObject*>(0));
1885 Locker locker(this);
1886 m_qmlLists.insert(lst_type, ptr_type);
1887 m_compositeTypes.insert(ptr_type, data);
1890 bool QQml_isFileCaseCorrect(const QString &fileName)
1892 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1893 QFileInfo info(fileName);
1894 const QString absolute = info.absoluteFilePath();
1896 #if defined(Q_OS_MAC)
1897 const QString canonical = info.canonicalFilePath();
1898 #elif defined(Q_OS_WIN)
1899 wchar_t buffer[1024];
1901 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1902 if (rv == 0 || rv >= 1024) return true;
1903 rv = ::GetLongPathName(buffer, buffer, 1024);
1904 if (rv == 0 || rv >= 1024) return true;
1906 const QString canonical = QString::fromWCharArray(buffer);
1909 const int absoluteLength = absolute.length();
1910 const int canonicalLength = canonical.length();
1912 const int length = qMin(absoluteLength, canonicalLength);
1913 for (int ii = 0; ii < length; ++ii) {
1914 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1915 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1917 if (a.toLower() != c.toLower())
1929 \fn QQmlEngine *qmlEngine(const QObject *object)
1932 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1933 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1937 \fn QQmlContext *qmlContext(const QObject *object)
1940 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1941 QQmlEngine::contextForObject(object).