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 QQmlImageProviderBase::QQmlImageProviderBase()
213 QQmlImageProviderBase::~QQmlImageProviderBase()
219 \qmlclass Qt QQmlEnginePrivate
220 \ingroup qml-utility-elements
221 \brief The QML global Qt object provides useful enums and functions from Qt.
223 \keyword QmlGlobalQtObject
225 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
227 The \c Qt object is a global object with utility functions, properties and enums.
229 It is not instantiable; to use it, call the members of the global \c Qt object directly.
236 color: Qt.rgba(1, 0, 0, 1)
237 text: Qt.md5("hello, world")
244 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
245 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
249 The Qt object also contains helper functions for creating objects of specific
250 data types. This is primarily useful when setting the properties of an item
251 when the property has one of the following types:
254 \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()}
255 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
256 \li \c point - use \l{Qt::point()}{Qt.point()}
257 \li \c size - use \l{Qt::size()}{Qt.size()}
258 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
261 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
263 \section1 Date/Time Formatters
265 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
268 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
269 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
270 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
273 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
276 \section1 Dynamic Object Creation
277 The following functions on the global object allow you to dynamically create QML
278 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
282 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
283 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
287 \section1 Other Functions
289 The following functions are also on the Qt object.
292 \li \l{Qt::quit()}{Qt.quit()}
293 \li \l{Qt::md5()}{Qt.md5(string)}
294 \li \l{Qt::btoa()}{string Qt.btoa(string)}
295 \li \l{Qt::atob()}{string Qt.atob(string)}
296 \li \l{Qt::binding()}{object Qt.binding(function)}
297 \li \l{Qt::locale()}{object Qt.locale()}
298 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
299 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
300 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
305 \qmlproperty object Qt::application
308 The \c application object provides access to global application state
309 properties shared by many QML components.
315 \li \c application.active
317 This read-only property indicates whether the application is the top-most and focused
318 application, and the user is able to interact with the application. The property
319 is false when the application is in the background, the device keylock or screen
320 saver is active, the screen backlight is turned off, or the global system dialog
321 is being displayed on top of the application. It can be used for stopping and
322 pausing animations, timers and active processing of data in order to save device
323 battery power and free device memory and processor load when the application is not
327 \li \c application.layoutDirection
329 This read-only property can be used to query the default layout direction of the
330 application. On system start-up, the default layout direction depends on the
331 application's language. The property has a value of \c Qt.RightToLeft in locales
332 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
333 where the reading direction flows from left to right. You can bind to this
334 property to customize your application layouts to support both layout directions.
339 \li Qt.LeftToRight - Text and graphics elements should be positioned
341 \li Qt.RightToLeft - Text and graphics elements should be positioned
345 The following example uses the \c application object to indicate
346 whether the application is currently active:
348 \snippet doc/snippets/qml/application.qml document
350 \qmlproperty object Qt::inputMethod
353 The \c inputMethod object allows access to application's QInputMethod object
354 and all its properties and slots. See the QInputMethod documentation for
360 \qmlmethod object Qt::include(string url, jsobject callback)
362 Includes another JavaScript file. This method can only be used from within JavaScript files,
363 and not regular QML files.
365 This imports all functions from \a url into the current script's namespace.
367 Qt.include() returns an object that describes the status of the operation. The object has
368 a single property, \c {status}, that is set to one of the following values:
371 \header \li Symbol \li Value \li Description
372 \row \li result.OK \li 0 \li The include completed successfully.
373 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
374 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
375 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
376 An additional \c exception property will be set in this case.
379 The \c status property will be updated as the operation progresses.
381 If provided, \a callback is invoked when the operation completes. The callback is passed
382 the same object as is returned from the Qt.include() call.
384 // Qt.include() is implemented in qv8include.cpp
387 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
388 : propertyCapture(0), rootContext(0), isDebugging(false),
389 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
390 cleanup(0), erroredBindings(0), inProgressCreations(0),
391 workerScriptEngine(0), activeVME(0),
392 networkAccessManager(0), networkAccessManagerFactory(0),
393 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
394 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
398 QQmlEnginePrivate::~QQmlEnginePrivate()
400 if (inProgressCreations)
401 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
404 QQmlCleanup *c = cleanup;
406 if (cleanup) cleanup->prev = &cleanup;
412 doDeleteInEngineThread();
414 if (incubationController) incubationController->d = 0;
415 incubationController = 0;
420 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
422 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
424 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
426 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
427 delete (*iter)->qobjectApi;
432 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
434 QObjectPrivate *p = QObjectPrivate::get(o);
435 if (p->declarativeData) {
436 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
437 if (d->ownContext && d->context) {
438 d->context->destroy();
442 // Mark this object as in the process of deletion to
443 // prevent it resolving in bindings
444 QQmlData::markAsDeleted(o);
448 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
450 static_cast<QQmlData *>(d)->destroyed(o);
453 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
455 static_cast<QQmlData *>(d)->parentChanged(o, p);
458 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
460 QQmlData *ddata = QQmlData::get(object, false);
461 if (!ddata) return; // Probably being deleted
463 QQmlNotifierEndpoint *ep = ddata->notify(index);
464 if (ep) QQmlNotifier::emitNotify(ep, a);
467 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
469 return static_cast<QQmlData *>(d)->endpointCount(index);
472 int QQmlData::endpointCount(int index)
475 QQmlNotifierEndpoint *ep = notify(index);
486 void QQmlData::markAsDeleted(QObject *o)
488 QQmlData::setQueuedForDeletion(o);
490 QObjectPrivate *p = QObjectPrivate::get(o);
491 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
492 QQmlData::markAsDeleted(*it);
496 void QQmlData::setQueuedForDeletion(QObject *object)
499 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
500 if (!priv->wasDeleted && priv->declarativeData) {
501 QQmlData *ddata = QQmlData::get(object, false);
502 if (ddata->ownContext && ddata->context)
503 ddata->context->emitDestruction();
504 ddata->isQueuedForDeletion = true;
510 void QQmlEnginePrivate::init()
514 static bool firstTime = true;
516 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
522 qRegisterMetaType<QVariant>("QVariant");
523 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
524 qRegisterMetaType<QJSValue>("QJSValue");
525 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
526 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
527 qRegisterMetaType<QList<int> >("QList<int>");
528 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
530 v8engine()->setEngine(q);
532 rootContext = new QQmlContext(q,true);
534 if (QCoreApplication::instance()->thread() == q->thread() &&
535 QQmlEngineDebugService::isDebuggingEnabled()) {
537 QQmlEngineDebugService::instance()->addEngine(q);
538 QV8DebugService::initialize(v8engine());
539 QV8ProfilerService::initialize();
540 QQmlProfilerService::initialize();
541 QDebugMessageService::instance();
544 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
545 if (!dataLocation.isEmpty())
546 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
547 + QDir::separator() + QLatin1String("QML")
548 + QDir::separator() + QLatin1String("OfflineStorage");
551 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
554 if (!workerScriptEngine)
555 workerScriptEngine = new QQuickWorkerScriptEngine(q);
556 return workerScriptEngine;
563 \brief The QQmlEngine class provides an environment for instantiating QML components.
566 Each QML component is instantiated in a QQmlContext.
567 QQmlContext's are essential for passing data to QML
568 components. In QML, contexts are arranged hierarchically and this
569 hierarchy is managed by the QQmlEngine.
571 Prior to creating any QML components, an application must have
572 created a QQmlEngine to gain access to a QML context. The
573 following example shows how to create a simple Text item.
577 QQmlComponent component(&engine);
578 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
579 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
581 //add item to view, etc
585 In this case, the Text item will be created in the engine's
586 \l {QQmlEngine::rootContext()}{root context}.
588 Note that the QtQuick 1 version is called QDeclarativeEngine.
590 \sa QQmlComponent, QQmlContext
594 Create a new QQmlEngine with the given \a parent.
596 QQmlEngine::QQmlEngine(QObject *parent)
597 : QJSEngine(*new QQmlEnginePrivate(this), parent)
604 Destroys the QQmlEngine.
606 Any QQmlContext's created on this engine will be
607 invalidated, but not destroyed (unless they are parented to the
610 QQmlEngine::~QQmlEngine()
613 if (d->isDebugging) {
614 QQmlEngineDebugService::instance()->remEngine(this);
617 // Emit onDestruction signals for the root context before
618 // we destroy the contexts, engine, Module APIs etc. that
619 // may be required to handle the destruction signal.
620 QQmlContextData::get(rootContext())->emitDestruction();
622 // if we are the parent of any of the qobject module api instances,
623 // we need to remove them from our internal list, in order to prevent
624 // a segfault in engine private dtor.
625 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
626 QObject *currQObjectApi = 0;
627 QQmlMetaType::ModuleApiInstance *currInstance = 0;
628 foreach (const QQmlMetaType::ModuleApi &key, keys) {
629 currInstance = d->moduleApiInstances.value(key);
630 currQObjectApi = currInstance->qobjectApi;
631 if (this->children().contains(currQObjectApi)) {
632 delete currQObjectApi;
634 d->moduleApiInstances.remove(key);
638 if (d->incubationController)
639 d->incubationController->d = 0;
642 /*! \fn void QQmlEngine::quit()
643 This signal is emitted when the QML loaded by the engine would like to quit.
646 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
647 This signal is emitted when \a warnings messages are generated by QML.
651 Clears the engine's internal component cache.
653 This function causes the property metadata of all components previously
654 loaded by the engine to be destroyed. All previously loaded components and
655 the property bindings for all extant objects created from those components will
658 This function returns the engine to a state where it does not contain any loaded
659 component data. This may be useful in order to reload a smaller subset of the
660 previous component set, or to load a new version of a previously loaded component.
662 Once the component cache has been cleared, components must be loaded before
663 any new objects can be created.
665 void QQmlEngine::clearComponentCache()
668 d->typeLoader.clearCache();
672 Returns the engine's root context.
674 The root context is automatically created by the QQmlEngine.
675 Data that should be available to all QML component instances
676 instantiated by the engine should be put in the root context.
678 Additional data that should only be available to a subset of
679 component instances should be added to sub-contexts parented to the
682 QQmlContext *QQmlEngine::rootContext() const
684 Q_D(const QQmlEngine);
685 return d->rootContext;
689 Sets the \a factory to use for creating QNetworkAccessManager(s).
691 QNetworkAccessManager is used for all network access by QML. By
692 implementing a factory it is possible to create custom
693 QNetworkAccessManager with specialized caching, proxy and cookie
696 The factory must be set before executing the engine.
698 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
701 QMutexLocker locker(&d->mutex);
702 d->networkAccessManagerFactory = factory;
706 Returns the current QQmlNetworkAccessManagerFactory.
708 \sa setNetworkAccessManagerFactory()
710 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
712 Q_D(const QQmlEngine);
713 return d->networkAccessManagerFactory;
716 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
719 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
721 void *args[] = { 0 };
722 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
726 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
728 QMutexLocker locker(&mutex);
729 QNetworkAccessManager *nam;
730 if (networkAccessManagerFactory) {
731 nam = networkAccessManagerFactory->create(parent);
733 nam = new QNetworkAccessManager(parent);
739 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
741 Q_Q(const QQmlEngine);
742 if (!networkAccessManager)
743 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
744 return networkAccessManager;
748 Returns a common QNetworkAccessManager which can be used by any QML
749 element instantiated by this engine.
751 If a QQmlNetworkAccessManagerFactory has been set and a
752 QNetworkAccessManager has not yet been created, the
753 QQmlNetworkAccessManagerFactory will be used to create the
754 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
755 will have no proxy or cache set.
757 \sa setNetworkAccessManagerFactory()
759 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
761 Q_D(const QQmlEngine);
762 return d->getNetworkAccessManager();
767 Sets the \a provider to use for images requested via the \e
768 image: url scheme, with host \a providerId. The QQmlEngine
769 takes ownership of \a provider.
771 Image providers enable support for pixmap and threaded image
772 requests. See the QQuickImageProvider documentation for details on
773 implementing and using image providers.
775 All required image providers should be added to the engine before any
776 QML sources files are loaded.
778 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
780 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
783 QMutexLocker locker(&d->mutex);
784 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
788 Returns the image provider set for \a providerId.
790 Returns the provider if it was found; otherwise returns 0.
792 \sa QQuickImageProvider
794 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
796 Q_D(const QQmlEngine);
797 QMutexLocker locker(&d->mutex);
798 return d->imageProviders.value(providerId).data();
802 Removes the image provider for \a providerId.
804 \sa addImageProvider(), QQuickImageProvider
806 void QQmlEngine::removeImageProvider(const QString &providerId)
809 QMutexLocker locker(&d->mutex);
810 d->imageProviders.take(providerId);
814 Return the base URL for this engine. The base URL is only used to
815 resolve components when a relative URL is passed to the
816 QQmlComponent constructor.
818 If a base URL has not been explicitly set, this method returns the
819 application's current working directory.
823 QUrl QQmlEngine::baseUrl() const
825 Q_D(const QQmlEngine);
826 if (d->baseUrl.isEmpty()) {
827 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
834 Set the base URL for this engine to \a url.
838 void QQmlEngine::setBaseUrl(const QUrl &url)
845 Returns true if warning messages will be output to stderr in addition
846 to being emitted by the warnings() signal, otherwise false.
848 The default value is true.
850 bool QQmlEngine::outputWarningsToStandardError() const
852 Q_D(const QQmlEngine);
853 return d->outputWarningsToStdErr;
857 Set whether warning messages will be output to stderr to \a enabled.
859 If \a enabled is true, any warning messages generated by QML will be
860 output to stderr and emitted by the warnings() signal. If \a enabled
861 is false, on the warnings() signal will be emitted. This allows
862 applications to handle warning output themselves.
864 The default value is true.
866 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
869 d->outputWarningsToStdErr = enabled;
873 Attempt to free unused memory.
875 void QQmlEngine::collectGarbage()
881 Returns the QQmlContext for the \a object, or 0 if no
882 context has been set.
884 When the QQmlEngine instantiates a QObject, the context is
887 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
892 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
895 static_cast<QQmlData *>(priv->declarativeData);
899 else if (data->outerContext)
900 return data->outerContext->asQQmlContext();
906 Sets the QQmlContext for the \a object to \a context.
907 If the \a object already has a context, a warning is
908 output, but the context is not changed.
910 When the QQmlEngine instantiates a QObject, the context is
913 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
915 if (!object || !context)
918 QQmlData *data = QQmlData::get(object, true);
920 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
924 QQmlContextData *contextData = QQmlContextData::get(context);
925 contextData->addObject(object);
929 \enum QQmlEngine::ObjectOwnership
931 Ownership controls whether or not QML automatically destroys the
932 QObject when the object is garbage collected by the JavaScript
933 engine. The two ownership options are:
935 \value CppOwnership The object is owned by C++ code, and will
936 never be deleted by QML. The JavaScript destroy() method cannot be
937 used on objects with CppOwnership. This option is similar to
938 QScriptEngine::QtOwnership.
940 \value JavaScriptOwnership The object is owned by JavaScript.
941 When the object is returned to QML as the return value of a method
942 call or property access, QML will track it, and delete the object
943 if there are no remaining JavaScript references to it and it has no
944 QObject::parent(). An object tracked by one QQmlEngine
945 will be deleted during that QQmlEngine's destructor, and thus
946 JavaScript references between objects with JavaScriptOwnership from
947 two different engines will not be valid after the deletion of one of
948 those engines. This option is similar to QScriptEngine::ScriptOwnership.
950 Generally an application doesn't need to set an object's ownership
951 explicitly. QML uses a heuristic to set the default object
952 ownership. By default, an object that is created by QML has
953 JavaScriptOwnership. The exception to this are the root objects
954 created by calling QQmlComponent::create() or
955 QQmlComponent::beginCreate() which have CppOwnership by
956 default. The ownership of these root-level objects is considered to
957 have been transferred to the C++ caller.
959 Objects not-created by QML have CppOwnership by default. The
960 exception to this is objects returned from a C++ method call. The
961 ownership of these objects is passed to JavaScript.
963 Calling setObjectOwnership() overrides the default ownership
964 heuristic used by QML.
968 Sets the \a ownership of \a object.
970 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
975 QQmlData *ddata = QQmlData::get(object, true);
979 ddata->indestructible = (ownership == CppOwnership)?true:false;
980 ddata->explicitIndestructibleSet = true;
984 Returns the ownership of \a object.
986 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
991 QQmlData *ddata = QQmlData::get(object, false);
995 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
998 bool QQmlEngine::event(QEvent *e)
1001 if (e->type() == QEvent::User)
1002 d->doDeleteInEngineThread();
1004 return QJSEngine::event(e);
1007 void QQmlEnginePrivate::doDeleteInEngineThread()
1009 QFieldList<Deletable, &Deletable::next> list;
1011 list.copyAndClear(toDeleteInEngineThread);
1014 while (Deletable *d = list.takeFirst())
1018 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1020 QQmlData *data = QQmlData::get(object);
1022 if (data && data->deferredComponent) {
1023 QQmlObjectCreatingProfiler prof;
1025 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1026 prof.setTypeName(type ? type->qmlTypeName()
1027 : QString::fromUtf8(object->metaObject()->className()));
1028 if (data->outerContext)
1029 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1031 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1033 QQmlComponentPrivate::ConstructionState state;
1034 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1036 data->deferredComponent->release();
1037 data->deferredComponent = 0;
1039 QQmlComponentPrivate::complete(ep, &state);
1043 QQmlContext *qmlContext(const QObject *obj)
1045 return QQmlEngine::contextForObject(obj);
1048 QQmlEngine *qmlEngine(const QObject *obj)
1050 QQmlData *data = QQmlData::get(obj, false);
1051 if (!data || !data->context)
1053 return data->context->engine;
1056 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1058 QQmlData *data = QQmlData::get(object);
1060 return 0; // Attached properties are only on objects created by QML
1062 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1066 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1070 rv = pf(const_cast<QObject *>(object));
1073 data->attachedProperties()->insert(id, rv);
1078 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1079 const QMetaObject *attachedMetaObject, bool create)
1082 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1084 if (*idCache == -1 || !object)
1087 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1090 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1092 #ifndef QQML_NO_DEBUG_PROTOCOL
1093 if (!QQmlEnginePrivate::qml_debugging_enabled
1095 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1097 QQmlEnginePrivate::qml_debugging_enabled = true;
1102 class QQmlDataExtended {
1105 ~QQmlDataExtended();
1107 QHash<int, QObject *> attachedProperties;
1110 QQmlDataExtended::QQmlDataExtended()
1114 QQmlDataExtended::~QQmlDataExtended()
1118 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1121 layout(endpoint->next);
1123 int index = endpoint->sourceSignal;
1124 index = qMin(index, 0xFFFF - 1);
1126 endpoint->next = notifies[index];
1127 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1128 endpoint->prev = ¬ifies[index];
1129 notifies[index] = endpoint;
1132 void QQmlData::NotifyList::layout()
1134 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1137 QQmlNotifierEndpoint **old = notifies;
1138 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1139 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1140 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1141 sizeof(QQmlNotifierEndpoint*);
1142 memset(notifies + notifiesSize, 0, memsetSize);
1144 if (notifies != old) {
1145 for (int ii = 0; ii < notifiesSize; ++ii)
1147 notifies[ii]->prev = ¬ifies[ii];
1150 notifiesSize = maximumTodoIndex + 1;
1155 maximumTodoIndex = 0;
1159 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1162 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1163 notifyList->connectionMask = 0;
1164 notifyList->maximumTodoIndex = 0;
1165 notifyList->notifiesSize = 0;
1166 notifyList->todo = 0;
1167 notifyList->notifies = 0;
1170 Q_ASSERT(!endpoint->isConnected());
1172 index = qMin(index, 0xFFFF - 1);
1173 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1175 if (index < notifyList->notifiesSize) {
1177 endpoint->next = notifyList->notifies[index];
1178 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1179 endpoint->prev = ¬ifyList->notifies[index];
1180 notifyList->notifies[index] = endpoint;
1183 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1185 endpoint->next = notifyList->todo;
1186 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1187 endpoint->prev = ¬ifyList->todo;
1188 notifyList->todo = endpoint;
1192 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1194 QQmlData *data = QQmlData::get(obj);
1195 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1199 index MUST be the index returned by QMetaMethod::index()
1200 This is different than the index returned by QObjectPrivate::signalIndex()
1202 bool QQmlData::signalHasEndpoint(int index)
1204 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1207 QHash<int, QObject *> *QQmlData::attachedProperties() const
1209 if (!extendedData) extendedData = new QQmlDataExtended;
1210 return &extendedData->attachedProperties;
1213 void QQmlData::destroyed(QObject *object)
1215 if (deferredComponent)
1216 deferredComponent->release();
1218 if (nextContextObject)
1219 nextContextObject->prevContextObject = prevContextObject;
1220 if (prevContextObject)
1221 *prevContextObject = nextContextObject;
1223 QQmlAbstractBinding *binding = bindings;
1225 QQmlAbstractBinding *next = binding->m_nextBinding;
1226 binding->m_prevBinding = 0;
1227 binding->m_nextBinding = 0;
1232 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1233 while (signalHandler) {
1234 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1235 signalHandler->m_prevSignal = 0;
1236 signalHandler->m_nextSignal = 0;
1237 delete signalHandler;
1238 signalHandler = next;
1245 propertyCache->release();
1247 if (ownContext && context)
1251 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1252 *guard = (QObject *)0;
1253 guard->objectDestroyed(object);
1257 while (notifyList->todo)
1258 notifyList->todo->disconnect();
1259 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1260 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1263 free(notifyList->notifies);
1269 delete extendedData;
1271 v8object.Clear(); // The WeakReference handler will clean the actual handle
1277 void QQmlData::parentChanged(QObject *object, QObject *parent)
1283 bool QQmlData::hasBindingBit(int bit) const
1285 if (bindingBitsSize > bit)
1286 return bindingBits[bit / 32] & (1 << (bit % 32));
1291 void QQmlData::clearBindingBit(int bit)
1293 if (bindingBitsSize > bit)
1294 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1297 void QQmlData::setBindingBit(QObject *obj, int bit)
1299 if (bindingBitsSize <= bit) {
1300 int props = obj->metaObject()->propertyCount();
1301 Q_ASSERT(bit < props);
1303 int arraySize = (props + 31) / 32;
1304 int oldArraySize = bindingBitsSize / 32;
1306 bindingBits = (quint32 *)realloc(bindingBits,
1307 arraySize * sizeof(quint32));
1309 memset(bindingBits + oldArraySize,
1311 sizeof(quint32) * (arraySize - oldArraySize));
1313 bindingBitsSize = arraySize * 32;
1316 bindingBits[bit / 32] |= (1 << (bit % 32));
1319 void QQmlEnginePrivate::sendQuit()
1323 if (q->receivers(SIGNAL(quit())) == 0) {
1324 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1328 static void dumpwarning(const QQmlError &error)
1330 QMessageLogger(error.url().toString().toLatin1().constData(),
1331 error.line(), 0).warning().nospace()
1332 << qPrintable(error.toString());
1335 static void dumpwarning(const QList<QQmlError> &errors)
1337 for (int ii = 0; ii < errors.count(); ++ii)
1338 dumpwarning(errors.at(ii));
1341 void QQmlEnginePrivate::warning(const QQmlError &error)
1344 q->warnings(QList<QQmlError>() << error);
1345 if (outputWarningsToStdErr)
1349 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1352 q->warnings(errors);
1353 if (outputWarningsToStdErr)
1354 dumpwarning(errors);
1357 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1360 QQmlEnginePrivate::get(engine)->warning(error);
1365 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1368 QQmlEnginePrivate::get(engine)->warning(error);
1373 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1376 engine->warning(error);
1381 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1384 engine->warning(error);
1390 This function should be called prior to evaluation of any js expression,
1391 so that scarce resources are not freed prematurely (eg, if there is a
1392 nested javascript expression).
1394 void QQmlEnginePrivate::referenceScarceResources()
1396 scarceResourcesRefCount += 1;
1400 This function should be called after evaluation of the js expression is
1401 complete, and so the scarce resources may be freed safely.
1403 void QQmlEnginePrivate::dereferenceScarceResources()
1405 Q_ASSERT(scarceResourcesRefCount > 0);
1406 scarceResourcesRefCount -= 1;
1408 // if the refcount is zero, then evaluation of the "top level"
1409 // expression must have completed. We can safely release the
1410 // scarce resources.
1411 if (scarceResourcesRefCount == 0) {
1412 // iterate through the list and release them all.
1413 // note that the actual SRD is owned by the JS engine,
1414 // so we cannot delete the SRD; but we can free the
1415 // memory used by the variant in the SRD.
1416 while (ScarceResourceData *sr = scarceResources.first()) {
1417 sr->data = QVariant();
1418 scarceResources.remove(sr);
1424 Adds \a path as a directory where the engine searches for
1425 installed modules in a URL-based directory structure.
1426 The \a path may be a local filesystem directory or a URL.
1428 The newly added \a path will be first in the importPathList().
1430 \sa setImportPathList(), {QML Modules}
1432 void QQmlEngine::addImportPath(const QString& path)
1435 d->importDatabase.addImportPath(path);
1439 Returns the list of directories where the engine searches for
1440 installed modules in a URL-based directory structure.
1442 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1443 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1444 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1445 provided by that module. A \c qmldir file is required for defining the
1446 type version mapping and possibly QML extensions plugins.
1448 By default, the list contains the directory of the application executable,
1449 paths specified in the \c QML_IMPORT_PATH environment variable,
1450 and the builtin \c ImportsPath from QLibraryInfo.
1452 \sa addImportPath(), setImportPathList()
1454 QStringList QQmlEngine::importPathList() const
1456 Q_D(const QQmlEngine);
1457 return d->importDatabase.importPathList();
1461 Sets \a paths as the list of directories where the engine searches for
1462 installed modules in a URL-based directory structure.
1464 By default, the list contains the directory of the application executable,
1465 paths specified in the \c QML_IMPORT_PATH environment variable,
1466 and the builtin \c ImportsPath from QLibraryInfo.
1468 \sa importPathList(), addImportPath()
1470 void QQmlEngine::setImportPathList(const QStringList &paths)
1473 d->importDatabase.setImportPathList(paths);
1478 Adds \a path as a directory where the engine searches for
1479 native plugins for imported modules (referenced in the \c qmldir file).
1481 By default, the list contains only \c ., i.e. the engine searches
1482 in the directory of the \c qmldir file itself.
1484 The newly added \a path will be first in the pluginPathList().
1486 \sa setPluginPathList()
1488 void QQmlEngine::addPluginPath(const QString& path)
1491 d->importDatabase.addPluginPath(path);
1496 Returns the list of directories where the engine searches for
1497 native plugins for imported modules (referenced in the \c qmldir file).
1499 By default, the list contains only \c ., i.e. the engine searches
1500 in the directory of the \c qmldir file itself.
1502 \sa addPluginPath(), setPluginPathList()
1504 QStringList QQmlEngine::pluginPathList() const
1506 Q_D(const QQmlEngine);
1507 return d->importDatabase.pluginPathList();
1511 Sets the list of directories where the engine searches for
1512 native plugins for imported modules (referenced in the \c qmldir file)
1515 By default, the list contains only \c ., i.e. the engine searches
1516 in the directory of the \c qmldir file itself.
1518 \sa pluginPathList(), addPluginPath()
1520 void QQmlEngine::setPluginPathList(const QStringList &paths)
1523 d->importDatabase.setPluginPathList(paths);
1527 Imports the plugin named \a filePath with the \a uri provided.
1528 Returns true if the plugin was successfully imported; otherwise returns false.
1530 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1532 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1534 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1537 return d->importDatabase.importPlugin(filePath, uri, errors);
1541 Imports the plugin named \a filePath with the \a uri provided.
1542 Returns true if the plugin was successfully imported; otherwise returns false.
1544 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1546 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1548 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1551 QList<QQmlError> errors;
1552 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1553 if (!errors.isEmpty()) {
1555 for (int i = 0; i < errors.size(); ++i) {
1556 builtError = QString(QLatin1String("%1\n %2"))
1558 .arg(errors.at(i).toString());
1560 *errorString = builtError;
1566 \property QQmlEngine::offlineStoragePath
1567 \brief the directory for storing offline user data
1569 Returns the directory where SQL and other offline
1572 QQuickWebView and the SQL databases created with openDatabase()
1575 The default is QML/OfflineStorage in the platform-standard
1576 user application data directory.
1578 Note that the path may not currently exist on the filesystem, so
1579 callers wanting to \e create new files at this location should create
1580 it first - see QDir::mkpath().
1582 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1585 d->offlineStoragePath = dir;
1588 QString QQmlEngine::offlineStoragePath() const
1590 Q_D(const QQmlEngine);
1591 return d->offlineStoragePath;
1594 static void voidptr_destructor(void *v)
1596 void **ptr = (void **)v;
1600 static void *voidptr_constructor(const void *v)
1605 return new void*(*(void **)v);
1609 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1613 if (!mo->superClass()) {
1614 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1615 propertyCache.insert(mo, rv);
1618 QQmlPropertyCache *super = cache(mo->superClass());
1619 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1620 propertyCache.insert(mo, rv);
1625 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1628 QList<QQmlType *> types;
1630 int maxMinorVersion = 0;
1632 const QMetaObject *metaObject = type->metaObject();
1634 while (metaObject) {
1635 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1636 type->majorVersion(), minorVersion);
1638 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1644 metaObject = metaObject->superClass();
1647 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1649 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1653 QQmlPropertyCache *raw = cache(type->metaObject());
1655 bool hasCopied = false;
1657 for (int ii = 0; ii < types.count(); ++ii) {
1658 QQmlType *currentType = types.at(ii);
1662 int rev = currentType->metaObjectRevision();
1663 int moIndex = types.count() - 1 - ii;
1665 if (raw->allowedRevisionCache[moIndex] != rev) {
1670 raw->allowedRevisionCache[moIndex] = rev;
1674 // Test revision compatibility - the basic rule is:
1675 // * Anything that is excluded, cannot overload something that is not excluded *
1677 // Signals override:
1678 // * other signals and methods of the same name.
1679 // * properties named on<Signal Name>
1680 // * automatic <property name>Changed notify signals
1682 // Methods override:
1683 // * other methods of the same name
1685 // Properties override:
1686 // * other elements of the same name
1688 bool overloadError = false;
1689 QString overloadName;
1692 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1693 !overloadError && iter != raw->stringCache.end();
1696 QQmlPropertyData *d = *iter;
1697 if (raw->isAllowedInRevision(d))
1698 continue; // Not excluded - no problems
1700 // check that a regular "name" overload isn't happening
1701 QQmlPropertyData *current = d;
1702 while (!overloadError && current) {
1703 current = d->overrideData(current);
1704 if (current && raw->isAllowedInRevision(current))
1705 overloadError = true;
1710 if (overloadError) {
1711 if (hasCopied) raw->release();
1713 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."));
1717 if (!hasCopied) raw->addref();
1718 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1720 if (minorVersion != maxMinorVersion) {
1722 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1728 QQmlMetaType::ModuleApiInstance *
1729 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1731 Locker locker(this);
1733 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1735 a = new QQmlMetaType::ModuleApiInstance;
1736 a->scriptCallback = module.script;
1737 a->qobjectCallback = module.qobject;
1738 a->instanceMetaObject = module.instanceMetaObject;
1739 moduleApiInstances.insert(module, a);
1745 bool QQmlEnginePrivate::isQObject(int t)
1747 Locker locker(this);
1748 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1751 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1753 Locker locker(this);
1754 int t = v.userType();
1755 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1757 return *(QObject **)(v.constData());
1759 return QQmlMetaType::toQObject(v, ok);
1763 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1765 Locker locker(this);
1766 if (m_compositeTypes.contains(t))
1767 return QQmlMetaType::Object;
1768 else if (m_qmlLists.contains(t))
1769 return QQmlMetaType::List;
1771 return QQmlMetaType::typeCategory(t);
1774 bool QQmlEnginePrivate::isList(int t) const
1776 Locker locker(this);
1777 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1780 int QQmlEnginePrivate::listType(int t) const
1782 Locker locker(this);
1783 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1784 if (iter != m_qmlLists.end())
1787 return QQmlMetaType::listType(t);
1790 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1792 Locker locker(this);
1793 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1794 if (iter != m_compositeTypes.end()) {
1795 return (*iter)->root;
1797 QQmlType *type = QQmlMetaType::qmlType(t);
1798 return type?type->baseMetaObject():0;
1802 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1804 Locker locker(this);
1805 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1806 if (iter != m_compositeTypes.end()) {
1807 return (*iter)->root;
1809 QQmlType *type = QQmlMetaType::qmlType(t);
1810 return type?type->metaObject():0;
1814 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1816 QByteArray name = data->root->className();
1818 QByteArray ptr = name + '*';
1819 QByteArray lst = "QQmlListProperty<" + name + '>';
1821 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1822 voidptr_constructor);
1823 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1824 voidptr_constructor);
1828 Locker locker(this);
1829 m_qmlLists.insert(lst_type, ptr_type);
1830 m_compositeTypes.insert(ptr_type, data);
1833 bool QQml_isFileCaseCorrect(const QString &fileName)
1835 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1836 QFileInfo info(fileName);
1837 const QString absolute = info.absoluteFilePath();
1839 #if defined(Q_OS_MAC)
1840 const QString canonical = info.canonicalFilePath();
1841 #elif defined(Q_OS_WIN)
1842 wchar_t buffer[1024];
1844 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1845 if (rv == 0 || rv >= 1024) return true;
1846 rv = ::GetLongPathName(buffer, buffer, 1024);
1847 if (rv == 0 || rv >= 1024) return true;
1849 const QString canonical = QString::fromWCharArray(buffer);
1852 const int absoluteLength = absolute.length();
1853 const int canonicalLength = canonical.length();
1855 const int length = qMin(absoluteLength, canonicalLength);
1856 for (int ii = 0; ii < length; ++ii) {
1857 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1858 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1860 if (a.toLower() != c.toLower())
1872 \fn QQmlEngine *qmlEngine(const QObject *object)
1875 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1876 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1880 \fn QQmlContext *qmlContext(const QObject *object)
1883 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1884 QQmlEngine::contextForObject(object).