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 "qqmlimageprovider.h"
63 #include "qqmldirparser_p.h"
64 #include "qqmlextensioninterface.h"
65 #include "qqmllist_p.h"
66 #include "qqmltypenamecache_p.h"
67 #include "qqmlnotifier_p.h"
68 #include <private/qqmlprofilerservice_p.h>
69 #include <private/qquickapplication_p.h>
70 #include <private/qv8debugservice_p.h>
71 #include <private/qdebugmessageservice_p.h>
72 #include "qqmlincubator.h"
73 #include <private/qv8profilerservice_p.h>
74 #include <private/qqmlboundsignal_p.h>
76 #include <QtCore/qstandardpaths.h>
77 #include <QtCore/qsettings.h>
79 #include <QtCore/qmetaobject.h>
80 #include <QNetworkAccessManager>
82 #include <QMetaObject>
83 #include <QtCore/qcoreapplication.h>
84 #include <QtCore/qdir.h>
85 #include <QtCore/qmutex.h>
86 #include <QtNetwork/qnetworkconfigmanager.h>
88 #include <private/qobject_p.h>
90 #include <private/qqmllocale_p.h>
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
97 #define CSIDL_APPDATA 0x001a // <username>\Application Data
100 Q_DECLARE_METATYPE(QQmlProperty)
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
106 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
111 \qmlclass QtObject QObject
112 \ingroup qml-utility-elements
114 \brief The QtObject element is the most basic element in QML.
116 The QtObject element is a non-visual element which contains only the
119 It can be useful to create a QtObject if you need an extremely
120 lightweight element to enclose a set of custom properties:
122 \snippet doc/src/snippets/qml/qtobject.qml 0
124 It can also be useful for C++ integration, as it is just a plain
125 QObject. See the QObject documentation for further details.
128 \qmlproperty string QtObject::objectName
129 This property holds the QObject::objectName for this specific object instance.
131 This allows a C++ application to locate an item within a QML component
132 using the QObject::findChild() method. For example, the following C++
133 application locates the child \l Rectangle item and dynamically changes its
142 width: 200; height: 200
156 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
159 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
161 item->setProperty("color", QColor(Qt::yellow));
165 bool QQmlEnginePrivate::qml_debugging_enabled = false;
167 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
169 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
170 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
171 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
172 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
173 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
176 void QQmlEnginePrivate::defineModule()
178 registerBaseTypes("QtQuick", 2, 0);
179 qmlRegisterUncreatableType<QQuickApplication>("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class"));
180 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
184 \qmlclass Qt QQmlEnginePrivate
185 \ingroup qml-utility-elements
186 \brief The QML global Qt object provides useful enums and functions from Qt.
188 \keyword QmlGlobalQtObject
190 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
192 The \c Qt object is a global object with utility functions, properties and enums.
194 It is not instantiable; to use it, call the members of the global \c Qt object directly.
201 color: Qt.rgba(1, 0, 0, 1)
202 text: Qt.md5("hello, world")
209 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
210 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
214 The Qt object also contains helper functions for creating objects of specific
215 data types. This is primarily useful when setting the properties of an item
216 when the property has one of the following types:
219 \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()}
220 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
221 \li \c point - use \l{Qt::point()}{Qt.point()}
222 \li \c size - use \l{Qt::size()}{Qt.size()}
223 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
226 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
228 \section1 Date/Time Formatters
230 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
233 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
234 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
235 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
238 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
241 \section1 Dynamic Object Creation
242 The following functions on the global object allow you to dynamically create QML
243 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
247 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
248 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
254 \qmlproperty object Qt::application
257 The \c application object provides access to global application state
258 properties shared by many QML components.
264 \li \c application.active
266 This read-only property indicates whether the application is the top-most and focused
267 application, and the user is able to interact with the application. The property
268 is false when the application is in the background, the device keylock or screen
269 saver is active, the screen backlight is turned off, or the global system dialog
270 is being displayed on top of the application. It can be used for stopping and
271 pausing animations, timers and active processing of data in order to save device
272 battery power and free device memory and processor load when the application is not
276 \li \c application.layoutDirection
278 This read-only property can be used to query the default layout direction of the
279 application. On system start-up, the default layout direction depends on the
280 application's language. The property has a value of \c Qt.RightToLeft in locales
281 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
282 where the reading direction flows from left to right. You can bind to this
283 property to customize your application layouts to support both layout directions.
288 \li Qt.LeftToRight - Text and graphics elements should be positioned
290 \li Qt.RightToLeft - Text and graphics elements should be positioned
295 \li \c application.inputPanel
297 This read-only property allows access to application's QInputPanel object
298 and all its properties and slots. See the QInputPanel documentation for
299 further details. Deprecated in favor of Qt.InputMethod
302 The following example uses the \c application object to indicate
303 whether the application is currently active:
305 \snippet doc/src/snippets/qml/application.qml document
307 \qmlproperty object Qt::inputMethod
310 The \c inputMethod object allows access to application's QInputMethod object
311 and all its properties and slots. See the QInputMethod documentation for
317 \qmlmethod object Qt::include(string url, jsobject callback)
319 Includes another JavaScript file. This method can only be used from within JavaScript files,
320 and not regular QML files.
322 This imports all functions from \a url into the current script's namespace.
324 Qt.include() returns an object that describes the status of the operation. The object has
325 a single property, \c {status}, that is set to one of the following values:
328 \header \li Symbol \li Value \li Description
329 \row \li result.OK \li 0 \li The include completed successfully.
330 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
331 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
332 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
333 An additional \c exception property will be set in this case.
336 The \c status property will be updated as the operation progresses.
338 If provided, \a callback is invoked when the operation completes. The callback is passed
339 the same object as is returned from the Qt.include() call.
341 // Qt.include() is implemented in qv8include.cpp
344 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
345 : propertyCapture(0), rootContext(0), isDebugging(false),
346 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
347 cleanup(0), erroredBindings(0), inProgressCreations(0),
348 workerScriptEngine(0), activeVME(0),
349 networkAccessManager(0), networkAccessManagerFactory(0),
350 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
351 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
355 QQmlEnginePrivate::~QQmlEnginePrivate()
357 if (inProgressCreations)
358 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
361 QQmlCleanup *c = cleanup;
363 if (cleanup) cleanup->prev = &cleanup;
369 doDeleteInEngineThread();
371 if (incubationController) incubationController->d = 0;
372 incubationController = 0;
377 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
379 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
381 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
383 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
384 delete (*iter)->qobjectApi;
389 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
391 QObjectPrivate *p = QObjectPrivate::get(o);
392 if (p->declarativeData) {
393 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
394 if (d->ownContext && d->context) {
395 d->context->destroy();
401 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
403 static_cast<QQmlData *>(d)->destroyed(o);
406 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
408 static_cast<QQmlData *>(d)->parentChanged(o, p);
411 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
413 static_cast<QQmlData *>(d)->objectNameChanged(o);
416 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
418 QQmlData *ddata = QQmlData::get(object, false);
419 if (!ddata) return; // Probably being deleted
421 QQmlNotifierEndpoint *ep = ddata->notify(index);
422 if (ep) QQmlNotifier::emitNotify(ep);
425 void QQmlEnginePrivate::init()
429 static bool firstTime = true;
431 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
436 qRegisterMetaType<QVariant>("QVariant");
437 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
438 qRegisterMetaType<QJSValue>("QJSValue");
439 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
440 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
441 qRegisterMetaType<QList<int> >("QList<int>");
442 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
446 v8engine()->setEngine(q);
448 rootContext = new QQmlContext(q,true);
450 if (QCoreApplication::instance()->thread() == q->thread() &&
451 QQmlEngineDebugService::isDebuggingEnabled()) {
453 QQmlEngineDebugService::instance()->addEngine(q);
454 QV8DebugService::initialize(v8engine());
455 QV8ProfilerService::initialize();
456 QQmlProfilerService::initialize();
457 QDebugMessageService::instance();
460 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
461 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
462 QDir::separator() + QLatin1String("QML") +
463 QDir::separator() + QLatin1String("OfflineStorage");
466 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
469 if (!workerScriptEngine)
470 workerScriptEngine = new QQuickWorkerScriptEngine(q);
471 return workerScriptEngine;
477 \brief The QQmlEngine class provides an environment for instantiating QML components.
480 Each QML component is instantiated in a QQmlContext.
481 QQmlContext's are essential for passing data to QML
482 components. In QML, contexts are arranged hierarchically and this
483 hierarchy is managed by the QQmlEngine.
485 Prior to creating any QML components, an application must have
486 created a QQmlEngine to gain access to a QML context. The
487 following example shows how to create a simple Text item.
491 QQmlComponent component(&engine);
492 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
493 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
495 //add item to view, etc
499 In this case, the Text item will be created in the engine's
500 \l {QQmlEngine::rootContext()}{root context}.
502 \sa QQmlComponent QQmlContext
506 Create a new QQmlEngine with the given \a parent.
508 QQmlEngine::QQmlEngine(QObject *parent)
509 : QJSEngine(*new QQmlEnginePrivate(this), parent)
516 Destroys the QQmlEngine.
518 Any QQmlContext's created on this engine will be
519 invalidated, but not destroyed (unless they are parented to the
522 QQmlEngine::~QQmlEngine()
525 if (d->isDebugging) {
526 QQmlEngineDebugService::instance()->remEngine(this);
529 // if we are the parent of any of the qobject module api instances,
530 // we need to remove them from our internal list, in order to prevent
531 // a segfault in engine private dtor.
532 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
533 QObject *currQObjectApi = 0;
534 QQmlMetaType::ModuleApiInstance *currInstance = 0;
535 foreach (const QQmlMetaType::ModuleApi &key, keys) {
536 currInstance = d->moduleApiInstances.value(key);
537 currQObjectApi = currInstance->qobjectApi;
538 if (this->children().contains(currQObjectApi)) {
539 delete currQObjectApi;
541 d->moduleApiInstances.remove(key);
545 // ensure we clean up QObjects with JS ownership
548 if (d->incubationController)
549 d->incubationController->d = 0;
552 /*! \fn void QQmlEngine::quit()
553 This signal is emitted when the QML loaded by the engine would like to quit.
556 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
557 This signal is emitted when \a warnings messages are generated by QML.
561 Clears the engine's internal component cache.
563 Normally the QQmlEngine caches components loaded from qml
564 files. This method clears this cache and forces the component to be
567 void QQmlEngine::clearComponentCache()
570 d->typeLoader.clearCache();
574 Returns the engine's root context.
576 The root context is automatically created by the QQmlEngine.
577 Data that should be available to all QML component instances
578 instantiated by the engine should be put in the root context.
580 Additional data that should only be available to a subset of
581 component instances should be added to sub-contexts parented to the
584 QQmlContext *QQmlEngine::rootContext() const
586 Q_D(const QQmlEngine);
587 return d->rootContext;
591 Sets the \a factory to use for creating QNetworkAccessManager(s).
593 QNetworkAccessManager is used for all network access by QML. By
594 implementing a factory it is possible to create custom
595 QNetworkAccessManager with specialized caching, proxy and cookie
598 The factory must be set before executing the engine.
600 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
603 QMutexLocker locker(&d->mutex);
604 d->networkAccessManagerFactory = factory;
608 Returns the current QQmlNetworkAccessManagerFactory.
610 \sa setNetworkAccessManagerFactory()
612 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
614 Q_D(const QQmlEngine);
615 return d->networkAccessManagerFactory;
618 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
621 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
623 void *args[] = { 0 };
624 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
628 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
630 QMutexLocker locker(&mutex);
631 QNetworkAccessManager *nam;
632 if (networkAccessManagerFactory) {
633 nam = networkAccessManagerFactory->create(parent);
635 nam = new QNetworkAccessManager(parent);
641 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
643 Q_Q(const QQmlEngine);
644 if (!networkAccessManager)
645 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
646 return networkAccessManager;
650 Returns a common QNetworkAccessManager which can be used by any QML
651 element instantiated by this engine.
653 If a QQmlNetworkAccessManagerFactory has been set and a
654 QNetworkAccessManager has not yet been created, the
655 QQmlNetworkAccessManagerFactory will be used to create the
656 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
657 will have no proxy or cache set.
659 \sa setNetworkAccessManagerFactory()
661 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
663 Q_D(const QQmlEngine);
664 return d->getNetworkAccessManager();
669 Sets the \a provider to use for images requested via the \e
670 image: url scheme, with host \a providerId. The QQmlEngine
671 takes ownership of \a provider.
673 Image providers enable support for pixmap and threaded image
674 requests. See the QQmlImageProvider documentation for details on
675 implementing and using image providers.
677 All required image providers should be added to the engine before any
678 QML sources files are loaded.
680 \sa removeImageProvider()
682 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProvider *provider)
685 QMutexLocker locker(&d->mutex);
686 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProvider>(provider));
690 Returns the QQmlImageProvider set for \a providerId.
692 Returns the provider if it was found; otherwise returns 0.
694 QQmlImageProvider *QQmlEngine::imageProvider(const QString &providerId) const
696 Q_D(const QQmlEngine);
697 QMutexLocker locker(&d->mutex);
698 return d->imageProviders.value(providerId).data();
702 Removes the QQmlImageProvider for \a providerId.
704 \sa addImageProvider()
706 void QQmlEngine::removeImageProvider(const QString &providerId)
709 QMutexLocker locker(&d->mutex);
710 d->imageProviders.take(providerId);
713 QQmlImageProvider::ImageType QQmlEnginePrivate::getImageProviderType(const QUrl &url)
715 QMutexLocker locker(&mutex);
716 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
719 return provider->imageType();
720 return QQmlImageProvider::Invalid;
723 QQuickTextureFactory *QQmlEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
725 QMutexLocker locker(&mutex);
726 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
729 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
730 return provider->requestTexture(imageId, size, req_size);
735 QImage QQmlEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
737 QMutexLocker locker(&mutex);
739 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
742 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
743 image = provider->requestImage(imageId, size, req_size);
748 QPixmap QQmlEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
750 QMutexLocker locker(&mutex);
752 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
755 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
756 pixmap = provider->requestPixmap(imageId, size, req_size);
762 Return the base URL for this engine. The base URL is only used to
763 resolve components when a relative URL is passed to the
764 QQmlComponent constructor.
766 If a base URL has not been explicitly set, this method returns the
767 application's current working directory.
771 QUrl QQmlEngine::baseUrl() const
773 Q_D(const QQmlEngine);
774 if (d->baseUrl.isEmpty()) {
775 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
782 Set the base URL for this engine to \a url.
786 void QQmlEngine::setBaseUrl(const QUrl &url)
793 Returns true if warning messages will be output to stderr in addition
794 to being emitted by the warnings() signal, otherwise false.
796 The default value is true.
798 bool QQmlEngine::outputWarningsToStandardError() const
800 Q_D(const QQmlEngine);
801 return d->outputWarningsToStdErr;
805 Set whether warning messages will be output to stderr to \a enabled.
807 If \a enabled is true, any warning messages generated by QML will be
808 output to stderr and emitted by the warnings() signal. If \a enabled
809 is false, on the warnings() signal will be emitted. This allows
810 applications to handle warning output themselves.
812 The default value is true.
814 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
817 d->outputWarningsToStdErr = enabled;
821 Attempt to free unused memory.
823 void QQmlEngine::collectGarbage()
829 Returns the QQmlContext for the \a object, or 0 if no
830 context has been set.
832 When the QQmlEngine instantiates a QObject, the context is
835 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
840 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
843 static_cast<QQmlData *>(priv->declarativeData);
847 else if (data->outerContext)
848 return data->outerContext->asQQmlContext();
854 Sets the QQmlContext for the \a object to \a context.
855 If the \a object already has a context, a warning is
856 output, but the context is not changed.
858 When the QQmlEngine instantiates a QObject, the context is
861 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
863 if (!object || !context)
866 QQmlData *data = QQmlData::get(object, true);
868 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
872 QQmlContextData *contextData = QQmlContextData::get(context);
873 contextData->addObject(object);
877 \enum QQmlEngine::ObjectOwnership
879 Ownership controls whether or not QML automatically destroys the
880 QObject when the object is garbage collected by the JavaScript
881 engine. The two ownership options are:
883 \value CppOwnership The object is owned by C++ code, and will
884 never be deleted by QML. The JavaScript destroy() method cannot be
885 used on objects with CppOwnership. This option is similar to
886 QScriptEngine::QtOwnership.
888 \value JavaScriptOwnership The object is owned by JavaScript.
889 When the object is returned to QML as the return value of a method
890 call or property access, QML will delete the object if there are no
891 remaining JavaScript references to it and it has no
892 QObject::parent(). This option is similar to
893 QScriptEngine::ScriptOwnership.
895 Generally an application doesn't need to set an object's ownership
896 explicitly. QML uses a heuristic to set the default object
897 ownership. By default, an object that is created by QML has
898 JavaScriptOwnership. The exception to this are the root objects
899 created by calling QQmlComponent::create() or
900 QQmlComponent::beginCreate() which have CppOwnership by
901 default. The ownership of these root-level objects is considered to
902 have been transferred to the C++ caller.
904 Objects not-created by QML have CppOwnership by default. The
905 exception to this is objects returned from a C++ method call. The
906 ownership of these objects is passed to JavaScript.
908 Calling setObjectOwnership() overrides the default ownership
909 heuristic used by QML.
913 Sets the \a ownership of \a object.
915 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
920 QQmlData *ddata = QQmlData::get(object, true);
924 ddata->indestructible = (ownership == CppOwnership)?true:false;
925 ddata->explicitIndestructibleSet = true;
929 Returns the ownership of \a object.
931 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
936 QQmlData *ddata = QQmlData::get(object, false);
940 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
943 bool QQmlEngine::event(QEvent *e)
946 if (e->type() == QEvent::User)
947 d->doDeleteInEngineThread();
949 return QJSEngine::event(e);
952 void QQmlEnginePrivate::doDeleteInEngineThread()
954 QFieldList<Deletable, &Deletable::next> list;
956 list.copyAndClear(toDeleteInEngineThread);
959 while (Deletable *d = list.takeFirst())
963 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
965 QQmlData *data = QQmlData::get(object);
967 if (data && data->deferredComponent) {
968 QQmlObjectCreatingProfiler prof;
970 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
971 prof.setTypeName(type ? type->qmlTypeName()
972 : QString::fromUtf8(object->metaObject()->className()));
973 if (data->outerContext)
974 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
976 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
978 QQmlComponentPrivate::ConstructionState state;
979 QQmlComponentPrivate::beginDeferred(ep, object, &state);
981 data->deferredComponent->release();
982 data->deferredComponent = 0;
984 QQmlComponentPrivate::complete(ep, &state);
988 QQmlContext *qmlContext(const QObject *obj)
990 return QQmlEngine::contextForObject(obj);
993 QQmlEngine *qmlEngine(const QObject *obj)
995 QQmlData *data = QQmlData::get(obj, false);
996 if (!data || !data->context)
998 return data->context->engine;
1001 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1003 QQmlData *data = QQmlData::get(object);
1005 return 0; // Attached properties are only on objects created by QML
1007 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1011 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1015 rv = pf(const_cast<QObject *>(object));
1018 data->attachedProperties()->insert(id, rv);
1023 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1024 const QMetaObject *attachedMetaObject, bool create)
1027 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1029 if (*idCache == -1 || !object)
1032 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1035 QQmlDebuggingEnabler::QQmlDebuggingEnabler()
1037 #ifndef QQML_NO_DEBUG_PROTOCOL
1038 if (!QQmlEnginePrivate::qml_debugging_enabled) {
1039 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1041 QQmlEnginePrivate::qml_debugging_enabled = true;
1046 class QQmlDataExtended {
1049 ~QQmlDataExtended();
1051 QHash<int, QObject *> attachedProperties;
1052 QQmlNotifier objectNameNotifier;
1055 QQmlDataExtended::QQmlDataExtended()
1059 QQmlDataExtended::~QQmlDataExtended()
1063 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1066 layout(endpoint->next);
1068 int index = endpoint->sourceSignal;
1069 index = qMin(index, 0xFFFF - 1);
1071 endpoint->next = notifies[index];
1072 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1073 endpoint->prev = ¬ifies[index];
1074 notifies[index] = endpoint;
1077 void QQmlData::NotifyList::layout()
1079 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1082 QQmlNotifierEndpoint **old = notifies;
1083 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1084 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1085 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1086 sizeof(QQmlNotifierEndpoint*);
1087 memset(notifies + notifiesSize, 0, memsetSize);
1089 if (notifies != old) {
1090 for (int ii = 0; ii < notifiesSize; ++ii)
1092 notifies[ii]->prev = ¬ifies[ii];
1095 notifiesSize = maximumTodoIndex + 1;
1100 maximumTodoIndex = 0;
1104 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1107 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1108 notifyList->connectionMask = 0;
1109 notifyList->maximumTodoIndex = 0;
1110 notifyList->notifiesSize = 0;
1111 notifyList->todo = 0;
1112 notifyList->notifies = 0;
1115 Q_ASSERT(!endpoint->isConnected());
1117 index = qMin(index, 0xFFFF - 1);
1118 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1120 if (index < notifyList->notifiesSize) {
1122 endpoint->next = notifyList->notifies[index];
1123 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1124 endpoint->prev = ¬ifyList->notifies[index];
1125 notifyList->notifies[index] = endpoint;
1128 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1130 endpoint->next = notifyList->todo;
1131 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1132 endpoint->prev = ¬ifyList->todo;
1133 notifyList->todo = endpoint;
1137 QQmlNotifier *QQmlData::objectNameNotifier() const
1139 if (!extendedData) extendedData = new QQmlDataExtended;
1140 return &extendedData->objectNameNotifier;
1143 QHash<int, QObject *> *QQmlData::attachedProperties() const
1145 if (!extendedData) extendedData = new QQmlDataExtended;
1146 return &extendedData->attachedProperties;
1149 void QQmlData::destroyed(QObject *object)
1151 if (deferredComponent)
1152 deferredComponent->release();
1154 if (nextContextObject)
1155 nextContextObject->prevContextObject = prevContextObject;
1156 if (prevContextObject)
1157 *prevContextObject = nextContextObject;
1159 QQmlAbstractBinding *binding = bindings;
1161 QQmlAbstractBinding *next = binding->m_nextBinding;
1162 binding->m_prevBinding = 0;
1163 binding->m_nextBinding = 0;
1168 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1169 while (signalHandler) {
1170 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1171 signalHandler->m_prevSignal = 0;
1172 signalHandler->m_nextSignal = 0;
1173 delete signalHandler;
1174 signalHandler = next;
1181 propertyCache->release();
1183 if (ownContext && context)
1187 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1188 *guard = (QObject *)0;
1189 guard->objectDestroyed(object);
1193 while (notifyList->todo)
1194 notifyList->todo->disconnect();
1195 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1196 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1199 free(notifyList->notifies);
1204 delete extendedData;
1206 v8object.Clear(); // The WeakReference handler will clean the actual handle
1212 void QQmlData::parentChanged(QObject *object, QObject *parent)
1218 void QQmlData::objectNameChanged(QObject *)
1220 if (extendedData) objectNameNotifier()->notify();
1223 bool QQmlData::hasBindingBit(int bit) const
1225 if (bindingBitsSize > bit)
1226 return bindingBits[bit / 32] & (1 << (bit % 32));
1231 void QQmlData::clearBindingBit(int bit)
1233 if (bindingBitsSize > bit)
1234 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1237 void QQmlData::setBindingBit(QObject *obj, int bit)
1239 if (bindingBitsSize <= bit) {
1240 int props = obj->metaObject()->propertyCount();
1241 Q_ASSERT(bit < props);
1243 int arraySize = (props + 31) / 32;
1244 int oldArraySize = bindingBitsSize / 32;
1246 bindingBits = (quint32 *)realloc(bindingBits,
1247 arraySize * sizeof(quint32));
1249 memset(bindingBits + oldArraySize,
1251 sizeof(quint32) * (arraySize - oldArraySize));
1253 bindingBitsSize = arraySize * 32;
1256 bindingBits[bit / 32] |= (1 << (bit % 32));
1259 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1261 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1262 if (url.authority().isEmpty())
1263 return QLatin1Char(':') + url.path();
1266 return url.toLocalFile();
1270 static QString toLocalFile(const QString &url)
1272 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1275 QString file = url.mid(7);
1277 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1279 // magic for drives on windows
1280 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1286 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1288 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1289 if (url.length() > 4)
1290 return QLatin1Char(':') + url.mid(4);
1294 return toLocalFile(url);
1297 void QQmlEnginePrivate::sendQuit()
1301 if (q->receivers(SIGNAL(quit())) == 0) {
1302 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1306 static void dumpwarning(const QQmlError &error)
1308 qWarning().nospace() << qPrintable(error.toString());
1311 static void dumpwarning(const QList<QQmlError> &errors)
1313 for (int ii = 0; ii < errors.count(); ++ii)
1314 dumpwarning(errors.at(ii));
1317 void QQmlEnginePrivate::warning(const QQmlError &error)
1320 q->warnings(QList<QQmlError>() << error);
1321 if (outputWarningsToStdErr)
1325 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1328 q->warnings(errors);
1329 if (outputWarningsToStdErr)
1330 dumpwarning(errors);
1333 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1336 QQmlEnginePrivate::get(engine)->warning(error);
1341 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1344 QQmlEnginePrivate::get(engine)->warning(error);
1349 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1352 engine->warning(error);
1357 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1360 engine->warning(error);
1366 This function should be called prior to evaluation of any js expression,
1367 so that scarce resources are not freed prematurely (eg, if there is a
1368 nested javascript expression).
1370 void QQmlEnginePrivate::referenceScarceResources()
1372 scarceResourcesRefCount += 1;
1376 This function should be called after evaluation of the js expression is
1377 complete, and so the scarce resources may be freed safely.
1379 void QQmlEnginePrivate::dereferenceScarceResources()
1381 Q_ASSERT(scarceResourcesRefCount > 0);
1382 scarceResourcesRefCount -= 1;
1384 // if the refcount is zero, then evaluation of the "top level"
1385 // expression must have completed. We can safely release the
1386 // scarce resources.
1387 if (scarceResourcesRefCount == 0) {
1388 // iterate through the list and release them all.
1389 // note that the actual SRD is owned by the JS engine,
1390 // so we cannot delete the SRD; but we can free the
1391 // memory used by the variant in the SRD.
1392 while (ScarceResourceData *sr = scarceResources.first()) {
1393 sr->data = QVariant();
1394 scarceResources.remove(sr);
1400 Adds \a path as a directory where the engine searches for
1401 installed modules in a URL-based directory structure.
1402 The \a path may be a local filesystem directory or a URL.
1404 The newly added \a path will be first in the importPathList().
1406 \sa setImportPathList(), {QML Modules}
1408 void QQmlEngine::addImportPath(const QString& path)
1411 d->importDatabase.addImportPath(path);
1415 Returns the list of directories where the engine searches for
1416 installed modules in a URL-based directory structure.
1418 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1419 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1420 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1421 provided by that module. A \c qmldir file is required for defining the
1422 type version mapping and possibly QML extensions plugins.
1424 By default, the list contains the directory of the application executable,
1425 paths specified in the \c QML_IMPORT_PATH environment variable,
1426 and the builtin \c ImportsPath from QLibraryInfo.
1428 \sa addImportPath() setImportPathList()
1430 QStringList QQmlEngine::importPathList() const
1432 Q_D(const QQmlEngine);
1433 return d->importDatabase.importPathList();
1437 Sets \a paths as the list of directories where the engine searches for
1438 installed modules in a URL-based directory structure.
1440 By default, the list contains the directory of the application executable,
1441 paths specified in the \c QML_IMPORT_PATH environment variable,
1442 and the builtin \c ImportsPath from QLibraryInfo.
1444 \sa importPathList() addImportPath()
1446 void QQmlEngine::setImportPathList(const QStringList &paths)
1449 d->importDatabase.setImportPathList(paths);
1454 Adds \a path as a directory where the engine searches for
1455 native plugins for imported modules (referenced in the \c qmldir file).
1457 By default, the list contains only \c ., i.e. the engine searches
1458 in the directory of the \c qmldir file itself.
1460 The newly added \a path will be first in the pluginPathList().
1462 \sa setPluginPathList()
1464 void QQmlEngine::addPluginPath(const QString& path)
1467 d->importDatabase.addPluginPath(path);
1472 Returns the list of directories where the engine searches for
1473 native plugins for imported modules (referenced in the \c qmldir file).
1475 By default, the list contains only \c ., i.e. the engine searches
1476 in the directory of the \c qmldir file itself.
1478 \sa addPluginPath() setPluginPathList()
1480 QStringList QQmlEngine::pluginPathList() const
1482 Q_D(const QQmlEngine);
1483 return d->importDatabase.pluginPathList();
1487 Sets the list of directories where the engine searches for
1488 native plugins for imported modules (referenced in the \c qmldir file)
1491 By default, the list contains only \c ., i.e. the engine searches
1492 in the directory of the \c qmldir file itself.
1494 \sa pluginPathList() addPluginPath()
1496 void QQmlEngine::setPluginPathList(const QStringList &paths)
1499 d->importDatabase.setPluginPathList(paths);
1503 Imports the plugin named \a filePath with the \a uri provided.
1504 Returns true if the plugin was successfully imported; otherwise returns false.
1506 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1508 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1510 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1513 return d->importDatabase.importPlugin(filePath, uri, errors);
1517 Imports the plugin named \a filePath with the \a uri provided.
1518 Returns true if the plugin was successfully imported; otherwise returns false.
1520 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1522 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1524 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1527 QList<QQmlError> errors;
1528 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1529 if (!errors.isEmpty()) {
1531 for (int i = 0; i < errors.size(); ++i) {
1532 builtError = QString(QLatin1String("%1\n %2"))
1534 .arg(errors.at(i).toString());
1536 *errorString = builtError;
1542 \property QQmlEngine::offlineStoragePath
1543 \brief the directory for storing offline user data
1545 Returns the directory where SQL and other offline
1548 QQuickWebView and the SQL databases created with openDatabase()
1551 The default is QML/OfflineStorage in the platform-standard
1552 user application data directory.
1554 Note that the path may not currently exist on the filesystem, so
1555 callers wanting to \e create new files at this location should create
1556 it first - see QDir::mkpath().
1558 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1561 d->offlineStoragePath = dir;
1564 QString QQmlEngine::offlineStoragePath() const
1566 Q_D(const QQmlEngine);
1567 return d->offlineStoragePath;
1570 static void voidptr_destructor(void *v)
1572 void **ptr = (void **)v;
1576 static void *voidptr_constructor(const void *v)
1581 return new void*(*(void **)v);
1585 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1589 if (!mo->superClass()) {
1590 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1591 propertyCache.insert(mo, rv);
1594 QQmlPropertyCache *super = cache(mo->superClass());
1595 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1596 propertyCache.insert(mo, rv);
1601 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1604 QList<QQmlType *> types;
1606 int maxMinorVersion = 0;
1608 const QMetaObject *metaObject = type->metaObject();
1610 while (metaObject) {
1611 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1612 type->majorVersion(), minorVersion);
1614 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1620 metaObject = metaObject->superClass();
1623 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1625 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1629 QQmlPropertyCache *raw = cache(type->metaObject());
1631 bool hasCopied = false;
1633 for (int ii = 0; ii < types.count(); ++ii) {
1634 QQmlType *currentType = types.at(ii);
1638 int rev = currentType->metaObjectRevision();
1639 int moIndex = types.count() - 1 - ii;
1641 if (raw->allowedRevisionCache[moIndex] != rev) {
1646 raw->allowedRevisionCache[moIndex] = rev;
1650 // Test revision compatibility - the basic rule is:
1651 // * Anything that is excluded, cannot overload something that is not excluded *
1653 // Signals override:
1654 // * other signals and methods of the same name.
1655 // * properties named on<Signal Name>
1656 // * automatic <property name>Changed notify signals
1658 // Methods override:
1659 // * other methods of the same name
1661 // Properties override:
1662 // * other elements of the same name
1664 bool overloadError = false;
1665 QString overloadName;
1668 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1669 !overloadError && iter != raw->stringCache.end();
1672 QQmlPropertyData *d = *iter;
1673 if (raw->isAllowedInRevision(d))
1674 continue; // Not excluded - no problems
1676 // check that a regular "name" overload isn't happening
1677 QQmlPropertyData *current = d;
1678 while (!overloadError && current) {
1679 current = d->overrideData(current);
1680 if (current && raw->isAllowedInRevision(current))
1681 overloadError = true;
1686 if (overloadError) {
1687 if (hasCopied) raw->release();
1689 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."));
1693 if (!hasCopied) raw->addref();
1694 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1696 if (minorVersion != maxMinorVersion) {
1698 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1704 QQmlMetaType::ModuleApiInstance *
1705 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1707 Locker locker(this);
1709 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1711 a = new QQmlMetaType::ModuleApiInstance;
1712 a->scriptCallback = module.script;
1713 a->qobjectCallback = module.qobject;
1714 a->instanceMetaObject = module.instanceMetaObject;
1715 moduleApiInstances.insert(module, a);
1721 bool QQmlEnginePrivate::isQObject(int t)
1723 Locker locker(this);
1724 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1727 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1729 Locker locker(this);
1730 int t = v.userType();
1731 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1733 return *(QObject **)(v.constData());
1735 return QQmlMetaType::toQObject(v, ok);
1739 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1741 Locker locker(this);
1742 if (m_compositeTypes.contains(t))
1743 return QQmlMetaType::Object;
1744 else if (m_qmlLists.contains(t))
1745 return QQmlMetaType::List;
1747 return QQmlMetaType::typeCategory(t);
1750 bool QQmlEnginePrivate::isList(int t) const
1752 Locker locker(this);
1753 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1756 int QQmlEnginePrivate::listType(int t) const
1758 Locker locker(this);
1759 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1760 if (iter != m_qmlLists.end())
1763 return QQmlMetaType::listType(t);
1766 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1768 Locker locker(this);
1769 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1770 if (iter != m_compositeTypes.end()) {
1771 return (*iter)->root;
1773 QQmlType *type = QQmlMetaType::qmlType(t);
1774 return type?type->baseMetaObject():0;
1778 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1780 Locker locker(this);
1781 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1782 if (iter != m_compositeTypes.end()) {
1783 return (*iter)->root;
1785 QQmlType *type = QQmlMetaType::qmlType(t);
1786 return type?type->metaObject():0;
1790 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1792 QByteArray name = data->root->className();
1794 QByteArray ptr = name + '*';
1795 QByteArray lst = "QQmlListProperty<" + name + '>';
1797 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1798 voidptr_constructor);
1799 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1800 voidptr_constructor);
1804 Locker locker(this);
1805 m_qmlLists.insert(lst_type, ptr_type);
1806 m_compositeTypes.insert(ptr_type, data);
1809 bool QQml_isFileCaseCorrect(const QString &fileName)
1811 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1812 QFileInfo info(fileName);
1813 const QString absolute = info.absoluteFilePath();
1815 #if defined(Q_OS_MAC)
1816 const QString canonical = info.canonicalFilePath();
1817 #elif defined(Q_OS_WIN)
1818 wchar_t buffer[1024];
1820 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1821 if (rv == 0 || rv >= 1024) return true;
1822 rv = ::GetLongPathName(buffer, buffer, 1024);
1823 if (rv == 0 || rv >= 1024) return true;
1825 const QString canonical = QString::fromWCharArray(buffer);
1828 const int absoluteLength = absolute.length();
1829 const int canonicalLength = canonical.length();
1831 const int length = qMin(absoluteLength, canonicalLength);
1832 for (int ii = 0; ii < length; ++ii) {
1833 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1834 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1836 if (a.toLower() != c.toLower())
1848 \fn QQmlEngine *qmlEngine(const QObject *object)
1851 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1852 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1856 \fn QQmlContext *qmlContext(const QObject *object)
1859 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1860 QQmlEngine::contextForObject(object).