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 QtDeclarative 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 "qdeclarativeengine_p.h"
43 #include "qdeclarativeengine.h"
44 #include "qdeclarativecomponentattached_p.h"
46 #include "qdeclarativecontext_p.h"
47 #include "qdeclarativecompiler_p.h"
48 #include "qdeclarative.h"
49 #include "qdeclarativecontext.h"
50 #include "qdeclarativeexpression.h"
51 #include "qdeclarativecomponent.h"
52 #include "qdeclarativebinding_p_p.h"
53 #include "qdeclarativevme_p.h"
54 #include <private/qdeclarativeenginedebugservice_p.h>
55 #include "qdeclarativestringconverters_p.h"
56 #include "qdeclarativexmlhttprequest_p.h"
57 #include "qdeclarativesqldatabase_p.h"
58 #include "qdeclarativescriptstring.h"
59 #include "qdeclarativeglobal_p.h"
60 #include "qdeclarativelistmodel_p.h"
61 #include "qdeclarativeworkerscript_p.h"
62 #include "qdeclarativecomponent_p.h"
63 #include "qdeclarativenetworkaccessmanagerfactory.h"
64 #include "qdeclarativeimageprovider.h"
65 #include "qdeclarativedirparser_p.h"
66 #include "qdeclarativeextensioninterface.h"
67 #include "qdeclarativelist_p.h"
68 #include "qdeclarativetypenamecache_p.h"
69 #include "qdeclarativenotifier_p.h"
70 #include <private/qdeclarativedebugtrace_p.h>
71 #include <private/qdeclarativeapplication_p.h>
72 #include <private/qv8debugservice_p.h>
73 #include <private/qdebugmessageservice_p.h>
74 #include "qdeclarativeincubator.h"
75 #include <private/qv8profilerservice_p.h>
77 #include <QtCore/qstandardpaths.h>
78 #include <QtCore/qsettings.h>
80 #include <QtCore/qmetaobject.h>
81 #include <QNetworkAccessManager>
83 #include <QMetaObject>
84 #include <QtCore/qcoreapplication.h>
85 #include <QtCore/qdir.h>
86 #include <QtCore/qmutex.h>
87 #include <QtNetwork/qnetworkconfigmanager.h>
89 #include <private/qobject_p.h>
91 #include <private/qdeclarativelocale_p.h>
93 #ifdef Q_OS_WIN // for %APPDATA%
94 #include <qt_windows.h>
98 #define CSIDL_APPDATA 0x001a // <username>\Application Data
101 Q_DECLARE_METATYPE(QDeclarativeProperty)
105 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
107 QDeclarativeEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
108 QDeclarativeValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
112 \qmlclass QtObject QObject
113 \ingroup qml-utility-elements
115 \brief The QtObject element is the most basic element in QML.
117 The QtObject element is a non-visual element which contains only the
120 It can be useful to create a QtObject if you need an extremely
121 lightweight element to enclose a set of custom properties:
123 \snippet doc/src/snippets/declarative/qtobject.qml 0
125 It can also be useful for C++ integration, as it is just a plain
126 QObject. See the QObject documentation for further details.
129 \qmlproperty string QtObject::objectName
130 This property holds the QObject::objectName for this specific object instance.
132 This allows a C++ application to locate an item within a QML component
133 using the QObject::findChild() method. For example, the following C++
134 application locates the child \l Rectangle item and dynamically changes its
143 width: 200; height: 200
156 QDeclarativeView view;
157 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
160 QDeclarativeItem *item = view.rootObject()->findChild<QDeclarativeItem*>("myRect");
162 item->setProperty("color", QColor(Qt::yellow));
166 bool QDeclarativeEnginePrivate::qml_debugging_enabled = false;
168 void QDeclarativeEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
170 qmlRegisterType<QDeclarativeComponent>(uri,versionMajor,versionMinor,"Component");
171 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
172 qmlRegisterType<QDeclarativeListElement>(uri, versionMajor, versionMinor,"ListElement");
173 qmlRegisterCustomType<QDeclarativeListModel>(uri, versionMajor, versionMinor,"ListModel", new QDeclarativeListModelParser);
174 qmlRegisterType<QDeclarativeWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
177 void QDeclarativeEnginePrivate::defineModule()
179 registerBaseTypes("QtQuick", 2, 0);
180 qmlRegisterType<QDeclarativeBinding>();
181 qmlRegisterUncreatableType<QDeclarativeApplication>("QtQuick",2,0,"Application", QDeclarativeApplication::tr("Application is an abstract class"));
182 qmlRegisterUncreatableType<QDeclarativeLocale>("QtQuick",2,0,"Locale",QDeclarativeEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
186 \qmlclass Qt QDeclarativeEnginePrivate
187 \ingroup qml-utility-elements
188 \brief The QML global Qt object provides useful enums and functions from Qt.
190 \keyword QmlGlobalQtObject
192 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
194 The \c Qt object is a global object with utility functions, properties and enums.
196 It is not instantiable; to use it, call the members of the global \c Qt object directly.
203 color: Qt.rgba(1, 0, 0, 1)
204 text: Qt.md5("hello, world")
211 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
212 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
216 The Qt object also contains helper functions for creating objects of specific
217 data types. This is primarily useful when setting the properties of an item
218 when the property has one of the following types:
221 \o \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
222 \o \c rect - use \l{Qt::rect()}{Qt.rect()}
223 \o \c point - use \l{Qt::point()}{Qt.point()}
224 \o \c size - use \l{Qt::size()}{Qt.size()}
225 \o \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
228 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
230 \section1 Date/Time Formatters
232 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
235 \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
236 \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
237 \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
240 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
243 \section1 Dynamic Object Creation
244 The following functions on the global object allow you to dynamically create QML
245 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
249 \o \l{Qt::createComponent()}{object Qt.createComponent(url)}
250 \o \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
256 \qmlproperty object Qt::application
259 The \c application object provides access to global application state
260 properties shared by many QML components.
266 \o \c application.active
268 This read-only property indicates whether the application is the top-most and focused
269 application, and the user is able to interact with the application. The property
270 is false when the application is in the background, the device keylock or screen
271 saver is active, the screen backlight is turned off, or the global system dialog
272 is being displayed on top of the application. It can be used for stopping and
273 pausing animations, timers and active processing of data in order to save device
274 battery power and free device memory and processor load when the application is not
278 \o \c application.layoutDirection
280 This read-only property can be used to query the default layout direction of the
281 application. On system start-up, the default layout direction depends on the
282 application's language. The property has a value of \c Qt.RightToLeft in locales
283 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
284 where the reading direction flows from left to right. You can bind to this
285 property to customize your application layouts to support both layout directions.
290 \o Qt.LeftToRight - Text and graphics elements should be positioned
292 \o Qt.RightToLeft - Text and graphics elements should be positioned
297 \o \c application.inputPanel
299 This read-only property allows access to application's QInputPanel object
300 and all its properties and slots. See the QInputPanel documentation for
304 The following example uses the \c application object to indicate
305 whether the application is currently active:
307 \snippet doc/src/snippets/declarative/application.qml document
313 \qmlmethod object Qt::include(string url, jsobject callback)
315 Includes another JavaScript file. This method can only be used from within JavaScript files,
316 and not regular QML files.
318 This imports all functions from \a url into the current script's namespace.
320 Qt.include() returns an object that describes the status of the operation. The object has
321 a single property, \c {status}, that is set to one of the following values:
324 \header \o Symbol \o Value \o Description
325 \row \o result.OK \o 0 \o The include completed successfully.
326 \row \o result.LOADING \o 1 \o Data is being loaded from the network.
327 \row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url.
328 \row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code.
329 An additional \c exception property will be set in this case.
332 The \c status property will be updated as the operation progresses.
334 If provided, \a callback is invoked when the operation completes. The callback is passed
335 the same object as is returned from the Qt.include() call.
337 // Qt.include() is implemented in qv8include.cpp
340 QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
341 : propertyCapture(0), rootContext(0), isDebugging(false),
342 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
343 cleanup(0), erroredBindings(0), inProgressCreations(0),
344 workerScriptEngine(0), activeVME(0),
345 networkAccessManager(0), networkAccessManagerFactory(0),
346 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
347 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
351 QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate()
353 Q_ASSERT(inProgressCreations == 0);
356 QDeclarativeCleanup *c = cleanup;
358 if (cleanup) cleanup->prev = &cleanup;
364 doDeleteInEngineThread();
366 if (incubationController) incubationController->d = 0;
367 incubationController = 0;
372 for(QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
374 for(QHash<const QMetaObject *, QDeclarativePropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
376 for(QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
378 for(QHash<QDeclarativeMetaType::ModuleApi, QDeclarativeMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
379 delete (*iter)->qobjectApi;
384 void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *o)
386 QObjectPrivate *p = QObjectPrivate::get(o);
387 if (p->declarativeData) {
388 QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
389 if (d->ownContext && d->context) {
390 d->context->destroy();
396 void QDeclarativeData::destroyed(QAbstractDeclarativeData *d, QObject *o)
398 static_cast<QDeclarativeData *>(d)->destroyed(o);
401 void QDeclarativeData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
403 static_cast<QDeclarativeData *>(d)->parentChanged(o, p);
406 void QDeclarativeData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
408 static_cast<QDeclarativeData *>(d)->objectNameChanged(o);
411 void QDeclarativeData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
413 QDeclarativeData *ddata = QDeclarativeData::get(object, false);
414 if (!ddata) return; // Probably being deleted
416 QDeclarativeNotifierEndpoint *ep = ddata->notify(index);
417 if (ep) QDeclarativeNotifier::emitNotify(ep);
420 void QDeclarativeEnginePrivate::init()
422 Q_Q(QDeclarativeEngine);
424 static bool firstTime = true;
426 qmlRegisterType<QDeclarativeComponent>("QML", 1, 0, "Component");
431 qRegisterMetaType<QVariant>("QVariant");
432 qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString");
433 qRegisterMetaType<QJSValue>("QJSValue");
434 qRegisterMetaType<QDeclarativeComponent::Status>("QDeclarativeComponent::Status");
435 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
436 qRegisterMetaType<QList<int> >("QList<int>");
437 qRegisterMetaType<QDeclarativeV8Handle>("QDeclarativeV8Handle");
439 QDeclarativeData::init();
441 v8engine()->setEngine(q);
443 rootContext = new QDeclarativeContext(q,true);
445 if (QCoreApplication::instance()->thread() == q->thread() &&
446 QDeclarativeEngineDebugService::isDebuggingEnabled()) {
448 QDeclarativeEngineDebugService::instance()->addEngine(q);
449 QV8DebugService::initialize(v8engine());
450 QV8ProfilerService::initialize();
451 QDeclarativeDebugTrace::initialize();
452 QDebugMessageService::instance();
455 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
456 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
457 QDir::separator() + QLatin1String("QML") +
458 QDir::separator() + QLatin1String("OfflineStorage");
461 QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine()
463 Q_Q(QDeclarativeEngine);
464 if (!workerScriptEngine)
465 workerScriptEngine = new QDeclarativeWorkerScriptEngine(q);
466 return workerScriptEngine;
470 \class QDeclarativeEngine
472 \brief The QDeclarativeEngine class provides an environment for instantiating QML components.
475 Each QML component is instantiated in a QDeclarativeContext.
476 QDeclarativeContext's are essential for passing data to QML
477 components. In QML, contexts are arranged hierarchically and this
478 hierarchy is managed by the QDeclarativeEngine.
480 Prior to creating any QML components, an application must have
481 created a QDeclarativeEngine to gain access to a QML context. The
482 following example shows how to create a simple Text item.
485 QDeclarativeEngine engine;
486 QDeclarativeComponent component(&engine);
487 component.setData("import QtQuick 1.0\nText { text: \"Hello world!\" }", QUrl());
488 QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create());
490 //add item to view, etc
494 In this case, the Text item will be created in the engine's
495 \l {QDeclarativeEngine::rootContext()}{root context}.
497 \sa QDeclarativeComponent QDeclarativeContext
501 Create a new QDeclarativeEngine with the given \a parent.
503 QDeclarativeEngine::QDeclarativeEngine(QObject *parent)
504 : QJSEngine(*new QDeclarativeEnginePrivate(this), parent)
506 Q_D(QDeclarativeEngine);
511 Destroys the QDeclarativeEngine.
513 Any QDeclarativeContext's created on this engine will be
514 invalidated, but not destroyed (unless they are parented to the
515 QDeclarativeEngine object).
517 QDeclarativeEngine::~QDeclarativeEngine()
519 Q_D(QDeclarativeEngine);
520 if (d->isDebugging) {
521 QDeclarativeEngineDebugService::instance()->remEngine(this);
524 // if we are the parent of any of the qobject module api instances,
525 // we need to remove them from our internal list, in order to prevent
526 // a segfault in engine private dtor.
527 QList<QDeclarativeMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
528 QObject *currQObjectApi = 0;
529 QDeclarativeMetaType::ModuleApiInstance *currInstance = 0;
530 foreach (const QDeclarativeMetaType::ModuleApi &key, keys) {
531 currInstance = d->moduleApiInstances.value(key);
532 currQObjectApi = currInstance->qobjectApi;
533 if (this->children().contains(currQObjectApi)) {
534 delete currQObjectApi;
536 d->moduleApiInstances.remove(key);
540 // ensure we clean up QObjects with JS ownership
543 if (d->incubationController)
544 d->incubationController->d = 0;
547 /*! \fn void QDeclarativeEngine::quit()
548 This signal is emitted when the QML loaded by the engine would like to quit.
551 /*! \fn void QDeclarativeEngine::warnings(const QList<QDeclarativeError> &warnings)
552 This signal is emitted when \a warnings messages are generated by QML.
556 Clears the engine's internal component cache.
558 Normally the QDeclarativeEngine caches components loaded from qml
559 files. This method clears this cache and forces the component to be
562 void QDeclarativeEngine::clearComponentCache()
564 Q_D(QDeclarativeEngine);
565 d->typeLoader.clearCache();
569 Returns the engine's root context.
571 The root context is automatically created by the QDeclarativeEngine.
572 Data that should be available to all QML component instances
573 instantiated by the engine should be put in the root context.
575 Additional data that should only be available to a subset of
576 component instances should be added to sub-contexts parented to the
579 QDeclarativeContext *QDeclarativeEngine::rootContext() const
581 Q_D(const QDeclarativeEngine);
582 return d->rootContext;
586 Sets the \a factory to use for creating QNetworkAccessManager(s).
588 QNetworkAccessManager is used for all network access by QML. By
589 implementing a factory it is possible to create custom
590 QNetworkAccessManager with specialized caching, proxy and cookie
593 The factory must be set before executing the engine.
595 void QDeclarativeEngine::setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *factory)
597 Q_D(QDeclarativeEngine);
598 QMutexLocker locker(&d->mutex);
599 d->networkAccessManagerFactory = factory;
603 Returns the current QDeclarativeNetworkAccessManagerFactory.
605 \sa setNetworkAccessManagerFactory()
607 QDeclarativeNetworkAccessManagerFactory *QDeclarativeEngine::networkAccessManagerFactory() const
609 Q_D(const QDeclarativeEngine);
610 return d->networkAccessManagerFactory;
613 void QDeclarativeEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
616 activeVME->finalizeCallbacks.append(qMakePair(QDeclarativeGuard<QObject>(obj), index));
618 void *args[] = { 0 };
619 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
623 QNetworkAccessManager *QDeclarativeEnginePrivate::createNetworkAccessManager(QObject *parent) const
625 QMutexLocker locker(&mutex);
626 QNetworkAccessManager *nam;
627 if (networkAccessManagerFactory) {
628 nam = networkAccessManagerFactory->create(parent);
630 nam = new QNetworkAccessManager(parent);
636 QNetworkAccessManager *QDeclarativeEnginePrivate::getNetworkAccessManager() const
638 Q_Q(const QDeclarativeEngine);
639 if (!networkAccessManager)
640 networkAccessManager = createNetworkAccessManager(const_cast<QDeclarativeEngine*>(q));
641 return networkAccessManager;
645 Returns a common QNetworkAccessManager which can be used by any QML
646 element instantiated by this engine.
648 If a QDeclarativeNetworkAccessManagerFactory has been set and a
649 QNetworkAccessManager has not yet been created, the
650 QDeclarativeNetworkAccessManagerFactory will be used to create the
651 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
652 will have no proxy or cache set.
654 \sa setNetworkAccessManagerFactory()
656 QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
658 Q_D(const QDeclarativeEngine);
659 return d->getNetworkAccessManager();
664 Sets the \a provider to use for images requested via the \e
665 image: url scheme, with host \a providerId. The QDeclarativeEngine
666 takes ownership of \a provider.
668 Image providers enable support for pixmap and threaded image
669 requests. See the QDeclarativeImageProvider documentation for details on
670 implementing and using image providers.
672 All required image providers should be added to the engine before any
673 QML sources files are loaded.
675 \sa removeImageProvider()
677 void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativeImageProvider *provider)
679 Q_D(QDeclarativeEngine);
680 QMutexLocker locker(&d->mutex);
681 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QDeclarativeImageProvider>(provider));
685 Returns the QDeclarativeImageProvider set for \a providerId.
687 Returns the provider if it was found; otherwise returns 0.
689 QDeclarativeImageProvider *QDeclarativeEngine::imageProvider(const QString &providerId) const
691 Q_D(const QDeclarativeEngine);
692 QMutexLocker locker(&d->mutex);
693 return d->imageProviders.value(providerId).data();
697 Removes the QDeclarativeImageProvider for \a providerId.
699 \sa addImageProvider()
701 void QDeclarativeEngine::removeImageProvider(const QString &providerId)
703 Q_D(QDeclarativeEngine);
704 QMutexLocker locker(&d->mutex);
705 d->imageProviders.take(providerId);
708 QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProviderType(const QUrl &url)
710 QMutexLocker locker(&mutex);
711 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
714 return provider->imageType();
715 return QDeclarativeImageProvider::Invalid;
718 QDeclarativeTextureFactory *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
720 QMutexLocker locker(&mutex);
721 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
724 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
725 return provider->requestTexture(imageId, size, req_size);
730 QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
732 QMutexLocker locker(&mutex);
734 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
737 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
738 image = provider->requestImage(imageId, size, req_size);
743 QPixmap QDeclarativeEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
745 QMutexLocker locker(&mutex);
747 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
750 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
751 pixmap = provider->requestPixmap(imageId, size, req_size);
757 Return the base URL for this engine. The base URL is only used to
758 resolve components when a relative URL is passed to the
759 QDeclarativeComponent constructor.
761 If a base URL has not been explicitly set, this method returns the
762 application's current working directory.
766 QUrl QDeclarativeEngine::baseUrl() const
768 Q_D(const QDeclarativeEngine);
769 if (d->baseUrl.isEmpty()) {
770 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
777 Set the base URL for this engine to \a url.
781 void QDeclarativeEngine::setBaseUrl(const QUrl &url)
783 Q_D(QDeclarativeEngine);
788 Returns true if warning messages will be output to stderr in addition
789 to being emitted by the warnings() signal, otherwise false.
791 The default value is true.
793 bool QDeclarativeEngine::outputWarningsToStandardError() const
795 Q_D(const QDeclarativeEngine);
796 return d->outputWarningsToStdErr;
800 Set whether warning messages will be output to stderr to \a enabled.
802 If \a enabled is true, any warning messages generated by QML will be
803 output to stderr and emitted by the warnings() signal. If \a enabled
804 is false, on the warnings() signal will be emitted. This allows
805 applications to handle warning output themselves.
807 The default value is true.
809 void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled)
811 Q_D(QDeclarativeEngine);
812 d->outputWarningsToStdErr = enabled;
816 Attempt to free unused memory.
818 void QDeclarativeEngine::collectGarbage()
824 Returns the QDeclarativeContext for the \a object, or 0 if no
825 context has been set.
827 When the QDeclarativeEngine instantiates a QObject, the context is
830 QDeclarativeContext *QDeclarativeEngine::contextForObject(const QObject *object)
835 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
837 QDeclarativeData *data =
838 static_cast<QDeclarativeData *>(priv->declarativeData);
842 else if (data->outerContext)
843 return data->outerContext->asQDeclarativeContext();
849 Sets the QDeclarativeContext for the \a object to \a context.
850 If the \a object already has a context, a warning is
851 output, but the context is not changed.
853 When the QDeclarativeEngine instantiates a QObject, the context is
856 void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContext *context)
858 if (!object || !context)
861 QDeclarativeData *data = QDeclarativeData::get(object, true);
863 qWarning("QDeclarativeEngine::setContextForObject(): Object already has a QDeclarativeContext");
867 QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
868 contextData->addObject(object);
872 \enum QDeclarativeEngine::ObjectOwnership
874 Ownership controls whether or not QML automatically destroys the
875 QObject when the object is garbage collected by the JavaScript
876 engine. The two ownership options are:
878 \value CppOwnership The object is owned by C++ code, and will
879 never be deleted by QML. The JavaScript destroy() method cannot be
880 used on objects with CppOwnership. This option is similar to
881 QScriptEngine::QtOwnership.
883 \value JavaScriptOwnership The object is owned by JavaScript.
884 When the object is returned to QML as the return value of a method
885 call or property access, QML will delete the object if there are no
886 remaining JavaScript references to it and it has no
887 QObject::parent(). This option is similar to
888 QScriptEngine::ScriptOwnership.
890 Generally an application doesn't need to set an object's ownership
891 explicitly. QML uses a heuristic to set the default object
892 ownership. By default, an object that is created by QML has
893 JavaScriptOwnership. The exception to this are the root objects
894 created by calling QDeclarativeCompnent::create() or
895 QDeclarativeComponent::beginCreate() which have CppOwnership by
896 default. The ownership of these root-level objects is considered to
897 have been transferred to the C++ caller.
899 Objects not-created by QML have CppOwnership by default. The
900 exception to this is objects returned from a C++ method call. The
901 ownership of these objects is passed to JavaScript.
903 Calling setObjectOwnership() overrides the default ownership
904 heuristic used by QML.
908 Sets the \a ownership of \a object.
910 void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
915 QDeclarativeData *ddata = QDeclarativeData::get(object, true);
919 ddata->indestructible = (ownership == CppOwnership)?true:false;
920 ddata->explicitIndestructibleSet = true;
924 Returns the ownership of \a object.
926 QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object)
931 QDeclarativeData *ddata = QDeclarativeData::get(object, false);
935 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
938 bool QDeclarativeEngine::event(QEvent *e)
940 Q_D(QDeclarativeEngine);
941 if (e->type() == QEvent::User)
942 d->doDeleteInEngineThread();
944 return QJSEngine::event(e);
947 void QDeclarativeEnginePrivate::doDeleteInEngineThread()
949 QFieldList<Deletable, &Deletable::next> list;
951 list.copyAndClear(toDeleteInEngineThread);
954 while (Deletable *d = list.takeFirst())
958 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
960 QDeclarativeData *data = QDeclarativeData::get(object);
962 if (data && data->deferredComponent) {
963 if (QDeclarativeDebugService::isDebuggingEnabled()) {
964 QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
965 QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
966 QString typeName = type ? type->qmlTypeName() : QString::fromUtf8(object->metaObject()->className());
967 QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, typeName);
968 if (data->outerContext)
969 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, data->outerContext->url, data->lineNumber, data->columnNumber);
971 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine);
973 QDeclarativeComponentPrivate::ConstructionState state;
974 QDeclarativeComponentPrivate::beginDeferred(ep, object, &state);
976 data->deferredComponent->release();
977 data->deferredComponent = 0;
979 QDeclarativeComponentPrivate::complete(ep, &state);
980 QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
984 QDeclarativeContext *qmlContext(const QObject *obj)
986 return QDeclarativeEngine::contextForObject(obj);
989 QDeclarativeEngine *qmlEngine(const QObject *obj)
991 QDeclarativeData *data = QDeclarativeData::get(obj, false);
992 if (!data || !data->context)
994 return data->context->engine;
997 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
999 QDeclarativeData *data = QDeclarativeData::get(object);
1001 return 0; // Attached properties are only on objects created by QML
1003 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1007 QDeclarativeAttachedPropertiesFunc pf = QDeclarativeMetaType::attachedPropertiesFuncById(id);
1011 rv = pf(const_cast<QObject *>(object));
1014 data->attachedProperties()->insert(id, rv);
1019 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1020 const QMetaObject *attachedMetaObject, bool create)
1023 *idCache = QDeclarativeMetaType::attachedPropertiesFuncId(attachedMetaObject);
1025 if (*idCache == -1 || !object)
1028 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1031 QDeclarativeDebuggingEnabler::QDeclarativeDebuggingEnabler()
1033 #ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
1034 if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
1035 qWarning("Qml debugging is enabled. Only use this in a safe environment!");
1037 QDeclarativeEnginePrivate::qml_debugging_enabled = true;
1042 class QDeclarativeDataExtended {
1044 QDeclarativeDataExtended();
1045 ~QDeclarativeDataExtended();
1047 QHash<int, QObject *> attachedProperties;
1048 QDeclarativeNotifier objectNameNotifier;
1051 QDeclarativeDataExtended::QDeclarativeDataExtended()
1055 QDeclarativeDataExtended::~QDeclarativeDataExtended()
1059 void QDeclarativeData::NotifyList::layout(QDeclarativeNotifierEndpoint *endpoint)
1062 layout(endpoint->next);
1064 int index = endpoint->sourceSignal;
1065 index = qMin(index, 0xFFFF - 1);
1067 endpoint->next = notifies[index];
1068 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1069 endpoint->prev = ¬ifies[index];
1070 notifies[index] = endpoint;
1073 void QDeclarativeData::NotifyList::layout()
1075 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1078 QDeclarativeNotifierEndpoint **old = notifies;
1079 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QDeclarativeNotifierEndpoint*);
1080 notifies = (QDeclarativeNotifierEndpoint**)realloc(notifies, reallocSize);
1081 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1082 sizeof(QDeclarativeNotifierEndpoint*);
1083 memset(notifies + notifiesSize, 0, memsetSize);
1085 if (notifies != old) {
1086 for (int ii = 0; ii < notifiesSize; ++ii)
1088 notifies[ii]->prev = ¬ifies[ii];
1091 notifiesSize = maximumTodoIndex + 1;
1096 maximumTodoIndex = 0;
1100 void QDeclarativeData::addNotify(int index, QDeclarativeNotifierEndpoint *endpoint)
1103 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1104 notifyList->connectionMask = 0;
1105 notifyList->maximumTodoIndex = 0;
1106 notifyList->notifiesSize = 0;
1107 notifyList->todo = 0;
1108 notifyList->notifies = 0;
1111 Q_ASSERT(!endpoint->isConnected());
1113 index = qMin(index, 0xFFFF - 1);
1114 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1116 if (index < notifyList->notifiesSize) {
1118 endpoint->next = notifyList->notifies[index];
1119 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1120 endpoint->prev = ¬ifyList->notifies[index];
1121 notifyList->notifies[index] = endpoint;
1124 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1126 endpoint->next = notifyList->todo;
1127 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1128 endpoint->prev = ¬ifyList->todo;
1129 notifyList->todo = endpoint;
1133 QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const
1135 if (!extendedData) extendedData = new QDeclarativeDataExtended;
1136 return &extendedData->objectNameNotifier;
1139 QHash<int, QObject *> *QDeclarativeData::attachedProperties() const
1141 if (!extendedData) extendedData = new QDeclarativeDataExtended;
1142 return &extendedData->attachedProperties;
1145 void QDeclarativeData::destroyed(QObject *object)
1147 if (deferredComponent)
1148 deferredComponent->release();
1150 if (nextContextObject)
1151 nextContextObject->prevContextObject = prevContextObject;
1152 if (prevContextObject)
1153 *prevContextObject = nextContextObject;
1155 QDeclarativeAbstractBinding *binding = bindings;
1157 QDeclarativeAbstractBinding *next = binding->m_nextBinding;
1158 binding->m_prevBinding = 0;
1159 binding->m_nextBinding = 0;
1168 propertyCache->release();
1170 if (ownContext && context)
1174 QDeclarativeGuard<QObject> *guard = static_cast<QDeclarativeGuard<QObject> *>(guards);
1175 *guard = (QObject *)0;
1176 guard->objectDestroyed(object);
1180 while (notifyList->todo)
1181 notifyList->todo->disconnect();
1182 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1183 while (QDeclarativeNotifierEndpoint *ep = notifyList->notifies[ii])
1186 free(notifyList->notifies);
1191 delete extendedData;
1193 v8object.Clear(); // The WeakReference handler will clean the actual handle
1199 void QDeclarativeData::parentChanged(QObject *object, QObject *parent)
1205 void QDeclarativeData::objectNameChanged(QObject *)
1207 if (extendedData) objectNameNotifier()->notify();
1210 bool QDeclarativeData::hasBindingBit(int bit) const
1212 if (bindingBitsSize > bit)
1213 return bindingBits[bit / 32] & (1 << (bit % 32));
1218 void QDeclarativeData::clearBindingBit(int bit)
1220 if (bindingBitsSize > bit)
1221 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1224 void QDeclarativeData::setBindingBit(QObject *obj, int bit)
1226 if (bindingBitsSize <= bit) {
1227 int props = obj->metaObject()->propertyCount();
1228 Q_ASSERT(bit < props);
1230 int arraySize = (props + 31) / 32;
1231 int oldArraySize = bindingBitsSize / 32;
1233 bindingBits = (quint32 *)realloc(bindingBits,
1234 arraySize * sizeof(quint32));
1236 memset(bindingBits + oldArraySize,
1238 sizeof(quint32) * (arraySize - oldArraySize));
1240 bindingBitsSize = arraySize * 32;
1243 bindingBits[bit / 32] |= (1 << (bit % 32));
1246 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1248 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1249 if (url.authority().isEmpty())
1250 return QLatin1Char(':') + url.path();
1253 return url.toLocalFile();
1257 static QString toLocalFile(const QString &url)
1259 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1262 QString file = url.mid(7);
1264 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1266 // magic for drives on windows
1267 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1273 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1275 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1276 if (url.length() > 4)
1277 return QLatin1Char(':') + url.mid(4);
1281 return toLocalFile(url);
1284 void QDeclarativeEnginePrivate::sendQuit()
1286 Q_Q(QDeclarativeEngine);
1288 if (q->receivers(SIGNAL(quit())) == 0) {
1289 qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it.");
1293 static void dumpwarning(const QDeclarativeError &error)
1295 qWarning().nospace() << qPrintable(error.toString());
1298 static void dumpwarning(const QList<QDeclarativeError> &errors)
1300 for (int ii = 0; ii < errors.count(); ++ii)
1301 dumpwarning(errors.at(ii));
1304 void QDeclarativeEnginePrivate::warning(const QDeclarativeError &error)
1306 Q_Q(QDeclarativeEngine);
1307 q->warnings(QList<QDeclarativeError>() << error);
1308 if (outputWarningsToStdErr)
1312 void QDeclarativeEnginePrivate::warning(const QList<QDeclarativeError> &errors)
1314 Q_Q(QDeclarativeEngine);
1315 q->warnings(errors);
1316 if (outputWarningsToStdErr)
1317 dumpwarning(errors);
1320 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QDeclarativeError &error)
1323 QDeclarativeEnginePrivate::get(engine)->warning(error);
1328 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QList<QDeclarativeError> &error)
1331 QDeclarativeEnginePrivate::get(engine)->warning(error);
1336 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QDeclarativeError &error)
1339 engine->warning(error);
1344 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QList<QDeclarativeError> &error)
1347 engine->warning(error);
1353 This function should be called prior to evaluation of any js expression,
1354 so that scarce resources are not freed prematurely (eg, if there is a
1355 nested javascript expression).
1357 void QDeclarativeEnginePrivate::referenceScarceResources()
1359 scarceResourcesRefCount += 1;
1363 This function should be called after evaluation of the js expression is
1364 complete, and so the scarce resources may be freed safely.
1366 void QDeclarativeEnginePrivate::dereferenceScarceResources()
1368 Q_ASSERT(scarceResourcesRefCount > 0);
1369 scarceResourcesRefCount -= 1;
1371 // if the refcount is zero, then evaluation of the "top level"
1372 // expression must have completed. We can safely release the
1373 // scarce resources.
1374 if (scarceResourcesRefCount == 0) {
1375 // iterate through the list and release them all.
1376 // note that the actual SRD is owned by the JS engine,
1377 // so we cannot delete the SRD; but we can free the
1378 // memory used by the variant in the SRD.
1379 while (ScarceResourceData *sr = scarceResources.first()) {
1380 sr->data = QVariant();
1381 scarceResources.remove(sr);
1387 Adds \a path as a directory where the engine searches for
1388 installed modules in a URL-based directory structure.
1389 The \a path may be a local filesystem directory or a URL.
1391 The newly added \a path will be first in the importPathList().
1393 \sa setImportPathList(), {QML Modules}
1395 void QDeclarativeEngine::addImportPath(const QString& path)
1397 Q_D(QDeclarativeEngine);
1398 d->importDatabase.addImportPath(path);
1402 Returns the list of directories where the engine searches for
1403 installed modules in a URL-based directory structure.
1405 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1406 imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look
1407 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1408 provided by that module. A \c qmldir file is required for defining the
1409 type version mapping and possibly declarative extensions plugins.
1411 By default, the list contains the directory of the application executable,
1412 paths specified in the \c QML_IMPORT_PATH environment variable,
1413 and the builtin \c ImportsPath from QLibraryInfo.
1415 \sa addImportPath() setImportPathList()
1417 QStringList QDeclarativeEngine::importPathList() const
1419 Q_D(const QDeclarativeEngine);
1420 return d->importDatabase.importPathList();
1424 Sets \a paths as the list of directories where the engine searches for
1425 installed modules in a URL-based directory structure.
1427 By default, the list contains the directory of the application executable,
1428 paths specified in the \c QML_IMPORT_PATH environment variable,
1429 and the builtin \c ImportsPath from QLibraryInfo.
1431 \sa importPathList() addImportPath()
1433 void QDeclarativeEngine::setImportPathList(const QStringList &paths)
1435 Q_D(QDeclarativeEngine);
1436 d->importDatabase.setImportPathList(paths);
1441 Adds \a path as a directory where the engine searches for
1442 native plugins for imported modules (referenced in the \c qmldir file).
1444 By default, the list contains only \c ., i.e. the engine searches
1445 in the directory of the \c qmldir file itself.
1447 The newly added \a path will be first in the pluginPathList().
1449 \sa setPluginPathList()
1451 void QDeclarativeEngine::addPluginPath(const QString& path)
1453 Q_D(QDeclarativeEngine);
1454 d->importDatabase.addPluginPath(path);
1459 Returns the list of directories where the engine searches for
1460 native plugins for imported modules (referenced in the \c qmldir file).
1462 By default, the list contains only \c ., i.e. the engine searches
1463 in the directory of the \c qmldir file itself.
1465 \sa addPluginPath() setPluginPathList()
1467 QStringList QDeclarativeEngine::pluginPathList() const
1469 Q_D(const QDeclarativeEngine);
1470 return d->importDatabase.pluginPathList();
1474 Sets the list of directories where the engine searches for
1475 native plugins for imported modules (referenced in the \c qmldir file)
1478 By default, the list contains only \c ., i.e. the engine searches
1479 in the directory of the \c qmldir file itself.
1481 \sa pluginPathList() addPluginPath()
1483 void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
1485 Q_D(QDeclarativeEngine);
1486 d->importDatabase.setPluginPathList(paths);
1490 Imports the plugin named \a filePath with the \a uri provided.
1491 Returns true if the plugin was successfully imported; otherwise returns false.
1493 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1495 The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1497 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
1499 Q_D(QDeclarativeEngine);
1500 return d->importDatabase.importPlugin(filePath, uri, errors);
1504 Imports the plugin named \a filePath with the \a uri provided.
1505 Returns true if the plugin was successfully imported; otherwise returns false.
1507 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1509 The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1511 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1513 Q_D(QDeclarativeEngine);
1514 QList<QDeclarativeError> errors;
1515 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1516 if (!errors.isEmpty()) {
1518 for (int i = 0; i < errors.size(); ++i) {
1519 builtError = QString(QLatin1String("%1\n %2"))
1521 .arg(errors.at(i).toString());
1523 *errorString = builtError;
1529 \property QDeclarativeEngine::offlineStoragePath
1530 \brief the directory for storing offline user data
1532 Returns the directory where SQL and other offline
1535 QDeclarativeWebView and the SQL databases created with openDatabase()
1538 The default is QML/OfflineStorage in the platform-standard
1539 user application data directory.
1541 Note that the path may not currently exist on the filesystem, so
1542 callers wanting to \e create new files at this location should create
1543 it first - see QDir::mkpath().
1545 void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
1547 Q_D(QDeclarativeEngine);
1548 d->offlineStoragePath = dir;
1551 QString QDeclarativeEngine::offlineStoragePath() const
1553 Q_D(const QDeclarativeEngine);
1554 return d->offlineStoragePath;
1557 static void voidptr_destructor(void *v)
1559 void **ptr = (void **)v;
1563 static void *voidptr_constructor(const void *v)
1568 return new void*(*(void **)v);
1572 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo)
1574 Q_Q(QDeclarativeEngine);
1576 if (!mo->superClass()) {
1577 QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo);
1578 propertyCache.insert(mo, rv);
1581 QDeclarativePropertyCache *super = cache(mo->superClass());
1582 QDeclarativePropertyCache *rv = super->copyAndAppend(q, mo);
1583 propertyCache.insert(mo, rv);
1588 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
1589 QDeclarativeError &error)
1591 QList<QDeclarativeType *> types;
1593 int maxMinorVersion = 0;
1595 const QMetaObject *metaObject = type->metaObject();
1597 while (metaObject) {
1598 QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
1599 type->majorVersion(), minorVersion);
1601 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1607 metaObject = metaObject->superClass();
1610 if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1612 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1616 QDeclarativePropertyCache *raw = cache(type->metaObject());
1618 bool hasCopied = false;
1620 for (int ii = 0; ii < types.count(); ++ii) {
1621 QDeclarativeType *currentType = types.at(ii);
1625 int rev = currentType->metaObjectRevision();
1626 int moIndex = types.count() - 1 - ii;
1628 if (raw->allowedRevisionCache[moIndex] != rev) {
1633 raw->allowedRevisionCache[moIndex] = rev;
1637 // Test revision compatibility - the basic rule is:
1638 // * Anything that is excluded, cannot overload something that is not excluded *
1640 // Signals override:
1641 // * other signals and methods of the same name.
1642 // * properties named on<Signal Name>
1643 // * automatic <property name>Changed notify signals
1645 // Methods override:
1646 // * other methods of the same name
1648 // Properties override:
1649 // * other elements of the same name
1651 bool overloadError = false;
1652 QString overloadName;
1655 for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1656 !overloadError && iter != raw->stringCache.end();
1659 QDeclarativePropertyData *d = *iter;
1660 if (raw->isAllowedInRevision(d))
1661 continue; // Not excluded - no problems
1663 // check that a regular "name" overload isn't happening
1664 QDeclarativePropertyData *current = d;
1665 while (!overloadError && current) {
1666 current = d->overrideData(current);
1667 if (current && raw->isAllowedInRevision(current))
1668 overloadError = true;
1673 if (overloadError) {
1674 if (hasCopied) raw->release();
1676 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."));
1680 if (!hasCopied) raw->addref();
1681 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1683 if (minorVersion != maxMinorVersion) {
1685 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1691 QDeclarativeMetaType::ModuleApiInstance *
1692 QDeclarativeEnginePrivate::moduleApiInstance(const QDeclarativeMetaType::ModuleApi &module)
1694 Locker locker(this);
1696 QDeclarativeMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1698 a = new QDeclarativeMetaType::ModuleApiInstance;
1699 a->scriptCallback = module.script;
1700 a->qobjectCallback = module.qobject;
1701 moduleApiInstances.insert(module, a);
1707 bool QDeclarativeEnginePrivate::isQObject(int t)
1709 Locker locker(this);
1710 return m_compositeTypes.contains(t) || QDeclarativeMetaType::isQObject(t);
1713 QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1715 Locker locker(this);
1716 int t = v.userType();
1717 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1719 return *(QObject **)(v.constData());
1721 return QDeclarativeMetaType::toQObject(v, ok);
1725 QDeclarativeMetaType::TypeCategory QDeclarativeEnginePrivate::typeCategory(int t) const
1727 Locker locker(this);
1728 if (m_compositeTypes.contains(t))
1729 return QDeclarativeMetaType::Object;
1730 else if (m_qmlLists.contains(t))
1731 return QDeclarativeMetaType::List;
1733 return QDeclarativeMetaType::typeCategory(t);
1736 bool QDeclarativeEnginePrivate::isList(int t) const
1738 Locker locker(this);
1739 return m_qmlLists.contains(t) || QDeclarativeMetaType::isList(t);
1742 int QDeclarativeEnginePrivate::listType(int t) const
1744 Locker locker(this);
1745 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1746 if (iter != m_qmlLists.end())
1749 return QDeclarativeMetaType::listType(t);
1752 const QMetaObject *QDeclarativeEnginePrivate::rawMetaObjectForType(int t) const
1754 Locker locker(this);
1755 QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1756 if (iter != m_compositeTypes.end()) {
1757 return (*iter)->root;
1759 QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1760 return type?type->baseMetaObject():0;
1764 const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const
1766 Locker locker(this);
1767 QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1768 if (iter != m_compositeTypes.end()) {
1769 return (*iter)->root;
1771 QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1772 return type?type->metaObject():0;
1776 void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data)
1778 QByteArray name = data->root->className();
1780 QByteArray ptr = name + '*';
1781 QByteArray lst = "QDeclarativeListProperty<" + name + '>';
1783 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1784 voidptr_constructor);
1785 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1786 voidptr_constructor);
1790 Locker locker(this);
1791 m_qmlLists.insert(lst_type, ptr_type);
1792 m_compositeTypes.insert(ptr_type, data);
1795 bool QDeclarative_isFileCaseCorrect(const QString &fileName)
1797 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1798 QFileInfo info(fileName);
1799 const QString absolute = info.absoluteFilePath();
1801 #if defined(Q_OS_MAC)
1802 const QString canonical = info.canonicalFilePath();
1803 #elif defined(Q_OS_WIN)
1804 wchar_t buffer[1024];
1806 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1807 if (rv == 0 || rv >= 1024) return true;
1808 rv = ::GetLongPathName(buffer, buffer, 1024);
1809 if (rv == 0 || rv >= 1024) return true;
1811 const QString canonical = QString::fromWCharArray(buffer);
1814 const int absoluteLength = absolute.length();
1815 const int canonicalLength = canonical.length();
1817 const int length = qMin(absoluteLength, canonicalLength);
1818 for (int ii = 0; ii < length; ++ii) {
1819 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1820 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1822 if (a.toLower() != c.toLower())
1834 \fn QDeclarativeEngine *qmlEngine(const QObject *object)
1835 \relates QDeclarativeEngine
1837 Returns the QDeclarativeEngine associated with \a object, if any. This is equivalent to
1838 QDeclarativeEngine::contextForObject(object)->engine(), but more efficient.
1842 \fn QDeclarativeContext *qmlContext(const QObject *object)
1843 \relates QDeclarativeEngine
1845 Returns the QDeclarativeContext associated with \a object, if any. This is equivalent to
1846 QDeclarativeEngine::contextForObject(object).