1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlbinding_p_p.h"
53 #include "qqmlvme_p.h"
54 #include <private/qqmlenginedebugservice_p.h>
55 #include "qqmlstringconverters_p.h"
56 #include "qqmlxmlhttprequest_p.h"
57 #include "qqmlscriptstring.h"
58 #include "qqmlglobal_p.h"
59 #include "qquicklistmodel_p.h"
60 #include "qquickworkerscript_p.h"
61 #include "qqmlcomponent_p.h"
62 #include "qqmlnetworkaccessmanagerfactory.h"
63 #include "qqmldirparser_p.h"
64 #include "qqmlextensioninterface.h"
65 #include "qqmllist_p.h"
66 #include "qqmltypenamecache_p.h"
67 #include "qqmlnotifier_p.h"
68 #include <private/qqmlprofilerservice_p.h>
69 #include <private/qquickapplication_p.h>
70 #include <private/qv8debugservice_p.h>
71 #include <private/qdebugmessageservice_p.h>
72 #include "qqmlincubator.h"
73 #include <private/qv8profilerservice_p.h>
75 #include <QtCore/qstandardpaths.h>
76 #include <QtCore/qsettings.h>
78 #include <QtCore/qmetaobject.h>
79 #include <QNetworkAccessManager>
81 #include <QMetaObject>
82 #include <QtCore/qcoreapplication.h>
83 #include <QtCore/qdir.h>
84 #include <QtCore/qmutex.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
87 #include <private/qobject_p.h>
89 #include <private/qqmllocale_p.h>
91 #ifdef Q_OS_WIN // for %APPDATA%
92 #include <qt_windows.h>
96 #define CSIDL_APPDATA 0x001a // <username>\Application Data
99 Q_DECLARE_METATYPE(QQmlProperty)
103 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
105 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
106 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
110 \qmlclass QtObject QObject
111 \ingroup qml-utility-elements
113 \brief The QtObject element is the most basic element in QML.
115 The QtObject element is a non-visual element which contains only the
118 It can be useful to create a QtObject if you need an extremely
119 lightweight element to enclose a set of custom properties:
121 \snippet doc/src/snippets/qml/qtobject.qml 0
123 It can also be useful for C++ integration, as it is just a plain
124 QObject. See the QObject documentation for further details.
127 \qmlproperty string QtObject::objectName
128 This property holds the QObject::objectName for this specific object instance.
130 This allows a C++ application to locate an item within a QML component
131 using the QObject::findChild() method. For example, the following C++
132 application locates the child \l Rectangle item and dynamically changes its
141 width: 200; height: 200
155 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
158 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
160 item->setProperty("color", QColor(Qt::yellow));
164 bool QQmlEnginePrivate::qml_debugging_enabled = false;
166 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
168 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
169 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
170 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
171 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
172 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
175 void QQmlEnginePrivate::defineModule()
177 registerBaseTypes("QtQuick", 2, 0);
178 qmlRegisterType<QQmlBinding>();
179 qmlRegisterUncreatableType<QQuickApplication>("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class"));
180 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
184 QQmlImageProviderBase::~QQmlImageProviderBase()
190 \qmlclass Qt QQmlEnginePrivate
191 \ingroup qml-utility-elements
192 \brief The QML global Qt object provides useful enums and functions from Qt.
194 \keyword QmlGlobalQtObject
196 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
198 The \c Qt object is a global object with utility functions, properties and enums.
200 It is not instantiable; to use it, call the members of the global \c Qt object directly.
207 color: Qt.rgba(1, 0, 0, 1)
208 text: Qt.md5("hello, world")
215 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
216 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
220 The Qt object also contains helper functions for creating objects of specific
221 data types. This is primarily useful when setting the properties of an item
222 when the property has one of the following types:
225 \o \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
226 \o \c rect - use \l{Qt::rect()}{Qt.rect()}
227 \o \c point - use \l{Qt::point()}{Qt.point()}
228 \o \c size - use \l{Qt::size()}{Qt.size()}
229 \o \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
232 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
234 \section1 Date/Time Formatters
236 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
239 \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
240 \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
241 \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
244 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
247 \section1 Dynamic Object Creation
248 The following functions on the global object allow you to dynamically create QML
249 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
253 \o \l{Qt::createComponent()}{object Qt.createComponent(url)}
254 \o \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
260 \qmlproperty object Qt::application
263 The \c application object provides access to global application state
264 properties shared by many QML components.
270 \o \c application.active
272 This read-only property indicates whether the application is the top-most and focused
273 application, and the user is able to interact with the application. The property
274 is false when the application is in the background, the device keylock or screen
275 saver is active, the screen backlight is turned off, or the global system dialog
276 is being displayed on top of the application. It can be used for stopping and
277 pausing animations, timers and active processing of data in order to save device
278 battery power and free device memory and processor load when the application is not
282 \o \c application.layoutDirection
284 This read-only property can be used to query the default layout direction of the
285 application. On system start-up, the default layout direction depends on the
286 application's language. The property has a value of \c Qt.RightToLeft in locales
287 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
288 where the reading direction flows from left to right. You can bind to this
289 property to customize your application layouts to support both layout directions.
294 \o Qt.LeftToRight - Text and graphics elements should be positioned
296 \o Qt.RightToLeft - Text and graphics elements should be positioned
301 \o \c application.inputPanel
303 This read-only property allows access to application's QInputPanel object
304 and all its properties and slots. See the QInputPanel documentation for
305 further details. Deprecated in favor of Qt.InputMethod
308 The following example uses the \c application object to indicate
309 whether the application is currently active:
311 \snippet doc/src/snippets/qml/application.qml document
313 \qmlproperty object Qt::inputMethod
316 The \c inputMethod object allows access to application's QInputMethod object
317 and all its properties and slots. See the QInputMethod documentation for
323 \qmlmethod object Qt::include(string url, jsobject callback)
325 Includes another JavaScript file. This method can only be used from within JavaScript files,
326 and not regular QML files.
328 This imports all functions from \a url into the current script's namespace.
330 Qt.include() returns an object that describes the status of the operation. The object has
331 a single property, \c {status}, that is set to one of the following values:
334 \header \o Symbol \o Value \o Description
335 \row \o result.OK \o 0 \o The include completed successfully.
336 \row \o result.LOADING \o 1 \o Data is being loaded from the network.
337 \row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url.
338 \row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code.
339 An additional \c exception property will be set in this case.
342 The \c status property will be updated as the operation progresses.
344 If provided, \a callback is invoked when the operation completes. The callback is passed
345 the same object as is returned from the Qt.include() call.
347 // Qt.include() is implemented in qv8include.cpp
350 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
351 : propertyCapture(0), rootContext(0), isDebugging(false),
352 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
353 cleanup(0), erroredBindings(0), inProgressCreations(0),
354 workerScriptEngine(0), activeVME(0),
355 networkAccessManager(0), networkAccessManagerFactory(0),
356 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
357 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
361 QQmlEnginePrivate::~QQmlEnginePrivate()
363 if (inProgressCreations)
364 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
367 QQmlCleanup *c = cleanup;
369 if (cleanup) cleanup->prev = &cleanup;
375 doDeleteInEngineThread();
377 if (incubationController) incubationController->d = 0;
378 incubationController = 0;
383 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
385 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
387 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
389 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
390 delete (*iter)->qobjectApi;
395 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
397 QObjectPrivate *p = QObjectPrivate::get(o);
398 if (p->declarativeData) {
399 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
400 if (d->ownContext && d->context) {
401 d->context->destroy();
407 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
409 static_cast<QQmlData *>(d)->destroyed(o);
412 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
414 static_cast<QQmlData *>(d)->parentChanged(o, p);
417 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
419 static_cast<QQmlData *>(d)->objectNameChanged(o);
422 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
424 QQmlData *ddata = QQmlData::get(object, false);
425 if (!ddata) return; // Probably being deleted
427 QQmlNotifierEndpoint *ep = ddata->notify(index);
428 if (ep) QQmlNotifier::emitNotify(ep);
431 void QQmlEnginePrivate::init()
435 static bool firstTime = true;
437 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
442 qRegisterMetaType<QVariant>("QVariant");
443 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
444 qRegisterMetaType<QJSValue>("QJSValue");
445 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
446 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
447 qRegisterMetaType<QList<int> >("QList<int>");
448 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
452 v8engine()->setEngine(q);
454 rootContext = new QQmlContext(q,true);
456 if (QCoreApplication::instance()->thread() == q->thread() &&
457 QQmlEngineDebugService::isDebuggingEnabled()) {
459 QQmlEngineDebugService::instance()->addEngine(q);
460 QV8DebugService::initialize(v8engine());
461 QV8ProfilerService::initialize();
462 QQmlProfilerService::initialize();
463 QDebugMessageService::instance();
466 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
467 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
468 QDir::separator() + QLatin1String("QML") +
469 QDir::separator() + QLatin1String("OfflineStorage");
472 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
475 if (!workerScriptEngine)
476 workerScriptEngine = new QQuickWorkerScriptEngine(q);
477 return workerScriptEngine;
483 \brief The QQmlEngine class provides an environment for instantiating QML components.
486 Each QML component is instantiated in a QQmlContext.
487 QQmlContext's are essential for passing data to QML
488 components. In QML, contexts are arranged hierarchically and this
489 hierarchy is managed by the QQmlEngine.
491 Prior to creating any QML components, an application must have
492 created a QQmlEngine to gain access to a QML context. The
493 following example shows how to create a simple Text item.
497 QQmlComponent component(&engine);
498 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
499 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
501 //add item to view, etc
505 In this case, the Text item will be created in the engine's
506 \l {QQmlEngine::rootContext()}{root context}.
508 \sa QQmlComponent QQmlContext
512 Create a new QQmlEngine with the given \a parent.
514 QQmlEngine::QQmlEngine(QObject *parent)
515 : QJSEngine(*new QQmlEnginePrivate(this), parent)
522 Destroys the QQmlEngine.
524 Any QQmlContext's created on this engine will be
525 invalidated, but not destroyed (unless they are parented to the
528 QQmlEngine::~QQmlEngine()
531 if (d->isDebugging) {
532 QQmlEngineDebugService::instance()->remEngine(this);
535 // if we are the parent of any of the qobject module api instances,
536 // we need to remove them from our internal list, in order to prevent
537 // a segfault in engine private dtor.
538 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
539 QObject *currQObjectApi = 0;
540 QQmlMetaType::ModuleApiInstance *currInstance = 0;
541 foreach (const QQmlMetaType::ModuleApi &key, keys) {
542 currInstance = d->moduleApiInstances.value(key);
543 currQObjectApi = currInstance->qobjectApi;
544 if (this->children().contains(currQObjectApi)) {
545 delete currQObjectApi;
547 d->moduleApiInstances.remove(key);
551 // ensure we clean up QObjects with JS ownership
554 if (d->incubationController)
555 d->incubationController->d = 0;
558 /*! \fn void QQmlEngine::quit()
559 This signal is emitted when the QML loaded by the engine would like to quit.
562 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
563 This signal is emitted when \a warnings messages are generated by QML.
567 Clears the engine's internal component cache.
569 Normally the QQmlEngine caches components loaded from qml
570 files. This method clears this cache and forces the component to be
573 void QQmlEngine::clearComponentCache()
576 d->typeLoader.clearCache();
580 Returns the engine's root context.
582 The root context is automatically created by the QQmlEngine.
583 Data that should be available to all QML component instances
584 instantiated by the engine should be put in the root context.
586 Additional data that should only be available to a subset of
587 component instances should be added to sub-contexts parented to the
590 QQmlContext *QQmlEngine::rootContext() const
592 Q_D(const QQmlEngine);
593 return d->rootContext;
597 Sets the \a factory to use for creating QNetworkAccessManager(s).
599 QNetworkAccessManager is used for all network access by QML. By
600 implementing a factory it is possible to create custom
601 QNetworkAccessManager with specialized caching, proxy and cookie
604 The factory must be set before executing the engine.
606 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
609 QMutexLocker locker(&d->mutex);
610 d->networkAccessManagerFactory = factory;
614 Returns the current QQmlNetworkAccessManagerFactory.
616 \sa setNetworkAccessManagerFactory()
618 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
620 Q_D(const QQmlEngine);
621 return d->networkAccessManagerFactory;
624 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
627 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
629 void *args[] = { 0 };
630 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
634 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
636 QMutexLocker locker(&mutex);
637 QNetworkAccessManager *nam;
638 if (networkAccessManagerFactory) {
639 nam = networkAccessManagerFactory->create(parent);
641 nam = new QNetworkAccessManager(parent);
647 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
649 Q_Q(const QQmlEngine);
650 if (!networkAccessManager)
651 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
652 return networkAccessManager;
656 Returns a common QNetworkAccessManager which can be used by any QML
657 element instantiated by this engine.
659 If a QQmlNetworkAccessManagerFactory has been set and a
660 QNetworkAccessManager has not yet been created, the
661 QQmlNetworkAccessManagerFactory will be used to create the
662 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
663 will have no proxy or cache set.
665 \sa setNetworkAccessManagerFactory()
667 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
669 Q_D(const QQmlEngine);
670 return d->getNetworkAccessManager();
675 Sets the \a provider to use for images requested via the \e
676 image: url scheme, with host \a providerId. The QQmlEngine
677 takes ownership of \a provider.
679 Image providers enable support for pixmap and threaded image
680 requests. See the QQuickImageProvider documentation for details on
681 implementing and using image providers.
683 All required image providers should be added to the engine before any
684 QML sources files are loaded.
686 \sa removeImageProvider(), QQuickImageProvider
688 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
691 QMutexLocker locker(&d->mutex);
692 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
696 Returns the image provider set for \a providerId.
698 Returns the provider if it was found; otherwise returns 0.
700 \sa QQuickImageProvider
702 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
704 Q_D(const QQmlEngine);
705 QMutexLocker locker(&d->mutex);
706 return d->imageProviders.value(providerId).data();
710 Removes the image provider for \a providerId.
712 \sa addImageProvider(), QQuickImageProvider
714 void QQmlEngine::removeImageProvider(const QString &providerId)
717 QMutexLocker locker(&d->mutex);
718 d->imageProviders.take(providerId);
722 Return the base URL for this engine. The base URL is only used to
723 resolve components when a relative URL is passed to the
724 QQmlComponent constructor.
726 If a base URL has not been explicitly set, this method returns the
727 application's current working directory.
731 QUrl QQmlEngine::baseUrl() const
733 Q_D(const QQmlEngine);
734 if (d->baseUrl.isEmpty()) {
735 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
742 Set the base URL for this engine to \a url.
746 void QQmlEngine::setBaseUrl(const QUrl &url)
753 Returns true if warning messages will be output to stderr in addition
754 to being emitted by the warnings() signal, otherwise false.
756 The default value is true.
758 bool QQmlEngine::outputWarningsToStandardError() const
760 Q_D(const QQmlEngine);
761 return d->outputWarningsToStdErr;
765 Set whether warning messages will be output to stderr to \a enabled.
767 If \a enabled is true, any warning messages generated by QML will be
768 output to stderr and emitted by the warnings() signal. If \a enabled
769 is false, on the warnings() signal will be emitted. This allows
770 applications to handle warning output themselves.
772 The default value is true.
774 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
777 d->outputWarningsToStdErr = enabled;
781 Attempt to free unused memory.
783 void QQmlEngine::collectGarbage()
789 Returns the QQmlContext for the \a object, or 0 if no
790 context has been set.
792 When the QQmlEngine instantiates a QObject, the context is
795 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
800 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
803 static_cast<QQmlData *>(priv->declarativeData);
807 else if (data->outerContext)
808 return data->outerContext->asQQmlContext();
814 Sets the QQmlContext for the \a object to \a context.
815 If the \a object already has a context, a warning is
816 output, but the context is not changed.
818 When the QQmlEngine instantiates a QObject, the context is
821 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
823 if (!object || !context)
826 QQmlData *data = QQmlData::get(object, true);
828 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
832 QQmlContextData *contextData = QQmlContextData::get(context);
833 contextData->addObject(object);
837 \enum QQmlEngine::ObjectOwnership
839 Ownership controls whether or not QML automatically destroys the
840 QObject when the object is garbage collected by the JavaScript
841 engine. The two ownership options are:
843 \value CppOwnership The object is owned by C++ code, and will
844 never be deleted by QML. The JavaScript destroy() method cannot be
845 used on objects with CppOwnership. This option is similar to
846 QScriptEngine::QtOwnership.
848 \value JavaScriptOwnership The object is owned by JavaScript.
849 When the object is returned to QML as the return value of a method
850 call or property access, QML will delete the object if there are no
851 remaining JavaScript references to it and it has no
852 QObject::parent(). This option is similar to
853 QScriptEngine::ScriptOwnership.
855 Generally an application doesn't need to set an object's ownership
856 explicitly. QML uses a heuristic to set the default object
857 ownership. By default, an object that is created by QML has
858 JavaScriptOwnership. The exception to this are the root objects
859 created by calling QQmlComponent::create() or
860 QQmlComponent::beginCreate() which have CppOwnership by
861 default. The ownership of these root-level objects is considered to
862 have been transferred to the C++ caller.
864 Objects not-created by QML have CppOwnership by default. The
865 exception to this is objects returned from a C++ method call. The
866 ownership of these objects is passed to JavaScript.
868 Calling setObjectOwnership() overrides the default ownership
869 heuristic used by QML.
873 Sets the \a ownership of \a object.
875 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
880 QQmlData *ddata = QQmlData::get(object, true);
884 ddata->indestructible = (ownership == CppOwnership)?true:false;
885 ddata->explicitIndestructibleSet = true;
889 Returns the ownership of \a object.
891 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
896 QQmlData *ddata = QQmlData::get(object, false);
900 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
903 bool QQmlEngine::event(QEvent *e)
906 if (e->type() == QEvent::User)
907 d->doDeleteInEngineThread();
909 return QJSEngine::event(e);
912 void QQmlEnginePrivate::doDeleteInEngineThread()
914 QFieldList<Deletable, &Deletable::next> list;
916 list.copyAndClear(toDeleteInEngineThread);
919 while (Deletable *d = list.takeFirst())
923 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
925 QQmlData *data = QQmlData::get(object);
927 if (data && data->deferredComponent) {
928 QQmlObjectCreatingProfiler prof;
930 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
931 prof.setTypeName(type ? type->qmlTypeName()
932 : QString::fromUtf8(object->metaObject()->className()));
933 if (data->outerContext)
934 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
936 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
938 QQmlComponentPrivate::ConstructionState state;
939 QQmlComponentPrivate::beginDeferred(ep, object, &state);
941 data->deferredComponent->release();
942 data->deferredComponent = 0;
944 QQmlComponentPrivate::complete(ep, &state);
948 QQmlContext *qmlContext(const QObject *obj)
950 return QQmlEngine::contextForObject(obj);
953 QQmlEngine *qmlEngine(const QObject *obj)
955 QQmlData *data = QQmlData::get(obj, false);
956 if (!data || !data->context)
958 return data->context->engine;
961 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
963 QQmlData *data = QQmlData::get(object);
965 return 0; // Attached properties are only on objects created by QML
967 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
971 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
975 rv = pf(const_cast<QObject *>(object));
978 data->attachedProperties()->insert(id, rv);
983 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
984 const QMetaObject *attachedMetaObject, bool create)
987 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
989 if (*idCache == -1 || !object)
992 return qmlAttachedPropertiesObjectById(*idCache, object, create);
995 QQmlDebuggingEnabler::QQmlDebuggingEnabler()
997 #ifndef QQML_NO_DEBUG_PROTOCOL
998 if (!QQmlEnginePrivate::qml_debugging_enabled) {
999 qWarning("QML debugging is enabled. Only use this in a safe environment.");
1001 QQmlEnginePrivate::qml_debugging_enabled = true;
1006 class QQmlDataExtended {
1009 ~QQmlDataExtended();
1011 QHash<int, QObject *> attachedProperties;
1012 QQmlNotifier objectNameNotifier;
1015 QQmlDataExtended::QQmlDataExtended()
1019 QQmlDataExtended::~QQmlDataExtended()
1023 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1026 layout(endpoint->next);
1028 int index = endpoint->sourceSignal;
1029 index = qMin(index, 0xFFFF - 1);
1031 endpoint->next = notifies[index];
1032 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1033 endpoint->prev = ¬ifies[index];
1034 notifies[index] = endpoint;
1037 void QQmlData::NotifyList::layout()
1039 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1042 QQmlNotifierEndpoint **old = notifies;
1043 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1044 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1045 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1046 sizeof(QQmlNotifierEndpoint*);
1047 memset(notifies + notifiesSize, 0, memsetSize);
1049 if (notifies != old) {
1050 for (int ii = 0; ii < notifiesSize; ++ii)
1052 notifies[ii]->prev = ¬ifies[ii];
1055 notifiesSize = maximumTodoIndex + 1;
1060 maximumTodoIndex = 0;
1064 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1067 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1068 notifyList->connectionMask = 0;
1069 notifyList->maximumTodoIndex = 0;
1070 notifyList->notifiesSize = 0;
1071 notifyList->todo = 0;
1072 notifyList->notifies = 0;
1075 Q_ASSERT(!endpoint->isConnected());
1077 index = qMin(index, 0xFFFF - 1);
1078 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1080 if (index < notifyList->notifiesSize) {
1082 endpoint->next = notifyList->notifies[index];
1083 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1084 endpoint->prev = ¬ifyList->notifies[index];
1085 notifyList->notifies[index] = endpoint;
1088 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1090 endpoint->next = notifyList->todo;
1091 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1092 endpoint->prev = ¬ifyList->todo;
1093 notifyList->todo = endpoint;
1097 QQmlNotifier *QQmlData::objectNameNotifier() const
1099 if (!extendedData) extendedData = new QQmlDataExtended;
1100 return &extendedData->objectNameNotifier;
1103 QHash<int, QObject *> *QQmlData::attachedProperties() const
1105 if (!extendedData) extendedData = new QQmlDataExtended;
1106 return &extendedData->attachedProperties;
1109 void QQmlData::destroyed(QObject *object)
1111 if (deferredComponent)
1112 deferredComponent->release();
1114 if (nextContextObject)
1115 nextContextObject->prevContextObject = prevContextObject;
1116 if (prevContextObject)
1117 *prevContextObject = nextContextObject;
1119 QQmlAbstractBinding *binding = bindings;
1121 QQmlAbstractBinding *next = binding->m_nextBinding;
1122 binding->m_prevBinding = 0;
1123 binding->m_nextBinding = 0;
1132 propertyCache->release();
1134 if (ownContext && context)
1138 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1139 *guard = (QObject *)0;
1140 guard->objectDestroyed(object);
1144 while (notifyList->todo)
1145 notifyList->todo->disconnect();
1146 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1147 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1150 free(notifyList->notifies);
1155 delete extendedData;
1157 v8object.Clear(); // The WeakReference handler will clean the actual handle
1163 void QQmlData::parentChanged(QObject *object, QObject *parent)
1169 void QQmlData::objectNameChanged(QObject *)
1171 if (extendedData) objectNameNotifier()->notify();
1174 bool QQmlData::hasBindingBit(int bit) const
1176 if (bindingBitsSize > bit)
1177 return bindingBits[bit / 32] & (1 << (bit % 32));
1182 void QQmlData::clearBindingBit(int bit)
1184 if (bindingBitsSize > bit)
1185 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1188 void QQmlData::setBindingBit(QObject *obj, int bit)
1190 if (bindingBitsSize <= bit) {
1191 int props = obj->metaObject()->propertyCount();
1192 Q_ASSERT(bit < props);
1194 int arraySize = (props + 31) / 32;
1195 int oldArraySize = bindingBitsSize / 32;
1197 bindingBits = (quint32 *)realloc(bindingBits,
1198 arraySize * sizeof(quint32));
1200 memset(bindingBits + oldArraySize,
1202 sizeof(quint32) * (arraySize - oldArraySize));
1204 bindingBitsSize = arraySize * 32;
1207 bindingBits[bit / 32] |= (1 << (bit % 32));
1210 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1212 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1213 if (url.authority().isEmpty())
1214 return QLatin1Char(':') + url.path();
1217 return url.toLocalFile();
1221 static QString toLocalFile(const QString &url)
1223 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1226 QString file = url.mid(7);
1228 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1230 // magic for drives on windows
1231 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1237 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1239 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1240 if (url.length() > 4)
1241 return QLatin1Char(':') + url.mid(4);
1245 return toLocalFile(url);
1248 void QQmlEnginePrivate::sendQuit()
1252 if (q->receivers(SIGNAL(quit())) == 0) {
1253 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1257 static void dumpwarning(const QQmlError &error)
1259 qWarning().nospace() << qPrintable(error.toString());
1262 static void dumpwarning(const QList<QQmlError> &errors)
1264 for (int ii = 0; ii < errors.count(); ++ii)
1265 dumpwarning(errors.at(ii));
1268 void QQmlEnginePrivate::warning(const QQmlError &error)
1271 q->warnings(QList<QQmlError>() << error);
1272 if (outputWarningsToStdErr)
1276 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1279 q->warnings(errors);
1280 if (outputWarningsToStdErr)
1281 dumpwarning(errors);
1284 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1287 QQmlEnginePrivate::get(engine)->warning(error);
1292 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1295 QQmlEnginePrivate::get(engine)->warning(error);
1300 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1303 engine->warning(error);
1308 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1311 engine->warning(error);
1317 This function should be called prior to evaluation of any js expression,
1318 so that scarce resources are not freed prematurely (eg, if there is a
1319 nested javascript expression).
1321 void QQmlEnginePrivate::referenceScarceResources()
1323 scarceResourcesRefCount += 1;
1327 This function should be called after evaluation of the js expression is
1328 complete, and so the scarce resources may be freed safely.
1330 void QQmlEnginePrivate::dereferenceScarceResources()
1332 Q_ASSERT(scarceResourcesRefCount > 0);
1333 scarceResourcesRefCount -= 1;
1335 // if the refcount is zero, then evaluation of the "top level"
1336 // expression must have completed. We can safely release the
1337 // scarce resources.
1338 if (scarceResourcesRefCount == 0) {
1339 // iterate through the list and release them all.
1340 // note that the actual SRD is owned by the JS engine,
1341 // so we cannot delete the SRD; but we can free the
1342 // memory used by the variant in the SRD.
1343 while (ScarceResourceData *sr = scarceResources.first()) {
1344 sr->data = QVariant();
1345 scarceResources.remove(sr);
1351 Adds \a path as a directory where the engine searches for
1352 installed modules in a URL-based directory structure.
1353 The \a path may be a local filesystem directory or a URL.
1355 The newly added \a path will be first in the importPathList().
1357 \sa setImportPathList(), {QML Modules}
1359 void QQmlEngine::addImportPath(const QString& path)
1362 d->importDatabase.addImportPath(path);
1366 Returns the list of directories where the engine searches for
1367 installed modules in a URL-based directory structure.
1369 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1370 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1371 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1372 provided by that module. A \c qmldir file is required for defining the
1373 type version mapping and possibly QML extensions plugins.
1375 By default, the list contains the directory of the application executable,
1376 paths specified in the \c QML_IMPORT_PATH environment variable,
1377 and the builtin \c ImportsPath from QLibraryInfo.
1379 \sa addImportPath() setImportPathList()
1381 QStringList QQmlEngine::importPathList() const
1383 Q_D(const QQmlEngine);
1384 return d->importDatabase.importPathList();
1388 Sets \a paths as the list of directories where the engine searches for
1389 installed modules in a URL-based directory structure.
1391 By default, the list contains the directory of the application executable,
1392 paths specified in the \c QML_IMPORT_PATH environment variable,
1393 and the builtin \c ImportsPath from QLibraryInfo.
1395 \sa importPathList() addImportPath()
1397 void QQmlEngine::setImportPathList(const QStringList &paths)
1400 d->importDatabase.setImportPathList(paths);
1405 Adds \a path as a directory where the engine searches for
1406 native plugins for imported modules (referenced in the \c qmldir file).
1408 By default, the list contains only \c ., i.e. the engine searches
1409 in the directory of the \c qmldir file itself.
1411 The newly added \a path will be first in the pluginPathList().
1413 \sa setPluginPathList()
1415 void QQmlEngine::addPluginPath(const QString& path)
1418 d->importDatabase.addPluginPath(path);
1423 Returns the list of directories where the engine searches for
1424 native plugins for imported modules (referenced in the \c qmldir file).
1426 By default, the list contains only \c ., i.e. the engine searches
1427 in the directory of the \c qmldir file itself.
1429 \sa addPluginPath() setPluginPathList()
1431 QStringList QQmlEngine::pluginPathList() const
1433 Q_D(const QQmlEngine);
1434 return d->importDatabase.pluginPathList();
1438 Sets the list of directories where the engine searches for
1439 native plugins for imported modules (referenced in the \c qmldir file)
1442 By default, the list contains only \c ., i.e. the engine searches
1443 in the directory of the \c qmldir file itself.
1445 \sa pluginPathList() addPluginPath()
1447 void QQmlEngine::setPluginPathList(const QStringList &paths)
1450 d->importDatabase.setPluginPathList(paths);
1454 Imports the plugin named \a filePath with the \a uri provided.
1455 Returns true if the plugin was successfully imported; otherwise returns false.
1457 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1459 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1461 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1464 return d->importDatabase.importPlugin(filePath, uri, errors);
1468 Imports the plugin named \a filePath with the \a uri provided.
1469 Returns true if the plugin was successfully imported; otherwise returns false.
1471 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1473 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1475 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1478 QList<QQmlError> errors;
1479 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1480 if (!errors.isEmpty()) {
1482 for (int i = 0; i < errors.size(); ++i) {
1483 builtError = QString(QLatin1String("%1\n %2"))
1485 .arg(errors.at(i).toString());
1487 *errorString = builtError;
1493 \property QQmlEngine::offlineStoragePath
1494 \brief the directory for storing offline user data
1496 Returns the directory where SQL and other offline
1499 QQuickWebView and the SQL databases created with openDatabase()
1502 The default is QML/OfflineStorage in the platform-standard
1503 user application data directory.
1505 Note that the path may not currently exist on the filesystem, so
1506 callers wanting to \e create new files at this location should create
1507 it first - see QDir::mkpath().
1509 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1512 d->offlineStoragePath = dir;
1515 QString QQmlEngine::offlineStoragePath() const
1517 Q_D(const QQmlEngine);
1518 return d->offlineStoragePath;
1521 static void voidptr_destructor(void *v)
1523 void **ptr = (void **)v;
1527 static void *voidptr_constructor(const void *v)
1532 return new void*(*(void **)v);
1536 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1540 if (!mo->superClass()) {
1541 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1542 propertyCache.insert(mo, rv);
1545 QQmlPropertyCache *super = cache(mo->superClass());
1546 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1547 propertyCache.insert(mo, rv);
1552 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1555 QList<QQmlType *> types;
1557 int maxMinorVersion = 0;
1559 const QMetaObject *metaObject = type->metaObject();
1561 while (metaObject) {
1562 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1563 type->majorVersion(), minorVersion);
1565 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1571 metaObject = metaObject->superClass();
1574 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1576 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1580 QQmlPropertyCache *raw = cache(type->metaObject());
1582 bool hasCopied = false;
1584 for (int ii = 0; ii < types.count(); ++ii) {
1585 QQmlType *currentType = types.at(ii);
1589 int rev = currentType->metaObjectRevision();
1590 int moIndex = types.count() - 1 - ii;
1592 if (raw->allowedRevisionCache[moIndex] != rev) {
1597 raw->allowedRevisionCache[moIndex] = rev;
1601 // Test revision compatibility - the basic rule is:
1602 // * Anything that is excluded, cannot overload something that is not excluded *
1604 // Signals override:
1605 // * other signals and methods of the same name.
1606 // * properties named on<Signal Name>
1607 // * automatic <property name>Changed notify signals
1609 // Methods override:
1610 // * other methods of the same name
1612 // Properties override:
1613 // * other elements of the same name
1615 bool overloadError = false;
1616 QString overloadName;
1619 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1620 !overloadError && iter != raw->stringCache.end();
1623 QQmlPropertyData *d = *iter;
1624 if (raw->isAllowedInRevision(d))
1625 continue; // Not excluded - no problems
1627 // check that a regular "name" overload isn't happening
1628 QQmlPropertyData *current = d;
1629 while (!overloadError && current) {
1630 current = d->overrideData(current);
1631 if (current && raw->isAllowedInRevision(current))
1632 overloadError = true;
1637 if (overloadError) {
1638 if (hasCopied) raw->release();
1640 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."));
1644 if (!hasCopied) raw->addref();
1645 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1647 if (minorVersion != maxMinorVersion) {
1649 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1655 QQmlMetaType::ModuleApiInstance *
1656 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1658 Locker locker(this);
1660 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1662 a = new QQmlMetaType::ModuleApiInstance;
1663 a->scriptCallback = module.script;
1664 a->qobjectCallback = module.qobject;
1665 moduleApiInstances.insert(module, a);
1671 bool QQmlEnginePrivate::isQObject(int t)
1673 Locker locker(this);
1674 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1677 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1679 Locker locker(this);
1680 int t = v.userType();
1681 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1683 return *(QObject **)(v.constData());
1685 return QQmlMetaType::toQObject(v, ok);
1689 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1691 Locker locker(this);
1692 if (m_compositeTypes.contains(t))
1693 return QQmlMetaType::Object;
1694 else if (m_qmlLists.contains(t))
1695 return QQmlMetaType::List;
1697 return QQmlMetaType::typeCategory(t);
1700 bool QQmlEnginePrivate::isList(int t) const
1702 Locker locker(this);
1703 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1706 int QQmlEnginePrivate::listType(int t) const
1708 Locker locker(this);
1709 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1710 if (iter != m_qmlLists.end())
1713 return QQmlMetaType::listType(t);
1716 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1718 Locker locker(this);
1719 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1720 if (iter != m_compositeTypes.end()) {
1721 return (*iter)->root;
1723 QQmlType *type = QQmlMetaType::qmlType(t);
1724 return type?type->baseMetaObject():0;
1728 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1730 Locker locker(this);
1731 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1732 if (iter != m_compositeTypes.end()) {
1733 return (*iter)->root;
1735 QQmlType *type = QQmlMetaType::qmlType(t);
1736 return type?type->metaObject():0;
1740 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1742 QByteArray name = data->root->className();
1744 QByteArray ptr = name + '*';
1745 QByteArray lst = "QQmlListProperty<" + name + '>';
1747 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1748 voidptr_constructor);
1749 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1750 voidptr_constructor);
1754 Locker locker(this);
1755 m_qmlLists.insert(lst_type, ptr_type);
1756 m_compositeTypes.insert(ptr_type, data);
1759 bool QQml_isFileCaseCorrect(const QString &fileName)
1761 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1762 QFileInfo info(fileName);
1763 const QString absolute = info.absoluteFilePath();
1765 #if defined(Q_OS_MAC)
1766 const QString canonical = info.canonicalFilePath();
1767 #elif defined(Q_OS_WIN)
1768 wchar_t buffer[1024];
1770 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1771 if (rv == 0 || rv >= 1024) return true;
1772 rv = ::GetLongPathName(buffer, buffer, 1024);
1773 if (rv == 0 || rv >= 1024) return true;
1775 const QString canonical = QString::fromWCharArray(buffer);
1778 const int absoluteLength = absolute.length();
1779 const int canonicalLength = canonical.length();
1781 const int length = qMin(absoluteLength, canonicalLength);
1782 for (int ii = 0; ii < length; ++ii) {
1783 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1784 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1786 if (a.toLower() != c.toLower())
1798 \fn QQmlEngine *qmlEngine(const QObject *object)
1801 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1802 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1806 \fn QQmlContext *qmlContext(const QObject *object)
1809 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1810 QQmlEngine::contextForObject(object).