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>
75 #include <QtCore/qstandardpaths.h>
76 #include <QtCore/qsettings.h>
78 #include <QtCore/qmetaobject.h>
79 #include <QNetworkAccessManager>
81 #include <QMetaObject>
82 #include <QtCore/qcoreapplication.h>
83 #include <QtCore/qdir.h>
84 #include <QtCore/qmutex.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
87 #include <private/qobject_p.h>
89 #include <private/qqmllocale_p.h>
91 #ifdef Q_OS_WIN // for %APPDATA%
92 #include <qt_windows.h>
96 #define CSIDL_APPDATA 0x001a // <username>\Application Data
99 Q_DECLARE_METATYPE(QQmlProperty)
103 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
105 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
106 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
110 \qmlclass QtObject QObject
111 \ingroup qml-utility-elements
113 \brief The QtObject element is the most basic element in QML.
115 The QtObject element is a non-visual element which contains only the
118 It can be useful to create a QtObject if you need an extremely
119 lightweight element to enclose a set of custom properties:
121 \snippet doc/src/snippets/qml/qtobject.qml 0
123 It can also be useful for C++ integration, as it is just a plain
124 QObject. See the QObject documentation for further details.
127 \qmlproperty string QtObject::objectName
128 This property holds the QObject::objectName for this specific object instance.
130 This allows a C++ application to locate an item within a QML component
131 using the QObject::findChild() method. For example, the following C++
132 application locates the child \l Rectangle item and dynamically changes its
141 width: 200; height: 200
155 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
158 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
160 item->setProperty("color", QColor(Qt::yellow));
164 bool QQmlEnginePrivate::qml_debugging_enabled = false;
166 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
168 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
169 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
170 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
171 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
172 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
175 void QQmlEnginePrivate::defineModule()
177 registerBaseTypes("QtQuick", 2, 0);
178 qmlRegisterUncreatableType<QQuickApplication>("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class"));
179 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
183 \qmlclass Qt QQmlEnginePrivate
184 \ingroup qml-utility-elements
185 \brief The QML global Qt object provides useful enums and functions from Qt.
187 \keyword QmlGlobalQtObject
189 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
191 The \c Qt object is a global object with utility functions, properties and enums.
193 It is not instantiable; to use it, call the members of the global \c Qt object directly.
200 color: Qt.rgba(1, 0, 0, 1)
201 text: Qt.md5("hello, world")
208 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
209 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
213 The Qt object also contains helper functions for creating objects of specific
214 data types. This is primarily useful when setting the properties of an item
215 when the property has one of the following types:
218 \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()}
219 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
220 \li \c point - use \l{Qt::point()}{Qt.point()}
221 \li \c size - use \l{Qt::size()}{Qt.size()}
222 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
225 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
227 \section1 Date/Time Formatters
229 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
232 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
233 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
234 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
237 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
240 \section1 Dynamic Object Creation
241 The following functions on the global object allow you to dynamically create QML
242 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
246 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
247 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
253 \qmlproperty object Qt::application
256 The \c application object provides access to global application state
257 properties shared by many QML components.
263 \li \c application.active
265 This read-only property indicates whether the application is the top-most and focused
266 application, and the user is able to interact with the application. The property
267 is false when the application is in the background, the device keylock or screen
268 saver is active, the screen backlight is turned off, or the global system dialog
269 is being displayed on top of the application. It can be used for stopping and
270 pausing animations, timers and active processing of data in order to save device
271 battery power and free device memory and processor load when the application is not
275 \li \c application.layoutDirection
277 This read-only property can be used to query the default layout direction of the
278 application. On system start-up, the default layout direction depends on the
279 application's language. The property has a value of \c Qt.RightToLeft in locales
280 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
281 where the reading direction flows from left to right. You can bind to this
282 property to customize your application layouts to support both layout directions.
287 \li Qt.LeftToRight - Text and graphics elements should be positioned
289 \li Qt.RightToLeft - Text and graphics elements should be positioned
294 \li \c application.inputPanel
296 This read-only property allows access to application's QInputPanel object
297 and all its properties and slots. See the QInputPanel documentation for
298 further details. Deprecated in favor of Qt.InputMethod
301 The following example uses the \c application object to indicate
302 whether the application is currently active:
304 \snippet doc/src/snippets/qml/application.qml document
306 \qmlproperty object Qt::inputMethod
309 The \c inputMethod object allows access to application's QInputMethod object
310 and all its properties and slots. See the QInputMethod documentation for
316 \qmlmethod object Qt::include(string url, jsobject callback)
318 Includes another JavaScript file. This method can only be used from within JavaScript files,
319 and not regular QML files.
321 This imports all functions from \a url into the current script's namespace.
323 Qt.include() returns an object that describes the status of the operation. The object has
324 a single property, \c {status}, that is set to one of the following values:
327 \header \li Symbol \li Value \li Description
328 \row \li result.OK \li 0 \li The include completed successfully.
329 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
330 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
331 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
332 An additional \c exception property will be set in this case.
335 The \c status property will be updated as the operation progresses.
337 If provided, \a callback is invoked when the operation completes. The callback is passed
338 the same object as is returned from the Qt.include() call.
340 // Qt.include() is implemented in qv8include.cpp
343 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
344 : propertyCapture(0), rootContext(0), isDebugging(false),
345 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
346 cleanup(0), erroredBindings(0), inProgressCreations(0),
347 workerScriptEngine(0), activeVME(0),
348 networkAccessManager(0), networkAccessManagerFactory(0),
349 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
350 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
354 QQmlEnginePrivate::~QQmlEnginePrivate()
356 if (inProgressCreations)
357 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
360 QQmlCleanup *c = cleanup;
362 if (cleanup) cleanup->prev = &cleanup;
368 doDeleteInEngineThread();
370 if (incubationController) incubationController->d = 0;
371 incubationController = 0;
376 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
378 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
380 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
382 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
383 delete (*iter)->qobjectApi;
388 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
390 QObjectPrivate *p = QObjectPrivate::get(o);
391 if (p->declarativeData) {
392 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
393 if (d->ownContext && d->context) {
394 d->context->destroy();
400 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
402 static_cast<QQmlData *>(d)->destroyed(o);
405 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
407 static_cast<QQmlData *>(d)->parentChanged(o, p);
410 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
412 static_cast<QQmlData *>(d)->objectNameChanged(o);
415 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
417 QQmlData *ddata = QQmlData::get(object, false);
418 if (!ddata) return; // Probably being deleted
420 QQmlNotifierEndpoint *ep = ddata->notify(index);
421 if (ep) QQmlNotifier::emitNotify(ep);
424 void QQmlEnginePrivate::init()
428 static bool firstTime = true;
430 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
435 qRegisterMetaType<QVariant>("QVariant");
436 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
437 qRegisterMetaType<QJSValue>("QJSValue");
438 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
439 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
440 qRegisterMetaType<QList<int> >("QList<int>");
441 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
445 v8engine()->setEngine(q);
447 rootContext = new QQmlContext(q,true);
449 if (QCoreApplication::instance()->thread() == q->thread() &&
450 QQmlEngineDebugService::isDebuggingEnabled()) {
452 QQmlEngineDebugService::instance()->addEngine(q);
453 QV8DebugService::initialize(v8engine());
454 QV8ProfilerService::initialize();
455 QQmlProfilerService::initialize();
456 QDebugMessageService::instance();
459 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
460 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
461 QDir::separator() + QLatin1String("QML") +
462 QDir::separator() + QLatin1String("OfflineStorage");
465 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
468 if (!workerScriptEngine)
469 workerScriptEngine = new QQuickWorkerScriptEngine(q);
470 return workerScriptEngine;
476 \brief The QQmlEngine class provides an environment for instantiating QML components.
479 Each QML component is instantiated in a QQmlContext.
480 QQmlContext's are essential for passing data to QML
481 components. In QML, contexts are arranged hierarchically and this
482 hierarchy is managed by the QQmlEngine.
484 Prior to creating any QML components, an application must have
485 created a QQmlEngine to gain access to a QML context. The
486 following example shows how to create a simple Text item.
490 QQmlComponent component(&engine);
491 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
492 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
494 //add item to view, etc
498 In this case, the Text item will be created in the engine's
499 \l {QQmlEngine::rootContext()}{root context}.
501 \sa QQmlComponent QQmlContext
505 Create a new QQmlEngine with the given \a parent.
507 QQmlEngine::QQmlEngine(QObject *parent)
508 : QJSEngine(*new QQmlEnginePrivate(this), parent)
515 Destroys the QQmlEngine.
517 Any QQmlContext's created on this engine will be
518 invalidated, but not destroyed (unless they are parented to the
521 QQmlEngine::~QQmlEngine()
524 if (d->isDebugging) {
525 QQmlEngineDebugService::instance()->remEngine(this);
528 // if we are the parent of any of the qobject module api instances,
529 // we need to remove them from our internal list, in order to prevent
530 // a segfault in engine private dtor.
531 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
532 QObject *currQObjectApi = 0;
533 QQmlMetaType::ModuleApiInstance *currInstance = 0;
534 foreach (const QQmlMetaType::ModuleApi &key, keys) {
535 currInstance = d->moduleApiInstances.value(key);
536 currQObjectApi = currInstance->qobjectApi;
537 if (this->children().contains(currQObjectApi)) {
538 delete currQObjectApi;
540 d->moduleApiInstances.remove(key);
544 // ensure we clean up QObjects with JS ownership
547 if (d->incubationController)
548 d->incubationController->d = 0;
551 /*! \fn void QQmlEngine::quit()
552 This signal is emitted when the QML loaded by the engine would like to quit.
555 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
556 This signal is emitted when \a warnings messages are generated by QML.
560 Clears the engine's internal component cache.
562 Normally the QQmlEngine caches components loaded from qml
563 files. This method clears this cache and forces the component to be
566 void QQmlEngine::clearComponentCache()
569 d->typeLoader.clearCache();
573 Returns the engine's root context.
575 The root context is automatically created by the QQmlEngine.
576 Data that should be available to all QML component instances
577 instantiated by the engine should be put in the root context.
579 Additional data that should only be available to a subset of
580 component instances should be added to sub-contexts parented to the
583 QQmlContext *QQmlEngine::rootContext() const
585 Q_D(const QQmlEngine);
586 return d->rootContext;
590 Sets the \a factory to use for creating QNetworkAccessManager(s).
592 QNetworkAccessManager is used for all network access by QML. By
593 implementing a factory it is possible to create custom
594 QNetworkAccessManager with specialized caching, proxy and cookie
597 The factory must be set before executing the engine.
599 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
602 QMutexLocker locker(&d->mutex);
603 d->networkAccessManagerFactory = factory;
607 Returns the current QQmlNetworkAccessManagerFactory.
609 \sa setNetworkAccessManagerFactory()
611 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
613 Q_D(const QQmlEngine);
614 return d->networkAccessManagerFactory;
617 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
620 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
622 void *args[] = { 0 };
623 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
627 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
629 QMutexLocker locker(&mutex);
630 QNetworkAccessManager *nam;
631 if (networkAccessManagerFactory) {
632 nam = networkAccessManagerFactory->create(parent);
634 nam = new QNetworkAccessManager(parent);
640 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
642 Q_Q(const QQmlEngine);
643 if (!networkAccessManager)
644 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
645 return networkAccessManager;
649 Returns a common QNetworkAccessManager which can be used by any QML
650 element instantiated by this engine.
652 If a QQmlNetworkAccessManagerFactory has been set and a
653 QNetworkAccessManager has not yet been created, the
654 QQmlNetworkAccessManagerFactory will be used to create the
655 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
656 will have no proxy or cache set.
658 \sa setNetworkAccessManagerFactory()
660 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
662 Q_D(const QQmlEngine);
663 return d->getNetworkAccessManager();
668 Sets the \a provider to use for images requested via the \e
669 image: url scheme, with host \a providerId. The QQmlEngine
670 takes ownership of \a provider.
672 Image providers enable support for pixmap and threaded image
673 requests. See the QQmlImageProvider documentation for details on
674 implementing and using image providers.
676 All required image providers should be added to the engine before any
677 QML sources files are loaded.
679 \sa removeImageProvider()
681 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProvider *provider)
684 QMutexLocker locker(&d->mutex);
685 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProvider>(provider));
689 Returns the QQmlImageProvider set for \a providerId.
691 Returns the provider if it was found; otherwise returns 0.
693 QQmlImageProvider *QQmlEngine::imageProvider(const QString &providerId) const
695 Q_D(const QQmlEngine);
696 QMutexLocker locker(&d->mutex);
697 return d->imageProviders.value(providerId).data();
701 Removes the QQmlImageProvider for \a providerId.
703 \sa addImageProvider()
705 void QQmlEngine::removeImageProvider(const QString &providerId)
708 QMutexLocker locker(&d->mutex);
709 d->imageProviders.take(providerId);
712 QQmlImageProvider::ImageType QQmlEnginePrivate::getImageProviderType(const QUrl &url)
714 QMutexLocker locker(&mutex);
715 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
718 return provider->imageType();
719 return QQmlImageProvider::Invalid;
722 QQuickTextureFactory *QQmlEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
724 QMutexLocker locker(&mutex);
725 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
728 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
729 return provider->requestTexture(imageId, size, req_size);
734 QImage QQmlEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
736 QMutexLocker locker(&mutex);
738 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
741 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
742 image = provider->requestImage(imageId, size, req_size);
747 QPixmap QQmlEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
749 QMutexLocker locker(&mutex);
751 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
754 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
755 pixmap = provider->requestPixmap(imageId, size, req_size);
761 Return the base URL for this engine. The base URL is only used to
762 resolve components when a relative URL is passed to the
763 QQmlComponent constructor.
765 If a base URL has not been explicitly set, this method returns the
766 application's current working directory.
770 QUrl QQmlEngine::baseUrl() const
772 Q_D(const QQmlEngine);
773 if (d->baseUrl.isEmpty()) {
774 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
781 Set the base URL for this engine to \a url.
785 void QQmlEngine::setBaseUrl(const QUrl &url)
792 Returns true if warning messages will be output to stderr in addition
793 to being emitted by the warnings() signal, otherwise false.
795 The default value is true.
797 bool QQmlEngine::outputWarningsToStandardError() const
799 Q_D(const QQmlEngine);
800 return d->outputWarningsToStdErr;
804 Set whether warning messages will be output to stderr to \a enabled.
806 If \a enabled is true, any warning messages generated by QML will be
807 output to stderr and emitted by the warnings() signal. If \a enabled
808 is false, on the warnings() signal will be emitted. This allows
809 applications to handle warning output themselves.
811 The default value is true.
813 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
816 d->outputWarningsToStdErr = enabled;
820 Attempt to free unused memory.
822 void QQmlEngine::collectGarbage()
828 Returns the QQmlContext for the \a object, or 0 if no
829 context has been set.
831 When the QQmlEngine instantiates a QObject, the context is
834 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
839 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
842 static_cast<QQmlData *>(priv->declarativeData);
846 else if (data->outerContext)
847 return data->outerContext->asQQmlContext();
853 Sets the QQmlContext for the \a object to \a context.
854 If the \a object already has a context, a warning is
855 output, but the context is not changed.
857 When the QQmlEngine instantiates a QObject, the context is
860 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
862 if (!object || !context)
865 QQmlData *data = QQmlData::get(object, true);
867 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
871 QQmlContextData *contextData = QQmlContextData::get(context);
872 contextData->addObject(object);
876 \enum QQmlEngine::ObjectOwnership
878 Ownership controls whether or not QML automatically destroys the
879 QObject when the object is garbage collected by the JavaScript
880 engine. The two ownership options are:
882 \value CppOwnership The object is owned by C++ code, and will
883 never be deleted by QML. The JavaScript destroy() method cannot be
884 used on objects with CppOwnership. This option is similar to
885 QScriptEngine::QtOwnership.
887 \value JavaScriptOwnership The object is owned by JavaScript.
888 When the object is returned to QML as the return value of a method
889 call or property access, QML will delete the object if there are no
890 remaining JavaScript references to it and it has no
891 QObject::parent(). This option is similar to
892 QScriptEngine::ScriptOwnership.
894 Generally an application doesn't need to set an object's ownership
895 explicitly. QML uses a heuristic to set the default object
896 ownership. By default, an object that is created by QML has
897 JavaScriptOwnership. The exception to this are the root objects
898 created by calling QQmlComponent::create() or
899 QQmlComponent::beginCreate() which have CppOwnership by
900 default. The ownership of these root-level objects is considered to
901 have been transferred to the C++ caller.
903 Objects not-created by QML have CppOwnership by default. The
904 exception to this is objects returned from a C++ method call. The
905 ownership of these objects is passed to JavaScript.
907 Calling setObjectOwnership() overrides the default ownership
908 heuristic used by QML.
912 Sets the \a ownership of \a object.
914 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
919 QQmlData *ddata = QQmlData::get(object, true);
923 ddata->indestructible = (ownership == CppOwnership)?true:false;
924 ddata->explicitIndestructibleSet = true;
928 Returns the ownership of \a object.
930 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
935 QQmlData *ddata = QQmlData::get(object, false);
939 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
942 bool QQmlEngine::event(QEvent *e)
945 if (e->type() == QEvent::User)
946 d->doDeleteInEngineThread();
948 return QJSEngine::event(e);
951 void QQmlEnginePrivate::doDeleteInEngineThread()
953 QFieldList<Deletable, &Deletable::next> list;
955 list.copyAndClear(toDeleteInEngineThread);
958 while (Deletable *d = list.takeFirst())
962 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
964 QQmlData *data = QQmlData::get(object);
966 if (data && data->deferredComponent) {
967 QQmlObjectCreatingProfiler prof;
969 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
970 prof.setTypeName(type ? type->qmlTypeName()
971 : QString::fromUtf8(object->metaObject()->className()));
972 if (data->outerContext)
973 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
975 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
977 QQmlComponentPrivate::ConstructionState state;
978 QQmlComponentPrivate::beginDeferred(ep, object, &state);
980 data->deferredComponent->release();
981 data->deferredComponent = 0;
983 QQmlComponentPrivate::complete(ep, &state);
987 QQmlContext *qmlContext(const QObject *obj)
989 return QQmlEngine::contextForObject(obj);
992 QQmlEngine *qmlEngine(const QObject *obj)
994 QQmlData *data = QQmlData::get(obj, false);
995 if (!data || !data->context)
997 return data->context->engine;
1000 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1002 QQmlData *data = QQmlData::get(object);
1004 return 0; // Attached properties are only on objects created by QML
1006 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1010 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1014 rv = pf(const_cast<QObject *>(object));
1017 data->attachedProperties()->insert(id, rv);
1022 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1023 const QMetaObject *attachedMetaObject, bool create)
1026 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1028 if (*idCache == -1 || !object)
1031 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1034 QQmlDebuggingEnabler::QQmlDebuggingEnabler()
1036 #ifndef QQML_NO_DEBUG_PROTOCOL
1037 if (!QQmlEnginePrivate::qml_debugging_enabled) {
1038 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1040 QQmlEnginePrivate::qml_debugging_enabled = true;
1045 class QQmlDataExtended {
1048 ~QQmlDataExtended();
1050 QHash<int, QObject *> attachedProperties;
1051 QQmlNotifier objectNameNotifier;
1054 QQmlDataExtended::QQmlDataExtended()
1058 QQmlDataExtended::~QQmlDataExtended()
1062 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1065 layout(endpoint->next);
1067 int index = endpoint->sourceSignal;
1068 index = qMin(index, 0xFFFF - 1);
1070 endpoint->next = notifies[index];
1071 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1072 endpoint->prev = ¬ifies[index];
1073 notifies[index] = endpoint;
1076 void QQmlData::NotifyList::layout()
1078 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1081 QQmlNotifierEndpoint **old = notifies;
1082 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1083 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1084 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1085 sizeof(QQmlNotifierEndpoint*);
1086 memset(notifies + notifiesSize, 0, memsetSize);
1088 if (notifies != old) {
1089 for (int ii = 0; ii < notifiesSize; ++ii)
1091 notifies[ii]->prev = ¬ifies[ii];
1094 notifiesSize = maximumTodoIndex + 1;
1099 maximumTodoIndex = 0;
1103 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1106 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1107 notifyList->connectionMask = 0;
1108 notifyList->maximumTodoIndex = 0;
1109 notifyList->notifiesSize = 0;
1110 notifyList->todo = 0;
1111 notifyList->notifies = 0;
1114 Q_ASSERT(!endpoint->isConnected());
1116 index = qMin(index, 0xFFFF - 1);
1117 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1119 if (index < notifyList->notifiesSize) {
1121 endpoint->next = notifyList->notifies[index];
1122 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1123 endpoint->prev = ¬ifyList->notifies[index];
1124 notifyList->notifies[index] = endpoint;
1127 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1129 endpoint->next = notifyList->todo;
1130 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1131 endpoint->prev = ¬ifyList->todo;
1132 notifyList->todo = endpoint;
1136 QQmlNotifier *QQmlData::objectNameNotifier() const
1138 if (!extendedData) extendedData = new QQmlDataExtended;
1139 return &extendedData->objectNameNotifier;
1142 QHash<int, QObject *> *QQmlData::attachedProperties() const
1144 if (!extendedData) extendedData = new QQmlDataExtended;
1145 return &extendedData->attachedProperties;
1148 void QQmlData::destroyed(QObject *object)
1150 if (deferredComponent)
1151 deferredComponent->release();
1153 if (nextContextObject)
1154 nextContextObject->prevContextObject = prevContextObject;
1155 if (prevContextObject)
1156 *prevContextObject = nextContextObject;
1158 QQmlAbstractBinding *binding = bindings;
1160 QQmlAbstractBinding *next = binding->m_nextBinding;
1161 binding->m_prevBinding = 0;
1162 binding->m_nextBinding = 0;
1171 propertyCache->release();
1173 if (ownContext && context)
1177 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1178 *guard = (QObject *)0;
1179 guard->objectDestroyed(object);
1183 while (notifyList->todo)
1184 notifyList->todo->disconnect();
1185 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1186 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1189 free(notifyList->notifies);
1194 delete extendedData;
1196 v8object.Clear(); // The WeakReference handler will clean the actual handle
1202 void QQmlData::parentChanged(QObject *object, QObject *parent)
1208 void QQmlData::objectNameChanged(QObject *)
1210 if (extendedData) objectNameNotifier()->notify();
1213 bool QQmlData::hasBindingBit(int bit) const
1215 if (bindingBitsSize > bit)
1216 return bindingBits[bit / 32] & (1 << (bit % 32));
1221 void QQmlData::clearBindingBit(int bit)
1223 if (bindingBitsSize > bit)
1224 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1227 void QQmlData::setBindingBit(QObject *obj, int bit)
1229 if (bindingBitsSize <= bit) {
1230 int props = obj->metaObject()->propertyCount();
1231 Q_ASSERT(bit < props);
1233 int arraySize = (props + 31) / 32;
1234 int oldArraySize = bindingBitsSize / 32;
1236 bindingBits = (quint32 *)realloc(bindingBits,
1237 arraySize * sizeof(quint32));
1239 memset(bindingBits + oldArraySize,
1241 sizeof(quint32) * (arraySize - oldArraySize));
1243 bindingBitsSize = arraySize * 32;
1246 bindingBits[bit / 32] |= (1 << (bit % 32));
1249 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1251 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1252 if (url.authority().isEmpty())
1253 return QLatin1Char(':') + url.path();
1256 return url.toLocalFile();
1260 static QString toLocalFile(const QString &url)
1262 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1265 QString file = url.mid(7);
1267 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1269 // magic for drives on windows
1270 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1276 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1278 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1279 if (url.length() > 4)
1280 return QLatin1Char(':') + url.mid(4);
1284 return toLocalFile(url);
1287 void QQmlEnginePrivate::sendQuit()
1291 if (q->receivers(SIGNAL(quit())) == 0) {
1292 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1296 static void dumpwarning(const QQmlError &error)
1298 qWarning().nospace() << qPrintable(error.toString());
1301 static void dumpwarning(const QList<QQmlError> &errors)
1303 for (int ii = 0; ii < errors.count(); ++ii)
1304 dumpwarning(errors.at(ii));
1307 void QQmlEnginePrivate::warning(const QQmlError &error)
1310 q->warnings(QList<QQmlError>() << error);
1311 if (outputWarningsToStdErr)
1315 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1318 q->warnings(errors);
1319 if (outputWarningsToStdErr)
1320 dumpwarning(errors);
1323 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1326 QQmlEnginePrivate::get(engine)->warning(error);
1331 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1334 QQmlEnginePrivate::get(engine)->warning(error);
1339 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1342 engine->warning(error);
1347 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1350 engine->warning(error);
1356 This function should be called prior to evaluation of any js expression,
1357 so that scarce resources are not freed prematurely (eg, if there is a
1358 nested javascript expression).
1360 void QQmlEnginePrivate::referenceScarceResources()
1362 scarceResourcesRefCount += 1;
1366 This function should be called after evaluation of the js expression is
1367 complete, and so the scarce resources may be freed safely.
1369 void QQmlEnginePrivate::dereferenceScarceResources()
1371 Q_ASSERT(scarceResourcesRefCount > 0);
1372 scarceResourcesRefCount -= 1;
1374 // if the refcount is zero, then evaluation of the "top level"
1375 // expression must have completed. We can safely release the
1376 // scarce resources.
1377 if (scarceResourcesRefCount == 0) {
1378 // iterate through the list and release them all.
1379 // note that the actual SRD is owned by the JS engine,
1380 // so we cannot delete the SRD; but we can free the
1381 // memory used by the variant in the SRD.
1382 while (ScarceResourceData *sr = scarceResources.first()) {
1383 sr->data = QVariant();
1384 scarceResources.remove(sr);
1390 Adds \a path as a directory where the engine searches for
1391 installed modules in a URL-based directory structure.
1392 The \a path may be a local filesystem directory or a URL.
1394 The newly added \a path will be first in the importPathList().
1396 \sa setImportPathList(), {QML Modules}
1398 void QQmlEngine::addImportPath(const QString& path)
1401 d->importDatabase.addImportPath(path);
1405 Returns the list of directories where the engine searches for
1406 installed modules in a URL-based directory structure.
1408 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1409 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1410 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1411 provided by that module. A \c qmldir file is required for defining the
1412 type version mapping and possibly QML extensions plugins.
1414 By default, the list contains the directory of the application executable,
1415 paths specified in the \c QML_IMPORT_PATH environment variable,
1416 and the builtin \c ImportsPath from QLibraryInfo.
1418 \sa addImportPath() setImportPathList()
1420 QStringList QQmlEngine::importPathList() const
1422 Q_D(const QQmlEngine);
1423 return d->importDatabase.importPathList();
1427 Sets \a paths as the list of directories where the engine searches for
1428 installed modules in a URL-based directory structure.
1430 By default, the list contains the directory of the application executable,
1431 paths specified in the \c QML_IMPORT_PATH environment variable,
1432 and the builtin \c ImportsPath from QLibraryInfo.
1434 \sa importPathList() addImportPath()
1436 void QQmlEngine::setImportPathList(const QStringList &paths)
1439 d->importDatabase.setImportPathList(paths);
1444 Adds \a path as a directory where the engine searches for
1445 native plugins for imported modules (referenced in the \c qmldir file).
1447 By default, the list contains only \c ., i.e. the engine searches
1448 in the directory of the \c qmldir file itself.
1450 The newly added \a path will be first in the pluginPathList().
1452 \sa setPluginPathList()
1454 void QQmlEngine::addPluginPath(const QString& path)
1457 d->importDatabase.addPluginPath(path);
1462 Returns the list of directories where the engine searches for
1463 native plugins for imported modules (referenced in the \c qmldir file).
1465 By default, the list contains only \c ., i.e. the engine searches
1466 in the directory of the \c qmldir file itself.
1468 \sa addPluginPath() setPluginPathList()
1470 QStringList QQmlEngine::pluginPathList() const
1472 Q_D(const QQmlEngine);
1473 return d->importDatabase.pluginPathList();
1477 Sets the list of directories where the engine searches for
1478 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 \sa pluginPathList() addPluginPath()
1486 void QQmlEngine::setPluginPathList(const QStringList &paths)
1489 d->importDatabase.setPluginPathList(paths);
1493 Imports the plugin named \a filePath with the \a uri provided.
1494 Returns true if the plugin was successfully imported; otherwise returns false.
1496 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1498 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1500 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1503 return d->importDatabase.importPlugin(filePath, uri, errors);
1507 Imports the plugin named \a filePath with the \a uri provided.
1508 Returns true if the plugin was successfully imported; otherwise returns false.
1510 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1512 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1514 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1517 QList<QQmlError> errors;
1518 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1519 if (!errors.isEmpty()) {
1521 for (int i = 0; i < errors.size(); ++i) {
1522 builtError = QString(QLatin1String("%1\n %2"))
1524 .arg(errors.at(i).toString());
1526 *errorString = builtError;
1532 \property QQmlEngine::offlineStoragePath
1533 \brief the directory for storing offline user data
1535 Returns the directory where SQL and other offline
1538 QQuickWebView and the SQL databases created with openDatabase()
1541 The default is QML/OfflineStorage in the platform-standard
1542 user application data directory.
1544 Note that the path may not currently exist on the filesystem, so
1545 callers wanting to \e create new files at this location should create
1546 it first - see QDir::mkpath().
1548 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1551 d->offlineStoragePath = dir;
1554 QString QQmlEngine::offlineStoragePath() const
1556 Q_D(const QQmlEngine);
1557 return d->offlineStoragePath;
1560 static void voidptr_destructor(void *v)
1562 void **ptr = (void **)v;
1566 static void *voidptr_constructor(const void *v)
1571 return new void*(*(void **)v);
1575 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1579 if (!mo->superClass()) {
1580 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1581 propertyCache.insert(mo, rv);
1584 QQmlPropertyCache *super = cache(mo->superClass());
1585 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1586 propertyCache.insert(mo, rv);
1591 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1594 QList<QQmlType *> types;
1596 int maxMinorVersion = 0;
1598 const QMetaObject *metaObject = type->metaObject();
1600 while (metaObject) {
1601 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1602 type->majorVersion(), minorVersion);
1604 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1610 metaObject = metaObject->superClass();
1613 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1615 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1619 QQmlPropertyCache *raw = cache(type->metaObject());
1621 bool hasCopied = false;
1623 for (int ii = 0; ii < types.count(); ++ii) {
1624 QQmlType *currentType = types.at(ii);
1628 int rev = currentType->metaObjectRevision();
1629 int moIndex = types.count() - 1 - ii;
1631 if (raw->allowedRevisionCache[moIndex] != rev) {
1636 raw->allowedRevisionCache[moIndex] = rev;
1640 // Test revision compatibility - the basic rule is:
1641 // * Anything that is excluded, cannot overload something that is not excluded *
1643 // Signals override:
1644 // * other signals and methods of the same name.
1645 // * properties named on<Signal Name>
1646 // * automatic <property name>Changed notify signals
1648 // Methods override:
1649 // * other methods of the same name
1651 // Properties override:
1652 // * other elements of the same name
1654 bool overloadError = false;
1655 QString overloadName;
1658 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1659 !overloadError && iter != raw->stringCache.end();
1662 QQmlPropertyData *d = *iter;
1663 if (raw->isAllowedInRevision(d))
1664 continue; // Not excluded - no problems
1666 // check that a regular "name" overload isn't happening
1667 QQmlPropertyData *current = d;
1668 while (!overloadError && current) {
1669 current = d->overrideData(current);
1670 if (current && raw->isAllowedInRevision(current))
1671 overloadError = true;
1676 if (overloadError) {
1677 if (hasCopied) raw->release();
1679 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."));
1683 if (!hasCopied) raw->addref();
1684 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1686 if (minorVersion != maxMinorVersion) {
1688 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1694 QQmlMetaType::ModuleApiInstance *
1695 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1697 Locker locker(this);
1699 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1701 a = new QQmlMetaType::ModuleApiInstance;
1702 a->scriptCallback = module.script;
1703 a->qobjectCallback = module.qobject;
1704 moduleApiInstances.insert(module, a);
1710 bool QQmlEnginePrivate::isQObject(int t)
1712 Locker locker(this);
1713 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1716 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1718 Locker locker(this);
1719 int t = v.userType();
1720 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1722 return *(QObject **)(v.constData());
1724 return QQmlMetaType::toQObject(v, ok);
1728 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1730 Locker locker(this);
1731 if (m_compositeTypes.contains(t))
1732 return QQmlMetaType::Object;
1733 else if (m_qmlLists.contains(t))
1734 return QQmlMetaType::List;
1736 return QQmlMetaType::typeCategory(t);
1739 bool QQmlEnginePrivate::isList(int t) const
1741 Locker locker(this);
1742 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1745 int QQmlEnginePrivate::listType(int t) const
1747 Locker locker(this);
1748 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1749 if (iter != m_qmlLists.end())
1752 return QQmlMetaType::listType(t);
1755 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1757 Locker locker(this);
1758 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1759 if (iter != m_compositeTypes.end()) {
1760 return (*iter)->root;
1762 QQmlType *type = QQmlMetaType::qmlType(t);
1763 return type?type->baseMetaObject():0;
1767 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1769 Locker locker(this);
1770 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1771 if (iter != m_compositeTypes.end()) {
1772 return (*iter)->root;
1774 QQmlType *type = QQmlMetaType::qmlType(t);
1775 return type?type->metaObject():0;
1779 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1781 QByteArray name = data->root->className();
1783 QByteArray ptr = name + '*';
1784 QByteArray lst = "QQmlListProperty<" + name + '>';
1786 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1787 voidptr_constructor);
1788 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1789 voidptr_constructor);
1793 Locker locker(this);
1794 m_qmlLists.insert(lst_type, ptr_type);
1795 m_compositeTypes.insert(ptr_type, data);
1798 bool QQml_isFileCaseCorrect(const QString &fileName)
1800 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1801 QFileInfo info(fileName);
1802 const QString absolute = info.absoluteFilePath();
1804 #if defined(Q_OS_MAC)
1805 const QString canonical = info.canonicalFilePath();
1806 #elif defined(Q_OS_WIN)
1807 wchar_t buffer[1024];
1809 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1810 if (rv == 0 || rv >= 1024) return true;
1811 rv = ::GetLongPathName(buffer, buffer, 1024);
1812 if (rv == 0 || rv >= 1024) return true;
1814 const QString canonical = QString::fromWCharArray(buffer);
1817 const int absoluteLength = absolute.length();
1818 const int canonicalLength = canonical.length();
1820 const int length = qMin(absoluteLength, canonicalLength);
1821 for (int ii = 0; ii < length; ++ii) {
1822 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1823 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1825 if (a.toLower() != c.toLower())
1837 \fn QQmlEngine *qmlEngine(const QObject *object)
1840 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1841 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1845 \fn QQmlContext *qmlContext(const QObject *object)
1848 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1849 QQmlEngine::contextForObject(object).