1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
72 #include <private/qqmlboundsignal_p.h>
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
80 #include <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<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
182 \class QQmlImageProviderBase
183 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
186 Image providers must be registered with the QML engine. The only information the QML
187 engine knows about image providers is the type of image data they provide. To use an
188 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
189 to a QQuickImageProvider pointer.
191 \sa QQuickImageProvider, QQuickTextureFactory
195 \enum QQmlImageProviderBase::ImageType
197 Defines the type of image supported by this image provider.
199 \value Image The Image Provider provides QImage images.
200 The QQuickImageProvider::requestImage() method will be called for all image requests.
201 \value Pixmap The Image Provider provides QPixmap images.
202 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
203 \value Texture The Image Provider provides QSGTextureProvider based images.
204 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
208 QQmlImageProviderBase::QQmlImageProviderBase()
213 QQmlImageProviderBase::~QQmlImageProviderBase()
219 \qmlclass Qt QQmlEnginePrivate
220 \ingroup qml-utility-elements
221 \brief The QML global Qt object provides useful enums and functions from Qt.
223 \keyword QmlGlobalQtObject
225 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
227 The \c Qt object is a global object with utility functions, properties and enums.
229 It is not instantiable; to use it, call the members of the global \c Qt object directly.
236 color: Qt.rgba(1, 0, 0, 1)
237 text: Qt.md5("hello, world")
244 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
245 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
249 The Qt object also contains helper functions for creating objects of specific
250 data types. This is primarily useful when setting the properties of an item
251 when the property has one of the following types:
254 \li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
255 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
256 \li \c point - use \l{Qt::point()}{Qt.point()}
257 \li \c size - use \l{Qt::size()}{Qt.size()}
258 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
261 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
263 \section1 Date/Time Formatters
265 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
268 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
269 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
270 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
273 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
276 \section1 Dynamic Object Creation
277 The following functions on the global object allow you to dynamically create QML
278 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
282 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
283 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
289 \qmlproperty object Qt::application
292 The \c application object provides access to global application state
293 properties shared by many QML components.
299 \li \c application.active
301 This read-only property indicates whether the application is the top-most and focused
302 application, and the user is able to interact with the application. The property
303 is false when the application is in the background, the device keylock or screen
304 saver is active, the screen backlight is turned off, or the global system dialog
305 is being displayed on top of the application. It can be used for stopping and
306 pausing animations, timers and active processing of data in order to save device
307 battery power and free device memory and processor load when the application is not
311 \li \c application.layoutDirection
313 This read-only property can be used to query the default layout direction of the
314 application. On system start-up, the default layout direction depends on the
315 application's language. The property has a value of \c Qt.RightToLeft in locales
316 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
317 where the reading direction flows from left to right. You can bind to this
318 property to customize your application layouts to support both layout directions.
323 \li Qt.LeftToRight - Text and graphics elements should be positioned
325 \li Qt.RightToLeft - Text and graphics elements should be positioned
330 \li \c application.inputPanel
332 This read-only property allows access to application's QInputPanel object
333 and all its properties and slots. See the QInputPanel documentation for
334 further details. Deprecated in favor of Qt.InputMethod
337 The following example uses the \c application object to indicate
338 whether the application is currently active:
340 \snippet doc/src/snippets/qml/application.qml document
342 \qmlproperty object Qt::inputMethod
345 The \c inputMethod object allows access to application's QInputMethod object
346 and all its properties and slots. See the QInputMethod documentation for
352 \qmlmethod object Qt::include(string url, jsobject callback)
354 Includes another JavaScript file. This method can only be used from within JavaScript files,
355 and not regular QML files.
357 This imports all functions from \a url into the current script's namespace.
359 Qt.include() returns an object that describes the status of the operation. The object has
360 a single property, \c {status}, that is set to one of the following values:
363 \header \li Symbol \li Value \li Description
364 \row \li result.OK \li 0 \li The include completed successfully.
365 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
366 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
367 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
368 An additional \c exception property will be set in this case.
371 The \c status property will be updated as the operation progresses.
373 If provided, \a callback is invoked when the operation completes. The callback is passed
374 the same object as is returned from the Qt.include() call.
376 // Qt.include() is implemented in qv8include.cpp
379 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
380 : propertyCapture(0), rootContext(0), isDebugging(false),
381 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
382 cleanup(0), erroredBindings(0), inProgressCreations(0),
383 workerScriptEngine(0), activeVME(0),
384 networkAccessManager(0), networkAccessManagerFactory(0),
385 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
386 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
390 QQmlEnginePrivate::~QQmlEnginePrivate()
392 if (inProgressCreations)
393 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
396 QQmlCleanup *c = cleanup;
398 if (cleanup) cleanup->prev = &cleanup;
404 doDeleteInEngineThread();
406 if (incubationController) incubationController->d = 0;
407 incubationController = 0;
412 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
414 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
416 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
418 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
419 delete (*iter)->qobjectApi;
424 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
426 QObjectPrivate *p = QObjectPrivate::get(o);
427 if (p->declarativeData) {
428 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
429 if (d->ownContext && d->context) {
430 d->context->destroy();
436 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
438 static_cast<QQmlData *>(d)->destroyed(o);
441 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
443 static_cast<QQmlData *>(d)->parentChanged(o, p);
446 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
448 static_cast<QQmlData *>(d)->objectNameChanged(o);
451 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
453 QQmlData *ddata = QQmlData::get(object, false);
454 if (!ddata) return; // Probably being deleted
456 QQmlNotifierEndpoint *ep = ddata->notify(index);
457 if (ep) QQmlNotifier::emitNotify(ep, a);
460 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
462 return static_cast<QQmlData *>(d)->endpointCount(index);
465 int QQmlData::endpointCount(int index)
468 QQmlNotifierEndpoint *ep = notify(index);
479 void QQmlEnginePrivate::init()
483 static bool firstTime = true;
485 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
490 qRegisterMetaType<QVariant>("QVariant");
491 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
492 qRegisterMetaType<QJSValue>("QJSValue");
493 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
494 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
495 qRegisterMetaType<QList<int> >("QList<int>");
496 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
500 v8engine()->setEngine(q);
502 rootContext = new QQmlContext(q,true);
504 if (QCoreApplication::instance()->thread() == q->thread() &&
505 QQmlEngineDebugService::isDebuggingEnabled()) {
507 QQmlEngineDebugService::instance()->addEngine(q);
508 QV8DebugService::initialize(v8engine());
509 QV8ProfilerService::initialize();
510 QQmlProfilerService::initialize();
511 QDebugMessageService::instance();
514 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
515 if (!dataLocation.isEmpty())
516 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
517 + QDir::separator() + QLatin1String("QML")
518 + QDir::separator() + QLatin1String("OfflineStorage");
521 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
524 if (!workerScriptEngine)
525 workerScriptEngine = new QQuickWorkerScriptEngine(q);
526 return workerScriptEngine;
533 \brief The QQmlEngine class provides an environment for instantiating QML components.
536 Each QML component is instantiated in a QQmlContext.
537 QQmlContext's are essential for passing data to QML
538 components. In QML, contexts are arranged hierarchically and this
539 hierarchy is managed by the QQmlEngine.
541 Prior to creating any QML components, an application must have
542 created a QQmlEngine to gain access to a QML context. The
543 following example shows how to create a simple Text item.
547 QQmlComponent component(&engine);
548 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
549 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
551 //add item to view, etc
555 In this case, the Text item will be created in the engine's
556 \l {QQmlEngine::rootContext()}{root context}.
558 Note that the QtQuick 1 version is called QDeclarativeEngine.
560 \sa QQmlComponent QQmlContext
564 Create a new QQmlEngine with the given \a parent.
566 QQmlEngine::QQmlEngine(QObject *parent)
567 : QJSEngine(*new QQmlEnginePrivate(this), parent)
574 Destroys the QQmlEngine.
576 Any QQmlContext's created on this engine will be
577 invalidated, but not destroyed (unless they are parented to the
580 QQmlEngine::~QQmlEngine()
583 if (d->isDebugging) {
584 QQmlEngineDebugService::instance()->remEngine(this);
587 // if we are the parent of any of the qobject module api instances,
588 // we need to remove them from our internal list, in order to prevent
589 // a segfault in engine private dtor.
590 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
591 QObject *currQObjectApi = 0;
592 QQmlMetaType::ModuleApiInstance *currInstance = 0;
593 foreach (const QQmlMetaType::ModuleApi &key, keys) {
594 currInstance = d->moduleApiInstances.value(key);
595 currQObjectApi = currInstance->qobjectApi;
596 if (this->children().contains(currQObjectApi)) {
597 delete currQObjectApi;
599 d->moduleApiInstances.remove(key);
603 // ensure we clean up QObjects with JS ownership
606 if (d->incubationController)
607 d->incubationController->d = 0;
610 /*! \fn void QQmlEngine::quit()
611 This signal is emitted when the QML loaded by the engine would like to quit.
614 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
615 This signal is emitted when \a warnings messages are generated by QML.
619 Clears the engine's internal component cache.
621 This function causes the property metadata of all components previously
622 loaded by the engine to be destroyed. All previously loaded components and
623 the property bindings for all extant objects created from those components will
626 This function returns the engine to a state where it does not contain any loaded
627 component data. This may be useful in order to reload a smaller subset of the
628 previous component set, or to load a new version of a previously loaded component.
630 Once the component cache has been cleared, components must be loaded before
631 any new objects can be created.
633 void QQmlEngine::clearComponentCache()
636 d->typeLoader.clearCache();
640 Returns the engine's root context.
642 The root context is automatically created by the QQmlEngine.
643 Data that should be available to all QML component instances
644 instantiated by the engine should be put in the root context.
646 Additional data that should only be available to a subset of
647 component instances should be added to sub-contexts parented to the
650 QQmlContext *QQmlEngine::rootContext() const
652 Q_D(const QQmlEngine);
653 return d->rootContext;
657 Sets the \a factory to use for creating QNetworkAccessManager(s).
659 QNetworkAccessManager is used for all network access by QML. By
660 implementing a factory it is possible to create custom
661 QNetworkAccessManager with specialized caching, proxy and cookie
664 The factory must be set before executing the engine.
666 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
669 QMutexLocker locker(&d->mutex);
670 d->networkAccessManagerFactory = factory;
674 Returns the current QQmlNetworkAccessManagerFactory.
676 \sa setNetworkAccessManagerFactory()
678 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
680 Q_D(const QQmlEngine);
681 return d->networkAccessManagerFactory;
684 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
687 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
689 void *args[] = { 0 };
690 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
694 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
696 QMutexLocker locker(&mutex);
697 QNetworkAccessManager *nam;
698 if (networkAccessManagerFactory) {
699 nam = networkAccessManagerFactory->create(parent);
701 nam = new QNetworkAccessManager(parent);
707 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
709 Q_Q(const QQmlEngine);
710 if (!networkAccessManager)
711 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
712 return networkAccessManager;
716 Returns a common QNetworkAccessManager which can be used by any QML
717 element instantiated by this engine.
719 If a QQmlNetworkAccessManagerFactory has been set and a
720 QNetworkAccessManager has not yet been created, the
721 QQmlNetworkAccessManagerFactory will be used to create the
722 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
723 will have no proxy or cache set.
725 \sa setNetworkAccessManagerFactory()
727 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
729 Q_D(const QQmlEngine);
730 return d->getNetworkAccessManager();
735 Sets the \a provider to use for images requested via the \e
736 image: url scheme, with host \a providerId. The QQmlEngine
737 takes ownership of \a provider.
739 Image providers enable support for pixmap and threaded image
740 requests. See the QQuickImageProvider documentation for details on
741 implementing and using image providers.
743 All required image providers should be added to the engine before any
744 QML sources files are loaded.
746 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
748 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
751 QMutexLocker locker(&d->mutex);
752 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
756 Returns the image provider set for \a providerId.
758 Returns the provider if it was found; otherwise returns 0.
760 \sa QQuickImageProvider
762 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
764 Q_D(const QQmlEngine);
765 QMutexLocker locker(&d->mutex);
766 return d->imageProviders.value(providerId).data();
770 Removes the image provider for \a providerId.
772 \sa addImageProvider(), QQuickImageProvider
774 void QQmlEngine::removeImageProvider(const QString &providerId)
777 QMutexLocker locker(&d->mutex);
778 d->imageProviders.take(providerId);
782 Return the base URL for this engine. The base URL is only used to
783 resolve components when a relative URL is passed to the
784 QQmlComponent constructor.
786 If a base URL has not been explicitly set, this method returns the
787 application's current working directory.
791 QUrl QQmlEngine::baseUrl() const
793 Q_D(const QQmlEngine);
794 if (d->baseUrl.isEmpty()) {
795 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
802 Set the base URL for this engine to \a url.
806 void QQmlEngine::setBaseUrl(const QUrl &url)
813 Returns true if warning messages will be output to stderr in addition
814 to being emitted by the warnings() signal, otherwise false.
816 The default value is true.
818 bool QQmlEngine::outputWarningsToStandardError() const
820 Q_D(const QQmlEngine);
821 return d->outputWarningsToStdErr;
825 Set whether warning messages will be output to stderr to \a enabled.
827 If \a enabled is true, any warning messages generated by QML will be
828 output to stderr and emitted by the warnings() signal. If \a enabled
829 is false, on the warnings() signal will be emitted. This allows
830 applications to handle warning output themselves.
832 The default value is true.
834 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
837 d->outputWarningsToStdErr = enabled;
841 Attempt to free unused memory.
843 void QQmlEngine::collectGarbage()
849 Returns the QQmlContext for the \a object, or 0 if no
850 context has been set.
852 When the QQmlEngine instantiates a QObject, the context is
855 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
860 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
863 static_cast<QQmlData *>(priv->declarativeData);
867 else if (data->outerContext)
868 return data->outerContext->asQQmlContext();
874 Sets the QQmlContext for the \a object to \a context.
875 If the \a object already has a context, a warning is
876 output, but the context is not changed.
878 When the QQmlEngine instantiates a QObject, the context is
881 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
883 if (!object || !context)
886 QQmlData *data = QQmlData::get(object, true);
888 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
892 QQmlContextData *contextData = QQmlContextData::get(context);
893 contextData->addObject(object);
897 \enum QQmlEngine::ObjectOwnership
899 Ownership controls whether or not QML automatically destroys the
900 QObject when the object is garbage collected by the JavaScript
901 engine. The two ownership options are:
903 \value CppOwnership The object is owned by C++ code, and will
904 never be deleted by QML. The JavaScript destroy() method cannot be
905 used on objects with CppOwnership. This option is similar to
906 QScriptEngine::QtOwnership.
908 \value JavaScriptOwnership The object is owned by JavaScript.
909 When the object is returned to QML as the return value of a method
910 call or property access, QML will delete the object if there are no
911 remaining JavaScript references to it and it has no
912 QObject::parent(). This option is similar to
913 QScriptEngine::ScriptOwnership.
915 Generally an application doesn't need to set an object's ownership
916 explicitly. QML uses a heuristic to set the default object
917 ownership. By default, an object that is created by QML has
918 JavaScriptOwnership. The exception to this are the root objects
919 created by calling QQmlComponent::create() or
920 QQmlComponent::beginCreate() which have CppOwnership by
921 default. The ownership of these root-level objects is considered to
922 have been transferred to the C++ caller.
924 Objects not-created by QML have CppOwnership by default. The
925 exception to this is objects returned from a C++ method call. The
926 ownership of these objects is passed to JavaScript.
928 Calling setObjectOwnership() overrides the default ownership
929 heuristic used by QML.
933 Sets the \a ownership of \a object.
935 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
940 QQmlData *ddata = QQmlData::get(object, true);
944 ddata->indestructible = (ownership == CppOwnership)?true:false;
945 ddata->explicitIndestructibleSet = true;
949 Returns the ownership of \a object.
951 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
956 QQmlData *ddata = QQmlData::get(object, false);
960 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
963 bool QQmlEngine::event(QEvent *e)
966 if (e->type() == QEvent::User)
967 d->doDeleteInEngineThread();
969 return QJSEngine::event(e);
972 void QQmlEnginePrivate::doDeleteInEngineThread()
974 QFieldList<Deletable, &Deletable::next> list;
976 list.copyAndClear(toDeleteInEngineThread);
979 while (Deletable *d = list.takeFirst())
983 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
985 QQmlData *data = QQmlData::get(object);
987 if (data && data->deferredComponent) {
988 QQmlObjectCreatingProfiler prof;
990 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
991 prof.setTypeName(type ? type->qmlTypeName()
992 : QString::fromUtf8(object->metaObject()->className()));
993 if (data->outerContext)
994 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
996 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
998 QQmlComponentPrivate::ConstructionState state;
999 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1001 data->deferredComponent->release();
1002 data->deferredComponent = 0;
1004 QQmlComponentPrivate::complete(ep, &state);
1008 QQmlContext *qmlContext(const QObject *obj)
1010 return QQmlEngine::contextForObject(obj);
1013 QQmlEngine *qmlEngine(const QObject *obj)
1015 QQmlData *data = QQmlData::get(obj, false);
1016 if (!data || !data->context)
1018 return data->context->engine;
1021 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1023 QQmlData *data = QQmlData::get(object);
1025 return 0; // Attached properties are only on objects created by QML
1027 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1031 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1035 rv = pf(const_cast<QObject *>(object));
1038 data->attachedProperties()->insert(id, rv);
1043 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1044 const QMetaObject *attachedMetaObject, bool create)
1047 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1049 if (*idCache == -1 || !object)
1052 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1055 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1057 #ifndef QQML_NO_DEBUG_PROTOCOL
1058 if (!QQmlEnginePrivate::qml_debugging_enabled
1060 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1062 QQmlEnginePrivate::qml_debugging_enabled = true;
1067 class QQmlDataExtended {
1070 ~QQmlDataExtended();
1072 QHash<int, QObject *> attachedProperties;
1073 QQmlNotifier objectNameNotifier;
1076 QQmlDataExtended::QQmlDataExtended()
1080 QQmlDataExtended::~QQmlDataExtended()
1084 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1087 layout(endpoint->next);
1089 int index = endpoint->sourceSignal;
1090 index = qMin(index, 0xFFFF - 1);
1092 endpoint->next = notifies[index];
1093 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1094 endpoint->prev = ¬ifies[index];
1095 notifies[index] = endpoint;
1098 void QQmlData::NotifyList::layout()
1100 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1103 QQmlNotifierEndpoint **old = notifies;
1104 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1105 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1106 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1107 sizeof(QQmlNotifierEndpoint*);
1108 memset(notifies + notifiesSize, 0, memsetSize);
1110 if (notifies != old) {
1111 for (int ii = 0; ii < notifiesSize; ++ii)
1113 notifies[ii]->prev = ¬ifies[ii];
1116 notifiesSize = maximumTodoIndex + 1;
1121 maximumTodoIndex = 0;
1125 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1128 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1129 notifyList->connectionMask = 0;
1130 notifyList->maximumTodoIndex = 0;
1131 notifyList->notifiesSize = 0;
1132 notifyList->todo = 0;
1133 notifyList->notifies = 0;
1136 Q_ASSERT(!endpoint->isConnected());
1138 index = qMin(index, 0xFFFF - 1);
1139 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1141 if (index < notifyList->notifiesSize) {
1143 endpoint->next = notifyList->notifies[index];
1144 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1145 endpoint->prev = ¬ifyList->notifies[index];
1146 notifyList->notifies[index] = endpoint;
1149 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1151 endpoint->next = notifyList->todo;
1152 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1153 endpoint->prev = ¬ifyList->todo;
1154 notifyList->todo = endpoint;
1158 QQmlNotifier *QQmlData::objectNameNotifier() const
1160 if (!extendedData) extendedData = new QQmlDataExtended;
1161 return &extendedData->objectNameNotifier;
1164 QHash<int, QObject *> *QQmlData::attachedProperties() const
1166 if (!extendedData) extendedData = new QQmlDataExtended;
1167 return &extendedData->attachedProperties;
1170 void QQmlData::destroyed(QObject *object)
1172 if (deferredComponent)
1173 deferredComponent->release();
1175 if (nextContextObject)
1176 nextContextObject->prevContextObject = prevContextObject;
1177 if (prevContextObject)
1178 *prevContextObject = nextContextObject;
1180 QQmlAbstractBinding *binding = bindings;
1182 QQmlAbstractBinding *next = binding->m_nextBinding;
1183 binding->m_prevBinding = 0;
1184 binding->m_nextBinding = 0;
1189 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1190 while (signalHandler) {
1191 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1192 signalHandler->m_prevSignal = 0;
1193 signalHandler->m_nextSignal = 0;
1194 delete signalHandler;
1195 signalHandler = next;
1202 propertyCache->release();
1204 if (ownContext && context)
1208 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1209 *guard = (QObject *)0;
1210 guard->objectDestroyed(object);
1214 while (notifyList->todo)
1215 notifyList->todo->disconnect();
1216 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1217 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1220 free(notifyList->notifies);
1225 delete extendedData;
1227 v8object.Clear(); // The WeakReference handler will clean the actual handle
1233 void QQmlData::parentChanged(QObject *object, QObject *parent)
1239 void QQmlData::objectNameChanged(QObject *)
1241 if (extendedData) objectNameNotifier()->notify();
1244 bool QQmlData::hasBindingBit(int bit) const
1246 if (bindingBitsSize > bit)
1247 return bindingBits[bit / 32] & (1 << (bit % 32));
1252 void QQmlData::clearBindingBit(int bit)
1254 if (bindingBitsSize > bit)
1255 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1258 void QQmlData::setBindingBit(QObject *obj, int bit)
1260 if (bindingBitsSize <= bit) {
1261 int props = obj->metaObject()->propertyCount();
1262 Q_ASSERT(bit < props);
1264 int arraySize = (props + 31) / 32;
1265 int oldArraySize = bindingBitsSize / 32;
1267 bindingBits = (quint32 *)realloc(bindingBits,
1268 arraySize * sizeof(quint32));
1270 memset(bindingBits + oldArraySize,
1272 sizeof(quint32) * (arraySize - oldArraySize));
1274 bindingBitsSize = arraySize * 32;
1277 bindingBits[bit / 32] |= (1 << (bit % 32));
1280 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1282 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1283 if (url.authority().isEmpty())
1284 return QLatin1Char(':') + url.path();
1287 return url.toLocalFile();
1291 static QString toLocalFile(const QString &url)
1293 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1296 QString file = url.mid(7);
1298 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1300 // magic for drives on windows
1301 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1307 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1309 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1310 if (url.length() > 4)
1311 return QLatin1Char(':') + url.mid(4);
1315 return toLocalFile(url);
1318 void QQmlEnginePrivate::sendQuit()
1322 if (q->receivers(SIGNAL(quit())) == 0) {
1323 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1327 static void dumpwarning(const QQmlError &error)
1329 qWarning().nospace() << qPrintable(error.toString());
1332 static void dumpwarning(const QList<QQmlError> &errors)
1334 for (int ii = 0; ii < errors.count(); ++ii)
1335 dumpwarning(errors.at(ii));
1338 void QQmlEnginePrivate::warning(const QQmlError &error)
1341 q->warnings(QList<QQmlError>() << error);
1342 if (outputWarningsToStdErr)
1346 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1349 q->warnings(errors);
1350 if (outputWarningsToStdErr)
1351 dumpwarning(errors);
1354 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1357 QQmlEnginePrivate::get(engine)->warning(error);
1362 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1365 QQmlEnginePrivate::get(engine)->warning(error);
1370 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1373 engine->warning(error);
1378 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1381 engine->warning(error);
1387 This function should be called prior to evaluation of any js expression,
1388 so that scarce resources are not freed prematurely (eg, if there is a
1389 nested javascript expression).
1391 void QQmlEnginePrivate::referenceScarceResources()
1393 scarceResourcesRefCount += 1;
1397 This function should be called after evaluation of the js expression is
1398 complete, and so the scarce resources may be freed safely.
1400 void QQmlEnginePrivate::dereferenceScarceResources()
1402 Q_ASSERT(scarceResourcesRefCount > 0);
1403 scarceResourcesRefCount -= 1;
1405 // if the refcount is zero, then evaluation of the "top level"
1406 // expression must have completed. We can safely release the
1407 // scarce resources.
1408 if (scarceResourcesRefCount == 0) {
1409 // iterate through the list and release them all.
1410 // note that the actual SRD is owned by the JS engine,
1411 // so we cannot delete the SRD; but we can free the
1412 // memory used by the variant in the SRD.
1413 while (ScarceResourceData *sr = scarceResources.first()) {
1414 sr->data = QVariant();
1415 scarceResources.remove(sr);
1421 Adds \a path as a directory where the engine searches for
1422 installed modules in a URL-based directory structure.
1423 The \a path may be a local filesystem directory or a URL.
1425 The newly added \a path will be first in the importPathList().
1427 \sa setImportPathList(), {QML Modules}
1429 void QQmlEngine::addImportPath(const QString& path)
1432 d->importDatabase.addImportPath(path);
1436 Returns the list of directories where the engine searches for
1437 installed modules in a URL-based directory structure.
1439 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1440 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1441 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1442 provided by that module. A \c qmldir file is required for defining the
1443 type version mapping and possibly QML extensions plugins.
1445 By default, the list contains the directory of the application executable,
1446 paths specified in the \c QML_IMPORT_PATH environment variable,
1447 and the builtin \c ImportsPath from QLibraryInfo.
1449 \sa addImportPath() setImportPathList()
1451 QStringList QQmlEngine::importPathList() const
1453 Q_D(const QQmlEngine);
1454 return d->importDatabase.importPathList();
1458 Sets \a paths as the list of directories where the engine searches for
1459 installed modules in a URL-based directory structure.
1461 By default, the list contains the directory of the application executable,
1462 paths specified in the \c QML_IMPORT_PATH environment variable,
1463 and the builtin \c ImportsPath from QLibraryInfo.
1465 \sa importPathList() addImportPath()
1467 void QQmlEngine::setImportPathList(const QStringList &paths)
1470 d->importDatabase.setImportPathList(paths);
1475 Adds \a path as a directory where the engine searches for
1476 native plugins for imported modules (referenced in the \c qmldir file).
1478 By default, the list contains only \c ., i.e. the engine searches
1479 in the directory of the \c qmldir file itself.
1481 The newly added \a path will be first in the pluginPathList().
1483 \sa setPluginPathList()
1485 void QQmlEngine::addPluginPath(const QString& path)
1488 d->importDatabase.addPluginPath(path);
1493 Returns the list of directories where the engine searches for
1494 native plugins for imported modules (referenced in the \c qmldir file).
1496 By default, the list contains only \c ., i.e. the engine searches
1497 in the directory of the \c qmldir file itself.
1499 \sa addPluginPath() setPluginPathList()
1501 QStringList QQmlEngine::pluginPathList() const
1503 Q_D(const QQmlEngine);
1504 return d->importDatabase.pluginPathList();
1508 Sets the list of directories where the engine searches for
1509 native plugins for imported modules (referenced in the \c qmldir file)
1512 By default, the list contains only \c ., i.e. the engine searches
1513 in the directory of the \c qmldir file itself.
1515 \sa pluginPathList() addPluginPath()
1517 void QQmlEngine::setPluginPathList(const QStringList &paths)
1520 d->importDatabase.setPluginPathList(paths);
1524 Imports the plugin named \a filePath with the \a uri provided.
1525 Returns true if the plugin was successfully imported; otherwise returns false.
1527 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1529 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1531 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1534 return d->importDatabase.importPlugin(filePath, uri, errors);
1538 Imports the plugin named \a filePath with the \a uri provided.
1539 Returns true if the plugin was successfully imported; otherwise returns false.
1541 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1543 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1545 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1548 QList<QQmlError> errors;
1549 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1550 if (!errors.isEmpty()) {
1552 for (int i = 0; i < errors.size(); ++i) {
1553 builtError = QString(QLatin1String("%1\n %2"))
1555 .arg(errors.at(i).toString());
1557 *errorString = builtError;
1563 \property QQmlEngine::offlineStoragePath
1564 \brief the directory for storing offline user data
1566 Returns the directory where SQL and other offline
1569 QQuickWebView and the SQL databases created with openDatabase()
1572 The default is QML/OfflineStorage in the platform-standard
1573 user application data directory.
1575 Note that the path may not currently exist on the filesystem, so
1576 callers wanting to \e create new files at this location should create
1577 it first - see QDir::mkpath().
1579 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1582 d->offlineStoragePath = dir;
1585 QString QQmlEngine::offlineStoragePath() const
1587 Q_D(const QQmlEngine);
1588 return d->offlineStoragePath;
1591 static void voidptr_destructor(void *v)
1593 void **ptr = (void **)v;
1597 static void *voidptr_constructor(const void *v)
1602 return new void*(*(void **)v);
1606 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1610 if (!mo->superClass()) {
1611 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1612 propertyCache.insert(mo, rv);
1615 QQmlPropertyCache *super = cache(mo->superClass());
1616 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1617 propertyCache.insert(mo, rv);
1622 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1625 QList<QQmlType *> types;
1627 int maxMinorVersion = 0;
1629 const QMetaObject *metaObject = type->metaObject();
1631 while (metaObject) {
1632 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1633 type->majorVersion(), minorVersion);
1635 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1641 metaObject = metaObject->superClass();
1644 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1646 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1650 QQmlPropertyCache *raw = cache(type->metaObject());
1652 bool hasCopied = false;
1654 for (int ii = 0; ii < types.count(); ++ii) {
1655 QQmlType *currentType = types.at(ii);
1659 int rev = currentType->metaObjectRevision();
1660 int moIndex = types.count() - 1 - ii;
1662 if (raw->allowedRevisionCache[moIndex] != rev) {
1667 raw->allowedRevisionCache[moIndex] = rev;
1671 // Test revision compatibility - the basic rule is:
1672 // * Anything that is excluded, cannot overload something that is not excluded *
1674 // Signals override:
1675 // * other signals and methods of the same name.
1676 // * properties named on<Signal Name>
1677 // * automatic <property name>Changed notify signals
1679 // Methods override:
1680 // * other methods of the same name
1682 // Properties override:
1683 // * other elements of the same name
1685 bool overloadError = false;
1686 QString overloadName;
1689 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1690 !overloadError && iter != raw->stringCache.end();
1693 QQmlPropertyData *d = *iter;
1694 if (raw->isAllowedInRevision(d))
1695 continue; // Not excluded - no problems
1697 // check that a regular "name" overload isn't happening
1698 QQmlPropertyData *current = d;
1699 while (!overloadError && current) {
1700 current = d->overrideData(current);
1701 if (current && raw->isAllowedInRevision(current))
1702 overloadError = true;
1707 if (overloadError) {
1708 if (hasCopied) raw->release();
1710 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."));
1714 if (!hasCopied) raw->addref();
1715 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1717 if (minorVersion != maxMinorVersion) {
1719 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1725 QQmlMetaType::ModuleApiInstance *
1726 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1728 Locker locker(this);
1730 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1732 a = new QQmlMetaType::ModuleApiInstance;
1733 a->scriptCallback = module.script;
1734 a->qobjectCallback = module.qobject;
1735 a->instanceMetaObject = module.instanceMetaObject;
1736 moduleApiInstances.insert(module, a);
1742 bool QQmlEnginePrivate::isQObject(int t)
1744 Locker locker(this);
1745 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1748 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1750 Locker locker(this);
1751 int t = v.userType();
1752 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1754 return *(QObject **)(v.constData());
1756 return QQmlMetaType::toQObject(v, ok);
1760 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1762 Locker locker(this);
1763 if (m_compositeTypes.contains(t))
1764 return QQmlMetaType::Object;
1765 else if (m_qmlLists.contains(t))
1766 return QQmlMetaType::List;
1768 return QQmlMetaType::typeCategory(t);
1771 bool QQmlEnginePrivate::isList(int t) const
1773 Locker locker(this);
1774 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1777 int QQmlEnginePrivate::listType(int t) const
1779 Locker locker(this);
1780 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1781 if (iter != m_qmlLists.end())
1784 return QQmlMetaType::listType(t);
1787 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1789 Locker locker(this);
1790 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1791 if (iter != m_compositeTypes.end()) {
1792 return (*iter)->root;
1794 QQmlType *type = QQmlMetaType::qmlType(t);
1795 return type?type->baseMetaObject():0;
1799 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1801 Locker locker(this);
1802 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1803 if (iter != m_compositeTypes.end()) {
1804 return (*iter)->root;
1806 QQmlType *type = QQmlMetaType::qmlType(t);
1807 return type?type->metaObject():0;
1811 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1813 QByteArray name = data->root->className();
1815 QByteArray ptr = name + '*';
1816 QByteArray lst = "QQmlListProperty<" + name + '>';
1818 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1819 voidptr_constructor);
1820 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1821 voidptr_constructor);
1825 Locker locker(this);
1826 m_qmlLists.insert(lst_type, ptr_type);
1827 m_compositeTypes.insert(ptr_type, data);
1830 bool QQml_isFileCaseCorrect(const QString &fileName)
1832 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1833 QFileInfo info(fileName);
1834 const QString absolute = info.absoluteFilePath();
1836 #if defined(Q_OS_MAC)
1837 const QString canonical = info.canonicalFilePath();
1838 #elif defined(Q_OS_WIN)
1839 wchar_t buffer[1024];
1841 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1842 if (rv == 0 || rv >= 1024) return true;
1843 rv = ::GetLongPathName(buffer, buffer, 1024);
1844 if (rv == 0 || rv >= 1024) return true;
1846 const QString canonical = QString::fromWCharArray(buffer);
1849 const int absoluteLength = absolute.length();
1850 const int canonicalLength = canonical.length();
1852 const int length = qMin(absoluteLength, canonicalLength);
1853 for (int ii = 0; ii < length; ++ii) {
1854 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1855 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1857 if (a.toLower() != c.toLower())
1869 \fn QQmlEngine *qmlEngine(const QObject *object)
1872 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1873 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1877 \fn QQmlContext *qmlContext(const QObject *object)
1880 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1881 QQmlEngine::contextForObject(object).