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 "qqmlbinding_p_p.h"
53 #include "qqmlvme_p.h"
54 #include <private/qqmlenginedebugservice_p.h>
55 #include "qqmlstringconverters_p.h"
56 #include "qqmlxmlhttprequest_p.h"
57 #include "qqmlscriptstring.h"
58 #include "qqmlglobal_p.h"
59 #include "qquicklistmodel_p.h"
60 #include "qquickworkerscript_p.h"
61 #include "qqmlcomponent_p.h"
62 #include "qqmlnetworkaccessmanagerfactory.h"
63 #include "qqmlimageprovider.h"
64 #include "qqmldirparser_p.h"
65 #include "qqmlextensioninterface.h"
66 #include "qqmllist_p.h"
67 #include "qqmltypenamecache_p.h"
68 #include "qqmlnotifier_p.h"
69 #include <private/qqmlprofilerservice_p.h>
70 #include <private/qquickapplication_p.h>
71 #include <private/qv8debugservice_p.h>
72 #include <private/qdebugmessageservice_p.h>
73 #include "qqmlincubator.h"
74 #include <private/qv8profilerservice_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 qmlRegisterType<QQmlBinding>();
180 qmlRegisterUncreatableType<QQuickApplication>("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class"));
181 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
185 \qmlclass Qt QQmlEnginePrivate
186 \ingroup qml-utility-elements
187 \brief The QML global Qt object provides useful enums and functions from Qt.
189 \keyword QmlGlobalQtObject
191 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
193 The \c Qt object is a global object with utility functions, properties and enums.
195 It is not instantiable; to use it, call the members of the global \c Qt object directly.
202 color: Qt.rgba(1, 0, 0, 1)
203 text: Qt.md5("hello, world")
210 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
211 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
215 The Qt object also contains helper functions for creating objects of specific
216 data types. This is primarily useful when setting the properties of an item
217 when the property has one of the following types:
220 \o \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()}
221 \o \c rect - use \l{Qt::rect()}{Qt.rect()}
222 \o \c point - use \l{Qt::point()}{Qt.point()}
223 \o \c size - use \l{Qt::size()}{Qt.size()}
224 \o \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
227 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
229 \section1 Date/Time Formatters
231 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
234 \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
235 \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
236 \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
239 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
242 \section1 Dynamic Object Creation
243 The following functions on the global object allow you to dynamically create QML
244 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
248 \o \l{Qt::createComponent()}{object Qt.createComponent(url)}
249 \o \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
255 \qmlproperty object Qt::application
258 The \c application object provides access to global application state
259 properties shared by many QML components.
265 \o \c application.active
267 This read-only property indicates whether the application is the top-most and focused
268 application, and the user is able to interact with the application. The property
269 is false when the application is in the background, the device keylock or screen
270 saver is active, the screen backlight is turned off, or the global system dialog
271 is being displayed on top of the application. It can be used for stopping and
272 pausing animations, timers and active processing of data in order to save device
273 battery power and free device memory and processor load when the application is not
277 \o \c application.layoutDirection
279 This read-only property can be used to query the default layout direction of the
280 application. On system start-up, the default layout direction depends on the
281 application's language. The property has a value of \c Qt.RightToLeft in locales
282 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
283 where the reading direction flows from left to right. You can bind to this
284 property to customize your application layouts to support both layout directions.
289 \o Qt.LeftToRight - Text and graphics elements should be positioned
291 \o Qt.RightToLeft - Text and graphics elements should be positioned
296 \o \c application.inputPanel
298 This read-only property allows access to application's QInputPanel object
299 and all its properties and slots. See the QInputPanel documentation for
300 further details. Deprecated in favor of Qt.InputMethod
303 The following example uses the \c application object to indicate
304 whether the application is currently active:
306 \snippet doc/src/snippets/qml/application.qml document
308 \qmlproperty object Qt::inputMethod
311 The \c inputMethod object allows access to application's QInputMethod object
312 and all its properties and slots. See the QInputMethod documentation for
318 \qmlmethod object Qt::include(string url, jsobject callback)
320 Includes another JavaScript file. This method can only be used from within JavaScript files,
321 and not regular QML files.
323 This imports all functions from \a url into the current script's namespace.
325 Qt.include() returns an object that describes the status of the operation. The object has
326 a single property, \c {status}, that is set to one of the following values:
329 \header \o Symbol \o Value \o Description
330 \row \o result.OK \o 0 \o The include completed successfully.
331 \row \o result.LOADING \o 1 \o Data is being loaded from the network.
332 \row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url.
333 \row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code.
334 An additional \c exception property will be set in this case.
337 The \c status property will be updated as the operation progresses.
339 If provided, \a callback is invoked when the operation completes. The callback is passed
340 the same object as is returned from the Qt.include() call.
342 // Qt.include() is implemented in qv8include.cpp
345 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
346 : propertyCapture(0), rootContext(0), isDebugging(false),
347 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
348 cleanup(0), erroredBindings(0), inProgressCreations(0),
349 workerScriptEngine(0), activeVME(0),
350 networkAccessManager(0), networkAccessManagerFactory(0),
351 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
352 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
356 QQmlEnginePrivate::~QQmlEnginePrivate()
358 if (inProgressCreations)
359 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
362 QQmlCleanup *c = cleanup;
364 if (cleanup) cleanup->prev = &cleanup;
370 doDeleteInEngineThread();
372 if (incubationController) incubationController->d = 0;
373 incubationController = 0;
378 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
380 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
382 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
384 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
385 delete (*iter)->qobjectApi;
390 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
392 QObjectPrivate *p = QObjectPrivate::get(o);
393 if (p->declarativeData) {
394 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
395 if (d->ownContext && d->context) {
396 d->context->destroy();
402 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
404 static_cast<QQmlData *>(d)->destroyed(o);
407 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
409 static_cast<QQmlData *>(d)->parentChanged(o, p);
412 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
414 static_cast<QQmlData *>(d)->objectNameChanged(o);
417 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
419 QQmlData *ddata = QQmlData::get(object, false);
420 if (!ddata) return; // Probably being deleted
422 QQmlNotifierEndpoint *ep = ddata->notify(index);
423 if (ep) QQmlNotifier::emitNotify(ep);
426 void QQmlEnginePrivate::init()
430 static bool firstTime = true;
432 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
437 qRegisterMetaType<QVariant>("QVariant");
438 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
439 qRegisterMetaType<QJSValue>("QJSValue");
440 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
441 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
442 qRegisterMetaType<QList<int> >("QList<int>");
443 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
447 v8engine()->setEngine(q);
449 rootContext = new QQmlContext(q,true);
451 if (QCoreApplication::instance()->thread() == q->thread() &&
452 QQmlEngineDebugService::isDebuggingEnabled()) {
454 QQmlEngineDebugService::instance()->addEngine(q);
455 QV8DebugService::initialize(v8engine());
456 QV8ProfilerService::initialize();
457 QQmlProfilerService::initialize();
458 QDebugMessageService::instance();
461 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
462 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
463 QDir::separator() + QLatin1String("QML") +
464 QDir::separator() + QLatin1String("OfflineStorage");
467 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
470 if (!workerScriptEngine)
471 workerScriptEngine = new QQuickWorkerScriptEngine(q);
472 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 \sa QQmlComponent QQmlContext
507 Create a new QQmlEngine with the given \a parent.
509 QQmlEngine::QQmlEngine(QObject *parent)
510 : QJSEngine(*new QQmlEnginePrivate(this), parent)
517 Destroys the QQmlEngine.
519 Any QQmlContext's created on this engine will be
520 invalidated, but not destroyed (unless they are parented to the
523 QQmlEngine::~QQmlEngine()
526 if (d->isDebugging) {
527 QQmlEngineDebugService::instance()->remEngine(this);
530 // if we are the parent of any of the qobject module api instances,
531 // we need to remove them from our internal list, in order to prevent
532 // a segfault in engine private dtor.
533 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
534 QObject *currQObjectApi = 0;
535 QQmlMetaType::ModuleApiInstance *currInstance = 0;
536 foreach (const QQmlMetaType::ModuleApi &key, keys) {
537 currInstance = d->moduleApiInstances.value(key);
538 currQObjectApi = currInstance->qobjectApi;
539 if (this->children().contains(currQObjectApi)) {
540 delete currQObjectApi;
542 d->moduleApiInstances.remove(key);
546 // ensure we clean up QObjects with JS ownership
549 if (d->incubationController)
550 d->incubationController->d = 0;
553 /*! \fn void QQmlEngine::quit()
554 This signal is emitted when the QML loaded by the engine would like to quit.
557 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
558 This signal is emitted when \a warnings messages are generated by QML.
562 Clears the engine's internal component cache.
564 Normally the QQmlEngine caches components loaded from qml
565 files. This method clears this cache and forces the component to be
568 void QQmlEngine::clearComponentCache()
571 d->typeLoader.clearCache();
575 Returns the engine's root context.
577 The root context is automatically created by the QQmlEngine.
578 Data that should be available to all QML component instances
579 instantiated by the engine should be put in the root context.
581 Additional data that should only be available to a subset of
582 component instances should be added to sub-contexts parented to the
585 QQmlContext *QQmlEngine::rootContext() const
587 Q_D(const QQmlEngine);
588 return d->rootContext;
592 Sets the \a factory to use for creating QNetworkAccessManager(s).
594 QNetworkAccessManager is used for all network access by QML. By
595 implementing a factory it is possible to create custom
596 QNetworkAccessManager with specialized caching, proxy and cookie
599 The factory must be set before executing the engine.
601 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
604 QMutexLocker locker(&d->mutex);
605 d->networkAccessManagerFactory = factory;
609 Returns the current QQmlNetworkAccessManagerFactory.
611 \sa setNetworkAccessManagerFactory()
613 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
615 Q_D(const QQmlEngine);
616 return d->networkAccessManagerFactory;
619 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
622 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
624 void *args[] = { 0 };
625 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
629 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
631 QMutexLocker locker(&mutex);
632 QNetworkAccessManager *nam;
633 if (networkAccessManagerFactory) {
634 nam = networkAccessManagerFactory->create(parent);
636 nam = new QNetworkAccessManager(parent);
642 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
644 Q_Q(const QQmlEngine);
645 if (!networkAccessManager)
646 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
647 return networkAccessManager;
651 Returns a common QNetworkAccessManager which can be used by any QML
652 element instantiated by this engine.
654 If a QQmlNetworkAccessManagerFactory has been set and a
655 QNetworkAccessManager has not yet been created, the
656 QQmlNetworkAccessManagerFactory will be used to create the
657 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
658 will have no proxy or cache set.
660 \sa setNetworkAccessManagerFactory()
662 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
664 Q_D(const QQmlEngine);
665 return d->getNetworkAccessManager();
670 Sets the \a provider to use for images requested via the \e
671 image: url scheme, with host \a providerId. The QQmlEngine
672 takes ownership of \a provider.
674 Image providers enable support for pixmap and threaded image
675 requests. See the QQmlImageProvider documentation for details on
676 implementing and using image providers.
678 All required image providers should be added to the engine before any
679 QML sources files are loaded.
681 \sa removeImageProvider()
683 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProvider *provider)
686 QMutexLocker locker(&d->mutex);
687 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProvider>(provider));
691 Returns the QQmlImageProvider set for \a providerId.
693 Returns the provider if it was found; otherwise returns 0.
695 QQmlImageProvider *QQmlEngine::imageProvider(const QString &providerId) const
697 Q_D(const QQmlEngine);
698 QMutexLocker locker(&d->mutex);
699 return d->imageProviders.value(providerId).data();
703 Removes the QQmlImageProvider for \a providerId.
705 \sa addImageProvider()
707 void QQmlEngine::removeImageProvider(const QString &providerId)
710 QMutexLocker locker(&d->mutex);
711 d->imageProviders.take(providerId);
714 QQmlImageProvider::ImageType QQmlEnginePrivate::getImageProviderType(const QUrl &url)
716 QMutexLocker locker(&mutex);
717 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
720 return provider->imageType();
721 return QQmlImageProvider::Invalid;
724 QQuickTextureFactory *QQmlEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
726 QMutexLocker locker(&mutex);
727 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
730 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
731 return provider->requestTexture(imageId, size, req_size);
736 QImage QQmlEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
738 QMutexLocker locker(&mutex);
740 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
743 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
744 image = provider->requestImage(imageId, size, req_size);
749 QPixmap QQmlEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
751 QMutexLocker locker(&mutex);
753 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
756 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
757 pixmap = provider->requestPixmap(imageId, size, req_size);
763 Return the base URL for this engine. The base URL is only used to
764 resolve components when a relative URL is passed to the
765 QQmlComponent constructor.
767 If a base URL has not been explicitly set, this method returns the
768 application's current working directory.
772 QUrl QQmlEngine::baseUrl() const
774 Q_D(const QQmlEngine);
775 if (d->baseUrl.isEmpty()) {
776 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
783 Set the base URL for this engine to \a url.
787 void QQmlEngine::setBaseUrl(const QUrl &url)
794 Returns true if warning messages will be output to stderr in addition
795 to being emitted by the warnings() signal, otherwise false.
797 The default value is true.
799 bool QQmlEngine::outputWarningsToStandardError() const
801 Q_D(const QQmlEngine);
802 return d->outputWarningsToStdErr;
806 Set whether warning messages will be output to stderr to \a enabled.
808 If \a enabled is true, any warning messages generated by QML will be
809 output to stderr and emitted by the warnings() signal. If \a enabled
810 is false, on the warnings() signal will be emitted. This allows
811 applications to handle warning output themselves.
813 The default value is true.
815 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
818 d->outputWarningsToStdErr = enabled;
822 Attempt to free unused memory.
824 void QQmlEngine::collectGarbage()
830 Returns the QQmlContext for the \a object, or 0 if no
831 context has been set.
833 When the QQmlEngine instantiates a QObject, the context is
836 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
841 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
844 static_cast<QQmlData *>(priv->declarativeData);
848 else if (data->outerContext)
849 return data->outerContext->asQQmlContext();
855 Sets the QQmlContext for the \a object to \a context.
856 If the \a object already has a context, a warning is
857 output, but the context is not changed.
859 When the QQmlEngine instantiates a QObject, the context is
862 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
864 if (!object || !context)
867 QQmlData *data = QQmlData::get(object, true);
869 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
873 QQmlContextData *contextData = QQmlContextData::get(context);
874 contextData->addObject(object);
878 \enum QQmlEngine::ObjectOwnership
880 Ownership controls whether or not QML automatically destroys the
881 QObject when the object is garbage collected by the JavaScript
882 engine. The two ownership options are:
884 \value CppOwnership The object is owned by C++ code, and will
885 never be deleted by QML. The JavaScript destroy() method cannot be
886 used on objects with CppOwnership. This option is similar to
887 QScriptEngine::QtOwnership.
889 \value JavaScriptOwnership The object is owned by JavaScript.
890 When the object is returned to QML as the return value of a method
891 call or property access, QML will delete the object if there are no
892 remaining JavaScript references to it and it has no
893 QObject::parent(). This option is similar to
894 QScriptEngine::ScriptOwnership.
896 Generally an application doesn't need to set an object's ownership
897 explicitly. QML uses a heuristic to set the default object
898 ownership. By default, an object that is created by QML has
899 JavaScriptOwnership. The exception to this are the root objects
900 created by calling QQmlComponent::create() or
901 QQmlComponent::beginCreate() which have CppOwnership by
902 default. The ownership of these root-level objects is considered to
903 have been transferred to the C++ caller.
905 Objects not-created by QML have CppOwnership by default. The
906 exception to this is objects returned from a C++ method call. The
907 ownership of these objects is passed to JavaScript.
909 Calling setObjectOwnership() overrides the default ownership
910 heuristic used by QML.
914 Sets the \a ownership of \a object.
916 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
921 QQmlData *ddata = QQmlData::get(object, true);
925 ddata->indestructible = (ownership == CppOwnership)?true:false;
926 ddata->explicitIndestructibleSet = true;
930 Returns the ownership of \a object.
932 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
937 QQmlData *ddata = QQmlData::get(object, false);
941 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
944 bool QQmlEngine::event(QEvent *e)
947 if (e->type() == QEvent::User)
948 d->doDeleteInEngineThread();
950 return QJSEngine::event(e);
953 void QQmlEnginePrivate::doDeleteInEngineThread()
955 QFieldList<Deletable, &Deletable::next> list;
957 list.copyAndClear(toDeleteInEngineThread);
960 while (Deletable *d = list.takeFirst())
964 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
966 QQmlData *data = QQmlData::get(object);
968 if (data && data->deferredComponent) {
969 QQmlObjectCreatingProfiler prof;
971 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
972 prof.setTypeName(type ? type->qmlTypeName()
973 : QString::fromUtf8(object->metaObject()->className()));
974 if (data->outerContext)
975 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
977 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
979 QQmlComponentPrivate::ConstructionState state;
980 QQmlComponentPrivate::beginDeferred(ep, object, &state);
982 data->deferredComponent->release();
983 data->deferredComponent = 0;
985 QQmlComponentPrivate::complete(ep, &state);
989 QQmlContext *qmlContext(const QObject *obj)
991 return QQmlEngine::contextForObject(obj);
994 QQmlEngine *qmlEngine(const QObject *obj)
996 QQmlData *data = QQmlData::get(obj, false);
997 if (!data || !data->context)
999 return data->context->engine;
1002 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1004 QQmlData *data = QQmlData::get(object);
1006 return 0; // Attached properties are only on objects created by QML
1008 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1012 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1016 rv = pf(const_cast<QObject *>(object));
1019 data->attachedProperties()->insert(id, rv);
1024 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1025 const QMetaObject *attachedMetaObject, bool create)
1028 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1030 if (*idCache == -1 || !object)
1033 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1036 QQmlDebuggingEnabler::QQmlDebuggingEnabler()
1038 #ifndef QQML_NO_DEBUG_PROTOCOL
1039 if (!QQmlEnginePrivate::qml_debugging_enabled) {
1040 qWarning("QML debugging is enabled. Only use this in a safe environment.");
1042 QQmlEnginePrivate::qml_debugging_enabled = true;
1047 class QQmlDataExtended {
1050 ~QQmlDataExtended();
1052 QHash<int, QObject *> attachedProperties;
1053 QQmlNotifier objectNameNotifier;
1056 QQmlDataExtended::QQmlDataExtended()
1060 QQmlDataExtended::~QQmlDataExtended()
1064 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1067 layout(endpoint->next);
1069 int index = endpoint->sourceSignal;
1070 index = qMin(index, 0xFFFF - 1);
1072 endpoint->next = notifies[index];
1073 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1074 endpoint->prev = ¬ifies[index];
1075 notifies[index] = endpoint;
1078 void QQmlData::NotifyList::layout()
1080 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1083 QQmlNotifierEndpoint **old = notifies;
1084 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1085 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1086 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1087 sizeof(QQmlNotifierEndpoint*);
1088 memset(notifies + notifiesSize, 0, memsetSize);
1090 if (notifies != old) {
1091 for (int ii = 0; ii < notifiesSize; ++ii)
1093 notifies[ii]->prev = ¬ifies[ii];
1096 notifiesSize = maximumTodoIndex + 1;
1101 maximumTodoIndex = 0;
1105 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1108 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1109 notifyList->connectionMask = 0;
1110 notifyList->maximumTodoIndex = 0;
1111 notifyList->notifiesSize = 0;
1112 notifyList->todo = 0;
1113 notifyList->notifies = 0;
1116 Q_ASSERT(!endpoint->isConnected());
1118 index = qMin(index, 0xFFFF - 1);
1119 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1121 if (index < notifyList->notifiesSize) {
1123 endpoint->next = notifyList->notifies[index];
1124 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1125 endpoint->prev = ¬ifyList->notifies[index];
1126 notifyList->notifies[index] = endpoint;
1129 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1131 endpoint->next = notifyList->todo;
1132 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1133 endpoint->prev = ¬ifyList->todo;
1134 notifyList->todo = endpoint;
1138 QQmlNotifier *QQmlData::objectNameNotifier() const
1140 if (!extendedData) extendedData = new QQmlDataExtended;
1141 return &extendedData->objectNameNotifier;
1144 QHash<int, QObject *> *QQmlData::attachedProperties() const
1146 if (!extendedData) extendedData = new QQmlDataExtended;
1147 return &extendedData->attachedProperties;
1150 void QQmlData::destroyed(QObject *object)
1152 if (deferredComponent)
1153 deferredComponent->release();
1155 if (nextContextObject)
1156 nextContextObject->prevContextObject = prevContextObject;
1157 if (prevContextObject)
1158 *prevContextObject = nextContextObject;
1160 QQmlAbstractBinding *binding = bindings;
1162 QQmlAbstractBinding *next = binding->m_nextBinding;
1163 binding->m_prevBinding = 0;
1164 binding->m_nextBinding = 0;
1173 propertyCache->release();
1175 if (ownContext && context)
1179 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1180 *guard = (QObject *)0;
1181 guard->objectDestroyed(object);
1185 while (notifyList->todo)
1186 notifyList->todo->disconnect();
1187 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1188 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1191 free(notifyList->notifies);
1196 delete extendedData;
1198 v8object.Clear(); // The WeakReference handler will clean the actual handle
1204 void QQmlData::parentChanged(QObject *object, QObject *parent)
1210 void QQmlData::objectNameChanged(QObject *)
1212 if (extendedData) objectNameNotifier()->notify();
1215 bool QQmlData::hasBindingBit(int bit) const
1217 if (bindingBitsSize > bit)
1218 return bindingBits[bit / 32] & (1 << (bit % 32));
1223 void QQmlData::clearBindingBit(int bit)
1225 if (bindingBitsSize > bit)
1226 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1229 void QQmlData::setBindingBit(QObject *obj, int bit)
1231 if (bindingBitsSize <= bit) {
1232 int props = obj->metaObject()->propertyCount();
1233 Q_ASSERT(bit < props);
1235 int arraySize = (props + 31) / 32;
1236 int oldArraySize = bindingBitsSize / 32;
1238 bindingBits = (quint32 *)realloc(bindingBits,
1239 arraySize * sizeof(quint32));
1241 memset(bindingBits + oldArraySize,
1243 sizeof(quint32) * (arraySize - oldArraySize));
1245 bindingBitsSize = arraySize * 32;
1248 bindingBits[bit / 32] |= (1 << (bit % 32));
1251 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1253 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1254 if (url.authority().isEmpty())
1255 return QLatin1Char(':') + url.path();
1258 return url.toLocalFile();
1262 static QString toLocalFile(const QString &url)
1264 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1267 QString file = url.mid(7);
1269 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1271 // magic for drives on windows
1272 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1278 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1280 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1281 if (url.length() > 4)
1282 return QLatin1Char(':') + url.mid(4);
1286 return toLocalFile(url);
1289 void QQmlEnginePrivate::sendQuit()
1293 if (q->receivers(SIGNAL(quit())) == 0) {
1294 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1298 static void dumpwarning(const QQmlError &error)
1300 qWarning().nospace() << qPrintable(error.toString());
1303 static void dumpwarning(const QList<QQmlError> &errors)
1305 for (int ii = 0; ii < errors.count(); ++ii)
1306 dumpwarning(errors.at(ii));
1309 void QQmlEnginePrivate::warning(const QQmlError &error)
1312 q->warnings(QList<QQmlError>() << error);
1313 if (outputWarningsToStdErr)
1317 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1320 q->warnings(errors);
1321 if (outputWarningsToStdErr)
1322 dumpwarning(errors);
1325 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1328 QQmlEnginePrivate::get(engine)->warning(error);
1333 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1336 QQmlEnginePrivate::get(engine)->warning(error);
1341 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1344 engine->warning(error);
1349 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1352 engine->warning(error);
1358 This function should be called prior to evaluation of any js expression,
1359 so that scarce resources are not freed prematurely (eg, if there is a
1360 nested javascript expression).
1362 void QQmlEnginePrivate::referenceScarceResources()
1364 scarceResourcesRefCount += 1;
1368 This function should be called after evaluation of the js expression is
1369 complete, and so the scarce resources may be freed safely.
1371 void QQmlEnginePrivate::dereferenceScarceResources()
1373 Q_ASSERT(scarceResourcesRefCount > 0);
1374 scarceResourcesRefCount -= 1;
1376 // if the refcount is zero, then evaluation of the "top level"
1377 // expression must have completed. We can safely release the
1378 // scarce resources.
1379 if (scarceResourcesRefCount == 0) {
1380 // iterate through the list and release them all.
1381 // note that the actual SRD is owned by the JS engine,
1382 // so we cannot delete the SRD; but we can free the
1383 // memory used by the variant in the SRD.
1384 while (ScarceResourceData *sr = scarceResources.first()) {
1385 sr->data = QVariant();
1386 scarceResources.remove(sr);
1392 Adds \a path as a directory where the engine searches for
1393 installed modules in a URL-based directory structure.
1394 The \a path may be a local filesystem directory or a URL.
1396 The newly added \a path will be first in the importPathList().
1398 \sa setImportPathList(), {QML Modules}
1400 void QQmlEngine::addImportPath(const QString& path)
1403 d->importDatabase.addImportPath(path);
1407 Returns the list of directories where the engine searches for
1408 installed modules in a URL-based directory structure.
1410 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1411 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1412 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1413 provided by that module. A \c qmldir file is required for defining the
1414 type version mapping and possibly QML extensions plugins.
1416 By default, the list contains the directory of the application executable,
1417 paths specified in the \c QML_IMPORT_PATH environment variable,
1418 and the builtin \c ImportsPath from QLibraryInfo.
1420 \sa addImportPath() setImportPathList()
1422 QStringList QQmlEngine::importPathList() const
1424 Q_D(const QQmlEngine);
1425 return d->importDatabase.importPathList();
1429 Sets \a paths as the list of directories where the engine searches for
1430 installed modules in a URL-based directory structure.
1432 By default, the list contains the directory of the application executable,
1433 paths specified in the \c QML_IMPORT_PATH environment variable,
1434 and the builtin \c ImportsPath from QLibraryInfo.
1436 \sa importPathList() addImportPath()
1438 void QQmlEngine::setImportPathList(const QStringList &paths)
1441 d->importDatabase.setImportPathList(paths);
1446 Adds \a path as a directory where the engine searches for
1447 native plugins for imported modules (referenced in the \c qmldir file).
1449 By default, the list contains only \c ., i.e. the engine searches
1450 in the directory of the \c qmldir file itself.
1452 The newly added \a path will be first in the pluginPathList().
1454 \sa setPluginPathList()
1456 void QQmlEngine::addPluginPath(const QString& path)
1459 d->importDatabase.addPluginPath(path);
1464 Returns the list of directories where the engine searches for
1465 native plugins for imported modules (referenced in the \c qmldir file).
1467 By default, the list contains only \c ., i.e. the engine searches
1468 in the directory of the \c qmldir file itself.
1470 \sa addPluginPath() setPluginPathList()
1472 QStringList QQmlEngine::pluginPathList() const
1474 Q_D(const QQmlEngine);
1475 return d->importDatabase.pluginPathList();
1479 Sets the list of directories where the engine searches for
1480 native plugins for imported modules (referenced in the \c qmldir file)
1483 By default, the list contains only \c ., i.e. the engine searches
1484 in the directory of the \c qmldir file itself.
1486 \sa pluginPathList() addPluginPath()
1488 void QQmlEngine::setPluginPathList(const QStringList &paths)
1491 d->importDatabase.setPluginPathList(paths);
1495 Imports the plugin named \a filePath with the \a uri provided.
1496 Returns true if the plugin was successfully imported; otherwise returns false.
1498 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1500 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1502 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1505 return d->importDatabase.importPlugin(filePath, uri, errors);
1509 Imports the plugin named \a filePath with the \a uri provided.
1510 Returns true if the plugin was successfully imported; otherwise returns false.
1512 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1514 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1516 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1519 QList<QQmlError> errors;
1520 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1521 if (!errors.isEmpty()) {
1523 for (int i = 0; i < errors.size(); ++i) {
1524 builtError = QString(QLatin1String("%1\n %2"))
1526 .arg(errors.at(i).toString());
1528 *errorString = builtError;
1534 \property QQmlEngine::offlineStoragePath
1535 \brief the directory for storing offline user data
1537 Returns the directory where SQL and other offline
1540 QQuickWebView and the SQL databases created with openDatabase()
1543 The default is QML/OfflineStorage in the platform-standard
1544 user application data directory.
1546 Note that the path may not currently exist on the filesystem, so
1547 callers wanting to \e create new files at this location should create
1548 it first - see QDir::mkpath().
1550 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1553 d->offlineStoragePath = dir;
1556 QString QQmlEngine::offlineStoragePath() const
1558 Q_D(const QQmlEngine);
1559 return d->offlineStoragePath;
1562 static void voidptr_destructor(void *v)
1564 void **ptr = (void **)v;
1568 static void *voidptr_constructor(const void *v)
1573 return new void*(*(void **)v);
1577 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1581 if (!mo->superClass()) {
1582 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1583 propertyCache.insert(mo, rv);
1586 QQmlPropertyCache *super = cache(mo->superClass());
1587 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1588 propertyCache.insert(mo, rv);
1593 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1596 QList<QQmlType *> types;
1598 int maxMinorVersion = 0;
1600 const QMetaObject *metaObject = type->metaObject();
1602 while (metaObject) {
1603 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1604 type->majorVersion(), minorVersion);
1606 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1612 metaObject = metaObject->superClass();
1615 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1617 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1621 QQmlPropertyCache *raw = cache(type->metaObject());
1623 bool hasCopied = false;
1625 for (int ii = 0; ii < types.count(); ++ii) {
1626 QQmlType *currentType = types.at(ii);
1630 int rev = currentType->metaObjectRevision();
1631 int moIndex = types.count() - 1 - ii;
1633 if (raw->allowedRevisionCache[moIndex] != rev) {
1638 raw->allowedRevisionCache[moIndex] = rev;
1642 // Test revision compatibility - the basic rule is:
1643 // * Anything that is excluded, cannot overload something that is not excluded *
1645 // Signals override:
1646 // * other signals and methods of the same name.
1647 // * properties named on<Signal Name>
1648 // * automatic <property name>Changed notify signals
1650 // Methods override:
1651 // * other methods of the same name
1653 // Properties override:
1654 // * other elements of the same name
1656 bool overloadError = false;
1657 QString overloadName;
1660 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1661 !overloadError && iter != raw->stringCache.end();
1664 QQmlPropertyData *d = *iter;
1665 if (raw->isAllowedInRevision(d))
1666 continue; // Not excluded - no problems
1668 // check that a regular "name" overload isn't happening
1669 QQmlPropertyData *current = d;
1670 while (!overloadError && current) {
1671 current = d->overrideData(current);
1672 if (current && raw->isAllowedInRevision(current))
1673 overloadError = true;
1678 if (overloadError) {
1679 if (hasCopied) raw->release();
1681 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."));
1685 if (!hasCopied) raw->addref();
1686 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1688 if (minorVersion != maxMinorVersion) {
1690 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1696 QQmlMetaType::ModuleApiInstance *
1697 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1699 Locker locker(this);
1701 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1703 a = new QQmlMetaType::ModuleApiInstance;
1704 a->scriptCallback = module.script;
1705 a->qobjectCallback = module.qobject;
1706 moduleApiInstances.insert(module, a);
1712 bool QQmlEnginePrivate::isQObject(int t)
1714 Locker locker(this);
1715 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1718 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1720 Locker locker(this);
1721 int t = v.userType();
1722 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1724 return *(QObject **)(v.constData());
1726 return QQmlMetaType::toQObject(v, ok);
1730 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1732 Locker locker(this);
1733 if (m_compositeTypes.contains(t))
1734 return QQmlMetaType::Object;
1735 else if (m_qmlLists.contains(t))
1736 return QQmlMetaType::List;
1738 return QQmlMetaType::typeCategory(t);
1741 bool QQmlEnginePrivate::isList(int t) const
1743 Locker locker(this);
1744 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1747 int QQmlEnginePrivate::listType(int t) const
1749 Locker locker(this);
1750 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1751 if (iter != m_qmlLists.end())
1754 return QQmlMetaType::listType(t);
1757 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1759 Locker locker(this);
1760 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1761 if (iter != m_compositeTypes.end()) {
1762 return (*iter)->root;
1764 QQmlType *type = QQmlMetaType::qmlType(t);
1765 return type?type->baseMetaObject():0;
1769 const QMetaObject *QQmlEnginePrivate::metaObjectForType(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->metaObject():0;
1781 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1783 QByteArray name = data->root->className();
1785 QByteArray ptr = name + '*';
1786 QByteArray lst = "QQmlListProperty<" + name + '>';
1788 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1789 voidptr_constructor);
1790 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1791 voidptr_constructor);
1795 Locker locker(this);
1796 m_qmlLists.insert(lst_type, ptr_type);
1797 m_compositeTypes.insert(ptr_type, data);
1800 bool QQml_isFileCaseCorrect(const QString &fileName)
1802 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1803 QFileInfo info(fileName);
1804 const QString absolute = info.absoluteFilePath();
1806 #if defined(Q_OS_MAC)
1807 const QString canonical = info.canonicalFilePath();
1808 #elif defined(Q_OS_WIN)
1809 wchar_t buffer[1024];
1811 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1812 if (rv == 0 || rv >= 1024) return true;
1813 rv = ::GetLongPathName(buffer, buffer, 1024);
1814 if (rv == 0 || rv >= 1024) return true;
1816 const QString canonical = QString::fromWCharArray(buffer);
1819 const int absoluteLength = absolute.length();
1820 const int canonicalLength = canonical.length();
1822 const int length = qMin(absoluteLength, canonicalLength);
1823 for (int ii = 0; ii < length; ++ii) {
1824 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1825 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1827 if (a.toLower() != c.toLower())
1839 \fn QQmlEngine *qmlEngine(const QObject *object)
1842 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1843 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1847 \fn QQmlContext *qmlContext(const QObject *object)
1850 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1851 QQmlEngine::contextForObject(object).