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 **)
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);
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 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
516 QDir::separator() + QLatin1String("QML") +
517 QDir::separator() + QLatin1String("OfflineStorage");
520 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
523 if (!workerScriptEngine)
524 workerScriptEngine = new QQuickWorkerScriptEngine(q);
525 return workerScriptEngine;
532 \brief The QQmlEngine class provides an environment for instantiating QML components.
535 Each QML component is instantiated in a QQmlContext.
536 QQmlContext's are essential for passing data to QML
537 components. In QML, contexts are arranged hierarchically and this
538 hierarchy is managed by the QQmlEngine.
540 Prior to creating any QML components, an application must have
541 created a QQmlEngine to gain access to a QML context. The
542 following example shows how to create a simple Text item.
546 QQmlComponent component(&engine);
547 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
548 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
550 //add item to view, etc
554 In this case, the Text item will be created in the engine's
555 \l {QQmlEngine::rootContext()}{root context}.
557 Note that the QtQuick 1 version is called QDeclarativeEngine.
559 \sa QQmlComponent QQmlContext
563 Create a new QQmlEngine with the given \a parent.
565 QQmlEngine::QQmlEngine(QObject *parent)
566 : QJSEngine(*new QQmlEnginePrivate(this), parent)
573 Destroys the QQmlEngine.
575 Any QQmlContext's created on this engine will be
576 invalidated, but not destroyed (unless they are parented to the
579 QQmlEngine::~QQmlEngine()
582 if (d->isDebugging) {
583 QQmlEngineDebugService::instance()->remEngine(this);
586 // if we are the parent of any of the qobject module api instances,
587 // we need to remove them from our internal list, in order to prevent
588 // a segfault in engine private dtor.
589 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
590 QObject *currQObjectApi = 0;
591 QQmlMetaType::ModuleApiInstance *currInstance = 0;
592 foreach (const QQmlMetaType::ModuleApi &key, keys) {
593 currInstance = d->moduleApiInstances.value(key);
594 currQObjectApi = currInstance->qobjectApi;
595 if (this->children().contains(currQObjectApi)) {
596 delete currQObjectApi;
598 d->moduleApiInstances.remove(key);
602 // ensure we clean up QObjects with JS ownership
605 if (d->incubationController)
606 d->incubationController->d = 0;
609 /*! \fn void QQmlEngine::quit()
610 This signal is emitted when the QML loaded by the engine would like to quit.
613 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
614 This signal is emitted when \a warnings messages are generated by QML.
618 Clears the engine's internal component cache.
620 This function causes the property metadata of all components previously
621 loaded by the engine to be destroyed. All previously loaded components and
622 the property bindings for all extant objects created from those components will
625 This function returns the engine to a state where it does not contain any loaded
626 component data. This may be useful in order to reload a smaller subset of the
627 previous component set, or to load a new version of a previously loaded component.
629 Once the component cache has been cleared, components must be loaded before
630 any new objects can be created.
632 void QQmlEngine::clearComponentCache()
635 d->typeLoader.clearCache();
639 Returns the engine's root context.
641 The root context is automatically created by the QQmlEngine.
642 Data that should be available to all QML component instances
643 instantiated by the engine should be put in the root context.
645 Additional data that should only be available to a subset of
646 component instances should be added to sub-contexts parented to the
649 QQmlContext *QQmlEngine::rootContext() const
651 Q_D(const QQmlEngine);
652 return d->rootContext;
656 Sets the \a factory to use for creating QNetworkAccessManager(s).
658 QNetworkAccessManager is used for all network access by QML. By
659 implementing a factory it is possible to create custom
660 QNetworkAccessManager with specialized caching, proxy and cookie
663 The factory must be set before executing the engine.
665 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
668 QMutexLocker locker(&d->mutex);
669 d->networkAccessManagerFactory = factory;
673 Returns the current QQmlNetworkAccessManagerFactory.
675 \sa setNetworkAccessManagerFactory()
677 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
679 Q_D(const QQmlEngine);
680 return d->networkAccessManagerFactory;
683 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
686 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
688 void *args[] = { 0 };
689 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
693 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
695 QMutexLocker locker(&mutex);
696 QNetworkAccessManager *nam;
697 if (networkAccessManagerFactory) {
698 nam = networkAccessManagerFactory->create(parent);
700 nam = new QNetworkAccessManager(parent);
706 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
708 Q_Q(const QQmlEngine);
709 if (!networkAccessManager)
710 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
711 return networkAccessManager;
715 Returns a common QNetworkAccessManager which can be used by any QML
716 element instantiated by this engine.
718 If a QQmlNetworkAccessManagerFactory has been set and a
719 QNetworkAccessManager has not yet been created, the
720 QQmlNetworkAccessManagerFactory will be used to create the
721 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
722 will have no proxy or cache set.
724 \sa setNetworkAccessManagerFactory()
726 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
728 Q_D(const QQmlEngine);
729 return d->getNetworkAccessManager();
734 Sets the \a provider to use for images requested via the \e
735 image: url scheme, with host \a providerId. The QQmlEngine
736 takes ownership of \a provider.
738 Image providers enable support for pixmap and threaded image
739 requests. See the QQuickImageProvider documentation for details on
740 implementing and using image providers.
742 All required image providers should be added to the engine before any
743 QML sources files are loaded.
745 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
747 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
750 QMutexLocker locker(&d->mutex);
751 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
755 Returns the image provider set for \a providerId.
757 Returns the provider if it was found; otherwise returns 0.
759 \sa QQuickImageProvider
761 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
763 Q_D(const QQmlEngine);
764 QMutexLocker locker(&d->mutex);
765 return d->imageProviders.value(providerId).data();
769 Removes the image provider for \a providerId.
771 \sa addImageProvider(), QQuickImageProvider
773 void QQmlEngine::removeImageProvider(const QString &providerId)
776 QMutexLocker locker(&d->mutex);
777 d->imageProviders.take(providerId);
781 Return the base URL for this engine. The base URL is only used to
782 resolve components when a relative URL is passed to the
783 QQmlComponent constructor.
785 If a base URL has not been explicitly set, this method returns the
786 application's current working directory.
790 QUrl QQmlEngine::baseUrl() const
792 Q_D(const QQmlEngine);
793 if (d->baseUrl.isEmpty()) {
794 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
801 Set the base URL for this engine to \a url.
805 void QQmlEngine::setBaseUrl(const QUrl &url)
812 Returns true if warning messages will be output to stderr in addition
813 to being emitted by the warnings() signal, otherwise false.
815 The default value is true.
817 bool QQmlEngine::outputWarningsToStandardError() const
819 Q_D(const QQmlEngine);
820 return d->outputWarningsToStdErr;
824 Set whether warning messages will be output to stderr to \a enabled.
826 If \a enabled is true, any warning messages generated by QML will be
827 output to stderr and emitted by the warnings() signal. If \a enabled
828 is false, on the warnings() signal will be emitted. This allows
829 applications to handle warning output themselves.
831 The default value is true.
833 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
836 d->outputWarningsToStdErr = enabled;
840 Attempt to free unused memory.
842 void QQmlEngine::collectGarbage()
848 Returns the QQmlContext for the \a object, or 0 if no
849 context has been set.
851 When the QQmlEngine instantiates a QObject, the context is
854 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
859 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
862 static_cast<QQmlData *>(priv->declarativeData);
866 else if (data->outerContext)
867 return data->outerContext->asQQmlContext();
873 Sets the QQmlContext for the \a object to \a context.
874 If the \a object already has a context, a warning is
875 output, but the context is not changed.
877 When the QQmlEngine instantiates a QObject, the context is
880 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
882 if (!object || !context)
885 QQmlData *data = QQmlData::get(object, true);
887 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
891 QQmlContextData *contextData = QQmlContextData::get(context);
892 contextData->addObject(object);
896 \enum QQmlEngine::ObjectOwnership
898 Ownership controls whether or not QML automatically destroys the
899 QObject when the object is garbage collected by the JavaScript
900 engine. The two ownership options are:
902 \value CppOwnership The object is owned by C++ code, and will
903 never be deleted by QML. The JavaScript destroy() method cannot be
904 used on objects with CppOwnership. This option is similar to
905 QScriptEngine::QtOwnership.
907 \value JavaScriptOwnership The object is owned by JavaScript.
908 When the object is returned to QML as the return value of a method
909 call or property access, QML will delete the object if there are no
910 remaining JavaScript references to it and it has no
911 QObject::parent(). This option is similar to
912 QScriptEngine::ScriptOwnership.
914 Generally an application doesn't need to set an object's ownership
915 explicitly. QML uses a heuristic to set the default object
916 ownership. By default, an object that is created by QML has
917 JavaScriptOwnership. The exception to this are the root objects
918 created by calling QQmlComponent::create() or
919 QQmlComponent::beginCreate() which have CppOwnership by
920 default. The ownership of these root-level objects is considered to
921 have been transferred to the C++ caller.
923 Objects not-created by QML have CppOwnership by default. The
924 exception to this is objects returned from a C++ method call. The
925 ownership of these objects is passed to JavaScript.
927 Calling setObjectOwnership() overrides the default ownership
928 heuristic used by QML.
932 Sets the \a ownership of \a object.
934 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
939 QQmlData *ddata = QQmlData::get(object, true);
943 ddata->indestructible = (ownership == CppOwnership)?true:false;
944 ddata->explicitIndestructibleSet = true;
948 Returns the ownership of \a object.
950 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
955 QQmlData *ddata = QQmlData::get(object, false);
959 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
962 bool QQmlEngine::event(QEvent *e)
965 if (e->type() == QEvent::User)
966 d->doDeleteInEngineThread();
968 return QJSEngine::event(e);
971 void QQmlEnginePrivate::doDeleteInEngineThread()
973 QFieldList<Deletable, &Deletable::next> list;
975 list.copyAndClear(toDeleteInEngineThread);
978 while (Deletable *d = list.takeFirst())
982 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
984 QQmlData *data = QQmlData::get(object);
986 if (data && data->deferredComponent) {
987 QQmlObjectCreatingProfiler prof;
989 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
990 prof.setTypeName(type ? type->qmlTypeName()
991 : QString::fromUtf8(object->metaObject()->className()));
992 if (data->outerContext)
993 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
995 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
997 QQmlComponentPrivate::ConstructionState state;
998 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1000 data->deferredComponent->release();
1001 data->deferredComponent = 0;
1003 QQmlComponentPrivate::complete(ep, &state);
1007 QQmlContext *qmlContext(const QObject *obj)
1009 return QQmlEngine::contextForObject(obj);
1012 QQmlEngine *qmlEngine(const QObject *obj)
1014 QQmlData *data = QQmlData::get(obj, false);
1015 if (!data || !data->context)
1017 return data->context->engine;
1020 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1022 QQmlData *data = QQmlData::get(object);
1024 return 0; // Attached properties are only on objects created by QML
1026 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1030 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1034 rv = pf(const_cast<QObject *>(object));
1037 data->attachedProperties()->insert(id, rv);
1042 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1043 const QMetaObject *attachedMetaObject, bool create)
1046 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1048 if (*idCache == -1 || !object)
1051 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1054 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1056 #ifndef QQML_NO_DEBUG_PROTOCOL
1057 if (!QQmlEnginePrivate::qml_debugging_enabled
1059 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1061 QQmlEnginePrivate::qml_debugging_enabled = true;
1066 class QQmlDataExtended {
1069 ~QQmlDataExtended();
1071 QHash<int, QObject *> attachedProperties;
1072 QQmlNotifier objectNameNotifier;
1075 QQmlDataExtended::QQmlDataExtended()
1079 QQmlDataExtended::~QQmlDataExtended()
1083 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1086 layout(endpoint->next);
1088 int index = endpoint->sourceSignal;
1089 index = qMin(index, 0xFFFF - 1);
1091 endpoint->next = notifies[index];
1092 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1093 endpoint->prev = ¬ifies[index];
1094 notifies[index] = endpoint;
1097 void QQmlData::NotifyList::layout()
1099 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1102 QQmlNotifierEndpoint **old = notifies;
1103 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1104 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1105 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1106 sizeof(QQmlNotifierEndpoint*);
1107 memset(notifies + notifiesSize, 0, memsetSize);
1109 if (notifies != old) {
1110 for (int ii = 0; ii < notifiesSize; ++ii)
1112 notifies[ii]->prev = ¬ifies[ii];
1115 notifiesSize = maximumTodoIndex + 1;
1120 maximumTodoIndex = 0;
1124 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1127 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1128 notifyList->connectionMask = 0;
1129 notifyList->maximumTodoIndex = 0;
1130 notifyList->notifiesSize = 0;
1131 notifyList->todo = 0;
1132 notifyList->notifies = 0;
1135 Q_ASSERT(!endpoint->isConnected());
1137 index = qMin(index, 0xFFFF - 1);
1138 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1140 if (index < notifyList->notifiesSize) {
1142 endpoint->next = notifyList->notifies[index];
1143 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1144 endpoint->prev = ¬ifyList->notifies[index];
1145 notifyList->notifies[index] = endpoint;
1148 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1150 endpoint->next = notifyList->todo;
1151 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1152 endpoint->prev = ¬ifyList->todo;
1153 notifyList->todo = endpoint;
1157 QQmlNotifier *QQmlData::objectNameNotifier() const
1159 if (!extendedData) extendedData = new QQmlDataExtended;
1160 return &extendedData->objectNameNotifier;
1163 QHash<int, QObject *> *QQmlData::attachedProperties() const
1165 if (!extendedData) extendedData = new QQmlDataExtended;
1166 return &extendedData->attachedProperties;
1169 void QQmlData::destroyed(QObject *object)
1171 if (deferredComponent)
1172 deferredComponent->release();
1174 if (nextContextObject)
1175 nextContextObject->prevContextObject = prevContextObject;
1176 if (prevContextObject)
1177 *prevContextObject = nextContextObject;
1179 QQmlAbstractBinding *binding = bindings;
1181 QQmlAbstractBinding *next = binding->m_nextBinding;
1182 binding->m_prevBinding = 0;
1183 binding->m_nextBinding = 0;
1188 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1189 while (signalHandler) {
1190 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1191 signalHandler->m_prevSignal = 0;
1192 signalHandler->m_nextSignal = 0;
1193 delete signalHandler;
1194 signalHandler = next;
1201 propertyCache->release();
1203 if (ownContext && context)
1207 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1208 *guard = (QObject *)0;
1209 guard->objectDestroyed(object);
1213 while (notifyList->todo)
1214 notifyList->todo->disconnect();
1215 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1216 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1219 free(notifyList->notifies);
1224 delete extendedData;
1226 v8object.Clear(); // The WeakReference handler will clean the actual handle
1232 void QQmlData::parentChanged(QObject *object, QObject *parent)
1238 void QQmlData::objectNameChanged(QObject *)
1240 if (extendedData) objectNameNotifier()->notify();
1243 bool QQmlData::hasBindingBit(int bit) const
1245 if (bindingBitsSize > bit)
1246 return bindingBits[bit / 32] & (1 << (bit % 32));
1251 void QQmlData::clearBindingBit(int bit)
1253 if (bindingBitsSize > bit)
1254 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1257 void QQmlData::setBindingBit(QObject *obj, int bit)
1259 if (bindingBitsSize <= bit) {
1260 int props = obj->metaObject()->propertyCount();
1261 Q_ASSERT(bit < props);
1263 int arraySize = (props + 31) / 32;
1264 int oldArraySize = bindingBitsSize / 32;
1266 bindingBits = (quint32 *)realloc(bindingBits,
1267 arraySize * sizeof(quint32));
1269 memset(bindingBits + oldArraySize,
1271 sizeof(quint32) * (arraySize - oldArraySize));
1273 bindingBitsSize = arraySize * 32;
1276 bindingBits[bit / 32] |= (1 << (bit % 32));
1279 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1281 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1282 if (url.authority().isEmpty())
1283 return QLatin1Char(':') + url.path();
1286 return url.toLocalFile();
1290 static QString toLocalFile(const QString &url)
1292 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1295 QString file = url.mid(7);
1297 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1299 // magic for drives on windows
1300 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1306 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1308 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1309 if (url.length() > 4)
1310 return QLatin1Char(':') + url.mid(4);
1314 return toLocalFile(url);
1317 void QQmlEnginePrivate::sendQuit()
1321 if (q->receivers(SIGNAL(quit())) == 0) {
1322 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1326 static void dumpwarning(const QQmlError &error)
1328 qWarning().nospace() << qPrintable(error.toString());
1331 static void dumpwarning(const QList<QQmlError> &errors)
1333 for (int ii = 0; ii < errors.count(); ++ii)
1334 dumpwarning(errors.at(ii));
1337 void QQmlEnginePrivate::warning(const QQmlError &error)
1340 q->warnings(QList<QQmlError>() << error);
1341 if (outputWarningsToStdErr)
1345 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1348 q->warnings(errors);
1349 if (outputWarningsToStdErr)
1350 dumpwarning(errors);
1353 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1356 QQmlEnginePrivate::get(engine)->warning(error);
1361 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1364 QQmlEnginePrivate::get(engine)->warning(error);
1369 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1372 engine->warning(error);
1377 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1380 engine->warning(error);
1386 This function should be called prior to evaluation of any js expression,
1387 so that scarce resources are not freed prematurely (eg, if there is a
1388 nested javascript expression).
1390 void QQmlEnginePrivate::referenceScarceResources()
1392 scarceResourcesRefCount += 1;
1396 This function should be called after evaluation of the js expression is
1397 complete, and so the scarce resources may be freed safely.
1399 void QQmlEnginePrivate::dereferenceScarceResources()
1401 Q_ASSERT(scarceResourcesRefCount > 0);
1402 scarceResourcesRefCount -= 1;
1404 // if the refcount is zero, then evaluation of the "top level"
1405 // expression must have completed. We can safely release the
1406 // scarce resources.
1407 if (scarceResourcesRefCount == 0) {
1408 // iterate through the list and release them all.
1409 // note that the actual SRD is owned by the JS engine,
1410 // so we cannot delete the SRD; but we can free the
1411 // memory used by the variant in the SRD.
1412 while (ScarceResourceData *sr = scarceResources.first()) {
1413 sr->data = QVariant();
1414 scarceResources.remove(sr);
1420 Adds \a path as a directory where the engine searches for
1421 installed modules in a URL-based directory structure.
1422 The \a path may be a local filesystem directory or a URL.
1424 The newly added \a path will be first in the importPathList().
1426 \sa setImportPathList(), {QML Modules}
1428 void QQmlEngine::addImportPath(const QString& path)
1431 d->importDatabase.addImportPath(path);
1435 Returns the list of directories where the engine searches for
1436 installed modules in a URL-based directory structure.
1438 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1439 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1440 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1441 provided by that module. A \c qmldir file is required for defining the
1442 type version mapping and possibly QML extensions plugins.
1444 By default, the list contains the directory of the application executable,
1445 paths specified in the \c QML_IMPORT_PATH environment variable,
1446 and the builtin \c ImportsPath from QLibraryInfo.
1448 \sa addImportPath() setImportPathList()
1450 QStringList QQmlEngine::importPathList() const
1452 Q_D(const QQmlEngine);
1453 return d->importDatabase.importPathList();
1457 Sets \a paths as the list of directories where the engine searches for
1458 installed modules in a URL-based directory structure.
1460 By default, the list contains the directory of the application executable,
1461 paths specified in the \c QML_IMPORT_PATH environment variable,
1462 and the builtin \c ImportsPath from QLibraryInfo.
1464 \sa importPathList() addImportPath()
1466 void QQmlEngine::setImportPathList(const QStringList &paths)
1469 d->importDatabase.setImportPathList(paths);
1474 Adds \a path as a directory where the engine searches for
1475 native plugins for imported modules (referenced in the \c qmldir file).
1477 By default, the list contains only \c ., i.e. the engine searches
1478 in the directory of the \c qmldir file itself.
1480 The newly added \a path will be first in the pluginPathList().
1482 \sa setPluginPathList()
1484 void QQmlEngine::addPluginPath(const QString& path)
1487 d->importDatabase.addPluginPath(path);
1492 Returns the list of directories where the engine searches for
1493 native plugins for imported modules (referenced in the \c qmldir file).
1495 By default, the list contains only \c ., i.e. the engine searches
1496 in the directory of the \c qmldir file itself.
1498 \sa addPluginPath() setPluginPathList()
1500 QStringList QQmlEngine::pluginPathList() const
1502 Q_D(const QQmlEngine);
1503 return d->importDatabase.pluginPathList();
1507 Sets the list of directories where the engine searches for
1508 native plugins for imported modules (referenced in the \c qmldir file)
1511 By default, the list contains only \c ., i.e. the engine searches
1512 in the directory of the \c qmldir file itself.
1514 \sa pluginPathList() addPluginPath()
1516 void QQmlEngine::setPluginPathList(const QStringList &paths)
1519 d->importDatabase.setPluginPathList(paths);
1523 Imports the plugin named \a filePath with the \a uri provided.
1524 Returns true if the plugin was successfully imported; otherwise returns false.
1526 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1528 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1530 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1533 return d->importDatabase.importPlugin(filePath, uri, errors);
1537 Imports the plugin named \a filePath with the \a uri provided.
1538 Returns true if the plugin was successfully imported; otherwise returns false.
1540 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1542 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1544 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1547 QList<QQmlError> errors;
1548 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1549 if (!errors.isEmpty()) {
1551 for (int i = 0; i < errors.size(); ++i) {
1552 builtError = QString(QLatin1String("%1\n %2"))
1554 .arg(errors.at(i).toString());
1556 *errorString = builtError;
1562 \property QQmlEngine::offlineStoragePath
1563 \brief the directory for storing offline user data
1565 Returns the directory where SQL and other offline
1568 QQuickWebView and the SQL databases created with openDatabase()
1571 The default is QML/OfflineStorage in the platform-standard
1572 user application data directory.
1574 Note that the path may not currently exist on the filesystem, so
1575 callers wanting to \e create new files at this location should create
1576 it first - see QDir::mkpath().
1578 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1581 d->offlineStoragePath = dir;
1584 QString QQmlEngine::offlineStoragePath() const
1586 Q_D(const QQmlEngine);
1587 return d->offlineStoragePath;
1590 static void voidptr_destructor(void *v)
1592 void **ptr = (void **)v;
1596 static void *voidptr_constructor(const void *v)
1601 return new void*(*(void **)v);
1605 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1609 if (!mo->superClass()) {
1610 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1611 propertyCache.insert(mo, rv);
1614 QQmlPropertyCache *super = cache(mo->superClass());
1615 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1616 propertyCache.insert(mo, rv);
1621 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1624 QList<QQmlType *> types;
1626 int maxMinorVersion = 0;
1628 const QMetaObject *metaObject = type->metaObject();
1630 while (metaObject) {
1631 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1632 type->majorVersion(), minorVersion);
1634 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1640 metaObject = metaObject->superClass();
1643 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1645 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1649 QQmlPropertyCache *raw = cache(type->metaObject());
1651 bool hasCopied = false;
1653 for (int ii = 0; ii < types.count(); ++ii) {
1654 QQmlType *currentType = types.at(ii);
1658 int rev = currentType->metaObjectRevision();
1659 int moIndex = types.count() - 1 - ii;
1661 if (raw->allowedRevisionCache[moIndex] != rev) {
1666 raw->allowedRevisionCache[moIndex] = rev;
1670 // Test revision compatibility - the basic rule is:
1671 // * Anything that is excluded, cannot overload something that is not excluded *
1673 // Signals override:
1674 // * other signals and methods of the same name.
1675 // * properties named on<Signal Name>
1676 // * automatic <property name>Changed notify signals
1678 // Methods override:
1679 // * other methods of the same name
1681 // Properties override:
1682 // * other elements of the same name
1684 bool overloadError = false;
1685 QString overloadName;
1688 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1689 !overloadError && iter != raw->stringCache.end();
1692 QQmlPropertyData *d = *iter;
1693 if (raw->isAllowedInRevision(d))
1694 continue; // Not excluded - no problems
1696 // check that a regular "name" overload isn't happening
1697 QQmlPropertyData *current = d;
1698 while (!overloadError && current) {
1699 current = d->overrideData(current);
1700 if (current && raw->isAllowedInRevision(current))
1701 overloadError = true;
1706 if (overloadError) {
1707 if (hasCopied) raw->release();
1709 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."));
1713 if (!hasCopied) raw->addref();
1714 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1716 if (minorVersion != maxMinorVersion) {
1718 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1724 QQmlMetaType::ModuleApiInstance *
1725 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1727 Locker locker(this);
1729 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1731 a = new QQmlMetaType::ModuleApiInstance;
1732 a->scriptCallback = module.script;
1733 a->qobjectCallback = module.qobject;
1734 a->instanceMetaObject = module.instanceMetaObject;
1735 moduleApiInstances.insert(module, a);
1741 bool QQmlEnginePrivate::isQObject(int t)
1743 Locker locker(this);
1744 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1747 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1749 Locker locker(this);
1750 int t = v.userType();
1751 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1753 return *(QObject **)(v.constData());
1755 return QQmlMetaType::toQObject(v, ok);
1759 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1761 Locker locker(this);
1762 if (m_compositeTypes.contains(t))
1763 return QQmlMetaType::Object;
1764 else if (m_qmlLists.contains(t))
1765 return QQmlMetaType::List;
1767 return QQmlMetaType::typeCategory(t);
1770 bool QQmlEnginePrivate::isList(int t) const
1772 Locker locker(this);
1773 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1776 int QQmlEnginePrivate::listType(int t) const
1778 Locker locker(this);
1779 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1780 if (iter != m_qmlLists.end())
1783 return QQmlMetaType::listType(t);
1786 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1788 Locker locker(this);
1789 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1790 if (iter != m_compositeTypes.end()) {
1791 return (*iter)->root;
1793 QQmlType *type = QQmlMetaType::qmlType(t);
1794 return type?type->baseMetaObject():0;
1798 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1800 Locker locker(this);
1801 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1802 if (iter != m_compositeTypes.end()) {
1803 return (*iter)->root;
1805 QQmlType *type = QQmlMetaType::qmlType(t);
1806 return type?type->metaObject():0;
1810 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1812 QByteArray name = data->root->className();
1814 QByteArray ptr = name + '*';
1815 QByteArray lst = "QQmlListProperty<" + name + '>';
1817 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1818 voidptr_constructor);
1819 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1820 voidptr_constructor);
1824 Locker locker(this);
1825 m_qmlLists.insert(lst_type, ptr_type);
1826 m_compositeTypes.insert(ptr_type, data);
1829 bool QQml_isFileCaseCorrect(const QString &fileName)
1831 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1832 QFileInfo info(fileName);
1833 const QString absolute = info.absoluteFilePath();
1835 #if defined(Q_OS_MAC)
1836 const QString canonical = info.canonicalFilePath();
1837 #elif defined(Q_OS_WIN)
1838 wchar_t buffer[1024];
1840 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1841 if (rv == 0 || rv >= 1024) return true;
1842 rv = ::GetLongPathName(buffer, buffer, 1024);
1843 if (rv == 0 || rv >= 1024) return true;
1845 const QString canonical = QString::fromWCharArray(buffer);
1848 const int absoluteLength = absolute.length();
1849 const int canonicalLength = canonical.length();
1851 const int length = qMin(absoluteLength, canonicalLength);
1852 for (int ii = 0; ii < length; ++ii) {
1853 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1854 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1856 if (a.toLower() != c.toLower())
1868 \fn QQmlEngine *qmlEngine(const QObject *object)
1871 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1872 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1876 \fn QQmlContext *qmlContext(const QObject *object)
1879 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1880 QQmlEngine::contextForObject(object).