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();
428 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
430 static_cast<QQmlData *>(d)->destroyed(o);
433 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
435 static_cast<QQmlData *>(d)->parentChanged(o, p);
438 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
440 static_cast<QQmlData *>(d)->objectNameChanged(o);
443 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
445 QQmlData *ddata = QQmlData::get(object, false);
446 if (!ddata) return; // Probably being deleted
448 QQmlNotifierEndpoint *ep = ddata->notify(index);
449 if (ep) QQmlNotifier::emitNotify(ep, a);
452 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
454 return static_cast<QQmlData *>(d)->endpointCount(index);
457 int QQmlData::endpointCount(int index)
460 QQmlNotifierEndpoint *ep = notify(index);
471 void QQmlEnginePrivate::init()
475 static bool firstTime = true;
477 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
483 qRegisterMetaType<QVariant>("QVariant");
484 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
485 qRegisterMetaType<QJSValue>("QJSValue");
486 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
487 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
488 qRegisterMetaType<QList<int> >("QList<int>");
489 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
491 v8engine()->setEngine(q);
493 rootContext = new QQmlContext(q,true);
495 if (QCoreApplication::instance()->thread() == q->thread() &&
496 QQmlEngineDebugService::isDebuggingEnabled()) {
498 QQmlEngineDebugService::instance()->addEngine(q);
499 QV8DebugService::initialize(v8engine());
500 QV8ProfilerService::initialize();
501 QQmlProfilerService::initialize();
502 QDebugMessageService::instance();
505 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
506 if (!dataLocation.isEmpty())
507 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
508 + QDir::separator() + QLatin1String("QML")
509 + QDir::separator() + QLatin1String("OfflineStorage");
512 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
515 if (!workerScriptEngine)
516 workerScriptEngine = new QQuickWorkerScriptEngine(q);
517 return workerScriptEngine;
524 \brief The QQmlEngine class provides an environment for instantiating QML components.
527 Each QML component is instantiated in a QQmlContext.
528 QQmlContext's are essential for passing data to QML
529 components. In QML, contexts are arranged hierarchically and this
530 hierarchy is managed by the QQmlEngine.
532 Prior to creating any QML components, an application must have
533 created a QQmlEngine to gain access to a QML context. The
534 following example shows how to create a simple Text item.
538 QQmlComponent component(&engine);
539 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
540 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
542 //add item to view, etc
546 In this case, the Text item will be created in the engine's
547 \l {QQmlEngine::rootContext()}{root context}.
549 Note that the QtQuick 1 version is called QDeclarativeEngine.
551 \sa QQmlComponent, QQmlContext
555 Create a new QQmlEngine with the given \a parent.
557 QQmlEngine::QQmlEngine(QObject *parent)
558 : QJSEngine(*new QQmlEnginePrivate(this), parent)
565 Destroys the QQmlEngine.
567 Any QQmlContext's created on this engine will be
568 invalidated, but not destroyed (unless they are parented to the
571 QQmlEngine::~QQmlEngine()
574 if (d->isDebugging) {
575 QQmlEngineDebugService::instance()->remEngine(this);
578 // if we are the parent of any of the qobject module api instances,
579 // we need to remove them from our internal list, in order to prevent
580 // a segfault in engine private dtor.
581 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
582 QObject *currQObjectApi = 0;
583 QQmlMetaType::ModuleApiInstance *currInstance = 0;
584 foreach (const QQmlMetaType::ModuleApi &key, keys) {
585 currInstance = d->moduleApiInstances.value(key);
586 currQObjectApi = currInstance->qobjectApi;
587 if (this->children().contains(currQObjectApi)) {
588 delete currQObjectApi;
590 d->moduleApiInstances.remove(key);
594 if (d->incubationController)
595 d->incubationController->d = 0;
598 /*! \fn void QQmlEngine::quit()
599 This signal is emitted when the QML loaded by the engine would like to quit.
602 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
603 This signal is emitted when \a warnings messages are generated by QML.
607 Clears the engine's internal component cache.
609 This function causes the property metadata of all components previously
610 loaded by the engine to be destroyed. All previously loaded components and
611 the property bindings for all extant objects created from those components will
614 This function returns the engine to a state where it does not contain any loaded
615 component data. This may be useful in order to reload a smaller subset of the
616 previous component set, or to load a new version of a previously loaded component.
618 Once the component cache has been cleared, components must be loaded before
619 any new objects can be created.
621 void QQmlEngine::clearComponentCache()
624 d->typeLoader.clearCache();
628 Returns the engine's root context.
630 The root context is automatically created by the QQmlEngine.
631 Data that should be available to all QML component instances
632 instantiated by the engine should be put in the root context.
634 Additional data that should only be available to a subset of
635 component instances should be added to sub-contexts parented to the
638 QQmlContext *QQmlEngine::rootContext() const
640 Q_D(const QQmlEngine);
641 return d->rootContext;
645 Sets the \a factory to use for creating QNetworkAccessManager(s).
647 QNetworkAccessManager is used for all network access by QML. By
648 implementing a factory it is possible to create custom
649 QNetworkAccessManager with specialized caching, proxy and cookie
652 The factory must be set before executing the engine.
654 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
657 QMutexLocker locker(&d->mutex);
658 d->networkAccessManagerFactory = factory;
662 Returns the current QQmlNetworkAccessManagerFactory.
664 \sa setNetworkAccessManagerFactory()
666 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
668 Q_D(const QQmlEngine);
669 return d->networkAccessManagerFactory;
672 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
675 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
677 void *args[] = { 0 };
678 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
682 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
684 QMutexLocker locker(&mutex);
685 QNetworkAccessManager *nam;
686 if (networkAccessManagerFactory) {
687 nam = networkAccessManagerFactory->create(parent);
689 nam = new QNetworkAccessManager(parent);
695 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
697 Q_Q(const QQmlEngine);
698 if (!networkAccessManager)
699 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
700 return networkAccessManager;
704 Returns a common QNetworkAccessManager which can be used by any QML
705 element instantiated by this engine.
707 If a QQmlNetworkAccessManagerFactory has been set and a
708 QNetworkAccessManager has not yet been created, the
709 QQmlNetworkAccessManagerFactory will be used to create the
710 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
711 will have no proxy or cache set.
713 \sa setNetworkAccessManagerFactory()
715 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
717 Q_D(const QQmlEngine);
718 return d->getNetworkAccessManager();
723 Sets the \a provider to use for images requested via the \e
724 image: url scheme, with host \a providerId. The QQmlEngine
725 takes ownership of \a provider.
727 Image providers enable support for pixmap and threaded image
728 requests. See the QQuickImageProvider documentation for details on
729 implementing and using image providers.
731 All required image providers should be added to the engine before any
732 QML sources files are loaded.
734 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
736 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
739 QMutexLocker locker(&d->mutex);
740 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
744 Returns the image provider set for \a providerId.
746 Returns the provider if it was found; otherwise returns 0.
748 \sa QQuickImageProvider
750 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
752 Q_D(const QQmlEngine);
753 QMutexLocker locker(&d->mutex);
754 return d->imageProviders.value(providerId).data();
758 Removes the image provider for \a providerId.
760 \sa addImageProvider(), QQuickImageProvider
762 void QQmlEngine::removeImageProvider(const QString &providerId)
765 QMutexLocker locker(&d->mutex);
766 d->imageProviders.take(providerId);
770 Return the base URL for this engine. The base URL is only used to
771 resolve components when a relative URL is passed to the
772 QQmlComponent constructor.
774 If a base URL has not been explicitly set, this method returns the
775 application's current working directory.
779 QUrl QQmlEngine::baseUrl() const
781 Q_D(const QQmlEngine);
782 if (d->baseUrl.isEmpty()) {
783 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
790 Set the base URL for this engine to \a url.
794 void QQmlEngine::setBaseUrl(const QUrl &url)
801 Returns true if warning messages will be output to stderr in addition
802 to being emitted by the warnings() signal, otherwise false.
804 The default value is true.
806 bool QQmlEngine::outputWarningsToStandardError() const
808 Q_D(const QQmlEngine);
809 return d->outputWarningsToStdErr;
813 Set whether warning messages will be output to stderr to \a enabled.
815 If \a enabled is true, any warning messages generated by QML will be
816 output to stderr and emitted by the warnings() signal. If \a enabled
817 is false, on the warnings() signal will be emitted. This allows
818 applications to handle warning output themselves.
820 The default value is true.
822 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
825 d->outputWarningsToStdErr = enabled;
829 Attempt to free unused memory.
831 void QQmlEngine::collectGarbage()
837 Returns the QQmlContext for the \a object, or 0 if no
838 context has been set.
840 When the QQmlEngine instantiates a QObject, the context is
843 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
848 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
851 static_cast<QQmlData *>(priv->declarativeData);
855 else if (data->outerContext)
856 return data->outerContext->asQQmlContext();
862 Sets the QQmlContext for the \a object to \a context.
863 If the \a object already has a context, a warning is
864 output, but the context is not changed.
866 When the QQmlEngine instantiates a QObject, the context is
869 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
871 if (!object || !context)
874 QQmlData *data = QQmlData::get(object, true);
876 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
880 QQmlContextData *contextData = QQmlContextData::get(context);
881 contextData->addObject(object);
885 \enum QQmlEngine::ObjectOwnership
887 Ownership controls whether or not QML automatically destroys the
888 QObject when the object is garbage collected by the JavaScript
889 engine. The two ownership options are:
891 \value CppOwnership The object is owned by C++ code, and will
892 never be deleted by QML. The JavaScript destroy() method cannot be
893 used on objects with CppOwnership. This option is similar to
894 QScriptEngine::QtOwnership.
896 \value JavaScriptOwnership The object is owned by JavaScript.
897 When the object is returned to QML as the return value of a method
898 call or property access, QML will track it, and delete the object
899 if there are no remaining JavaScript references to it and it has no
900 QObject::parent(). An object tracked by one QQmlEngine
901 will be deleted during that QQmlEngine's destructor, and thus
902 JavaScript references between objects with JavaScriptOwnership from
903 two different engines will not be valid after the deletion of one of
904 those engines. This option is similar to QScriptEngine::ScriptOwnership.
906 Generally an application doesn't need to set an object's ownership
907 explicitly. QML uses a heuristic to set the default object
908 ownership. By default, an object that is created by QML has
909 JavaScriptOwnership. The exception to this are the root objects
910 created by calling QQmlComponent::create() or
911 QQmlComponent::beginCreate() which have CppOwnership by
912 default. The ownership of these root-level objects is considered to
913 have been transferred to the C++ caller.
915 Objects not-created by QML have CppOwnership by default. The
916 exception to this is objects returned from a C++ method call. The
917 ownership of these objects is passed to JavaScript.
919 Calling setObjectOwnership() overrides the default ownership
920 heuristic used by QML.
924 Sets the \a ownership of \a object.
926 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
931 QQmlData *ddata = QQmlData::get(object, true);
935 ddata->indestructible = (ownership == CppOwnership)?true:false;
936 ddata->explicitIndestructibleSet = true;
940 Returns the ownership of \a object.
942 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
947 QQmlData *ddata = QQmlData::get(object, false);
951 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
954 bool QQmlEngine::event(QEvent *e)
957 if (e->type() == QEvent::User)
958 d->doDeleteInEngineThread();
960 return QJSEngine::event(e);
963 void QQmlEnginePrivate::doDeleteInEngineThread()
965 QFieldList<Deletable, &Deletable::next> list;
967 list.copyAndClear(toDeleteInEngineThread);
970 while (Deletable *d = list.takeFirst())
974 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
976 QQmlData *data = QQmlData::get(object);
978 if (data && data->deferredComponent) {
979 QQmlObjectCreatingProfiler prof;
981 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
982 prof.setTypeName(type ? type->qmlTypeName()
983 : QString::fromUtf8(object->metaObject()->className()));
984 if (data->outerContext)
985 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
987 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
989 QQmlComponentPrivate::ConstructionState state;
990 QQmlComponentPrivate::beginDeferred(ep, object, &state);
992 data->deferredComponent->release();
993 data->deferredComponent = 0;
995 QQmlComponentPrivate::complete(ep, &state);
999 QQmlContext *qmlContext(const QObject *obj)
1001 return QQmlEngine::contextForObject(obj);
1004 QQmlEngine *qmlEngine(const QObject *obj)
1006 QQmlData *data = QQmlData::get(obj, false);
1007 if (!data || !data->context)
1009 return data->context->engine;
1012 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1014 QQmlData *data = QQmlData::get(object);
1016 return 0; // Attached properties are only on objects created by QML
1018 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1022 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1026 rv = pf(const_cast<QObject *>(object));
1029 data->attachedProperties()->insert(id, rv);
1034 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1035 const QMetaObject *attachedMetaObject, bool create)
1038 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1040 if (*idCache == -1 || !object)
1043 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1046 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1048 #ifndef QQML_NO_DEBUG_PROTOCOL
1049 if (!QQmlEnginePrivate::qml_debugging_enabled
1051 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1053 QQmlEnginePrivate::qml_debugging_enabled = true;
1058 class QQmlDataExtended {
1061 ~QQmlDataExtended();
1063 QHash<int, QObject *> attachedProperties;
1064 QQmlNotifier objectNameNotifier;
1067 QQmlDataExtended::QQmlDataExtended()
1071 QQmlDataExtended::~QQmlDataExtended()
1075 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1078 layout(endpoint->next);
1080 int index = endpoint->sourceSignal;
1081 index = qMin(index, 0xFFFF - 1);
1083 endpoint->next = notifies[index];
1084 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1085 endpoint->prev = ¬ifies[index];
1086 notifies[index] = endpoint;
1089 void QQmlData::NotifyList::layout()
1091 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1094 QQmlNotifierEndpoint **old = notifies;
1095 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1096 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1097 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1098 sizeof(QQmlNotifierEndpoint*);
1099 memset(notifies + notifiesSize, 0, memsetSize);
1101 if (notifies != old) {
1102 for (int ii = 0; ii < notifiesSize; ++ii)
1104 notifies[ii]->prev = ¬ifies[ii];
1107 notifiesSize = maximumTodoIndex + 1;
1112 maximumTodoIndex = 0;
1116 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1119 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1120 notifyList->connectionMask = 0;
1121 notifyList->maximumTodoIndex = 0;
1122 notifyList->notifiesSize = 0;
1123 notifyList->todo = 0;
1124 notifyList->notifies = 0;
1127 Q_ASSERT(!endpoint->isConnected());
1129 index = qMin(index, 0xFFFF - 1);
1130 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1132 if (index < notifyList->notifiesSize) {
1134 endpoint->next = notifyList->notifies[index];
1135 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1136 endpoint->prev = ¬ifyList->notifies[index];
1137 notifyList->notifies[index] = endpoint;
1140 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1142 endpoint->next = notifyList->todo;
1143 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1144 endpoint->prev = ¬ifyList->todo;
1145 notifyList->todo = endpoint;
1149 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1151 QQmlData *data = QQmlData::get(obj);
1152 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1156 index MUST be the index returned by QMetaMethod::index()
1157 This is different than the index returned by QObjectPrivate::signalIndex()
1159 bool QQmlData::signalHasEndpoint(int index)
1161 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1164 QQmlNotifier *QQmlData::objectNameNotifier() const
1166 if (!extendedData) extendedData = new QQmlDataExtended;
1167 return &extendedData->objectNameNotifier;
1170 QHash<int, QObject *> *QQmlData::attachedProperties() const
1172 if (!extendedData) extendedData = new QQmlDataExtended;
1173 return &extendedData->attachedProperties;
1176 void QQmlData::destroyed(QObject *object)
1178 if (deferredComponent)
1179 deferredComponent->release();
1181 if (nextContextObject)
1182 nextContextObject->prevContextObject = prevContextObject;
1183 if (prevContextObject)
1184 *prevContextObject = nextContextObject;
1186 QQmlAbstractBinding *binding = bindings;
1188 QQmlAbstractBinding *next = binding->m_nextBinding;
1189 binding->m_prevBinding = 0;
1190 binding->m_nextBinding = 0;
1195 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1196 while (signalHandler) {
1197 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1198 signalHandler->m_prevSignal = 0;
1199 signalHandler->m_nextSignal = 0;
1200 delete signalHandler;
1201 signalHandler = next;
1208 propertyCache->release();
1210 if (ownContext && context)
1214 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1215 *guard = (QObject *)0;
1216 guard->objectDestroyed(object);
1220 while (notifyList->todo)
1221 notifyList->todo->disconnect();
1222 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1223 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1226 free(notifyList->notifies);
1231 delete extendedData;
1233 v8object.Clear(); // The WeakReference handler will clean the actual handle
1239 void QQmlData::parentChanged(QObject *object, QObject *parent)
1245 void QQmlData::objectNameChanged(QObject *)
1247 if (extendedData) objectNameNotifier()->notify();
1250 bool QQmlData::hasBindingBit(int bit) const
1252 if (bindingBitsSize > bit)
1253 return bindingBits[bit / 32] & (1 << (bit % 32));
1258 void QQmlData::clearBindingBit(int bit)
1260 if (bindingBitsSize > bit)
1261 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1264 void QQmlData::setBindingBit(QObject *obj, int bit)
1266 if (bindingBitsSize <= bit) {
1267 int props = obj->metaObject()->propertyCount();
1268 Q_ASSERT(bit < props);
1270 int arraySize = (props + 31) / 32;
1271 int oldArraySize = bindingBitsSize / 32;
1273 bindingBits = (quint32 *)realloc(bindingBits,
1274 arraySize * sizeof(quint32));
1276 memset(bindingBits + oldArraySize,
1278 sizeof(quint32) * (arraySize - oldArraySize));
1280 bindingBitsSize = arraySize * 32;
1283 bindingBits[bit / 32] |= (1 << (bit % 32));
1286 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1288 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1289 if (url.authority().isEmpty())
1290 return QLatin1Char(':') + url.path();
1293 return url.toLocalFile();
1297 static QString toLocalFile(const QString &url)
1299 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1302 QString file = url.mid(7);
1304 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1306 // magic for drives on windows
1307 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1313 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1315 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1316 if (url.length() > 4)
1317 return QLatin1Char(':') + url.mid(4);
1321 return toLocalFile(url);
1324 void QQmlEnginePrivate::sendQuit()
1328 if (q->receivers(SIGNAL(quit())) == 0) {
1329 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1333 static void dumpwarning(const QQmlError &error)
1335 qWarning().nospace() << qPrintable(error.toString());
1338 static void dumpwarning(const QList<QQmlError> &errors)
1340 for (int ii = 0; ii < errors.count(); ++ii)
1341 dumpwarning(errors.at(ii));
1344 void QQmlEnginePrivate::warning(const QQmlError &error)
1347 q->warnings(QList<QQmlError>() << error);
1348 if (outputWarningsToStdErr)
1352 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1355 q->warnings(errors);
1356 if (outputWarningsToStdErr)
1357 dumpwarning(errors);
1360 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1363 QQmlEnginePrivate::get(engine)->warning(error);
1368 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1371 QQmlEnginePrivate::get(engine)->warning(error);
1376 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1379 engine->warning(error);
1384 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1387 engine->warning(error);
1393 This function should be called prior to evaluation of any js expression,
1394 so that scarce resources are not freed prematurely (eg, if there is a
1395 nested javascript expression).
1397 void QQmlEnginePrivate::referenceScarceResources()
1399 scarceResourcesRefCount += 1;
1403 This function should be called after evaluation of the js expression is
1404 complete, and so the scarce resources may be freed safely.
1406 void QQmlEnginePrivate::dereferenceScarceResources()
1408 Q_ASSERT(scarceResourcesRefCount > 0);
1409 scarceResourcesRefCount -= 1;
1411 // if the refcount is zero, then evaluation of the "top level"
1412 // expression must have completed. We can safely release the
1413 // scarce resources.
1414 if (scarceResourcesRefCount == 0) {
1415 // iterate through the list and release them all.
1416 // note that the actual SRD is owned by the JS engine,
1417 // so we cannot delete the SRD; but we can free the
1418 // memory used by the variant in the SRD.
1419 while (ScarceResourceData *sr = scarceResources.first()) {
1420 sr->data = QVariant();
1421 scarceResources.remove(sr);
1427 Adds \a path as a directory where the engine searches for
1428 installed modules in a URL-based directory structure.
1429 The \a path may be a local filesystem directory or a URL.
1431 The newly added \a path will be first in the importPathList().
1433 \sa setImportPathList(), {QML Modules}
1435 void QQmlEngine::addImportPath(const QString& path)
1438 d->importDatabase.addImportPath(path);
1442 Returns the list of directories where the engine searches for
1443 installed modules in a URL-based directory structure.
1445 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1446 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1447 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1448 provided by that module. A \c qmldir file is required for defining the
1449 type version mapping and possibly QML extensions plugins.
1451 By default, the list contains the directory of the application executable,
1452 paths specified in the \c QML_IMPORT_PATH environment variable,
1453 and the builtin \c ImportsPath from QLibraryInfo.
1455 \sa addImportPath(), setImportPathList()
1457 QStringList QQmlEngine::importPathList() const
1459 Q_D(const QQmlEngine);
1460 return d->importDatabase.importPathList();
1464 Sets \a paths as the list of directories where the engine searches for
1465 installed modules in a URL-based directory structure.
1467 By default, the list contains the directory of the application executable,
1468 paths specified in the \c QML_IMPORT_PATH environment variable,
1469 and the builtin \c ImportsPath from QLibraryInfo.
1471 \sa importPathList(), addImportPath()
1473 void QQmlEngine::setImportPathList(const QStringList &paths)
1476 d->importDatabase.setImportPathList(paths);
1481 Adds \a path as a directory where the engine searches for
1482 native plugins for imported modules (referenced in the \c qmldir file).
1484 By default, the list contains only \c ., i.e. the engine searches
1485 in the directory of the \c qmldir file itself.
1487 The newly added \a path will be first in the pluginPathList().
1489 \sa setPluginPathList()
1491 void QQmlEngine::addPluginPath(const QString& path)
1494 d->importDatabase.addPluginPath(path);
1499 Returns the list of directories where the engine searches for
1500 native plugins for imported modules (referenced in the \c qmldir file).
1502 By default, the list contains only \c ., i.e. the engine searches
1503 in the directory of the \c qmldir file itself.
1505 \sa addPluginPath(), setPluginPathList()
1507 QStringList QQmlEngine::pluginPathList() const
1509 Q_D(const QQmlEngine);
1510 return d->importDatabase.pluginPathList();
1514 Sets the list of directories where the engine searches for
1515 native plugins for imported modules (referenced in the \c qmldir file)
1518 By default, the list contains only \c ., i.e. the engine searches
1519 in the directory of the \c qmldir file itself.
1521 \sa pluginPathList(), addPluginPath()
1523 void QQmlEngine::setPluginPathList(const QStringList &paths)
1526 d->importDatabase.setPluginPathList(paths);
1530 Imports the plugin named \a filePath with the \a uri provided.
1531 Returns true if the plugin was successfully imported; otherwise returns false.
1533 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1535 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1537 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1540 return d->importDatabase.importPlugin(filePath, uri, errors);
1544 Imports the plugin named \a filePath with the \a uri provided.
1545 Returns true if the plugin was successfully imported; otherwise returns false.
1547 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1549 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1551 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1554 QList<QQmlError> errors;
1555 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1556 if (!errors.isEmpty()) {
1558 for (int i = 0; i < errors.size(); ++i) {
1559 builtError = QString(QLatin1String("%1\n %2"))
1561 .arg(errors.at(i).toString());
1563 *errorString = builtError;
1569 \property QQmlEngine::offlineStoragePath
1570 \brief the directory for storing offline user data
1572 Returns the directory where SQL and other offline
1575 QQuickWebView and the SQL databases created with openDatabase()
1578 The default is QML/OfflineStorage in the platform-standard
1579 user application data directory.
1581 Note that the path may not currently exist on the filesystem, so
1582 callers wanting to \e create new files at this location should create
1583 it first - see QDir::mkpath().
1585 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1588 d->offlineStoragePath = dir;
1591 QString QQmlEngine::offlineStoragePath() const
1593 Q_D(const QQmlEngine);
1594 return d->offlineStoragePath;
1597 static void voidptr_destructor(void *v)
1599 void **ptr = (void **)v;
1603 static void *voidptr_constructor(const void *v)
1608 return new void*(*(void **)v);
1612 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1616 if (!mo->superClass()) {
1617 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1618 propertyCache.insert(mo, rv);
1621 QQmlPropertyCache *super = cache(mo->superClass());
1622 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1623 propertyCache.insert(mo, rv);
1628 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1631 QList<QQmlType *> types;
1633 int maxMinorVersion = 0;
1635 const QMetaObject *metaObject = type->metaObject();
1637 while (metaObject) {
1638 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1639 type->majorVersion(), minorVersion);
1641 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1647 metaObject = metaObject->superClass();
1650 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1652 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1656 QQmlPropertyCache *raw = cache(type->metaObject());
1658 bool hasCopied = false;
1660 for (int ii = 0; ii < types.count(); ++ii) {
1661 QQmlType *currentType = types.at(ii);
1665 int rev = currentType->metaObjectRevision();
1666 int moIndex = types.count() - 1 - ii;
1668 if (raw->allowedRevisionCache[moIndex] != rev) {
1673 raw->allowedRevisionCache[moIndex] = rev;
1677 // Test revision compatibility - the basic rule is:
1678 // * Anything that is excluded, cannot overload something that is not excluded *
1680 // Signals override:
1681 // * other signals and methods of the same name.
1682 // * properties named on<Signal Name>
1683 // * automatic <property name>Changed notify signals
1685 // Methods override:
1686 // * other methods of the same name
1688 // Properties override:
1689 // * other elements of the same name
1691 bool overloadError = false;
1692 QString overloadName;
1695 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1696 !overloadError && iter != raw->stringCache.end();
1699 QQmlPropertyData *d = *iter;
1700 if (raw->isAllowedInRevision(d))
1701 continue; // Not excluded - no problems
1703 // check that a regular "name" overload isn't happening
1704 QQmlPropertyData *current = d;
1705 while (!overloadError && current) {
1706 current = d->overrideData(current);
1707 if (current && raw->isAllowedInRevision(current))
1708 overloadError = true;
1713 if (overloadError) {
1714 if (hasCopied) raw->release();
1716 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."));
1720 if (!hasCopied) raw->addref();
1721 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1723 if (minorVersion != maxMinorVersion) {
1725 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1731 QQmlMetaType::ModuleApiInstance *
1732 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1734 Locker locker(this);
1736 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1738 a = new QQmlMetaType::ModuleApiInstance;
1739 a->scriptCallback = module.script;
1740 a->qobjectCallback = module.qobject;
1741 a->instanceMetaObject = module.instanceMetaObject;
1742 moduleApiInstances.insert(module, a);
1748 bool QQmlEnginePrivate::isQObject(int t)
1750 Locker locker(this);
1751 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1754 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1756 Locker locker(this);
1757 int t = v.userType();
1758 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1760 return *(QObject **)(v.constData());
1762 return QQmlMetaType::toQObject(v, ok);
1766 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1768 Locker locker(this);
1769 if (m_compositeTypes.contains(t))
1770 return QQmlMetaType::Object;
1771 else if (m_qmlLists.contains(t))
1772 return QQmlMetaType::List;
1774 return QQmlMetaType::typeCategory(t);
1777 bool QQmlEnginePrivate::isList(int t) const
1779 Locker locker(this);
1780 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1783 int QQmlEnginePrivate::listType(int t) const
1785 Locker locker(this);
1786 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1787 if (iter != m_qmlLists.end())
1790 return QQmlMetaType::listType(t);
1793 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1795 Locker locker(this);
1796 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1797 if (iter != m_compositeTypes.end()) {
1798 return (*iter)->root;
1800 QQmlType *type = QQmlMetaType::qmlType(t);
1801 return type?type->baseMetaObject():0;
1805 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1807 Locker locker(this);
1808 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1809 if (iter != m_compositeTypes.end()) {
1810 return (*iter)->root;
1812 QQmlType *type = QQmlMetaType::qmlType(t);
1813 return type?type->metaObject():0;
1817 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1819 QByteArray name = data->root->className();
1821 QByteArray ptr = name + '*';
1822 QByteArray lst = "QQmlListProperty<" + name + '>';
1824 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1825 voidptr_constructor);
1826 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1827 voidptr_constructor);
1831 Locker locker(this);
1832 m_qmlLists.insert(lst_type, ptr_type);
1833 m_compositeTypes.insert(ptr_type, data);
1836 bool QQml_isFileCaseCorrect(const QString &fileName)
1838 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1839 QFileInfo info(fileName);
1840 const QString absolute = info.absoluteFilePath();
1842 #if defined(Q_OS_MAC)
1843 const QString canonical = info.canonicalFilePath();
1844 #elif defined(Q_OS_WIN)
1845 wchar_t buffer[1024];
1847 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1848 if (rv == 0 || rv >= 1024) return true;
1849 rv = ::GetLongPathName(buffer, buffer, 1024);
1850 if (rv == 0 || rv >= 1024) return true;
1852 const QString canonical = QString::fromWCharArray(buffer);
1855 const int absoluteLength = absolute.length();
1856 const int canonicalLength = canonical.length();
1858 const int length = qMin(absoluteLength, canonicalLength);
1859 for (int ii = 0; ii < length; ++ii) {
1860 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1861 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1863 if (a.toLower() != c.toLower())
1875 \fn QQmlEngine *qmlEngine(const QObject *object)
1878 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1879 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1883 \fn QQmlContext *qmlContext(const QObject *object)
1886 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1887 QQmlEngine::contextForObject(object).