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/qquickapplication_p.h>
69 #include <private/qv8debugservice_p.h>
70 #include <private/qdebugmessageservice_p.h>
71 #include "qqmlincubator.h"
72 #include <private/qv8profilerservice_p.h>
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
80 #include <QMetaObject>
81 #include <QtCore/qcoreapplication.h>
82 #include <QtCore/qdir.h>
83 #include <QtCore/qmutex.h>
84 #include <QtNetwork/qnetworkconfigmanager.h>
86 #include <private/qobject_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<QQuickApplication>("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class"));
178 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
182 QQmlImageProviderBase::~QQmlImageProviderBase()
188 \qmlclass Qt QQmlEnginePrivate
189 \ingroup qml-utility-elements
190 \brief The QML global Qt object provides useful enums and functions from Qt.
192 \keyword QmlGlobalQtObject
194 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
196 The \c Qt object is a global object with utility functions, properties and enums.
198 It is not instantiable; to use it, call the members of the global \c Qt object directly.
205 color: Qt.rgba(1, 0, 0, 1)
206 text: Qt.md5("hello, world")
213 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
214 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
218 The Qt object also contains helper functions for creating objects of specific
219 data types. This is primarily useful when setting the properties of an item
220 when the property has one of the following types:
223 \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()}
224 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
225 \li \c point - use \l{Qt::point()}{Qt.point()}
226 \li \c size - use \l{Qt::size()}{Qt.size()}
227 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
230 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
232 \section1 Date/Time Formatters
234 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
237 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
238 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
239 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
242 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
245 \section1 Dynamic Object Creation
246 The following functions on the global object allow you to dynamically create QML
247 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
251 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
252 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
258 \qmlproperty object Qt::application
261 The \c application object provides access to global application state
262 properties shared by many QML components.
268 \li \c application.active
270 This read-only property indicates whether the application is the top-most and focused
271 application, and the user is able to interact with the application. The property
272 is false when the application is in the background, the device keylock or screen
273 saver is active, the screen backlight is turned off, or the global system dialog
274 is being displayed on top of the application. It can be used for stopping and
275 pausing animations, timers and active processing of data in order to save device
276 battery power and free device memory and processor load when the application is not
280 \li \c application.layoutDirection
282 This read-only property can be used to query the default layout direction of the
283 application. On system start-up, the default layout direction depends on the
284 application's language. The property has a value of \c Qt.RightToLeft in locales
285 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
286 where the reading direction flows from left to right. You can bind to this
287 property to customize your application layouts to support both layout directions.
292 \li Qt.LeftToRight - Text and graphics elements should be positioned
294 \li Qt.RightToLeft - Text and graphics elements should be positioned
299 \li \c application.inputPanel
301 This read-only property allows access to application's QInputPanel object
302 and all its properties and slots. See the QInputPanel documentation for
303 further details. Deprecated in favor of Qt.InputMethod
306 The following example uses the \c application object to indicate
307 whether the application is currently active:
309 \snippet doc/src/snippets/qml/application.qml document
311 \qmlproperty object Qt::inputMethod
314 The \c inputMethod object allows access to application's QInputMethod object
315 and all its properties and slots. See the QInputMethod documentation for
321 \qmlmethod object Qt::include(string url, jsobject callback)
323 Includes another JavaScript file. This method can only be used from within JavaScript files,
324 and not regular QML files.
326 This imports all functions from \a url into the current script's namespace.
328 Qt.include() returns an object that describes the status of the operation. The object has
329 a single property, \c {status}, that is set to one of the following values:
332 \header \li Symbol \li Value \li Description
333 \row \li result.OK \li 0 \li The include completed successfully.
334 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
335 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
336 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
337 An additional \c exception property will be set in this case.
340 The \c status property will be updated as the operation progresses.
342 If provided, \a callback is invoked when the operation completes. The callback is passed
343 the same object as is returned from the Qt.include() call.
345 // Qt.include() is implemented in qv8include.cpp
348 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
349 : propertyCapture(0), rootContext(0), isDebugging(false),
350 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
351 cleanup(0), erroredBindings(0), inProgressCreations(0),
352 workerScriptEngine(0), activeVME(0),
353 networkAccessManager(0), networkAccessManagerFactory(0),
354 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
355 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
359 QQmlEnginePrivate::~QQmlEnginePrivate()
361 if (inProgressCreations)
362 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
365 QQmlCleanup *c = cleanup;
367 if (cleanup) cleanup->prev = &cleanup;
373 doDeleteInEngineThread();
375 if (incubationController) incubationController->d = 0;
376 incubationController = 0;
381 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
383 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
385 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
387 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
388 delete (*iter)->qobjectApi;
393 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
395 QObjectPrivate *p = QObjectPrivate::get(o);
396 if (p->declarativeData) {
397 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
398 if (d->ownContext && d->context) {
399 d->context->destroy();
405 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
407 static_cast<QQmlData *>(d)->destroyed(o);
410 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
412 static_cast<QQmlData *>(d)->parentChanged(o, p);
415 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
417 static_cast<QQmlData *>(d)->objectNameChanged(o);
420 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
422 QQmlData *ddata = QQmlData::get(object, false);
423 if (!ddata) return; // Probably being deleted
425 QQmlNotifierEndpoint *ep = ddata->notify(index);
426 if (ep) QQmlNotifier::emitNotify(ep);
429 void QQmlEnginePrivate::init()
433 static bool firstTime = true;
435 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
440 qRegisterMetaType<QVariant>("QVariant");
441 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
442 qRegisterMetaType<QJSValue>("QJSValue");
443 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
444 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
445 qRegisterMetaType<QList<int> >("QList<int>");
446 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
450 v8engine()->setEngine(q);
452 rootContext = new QQmlContext(q,true);
454 if (QCoreApplication::instance()->thread() == q->thread() &&
455 QQmlEngineDebugService::isDebuggingEnabled()) {
457 QQmlEngineDebugService::instance()->addEngine(q);
458 QV8DebugService::initialize(v8engine());
459 QV8ProfilerService::initialize();
460 QQmlProfilerService::initialize();
461 QDebugMessageService::instance();
464 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
465 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
466 QDir::separator() + QLatin1String("QML") +
467 QDir::separator() + QLatin1String("OfflineStorage");
470 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
473 if (!workerScriptEngine)
474 workerScriptEngine = new QQuickWorkerScriptEngine(q);
475 return workerScriptEngine;
481 \brief The QQmlEngine class provides an environment for instantiating QML components.
484 Each QML component is instantiated in a QQmlContext.
485 QQmlContext's are essential for passing data to QML
486 components. In QML, contexts are arranged hierarchically and this
487 hierarchy is managed by the QQmlEngine.
489 Prior to creating any QML components, an application must have
490 created a QQmlEngine to gain access to a QML context. The
491 following example shows how to create a simple Text item.
495 QQmlComponent component(&engine);
496 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
497 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
499 //add item to view, etc
503 In this case, the Text item will be created in the engine's
504 \l {QQmlEngine::rootContext()}{root context}.
506 \sa QQmlComponent QQmlContext
510 Create a new QQmlEngine with the given \a parent.
512 QQmlEngine::QQmlEngine(QObject *parent)
513 : QJSEngine(*new QQmlEnginePrivate(this), parent)
520 Destroys the QQmlEngine.
522 Any QQmlContext's created on this engine will be
523 invalidated, but not destroyed (unless they are parented to the
526 QQmlEngine::~QQmlEngine()
529 if (d->isDebugging) {
530 QQmlEngineDebugService::instance()->remEngine(this);
533 // if we are the parent of any of the qobject module api instances,
534 // we need to remove them from our internal list, in order to prevent
535 // a segfault in engine private dtor.
536 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
537 QObject *currQObjectApi = 0;
538 QQmlMetaType::ModuleApiInstance *currInstance = 0;
539 foreach (const QQmlMetaType::ModuleApi &key, keys) {
540 currInstance = d->moduleApiInstances.value(key);
541 currQObjectApi = currInstance->qobjectApi;
542 if (this->children().contains(currQObjectApi)) {
543 delete currQObjectApi;
545 d->moduleApiInstances.remove(key);
549 // ensure we clean up QObjects with JS ownership
552 if (d->incubationController)
553 d->incubationController->d = 0;
556 /*! \fn void QQmlEngine::quit()
557 This signal is emitted when the QML loaded by the engine would like to quit.
560 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
561 This signal is emitted when \a warnings messages are generated by QML.
565 Clears the engine's internal component cache.
567 Normally the QQmlEngine caches components loaded from qml
568 files. This method clears this cache and forces the component to be
571 void QQmlEngine::clearComponentCache()
574 d->typeLoader.clearCache();
578 Returns the engine's root context.
580 The root context is automatically created by the QQmlEngine.
581 Data that should be available to all QML component instances
582 instantiated by the engine should be put in the root context.
584 Additional data that should only be available to a subset of
585 component instances should be added to sub-contexts parented to the
588 QQmlContext *QQmlEngine::rootContext() const
590 Q_D(const QQmlEngine);
591 return d->rootContext;
595 Sets the \a factory to use for creating QNetworkAccessManager(s).
597 QNetworkAccessManager is used for all network access by QML. By
598 implementing a factory it is possible to create custom
599 QNetworkAccessManager with specialized caching, proxy and cookie
602 The factory must be set before executing the engine.
604 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
607 QMutexLocker locker(&d->mutex);
608 d->networkAccessManagerFactory = factory;
612 Returns the current QQmlNetworkAccessManagerFactory.
614 \sa setNetworkAccessManagerFactory()
616 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
618 Q_D(const QQmlEngine);
619 return d->networkAccessManagerFactory;
622 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
625 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
627 void *args[] = { 0 };
628 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
632 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
634 QMutexLocker locker(&mutex);
635 QNetworkAccessManager *nam;
636 if (networkAccessManagerFactory) {
637 nam = networkAccessManagerFactory->create(parent);
639 nam = new QNetworkAccessManager(parent);
645 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
647 Q_Q(const QQmlEngine);
648 if (!networkAccessManager)
649 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
650 return networkAccessManager;
654 Returns a common QNetworkAccessManager which can be used by any QML
655 element instantiated by this engine.
657 If a QQmlNetworkAccessManagerFactory has been set and a
658 QNetworkAccessManager has not yet been created, the
659 QQmlNetworkAccessManagerFactory will be used to create the
660 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
661 will have no proxy or cache set.
663 \sa setNetworkAccessManagerFactory()
665 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
667 Q_D(const QQmlEngine);
668 return d->getNetworkAccessManager();
673 Sets the \a provider to use for images requested via the \e
674 image: url scheme, with host \a providerId. The QQmlEngine
675 takes ownership of \a provider.
677 Image providers enable support for pixmap and threaded image
678 requests. See the QQuickImageProvider documentation for details on
679 implementing and using image providers.
681 All required image providers should be added to the engine before any
682 QML sources files are loaded.
684 \sa removeImageProvider(), QQuickImageProvider
686 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
689 QMutexLocker locker(&d->mutex);
690 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
694 Returns the image provider set for \a providerId.
696 Returns the provider if it was found; otherwise returns 0.
698 \sa QQuickImageProvider
700 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
702 Q_D(const QQmlEngine);
703 QMutexLocker locker(&d->mutex);
704 return d->imageProviders.value(providerId).data();
708 Removes the image provider for \a providerId.
710 \sa addImageProvider(), QQuickImageProvider
712 void QQmlEngine::removeImageProvider(const QString &providerId)
715 QMutexLocker locker(&d->mutex);
716 d->imageProviders.take(providerId);
720 Return the base URL for this engine. The base URL is only used to
721 resolve components when a relative URL is passed to the
722 QQmlComponent constructor.
724 If a base URL has not been explicitly set, this method returns the
725 application's current working directory.
729 QUrl QQmlEngine::baseUrl() const
731 Q_D(const QQmlEngine);
732 if (d->baseUrl.isEmpty()) {
733 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
740 Set the base URL for this engine to \a url.
744 void QQmlEngine::setBaseUrl(const QUrl &url)
751 Returns true if warning messages will be output to stderr in addition
752 to being emitted by the warnings() signal, otherwise false.
754 The default value is true.
756 bool QQmlEngine::outputWarningsToStandardError() const
758 Q_D(const QQmlEngine);
759 return d->outputWarningsToStdErr;
763 Set whether warning messages will be output to stderr to \a enabled.
765 If \a enabled is true, any warning messages generated by QML will be
766 output to stderr and emitted by the warnings() signal. If \a enabled
767 is false, on the warnings() signal will be emitted. This allows
768 applications to handle warning output themselves.
770 The default value is true.
772 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
775 d->outputWarningsToStdErr = enabled;
779 Attempt to free unused memory.
781 void QQmlEngine::collectGarbage()
787 Returns the QQmlContext for the \a object, or 0 if no
788 context has been set.
790 When the QQmlEngine instantiates a QObject, the context is
793 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
798 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
801 static_cast<QQmlData *>(priv->declarativeData);
805 else if (data->outerContext)
806 return data->outerContext->asQQmlContext();
812 Sets the QQmlContext for the \a object to \a context.
813 If the \a object already has a context, a warning is
814 output, but the context is not changed.
816 When the QQmlEngine instantiates a QObject, the context is
819 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
821 if (!object || !context)
824 QQmlData *data = QQmlData::get(object, true);
826 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
830 QQmlContextData *contextData = QQmlContextData::get(context);
831 contextData->addObject(object);
835 \enum QQmlEngine::ObjectOwnership
837 Ownership controls whether or not QML automatically destroys the
838 QObject when the object is garbage collected by the JavaScript
839 engine. The two ownership options are:
841 \value CppOwnership The object is owned by C++ code, and will
842 never be deleted by QML. The JavaScript destroy() method cannot be
843 used on objects with CppOwnership. This option is similar to
844 QScriptEngine::QtOwnership.
846 \value JavaScriptOwnership The object is owned by JavaScript.
847 When the object is returned to QML as the return value of a method
848 call or property access, QML will delete the object if there are no
849 remaining JavaScript references to it and it has no
850 QObject::parent(). This option is similar to
851 QScriptEngine::ScriptOwnership.
853 Generally an application doesn't need to set an object's ownership
854 explicitly. QML uses a heuristic to set the default object
855 ownership. By default, an object that is created by QML has
856 JavaScriptOwnership. The exception to this are the root objects
857 created by calling QQmlComponent::create() or
858 QQmlComponent::beginCreate() which have CppOwnership by
859 default. The ownership of these root-level objects is considered to
860 have been transferred to the C++ caller.
862 Objects not-created by QML have CppOwnership by default. The
863 exception to this is objects returned from a C++ method call. The
864 ownership of these objects is passed to JavaScript.
866 Calling setObjectOwnership() overrides the default ownership
867 heuristic used by QML.
871 Sets the \a ownership of \a object.
873 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
878 QQmlData *ddata = QQmlData::get(object, true);
882 ddata->indestructible = (ownership == CppOwnership)?true:false;
883 ddata->explicitIndestructibleSet = true;
887 Returns the ownership of \a object.
889 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
894 QQmlData *ddata = QQmlData::get(object, false);
898 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
901 bool QQmlEngine::event(QEvent *e)
904 if (e->type() == QEvent::User)
905 d->doDeleteInEngineThread();
907 return QJSEngine::event(e);
910 void QQmlEnginePrivate::doDeleteInEngineThread()
912 QFieldList<Deletable, &Deletable::next> list;
914 list.copyAndClear(toDeleteInEngineThread);
917 while (Deletable *d = list.takeFirst())
921 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
923 QQmlData *data = QQmlData::get(object);
925 if (data && data->deferredComponent) {
926 QQmlObjectCreatingProfiler prof;
928 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
929 prof.setTypeName(type ? type->qmlTypeName()
930 : QString::fromUtf8(object->metaObject()->className()));
931 if (data->outerContext)
932 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
934 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
936 QQmlComponentPrivate::ConstructionState state;
937 QQmlComponentPrivate::beginDeferred(ep, object, &state);
939 data->deferredComponent->release();
940 data->deferredComponent = 0;
942 QQmlComponentPrivate::complete(ep, &state);
946 QQmlContext *qmlContext(const QObject *obj)
948 return QQmlEngine::contextForObject(obj);
951 QQmlEngine *qmlEngine(const QObject *obj)
953 QQmlData *data = QQmlData::get(obj, false);
954 if (!data || !data->context)
956 return data->context->engine;
959 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
961 QQmlData *data = QQmlData::get(object);
963 return 0; // Attached properties are only on objects created by QML
965 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
969 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
973 rv = pf(const_cast<QObject *>(object));
976 data->attachedProperties()->insert(id, rv);
981 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
982 const QMetaObject *attachedMetaObject, bool create)
985 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
987 if (*idCache == -1 || !object)
990 return qmlAttachedPropertiesObjectById(*idCache, object, create);
993 QQmlDebuggingEnabler::QQmlDebuggingEnabler()
995 #ifndef QQML_NO_DEBUG_PROTOCOL
996 if (!QQmlEnginePrivate::qml_debugging_enabled) {
997 qDebug("QML debugging is enabled. Only use this in a safe environment.");
999 QQmlEnginePrivate::qml_debugging_enabled = true;
1004 class QQmlDataExtended {
1007 ~QQmlDataExtended();
1009 QHash<int, QObject *> attachedProperties;
1010 QQmlNotifier objectNameNotifier;
1013 QQmlDataExtended::QQmlDataExtended()
1017 QQmlDataExtended::~QQmlDataExtended()
1021 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1024 layout(endpoint->next);
1026 int index = endpoint->sourceSignal;
1027 index = qMin(index, 0xFFFF - 1);
1029 endpoint->next = notifies[index];
1030 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1031 endpoint->prev = ¬ifies[index];
1032 notifies[index] = endpoint;
1035 void QQmlData::NotifyList::layout()
1037 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1040 QQmlNotifierEndpoint **old = notifies;
1041 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1042 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1043 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1044 sizeof(QQmlNotifierEndpoint*);
1045 memset(notifies + notifiesSize, 0, memsetSize);
1047 if (notifies != old) {
1048 for (int ii = 0; ii < notifiesSize; ++ii)
1050 notifies[ii]->prev = ¬ifies[ii];
1053 notifiesSize = maximumTodoIndex + 1;
1058 maximumTodoIndex = 0;
1062 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1065 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1066 notifyList->connectionMask = 0;
1067 notifyList->maximumTodoIndex = 0;
1068 notifyList->notifiesSize = 0;
1069 notifyList->todo = 0;
1070 notifyList->notifies = 0;
1073 Q_ASSERT(!endpoint->isConnected());
1075 index = qMin(index, 0xFFFF - 1);
1076 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1078 if (index < notifyList->notifiesSize) {
1080 endpoint->next = notifyList->notifies[index];
1081 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1082 endpoint->prev = ¬ifyList->notifies[index];
1083 notifyList->notifies[index] = endpoint;
1086 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1088 endpoint->next = notifyList->todo;
1089 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1090 endpoint->prev = ¬ifyList->todo;
1091 notifyList->todo = endpoint;
1095 QQmlNotifier *QQmlData::objectNameNotifier() const
1097 if (!extendedData) extendedData = new QQmlDataExtended;
1098 return &extendedData->objectNameNotifier;
1101 QHash<int, QObject *> *QQmlData::attachedProperties() const
1103 if (!extendedData) extendedData = new QQmlDataExtended;
1104 return &extendedData->attachedProperties;
1107 void QQmlData::destroyed(QObject *object)
1109 if (deferredComponent)
1110 deferredComponent->release();
1112 if (nextContextObject)
1113 nextContextObject->prevContextObject = prevContextObject;
1114 if (prevContextObject)
1115 *prevContextObject = nextContextObject;
1117 QQmlAbstractBinding *binding = bindings;
1119 QQmlAbstractBinding *next = binding->m_nextBinding;
1120 binding->m_prevBinding = 0;
1121 binding->m_nextBinding = 0;
1130 propertyCache->release();
1132 if (ownContext && context)
1136 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1137 *guard = (QObject *)0;
1138 guard->objectDestroyed(object);
1142 while (notifyList->todo)
1143 notifyList->todo->disconnect();
1144 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1145 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1148 free(notifyList->notifies);
1153 delete extendedData;
1155 v8object.Clear(); // The WeakReference handler will clean the actual handle
1161 void QQmlData::parentChanged(QObject *object, QObject *parent)
1167 void QQmlData::objectNameChanged(QObject *)
1169 if (extendedData) objectNameNotifier()->notify();
1172 bool QQmlData::hasBindingBit(int bit) const
1174 if (bindingBitsSize > bit)
1175 return bindingBits[bit / 32] & (1 << (bit % 32));
1180 void QQmlData::clearBindingBit(int bit)
1182 if (bindingBitsSize > bit)
1183 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1186 void QQmlData::setBindingBit(QObject *obj, int bit)
1188 if (bindingBitsSize <= bit) {
1189 int props = obj->metaObject()->propertyCount();
1190 Q_ASSERT(bit < props);
1192 int arraySize = (props + 31) / 32;
1193 int oldArraySize = bindingBitsSize / 32;
1195 bindingBits = (quint32 *)realloc(bindingBits,
1196 arraySize * sizeof(quint32));
1198 memset(bindingBits + oldArraySize,
1200 sizeof(quint32) * (arraySize - oldArraySize));
1202 bindingBitsSize = arraySize * 32;
1205 bindingBits[bit / 32] |= (1 << (bit % 32));
1208 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1210 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1211 if (url.authority().isEmpty())
1212 return QLatin1Char(':') + url.path();
1215 return url.toLocalFile();
1219 static QString toLocalFile(const QString &url)
1221 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1224 QString file = url.mid(7);
1226 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1228 // magic for drives on windows
1229 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1235 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1237 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1238 if (url.length() > 4)
1239 return QLatin1Char(':') + url.mid(4);
1243 return toLocalFile(url);
1246 void QQmlEnginePrivate::sendQuit()
1250 if (q->receivers(SIGNAL(quit())) == 0) {
1251 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1255 static void dumpwarning(const QQmlError &error)
1257 qWarning().nospace() << qPrintable(error.toString());
1260 static void dumpwarning(const QList<QQmlError> &errors)
1262 for (int ii = 0; ii < errors.count(); ++ii)
1263 dumpwarning(errors.at(ii));
1266 void QQmlEnginePrivate::warning(const QQmlError &error)
1269 q->warnings(QList<QQmlError>() << error);
1270 if (outputWarningsToStdErr)
1274 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1277 q->warnings(errors);
1278 if (outputWarningsToStdErr)
1279 dumpwarning(errors);
1282 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1285 QQmlEnginePrivate::get(engine)->warning(error);
1290 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1293 QQmlEnginePrivate::get(engine)->warning(error);
1298 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1301 engine->warning(error);
1306 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1309 engine->warning(error);
1315 This function should be called prior to evaluation of any js expression,
1316 so that scarce resources are not freed prematurely (eg, if there is a
1317 nested javascript expression).
1319 void QQmlEnginePrivate::referenceScarceResources()
1321 scarceResourcesRefCount += 1;
1325 This function should be called after evaluation of the js expression is
1326 complete, and so the scarce resources may be freed safely.
1328 void QQmlEnginePrivate::dereferenceScarceResources()
1330 Q_ASSERT(scarceResourcesRefCount > 0);
1331 scarceResourcesRefCount -= 1;
1333 // if the refcount is zero, then evaluation of the "top level"
1334 // expression must have completed. We can safely release the
1335 // scarce resources.
1336 if (scarceResourcesRefCount == 0) {
1337 // iterate through the list and release them all.
1338 // note that the actual SRD is owned by the JS engine,
1339 // so we cannot delete the SRD; but we can free the
1340 // memory used by the variant in the SRD.
1341 while (ScarceResourceData *sr = scarceResources.first()) {
1342 sr->data = QVariant();
1343 scarceResources.remove(sr);
1349 Adds \a path as a directory where the engine searches for
1350 installed modules in a URL-based directory structure.
1351 The \a path may be a local filesystem directory or a URL.
1353 The newly added \a path will be first in the importPathList().
1355 \sa setImportPathList(), {QML Modules}
1357 void QQmlEngine::addImportPath(const QString& path)
1360 d->importDatabase.addImportPath(path);
1364 Returns the list of directories where the engine searches for
1365 installed modules in a URL-based directory structure.
1367 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1368 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1369 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1370 provided by that module. A \c qmldir file is required for defining the
1371 type version mapping and possibly QML extensions plugins.
1373 By default, the list contains the directory of the application executable,
1374 paths specified in the \c QML_IMPORT_PATH environment variable,
1375 and the builtin \c ImportsPath from QLibraryInfo.
1377 \sa addImportPath() setImportPathList()
1379 QStringList QQmlEngine::importPathList() const
1381 Q_D(const QQmlEngine);
1382 return d->importDatabase.importPathList();
1386 Sets \a paths as the list of directories where the engine searches for
1387 installed modules in a URL-based directory structure.
1389 By default, the list contains the directory of the application executable,
1390 paths specified in the \c QML_IMPORT_PATH environment variable,
1391 and the builtin \c ImportsPath from QLibraryInfo.
1393 \sa importPathList() addImportPath()
1395 void QQmlEngine::setImportPathList(const QStringList &paths)
1398 d->importDatabase.setImportPathList(paths);
1403 Adds \a path as a directory where the engine searches for
1404 native plugins for imported modules (referenced in the \c qmldir file).
1406 By default, the list contains only \c ., i.e. the engine searches
1407 in the directory of the \c qmldir file itself.
1409 The newly added \a path will be first in the pluginPathList().
1411 \sa setPluginPathList()
1413 void QQmlEngine::addPluginPath(const QString& path)
1416 d->importDatabase.addPluginPath(path);
1421 Returns the list of directories where the engine searches for
1422 native plugins for imported modules (referenced in the \c qmldir file).
1424 By default, the list contains only \c ., i.e. the engine searches
1425 in the directory of the \c qmldir file itself.
1427 \sa addPluginPath() setPluginPathList()
1429 QStringList QQmlEngine::pluginPathList() const
1431 Q_D(const QQmlEngine);
1432 return d->importDatabase.pluginPathList();
1436 Sets the list of directories where the engine searches for
1437 native plugins for imported modules (referenced in the \c qmldir file)
1440 By default, the list contains only \c ., i.e. the engine searches
1441 in the directory of the \c qmldir file itself.
1443 \sa pluginPathList() addPluginPath()
1445 void QQmlEngine::setPluginPathList(const QStringList &paths)
1448 d->importDatabase.setPluginPathList(paths);
1452 Imports the plugin named \a filePath with the \a uri provided.
1453 Returns true if the plugin was successfully imported; otherwise returns false.
1455 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1457 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1459 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1462 return d->importDatabase.importPlugin(filePath, uri, errors);
1466 Imports the plugin named \a filePath with the \a uri provided.
1467 Returns true if the plugin was successfully imported; otherwise returns false.
1469 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1471 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1473 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1476 QList<QQmlError> errors;
1477 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1478 if (!errors.isEmpty()) {
1480 for (int i = 0; i < errors.size(); ++i) {
1481 builtError = QString(QLatin1String("%1\n %2"))
1483 .arg(errors.at(i).toString());
1485 *errorString = builtError;
1491 \property QQmlEngine::offlineStoragePath
1492 \brief the directory for storing offline user data
1494 Returns the directory where SQL and other offline
1497 QQuickWebView and the SQL databases created with openDatabase()
1500 The default is QML/OfflineStorage in the platform-standard
1501 user application data directory.
1503 Note that the path may not currently exist on the filesystem, so
1504 callers wanting to \e create new files at this location should create
1505 it first - see QDir::mkpath().
1507 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1510 d->offlineStoragePath = dir;
1513 QString QQmlEngine::offlineStoragePath() const
1515 Q_D(const QQmlEngine);
1516 return d->offlineStoragePath;
1519 static void voidptr_destructor(void *v)
1521 void **ptr = (void **)v;
1525 static void *voidptr_constructor(const void *v)
1530 return new void*(*(void **)v);
1534 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1538 if (!mo->superClass()) {
1539 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1540 propertyCache.insert(mo, rv);
1543 QQmlPropertyCache *super = cache(mo->superClass());
1544 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1545 propertyCache.insert(mo, rv);
1550 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1553 QList<QQmlType *> types;
1555 int maxMinorVersion = 0;
1557 const QMetaObject *metaObject = type->metaObject();
1559 while (metaObject) {
1560 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1561 type->majorVersion(), minorVersion);
1563 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1569 metaObject = metaObject->superClass();
1572 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1574 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1578 QQmlPropertyCache *raw = cache(type->metaObject());
1580 bool hasCopied = false;
1582 for (int ii = 0; ii < types.count(); ++ii) {
1583 QQmlType *currentType = types.at(ii);
1587 int rev = currentType->metaObjectRevision();
1588 int moIndex = types.count() - 1 - ii;
1590 if (raw->allowedRevisionCache[moIndex] != rev) {
1595 raw->allowedRevisionCache[moIndex] = rev;
1599 // Test revision compatibility - the basic rule is:
1600 // * Anything that is excluded, cannot overload something that is not excluded *
1602 // Signals override:
1603 // * other signals and methods of the same name.
1604 // * properties named on<Signal Name>
1605 // * automatic <property name>Changed notify signals
1607 // Methods override:
1608 // * other methods of the same name
1610 // Properties override:
1611 // * other elements of the same name
1613 bool overloadError = false;
1614 QString overloadName;
1617 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1618 !overloadError && iter != raw->stringCache.end();
1621 QQmlPropertyData *d = *iter;
1622 if (raw->isAllowedInRevision(d))
1623 continue; // Not excluded - no problems
1625 // check that a regular "name" overload isn't happening
1626 QQmlPropertyData *current = d;
1627 while (!overloadError && current) {
1628 current = d->overrideData(current);
1629 if (current && raw->isAllowedInRevision(current))
1630 overloadError = true;
1635 if (overloadError) {
1636 if (hasCopied) raw->release();
1638 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."));
1642 if (!hasCopied) raw->addref();
1643 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1645 if (minorVersion != maxMinorVersion) {
1647 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1653 QQmlMetaType::ModuleApiInstance *
1654 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1656 Locker locker(this);
1658 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1660 a = new QQmlMetaType::ModuleApiInstance;
1661 a->scriptCallback = module.script;
1662 a->qobjectCallback = module.qobject;
1663 moduleApiInstances.insert(module, a);
1669 bool QQmlEnginePrivate::isQObject(int t)
1671 Locker locker(this);
1672 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1675 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1677 Locker locker(this);
1678 int t = v.userType();
1679 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1681 return *(QObject **)(v.constData());
1683 return QQmlMetaType::toQObject(v, ok);
1687 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1689 Locker locker(this);
1690 if (m_compositeTypes.contains(t))
1691 return QQmlMetaType::Object;
1692 else if (m_qmlLists.contains(t))
1693 return QQmlMetaType::List;
1695 return QQmlMetaType::typeCategory(t);
1698 bool QQmlEnginePrivate::isList(int t) const
1700 Locker locker(this);
1701 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1704 int QQmlEnginePrivate::listType(int t) const
1706 Locker locker(this);
1707 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1708 if (iter != m_qmlLists.end())
1711 return QQmlMetaType::listType(t);
1714 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1716 Locker locker(this);
1717 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1718 if (iter != m_compositeTypes.end()) {
1719 return (*iter)->root;
1721 QQmlType *type = QQmlMetaType::qmlType(t);
1722 return type?type->baseMetaObject():0;
1726 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1728 Locker locker(this);
1729 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1730 if (iter != m_compositeTypes.end()) {
1731 return (*iter)->root;
1733 QQmlType *type = QQmlMetaType::qmlType(t);
1734 return type?type->metaObject():0;
1738 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1740 QByteArray name = data->root->className();
1742 QByteArray ptr = name + '*';
1743 QByteArray lst = "QQmlListProperty<" + name + '>';
1745 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1746 voidptr_constructor);
1747 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1748 voidptr_constructor);
1752 Locker locker(this);
1753 m_qmlLists.insert(lst_type, ptr_type);
1754 m_compositeTypes.insert(ptr_type, data);
1757 bool QQml_isFileCaseCorrect(const QString &fileName)
1759 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1760 QFileInfo info(fileName);
1761 const QString absolute = info.absoluteFilePath();
1763 #if defined(Q_OS_MAC)
1764 const QString canonical = info.canonicalFilePath();
1765 #elif defined(Q_OS_WIN)
1766 wchar_t buffer[1024];
1768 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1769 if (rv == 0 || rv >= 1024) return true;
1770 rv = ::GetLongPathName(buffer, buffer, 1024);
1771 if (rv == 0 || rv >= 1024) return true;
1773 const QString canonical = QString::fromWCharArray(buffer);
1776 const int absoluteLength = absolute.length();
1777 const int canonicalLength = canonical.length();
1779 const int length = qMin(absoluteLength, canonicalLength);
1780 for (int ii = 0; ii < length; ++ii) {
1781 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1782 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1784 if (a.toLower() != c.toLower())
1796 \fn QQmlEngine *qmlEngine(const QObject *object)
1799 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1800 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1804 \fn QQmlContext *qmlContext(const QObject *object)
1807 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1808 QQmlEngine::contextForObject(object).