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 <QtNetwork/qnetworkconfigmanager.h>
85 #include <private/qobject_p.h>
86 #include <private/qmetaobject_p.h>
88 #include <private/qqmllocale_p.h>
90 #ifdef Q_OS_WIN // for %APPDATA%
91 #include <qt_windows.h>
95 #define CSIDL_APPDATA 0x001a // <username>\Application Data
98 Q_DECLARE_METATYPE(QQmlProperty)
102 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
104 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
105 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
109 \qmlclass QtObject QObject
110 \ingroup qml-utility-elements
112 \brief The QtObject element is the most basic element in QML.
114 The QtObject element is a non-visual element which contains only the
117 It can be useful to create a QtObject if you need an extremely
118 lightweight element to enclose a set of custom properties:
120 \snippet doc/snippets/qml/qtobject.qml 0
122 It can also be useful for C++ integration, as it is just a plain
123 QObject. See the QObject documentation for further details.
126 \qmlproperty string QtObject::objectName
127 This property holds the QObject::objectName for this specific object instance.
129 This allows a C++ application to locate an item within a QML component
130 using the QObject::findChild() method. For example, the following C++
131 application locates the child \l Rectangle item and dynamically changes its
140 width: 200; height: 200
154 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
157 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
159 item->setProperty("color", QColor(Qt::yellow));
163 bool QQmlEnginePrivate::qml_debugging_enabled = false;
165 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
167 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
168 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
169 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
170 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
171 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
174 void QQmlEnginePrivate::defineModule()
176 registerBaseTypes("QtQuick", 2, 0);
177 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
182 \class QQmlImageProviderBase
183 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
186 Image providers must be registered with the QML engine. The only information the QML
187 engine knows about image providers is the type of image data they provide. To use an
188 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
189 to a QQuickImageProvider pointer.
191 \sa QQuickImageProvider, QQuickTextureFactory
195 \enum QQmlImageProviderBase::ImageType
197 Defines the type of image supported by this image provider.
199 \value Image The Image Provider provides QImage images.
200 The QQuickImageProvider::requestImage() method will be called for all image requests.
201 \value Pixmap The Image Provider provides QPixmap images.
202 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
203 \value Texture The Image Provider provides QSGTextureProvider based images.
204 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
208 \enum QQmlImageProviderBase::Flag
210 Defines specific requirements or features of this image provider.
212 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
213 run in a separate thread, which allows the provider to spend as much time as needed
214 on producing the image without blocking the main thread.
218 QQmlImageProviderBase::QQmlImageProviderBase()
223 QQmlImageProviderBase::~QQmlImageProviderBase()
229 \qmlclass Qt QQmlEnginePrivate
230 \ingroup qml-utility-elements
231 \brief The QML global Qt object provides useful enums and functions from Qt.
233 \keyword QmlGlobalQtObject
235 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
237 The \c Qt object is a global object with utility functions, properties and enums.
239 It is not instantiable; to use it, call the members of the global \c Qt object directly.
246 color: Qt.rgba(1, 0, 0, 1)
247 text: Qt.md5("hello, world")
254 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
255 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
259 The Qt object also contains helper functions for creating objects of specific
260 data types. This is primarily useful when setting the properties of an item
261 when the property has one of the following types:
264 \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()}
265 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
266 \li \c point - use \l{Qt::point()}{Qt.point()}
267 \li \c size - use \l{Qt::size()}{Qt.size()}
268 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
271 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
273 \section1 Date/Time Formatters
275 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
278 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
279 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
280 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
283 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
286 \section1 Dynamic Object Creation
287 The following functions on the global object allow you to dynamically create QML
288 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
292 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
293 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
297 \section1 Other Functions
299 The following functions are also on the Qt object.
302 \li \l{Qt::quit()}{Qt.quit()}
303 \li \l{Qt::md5()}{Qt.md5(string)}
304 \li \l{Qt::btoa()}{string Qt.btoa(string)}
305 \li \l{Qt::atob()}{string Qt.atob(string)}
306 \li \l{Qt::binding()}{object Qt.binding(function)}
307 \li \l{Qt::locale()}{object Qt.locale()}
308 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
309 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
310 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
315 \qmlproperty object Qt::application
318 The \c application object provides access to global application state
319 properties shared by many QML components.
325 \li \c application.active
327 This read-only property indicates whether the application is the top-most and focused
328 application, and the user is able to interact with the application. The property
329 is false when the application is in the background, the device keylock or screen
330 saver is active, the screen backlight is turned off, or the global system dialog
331 is being displayed on top of the application. It can be used for stopping and
332 pausing animations, timers and active processing of data in order to save device
333 battery power and free device memory and processor load when the application is not
337 \li \c application.layoutDirection
339 This read-only property can be used to query the default layout direction of the
340 application. On system start-up, the default layout direction depends on the
341 application's language. The property has a value of \c Qt.RightToLeft in locales
342 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
343 where the reading direction flows from left to right. You can bind to this
344 property to customize your application layouts to support both layout directions.
349 \li Qt.LeftToRight - Text and graphics elements should be positioned
351 \li Qt.RightToLeft - Text and graphics elements should be positioned
355 The following example uses the \c application object to indicate
356 whether the application is currently active:
358 \snippet doc/snippets/qml/application.qml document
360 \qmlproperty object Qt::inputMethod
363 The \c inputMethod object allows access to application's QInputMethod object
364 and all its properties and slots. See the QInputMethod documentation for
370 \qmlmethod object Qt::include(string url, jsobject callback)
372 Includes another JavaScript file. This method can only be used from within JavaScript files,
373 and not regular QML files.
375 This imports all functions from \a url into the current script's namespace.
377 Qt.include() returns an object that describes the status of the operation. The object has
378 a single property, \c {status}, that is set to one of the following values:
381 \header \li Symbol \li Value \li Description
382 \row \li result.OK \li 0 \li The include completed successfully.
383 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
384 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
385 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
386 An additional \c exception property will be set in this case.
389 The \c status property will be updated as the operation progresses.
391 If provided, \a callback is invoked when the operation completes. The callback is passed
392 the same object as is returned from the Qt.include() call.
394 // Qt.include() is implemented in qv8include.cpp
397 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
398 : propertyCapture(0), rootContext(0), isDebugging(false),
399 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
400 cleanup(0), erroredBindings(0), inProgressCreations(0),
401 workerScriptEngine(0), activeVME(0),
402 networkAccessManager(0), networkAccessManagerFactory(0),
403 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
404 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
408 QQmlEnginePrivate::~QQmlEnginePrivate()
410 if (inProgressCreations)
411 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
414 QQmlCleanup *c = cleanup;
416 if (cleanup) cleanup->prev = &cleanup;
422 doDeleteInEngineThread();
424 if (incubationController) incubationController->d = 0;
425 incubationController = 0;
430 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
432 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
434 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
436 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
437 delete (*iter)->qobjectApi;
442 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
444 QObjectPrivate *p = QObjectPrivate::get(o);
445 if (p->declarativeData) {
446 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
447 if (d->ownContext && d->context) {
448 d->context->destroy();
452 // Mark this object as in the process of deletion to
453 // prevent it resolving in bindings
454 QQmlData::markAsDeleted(o);
458 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
460 static_cast<QQmlData *>(d)->destroyed(o);
463 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
465 static_cast<QQmlData *>(d)->parentChanged(o, p);
468 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
470 QQmlData *ddata = QQmlData::get(object, false);
471 if (!ddata) return; // Probably being deleted
473 QQmlNotifierEndpoint *ep = ddata->notify(index);
474 if (ep) QQmlNotifier::emitNotify(ep, a);
477 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
479 return static_cast<QQmlData *>(d)->endpointCount(index);
482 int QQmlData::endpointCount(int index)
485 QQmlNotifierEndpoint *ep = notify(index);
496 void QQmlData::markAsDeleted(QObject *o)
498 QQmlData::setQueuedForDeletion(o);
500 QObjectPrivate *p = QObjectPrivate::get(o);
501 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
502 QQmlData::markAsDeleted(*it);
506 void QQmlData::setQueuedForDeletion(QObject *object)
509 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
510 if (!priv->wasDeleted && priv->declarativeData) {
511 QQmlData *ddata = QQmlData::get(object, false);
512 if (ddata->ownContext && ddata->context)
513 ddata->context->emitDestruction();
514 ddata->isQueuedForDeletion = true;
520 void QQmlEnginePrivate::init()
524 static bool firstTime = true;
526 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
532 qRegisterMetaType<QVariant>("QVariant");
533 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
534 qRegisterMetaType<QJSValue>("QJSValue");
535 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
536 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
537 qRegisterMetaType<QList<int> >("QList<int>");
538 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
540 v8engine()->setEngine(q);
542 rootContext = new QQmlContext(q,true);
544 if (QCoreApplication::instance()->thread() == q->thread() &&
545 QQmlEngineDebugService::isDebuggingEnabled()) {
547 QQmlEngineDebugService::instance()->addEngine(q);
548 QV8DebugService::initialize(v8engine());
549 QV8ProfilerService::initialize();
550 QQmlProfilerService::initialize();
551 QDebugMessageService::instance();
554 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
555 if (!dataLocation.isEmpty())
556 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
557 + QDir::separator() + QLatin1String("QML")
558 + QDir::separator() + QLatin1String("OfflineStorage");
561 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
564 if (!workerScriptEngine)
565 workerScriptEngine = new QQuickWorkerScriptEngine(q);
566 return workerScriptEngine;
573 \brief The QQmlEngine class provides an environment for instantiating QML components.
576 Each QML component is instantiated in a QQmlContext.
577 QQmlContext's are essential for passing data to QML
578 components. In QML, contexts are arranged hierarchically and this
579 hierarchy is managed by the QQmlEngine.
581 Prior to creating any QML components, an application must have
582 created a QQmlEngine to gain access to a QML context. The
583 following example shows how to create a simple Text item.
587 QQmlComponent component(&engine);
588 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
589 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
591 //add item to view, etc
595 In this case, the Text item will be created in the engine's
596 \l {QQmlEngine::rootContext()}{root context}.
598 Note that the QtQuick 1 version is called QDeclarativeEngine.
600 \sa QQmlComponent, QQmlContext
604 Create a new QQmlEngine with the given \a parent.
606 QQmlEngine::QQmlEngine(QObject *parent)
607 : QJSEngine(*new QQmlEnginePrivate(this), parent)
614 Destroys the QQmlEngine.
616 Any QQmlContext's created on this engine will be
617 invalidated, but not destroyed (unless they are parented to the
620 QQmlEngine::~QQmlEngine()
623 if (d->isDebugging) {
624 QQmlEngineDebugService::instance()->remEngine(this);
627 // Emit onDestruction signals for the root context before
628 // we destroy the contexts, engine, Module APIs etc. that
629 // may be required to handle the destruction signal.
630 QQmlContextData::get(rootContext())->emitDestruction();
632 // if we are the parent of any of the qobject module api instances,
633 // we need to remove them from our internal list, in order to prevent
634 // a segfault in engine private dtor.
635 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
636 QObject *currQObjectApi = 0;
637 QQmlMetaType::ModuleApiInstance *currInstance = 0;
638 foreach (const QQmlMetaType::ModuleApi &key, keys) {
639 currInstance = d->moduleApiInstances.value(key);
640 currQObjectApi = currInstance->qobjectApi;
641 if (this->children().contains(currQObjectApi)) {
642 delete currQObjectApi;
644 d->moduleApiInstances.remove(key);
648 if (d->incubationController)
649 d->incubationController->d = 0;
652 /*! \fn void QQmlEngine::quit()
653 This signal is emitted when the QML loaded by the engine would like to quit.
656 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
657 This signal is emitted when \a warnings messages are generated by QML.
661 Clears the engine's internal component cache.
663 This function causes the property metadata of all components previously
664 loaded by the engine to be destroyed. All previously loaded components and
665 the property bindings for all extant objects created from those components will
668 This function returns the engine to a state where it does not contain any loaded
669 component data. This may be useful in order to reload a smaller subset of the
670 previous component set, or to load a new version of a previously loaded component.
672 Once the component cache has been cleared, components must be loaded before
673 any new objects can be created.
675 void QQmlEngine::clearComponentCache()
678 d->typeLoader.clearCache();
682 Returns the engine's root context.
684 The root context is automatically created by the QQmlEngine.
685 Data that should be available to all QML component instances
686 instantiated by the engine should be put in the root context.
688 Additional data that should only be available to a subset of
689 component instances should be added to sub-contexts parented to the
692 QQmlContext *QQmlEngine::rootContext() const
694 Q_D(const QQmlEngine);
695 return d->rootContext;
699 Sets the \a factory to use for creating QNetworkAccessManager(s).
701 QNetworkAccessManager is used for all network access by QML. By
702 implementing a factory it is possible to create custom
703 QNetworkAccessManager with specialized caching, proxy and cookie
706 The factory must be set before executing the engine.
708 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
711 QMutexLocker locker(&d->mutex);
712 d->networkAccessManagerFactory = factory;
716 Returns the current QQmlNetworkAccessManagerFactory.
718 \sa setNetworkAccessManagerFactory()
720 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
722 Q_D(const QQmlEngine);
723 return d->networkAccessManagerFactory;
726 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
729 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
731 void *args[] = { 0 };
732 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
736 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
738 QMutexLocker locker(&mutex);
739 QNetworkAccessManager *nam;
740 if (networkAccessManagerFactory) {
741 nam = networkAccessManagerFactory->create(parent);
743 nam = new QNetworkAccessManager(parent);
749 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
751 Q_Q(const QQmlEngine);
752 if (!networkAccessManager)
753 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
754 return networkAccessManager;
758 Returns a common QNetworkAccessManager which can be used by any QML
759 element instantiated by this engine.
761 If a QQmlNetworkAccessManagerFactory has been set and a
762 QNetworkAccessManager has not yet been created, the
763 QQmlNetworkAccessManagerFactory will be used to create the
764 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
765 will have no proxy or cache set.
767 \sa setNetworkAccessManagerFactory()
769 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
771 Q_D(const QQmlEngine);
772 return d->getNetworkAccessManager();
777 Sets the \a provider to use for images requested via the \e
778 image: url scheme, with host \a providerId. The QQmlEngine
779 takes ownership of \a provider.
781 Image providers enable support for pixmap and threaded image
782 requests. See the QQuickImageProvider documentation for details on
783 implementing and using image providers.
785 All required image providers should be added to the engine before any
786 QML sources files are loaded.
788 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
790 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
793 QMutexLocker locker(&d->mutex);
794 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
798 Returns the image provider set for \a providerId.
800 Returns the provider if it was found; otherwise returns 0.
802 \sa QQuickImageProvider
804 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
806 Q_D(const QQmlEngine);
807 QMutexLocker locker(&d->mutex);
808 return d->imageProviders.value(providerId).data();
812 Removes the image provider for \a providerId.
814 \sa addImageProvider(), QQuickImageProvider
816 void QQmlEngine::removeImageProvider(const QString &providerId)
819 QMutexLocker locker(&d->mutex);
820 d->imageProviders.take(providerId);
824 Return the base URL for this engine. The base URL is only used to
825 resolve components when a relative URL is passed to the
826 QQmlComponent constructor.
828 If a base URL has not been explicitly set, this method returns the
829 application's current working directory.
833 QUrl QQmlEngine::baseUrl() const
835 Q_D(const QQmlEngine);
836 if (d->baseUrl.isEmpty()) {
837 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
844 Set the base URL for this engine to \a url.
848 void QQmlEngine::setBaseUrl(const QUrl &url)
855 Returns true if warning messages will be output to stderr in addition
856 to being emitted by the warnings() signal, otherwise false.
858 The default value is true.
860 bool QQmlEngine::outputWarningsToStandardError() const
862 Q_D(const QQmlEngine);
863 return d->outputWarningsToStdErr;
867 Set whether warning messages will be output to stderr to \a enabled.
869 If \a enabled is true, any warning messages generated by QML will be
870 output to stderr and emitted by the warnings() signal. If \a enabled
871 is false, on the warnings() signal will be emitted. This allows
872 applications to handle warning output themselves.
874 The default value is true.
876 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
879 d->outputWarningsToStdErr = enabled;
883 Attempt to free unused memory.
885 void QQmlEngine::collectGarbage()
891 Returns the QQmlContext for the \a object, or 0 if no
892 context has been set.
894 When the QQmlEngine instantiates a QObject, the context is
897 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
902 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
905 static_cast<QQmlData *>(priv->declarativeData);
909 else if (data->outerContext)
910 return data->outerContext->asQQmlContext();
916 Sets the QQmlContext for the \a object to \a context.
917 If the \a object already has a context, a warning is
918 output, but the context is not changed.
920 When the QQmlEngine instantiates a QObject, the context is
923 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
925 if (!object || !context)
928 QQmlData *data = QQmlData::get(object, true);
930 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
934 QQmlContextData *contextData = QQmlContextData::get(context);
935 contextData->addObject(object);
939 \enum QQmlEngine::ObjectOwnership
941 Ownership controls whether or not QML automatically destroys the
942 QObject when the object is garbage collected by the JavaScript
943 engine. The two ownership options are:
945 \value CppOwnership The object is owned by C++ code, and will
946 never be deleted by QML. The JavaScript destroy() method cannot be
947 used on objects with CppOwnership. This option is similar to
948 QScriptEngine::QtOwnership.
950 \value JavaScriptOwnership The object is owned by JavaScript.
951 When the object is returned to QML as the return value of a method
952 call or property access, QML will track it, and delete the object
953 if there are no remaining JavaScript references to it and it has no
954 QObject::parent(). An object tracked by one QQmlEngine
955 will be deleted during that QQmlEngine's destructor, and thus
956 JavaScript references between objects with JavaScriptOwnership from
957 two different engines will not be valid after the deletion of one of
958 those engines. This option is similar to QScriptEngine::ScriptOwnership.
960 Generally an application doesn't need to set an object's ownership
961 explicitly. QML uses a heuristic to set the default object
962 ownership. By default, an object that is created by QML has
963 JavaScriptOwnership. The exception to this are the root objects
964 created by calling QQmlComponent::create() or
965 QQmlComponent::beginCreate() which have CppOwnership by
966 default. The ownership of these root-level objects is considered to
967 have been transferred to the C++ caller.
969 Objects not-created by QML have CppOwnership by default. The
970 exception to this is objects returned from a C++ method call. The
971 ownership of these objects is passed to JavaScript.
973 Calling setObjectOwnership() overrides the default ownership
974 heuristic used by QML.
978 Sets the \a ownership of \a object.
980 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
985 QQmlData *ddata = QQmlData::get(object, true);
989 ddata->indestructible = (ownership == CppOwnership)?true:false;
990 ddata->explicitIndestructibleSet = true;
994 Returns the ownership of \a object.
996 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1001 QQmlData *ddata = QQmlData::get(object, false);
1003 return CppOwnership;
1005 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1008 bool QQmlEngine::event(QEvent *e)
1011 if (e->type() == QEvent::User)
1012 d->doDeleteInEngineThread();
1014 return QJSEngine::event(e);
1017 void QQmlEnginePrivate::doDeleteInEngineThread()
1019 QFieldList<Deletable, &Deletable::next> list;
1021 list.copyAndClear(toDeleteInEngineThread);
1024 while (Deletable *d = list.takeFirst())
1028 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1030 QQmlData *data = QQmlData::get(object);
1032 if (data && data->deferredComponent) {
1033 QQmlObjectCreatingProfiler prof;
1035 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1036 prof.setTypeName(type ? type->qmlTypeName()
1037 : QString::fromUtf8(object->metaObject()->className()));
1038 if (data->outerContext)
1039 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1041 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1043 QQmlComponentPrivate::ConstructionState state;
1044 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1046 data->deferredComponent->release();
1047 data->deferredComponent = 0;
1049 QQmlComponentPrivate::complete(ep, &state);
1053 QQmlContext *qmlContext(const QObject *obj)
1055 return QQmlEngine::contextForObject(obj);
1058 QQmlEngine *qmlEngine(const QObject *obj)
1060 QQmlData *data = QQmlData::get(obj, false);
1061 if (!data || !data->context)
1063 return data->context->engine;
1066 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1068 QQmlData *data = QQmlData::get(object);
1070 return 0; // Attached properties are only on objects created by QML
1072 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1076 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1080 rv = pf(const_cast<QObject *>(object));
1083 data->attachedProperties()->insert(id, rv);
1088 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1089 const QMetaObject *attachedMetaObject, bool create)
1092 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1094 if (*idCache == -1 || !object)
1097 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1100 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1102 #ifndef QQML_NO_DEBUG_PROTOCOL
1103 if (!QQmlEnginePrivate::qml_debugging_enabled
1105 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1107 QQmlEnginePrivate::qml_debugging_enabled = true;
1112 class QQmlDataExtended {
1115 ~QQmlDataExtended();
1117 QHash<int, QObject *> attachedProperties;
1120 QQmlDataExtended::QQmlDataExtended()
1124 QQmlDataExtended::~QQmlDataExtended()
1128 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1131 layout(endpoint->next);
1133 int index = endpoint->sourceSignal;
1134 index = qMin(index, 0xFFFF - 1);
1136 endpoint->next = notifies[index];
1137 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1138 endpoint->prev = ¬ifies[index];
1139 notifies[index] = endpoint;
1142 void QQmlData::NotifyList::layout()
1144 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1147 QQmlNotifierEndpoint **old = notifies;
1148 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1149 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1150 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1151 sizeof(QQmlNotifierEndpoint*);
1152 memset(notifies + notifiesSize, 0, memsetSize);
1154 if (notifies != old) {
1155 for (int ii = 0; ii < notifiesSize; ++ii)
1157 notifies[ii]->prev = ¬ifies[ii];
1160 notifiesSize = maximumTodoIndex + 1;
1165 maximumTodoIndex = 0;
1169 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1172 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1173 notifyList->connectionMask = 0;
1174 notifyList->maximumTodoIndex = 0;
1175 notifyList->notifiesSize = 0;
1176 notifyList->todo = 0;
1177 notifyList->notifies = 0;
1180 Q_ASSERT(!endpoint->isConnected());
1182 index = qMin(index, 0xFFFF - 1);
1183 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1185 if (index < notifyList->notifiesSize) {
1187 endpoint->next = notifyList->notifies[index];
1188 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1189 endpoint->prev = ¬ifyList->notifies[index];
1190 notifyList->notifies[index] = endpoint;
1193 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1195 endpoint->next = notifyList->todo;
1196 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1197 endpoint->prev = ¬ifyList->todo;
1198 notifyList->todo = endpoint;
1202 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1204 QQmlData *data = QQmlData::get(obj);
1205 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1209 index MUST be the index returned by QMetaMethod::index()
1210 This is different than the index returned by QObjectPrivate::signalIndex()
1212 bool QQmlData::signalHasEndpoint(int index)
1214 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1217 QHash<int, QObject *> *QQmlData::attachedProperties() const
1219 if (!extendedData) extendedData = new QQmlDataExtended;
1220 return &extendedData->attachedProperties;
1223 void QQmlData::destroyed(QObject *object)
1225 if (deferredComponent)
1226 deferredComponent->release();
1228 if (nextContextObject)
1229 nextContextObject->prevContextObject = prevContextObject;
1230 if (prevContextObject)
1231 *prevContextObject = nextContextObject;
1233 QQmlAbstractBinding *binding = bindings;
1235 QQmlAbstractBinding *next = binding->m_nextBinding;
1236 binding->m_prevBinding = 0;
1237 binding->m_nextBinding = 0;
1242 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1243 while (signalHandler) {
1244 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1245 signalHandler->m_prevSignal = 0;
1246 signalHandler->m_nextSignal = 0;
1247 delete signalHandler;
1248 signalHandler = next;
1255 propertyCache->release();
1257 if (ownContext && context)
1261 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1262 *guard = (QObject *)0;
1263 guard->objectDestroyed(object);
1267 while (notifyList->todo)
1268 notifyList->todo->disconnect();
1269 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1270 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1273 free(notifyList->notifies);
1279 delete extendedData;
1281 v8object.Clear(); // The WeakReference handler will clean the actual handle
1287 void QQmlData::parentChanged(QObject *object, QObject *parent)
1293 bool QQmlData::hasBindingBit(int bit) const
1295 if (bindingBitsSize > bit)
1296 return bindingBits[bit / 32] & (1 << (bit % 32));
1301 void QQmlData::clearBindingBit(int bit)
1303 if (bindingBitsSize > bit)
1304 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1307 void QQmlData::setBindingBit(QObject *obj, int bit)
1309 if (bindingBitsSize <= bit) {
1310 int props = obj->metaObject()->propertyCount();
1311 Q_ASSERT(bit < props);
1313 int arraySize = (props + 31) / 32;
1314 int oldArraySize = bindingBitsSize / 32;
1316 bindingBits = (quint32 *)realloc(bindingBits,
1317 arraySize * sizeof(quint32));
1319 memset(bindingBits + oldArraySize,
1321 sizeof(quint32) * (arraySize - oldArraySize));
1323 bindingBitsSize = arraySize * 32;
1326 bindingBits[bit / 32] |= (1 << (bit % 32));
1329 void QQmlEnginePrivate::sendQuit()
1333 if (q->receivers(SIGNAL(quit())) == 0) {
1334 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1338 static void dumpwarning(const QQmlError &error)
1340 QMessageLogger(error.url().toString().toLatin1().constData(),
1341 error.line(), 0).warning().nospace()
1342 << qPrintable(error.toString());
1345 static void dumpwarning(const QList<QQmlError> &errors)
1347 for (int ii = 0; ii < errors.count(); ++ii)
1348 dumpwarning(errors.at(ii));
1351 void QQmlEnginePrivate::warning(const QQmlError &error)
1354 q->warnings(QList<QQmlError>() << error);
1355 if (outputWarningsToStdErr)
1359 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1362 q->warnings(errors);
1363 if (outputWarningsToStdErr)
1364 dumpwarning(errors);
1367 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1370 QQmlEnginePrivate::get(engine)->warning(error);
1375 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1378 QQmlEnginePrivate::get(engine)->warning(error);
1383 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1386 engine->warning(error);
1391 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1394 engine->warning(error);
1400 This function should be called prior to evaluation of any js expression,
1401 so that scarce resources are not freed prematurely (eg, if there is a
1402 nested javascript expression).
1404 void QQmlEnginePrivate::referenceScarceResources()
1406 scarceResourcesRefCount += 1;
1410 This function should be called after evaluation of the js expression is
1411 complete, and so the scarce resources may be freed safely.
1413 void QQmlEnginePrivate::dereferenceScarceResources()
1415 Q_ASSERT(scarceResourcesRefCount > 0);
1416 scarceResourcesRefCount -= 1;
1418 // if the refcount is zero, then evaluation of the "top level"
1419 // expression must have completed. We can safely release the
1420 // scarce resources.
1421 if (scarceResourcesRefCount == 0) {
1422 // iterate through the list and release them all.
1423 // note that the actual SRD is owned by the JS engine,
1424 // so we cannot delete the SRD; but we can free the
1425 // memory used by the variant in the SRD.
1426 while (ScarceResourceData *sr = scarceResources.first()) {
1427 sr->data = QVariant();
1428 scarceResources.remove(sr);
1434 Adds \a path as a directory where the engine searches for
1435 installed modules in a URL-based directory structure.
1436 The \a path may be a local filesystem directory or a URL.
1438 The newly added \a path will be first in the importPathList().
1440 \sa setImportPathList(), {QML Modules}
1442 void QQmlEngine::addImportPath(const QString& path)
1445 d->importDatabase.addImportPath(path);
1449 Returns the list of directories where the engine searches for
1450 installed modules in a URL-based directory structure.
1452 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1453 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1454 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1455 provided by that module. A \c qmldir file is required for defining the
1456 type version mapping and possibly QML extensions plugins.
1458 By default, the list contains the directory of the application executable,
1459 paths specified in the \c QML_IMPORT_PATH environment variable,
1460 and the builtin \c ImportsPath from QLibraryInfo.
1462 \sa addImportPath(), setImportPathList()
1464 QStringList QQmlEngine::importPathList() const
1466 Q_D(const QQmlEngine);
1467 return d->importDatabase.importPathList();
1471 Sets \a paths as the list of directories where the engine searches for
1472 installed modules in a URL-based directory structure.
1474 By default, the list contains the directory of the application executable,
1475 paths specified in the \c QML_IMPORT_PATH environment variable,
1476 and the builtin \c ImportsPath from QLibraryInfo.
1478 \sa importPathList(), addImportPath()
1480 void QQmlEngine::setImportPathList(const QStringList &paths)
1483 d->importDatabase.setImportPathList(paths);
1488 Adds \a path as a directory where the engine searches for
1489 native plugins for imported modules (referenced in the \c qmldir file).
1491 By default, the list contains only \c ., i.e. the engine searches
1492 in the directory of the \c qmldir file itself.
1494 The newly added \a path will be first in the pluginPathList().
1496 \sa setPluginPathList()
1498 void QQmlEngine::addPluginPath(const QString& path)
1501 d->importDatabase.addPluginPath(path);
1506 Returns the list of directories where the engine searches for
1507 native plugins for imported modules (referenced in the \c qmldir file).
1509 By default, the list contains only \c ., i.e. the engine searches
1510 in the directory of the \c qmldir file itself.
1512 \sa addPluginPath(), setPluginPathList()
1514 QStringList QQmlEngine::pluginPathList() const
1516 Q_D(const QQmlEngine);
1517 return d->importDatabase.pluginPathList();
1521 Sets the list of directories where the engine searches for
1522 native plugins for imported modules (referenced in the \c qmldir file)
1525 By default, the list contains only \c ., i.e. the engine searches
1526 in the directory of the \c qmldir file itself.
1528 \sa pluginPathList(), addPluginPath()
1530 void QQmlEngine::setPluginPathList(const QStringList &paths)
1533 d->importDatabase.setPluginPathList(paths);
1537 Imports the plugin named \a filePath with the \a uri provided.
1538 Returns true if the plugin was successfully imported; otherwise returns false.
1540 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1542 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1544 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1547 return d->importDatabase.importPlugin(filePath, uri, errors);
1551 Imports the plugin named \a filePath with the \a uri provided.
1552 Returns true if the plugin was successfully imported; otherwise returns false.
1554 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1556 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1558 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1561 QList<QQmlError> errors;
1562 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1563 if (!errors.isEmpty()) {
1565 for (int i = 0; i < errors.size(); ++i) {
1566 builtError = QString(QLatin1String("%1\n %2"))
1568 .arg(errors.at(i).toString());
1570 *errorString = builtError;
1576 \property QQmlEngine::offlineStoragePath
1577 \brief the directory for storing offline user data
1579 Returns the directory where SQL and other offline
1582 QQuickWebView and the SQL databases created with openDatabase()
1585 The default is QML/OfflineStorage in the platform-standard
1586 user application data directory.
1588 Note that the path may not currently exist on the filesystem, so
1589 callers wanting to \e create new files at this location should create
1590 it first - see QDir::mkpath().
1592 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1595 d->offlineStoragePath = dir;
1598 QString QQmlEngine::offlineStoragePath() const
1600 Q_D(const QQmlEngine);
1601 return d->offlineStoragePath;
1604 static void voidptr_destructor(void *v)
1606 void **ptr = (void **)v;
1610 static void *voidptr_constructor(const void *v)
1615 return new void*(*(void **)v);
1619 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1623 if (!mo->superClass()) {
1624 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1625 propertyCache.insert(mo, rv);
1628 QQmlPropertyCache *super = cache(mo->superClass());
1629 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1630 propertyCache.insert(mo, rv);
1635 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1638 QList<QQmlType *> types;
1640 int maxMinorVersion = 0;
1642 const QMetaObject *metaObject = type->metaObject();
1644 while (metaObject) {
1645 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1646 type->majorVersion(), minorVersion);
1648 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1654 metaObject = metaObject->superClass();
1657 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1659 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1663 QQmlPropertyCache *raw = cache(type->metaObject());
1665 bool hasCopied = false;
1667 for (int ii = 0; ii < types.count(); ++ii) {
1668 QQmlType *currentType = types.at(ii);
1672 int rev = currentType->metaObjectRevision();
1673 int moIndex = types.count() - 1 - ii;
1675 if (raw->allowedRevisionCache[moIndex] != rev) {
1680 raw->allowedRevisionCache[moIndex] = rev;
1684 // Test revision compatibility - the basic rule is:
1685 // * Anything that is excluded, cannot overload something that is not excluded *
1687 // Signals override:
1688 // * other signals and methods of the same name.
1689 // * properties named on<Signal Name>
1690 // * automatic <property name>Changed notify signals
1692 // Methods override:
1693 // * other methods of the same name
1695 // Properties override:
1696 // * other elements of the same name
1698 bool overloadError = false;
1699 QString overloadName;
1702 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1703 !overloadError && iter != raw->stringCache.end();
1706 QQmlPropertyData *d = *iter;
1707 if (raw->isAllowedInRevision(d))
1708 continue; // Not excluded - no problems
1710 // check that a regular "name" overload isn't happening
1711 QQmlPropertyData *current = d;
1712 while (!overloadError && current) {
1713 current = d->overrideData(current);
1714 if (current && raw->isAllowedInRevision(current))
1715 overloadError = true;
1720 if (overloadError) {
1721 if (hasCopied) raw->release();
1723 error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1String(" ") + QString::number(type->majorVersion()) + QLatin1String(".") + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation."));
1727 if (!hasCopied) raw->addref();
1728 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1730 if (minorVersion != maxMinorVersion) {
1732 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1738 QQmlMetaType::ModuleApiInstance *
1739 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1741 Locker locker(this);
1743 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1745 a = new QQmlMetaType::ModuleApiInstance;
1746 a->scriptCallback = module.script;
1747 a->qobjectCallback = module.qobject;
1748 a->instanceMetaObject = module.instanceMetaObject;
1749 moduleApiInstances.insert(module, a);
1755 bool QQmlEnginePrivate::isQObject(int t)
1757 Locker locker(this);
1758 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1761 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1763 Locker locker(this);
1764 int t = v.userType();
1765 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1767 return *(QObject **)(v.constData());
1769 return QQmlMetaType::toQObject(v, ok);
1773 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1775 Locker locker(this);
1776 if (m_compositeTypes.contains(t))
1777 return QQmlMetaType::Object;
1778 else if (m_qmlLists.contains(t))
1779 return QQmlMetaType::List;
1781 return QQmlMetaType::typeCategory(t);
1784 bool QQmlEnginePrivate::isList(int t) const
1786 Locker locker(this);
1787 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1790 int QQmlEnginePrivate::listType(int t) const
1792 Locker locker(this);
1793 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1794 if (iter != m_qmlLists.end())
1797 return QQmlMetaType::listType(t);
1800 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1802 Locker locker(this);
1803 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1804 if (iter != m_compositeTypes.end()) {
1805 return (*iter)->root;
1807 QQmlType *type = QQmlMetaType::qmlType(t);
1808 return type?type->baseMetaObject():0;
1812 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1814 Locker locker(this);
1815 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1816 if (iter != m_compositeTypes.end()) {
1817 return (*iter)->root;
1819 QQmlType *type = QQmlMetaType::qmlType(t);
1820 return type?type->metaObject():0;
1824 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1826 QByteArray name = data->root->className();
1828 QByteArray ptr = name + '*';
1829 QByteArray lst = "QQmlListProperty<" + name + '>';
1831 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1832 voidptr_constructor);
1833 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1834 voidptr_constructor);
1838 Locker locker(this);
1839 m_qmlLists.insert(lst_type, ptr_type);
1840 m_compositeTypes.insert(ptr_type, data);
1843 bool QQml_isFileCaseCorrect(const QString &fileName)
1845 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1846 QFileInfo info(fileName);
1847 const QString absolute = info.absoluteFilePath();
1849 #if defined(Q_OS_MAC)
1850 const QString canonical = info.canonicalFilePath();
1851 #elif defined(Q_OS_WIN)
1852 wchar_t buffer[1024];
1854 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1855 if (rv == 0 || rv >= 1024) return true;
1856 rv = ::GetLongPathName(buffer, buffer, 1024);
1857 if (rv == 0 || rv >= 1024) return true;
1859 const QString canonical = QString::fromWCharArray(buffer);
1862 const int absoluteLength = absolute.length();
1863 const int canonicalLength = canonical.length();
1865 const int length = qMin(absoluteLength, canonicalLength);
1866 for (int ii = 0; ii < length; ++ii) {
1867 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1868 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1870 if (a.toLower() != c.toLower())
1882 \fn QQmlEngine *qmlEngine(const QObject *object)
1885 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1886 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1890 \fn QQmlContext *qmlContext(const QObject *object)
1893 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1894 QQmlEngine::contextForObject(object).