1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
73 #include <QtCore/qstandardpaths.h>
74 #include <QtCore/qsettings.h>
76 #include <QtCore/qmetaobject.h>
77 #include <QNetworkAccessManager>
79 #include <QMetaObject>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtNetwork/qnetworkconfigmanager.h>
85 #include <private/qobject_p.h>
87 #include <private/qqmllocale_p.h>
89 #ifdef Q_OS_WIN // for %APPDATA%
90 #include <qt_windows.h>
94 #define CSIDL_APPDATA 0x001a // <username>\Application Data
97 Q_DECLARE_METATYPE(QQmlProperty)
101 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
103 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
104 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
108 \qmlclass QtObject QObject
109 \ingroup qml-utility-elements
111 \brief The QtObject element is the most basic element in QML.
113 The QtObject element is a non-visual element which contains only the
116 It can be useful to create a QtObject if you need an extremely
117 lightweight element to enclose a set of custom properties:
119 \snippet doc/src/snippets/qml/qtobject.qml 0
121 It can also be useful for C++ integration, as it is just a plain
122 QObject. See the QObject documentation for further details.
125 \qmlproperty string QtObject::objectName
126 This property holds the QObject::objectName for this specific object instance.
128 This allows a C++ application to locate an item within a QML component
129 using the QObject::findChild() method. For example, the following C++
130 application locates the child \l Rectangle item and dynamically changes its
139 width: 200; height: 200
153 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
156 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
158 item->setProperty("color", QColor(Qt::yellow));
162 bool QQmlEnginePrivate::qml_debugging_enabled = false;
164 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
166 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
167 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
168 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
169 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
170 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
173 void QQmlEnginePrivate::defineModule()
175 registerBaseTypes("QtQuick", 2, 0);
176 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
180 QQmlImageProviderBase::~QQmlImageProviderBase()
186 \qmlclass Qt QQmlEnginePrivate
187 \ingroup qml-utility-elements
188 \brief The QML global Qt object provides useful enums and functions from Qt.
190 \keyword QmlGlobalQtObject
192 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
194 The \c Qt object is a global object with utility functions, properties and enums.
196 It is not instantiable; to use it, call the members of the global \c Qt object directly.
203 color: Qt.rgba(1, 0, 0, 1)
204 text: Qt.md5("hello, world")
211 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
212 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
216 The Qt object also contains helper functions for creating objects of specific
217 data types. This is primarily useful when setting the properties of an item
218 when the property has one of the following types:
221 \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()}
222 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
223 \li \c point - use \l{Qt::point()}{Qt.point()}
224 \li \c size - use \l{Qt::size()}{Qt.size()}
225 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
228 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
230 \section1 Date/Time Formatters
232 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
235 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
236 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
237 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
240 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
243 \section1 Dynamic Object Creation
244 The following functions on the global object allow you to dynamically create QML
245 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
249 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
250 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
256 \qmlproperty object Qt::application
259 The \c application object provides access to global application state
260 properties shared by many QML components.
266 \li \c application.active
268 This read-only property indicates whether the application is the top-most and focused
269 application, and the user is able to interact with the application. The property
270 is false when the application is in the background, the device keylock or screen
271 saver is active, the screen backlight is turned off, or the global system dialog
272 is being displayed on top of the application. It can be used for stopping and
273 pausing animations, timers and active processing of data in order to save device
274 battery power and free device memory and processor load when the application is not
278 \li \c application.layoutDirection
280 This read-only property can be used to query the default layout direction of the
281 application. On system start-up, the default layout direction depends on the
282 application's language. The property has a value of \c Qt.RightToLeft in locales
283 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
284 where the reading direction flows from left to right. You can bind to this
285 property to customize your application layouts to support both layout directions.
290 \li Qt.LeftToRight - Text and graphics elements should be positioned
292 \li Qt.RightToLeft - Text and graphics elements should be positioned
297 \li \c application.inputPanel
299 This read-only property allows access to application's QInputPanel object
300 and all its properties and slots. See the QInputPanel documentation for
301 further details. Deprecated in favor of Qt.InputMethod
304 The following example uses the \c application object to indicate
305 whether the application is currently active:
307 \snippet doc/src/snippets/qml/application.qml document
309 \qmlproperty object Qt::inputMethod
312 The \c inputMethod object allows access to application's QInputMethod object
313 and all its properties and slots. See the QInputMethod documentation for
319 \qmlmethod object Qt::include(string url, jsobject callback)
321 Includes another JavaScript file. This method can only be used from within JavaScript files,
322 and not regular QML files.
324 This imports all functions from \a url into the current script's namespace.
326 Qt.include() returns an object that describes the status of the operation. The object has
327 a single property, \c {status}, that is set to one of the following values:
330 \header \li Symbol \li Value \li Description
331 \row \li result.OK \li 0 \li The include completed successfully.
332 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
333 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
334 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
335 An additional \c exception property will be set in this case.
338 The \c status property will be updated as the operation progresses.
340 If provided, \a callback is invoked when the operation completes. The callback is passed
341 the same object as is returned from the Qt.include() call.
343 // Qt.include() is implemented in qv8include.cpp
346 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
347 : propertyCapture(0), rootContext(0), isDebugging(false),
348 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
349 cleanup(0), erroredBindings(0), inProgressCreations(0),
350 workerScriptEngine(0), activeVME(0),
351 networkAccessManager(0), networkAccessManagerFactory(0),
352 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
353 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
357 QQmlEnginePrivate::~QQmlEnginePrivate()
359 if (inProgressCreations)
360 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
363 QQmlCleanup *c = cleanup;
365 if (cleanup) cleanup->prev = &cleanup;
371 doDeleteInEngineThread();
373 if (incubationController) incubationController->d = 0;
374 incubationController = 0;
379 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
381 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
383 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
385 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
386 delete (*iter)->qobjectApi;
391 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
393 QObjectPrivate *p = QObjectPrivate::get(o);
394 if (p->declarativeData) {
395 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
396 if (d->ownContext && d->context) {
397 d->context->destroy();
403 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
405 static_cast<QQmlData *>(d)->destroyed(o);
408 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
410 static_cast<QQmlData *>(d)->parentChanged(o, p);
413 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
415 static_cast<QQmlData *>(d)->objectNameChanged(o);
418 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
420 QQmlData *ddata = QQmlData::get(object, false);
421 if (!ddata) return; // Probably being deleted
423 QQmlNotifierEndpoint *ep = ddata->notify(index);
424 if (ep) QQmlNotifier::emitNotify(ep);
427 void QQmlEnginePrivate::init()
431 static bool firstTime = true;
433 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
438 qRegisterMetaType<QVariant>("QVariant");
439 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
440 qRegisterMetaType<QJSValue>("QJSValue");
441 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
442 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
443 qRegisterMetaType<QList<int> >("QList<int>");
444 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
448 v8engine()->setEngine(q);
450 rootContext = new QQmlContext(q,true);
452 if (QCoreApplication::instance()->thread() == q->thread() &&
453 QQmlEngineDebugService::isDebuggingEnabled()) {
455 QQmlEngineDebugService::instance()->addEngine(q);
456 QV8DebugService::initialize(v8engine());
457 QV8ProfilerService::initialize();
458 QQmlProfilerService::initialize();
459 QDebugMessageService::instance();
462 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
463 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
464 QDir::separator() + QLatin1String("QML") +
465 QDir::separator() + QLatin1String("OfflineStorage");
468 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
471 if (!workerScriptEngine)
472 workerScriptEngine = new QQuickWorkerScriptEngine(q);
473 return workerScriptEngine;
479 \brief The QQmlEngine class provides an environment for instantiating QML components.
482 Each QML component is instantiated in a QQmlContext.
483 QQmlContext's are essential for passing data to QML
484 components. In QML, contexts are arranged hierarchically and this
485 hierarchy is managed by the QQmlEngine.
487 Prior to creating any QML components, an application must have
488 created a QQmlEngine to gain access to a QML context. The
489 following example shows how to create a simple Text item.
493 QQmlComponent component(&engine);
494 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
495 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
497 //add item to view, etc
501 In this case, the Text item will be created in the engine's
502 \l {QQmlEngine::rootContext()}{root context}.
504 \sa QQmlComponent QQmlContext
508 Create a new QQmlEngine with the given \a parent.
510 QQmlEngine::QQmlEngine(QObject *parent)
511 : QJSEngine(*new QQmlEnginePrivate(this), parent)
518 Destroys the QQmlEngine.
520 Any QQmlContext's created on this engine will be
521 invalidated, but not destroyed (unless they are parented to the
524 QQmlEngine::~QQmlEngine()
527 if (d->isDebugging) {
528 QQmlEngineDebugService::instance()->remEngine(this);
531 // if we are the parent of any of the qobject module api instances,
532 // we need to remove them from our internal list, in order to prevent
533 // a segfault in engine private dtor.
534 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
535 QObject *currQObjectApi = 0;
536 QQmlMetaType::ModuleApiInstance *currInstance = 0;
537 foreach (const QQmlMetaType::ModuleApi &key, keys) {
538 currInstance = d->moduleApiInstances.value(key);
539 currQObjectApi = currInstance->qobjectApi;
540 if (this->children().contains(currQObjectApi)) {
541 delete currQObjectApi;
543 d->moduleApiInstances.remove(key);
547 // ensure we clean up QObjects with JS ownership
550 if (d->incubationController)
551 d->incubationController->d = 0;
554 /*! \fn void QQmlEngine::quit()
555 This signal is emitted when the QML loaded by the engine would like to quit.
558 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
559 This signal is emitted when \a warnings messages are generated by QML.
563 Clears the engine's internal component cache.
565 Normally the QQmlEngine caches components loaded from qml
566 files. This method clears this cache and forces the component to be
569 void QQmlEngine::clearComponentCache()
572 d->typeLoader.clearCache();
576 Returns the engine's root context.
578 The root context is automatically created by the QQmlEngine.
579 Data that should be available to all QML component instances
580 instantiated by the engine should be put in the root context.
582 Additional data that should only be available to a subset of
583 component instances should be added to sub-contexts parented to the
586 QQmlContext *QQmlEngine::rootContext() const
588 Q_D(const QQmlEngine);
589 return d->rootContext;
593 Sets the \a factory to use for creating QNetworkAccessManager(s).
595 QNetworkAccessManager is used for all network access by QML. By
596 implementing a factory it is possible to create custom
597 QNetworkAccessManager with specialized caching, proxy and cookie
600 The factory must be set before executing the engine.
602 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
605 QMutexLocker locker(&d->mutex);
606 d->networkAccessManagerFactory = factory;
610 Returns the current QQmlNetworkAccessManagerFactory.
612 \sa setNetworkAccessManagerFactory()
614 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
616 Q_D(const QQmlEngine);
617 return d->networkAccessManagerFactory;
620 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
623 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
625 void *args[] = { 0 };
626 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
630 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
632 QMutexLocker locker(&mutex);
633 QNetworkAccessManager *nam;
634 if (networkAccessManagerFactory) {
635 nam = networkAccessManagerFactory->create(parent);
637 nam = new QNetworkAccessManager(parent);
643 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
645 Q_Q(const QQmlEngine);
646 if (!networkAccessManager)
647 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
648 return networkAccessManager;
652 Returns a common QNetworkAccessManager which can be used by any QML
653 element instantiated by this engine.
655 If a QQmlNetworkAccessManagerFactory has been set and a
656 QNetworkAccessManager has not yet been created, the
657 QQmlNetworkAccessManagerFactory will be used to create the
658 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
659 will have no proxy or cache set.
661 \sa setNetworkAccessManagerFactory()
663 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
665 Q_D(const QQmlEngine);
666 return d->getNetworkAccessManager();
671 Sets the \a provider to use for images requested via the \e
672 image: url scheme, with host \a providerId. The QQmlEngine
673 takes ownership of \a provider.
675 Image providers enable support for pixmap and threaded image
676 requests. See the QQuickImageProvider documentation for details on
677 implementing and using image providers.
679 All required image providers should be added to the engine before any
680 QML sources files are loaded.
682 \sa removeImageProvider(), QQuickImageProvider
684 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
687 QMutexLocker locker(&d->mutex);
688 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
692 Returns the image provider set for \a providerId.
694 Returns the provider if it was found; otherwise returns 0.
696 \sa QQuickImageProvider
698 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
700 Q_D(const QQmlEngine);
701 QMutexLocker locker(&d->mutex);
702 return d->imageProviders.value(providerId).data();
706 Removes the image provider for \a providerId.
708 \sa addImageProvider(), QQuickImageProvider
710 void QQmlEngine::removeImageProvider(const QString &providerId)
713 QMutexLocker locker(&d->mutex);
714 d->imageProviders.take(providerId);
718 Return the base URL for this engine. The base URL is only used to
719 resolve components when a relative URL is passed to the
720 QQmlComponent constructor.
722 If a base URL has not been explicitly set, this method returns the
723 application's current working directory.
727 QUrl QQmlEngine::baseUrl() const
729 Q_D(const QQmlEngine);
730 if (d->baseUrl.isEmpty()) {
731 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
738 Set the base URL for this engine to \a url.
742 void QQmlEngine::setBaseUrl(const QUrl &url)
749 Returns true if warning messages will be output to stderr in addition
750 to being emitted by the warnings() signal, otherwise false.
752 The default value is true.
754 bool QQmlEngine::outputWarningsToStandardError() const
756 Q_D(const QQmlEngine);
757 return d->outputWarningsToStdErr;
761 Set whether warning messages will be output to stderr to \a enabled.
763 If \a enabled is true, any warning messages generated by QML will be
764 output to stderr and emitted by the warnings() signal. If \a enabled
765 is false, on the warnings() signal will be emitted. This allows
766 applications to handle warning output themselves.
768 The default value is true.
770 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
773 d->outputWarningsToStdErr = enabled;
777 Attempt to free unused memory.
779 void QQmlEngine::collectGarbage()
785 Returns the QQmlContext for the \a object, or 0 if no
786 context has been set.
788 When the QQmlEngine instantiates a QObject, the context is
791 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
796 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
799 static_cast<QQmlData *>(priv->declarativeData);
803 else if (data->outerContext)
804 return data->outerContext->asQQmlContext();
810 Sets the QQmlContext for the \a object to \a context.
811 If the \a object already has a context, a warning is
812 output, but the context is not changed.
814 When the QQmlEngine instantiates a QObject, the context is
817 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
819 if (!object || !context)
822 QQmlData *data = QQmlData::get(object, true);
824 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
828 QQmlContextData *contextData = QQmlContextData::get(context);
829 contextData->addObject(object);
833 \enum QQmlEngine::ObjectOwnership
835 Ownership controls whether or not QML automatically destroys the
836 QObject when the object is garbage collected by the JavaScript
837 engine. The two ownership options are:
839 \value CppOwnership The object is owned by C++ code, and will
840 never be deleted by QML. The JavaScript destroy() method cannot be
841 used on objects with CppOwnership. This option is similar to
842 QScriptEngine::QtOwnership.
844 \value JavaScriptOwnership The object is owned by JavaScript.
845 When the object is returned to QML as the return value of a method
846 call or property access, QML will delete the object if there are no
847 remaining JavaScript references to it and it has no
848 QObject::parent(). This option is similar to
849 QScriptEngine::ScriptOwnership.
851 Generally an application doesn't need to set an object's ownership
852 explicitly. QML uses a heuristic to set the default object
853 ownership. By default, an object that is created by QML has
854 JavaScriptOwnership. The exception to this are the root objects
855 created by calling QQmlComponent::create() or
856 QQmlComponent::beginCreate() which have CppOwnership by
857 default. The ownership of these root-level objects is considered to
858 have been transferred to the C++ caller.
860 Objects not-created by QML have CppOwnership by default. The
861 exception to this is objects returned from a C++ method call. The
862 ownership of these objects is passed to JavaScript.
864 Calling setObjectOwnership() overrides the default ownership
865 heuristic used by QML.
869 Sets the \a ownership of \a object.
871 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
876 QQmlData *ddata = QQmlData::get(object, true);
880 ddata->indestructible = (ownership == CppOwnership)?true:false;
881 ddata->explicitIndestructibleSet = true;
885 Returns the ownership of \a object.
887 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
892 QQmlData *ddata = QQmlData::get(object, false);
896 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
899 bool QQmlEngine::event(QEvent *e)
902 if (e->type() == QEvent::User)
903 d->doDeleteInEngineThread();
905 return QJSEngine::event(e);
908 void QQmlEnginePrivate::doDeleteInEngineThread()
910 QFieldList<Deletable, &Deletable::next> list;
912 list.copyAndClear(toDeleteInEngineThread);
915 while (Deletable *d = list.takeFirst())
919 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
921 QQmlData *data = QQmlData::get(object);
923 if (data && data->deferredComponent) {
924 QQmlObjectCreatingProfiler prof;
926 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
927 prof.setTypeName(type ? type->qmlTypeName()
928 : QString::fromUtf8(object->metaObject()->className()));
929 if (data->outerContext)
930 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
932 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
934 QQmlComponentPrivate::ConstructionState state;
935 QQmlComponentPrivate::beginDeferred(ep, object, &state);
937 data->deferredComponent->release();
938 data->deferredComponent = 0;
940 QQmlComponentPrivate::complete(ep, &state);
944 QQmlContext *qmlContext(const QObject *obj)
946 return QQmlEngine::contextForObject(obj);
949 QQmlEngine *qmlEngine(const QObject *obj)
951 QQmlData *data = QQmlData::get(obj, false);
952 if (!data || !data->context)
954 return data->context->engine;
957 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
959 QQmlData *data = QQmlData::get(object);
961 return 0; // Attached properties are only on objects created by QML
963 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
967 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
971 rv = pf(const_cast<QObject *>(object));
974 data->attachedProperties()->insert(id, rv);
979 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
980 const QMetaObject *attachedMetaObject, bool create)
983 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
985 if (*idCache == -1 || !object)
988 return qmlAttachedPropertiesObjectById(*idCache, object, create);
991 QQmlDebuggingEnabler::QQmlDebuggingEnabler()
993 #ifndef QQML_NO_DEBUG_PROTOCOL
994 if (!QQmlEnginePrivate::qml_debugging_enabled) {
995 qDebug("QML debugging is enabled. Only use this in a safe environment.");
997 QQmlEnginePrivate::qml_debugging_enabled = true;
1002 class QQmlDataExtended {
1005 ~QQmlDataExtended();
1007 QHash<int, QObject *> attachedProperties;
1008 QQmlNotifier objectNameNotifier;
1011 QQmlDataExtended::QQmlDataExtended()
1015 QQmlDataExtended::~QQmlDataExtended()
1019 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1022 layout(endpoint->next);
1024 int index = endpoint->sourceSignal;
1025 index = qMin(index, 0xFFFF - 1);
1027 endpoint->next = notifies[index];
1028 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1029 endpoint->prev = ¬ifies[index];
1030 notifies[index] = endpoint;
1033 void QQmlData::NotifyList::layout()
1035 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1038 QQmlNotifierEndpoint **old = notifies;
1039 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1040 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1041 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1042 sizeof(QQmlNotifierEndpoint*);
1043 memset(notifies + notifiesSize, 0, memsetSize);
1045 if (notifies != old) {
1046 for (int ii = 0; ii < notifiesSize; ++ii)
1048 notifies[ii]->prev = ¬ifies[ii];
1051 notifiesSize = maximumTodoIndex + 1;
1056 maximumTodoIndex = 0;
1060 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1063 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1064 notifyList->connectionMask = 0;
1065 notifyList->maximumTodoIndex = 0;
1066 notifyList->notifiesSize = 0;
1067 notifyList->todo = 0;
1068 notifyList->notifies = 0;
1071 Q_ASSERT(!endpoint->isConnected());
1073 index = qMin(index, 0xFFFF - 1);
1074 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1076 if (index < notifyList->notifiesSize) {
1078 endpoint->next = notifyList->notifies[index];
1079 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1080 endpoint->prev = ¬ifyList->notifies[index];
1081 notifyList->notifies[index] = endpoint;
1084 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1086 endpoint->next = notifyList->todo;
1087 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1088 endpoint->prev = ¬ifyList->todo;
1089 notifyList->todo = endpoint;
1093 QQmlNotifier *QQmlData::objectNameNotifier() const
1095 if (!extendedData) extendedData = new QQmlDataExtended;
1096 return &extendedData->objectNameNotifier;
1099 QHash<int, QObject *> *QQmlData::attachedProperties() const
1101 if (!extendedData) extendedData = new QQmlDataExtended;
1102 return &extendedData->attachedProperties;
1105 void QQmlData::destroyed(QObject *object)
1107 if (deferredComponent)
1108 deferredComponent->release();
1110 if (nextContextObject)
1111 nextContextObject->prevContextObject = prevContextObject;
1112 if (prevContextObject)
1113 *prevContextObject = nextContextObject;
1115 QQmlAbstractBinding *binding = bindings;
1117 QQmlAbstractBinding *next = binding->m_nextBinding;
1118 binding->m_prevBinding = 0;
1119 binding->m_nextBinding = 0;
1128 propertyCache->release();
1130 if (ownContext && context)
1134 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1135 *guard = (QObject *)0;
1136 guard->objectDestroyed(object);
1140 while (notifyList->todo)
1141 notifyList->todo->disconnect();
1142 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1143 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1146 free(notifyList->notifies);
1151 delete extendedData;
1153 v8object.Clear(); // The WeakReference handler will clean the actual handle
1159 void QQmlData::parentChanged(QObject *object, QObject *parent)
1165 void QQmlData::objectNameChanged(QObject *)
1167 if (extendedData) objectNameNotifier()->notify();
1170 bool QQmlData::hasBindingBit(int bit) const
1172 if (bindingBitsSize > bit)
1173 return bindingBits[bit / 32] & (1 << (bit % 32));
1178 void QQmlData::clearBindingBit(int bit)
1180 if (bindingBitsSize > bit)
1181 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1184 void QQmlData::setBindingBit(QObject *obj, int bit)
1186 if (bindingBitsSize <= bit) {
1187 int props = obj->metaObject()->propertyCount();
1188 Q_ASSERT(bit < props);
1190 int arraySize = (props + 31) / 32;
1191 int oldArraySize = bindingBitsSize / 32;
1193 bindingBits = (quint32 *)realloc(bindingBits,
1194 arraySize * sizeof(quint32));
1196 memset(bindingBits + oldArraySize,
1198 sizeof(quint32) * (arraySize - oldArraySize));
1200 bindingBitsSize = arraySize * 32;
1203 bindingBits[bit / 32] |= (1 << (bit % 32));
1206 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1208 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1209 if (url.authority().isEmpty())
1210 return QLatin1Char(':') + url.path();
1213 return url.toLocalFile();
1217 static QString toLocalFile(const QString &url)
1219 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1222 QString file = url.mid(7);
1224 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1226 // magic for drives on windows
1227 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1233 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1235 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1236 if (url.length() > 4)
1237 return QLatin1Char(':') + url.mid(4);
1241 return toLocalFile(url);
1244 void QQmlEnginePrivate::sendQuit()
1248 if (q->receivers(SIGNAL(quit())) == 0) {
1249 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1253 static void dumpwarning(const QQmlError &error)
1255 qWarning().nospace() << qPrintable(error.toString());
1258 static void dumpwarning(const QList<QQmlError> &errors)
1260 for (int ii = 0; ii < errors.count(); ++ii)
1261 dumpwarning(errors.at(ii));
1264 void QQmlEnginePrivate::warning(const QQmlError &error)
1267 q->warnings(QList<QQmlError>() << error);
1268 if (outputWarningsToStdErr)
1272 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1275 q->warnings(errors);
1276 if (outputWarningsToStdErr)
1277 dumpwarning(errors);
1280 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1283 QQmlEnginePrivate::get(engine)->warning(error);
1288 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1291 QQmlEnginePrivate::get(engine)->warning(error);
1296 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1299 engine->warning(error);
1304 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1307 engine->warning(error);
1313 This function should be called prior to evaluation of any js expression,
1314 so that scarce resources are not freed prematurely (eg, if there is a
1315 nested javascript expression).
1317 void QQmlEnginePrivate::referenceScarceResources()
1319 scarceResourcesRefCount += 1;
1323 This function should be called after evaluation of the js expression is
1324 complete, and so the scarce resources may be freed safely.
1326 void QQmlEnginePrivate::dereferenceScarceResources()
1328 Q_ASSERT(scarceResourcesRefCount > 0);
1329 scarceResourcesRefCount -= 1;
1331 // if the refcount is zero, then evaluation of the "top level"
1332 // expression must have completed. We can safely release the
1333 // scarce resources.
1334 if (scarceResourcesRefCount == 0) {
1335 // iterate through the list and release them all.
1336 // note that the actual SRD is owned by the JS engine,
1337 // so we cannot delete the SRD; but we can free the
1338 // memory used by the variant in the SRD.
1339 while (ScarceResourceData *sr = scarceResources.first()) {
1340 sr->data = QVariant();
1341 scarceResources.remove(sr);
1347 Adds \a path as a directory where the engine searches for
1348 installed modules in a URL-based directory structure.
1349 The \a path may be a local filesystem directory or a URL.
1351 The newly added \a path will be first in the importPathList().
1353 \sa setImportPathList(), {QML Modules}
1355 void QQmlEngine::addImportPath(const QString& path)
1358 d->importDatabase.addImportPath(path);
1362 Returns the list of directories where the engine searches for
1363 installed modules in a URL-based directory structure.
1365 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1366 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1367 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1368 provided by that module. A \c qmldir file is required for defining the
1369 type version mapping and possibly QML extensions plugins.
1371 By default, the list contains the directory of the application executable,
1372 paths specified in the \c QML_IMPORT_PATH environment variable,
1373 and the builtin \c ImportsPath from QLibraryInfo.
1375 \sa addImportPath() setImportPathList()
1377 QStringList QQmlEngine::importPathList() const
1379 Q_D(const QQmlEngine);
1380 return d->importDatabase.importPathList();
1384 Sets \a paths as the list of directories where the engine searches for
1385 installed modules in a URL-based directory structure.
1387 By default, the list contains the directory of the application executable,
1388 paths specified in the \c QML_IMPORT_PATH environment variable,
1389 and the builtin \c ImportsPath from QLibraryInfo.
1391 \sa importPathList() addImportPath()
1393 void QQmlEngine::setImportPathList(const QStringList &paths)
1396 d->importDatabase.setImportPathList(paths);
1401 Adds \a path as a directory where the engine searches for
1402 native plugins for imported modules (referenced in the \c qmldir file).
1404 By default, the list contains only \c ., i.e. the engine searches
1405 in the directory of the \c qmldir file itself.
1407 The newly added \a path will be first in the pluginPathList().
1409 \sa setPluginPathList()
1411 void QQmlEngine::addPluginPath(const QString& path)
1414 d->importDatabase.addPluginPath(path);
1419 Returns the list of directories where the engine searches for
1420 native plugins for imported modules (referenced in the \c qmldir file).
1422 By default, the list contains only \c ., i.e. the engine searches
1423 in the directory of the \c qmldir file itself.
1425 \sa addPluginPath() setPluginPathList()
1427 QStringList QQmlEngine::pluginPathList() const
1429 Q_D(const QQmlEngine);
1430 return d->importDatabase.pluginPathList();
1434 Sets the list of directories where the engine searches for
1435 native plugins for imported modules (referenced in the \c qmldir file)
1438 By default, the list contains only \c ., i.e. the engine searches
1439 in the directory of the \c qmldir file itself.
1441 \sa pluginPathList() addPluginPath()
1443 void QQmlEngine::setPluginPathList(const QStringList &paths)
1446 d->importDatabase.setPluginPathList(paths);
1450 Imports the plugin named \a filePath with the \a uri provided.
1451 Returns true if the plugin was successfully imported; otherwise returns false.
1453 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1455 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1457 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1460 return d->importDatabase.importPlugin(filePath, uri, errors);
1464 Imports the plugin named \a filePath with the \a uri provided.
1465 Returns true if the plugin was successfully imported; otherwise returns false.
1467 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1469 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1471 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1474 QList<QQmlError> errors;
1475 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1476 if (!errors.isEmpty()) {
1478 for (int i = 0; i < errors.size(); ++i) {
1479 builtError = QString(QLatin1String("%1\n %2"))
1481 .arg(errors.at(i).toString());
1483 *errorString = builtError;
1489 \property QQmlEngine::offlineStoragePath
1490 \brief the directory for storing offline user data
1492 Returns the directory where SQL and other offline
1495 QQuickWebView and the SQL databases created with openDatabase()
1498 The default is QML/OfflineStorage in the platform-standard
1499 user application data directory.
1501 Note that the path may not currently exist on the filesystem, so
1502 callers wanting to \e create new files at this location should create
1503 it first - see QDir::mkpath().
1505 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1508 d->offlineStoragePath = dir;
1511 QString QQmlEngine::offlineStoragePath() const
1513 Q_D(const QQmlEngine);
1514 return d->offlineStoragePath;
1517 static void voidptr_destructor(void *v)
1519 void **ptr = (void **)v;
1523 static void *voidptr_constructor(const void *v)
1528 return new void*(*(void **)v);
1532 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1536 if (!mo->superClass()) {
1537 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1538 propertyCache.insert(mo, rv);
1541 QQmlPropertyCache *super = cache(mo->superClass());
1542 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1543 propertyCache.insert(mo, rv);
1548 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1551 QList<QQmlType *> types;
1553 int maxMinorVersion = 0;
1555 const QMetaObject *metaObject = type->metaObject();
1557 while (metaObject) {
1558 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1559 type->majorVersion(), minorVersion);
1561 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1567 metaObject = metaObject->superClass();
1570 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1572 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1576 QQmlPropertyCache *raw = cache(type->metaObject());
1578 bool hasCopied = false;
1580 for (int ii = 0; ii < types.count(); ++ii) {
1581 QQmlType *currentType = types.at(ii);
1585 int rev = currentType->metaObjectRevision();
1586 int moIndex = types.count() - 1 - ii;
1588 if (raw->allowedRevisionCache[moIndex] != rev) {
1593 raw->allowedRevisionCache[moIndex] = rev;
1597 // Test revision compatibility - the basic rule is:
1598 // * Anything that is excluded, cannot overload something that is not excluded *
1600 // Signals override:
1601 // * other signals and methods of the same name.
1602 // * properties named on<Signal Name>
1603 // * automatic <property name>Changed notify signals
1605 // Methods override:
1606 // * other methods of the same name
1608 // Properties override:
1609 // * other elements of the same name
1611 bool overloadError = false;
1612 QString overloadName;
1615 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1616 !overloadError && iter != raw->stringCache.end();
1619 QQmlPropertyData *d = *iter;
1620 if (raw->isAllowedInRevision(d))
1621 continue; // Not excluded - no problems
1623 // check that a regular "name" overload isn't happening
1624 QQmlPropertyData *current = d;
1625 while (!overloadError && current) {
1626 current = d->overrideData(current);
1627 if (current && raw->isAllowedInRevision(current))
1628 overloadError = true;
1633 if (overloadError) {
1634 if (hasCopied) raw->release();
1636 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."));
1640 if (!hasCopied) raw->addref();
1641 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1643 if (minorVersion != maxMinorVersion) {
1645 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1651 QQmlMetaType::ModuleApiInstance *
1652 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1654 Locker locker(this);
1656 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1658 a = new QQmlMetaType::ModuleApiInstance;
1659 a->scriptCallback = module.script;
1660 a->qobjectCallback = module.qobject;
1661 moduleApiInstances.insert(module, a);
1667 bool QQmlEnginePrivate::isQObject(int t)
1669 Locker locker(this);
1670 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1673 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1675 Locker locker(this);
1676 int t = v.userType();
1677 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1679 return *(QObject **)(v.constData());
1681 return QQmlMetaType::toQObject(v, ok);
1685 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1687 Locker locker(this);
1688 if (m_compositeTypes.contains(t))
1689 return QQmlMetaType::Object;
1690 else if (m_qmlLists.contains(t))
1691 return QQmlMetaType::List;
1693 return QQmlMetaType::typeCategory(t);
1696 bool QQmlEnginePrivate::isList(int t) const
1698 Locker locker(this);
1699 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1702 int QQmlEnginePrivate::listType(int t) const
1704 Locker locker(this);
1705 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1706 if (iter != m_qmlLists.end())
1709 return QQmlMetaType::listType(t);
1712 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1714 Locker locker(this);
1715 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1716 if (iter != m_compositeTypes.end()) {
1717 return (*iter)->root;
1719 QQmlType *type = QQmlMetaType::qmlType(t);
1720 return type?type->baseMetaObject():0;
1724 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1726 Locker locker(this);
1727 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1728 if (iter != m_compositeTypes.end()) {
1729 return (*iter)->root;
1731 QQmlType *type = QQmlMetaType::qmlType(t);
1732 return type?type->metaObject():0;
1736 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1738 QByteArray name = data->root->className();
1740 QByteArray ptr = name + '*';
1741 QByteArray lst = "QQmlListProperty<" + name + '>';
1743 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1744 voidptr_constructor);
1745 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1746 voidptr_constructor);
1750 Locker locker(this);
1751 m_qmlLists.insert(lst_type, ptr_type);
1752 m_compositeTypes.insert(ptr_type, data);
1755 bool QQml_isFileCaseCorrect(const QString &fileName)
1757 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1758 QFileInfo info(fileName);
1759 const QString absolute = info.absoluteFilePath();
1761 #if defined(Q_OS_MAC)
1762 const QString canonical = info.canonicalFilePath();
1763 #elif defined(Q_OS_WIN)
1764 wchar_t buffer[1024];
1766 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1767 if (rv == 0 || rv >= 1024) return true;
1768 rv = ::GetLongPathName(buffer, buffer, 1024);
1769 if (rv == 0 || rv >= 1024) return true;
1771 const QString canonical = QString::fromWCharArray(buffer);
1774 const int absoluteLength = absolute.length();
1775 const int canonicalLength = canonical.length();
1777 const int length = qMin(absoluteLength, canonicalLength);
1778 for (int ii = 0; ii < length; ++ii) {
1779 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1780 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1782 if (a.toLower() != c.toLower())
1794 \fn QQmlEngine *qmlEngine(const QObject *object)
1797 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1798 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1802 \fn QQmlContext *qmlContext(const QObject *object)
1805 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1806 QQmlEngine::contextForObject(object).