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 "qqmlimageprovider.h"
63 #include "qqmldirparser_p.h"
64 #include "qqmlextensioninterface.h"
65 #include "qqmllist_p.h"
66 #include "qqmltypenamecache_p.h"
67 #include "qqmlnotifier_p.h"
68 #include <private/qqmlprofilerservice_p.h>
69 #include <private/qquickapplication_p.h>
70 #include <private/qv8debugservice_p.h>
71 #include <private/qdebugmessageservice_p.h>
72 #include "qqmlincubator.h"
73 #include <private/qv8profilerservice_p.h>
74 #include <private/qqmlboundsignal_p.h>
76 #include <QtCore/qstandardpaths.h>
77 #include <QtCore/qsettings.h>
79 #include <QtCore/qmetaobject.h>
80 #include <QNetworkAccessManager>
82 #include <QMetaObject>
83 #include <QtCore/qcoreapplication.h>
84 #include <QtCore/qdir.h>
85 #include <QtCore/qmutex.h>
86 #include <QtNetwork/qnetworkconfigmanager.h>
88 #include <private/qobject_p.h>
90 #include <private/qqmllocale_p.h>
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
97 #define CSIDL_APPDATA 0x001a // <username>\Application Data
100 Q_DECLARE_METATYPE(QQmlProperty)
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
106 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
111 \qmlclass QtObject QObject
112 \ingroup qml-utility-elements
114 \brief The QtObject element is the most basic element in QML.
116 The QtObject element is a non-visual element which contains only the
119 It can be useful to create a QtObject if you need an extremely
120 lightweight element to enclose a set of custom properties:
122 \snippet doc/src/snippets/qml/qtobject.qml 0
124 It can also be useful for C++ integration, as it is just a plain
125 QObject. See the QObject documentation for further details.
128 \qmlproperty string QtObject::objectName
129 This property holds the QObject::objectName for this specific object instance.
131 This allows a C++ application to locate an item within a QML component
132 using the QObject::findChild() method. For example, the following C++
133 application locates the child \l Rectangle item and dynamically changes its
142 width: 200; height: 200
156 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
159 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
161 item->setProperty("color", QColor(Qt::yellow));
165 bool QQmlEnginePrivate::qml_debugging_enabled = false;
167 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
169 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
170 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
171 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
172 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
173 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
176 void QQmlEnginePrivate::defineModule()
178 registerBaseTypes("QtQuick", 2, 0);
179 qmlRegisterUncreatableType<QQuickApplication>("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class"));
180 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
184 \qmlclass Qt QQmlEnginePrivate
185 \ingroup qml-utility-elements
186 \brief The QML global Qt object provides useful enums and functions from Qt.
188 \keyword QmlGlobalQtObject
190 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
192 The \c Qt object is a global object with utility functions, properties and enums.
194 It is not instantiable; to use it, call the members of the global \c Qt object directly.
201 color: Qt.rgba(1, 0, 0, 1)
202 text: Qt.md5("hello, world")
209 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
210 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
214 The Qt object also contains helper functions for creating objects of specific
215 data types. This is primarily useful when setting the properties of an item
216 when the property has one of the following types:
219 \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()}
220 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
221 \li \c point - use \l{Qt::point()}{Qt.point()}
222 \li \c size - use \l{Qt::size()}{Qt.size()}
223 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
226 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
228 \section1 Date/Time Formatters
230 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
233 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
234 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
235 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
238 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
241 \section1 Dynamic Object Creation
242 The following functions on the global object allow you to dynamically create QML
243 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
247 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
248 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
254 \qmlproperty object Qt::application
257 The \c application object provides access to global application state
258 properties shared by many QML components.
264 \li \c application.active
266 This read-only property indicates whether the application is the top-most and focused
267 application, and the user is able to interact with the application. The property
268 is false when the application is in the background, the device keylock or screen
269 saver is active, the screen backlight is turned off, or the global system dialog
270 is being displayed on top of the application. It can be used for stopping and
271 pausing animations, timers and active processing of data in order to save device
272 battery power and free device memory and processor load when the application is not
276 \li \c application.layoutDirection
278 This read-only property can be used to query the default layout direction of the
279 application. On system start-up, the default layout direction depends on the
280 application's language. The property has a value of \c Qt.RightToLeft in locales
281 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
282 where the reading direction flows from left to right. You can bind to this
283 property to customize your application layouts to support both layout directions.
288 \li Qt.LeftToRight - Text and graphics elements should be positioned
290 \li Qt.RightToLeft - Text and graphics elements should be positioned
295 \li \c application.inputPanel
297 This read-only property allows access to application's QInputPanel object
298 and all its properties and slots. See the QInputPanel documentation for
299 further details. Deprecated in favor of Qt.InputMethod
302 The following example uses the \c application object to indicate
303 whether the application is currently active:
305 \snippet doc/src/snippets/qml/application.qml document
307 \qmlproperty object Qt::inputMethod
310 The \c inputMethod object allows access to application's QInputMethod object
311 and all its properties and slots. See the QInputMethod documentation for
317 \qmlmethod object Qt::include(string url, jsobject callback)
319 Includes another JavaScript file. This method can only be used from within JavaScript files,
320 and not regular QML files.
322 This imports all functions from \a url into the current script's namespace.
324 Qt.include() returns an object that describes the status of the operation. The object has
325 a single property, \c {status}, that is set to one of the following values:
328 \header \li Symbol \li Value \li Description
329 \row \li result.OK \li 0 \li The include completed successfully.
330 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
331 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
332 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
333 An additional \c exception property will be set in this case.
336 The \c status property will be updated as the operation progresses.
338 If provided, \a callback is invoked when the operation completes. The callback is passed
339 the same object as is returned from the Qt.include() call.
341 // Qt.include() is implemented in qv8include.cpp
344 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
345 : propertyCapture(0), rootContext(0), isDebugging(false),
346 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
347 cleanup(0), erroredBindings(0), inProgressCreations(0),
348 workerScriptEngine(0), activeVME(0),
349 networkAccessManager(0), networkAccessManagerFactory(0),
350 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
351 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
355 QQmlEnginePrivate::~QQmlEnginePrivate()
357 if (inProgressCreations)
358 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
361 QQmlCleanup *c = cleanup;
363 if (cleanup) cleanup->prev = &cleanup;
369 doDeleteInEngineThread();
371 if (incubationController) incubationController->d = 0;
372 incubationController = 0;
377 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
379 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
381 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
383 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
384 delete (*iter)->qobjectApi;
389 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
391 QObjectPrivate *p = QObjectPrivate::get(o);
392 if (p->declarativeData) {
393 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
394 if (d->ownContext && d->context) {
395 d->context->destroy();
401 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
403 static_cast<QQmlData *>(d)->destroyed(o);
406 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
408 static_cast<QQmlData *>(d)->parentChanged(o, p);
411 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
413 static_cast<QQmlData *>(d)->objectNameChanged(o);
416 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
418 QQmlData *ddata = QQmlData::get(object, false);
419 if (!ddata) return; // Probably being deleted
421 QQmlNotifierEndpoint *ep = ddata->notify(index);
422 if (ep) QQmlNotifier::emitNotify(ep);
425 void QQmlEnginePrivate::init()
429 static bool firstTime = true;
431 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
436 qRegisterMetaType<QVariant>("QVariant");
437 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
438 qRegisterMetaType<QJSValue>("QJSValue");
439 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
440 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
441 qRegisterMetaType<QList<int> >("QList<int>");
442 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
446 v8engine()->setEngine(q);
448 rootContext = new QQmlContext(q,true);
450 if (QCoreApplication::instance()->thread() == q->thread() &&
451 QQmlEngineDebugService::isDebuggingEnabled()) {
453 QQmlEngineDebugService::instance()->addEngine(q);
454 QV8DebugService::initialize(v8engine());
455 QV8ProfilerService::initialize();
456 QQmlProfilerService::initialize();
457 QDebugMessageService::instance();
460 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
461 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
462 QDir::separator() + QLatin1String("QML") +
463 QDir::separator() + QLatin1String("OfflineStorage");
466 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
469 if (!workerScriptEngine)
470 workerScriptEngine = new QQuickWorkerScriptEngine(q);
471 return workerScriptEngine;
478 \brief The QQmlEngine class provides an environment for instantiating QML components.
481 Each QML component is instantiated in a QQmlContext.
482 QQmlContext's are essential for passing data to QML
483 components. In QML, contexts are arranged hierarchically and this
484 hierarchy is managed by the QQmlEngine.
486 Prior to creating any QML components, an application must have
487 created a QQmlEngine to gain access to a QML context. The
488 following example shows how to create a simple Text item.
492 QQmlComponent component(&engine);
493 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
494 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
496 //add item to view, etc
500 In this case, the Text item will be created in the engine's
501 \l {QQmlEngine::rootContext()}{root context}.
503 Note that the QtQuick 1 version is called QDeclarativeEngine.
505 \sa QQmlComponent QQmlContext
509 Create a new QQmlEngine with the given \a parent.
511 QQmlEngine::QQmlEngine(QObject *parent)
512 : QJSEngine(*new QQmlEnginePrivate(this), parent)
519 Destroys the QQmlEngine.
521 Any QQmlContext's created on this engine will be
522 invalidated, but not destroyed (unless they are parented to the
525 QQmlEngine::~QQmlEngine()
528 if (d->isDebugging) {
529 QQmlEngineDebugService::instance()->remEngine(this);
532 // if we are the parent of any of the qobject module api instances,
533 // we need to remove them from our internal list, in order to prevent
534 // a segfault in engine private dtor.
535 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
536 QObject *currQObjectApi = 0;
537 QQmlMetaType::ModuleApiInstance *currInstance = 0;
538 foreach (const QQmlMetaType::ModuleApi &key, keys) {
539 currInstance = d->moduleApiInstances.value(key);
540 currQObjectApi = currInstance->qobjectApi;
541 if (this->children().contains(currQObjectApi)) {
542 delete currQObjectApi;
544 d->moduleApiInstances.remove(key);
548 // ensure we clean up QObjects with JS ownership
551 if (d->incubationController)
552 d->incubationController->d = 0;
555 /*! \fn void QQmlEngine::quit()
556 This signal is emitted when the QML loaded by the engine would like to quit.
559 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
560 This signal is emitted when \a warnings messages are generated by QML.
564 Clears the engine's internal component cache.
566 Normally the QQmlEngine caches components loaded from qml
567 files. This method clears this cache and forces the component to be
570 void QQmlEngine::clearComponentCache()
573 d->typeLoader.clearCache();
577 Returns the engine's root context.
579 The root context is automatically created by the QQmlEngine.
580 Data that should be available to all QML component instances
581 instantiated by the engine should be put in the root context.
583 Additional data that should only be available to a subset of
584 component instances should be added to sub-contexts parented to the
587 QQmlContext *QQmlEngine::rootContext() const
589 Q_D(const QQmlEngine);
590 return d->rootContext;
594 Sets the \a factory to use for creating QNetworkAccessManager(s).
596 QNetworkAccessManager is used for all network access by QML. By
597 implementing a factory it is possible to create custom
598 QNetworkAccessManager with specialized caching, proxy and cookie
601 The factory must be set before executing the engine.
603 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
606 QMutexLocker locker(&d->mutex);
607 d->networkAccessManagerFactory = factory;
611 Returns the current QQmlNetworkAccessManagerFactory.
613 \sa setNetworkAccessManagerFactory()
615 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
617 Q_D(const QQmlEngine);
618 return d->networkAccessManagerFactory;
621 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
624 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
626 void *args[] = { 0 };
627 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
631 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
633 QMutexLocker locker(&mutex);
634 QNetworkAccessManager *nam;
635 if (networkAccessManagerFactory) {
636 nam = networkAccessManagerFactory->create(parent);
638 nam = new QNetworkAccessManager(parent);
644 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
646 Q_Q(const QQmlEngine);
647 if (!networkAccessManager)
648 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
649 return networkAccessManager;
653 Returns a common QNetworkAccessManager which can be used by any QML
654 element instantiated by this engine.
656 If a QQmlNetworkAccessManagerFactory has been set and a
657 QNetworkAccessManager has not yet been created, the
658 QQmlNetworkAccessManagerFactory will be used to create the
659 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
660 will have no proxy or cache set.
662 \sa setNetworkAccessManagerFactory()
664 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
666 Q_D(const QQmlEngine);
667 return d->getNetworkAccessManager();
672 Sets the \a provider to use for images requested via the \e
673 image: url scheme, with host \a providerId. The QQmlEngine
674 takes ownership of \a provider.
676 Image providers enable support for pixmap and threaded image
677 requests. See the QQmlImageProvider documentation for details on
678 implementing and using image providers.
680 All required image providers should be added to the engine before any
681 QML sources files are loaded.
683 \sa removeImageProvider()
685 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProvider *provider)
688 QMutexLocker locker(&d->mutex);
689 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProvider>(provider));
693 Returns the QQmlImageProvider set for \a providerId.
695 Returns the provider if it was found; otherwise returns 0.
697 QQmlImageProvider *QQmlEngine::imageProvider(const QString &providerId) const
699 Q_D(const QQmlEngine);
700 QMutexLocker locker(&d->mutex);
701 return d->imageProviders.value(providerId).data();
705 Removes the QQmlImageProvider for \a providerId.
707 \sa addImageProvider()
709 void QQmlEngine::removeImageProvider(const QString &providerId)
712 QMutexLocker locker(&d->mutex);
713 d->imageProviders.take(providerId);
716 QQmlImageProvider::ImageType QQmlEnginePrivate::getImageProviderType(const QUrl &url)
718 QMutexLocker locker(&mutex);
719 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
722 return provider->imageType();
723 return QQmlImageProvider::Invalid;
726 QQuickTextureFactory *QQmlEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
728 QMutexLocker locker(&mutex);
729 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
732 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
733 return provider->requestTexture(imageId, size, req_size);
738 QImage QQmlEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
740 QMutexLocker locker(&mutex);
742 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
745 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
746 image = provider->requestImage(imageId, size, req_size);
751 QPixmap QQmlEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
753 QMutexLocker locker(&mutex);
755 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
758 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
759 pixmap = provider->requestPixmap(imageId, size, req_size);
765 Return the base URL for this engine. The base URL is only used to
766 resolve components when a relative URL is passed to the
767 QQmlComponent constructor.
769 If a base URL has not been explicitly set, this method returns the
770 application's current working directory.
774 QUrl QQmlEngine::baseUrl() const
776 Q_D(const QQmlEngine);
777 if (d->baseUrl.isEmpty()) {
778 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
785 Set the base URL for this engine to \a url.
789 void QQmlEngine::setBaseUrl(const QUrl &url)
796 Returns true if warning messages will be output to stderr in addition
797 to being emitted by the warnings() signal, otherwise false.
799 The default value is true.
801 bool QQmlEngine::outputWarningsToStandardError() const
803 Q_D(const QQmlEngine);
804 return d->outputWarningsToStdErr;
808 Set whether warning messages will be output to stderr to \a enabled.
810 If \a enabled is true, any warning messages generated by QML will be
811 output to stderr and emitted by the warnings() signal. If \a enabled
812 is false, on the warnings() signal will be emitted. This allows
813 applications to handle warning output themselves.
815 The default value is true.
817 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
820 d->outputWarningsToStdErr = enabled;
824 Attempt to free unused memory.
826 void QQmlEngine::collectGarbage()
832 Returns the QQmlContext for the \a object, or 0 if no
833 context has been set.
835 When the QQmlEngine instantiates a QObject, the context is
838 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
843 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
846 static_cast<QQmlData *>(priv->declarativeData);
850 else if (data->outerContext)
851 return data->outerContext->asQQmlContext();
857 Sets the QQmlContext for the \a object to \a context.
858 If the \a object already has a context, a warning is
859 output, but the context is not changed.
861 When the QQmlEngine instantiates a QObject, the context is
864 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
866 if (!object || !context)
869 QQmlData *data = QQmlData::get(object, true);
871 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
875 QQmlContextData *contextData = QQmlContextData::get(context);
876 contextData->addObject(object);
880 \enum QQmlEngine::ObjectOwnership
882 Ownership controls whether or not QML automatically destroys the
883 QObject when the object is garbage collected by the JavaScript
884 engine. The two ownership options are:
886 \value CppOwnership The object is owned by C++ code, and will
887 never be deleted by QML. The JavaScript destroy() method cannot be
888 used on objects with CppOwnership. This option is similar to
889 QScriptEngine::QtOwnership.
891 \value JavaScriptOwnership The object is owned by JavaScript.
892 When the object is returned to QML as the return value of a method
893 call or property access, QML will delete the object if there are no
894 remaining JavaScript references to it and it has no
895 QObject::parent(). This option is similar to
896 QScriptEngine::ScriptOwnership.
898 Generally an application doesn't need to set an object's ownership
899 explicitly. QML uses a heuristic to set the default object
900 ownership. By default, an object that is created by QML has
901 JavaScriptOwnership. The exception to this are the root objects
902 created by calling QQmlComponent::create() or
903 QQmlComponent::beginCreate() which have CppOwnership by
904 default. The ownership of these root-level objects is considered to
905 have been transferred to the C++ caller.
907 Objects not-created by QML have CppOwnership by default. The
908 exception to this is objects returned from a C++ method call. The
909 ownership of these objects is passed to JavaScript.
911 Calling setObjectOwnership() overrides the default ownership
912 heuristic used by QML.
916 Sets the \a ownership of \a object.
918 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
923 QQmlData *ddata = QQmlData::get(object, true);
927 ddata->indestructible = (ownership == CppOwnership)?true:false;
928 ddata->explicitIndestructibleSet = true;
932 Returns the ownership of \a object.
934 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
939 QQmlData *ddata = QQmlData::get(object, false);
943 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
946 bool QQmlEngine::event(QEvent *e)
949 if (e->type() == QEvent::User)
950 d->doDeleteInEngineThread();
952 return QJSEngine::event(e);
955 void QQmlEnginePrivate::doDeleteInEngineThread()
957 QFieldList<Deletable, &Deletable::next> list;
959 list.copyAndClear(toDeleteInEngineThread);
962 while (Deletable *d = list.takeFirst())
966 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
968 QQmlData *data = QQmlData::get(object);
970 if (data && data->deferredComponent) {
971 QQmlObjectCreatingProfiler prof;
973 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
974 prof.setTypeName(type ? type->qmlTypeName()
975 : QString::fromUtf8(object->metaObject()->className()));
976 if (data->outerContext)
977 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
979 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
981 QQmlComponentPrivate::ConstructionState state;
982 QQmlComponentPrivate::beginDeferred(ep, object, &state);
984 data->deferredComponent->release();
985 data->deferredComponent = 0;
987 QQmlComponentPrivate::complete(ep, &state);
991 QQmlContext *qmlContext(const QObject *obj)
993 return QQmlEngine::contextForObject(obj);
996 QQmlEngine *qmlEngine(const QObject *obj)
998 QQmlData *data = QQmlData::get(obj, false);
999 if (!data || !data->context)
1001 return data->context->engine;
1004 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1006 QQmlData *data = QQmlData::get(object);
1008 return 0; // Attached properties are only on objects created by QML
1010 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1014 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1018 rv = pf(const_cast<QObject *>(object));
1021 data->attachedProperties()->insert(id, rv);
1026 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1027 const QMetaObject *attachedMetaObject, bool create)
1030 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1032 if (*idCache == -1 || !object)
1035 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1038 QQmlDebuggingEnabler::QQmlDebuggingEnabler()
1040 #ifndef QQML_NO_DEBUG_PROTOCOL
1041 if (!QQmlEnginePrivate::qml_debugging_enabled) {
1042 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1044 QQmlEnginePrivate::qml_debugging_enabled = true;
1049 class QQmlDataExtended {
1052 ~QQmlDataExtended();
1054 QHash<int, QObject *> attachedProperties;
1055 QQmlNotifier objectNameNotifier;
1058 QQmlDataExtended::QQmlDataExtended()
1062 QQmlDataExtended::~QQmlDataExtended()
1066 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1069 layout(endpoint->next);
1071 int index = endpoint->sourceSignal;
1072 index = qMin(index, 0xFFFF - 1);
1074 endpoint->next = notifies[index];
1075 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1076 endpoint->prev = ¬ifies[index];
1077 notifies[index] = endpoint;
1080 void QQmlData::NotifyList::layout()
1082 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1085 QQmlNotifierEndpoint **old = notifies;
1086 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1087 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1088 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1089 sizeof(QQmlNotifierEndpoint*);
1090 memset(notifies + notifiesSize, 0, memsetSize);
1092 if (notifies != old) {
1093 for (int ii = 0; ii < notifiesSize; ++ii)
1095 notifies[ii]->prev = ¬ifies[ii];
1098 notifiesSize = maximumTodoIndex + 1;
1103 maximumTodoIndex = 0;
1107 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1110 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1111 notifyList->connectionMask = 0;
1112 notifyList->maximumTodoIndex = 0;
1113 notifyList->notifiesSize = 0;
1114 notifyList->todo = 0;
1115 notifyList->notifies = 0;
1118 Q_ASSERT(!endpoint->isConnected());
1120 index = qMin(index, 0xFFFF - 1);
1121 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1123 if (index < notifyList->notifiesSize) {
1125 endpoint->next = notifyList->notifies[index];
1126 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1127 endpoint->prev = ¬ifyList->notifies[index];
1128 notifyList->notifies[index] = endpoint;
1131 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1133 endpoint->next = notifyList->todo;
1134 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1135 endpoint->prev = ¬ifyList->todo;
1136 notifyList->todo = endpoint;
1140 QQmlNotifier *QQmlData::objectNameNotifier() const
1142 if (!extendedData) extendedData = new QQmlDataExtended;
1143 return &extendedData->objectNameNotifier;
1146 QHash<int, QObject *> *QQmlData::attachedProperties() const
1148 if (!extendedData) extendedData = new QQmlDataExtended;
1149 return &extendedData->attachedProperties;
1152 void QQmlData::destroyed(QObject *object)
1154 if (deferredComponent)
1155 deferredComponent->release();
1157 if (nextContextObject)
1158 nextContextObject->prevContextObject = prevContextObject;
1159 if (prevContextObject)
1160 *prevContextObject = nextContextObject;
1162 QQmlAbstractBinding *binding = bindings;
1164 QQmlAbstractBinding *next = binding->m_nextBinding;
1165 binding->m_prevBinding = 0;
1166 binding->m_nextBinding = 0;
1171 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1172 while (signalHandler) {
1173 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1174 signalHandler->m_prevSignal = 0;
1175 signalHandler->m_nextSignal = 0;
1176 delete signalHandler;
1177 signalHandler = next;
1184 propertyCache->release();
1186 if (ownContext && context)
1190 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1191 *guard = (QObject *)0;
1192 guard->objectDestroyed(object);
1196 while (notifyList->todo)
1197 notifyList->todo->disconnect();
1198 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1199 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1202 free(notifyList->notifies);
1207 delete extendedData;
1209 v8object.Clear(); // The WeakReference handler will clean the actual handle
1215 void QQmlData::parentChanged(QObject *object, QObject *parent)
1221 void QQmlData::objectNameChanged(QObject *)
1223 if (extendedData) objectNameNotifier()->notify();
1226 bool QQmlData::hasBindingBit(int bit) const
1228 if (bindingBitsSize > bit)
1229 return bindingBits[bit / 32] & (1 << (bit % 32));
1234 void QQmlData::clearBindingBit(int bit)
1236 if (bindingBitsSize > bit)
1237 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1240 void QQmlData::setBindingBit(QObject *obj, int bit)
1242 if (bindingBitsSize <= bit) {
1243 int props = obj->metaObject()->propertyCount();
1244 Q_ASSERT(bit < props);
1246 int arraySize = (props + 31) / 32;
1247 int oldArraySize = bindingBitsSize / 32;
1249 bindingBits = (quint32 *)realloc(bindingBits,
1250 arraySize * sizeof(quint32));
1252 memset(bindingBits + oldArraySize,
1254 sizeof(quint32) * (arraySize - oldArraySize));
1256 bindingBitsSize = arraySize * 32;
1259 bindingBits[bit / 32] |= (1 << (bit % 32));
1262 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1264 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1265 if (url.authority().isEmpty())
1266 return QLatin1Char(':') + url.path();
1269 return url.toLocalFile();
1273 static QString toLocalFile(const QString &url)
1275 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1278 QString file = url.mid(7);
1280 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1282 // magic for drives on windows
1283 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1289 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1291 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1292 if (url.length() > 4)
1293 return QLatin1Char(':') + url.mid(4);
1297 return toLocalFile(url);
1300 void QQmlEnginePrivate::sendQuit()
1304 if (q->receivers(SIGNAL(quit())) == 0) {
1305 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1309 static void dumpwarning(const QQmlError &error)
1311 qWarning().nospace() << qPrintable(error.toString());
1314 static void dumpwarning(const QList<QQmlError> &errors)
1316 for (int ii = 0; ii < errors.count(); ++ii)
1317 dumpwarning(errors.at(ii));
1320 void QQmlEnginePrivate::warning(const QQmlError &error)
1323 q->warnings(QList<QQmlError>() << error);
1324 if (outputWarningsToStdErr)
1328 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1331 q->warnings(errors);
1332 if (outputWarningsToStdErr)
1333 dumpwarning(errors);
1336 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1339 QQmlEnginePrivate::get(engine)->warning(error);
1344 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1347 QQmlEnginePrivate::get(engine)->warning(error);
1352 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1355 engine->warning(error);
1360 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1363 engine->warning(error);
1369 This function should be called prior to evaluation of any js expression,
1370 so that scarce resources are not freed prematurely (eg, if there is a
1371 nested javascript expression).
1373 void QQmlEnginePrivate::referenceScarceResources()
1375 scarceResourcesRefCount += 1;
1379 This function should be called after evaluation of the js expression is
1380 complete, and so the scarce resources may be freed safely.
1382 void QQmlEnginePrivate::dereferenceScarceResources()
1384 Q_ASSERT(scarceResourcesRefCount > 0);
1385 scarceResourcesRefCount -= 1;
1387 // if the refcount is zero, then evaluation of the "top level"
1388 // expression must have completed. We can safely release the
1389 // scarce resources.
1390 if (scarceResourcesRefCount == 0) {
1391 // iterate through the list and release them all.
1392 // note that the actual SRD is owned by the JS engine,
1393 // so we cannot delete the SRD; but we can free the
1394 // memory used by the variant in the SRD.
1395 while (ScarceResourceData *sr = scarceResources.first()) {
1396 sr->data = QVariant();
1397 scarceResources.remove(sr);
1403 Adds \a path as a directory where the engine searches for
1404 installed modules in a URL-based directory structure.
1405 The \a path may be a local filesystem directory or a URL.
1407 The newly added \a path will be first in the importPathList().
1409 \sa setImportPathList(), {QML Modules}
1411 void QQmlEngine::addImportPath(const QString& path)
1414 d->importDatabase.addImportPath(path);
1418 Returns the list of directories where the engine searches for
1419 installed modules in a URL-based directory structure.
1421 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1422 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1423 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1424 provided by that module. A \c qmldir file is required for defining the
1425 type version mapping and possibly QML extensions plugins.
1427 By default, the list contains the directory of the application executable,
1428 paths specified in the \c QML_IMPORT_PATH environment variable,
1429 and the builtin \c ImportsPath from QLibraryInfo.
1431 \sa addImportPath() setImportPathList()
1433 QStringList QQmlEngine::importPathList() const
1435 Q_D(const QQmlEngine);
1436 return d->importDatabase.importPathList();
1440 Sets \a paths as the list of directories where the engine searches for
1441 installed modules in a URL-based directory structure.
1443 By default, the list contains the directory of the application executable,
1444 paths specified in the \c QML_IMPORT_PATH environment variable,
1445 and the builtin \c ImportsPath from QLibraryInfo.
1447 \sa importPathList() addImportPath()
1449 void QQmlEngine::setImportPathList(const QStringList &paths)
1452 d->importDatabase.setImportPathList(paths);
1457 Adds \a path as a directory where the engine searches for
1458 native plugins for imported modules (referenced in the \c qmldir file).
1460 By default, the list contains only \c ., i.e. the engine searches
1461 in the directory of the \c qmldir file itself.
1463 The newly added \a path will be first in the pluginPathList().
1465 \sa setPluginPathList()
1467 void QQmlEngine::addPluginPath(const QString& path)
1470 d->importDatabase.addPluginPath(path);
1475 Returns the list of directories where the engine searches for
1476 native plugins for imported modules (referenced in the \c qmldir file).
1478 By default, the list contains only \c ., i.e. the engine searches
1479 in the directory of the \c qmldir file itself.
1481 \sa addPluginPath() setPluginPathList()
1483 QStringList QQmlEngine::pluginPathList() const
1485 Q_D(const QQmlEngine);
1486 return d->importDatabase.pluginPathList();
1490 Sets the list of directories where the engine searches for
1491 native plugins for imported modules (referenced in the \c qmldir file)
1494 By default, the list contains only \c ., i.e. the engine searches
1495 in the directory of the \c qmldir file itself.
1497 \sa pluginPathList() addPluginPath()
1499 void QQmlEngine::setPluginPathList(const QStringList &paths)
1502 d->importDatabase.setPluginPathList(paths);
1506 Imports the plugin named \a filePath with the \a uri provided.
1507 Returns true if the plugin was successfully imported; otherwise returns false.
1509 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1511 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1513 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1516 return d->importDatabase.importPlugin(filePath, uri, errors);
1520 Imports the plugin named \a filePath with the \a uri provided.
1521 Returns true if the plugin was successfully imported; otherwise returns false.
1523 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1525 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1527 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1530 QList<QQmlError> errors;
1531 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1532 if (!errors.isEmpty()) {
1534 for (int i = 0; i < errors.size(); ++i) {
1535 builtError = QString(QLatin1String("%1\n %2"))
1537 .arg(errors.at(i).toString());
1539 *errorString = builtError;
1545 \property QQmlEngine::offlineStoragePath
1546 \brief the directory for storing offline user data
1548 Returns the directory where SQL and other offline
1551 QQuickWebView and the SQL databases created with openDatabase()
1554 The default is QML/OfflineStorage in the platform-standard
1555 user application data directory.
1557 Note that the path may not currently exist on the filesystem, so
1558 callers wanting to \e create new files at this location should create
1559 it first - see QDir::mkpath().
1561 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1564 d->offlineStoragePath = dir;
1567 QString QQmlEngine::offlineStoragePath() const
1569 Q_D(const QQmlEngine);
1570 return d->offlineStoragePath;
1573 static void voidptr_destructor(void *v)
1575 void **ptr = (void **)v;
1579 static void *voidptr_constructor(const void *v)
1584 return new void*(*(void **)v);
1588 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1592 if (!mo->superClass()) {
1593 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1594 propertyCache.insert(mo, rv);
1597 QQmlPropertyCache *super = cache(mo->superClass());
1598 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1599 propertyCache.insert(mo, rv);
1604 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1607 QList<QQmlType *> types;
1609 int maxMinorVersion = 0;
1611 const QMetaObject *metaObject = type->metaObject();
1613 while (metaObject) {
1614 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1615 type->majorVersion(), minorVersion);
1617 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1623 metaObject = metaObject->superClass();
1626 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1628 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1632 QQmlPropertyCache *raw = cache(type->metaObject());
1634 bool hasCopied = false;
1636 for (int ii = 0; ii < types.count(); ++ii) {
1637 QQmlType *currentType = types.at(ii);
1641 int rev = currentType->metaObjectRevision();
1642 int moIndex = types.count() - 1 - ii;
1644 if (raw->allowedRevisionCache[moIndex] != rev) {
1649 raw->allowedRevisionCache[moIndex] = rev;
1653 // Test revision compatibility - the basic rule is:
1654 // * Anything that is excluded, cannot overload something that is not excluded *
1656 // Signals override:
1657 // * other signals and methods of the same name.
1658 // * properties named on<Signal Name>
1659 // * automatic <property name>Changed notify signals
1661 // Methods override:
1662 // * other methods of the same name
1664 // Properties override:
1665 // * other elements of the same name
1667 bool overloadError = false;
1668 QString overloadName;
1671 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1672 !overloadError && iter != raw->stringCache.end();
1675 QQmlPropertyData *d = *iter;
1676 if (raw->isAllowedInRevision(d))
1677 continue; // Not excluded - no problems
1679 // check that a regular "name" overload isn't happening
1680 QQmlPropertyData *current = d;
1681 while (!overloadError && current) {
1682 current = d->overrideData(current);
1683 if (current && raw->isAllowedInRevision(current))
1684 overloadError = true;
1689 if (overloadError) {
1690 if (hasCopied) raw->release();
1692 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."));
1696 if (!hasCopied) raw->addref();
1697 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1699 if (minorVersion != maxMinorVersion) {
1701 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1707 QQmlMetaType::ModuleApiInstance *
1708 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1710 Locker locker(this);
1712 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1714 a = new QQmlMetaType::ModuleApiInstance;
1715 a->scriptCallback = module.script;
1716 a->qobjectCallback = module.qobject;
1717 a->instanceMetaObject = module.instanceMetaObject;
1718 moduleApiInstances.insert(module, a);
1724 bool QQmlEnginePrivate::isQObject(int t)
1726 Locker locker(this);
1727 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1730 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1732 Locker locker(this);
1733 int t = v.userType();
1734 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1736 return *(QObject **)(v.constData());
1738 return QQmlMetaType::toQObject(v, ok);
1742 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1744 Locker locker(this);
1745 if (m_compositeTypes.contains(t))
1746 return QQmlMetaType::Object;
1747 else if (m_qmlLists.contains(t))
1748 return QQmlMetaType::List;
1750 return QQmlMetaType::typeCategory(t);
1753 bool QQmlEnginePrivate::isList(int t) const
1755 Locker locker(this);
1756 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1759 int QQmlEnginePrivate::listType(int t) const
1761 Locker locker(this);
1762 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1763 if (iter != m_qmlLists.end())
1766 return QQmlMetaType::listType(t);
1769 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1771 Locker locker(this);
1772 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1773 if (iter != m_compositeTypes.end()) {
1774 return (*iter)->root;
1776 QQmlType *type = QQmlMetaType::qmlType(t);
1777 return type?type->baseMetaObject():0;
1781 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1783 Locker locker(this);
1784 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1785 if (iter != m_compositeTypes.end()) {
1786 return (*iter)->root;
1788 QQmlType *type = QQmlMetaType::qmlType(t);
1789 return type?type->metaObject():0;
1793 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1795 QByteArray name = data->root->className();
1797 QByteArray ptr = name + '*';
1798 QByteArray lst = "QQmlListProperty<" + name + '>';
1800 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1801 voidptr_constructor);
1802 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1803 voidptr_constructor);
1807 Locker locker(this);
1808 m_qmlLists.insert(lst_type, ptr_type);
1809 m_compositeTypes.insert(ptr_type, data);
1812 bool QQml_isFileCaseCorrect(const QString &fileName)
1814 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1815 QFileInfo info(fileName);
1816 const QString absolute = info.absoluteFilePath();
1818 #if defined(Q_OS_MAC)
1819 const QString canonical = info.canonicalFilePath();
1820 #elif defined(Q_OS_WIN)
1821 wchar_t buffer[1024];
1823 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1824 if (rv == 0 || rv >= 1024) return true;
1825 rv = ::GetLongPathName(buffer, buffer, 1024);
1826 if (rv == 0 || rv >= 1024) return true;
1828 const QString canonical = QString::fromWCharArray(buffer);
1831 const int absoluteLength = absolute.length();
1832 const int canonicalLength = canonical.length();
1834 const int length = qMin(absoluteLength, canonicalLength);
1835 for (int ii = 0; ii < length; ++ii) {
1836 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1837 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1839 if (a.toLower() != c.toLower())
1851 \fn QQmlEngine *qmlEngine(const QObject *object)
1854 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1855 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1859 \fn QQmlContext *qmlContext(const QObject *object)
1862 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1863 QQmlEngine::contextForObject(object).