1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
72 #include <private/qqmlboundsignal_p.h>
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtNetwork/qnetworkconfigmanager.h>
85 #include <private/qobject_p.h>
86 #include <private/qmetaobject_p.h>
88 #include <private/qqmllocale_p.h>
90 #ifdef Q_OS_WIN // for %APPDATA%
91 #include <qt_windows.h>
95 #define CSIDL_APPDATA 0x001a // <username>\Application Data
98 Q_DECLARE_METATYPE(QQmlProperty)
102 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
104 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
105 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
109 \qmlclass QtObject QObject
110 \ingroup qml-utility-elements
112 \brief The QtObject element is the most basic element in QML.
114 The QtObject element is a non-visual element which contains only the
117 It can be useful to create a QtObject if you need an extremely
118 lightweight element to enclose a set of custom properties:
120 \snippet doc/src/snippets/qml/qtobject.qml 0
122 It can also be useful for C++ integration, as it is just a plain
123 QObject. See the QObject documentation for further details.
126 \qmlproperty string QtObject::objectName
127 This property holds the QObject::objectName for this specific object instance.
129 This allows a C++ application to locate an item within a QML component
130 using the QObject::findChild() method. For example, the following C++
131 application locates the child \l Rectangle item and dynamically changes its
140 width: 200; height: 200
154 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
157 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
159 item->setProperty("color", QColor(Qt::yellow));
163 bool QQmlEnginePrivate::qml_debugging_enabled = false;
165 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
167 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
168 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
169 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
170 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
171 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
174 void QQmlEnginePrivate::defineModule()
176 registerBaseTypes("QtQuick", 2, 0);
177 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
182 \class QQmlImageProviderBase
183 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
186 Image providers must be registered with the QML engine. The only information the QML
187 engine knows about image providers is the type of image data they provide. To use an
188 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
189 to a QQuickImageProvider pointer.
191 \sa QQuickImageProvider, QQuickTextureFactory
195 \enum QQmlImageProviderBase::ImageType
197 Defines the type of image supported by this image provider.
199 \value Image The Image Provider provides QImage images.
200 The QQuickImageProvider::requestImage() method will be called for all image requests.
201 \value Pixmap The Image Provider provides QPixmap images.
202 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
203 \value Texture The Image Provider provides QSGTextureProvider based images.
204 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
208 QQmlImageProviderBase::QQmlImageProviderBase()
213 QQmlImageProviderBase::~QQmlImageProviderBase()
219 \qmlclass Qt QQmlEnginePrivate
220 \ingroup qml-utility-elements
221 \brief The QML global Qt object provides useful enums and functions from Qt.
223 \keyword QmlGlobalQtObject
225 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
227 The \c Qt object is a global object with utility functions, properties and enums.
229 It is not instantiable; to use it, call the members of the global \c Qt object directly.
236 color: Qt.rgba(1, 0, 0, 1)
237 text: Qt.md5("hello, world")
244 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
245 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
249 The Qt object also contains helper functions for creating objects of specific
250 data types. This is primarily useful when setting the properties of an item
251 when the property has one of the following types:
254 \li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
255 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
256 \li \c point - use \l{Qt::point()}{Qt.point()}
257 \li \c size - use \l{Qt::size()}{Qt.size()}
258 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
261 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
263 \section1 Date/Time Formatters
265 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
268 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
269 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
270 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
273 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
276 \section1 Dynamic Object Creation
277 The following functions on the global object allow you to dynamically create QML
278 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
282 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
283 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
289 \qmlproperty object Qt::application
292 The \c application object provides access to global application state
293 properties shared by many QML components.
299 \li \c application.active
301 This read-only property indicates whether the application is the top-most and focused
302 application, and the user is able to interact with the application. The property
303 is false when the application is in the background, the device keylock or screen
304 saver is active, the screen backlight is turned off, or the global system dialog
305 is being displayed on top of the application. It can be used for stopping and
306 pausing animations, timers and active processing of data in order to save device
307 battery power and free device memory and processor load when the application is not
311 \li \c application.layoutDirection
313 This read-only property can be used to query the default layout direction of the
314 application. On system start-up, the default layout direction depends on the
315 application's language. The property has a value of \c Qt.RightToLeft in locales
316 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
317 where the reading direction flows from left to right. You can bind to this
318 property to customize your application layouts to support both layout directions.
323 \li Qt.LeftToRight - Text and graphics elements should be positioned
325 \li Qt.RightToLeft - Text and graphics elements should be positioned
329 The following example uses the \c application object to indicate
330 whether the application is currently active:
332 \snippet doc/src/snippets/qml/application.qml document
334 \qmlproperty object Qt::inputMethod
337 The \c inputMethod object allows access to application's QInputMethod object
338 and all its properties and slots. See the QInputMethod documentation for
344 \qmlmethod object Qt::include(string url, jsobject callback)
346 Includes another JavaScript file. This method can only be used from within JavaScript files,
347 and not regular QML files.
349 This imports all functions from \a url into the current script's namespace.
351 Qt.include() returns an object that describes the status of the operation. The object has
352 a single property, \c {status}, that is set to one of the following values:
355 \header \li Symbol \li Value \li Description
356 \row \li result.OK \li 0 \li The include completed successfully.
357 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
358 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
359 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
360 An additional \c exception property will be set in this case.
363 The \c status property will be updated as the operation progresses.
365 If provided, \a callback is invoked when the operation completes. The callback is passed
366 the same object as is returned from the Qt.include() call.
368 // Qt.include() is implemented in qv8include.cpp
371 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
372 : propertyCapture(0), rootContext(0), isDebugging(false),
373 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
374 cleanup(0), erroredBindings(0), inProgressCreations(0),
375 workerScriptEngine(0), activeVME(0),
376 networkAccessManager(0), networkAccessManagerFactory(0),
377 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
378 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
382 QQmlEnginePrivate::~QQmlEnginePrivate()
384 if (inProgressCreations)
385 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
388 QQmlCleanup *c = cleanup;
390 if (cleanup) cleanup->prev = &cleanup;
396 doDeleteInEngineThread();
398 if (incubationController) incubationController->d = 0;
399 incubationController = 0;
404 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
406 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
408 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
410 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
411 delete (*iter)->qobjectApi;
416 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
418 QObjectPrivate *p = QObjectPrivate::get(o);
419 if (p->declarativeData) {
420 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
421 if (d->ownContext && d->context) {
422 d->context->destroy();
426 // Mark this object as in the process of deletion to
427 // prevent it resolving in bindings
428 QQmlData::markAsDeleted(o);
432 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
434 static_cast<QQmlData *>(d)->destroyed(o);
437 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
439 static_cast<QQmlData *>(d)->parentChanged(o, p);
442 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
444 QQmlData *ddata = QQmlData::get(object, false);
445 if (!ddata) return; // Probably being deleted
447 QQmlNotifierEndpoint *ep = ddata->notify(index);
448 if (ep) QQmlNotifier::emitNotify(ep, a);
451 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
453 return static_cast<QQmlData *>(d)->endpointCount(index);
456 int QQmlData::endpointCount(int index)
459 QQmlNotifierEndpoint *ep = notify(index);
470 void QQmlData::markAsDeleted(QObject *o)
472 QQmlData::setQueuedForDeletion(o);
474 QObjectPrivate *p = QObjectPrivate::get(o);
475 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
476 QQmlData::markAsDeleted(*it);
480 void QQmlEnginePrivate::init()
484 static bool firstTime = true;
486 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
492 qRegisterMetaType<QVariant>("QVariant");
493 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
494 qRegisterMetaType<QJSValue>("QJSValue");
495 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
496 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
497 qRegisterMetaType<QList<int> >("QList<int>");
498 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
500 v8engine()->setEngine(q);
502 rootContext = new QQmlContext(q,true);
504 if (QCoreApplication::instance()->thread() == q->thread() &&
505 QQmlEngineDebugService::isDebuggingEnabled()) {
507 QQmlEngineDebugService::instance()->addEngine(q);
508 QV8DebugService::initialize(v8engine());
509 QV8ProfilerService::initialize();
510 QQmlProfilerService::initialize();
511 QDebugMessageService::instance();
514 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
515 if (!dataLocation.isEmpty())
516 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
517 + QDir::separator() + QLatin1String("QML")
518 + QDir::separator() + QLatin1String("OfflineStorage");
521 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
524 if (!workerScriptEngine)
525 workerScriptEngine = new QQuickWorkerScriptEngine(q);
526 return workerScriptEngine;
533 \brief The QQmlEngine class provides an environment for instantiating QML components.
536 Each QML component is instantiated in a QQmlContext.
537 QQmlContext's are essential for passing data to QML
538 components. In QML, contexts are arranged hierarchically and this
539 hierarchy is managed by the QQmlEngine.
541 Prior to creating any QML components, an application must have
542 created a QQmlEngine to gain access to a QML context. The
543 following example shows how to create a simple Text item.
547 QQmlComponent component(&engine);
548 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
549 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
551 //add item to view, etc
555 In this case, the Text item will be created in the engine's
556 \l {QQmlEngine::rootContext()}{root context}.
558 Note that the QtQuick 1 version is called QDeclarativeEngine.
560 \sa QQmlComponent, QQmlContext
564 Create a new QQmlEngine with the given \a parent.
566 QQmlEngine::QQmlEngine(QObject *parent)
567 : QJSEngine(*new QQmlEnginePrivate(this), parent)
574 Destroys the QQmlEngine.
576 Any QQmlContext's created on this engine will be
577 invalidated, but not destroyed (unless they are parented to the
580 QQmlEngine::~QQmlEngine()
583 if (d->isDebugging) {
584 QQmlEngineDebugService::instance()->remEngine(this);
587 // Emit onDestruction signals for the root context before
588 // we destroy the contexts, engine, Module APIs etc. that
589 // may be required to handle the destruction signal.
590 QQmlContextData::get(rootContext())->emitDestruction();
592 // if we are the parent of any of the qobject module api instances,
593 // we need to remove them from our internal list, in order to prevent
594 // a segfault in engine private dtor.
595 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
596 QObject *currQObjectApi = 0;
597 QQmlMetaType::ModuleApiInstance *currInstance = 0;
598 foreach (const QQmlMetaType::ModuleApi &key, keys) {
599 currInstance = d->moduleApiInstances.value(key);
600 currQObjectApi = currInstance->qobjectApi;
601 if (this->children().contains(currQObjectApi)) {
602 delete currQObjectApi;
604 d->moduleApiInstances.remove(key);
608 if (d->incubationController)
609 d->incubationController->d = 0;
612 /*! \fn void QQmlEngine::quit()
613 This signal is emitted when the QML loaded by the engine would like to quit.
616 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
617 This signal is emitted when \a warnings messages are generated by QML.
621 Clears the engine's internal component cache.
623 This function causes the property metadata of all components previously
624 loaded by the engine to be destroyed. All previously loaded components and
625 the property bindings for all extant objects created from those components will
628 This function returns the engine to a state where it does not contain any loaded
629 component data. This may be useful in order to reload a smaller subset of the
630 previous component set, or to load a new version of a previously loaded component.
632 Once the component cache has been cleared, components must be loaded before
633 any new objects can be created.
635 void QQmlEngine::clearComponentCache()
638 d->typeLoader.clearCache();
642 Returns the engine's root context.
644 The root context is automatically created by the QQmlEngine.
645 Data that should be available to all QML component instances
646 instantiated by the engine should be put in the root context.
648 Additional data that should only be available to a subset of
649 component instances should be added to sub-contexts parented to the
652 QQmlContext *QQmlEngine::rootContext() const
654 Q_D(const QQmlEngine);
655 return d->rootContext;
659 Sets the \a factory to use for creating QNetworkAccessManager(s).
661 QNetworkAccessManager is used for all network access by QML. By
662 implementing a factory it is possible to create custom
663 QNetworkAccessManager with specialized caching, proxy and cookie
666 The factory must be set before executing the engine.
668 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
671 QMutexLocker locker(&d->mutex);
672 d->networkAccessManagerFactory = factory;
676 Returns the current QQmlNetworkAccessManagerFactory.
678 \sa setNetworkAccessManagerFactory()
680 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
682 Q_D(const QQmlEngine);
683 return d->networkAccessManagerFactory;
686 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
689 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
691 void *args[] = { 0 };
692 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
696 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
698 QMutexLocker locker(&mutex);
699 QNetworkAccessManager *nam;
700 if (networkAccessManagerFactory) {
701 nam = networkAccessManagerFactory->create(parent);
703 nam = new QNetworkAccessManager(parent);
709 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
711 Q_Q(const QQmlEngine);
712 if (!networkAccessManager)
713 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
714 return networkAccessManager;
718 Returns a common QNetworkAccessManager which can be used by any QML
719 element instantiated by this engine.
721 If a QQmlNetworkAccessManagerFactory has been set and a
722 QNetworkAccessManager has not yet been created, the
723 QQmlNetworkAccessManagerFactory will be used to create the
724 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
725 will have no proxy or cache set.
727 \sa setNetworkAccessManagerFactory()
729 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
731 Q_D(const QQmlEngine);
732 return d->getNetworkAccessManager();
737 Sets the \a provider to use for images requested via the \e
738 image: url scheme, with host \a providerId. The QQmlEngine
739 takes ownership of \a provider.
741 Image providers enable support for pixmap and threaded image
742 requests. See the QQuickImageProvider documentation for details on
743 implementing and using image providers.
745 All required image providers should be added to the engine before any
746 QML sources files are loaded.
748 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
750 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
753 QMutexLocker locker(&d->mutex);
754 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
758 Returns the image provider set for \a providerId.
760 Returns the provider if it was found; otherwise returns 0.
762 \sa QQuickImageProvider
764 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
766 Q_D(const QQmlEngine);
767 QMutexLocker locker(&d->mutex);
768 return d->imageProviders.value(providerId).data();
772 Removes the image provider for \a providerId.
774 \sa addImageProvider(), QQuickImageProvider
776 void QQmlEngine::removeImageProvider(const QString &providerId)
779 QMutexLocker locker(&d->mutex);
780 d->imageProviders.take(providerId);
784 Return the base URL for this engine. The base URL is only used to
785 resolve components when a relative URL is passed to the
786 QQmlComponent constructor.
788 If a base URL has not been explicitly set, this method returns the
789 application's current working directory.
793 QUrl QQmlEngine::baseUrl() const
795 Q_D(const QQmlEngine);
796 if (d->baseUrl.isEmpty()) {
797 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
804 Set the base URL for this engine to \a url.
808 void QQmlEngine::setBaseUrl(const QUrl &url)
815 Returns true if warning messages will be output to stderr in addition
816 to being emitted by the warnings() signal, otherwise false.
818 The default value is true.
820 bool QQmlEngine::outputWarningsToStandardError() const
822 Q_D(const QQmlEngine);
823 return d->outputWarningsToStdErr;
827 Set whether warning messages will be output to stderr to \a enabled.
829 If \a enabled is true, any warning messages generated by QML will be
830 output to stderr and emitted by the warnings() signal. If \a enabled
831 is false, on the warnings() signal will be emitted. This allows
832 applications to handle warning output themselves.
834 The default value is true.
836 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
839 d->outputWarningsToStdErr = enabled;
843 Attempt to free unused memory.
845 void QQmlEngine::collectGarbage()
851 Returns the QQmlContext for the \a object, or 0 if no
852 context has been set.
854 When the QQmlEngine instantiates a QObject, the context is
857 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
862 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
865 static_cast<QQmlData *>(priv->declarativeData);
869 else if (data->outerContext)
870 return data->outerContext->asQQmlContext();
876 Sets the QQmlContext for the \a object to \a context.
877 If the \a object already has a context, a warning is
878 output, but the context is not changed.
880 When the QQmlEngine instantiates a QObject, the context is
883 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
885 if (!object || !context)
888 QQmlData *data = QQmlData::get(object, true);
890 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
894 QQmlContextData *contextData = QQmlContextData::get(context);
895 contextData->addObject(object);
899 \enum QQmlEngine::ObjectOwnership
901 Ownership controls whether or not QML automatically destroys the
902 QObject when the object is garbage collected by the JavaScript
903 engine. The two ownership options are:
905 \value CppOwnership The object is owned by C++ code, and will
906 never be deleted by QML. The JavaScript destroy() method cannot be
907 used on objects with CppOwnership. This option is similar to
908 QScriptEngine::QtOwnership.
910 \value JavaScriptOwnership The object is owned by JavaScript.
911 When the object is returned to QML as the return value of a method
912 call or property access, QML will track it, and delete the object
913 if there are no remaining JavaScript references to it and it has no
914 QObject::parent(). An object tracked by one QQmlEngine
915 will be deleted during that QQmlEngine's destructor, and thus
916 JavaScript references between objects with JavaScriptOwnership from
917 two different engines will not be valid after the deletion of one of
918 those engines. This option is similar to QScriptEngine::ScriptOwnership.
920 Generally an application doesn't need to set an object's ownership
921 explicitly. QML uses a heuristic to set the default object
922 ownership. By default, an object that is created by QML has
923 JavaScriptOwnership. The exception to this are the root objects
924 created by calling QQmlComponent::create() or
925 QQmlComponent::beginCreate() which have CppOwnership by
926 default. The ownership of these root-level objects is considered to
927 have been transferred to the C++ caller.
929 Objects not-created by QML have CppOwnership by default. The
930 exception to this is objects returned from a C++ method call. The
931 ownership of these objects is passed to JavaScript.
933 Calling setObjectOwnership() overrides the default ownership
934 heuristic used by QML.
938 Sets the \a ownership of \a object.
940 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
945 QQmlData *ddata = QQmlData::get(object, true);
949 ddata->indestructible = (ownership == CppOwnership)?true:false;
950 ddata->explicitIndestructibleSet = true;
954 Returns the ownership of \a object.
956 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
961 QQmlData *ddata = QQmlData::get(object, false);
965 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
968 bool QQmlEngine::event(QEvent *e)
971 if (e->type() == QEvent::User)
972 d->doDeleteInEngineThread();
974 return QJSEngine::event(e);
977 void QQmlEnginePrivate::doDeleteInEngineThread()
979 QFieldList<Deletable, &Deletable::next> list;
981 list.copyAndClear(toDeleteInEngineThread);
984 while (Deletable *d = list.takeFirst())
988 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
990 QQmlData *data = QQmlData::get(object);
992 if (data && data->deferredComponent) {
993 QQmlObjectCreatingProfiler prof;
995 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
996 prof.setTypeName(type ? type->qmlTypeName()
997 : QString::fromUtf8(object->metaObject()->className()));
998 if (data->outerContext)
999 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1001 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1003 QQmlComponentPrivate::ConstructionState state;
1004 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1006 data->deferredComponent->release();
1007 data->deferredComponent = 0;
1009 QQmlComponentPrivate::complete(ep, &state);
1013 QQmlContext *qmlContext(const QObject *obj)
1015 return QQmlEngine::contextForObject(obj);
1018 QQmlEngine *qmlEngine(const QObject *obj)
1020 QQmlData *data = QQmlData::get(obj, false);
1021 if (!data || !data->context)
1023 return data->context->engine;
1026 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1028 QQmlData *data = QQmlData::get(object);
1030 return 0; // Attached properties are only on objects created by QML
1032 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1036 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1040 rv = pf(const_cast<QObject *>(object));
1043 data->attachedProperties()->insert(id, rv);
1048 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1049 const QMetaObject *attachedMetaObject, bool create)
1052 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1054 if (*idCache == -1 || !object)
1057 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1060 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1062 #ifndef QQML_NO_DEBUG_PROTOCOL
1063 if (!QQmlEnginePrivate::qml_debugging_enabled
1065 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1067 QQmlEnginePrivate::qml_debugging_enabled = true;
1072 class QQmlDataExtended {
1075 ~QQmlDataExtended();
1077 QHash<int, QObject *> attachedProperties;
1080 QQmlDataExtended::QQmlDataExtended()
1084 QQmlDataExtended::~QQmlDataExtended()
1088 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1091 layout(endpoint->next);
1093 int index = endpoint->sourceSignal;
1094 index = qMin(index, 0xFFFF - 1);
1096 endpoint->next = notifies[index];
1097 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1098 endpoint->prev = ¬ifies[index];
1099 notifies[index] = endpoint;
1102 void QQmlData::NotifyList::layout()
1104 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1107 QQmlNotifierEndpoint **old = notifies;
1108 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1109 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1110 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1111 sizeof(QQmlNotifierEndpoint*);
1112 memset(notifies + notifiesSize, 0, memsetSize);
1114 if (notifies != old) {
1115 for (int ii = 0; ii < notifiesSize; ++ii)
1117 notifies[ii]->prev = ¬ifies[ii];
1120 notifiesSize = maximumTodoIndex + 1;
1125 maximumTodoIndex = 0;
1129 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1132 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1133 notifyList->connectionMask = 0;
1134 notifyList->maximumTodoIndex = 0;
1135 notifyList->notifiesSize = 0;
1136 notifyList->todo = 0;
1137 notifyList->notifies = 0;
1140 Q_ASSERT(!endpoint->isConnected());
1142 index = qMin(index, 0xFFFF - 1);
1143 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1145 if (index < notifyList->notifiesSize) {
1147 endpoint->next = notifyList->notifies[index];
1148 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1149 endpoint->prev = ¬ifyList->notifies[index];
1150 notifyList->notifies[index] = endpoint;
1153 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1155 endpoint->next = notifyList->todo;
1156 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1157 endpoint->prev = ¬ifyList->todo;
1158 notifyList->todo = endpoint;
1162 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1164 QQmlData *data = QQmlData::get(obj);
1165 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1169 index MUST be the index returned by QMetaMethod::index()
1170 This is different than the index returned by QObjectPrivate::signalIndex()
1172 bool QQmlData::signalHasEndpoint(int index)
1174 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1177 QHash<int, QObject *> *QQmlData::attachedProperties() const
1179 if (!extendedData) extendedData = new QQmlDataExtended;
1180 return &extendedData->attachedProperties;
1183 void QQmlData::destroyed(QObject *object)
1185 if (deferredComponent)
1186 deferredComponent->release();
1188 if (nextContextObject)
1189 nextContextObject->prevContextObject = prevContextObject;
1190 if (prevContextObject)
1191 *prevContextObject = nextContextObject;
1193 QQmlAbstractBinding *binding = bindings;
1195 QQmlAbstractBinding *next = binding->m_nextBinding;
1196 binding->m_prevBinding = 0;
1197 binding->m_nextBinding = 0;
1202 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1203 while (signalHandler) {
1204 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1205 signalHandler->m_prevSignal = 0;
1206 signalHandler->m_nextSignal = 0;
1207 delete signalHandler;
1208 signalHandler = next;
1215 propertyCache->release();
1217 if (ownContext && context)
1221 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1222 *guard = (QObject *)0;
1223 guard->objectDestroyed(object);
1227 while (notifyList->todo)
1228 notifyList->todo->disconnect();
1229 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1230 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1233 free(notifyList->notifies);
1239 delete extendedData;
1241 v8object.Clear(); // The WeakReference handler will clean the actual handle
1247 void QQmlData::parentChanged(QObject *object, QObject *parent)
1253 bool QQmlData::hasBindingBit(int bit) const
1255 if (bindingBitsSize > bit)
1256 return bindingBits[bit / 32] & (1 << (bit % 32));
1261 void QQmlData::clearBindingBit(int bit)
1263 if (bindingBitsSize > bit)
1264 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1267 void QQmlData::setBindingBit(QObject *obj, int bit)
1269 if (bindingBitsSize <= bit) {
1270 int props = obj->metaObject()->propertyCount();
1271 Q_ASSERT(bit < props);
1273 int arraySize = (props + 31) / 32;
1274 int oldArraySize = bindingBitsSize / 32;
1276 bindingBits = (quint32 *)realloc(bindingBits,
1277 arraySize * sizeof(quint32));
1279 memset(bindingBits + oldArraySize,
1281 sizeof(quint32) * (arraySize - oldArraySize));
1283 bindingBitsSize = arraySize * 32;
1286 bindingBits[bit / 32] |= (1 << (bit % 32));
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 a->instanceMetaObject = module.instanceMetaObject;
1707 moduleApiInstances.insert(module, a);
1713 bool QQmlEnginePrivate::isQObject(int t)
1715 Locker locker(this);
1716 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1719 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1721 Locker locker(this);
1722 int t = v.userType();
1723 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1725 return *(QObject **)(v.constData());
1727 return QQmlMetaType::toQObject(v, ok);
1731 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1733 Locker locker(this);
1734 if (m_compositeTypes.contains(t))
1735 return QQmlMetaType::Object;
1736 else if (m_qmlLists.contains(t))
1737 return QQmlMetaType::List;
1739 return QQmlMetaType::typeCategory(t);
1742 bool QQmlEnginePrivate::isList(int t) const
1744 Locker locker(this);
1745 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1748 int QQmlEnginePrivate::listType(int t) const
1750 Locker locker(this);
1751 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1752 if (iter != m_qmlLists.end())
1755 return QQmlMetaType::listType(t);
1758 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1760 Locker locker(this);
1761 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1762 if (iter != m_compositeTypes.end()) {
1763 return (*iter)->root;
1765 QQmlType *type = QQmlMetaType::qmlType(t);
1766 return type?type->baseMetaObject():0;
1770 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1772 Locker locker(this);
1773 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1774 if (iter != m_compositeTypes.end()) {
1775 return (*iter)->root;
1777 QQmlType *type = QQmlMetaType::qmlType(t);
1778 return type?type->metaObject():0;
1782 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1784 QByteArray name = data->root->className();
1786 QByteArray ptr = name + '*';
1787 QByteArray lst = "QQmlListProperty<" + name + '>';
1789 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1790 voidptr_constructor);
1791 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1792 voidptr_constructor);
1796 Locker locker(this);
1797 m_qmlLists.insert(lst_type, ptr_type);
1798 m_compositeTypes.insert(ptr_type, data);
1801 bool QQml_isFileCaseCorrect(const QString &fileName)
1803 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1804 QFileInfo info(fileName);
1805 const QString absolute = info.absoluteFilePath();
1807 #if defined(Q_OS_MAC)
1808 const QString canonical = info.canonicalFilePath();
1809 #elif defined(Q_OS_WIN)
1810 wchar_t buffer[1024];
1812 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1813 if (rv == 0 || rv >= 1024) return true;
1814 rv = ::GetLongPathName(buffer, buffer, 1024);
1815 if (rv == 0 || rv >= 1024) return true;
1817 const QString canonical = QString::fromWCharArray(buffer);
1820 const int absoluteLength = absolute.length();
1821 const int canonicalLength = canonical.length();
1823 const int length = qMin(absoluteLength, canonicalLength);
1824 for (int ii = 0; ii < length; ++ii) {
1825 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1826 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1828 if (a.toLower() != c.toLower())
1840 \fn QQmlEngine *qmlEngine(const QObject *object)
1843 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1844 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1848 \fn QQmlContext *qmlContext(const QObject *object)
1851 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1852 QQmlEngine::contextForObject(object).