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");
482 qRegisterMetaType<QVariant>("QVariant");
483 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
484 qRegisterMetaType<QJSValue>("QJSValue");
485 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
486 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
487 qRegisterMetaType<QList<int> >("QList<int>");
488 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
492 v8engine()->setEngine(q);
494 rootContext = new QQmlContext(q,true);
496 if (QCoreApplication::instance()->thread() == q->thread() &&
497 QQmlEngineDebugService::isDebuggingEnabled()) {
499 QQmlEngineDebugService::instance()->addEngine(q);
500 QV8DebugService::initialize(v8engine());
501 QV8ProfilerService::initialize();
502 QQmlProfilerService::initialize();
503 QDebugMessageService::instance();
506 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
507 if (!dataLocation.isEmpty())
508 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
509 + QDir::separator() + QLatin1String("QML")
510 + QDir::separator() + QLatin1String("OfflineStorage");
513 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
516 if (!workerScriptEngine)
517 workerScriptEngine = new QQuickWorkerScriptEngine(q);
518 return workerScriptEngine;
525 \brief The QQmlEngine class provides an environment for instantiating QML components.
528 Each QML component is instantiated in a QQmlContext.
529 QQmlContext's are essential for passing data to QML
530 components. In QML, contexts are arranged hierarchically and this
531 hierarchy is managed by the QQmlEngine.
533 Prior to creating any QML components, an application must have
534 created a QQmlEngine to gain access to a QML context. The
535 following example shows how to create a simple Text item.
539 QQmlComponent component(&engine);
540 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
541 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
543 //add item to view, etc
547 In this case, the Text item will be created in the engine's
548 \l {QQmlEngine::rootContext()}{root context}.
550 Note that the QtQuick 1 version is called QDeclarativeEngine.
552 \sa QQmlComponent QQmlContext
556 Create a new QQmlEngine with the given \a parent.
558 QQmlEngine::QQmlEngine(QObject *parent)
559 : QJSEngine(*new QQmlEnginePrivate(this), parent)
566 Destroys the QQmlEngine.
568 Any QQmlContext's created on this engine will be
569 invalidated, but not destroyed (unless they are parented to the
572 QQmlEngine::~QQmlEngine()
575 if (d->isDebugging) {
576 QQmlEngineDebugService::instance()->remEngine(this);
579 // if we are the parent of any of the qobject module api instances,
580 // we need to remove them from our internal list, in order to prevent
581 // a segfault in engine private dtor.
582 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
583 QObject *currQObjectApi = 0;
584 QQmlMetaType::ModuleApiInstance *currInstance = 0;
585 foreach (const QQmlMetaType::ModuleApi &key, keys) {
586 currInstance = d->moduleApiInstances.value(key);
587 currQObjectApi = currInstance->qobjectApi;
588 if (this->children().contains(currQObjectApi)) {
589 delete currQObjectApi;
591 d->moduleApiInstances.remove(key);
595 if (d->incubationController)
596 d->incubationController->d = 0;
599 /*! \fn void QQmlEngine::quit()
600 This signal is emitted when the QML loaded by the engine would like to quit.
603 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
604 This signal is emitted when \a warnings messages are generated by QML.
608 Clears the engine's internal component cache.
610 This function causes the property metadata of all components previously
611 loaded by the engine to be destroyed. All previously loaded components and
612 the property bindings for all extant objects created from those components will
615 This function returns the engine to a state where it does not contain any loaded
616 component data. This may be useful in order to reload a smaller subset of the
617 previous component set, or to load a new version of a previously loaded component.
619 Once the component cache has been cleared, components must be loaded before
620 any new objects can be created.
622 void QQmlEngine::clearComponentCache()
625 d->typeLoader.clearCache();
629 Returns the engine's root context.
631 The root context is automatically created by the QQmlEngine.
632 Data that should be available to all QML component instances
633 instantiated by the engine should be put in the root context.
635 Additional data that should only be available to a subset of
636 component instances should be added to sub-contexts parented to the
639 QQmlContext *QQmlEngine::rootContext() const
641 Q_D(const QQmlEngine);
642 return d->rootContext;
646 Sets the \a factory to use for creating QNetworkAccessManager(s).
648 QNetworkAccessManager is used for all network access by QML. By
649 implementing a factory it is possible to create custom
650 QNetworkAccessManager with specialized caching, proxy and cookie
653 The factory must be set before executing the engine.
655 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
658 QMutexLocker locker(&d->mutex);
659 d->networkAccessManagerFactory = factory;
663 Returns the current QQmlNetworkAccessManagerFactory.
665 \sa setNetworkAccessManagerFactory()
667 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
669 Q_D(const QQmlEngine);
670 return d->networkAccessManagerFactory;
673 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
676 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
678 void *args[] = { 0 };
679 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
683 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
685 QMutexLocker locker(&mutex);
686 QNetworkAccessManager *nam;
687 if (networkAccessManagerFactory) {
688 nam = networkAccessManagerFactory->create(parent);
690 nam = new QNetworkAccessManager(parent);
696 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
698 Q_Q(const QQmlEngine);
699 if (!networkAccessManager)
700 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
701 return networkAccessManager;
705 Returns a common QNetworkAccessManager which can be used by any QML
706 element instantiated by this engine.
708 If a QQmlNetworkAccessManagerFactory has been set and a
709 QNetworkAccessManager has not yet been created, the
710 QQmlNetworkAccessManagerFactory will be used to create the
711 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
712 will have no proxy or cache set.
714 \sa setNetworkAccessManagerFactory()
716 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
718 Q_D(const QQmlEngine);
719 return d->getNetworkAccessManager();
724 Sets the \a provider to use for images requested via the \e
725 image: url scheme, with host \a providerId. The QQmlEngine
726 takes ownership of \a provider.
728 Image providers enable support for pixmap and threaded image
729 requests. See the QQuickImageProvider documentation for details on
730 implementing and using image providers.
732 All required image providers should be added to the engine before any
733 QML sources files are loaded.
735 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
737 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
740 QMutexLocker locker(&d->mutex);
741 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
745 Returns the image provider set for \a providerId.
747 Returns the provider if it was found; otherwise returns 0.
749 \sa QQuickImageProvider
751 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
753 Q_D(const QQmlEngine);
754 QMutexLocker locker(&d->mutex);
755 return d->imageProviders.value(providerId).data();
759 Removes the image provider for \a providerId.
761 \sa addImageProvider(), QQuickImageProvider
763 void QQmlEngine::removeImageProvider(const QString &providerId)
766 QMutexLocker locker(&d->mutex);
767 d->imageProviders.take(providerId);
771 Return the base URL for this engine. The base URL is only used to
772 resolve components when a relative URL is passed to the
773 QQmlComponent constructor.
775 If a base URL has not been explicitly set, this method returns the
776 application's current working directory.
780 QUrl QQmlEngine::baseUrl() const
782 Q_D(const QQmlEngine);
783 if (d->baseUrl.isEmpty()) {
784 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
791 Set the base URL for this engine to \a url.
795 void QQmlEngine::setBaseUrl(const QUrl &url)
802 Returns true if warning messages will be output to stderr in addition
803 to being emitted by the warnings() signal, otherwise false.
805 The default value is true.
807 bool QQmlEngine::outputWarningsToStandardError() const
809 Q_D(const QQmlEngine);
810 return d->outputWarningsToStdErr;
814 Set whether warning messages will be output to stderr to \a enabled.
816 If \a enabled is true, any warning messages generated by QML will be
817 output to stderr and emitted by the warnings() signal. If \a enabled
818 is false, on the warnings() signal will be emitted. This allows
819 applications to handle warning output themselves.
821 The default value is true.
823 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
826 d->outputWarningsToStdErr = enabled;
830 Attempt to free unused memory.
832 void QQmlEngine::collectGarbage()
838 Returns the QQmlContext for the \a object, or 0 if no
839 context has been set.
841 When the QQmlEngine instantiates a QObject, the context is
844 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
849 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
852 static_cast<QQmlData *>(priv->declarativeData);
856 else if (data->outerContext)
857 return data->outerContext->asQQmlContext();
863 Sets the QQmlContext for the \a object to \a context.
864 If the \a object already has a context, a warning is
865 output, but the context is not changed.
867 When the QQmlEngine instantiates a QObject, the context is
870 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
872 if (!object || !context)
875 QQmlData *data = QQmlData::get(object, true);
877 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
881 QQmlContextData *contextData = QQmlContextData::get(context);
882 contextData->addObject(object);
886 \enum QQmlEngine::ObjectOwnership
888 Ownership controls whether or not QML automatically destroys the
889 QObject when the object is garbage collected by the JavaScript
890 engine. The two ownership options are:
892 \value CppOwnership The object is owned by C++ code, and will
893 never be deleted by QML. The JavaScript destroy() method cannot be
894 used on objects with CppOwnership. This option is similar to
895 QScriptEngine::QtOwnership.
897 \value JavaScriptOwnership The object is owned by JavaScript.
898 When the object is returned to QML as the return value of a method
899 call or property access, QML will track it, and delete the object
900 if there are no remaining JavaScript references to it and it has no
901 QObject::parent(). An object tracked by one QQmlEngine
902 will be deleted during that QQmlEngine's destructor, and thus
903 JavaScript references between objects with JavaScriptOwnership from
904 two different engines will not be valid after the deletion of one of
905 those engines. This option is similar to QScriptEngine::ScriptOwnership.
907 Generally an application doesn't need to set an object's ownership
908 explicitly. QML uses a heuristic to set the default object
909 ownership. By default, an object that is created by QML has
910 JavaScriptOwnership. The exception to this are the root objects
911 created by calling QQmlComponent::create() or
912 QQmlComponent::beginCreate() which have CppOwnership by
913 default. The ownership of these root-level objects is considered to
914 have been transferred to the C++ caller.
916 Objects not-created by QML have CppOwnership by default. The
917 exception to this is objects returned from a C++ method call. The
918 ownership of these objects is passed to JavaScript.
920 Calling setObjectOwnership() overrides the default ownership
921 heuristic used by QML.
925 Sets the \a ownership of \a object.
927 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
932 QQmlData *ddata = QQmlData::get(object, true);
936 ddata->indestructible = (ownership == CppOwnership)?true:false;
937 ddata->explicitIndestructibleSet = true;
941 Returns the ownership of \a object.
943 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
948 QQmlData *ddata = QQmlData::get(object, false);
952 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
955 bool QQmlEngine::event(QEvent *e)
958 if (e->type() == QEvent::User)
959 d->doDeleteInEngineThread();
961 return QJSEngine::event(e);
964 void QQmlEnginePrivate::doDeleteInEngineThread()
966 QFieldList<Deletable, &Deletable::next> list;
968 list.copyAndClear(toDeleteInEngineThread);
971 while (Deletable *d = list.takeFirst())
975 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
977 QQmlData *data = QQmlData::get(object);
979 if (data && data->deferredComponent) {
980 QQmlObjectCreatingProfiler prof;
982 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
983 prof.setTypeName(type ? type->qmlTypeName()
984 : QString::fromUtf8(object->metaObject()->className()));
985 if (data->outerContext)
986 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
988 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
990 QQmlComponentPrivate::ConstructionState state;
991 QQmlComponentPrivate::beginDeferred(ep, object, &state);
993 data->deferredComponent->release();
994 data->deferredComponent = 0;
996 QQmlComponentPrivate::complete(ep, &state);
1000 QQmlContext *qmlContext(const QObject *obj)
1002 return QQmlEngine::contextForObject(obj);
1005 QQmlEngine *qmlEngine(const QObject *obj)
1007 QQmlData *data = QQmlData::get(obj, false);
1008 if (!data || !data->context)
1010 return data->context->engine;
1013 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1015 QQmlData *data = QQmlData::get(object);
1017 return 0; // Attached properties are only on objects created by QML
1019 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1023 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1027 rv = pf(const_cast<QObject *>(object));
1030 data->attachedProperties()->insert(id, rv);
1035 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1036 const QMetaObject *attachedMetaObject, bool create)
1039 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1041 if (*idCache == -1 || !object)
1044 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1047 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1049 #ifndef QQML_NO_DEBUG_PROTOCOL
1050 if (!QQmlEnginePrivate::qml_debugging_enabled
1052 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1054 QQmlEnginePrivate::qml_debugging_enabled = true;
1059 class QQmlDataExtended {
1062 ~QQmlDataExtended();
1064 QHash<int, QObject *> attachedProperties;
1065 QQmlNotifier objectNameNotifier;
1068 QQmlDataExtended::QQmlDataExtended()
1072 QQmlDataExtended::~QQmlDataExtended()
1076 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1079 layout(endpoint->next);
1081 int index = endpoint->sourceSignal;
1082 index = qMin(index, 0xFFFF - 1);
1084 endpoint->next = notifies[index];
1085 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1086 endpoint->prev = ¬ifies[index];
1087 notifies[index] = endpoint;
1090 void QQmlData::NotifyList::layout()
1092 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1095 QQmlNotifierEndpoint **old = notifies;
1096 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1097 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1098 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1099 sizeof(QQmlNotifierEndpoint*);
1100 memset(notifies + notifiesSize, 0, memsetSize);
1102 if (notifies != old) {
1103 for (int ii = 0; ii < notifiesSize; ++ii)
1105 notifies[ii]->prev = ¬ifies[ii];
1108 notifiesSize = maximumTodoIndex + 1;
1113 maximumTodoIndex = 0;
1117 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1120 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1121 notifyList->connectionMask = 0;
1122 notifyList->maximumTodoIndex = 0;
1123 notifyList->notifiesSize = 0;
1124 notifyList->todo = 0;
1125 notifyList->notifies = 0;
1128 Q_ASSERT(!endpoint->isConnected());
1130 index = qMin(index, 0xFFFF - 1);
1131 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1133 if (index < notifyList->notifiesSize) {
1135 endpoint->next = notifyList->notifies[index];
1136 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1137 endpoint->prev = ¬ifyList->notifies[index];
1138 notifyList->notifies[index] = endpoint;
1141 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1143 endpoint->next = notifyList->todo;
1144 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1145 endpoint->prev = ¬ifyList->todo;
1146 notifyList->todo = endpoint;
1150 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1152 QQmlData *data = QQmlData::get(obj);
1153 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1157 index MUST be the index returned by QMetaMethod::index()
1158 This is different than the index returned by QObjectPrivate::signalIndex()
1160 bool QQmlData::signalHasEndpoint(int index)
1162 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1165 QQmlNotifier *QQmlData::objectNameNotifier() const
1167 if (!extendedData) extendedData = new QQmlDataExtended;
1168 return &extendedData->objectNameNotifier;
1171 QHash<int, QObject *> *QQmlData::attachedProperties() const
1173 if (!extendedData) extendedData = new QQmlDataExtended;
1174 return &extendedData->attachedProperties;
1177 void QQmlData::destroyed(QObject *object)
1179 if (deferredComponent)
1180 deferredComponent->release();
1182 if (nextContextObject)
1183 nextContextObject->prevContextObject = prevContextObject;
1184 if (prevContextObject)
1185 *prevContextObject = nextContextObject;
1187 QQmlAbstractBinding *binding = bindings;
1189 QQmlAbstractBinding *next = binding->m_nextBinding;
1190 binding->m_prevBinding = 0;
1191 binding->m_nextBinding = 0;
1196 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1197 while (signalHandler) {
1198 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1199 signalHandler->m_prevSignal = 0;
1200 signalHandler->m_nextSignal = 0;
1201 delete signalHandler;
1202 signalHandler = next;
1209 propertyCache->release();
1211 if (ownContext && context)
1215 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1216 *guard = (QObject *)0;
1217 guard->objectDestroyed(object);
1221 while (notifyList->todo)
1222 notifyList->todo->disconnect();
1223 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1224 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1227 free(notifyList->notifies);
1232 delete extendedData;
1234 v8object.Clear(); // The WeakReference handler will clean the actual handle
1240 void QQmlData::parentChanged(QObject *object, QObject *parent)
1246 void QQmlData::objectNameChanged(QObject *)
1248 if (extendedData) objectNameNotifier()->notify();
1251 bool QQmlData::hasBindingBit(int bit) const
1253 if (bindingBitsSize > bit)
1254 return bindingBits[bit / 32] & (1 << (bit % 32));
1259 void QQmlData::clearBindingBit(int bit)
1261 if (bindingBitsSize > bit)
1262 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1265 void QQmlData::setBindingBit(QObject *obj, int bit)
1267 if (bindingBitsSize <= bit) {
1268 int props = obj->metaObject()->propertyCount();
1269 Q_ASSERT(bit < props);
1271 int arraySize = (props + 31) / 32;
1272 int oldArraySize = bindingBitsSize / 32;
1274 bindingBits = (quint32 *)realloc(bindingBits,
1275 arraySize * sizeof(quint32));
1277 memset(bindingBits + oldArraySize,
1279 sizeof(quint32) * (arraySize - oldArraySize));
1281 bindingBitsSize = arraySize * 32;
1284 bindingBits[bit / 32] |= (1 << (bit % 32));
1287 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1289 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1290 if (url.authority().isEmpty())
1291 return QLatin1Char(':') + url.path();
1294 return url.toLocalFile();
1298 static QString toLocalFile(const QString &url)
1300 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1303 QString file = url.mid(7);
1305 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1307 // magic for drives on windows
1308 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1314 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1316 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1317 if (url.length() > 4)
1318 return QLatin1Char(':') + url.mid(4);
1322 return toLocalFile(url);
1325 void QQmlEnginePrivate::sendQuit()
1329 if (q->receivers(SIGNAL(quit())) == 0) {
1330 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1334 static void dumpwarning(const QQmlError &error)
1336 qWarning().nospace() << qPrintable(error.toString());
1339 static void dumpwarning(const QList<QQmlError> &errors)
1341 for (int ii = 0; ii < errors.count(); ++ii)
1342 dumpwarning(errors.at(ii));
1345 void QQmlEnginePrivate::warning(const QQmlError &error)
1348 q->warnings(QList<QQmlError>() << error);
1349 if (outputWarningsToStdErr)
1353 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1356 q->warnings(errors);
1357 if (outputWarningsToStdErr)
1358 dumpwarning(errors);
1361 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1364 QQmlEnginePrivate::get(engine)->warning(error);
1369 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1372 QQmlEnginePrivate::get(engine)->warning(error);
1377 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1380 engine->warning(error);
1385 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1388 engine->warning(error);
1394 This function should be called prior to evaluation of any js expression,
1395 so that scarce resources are not freed prematurely (eg, if there is a
1396 nested javascript expression).
1398 void QQmlEnginePrivate::referenceScarceResources()
1400 scarceResourcesRefCount += 1;
1404 This function should be called after evaluation of the js expression is
1405 complete, and so the scarce resources may be freed safely.
1407 void QQmlEnginePrivate::dereferenceScarceResources()
1409 Q_ASSERT(scarceResourcesRefCount > 0);
1410 scarceResourcesRefCount -= 1;
1412 // if the refcount is zero, then evaluation of the "top level"
1413 // expression must have completed. We can safely release the
1414 // scarce resources.
1415 if (scarceResourcesRefCount == 0) {
1416 // iterate through the list and release them all.
1417 // note that the actual SRD is owned by the JS engine,
1418 // so we cannot delete the SRD; but we can free the
1419 // memory used by the variant in the SRD.
1420 while (ScarceResourceData *sr = scarceResources.first()) {
1421 sr->data = QVariant();
1422 scarceResources.remove(sr);
1428 Adds \a path as a directory where the engine searches for
1429 installed modules in a URL-based directory structure.
1430 The \a path may be a local filesystem directory or a URL.
1432 The newly added \a path will be first in the importPathList().
1434 \sa setImportPathList(), {QML Modules}
1436 void QQmlEngine::addImportPath(const QString& path)
1439 d->importDatabase.addImportPath(path);
1443 Returns the list of directories where the engine searches for
1444 installed modules in a URL-based directory structure.
1446 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1447 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1448 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1449 provided by that module. A \c qmldir file is required for defining the
1450 type version mapping and possibly QML extensions plugins.
1452 By default, the list contains the directory of the application executable,
1453 paths specified in the \c QML_IMPORT_PATH environment variable,
1454 and the builtin \c ImportsPath from QLibraryInfo.
1456 \sa addImportPath() setImportPathList()
1458 QStringList QQmlEngine::importPathList() const
1460 Q_D(const QQmlEngine);
1461 return d->importDatabase.importPathList();
1465 Sets \a paths as the list of directories where the engine searches for
1466 installed modules in a URL-based directory structure.
1468 By default, the list contains the directory of the application executable,
1469 paths specified in the \c QML_IMPORT_PATH environment variable,
1470 and the builtin \c ImportsPath from QLibraryInfo.
1472 \sa importPathList() addImportPath()
1474 void QQmlEngine::setImportPathList(const QStringList &paths)
1477 d->importDatabase.setImportPathList(paths);
1482 Adds \a path as a directory where the engine searches for
1483 native plugins for imported modules (referenced in the \c qmldir file).
1485 By default, the list contains only \c ., i.e. the engine searches
1486 in the directory of the \c qmldir file itself.
1488 The newly added \a path will be first in the pluginPathList().
1490 \sa setPluginPathList()
1492 void QQmlEngine::addPluginPath(const QString& path)
1495 d->importDatabase.addPluginPath(path);
1500 Returns the list of directories where the engine searches for
1501 native plugins for imported modules (referenced in the \c qmldir file).
1503 By default, the list contains only \c ., i.e. the engine searches
1504 in the directory of the \c qmldir file itself.
1506 \sa addPluginPath() setPluginPathList()
1508 QStringList QQmlEngine::pluginPathList() const
1510 Q_D(const QQmlEngine);
1511 return d->importDatabase.pluginPathList();
1515 Sets the list of directories where the engine searches for
1516 native plugins for imported modules (referenced in the \c qmldir file)
1519 By default, the list contains only \c ., i.e. the engine searches
1520 in the directory of the \c qmldir file itself.
1522 \sa pluginPathList() addPluginPath()
1524 void QQmlEngine::setPluginPathList(const QStringList &paths)
1527 d->importDatabase.setPluginPathList(paths);
1531 Imports the plugin named \a filePath with the \a uri provided.
1532 Returns true if the plugin was successfully imported; otherwise returns false.
1534 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1536 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1538 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1541 return d->importDatabase.importPlugin(filePath, uri, errors);
1545 Imports the plugin named \a filePath with the \a uri provided.
1546 Returns true if the plugin was successfully imported; otherwise returns false.
1548 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1550 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1552 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1555 QList<QQmlError> errors;
1556 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1557 if (!errors.isEmpty()) {
1559 for (int i = 0; i < errors.size(); ++i) {
1560 builtError = QString(QLatin1String("%1\n %2"))
1562 .arg(errors.at(i).toString());
1564 *errorString = builtError;
1570 \property QQmlEngine::offlineStoragePath
1571 \brief the directory for storing offline user data
1573 Returns the directory where SQL and other offline
1576 QQuickWebView and the SQL databases created with openDatabase()
1579 The default is QML/OfflineStorage in the platform-standard
1580 user application data directory.
1582 Note that the path may not currently exist on the filesystem, so
1583 callers wanting to \e create new files at this location should create
1584 it first - see QDir::mkpath().
1586 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1589 d->offlineStoragePath = dir;
1592 QString QQmlEngine::offlineStoragePath() const
1594 Q_D(const QQmlEngine);
1595 return d->offlineStoragePath;
1598 static void voidptr_destructor(void *v)
1600 void **ptr = (void **)v;
1604 static void *voidptr_constructor(const void *v)
1609 return new void*(*(void **)v);
1613 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1617 if (!mo->superClass()) {
1618 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1619 propertyCache.insert(mo, rv);
1622 QQmlPropertyCache *super = cache(mo->superClass());
1623 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1624 propertyCache.insert(mo, rv);
1629 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1632 QList<QQmlType *> types;
1634 int maxMinorVersion = 0;
1636 const QMetaObject *metaObject = type->metaObject();
1638 while (metaObject) {
1639 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1640 type->majorVersion(), minorVersion);
1642 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1648 metaObject = metaObject->superClass();
1651 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1653 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1657 QQmlPropertyCache *raw = cache(type->metaObject());
1659 bool hasCopied = false;
1661 for (int ii = 0; ii < types.count(); ++ii) {
1662 QQmlType *currentType = types.at(ii);
1666 int rev = currentType->metaObjectRevision();
1667 int moIndex = types.count() - 1 - ii;
1669 if (raw->allowedRevisionCache[moIndex] != rev) {
1674 raw->allowedRevisionCache[moIndex] = rev;
1678 // Test revision compatibility - the basic rule is:
1679 // * Anything that is excluded, cannot overload something that is not excluded *
1681 // Signals override:
1682 // * other signals and methods of the same name.
1683 // * properties named on<Signal Name>
1684 // * automatic <property name>Changed notify signals
1686 // Methods override:
1687 // * other methods of the same name
1689 // Properties override:
1690 // * other elements of the same name
1692 bool overloadError = false;
1693 QString overloadName;
1696 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1697 !overloadError && iter != raw->stringCache.end();
1700 QQmlPropertyData *d = *iter;
1701 if (raw->isAllowedInRevision(d))
1702 continue; // Not excluded - no problems
1704 // check that a regular "name" overload isn't happening
1705 QQmlPropertyData *current = d;
1706 while (!overloadError && current) {
1707 current = d->overrideData(current);
1708 if (current && raw->isAllowedInRevision(current))
1709 overloadError = true;
1714 if (overloadError) {
1715 if (hasCopied) raw->release();
1717 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."));
1721 if (!hasCopied) raw->addref();
1722 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1724 if (minorVersion != maxMinorVersion) {
1726 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1732 QQmlMetaType::ModuleApiInstance *
1733 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1735 Locker locker(this);
1737 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1739 a = new QQmlMetaType::ModuleApiInstance;
1740 a->scriptCallback = module.script;
1741 a->qobjectCallback = module.qobject;
1742 a->instanceMetaObject = module.instanceMetaObject;
1743 moduleApiInstances.insert(module, a);
1749 bool QQmlEnginePrivate::isQObject(int t)
1751 Locker locker(this);
1752 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1755 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1757 Locker locker(this);
1758 int t = v.userType();
1759 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1761 return *(QObject **)(v.constData());
1763 return QQmlMetaType::toQObject(v, ok);
1767 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1769 Locker locker(this);
1770 if (m_compositeTypes.contains(t))
1771 return QQmlMetaType::Object;
1772 else if (m_qmlLists.contains(t))
1773 return QQmlMetaType::List;
1775 return QQmlMetaType::typeCategory(t);
1778 bool QQmlEnginePrivate::isList(int t) const
1780 Locker locker(this);
1781 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1784 int QQmlEnginePrivate::listType(int t) const
1786 Locker locker(this);
1787 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1788 if (iter != m_qmlLists.end())
1791 return QQmlMetaType::listType(t);
1794 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1796 Locker locker(this);
1797 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1798 if (iter != m_compositeTypes.end()) {
1799 return (*iter)->root;
1801 QQmlType *type = QQmlMetaType::qmlType(t);
1802 return type?type->baseMetaObject():0;
1806 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1808 Locker locker(this);
1809 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1810 if (iter != m_compositeTypes.end()) {
1811 return (*iter)->root;
1813 QQmlType *type = QQmlMetaType::qmlType(t);
1814 return type?type->metaObject():0;
1818 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1820 QByteArray name = data->root->className();
1822 QByteArray ptr = name + '*';
1823 QByteArray lst = "QQmlListProperty<" + name + '>';
1825 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1826 voidptr_constructor);
1827 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1828 voidptr_constructor);
1832 Locker locker(this);
1833 m_qmlLists.insert(lst_type, ptr_type);
1834 m_compositeTypes.insert(ptr_type, data);
1837 bool QQml_isFileCaseCorrect(const QString &fileName)
1839 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1840 QFileInfo info(fileName);
1841 const QString absolute = info.absoluteFilePath();
1843 #if defined(Q_OS_MAC)
1844 const QString canonical = info.canonicalFilePath();
1845 #elif defined(Q_OS_WIN)
1846 wchar_t buffer[1024];
1848 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1849 if (rv == 0 || rv >= 1024) return true;
1850 rv = ::GetLongPathName(buffer, buffer, 1024);
1851 if (rv == 0 || rv >= 1024) return true;
1853 const QString canonical = QString::fromWCharArray(buffer);
1856 const int absoluteLength = absolute.length();
1857 const int canonicalLength = canonical.length();
1859 const int length = qMin(absoluteLength, canonicalLength);
1860 for (int ii = 0; ii < length; ++ii) {
1861 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1862 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1864 if (a.toLower() != c.toLower())
1876 \fn QQmlEngine *qmlEngine(const QObject *object)
1879 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1880 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1884 \fn QQmlContext *qmlContext(const QObject *object)
1887 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1888 QQmlEngine::contextForObject(object).