1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qdeclarativeengine_p.h"
43 #include "qdeclarativeengine.h"
45 #include "qdeclarativecontext_p.h"
46 #include "qdeclarativecompiler_p.h"
47 #include "qdeclarative.h"
48 #include "qdeclarativecontext.h"
49 #include "qdeclarativeexpression.h"
50 #include "qdeclarativecomponent.h"
51 #include "qdeclarativebinding_p_p.h"
52 #include "qdeclarativevme_p.h"
53 #include <private/qdeclarativeenginedebugservice_p.h>
54 #include "qdeclarativestringconverters_p.h"
55 #include "qdeclarativexmlhttprequest_p.h"
56 #include "qdeclarativesqldatabase_p.h"
57 #include "qdeclarativescriptstring.h"
58 #include "qdeclarativeglobal_p.h"
59 #include "qdeclarativeworkerscript_p.h"
60 #include "qdeclarativecomponent_p.h"
61 #include "qdeclarativenetworkaccessmanagerfactory.h"
62 #include "qdeclarativeimageprovider.h"
63 #include "qdeclarativedirparser_p.h"
64 #include "qdeclarativeextensioninterface.h"
65 #include "qdeclarativelist_p.h"
66 #include "qdeclarativetypenamecache_p.h"
67 #include "qdeclarativenotifier_p.h"
68 #include <private/qdeclarativedebugtrace_p.h>
69 #include <private/qdeclarativeapplication_p.h>
70 #include <private/qv8debugservice_p.h>
71 #include "qdeclarativeincubator.h"
72 #include <private/qv8profilerservice_p.h>
74 #include <QtCore/qmetaobject.h>
75 #include <QNetworkAccessManager>
77 #include <QMetaObject>
78 #include <QtCore/qcoreapplication.h>
79 #include <QtCore/qdir.h>
80 #include <QtCore/qmutex.h>
81 #include <QtNetwork/qnetworkconfigmanager.h>
83 #include <private/qobject_p.h>
85 #include <private/qdeclarativeutilmodule_p.h>
86 #include <private/qquickitemsmodule_p.h>
87 #include <private/qquickparticlesmodule_p.h>
89 #ifdef Q_OS_WIN // for %APPDATA%
90 #include <qt_windows.h>
94 #define CSIDL_APPDATA 0x001a // <username>\Application Data
97 Q_DECLARE_METATYPE(QDeclarativeProperty)
101 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
103 QDeclarativeEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
104 QDeclarativeValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
105 QDeclarativeUtilModule::registerBaseTypes(uri, versionMajor, versionMinor);
109 \qmlclass QtObject QObject
110 \ingroup qml-utility-elements
112 \brief The QtObject element is the most basic element in QML.
114 The QtObject element is a non-visual element which contains only the
117 It can be useful to create a QtObject if you need an extremely
118 lightweight element to enclose a set of custom properties:
120 \snippet doc/src/snippets/declarative/qtobject.qml 0
122 It can also be useful for C++ integration, as it is just a plain
123 QObject. See the QObject documentation for further details.
126 \qmlproperty string QtObject::objectName
127 This property holds the QObject::objectName for this specific object instance.
129 This allows a C++ application to locate an item within a QML component
130 using the QObject::findChild() method. For example, the following C++
131 application locates the child \l Rectangle item and dynamically changes its
140 width: 200; height: 200
153 QDeclarativeView view;
154 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
157 QDeclarativeItem *item = view.rootObject()->findChild<QDeclarativeItem*>("myRect");
159 item->setProperty("color", QColor(Qt::yellow));
163 static bool qt_QmlQtModule_registered = false;
164 bool QDeclarativeEnginePrivate::qml_debugging_enabled = false;
166 void QDeclarativeEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
168 qmlRegisterType<QDeclarativeComponent>(uri,versionMajor,versionMinor,"Component");
169 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
170 qmlRegisterType<QDeclarativeWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
173 void QDeclarativeEnginePrivate::defineModule()
175 registerBaseTypes("QtQuick", 2, 0);
176 qmlRegisterType<QDeclarativeBinding>();
180 \qmlclass Qt QDeclarativeEnginePrivate
181 \ingroup qml-utility-elements
182 \brief The QML global Qt object provides useful enums and functions from Qt.
184 \keyword QmlGlobalQtObject
186 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
188 The \c Qt object is a global object with utility functions, properties and enums.
190 It is not instantiable; to use it, call the members of the global \c Qt object directly.
197 color: Qt.rgba(1, 0, 0, 1)
198 text: Qt.md5("hello, world")
205 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
206 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
210 The Qt object also contains helper functions for creating objects of specific
211 data types. This is primarily useful when setting the properties of an item
212 when the property has one of the following types:
215 \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()}
216 \o \c rect - use \l{Qt::rect()}{Qt.rect()}
217 \o \c point - use \l{Qt::point()}{Qt.point()}
218 \o \c size - use \l{Qt::size()}{Qt.size()}
219 \o \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
222 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
224 \section1 Date/Time Formatters
226 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
229 \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
230 \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
231 \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
234 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
237 \section1 Dynamic Object Creation
238 The following functions on the global object allow you to dynamically create QML
239 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
243 \o \l{Qt::createComponent()}{object Qt.createComponent(url)}
244 \o \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
250 \qmlproperty object Qt::application
253 The \c application object provides access to global application state
254 properties shared by many QML components.
260 \o \c application.active
262 This read-only property indicates whether the application is the top-most and focused
263 application, and the user is able to interact with the application. The property
264 is false when the application is in the background, the device keylock or screen
265 saver is active, the screen backlight is turned off, or the global system dialog
266 is being displayed on top of the application. It can be used for stopping and
267 pausing animations, timers and active processing of data in order to save device
268 battery power and free device memory and processor load when the application is not
272 \o \c application.layoutDirection
274 This read-only property can be used to query the default layout direction of the
275 application. On system start-up, the default layout direction depends on the
276 application's language. The property has a value of \c Qt.RightToLeft in locales
277 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
278 where the reading direction flows from left to right. You can bind to this
279 property to customize your application layouts to support both layout directions.
284 \o Qt.LeftToRight - Text and graphics elements should be positioned
286 \o Qt.RightToLeft - Text and graphics elements should be positioned
291 \o \c application.inputPanel
293 This read-only property allows access to application's QInputPanel object
294 and all its properties and slots. See the QInputPanel documentation for
298 The following example uses the \c application object to indicate
299 whether the application is currently active:
301 \snippet doc/src/snippets/declarative/application.qml document
307 \qmlmethod object Qt::include(string url, jsobject callback)
309 Includes another JavaScript file. This method can only be used from within JavaScript files,
310 and not regular QML files.
312 This imports all functions from \a url into the current script's namespace.
314 Qt.include() returns an object that describes the status of the operation. The object has
315 a single property, \c {status}, that is set to one of the following values:
318 \header \o Symbol \o Value \o Description
319 \row \o result.OK \o 0 \o The include completed successfully.
320 \row \o result.LOADING \o 1 \o Data is being loaded from the network.
321 \row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url.
322 \row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code.
323 An additional \c exception property will be set in this case.
326 The \c status property will be updated as the operation progresses.
328 If provided, \a callback is invoked when the operation completes. The callback is passed
329 the same object as is returned from the Qt.include() call.
331 // Qt.include() is implemented in qv8include.cpp
334 QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
335 : propertyCapture(0), rootContext(0), isDebugging(false),
336 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
337 cleanup(0), erroredBindings(0), inProgressCreations(0),
338 workerScriptEngine(0), activeVME(0),
339 networkAccessManager(0), networkAccessManagerFactory(0),
340 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
341 incubatorCount(0), incubationController(0), sgContext(0), mutex(QMutex::Recursive)
343 if (!qt_QmlQtModule_registered) {
344 qt_QmlQtModule_registered = true;
345 QDeclarativeUtilModule::defineModule();
346 QDeclarativeEnginePrivate::defineModule();
347 QQuickItemsModule::defineModule();
348 QQuickParticlesModule::defineModule();
349 QDeclarativeValueTypeFactory::registerValueTypes();
353 QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate()
355 Q_ASSERT(inProgressCreations == 0);
358 QDeclarativeCleanup *c = cleanup;
360 if (cleanup) cleanup->prev = &cleanup;
366 doDeleteInEngineThread();
368 if (incubationController) incubationController->d = 0;
369 incubationController = 0;
374 for(QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
376 for(QHash<const QMetaObject *, QDeclarativePropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
378 for(QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
380 for(QHash<QDeclarativeMetaType::ModuleApi, QDeclarativeMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
381 delete (*iter)->qobjectApi;
386 void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *o)
388 QObjectPrivate *p = QObjectPrivate::get(o);
389 if (p->declarativeData) {
390 QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
391 if (d->ownContext && d->context) {
392 d->context->destroy();
398 void QDeclarativeData::destroyed(QAbstractDeclarativeData *d, QObject *o)
400 static_cast<QDeclarativeData *>(d)->destroyed(o);
403 void QDeclarativeData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
405 static_cast<QDeclarativeData *>(d)->parentChanged(o, p);
408 void QDeclarativeData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
410 static_cast<QDeclarativeData *>(d)->objectNameChanged(o);
413 void QDeclarativeData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
415 QDeclarativeData *ddata = QDeclarativeData::get(object, false);
416 if (!ddata) return; // Probably being deleted
418 QDeclarativeNotifierEndpoint *ep = ddata->notify(index);
419 if (ep) QDeclarativeNotifier::emitNotify(ep);
422 void QDeclarativeEnginePrivate::init()
424 Q_Q(QDeclarativeEngine);
426 static bool firstTime = true;
428 // This is a nasty hack as QNetworkAccessManager will issue a
429 // BlockingQueuedConnection to the main thread if it is initialized for the
430 // first time on a non-main thread. This can cause a lockup if the main thread
431 // is blocking on the thread that initialize the network access manager.
432 QNetworkConfigurationManager man;
437 qRegisterMetaType<QVariant>("QVariant");
438 qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString");
439 qRegisterMetaType<QJSValue>("QJSValue");
440 qRegisterMetaType<QDeclarativeComponent::Status>("QDeclarativeComponent::Status");
441 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
442 qRegisterMetaType<QList<int> >("QList<int>");
443 qRegisterMetaType<QDeclarativeV8Handle>("QDeclarativeV8Handle");
445 QDeclarativeData::init();
447 v8engine()->setEngine(q);
449 rootContext = new QDeclarativeContext(q,true);
451 if (QCoreApplication::instance()->thread() == q->thread() &&
452 QDeclarativeEngineDebugService::isDebuggingEnabled()) {
454 QDeclarativeEngineDebugService::instance()->addEngine(q);
455 QV8DebugService::instance()->addEngine(q);
456 QV8ProfilerService::instance()->addEngine(q);
457 QDeclarativeDebugTrace::addEngine(q);
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);
522 QV8DebugService::instance()->removeEngine(this);
523 QV8ProfilerService::instance()->removeEngine(this);
524 QDeclarativeDebugTrace::removeEngine(this);
527 // if we are the parent of any of the qobject module api instances,
528 // we need to remove them from our internal list, in order to prevent
529 // a segfault in engine private dtor.
530 QList<QDeclarativeMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
531 QObject *currQObjectApi = 0;
532 QDeclarativeMetaType::ModuleApiInstance *currInstance = 0;
533 foreach (const QDeclarativeMetaType::ModuleApi &key, keys) {
534 currInstance = d->moduleApiInstances.value(key);
535 currQObjectApi = currInstance->qobjectApi;
536 if (this->children().contains(currQObjectApi)) {
537 delete currQObjectApi;
539 d->moduleApiInstances.remove(key);
543 // ensure we clean up QObjects with JS ownership
546 if (d->incubationController)
547 d->incubationController->d = 0;
550 /*! \fn void QDeclarativeEngine::quit()
551 This signal is emitted when the QML loaded by the engine would like to quit.
554 /*! \fn void QDeclarativeEngine::warnings(const QList<QDeclarativeError> &warnings)
555 This signal is emitted when \a warnings messages are generated by QML.
559 Clears the engine's internal component cache.
561 Normally the QDeclarativeEngine caches components loaded from qml
562 files. This method clears this cache and forces the component to be
565 void QDeclarativeEngine::clearComponentCache()
567 Q_D(QDeclarativeEngine);
568 d->typeLoader.clearCache();
572 Returns the engine's root context.
574 The root context is automatically created by the QDeclarativeEngine.
575 Data that should be available to all QML component instances
576 instantiated by the engine should be put in the root context.
578 Additional data that should only be available to a subset of
579 component instances should be added to sub-contexts parented to the
582 QDeclarativeContext *QDeclarativeEngine::rootContext() const
584 Q_D(const QDeclarativeEngine);
585 return d->rootContext;
589 Sets the \a factory to use for creating QNetworkAccessManager(s).
591 QNetworkAccessManager is used for all network access by QML. By
592 implementing a factory it is possible to create custom
593 QNetworkAccessManager with specialized caching, proxy and cookie
596 The factory must be set before executing the engine.
598 void QDeclarativeEngine::setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *factory)
600 Q_D(QDeclarativeEngine);
601 QMutexLocker locker(&d->mutex);
602 d->networkAccessManagerFactory = factory;
606 Returns the current QDeclarativeNetworkAccessManagerFactory.
608 \sa setNetworkAccessManagerFactory()
610 QDeclarativeNetworkAccessManagerFactory *QDeclarativeEngine::networkAccessManagerFactory() const
612 Q_D(const QDeclarativeEngine);
613 return d->networkAccessManagerFactory;
616 void QDeclarativeEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
619 activeVME->finalizeCallbacks.append(qMakePair(QDeclarativeGuard<QObject>(obj), index));
621 void *args[] = { 0 };
622 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
626 QNetworkAccessManager *QDeclarativeEnginePrivate::createNetworkAccessManager(QObject *parent) const
628 QMutexLocker locker(&mutex);
629 QNetworkAccessManager *nam;
630 if (networkAccessManagerFactory) {
631 nam = networkAccessManagerFactory->create(parent);
633 nam = new QNetworkAccessManager(parent);
639 QNetworkAccessManager *QDeclarativeEnginePrivate::getNetworkAccessManager() const
641 Q_Q(const QDeclarativeEngine);
642 if (!networkAccessManager)
643 networkAccessManager = createNetworkAccessManager(const_cast<QDeclarativeEngine*>(q));
644 return networkAccessManager;
648 Returns a common QNetworkAccessManager which can be used by any QML
649 element instantiated by this engine.
651 If a QDeclarativeNetworkAccessManagerFactory has been set and a
652 QNetworkAccessManager has not yet been created, the
653 QDeclarativeNetworkAccessManagerFactory will be used to create the
654 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
655 will have no proxy or cache set.
657 \sa setNetworkAccessManagerFactory()
659 QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
661 Q_D(const QDeclarativeEngine);
662 return d->getNetworkAccessManager();
667 Sets the \a provider to use for images requested via the \e
668 image: url scheme, with host \a providerId. The QDeclarativeEngine
669 takes ownership of \a provider.
671 Image providers enable support for pixmap and threaded image
672 requests. See the QDeclarativeImageProvider documentation for details on
673 implementing and using image providers.
675 All required image providers should be added to the engine before any
676 QML sources files are loaded.
678 \sa removeImageProvider()
680 void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativeImageProvider *provider)
682 Q_D(QDeclarativeEngine);
683 QMutexLocker locker(&d->mutex);
684 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QDeclarativeImageProvider>(provider));
688 Returns the QDeclarativeImageProvider set for \a providerId.
690 Returns the provider if it was found; otherwise returns 0.
692 QDeclarativeImageProvider *QDeclarativeEngine::imageProvider(const QString &providerId) const
694 Q_D(const QDeclarativeEngine);
695 QMutexLocker locker(&d->mutex);
696 return d->imageProviders.value(providerId).data();
700 Removes the QDeclarativeImageProvider for \a providerId.
702 \sa addImageProvider()
704 void QDeclarativeEngine::removeImageProvider(const QString &providerId)
706 Q_D(QDeclarativeEngine);
707 QMutexLocker locker(&d->mutex);
708 d->imageProviders.take(providerId);
711 QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProviderType(const QUrl &url)
713 QMutexLocker locker(&mutex);
714 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
717 return provider->imageType();
718 return QDeclarativeImageProvider::Invalid;
721 QSGTexture *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
723 QMutexLocker locker(&mutex);
724 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
727 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
728 return provider->requestTexture(imageId, size, req_size);
733 QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
735 QMutexLocker locker(&mutex);
737 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
740 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
741 image = provider->requestImage(imageId, size, req_size);
746 QPixmap QDeclarativeEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
748 QMutexLocker locker(&mutex);
750 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
753 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
754 pixmap = provider->requestPixmap(imageId, size, req_size);
760 Return the base URL for this engine. The base URL is only used to
761 resolve components when a relative URL is passed to the
762 QDeclarativeComponent constructor.
764 If a base URL has not been explicitly set, this method returns the
765 application's current working directory.
769 QUrl QDeclarativeEngine::baseUrl() const
771 Q_D(const QDeclarativeEngine);
772 if (d->baseUrl.isEmpty()) {
773 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
780 Set the base URL for this engine to \a url.
784 void QDeclarativeEngine::setBaseUrl(const QUrl &url)
786 Q_D(QDeclarativeEngine);
791 Returns true if warning messages will be output to stderr in addition
792 to being emitted by the warnings() signal, otherwise false.
794 The default value is true.
796 bool QDeclarativeEngine::outputWarningsToStandardError() const
798 Q_D(const QDeclarativeEngine);
799 return d->outputWarningsToStdErr;
803 Set whether warning messages will be output to stderr to \a enabled.
805 If \a enabled is true, any warning messages generated by QML will be
806 output to stderr and emitted by the warnings() signal. If \a enabled
807 is false, on the warnings() signal will be emitted. This allows
808 applications to handle warning output themselves.
810 The default value is true.
812 void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled)
814 Q_D(QDeclarativeEngine);
815 d->outputWarningsToStdErr = enabled;
819 Attempt to free unused memory.
821 void QDeclarativeEngine::collectGarbage()
827 Returns the QDeclarativeContext for the \a object, or 0 if no
828 context has been set.
830 When the QDeclarativeEngine instantiates a QObject, the context is
833 QDeclarativeContext *QDeclarativeEngine::contextForObject(const QObject *object)
838 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
840 QDeclarativeData *data =
841 static_cast<QDeclarativeData *>(priv->declarativeData);
845 else if (data->outerContext)
846 return data->outerContext->asQDeclarativeContext();
852 Sets the QDeclarativeContext for the \a object to \a context.
853 If the \a object already has a context, a warning is
854 output, but the context is not changed.
856 When the QDeclarativeEngine instantiates a QObject, the context is
859 void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContext *context)
861 if (!object || !context)
864 QDeclarativeData *data = QDeclarativeData::get(object, true);
866 qWarning("QDeclarativeEngine::setContextForObject(): Object already has a QDeclarativeContext");
870 QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
871 contextData->addObject(object);
875 \enum QDeclarativeEngine::ObjectOwnership
877 Ownership controls whether or not QML automatically destroys the
878 QObject when the object is garbage collected by the JavaScript
879 engine. The two ownership options are:
881 \value CppOwnership The object is owned by C++ code, and will
882 never be deleted by QML. The JavaScript destroy() method cannot be
883 used on objects with CppOwnership. This option is similar to
884 QScriptEngine::QtOwnership.
886 \value JavaScriptOwnership The object is owned by JavaScript.
887 When the object is returned to QML as the return value of a method
888 call or property access, QML will delete the object if there are no
889 remaining JavaScript references to it and it has no
890 QObject::parent(). This option is similar to
891 QScriptEngine::ScriptOwnership.
893 Generally an application doesn't need to set an object's ownership
894 explicitly. QML uses a heuristic to set the default object
895 ownership. By default, an object that is created by QML has
896 JavaScriptOwnership. The exception to this are the root objects
897 created by calling QDeclarativeCompnent::create() or
898 QDeclarativeComponent::beginCreate() which have CppOwnership by
899 default. The ownership of these root-level objects is considered to
900 have been transferred to the C++ caller.
902 Objects not-created by QML have CppOwnership by default. The
903 exception to this is objects returned from a C++ method call. The
904 ownership of these objects is passed to JavaScript.
906 Calling setObjectOwnership() overrides the default ownership
907 heuristic used by QML.
911 Sets the \a ownership of \a object.
913 void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
918 QDeclarativeData *ddata = QDeclarativeData::get(object, true);
922 ddata->indestructible = (ownership == CppOwnership)?true:false;
923 ddata->explicitIndestructibleSet = true;
927 Returns the ownership of \a object.
929 QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object)
934 QDeclarativeData *ddata = QDeclarativeData::get(object, false);
938 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
941 bool QDeclarativeEngine::event(QEvent *e)
943 Q_D(QDeclarativeEngine);
944 if (e->type() == QEvent::User)
945 d->doDeleteInEngineThread();
947 return QJSEngine::event(e);
950 void QDeclarativeEnginePrivate::doDeleteInEngineThread()
952 QFieldList<Deletable, &Deletable::next> list;
954 list.copyAndClear(toDeleteInEngineThread);
957 while (Deletable *d = list.takeFirst())
961 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
963 QDeclarativeData *data = QDeclarativeData::get(object);
965 if (data && data->deferredComponent) {
966 if (QDeclarativeDebugService::isDebuggingEnabled()) {
967 QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
968 QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
969 QString typeName = type ? type->qmlTypeName() : QString::fromUtf8(object->metaObject()->className());
970 QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, typeName);
971 if (data->outerContext)
972 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, data->outerContext->url, data->lineNumber);
974 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine);
976 QDeclarativeComponentPrivate::ConstructionState state;
977 QDeclarativeComponentPrivate::beginDeferred(ep, object, &state);
979 data->deferredComponent->release();
980 data->deferredComponent = 0;
982 QDeclarativeComponentPrivate::complete(ep, &state);
983 QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
987 QDeclarativeContext *qmlContext(const QObject *obj)
989 return QDeclarativeEngine::contextForObject(obj);
992 QDeclarativeEngine *qmlEngine(const QObject *obj)
994 QDeclarativeData *data = QDeclarativeData::get(obj, false);
995 if (!data || !data->context)
997 return data->context->engine;
1000 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1002 QDeclarativeData *data = QDeclarativeData::get(object);
1004 return 0; // Attached properties are only on objects created by QML
1006 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1010 QDeclarativeAttachedPropertiesFunc pf = QDeclarativeMetaType::attachedPropertiesFuncById(id);
1014 rv = pf(const_cast<QObject *>(object));
1017 data->attachedProperties()->insert(id, rv);
1022 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1023 const QMetaObject *attachedMetaObject, bool create)
1026 *idCache = QDeclarativeMetaType::attachedPropertiesFuncId(attachedMetaObject);
1028 if (*idCache == -1 || !object)
1031 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1034 QDeclarativeDebuggingEnabler::QDeclarativeDebuggingEnabler()
1036 #ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
1037 if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
1038 qWarning("Qml debugging is enabled. Only use this in a safe environment!");
1040 QDeclarativeEnginePrivate::qml_debugging_enabled = true;
1045 class QDeclarativeDataExtended {
1047 QDeclarativeDataExtended();
1048 ~QDeclarativeDataExtended();
1050 QHash<int, QObject *> attachedProperties;
1051 QDeclarativeNotifier objectNameNotifier;
1054 QDeclarativeDataExtended::QDeclarativeDataExtended()
1058 QDeclarativeDataExtended::~QDeclarativeDataExtended()
1062 void QDeclarativeData::NotifyList::layout(QDeclarativeNotifierEndpoint *endpoint)
1065 layout(endpoint->next);
1067 int index = endpoint->sourceSignal;
1068 index = qMin(index, 0xFFFF - 1);
1070 endpoint->next = notifies[index];
1071 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1072 endpoint->prev = ¬ifies[index];
1073 notifies[index] = endpoint;
1076 void QDeclarativeData::NotifyList::layout()
1078 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1081 QDeclarativeNotifierEndpoint **old = notifies;
1082 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QDeclarativeNotifierEndpoint*);
1083 notifies = (QDeclarativeNotifierEndpoint**)realloc(notifies, reallocSize);
1084 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1085 sizeof(QDeclarativeNotifierEndpoint*);
1086 memset(notifies + notifiesSize, 0, memsetSize);
1088 if (notifies != old) {
1089 for (int ii = 0; ii < notifiesSize; ++ii)
1091 notifies[ii]->prev = ¬ifies[ii];
1094 notifiesSize = maximumTodoIndex + 1;
1099 maximumTodoIndex = 0;
1103 void QDeclarativeData::addNotify(int index, QDeclarativeNotifierEndpoint *endpoint)
1106 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1107 notifyList->connectionMask = 0;
1108 notifyList->maximumTodoIndex = 0;
1109 notifyList->notifiesSize = 0;
1110 notifyList->todo = 0;
1111 notifyList->notifies = 0;
1114 Q_ASSERT(!endpoint->isConnected());
1116 index = qMin(index, 0xFFFF - 1);
1117 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1119 if (index < notifyList->notifiesSize) {
1121 endpoint->next = notifyList->notifies[index];
1122 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1123 endpoint->prev = ¬ifyList->notifies[index];
1124 notifyList->notifies[index] = endpoint;
1127 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1129 endpoint->next = notifyList->todo;
1130 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1131 endpoint->prev = ¬ifyList->todo;
1132 notifyList->todo = endpoint;
1136 QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const
1138 if (!extendedData) extendedData = new QDeclarativeDataExtended;
1139 return &extendedData->objectNameNotifier;
1142 QHash<int, QObject *> *QDeclarativeData::attachedProperties() const
1144 if (!extendedData) extendedData = new QDeclarativeDataExtended;
1145 return &extendedData->attachedProperties;
1148 void QDeclarativeData::destroyed(QObject *object)
1150 if (deferredComponent)
1151 deferredComponent->release();
1153 if (nextContextObject)
1154 nextContextObject->prevContextObject = prevContextObject;
1155 if (prevContextObject)
1156 *prevContextObject = nextContextObject;
1158 QDeclarativeAbstractBinding *binding = bindings;
1160 QDeclarativeAbstractBinding *next = binding->m_nextBinding;
1161 binding->m_prevBinding = 0;
1162 binding->m_nextBinding = 0;
1171 propertyCache->release();
1173 if (ownContext && context)
1177 QDeclarativeGuard<QObject> *guard = static_cast<QDeclarativeGuard<QObject> *>(guards);
1178 *guard = (QObject *)0;
1179 guard->objectDestroyed(object);
1183 while (notifyList->todo)
1184 notifyList->todo->disconnect();
1185 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1186 while (QDeclarativeNotifierEndpoint *ep = notifyList->notifies[ii])
1189 free(notifyList->notifies);
1194 delete extendedData;
1196 v8object.Clear(); // The WeakReference handler will clean the actual handle
1202 void QDeclarativeData::parentChanged(QObject *object, QObject *parent)
1208 void QDeclarativeData::objectNameChanged(QObject *)
1210 if (extendedData) objectNameNotifier()->notify();
1213 bool QDeclarativeData::hasBindingBit(int bit) const
1215 if (bindingBitsSize > bit)
1216 return bindingBits[bit / 32] & (1 << (bit % 32));
1221 void QDeclarativeData::clearBindingBit(int bit)
1223 if (bindingBitsSize > bit)
1224 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1227 void QDeclarativeData::setBindingBit(QObject *obj, int bit)
1229 if (bindingBitsSize <= bit) {
1230 int props = obj->metaObject()->propertyCount();
1231 Q_ASSERT(bit < props);
1233 int arraySize = (props + 31) / 32;
1234 int oldArraySize = bindingBitsSize / 32;
1236 bindingBits = (quint32 *)realloc(bindingBits,
1237 arraySize * sizeof(quint32));
1239 memset(bindingBits + oldArraySize,
1241 sizeof(quint32) * (arraySize - oldArraySize));
1243 bindingBitsSize = arraySize * 32;
1246 bindingBits[bit / 32] |= (1 << (bit % 32));
1249 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1251 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1252 if (url.authority().isEmpty())
1253 return QLatin1Char(':') + url.path();
1256 return url.toLocalFile();
1260 static QString toLocalFile(const QString &url)
1262 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1265 QString file = url.mid(7);
1267 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1269 // magic for drives on windows
1270 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1276 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1278 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1279 if (url.length() > 4)
1280 return QLatin1Char(':') + url.mid(4);
1284 return toLocalFile(url);
1287 void QDeclarativeEnginePrivate::sendQuit()
1289 Q_Q(QDeclarativeEngine);
1291 if (q->receivers(SIGNAL(quit())) == 0) {
1292 qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it.");
1296 static void dumpwarning(const QDeclarativeError &error)
1298 qWarning().nospace() << qPrintable(error.toString());
1301 static void dumpwarning(const QList<QDeclarativeError> &errors)
1303 for (int ii = 0; ii < errors.count(); ++ii)
1304 dumpwarning(errors.at(ii));
1307 void QDeclarativeEnginePrivate::warning(const QDeclarativeError &error)
1309 Q_Q(QDeclarativeEngine);
1310 q->warnings(QList<QDeclarativeError>() << error);
1311 if (outputWarningsToStdErr)
1315 void QDeclarativeEnginePrivate::warning(const QList<QDeclarativeError> &errors)
1317 Q_Q(QDeclarativeEngine);
1318 q->warnings(errors);
1319 if (outputWarningsToStdErr)
1320 dumpwarning(errors);
1323 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QDeclarativeError &error)
1326 QDeclarativeEnginePrivate::get(engine)->warning(error);
1331 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QList<QDeclarativeError> &error)
1334 QDeclarativeEnginePrivate::get(engine)->warning(error);
1339 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QDeclarativeError &error)
1342 engine->warning(error);
1347 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QList<QDeclarativeError> &error)
1350 engine->warning(error);
1356 This function should be called prior to evaluation of any js expression,
1357 so that scarce resources are not freed prematurely (eg, if there is a
1358 nested javascript expression).
1360 void QDeclarativeEnginePrivate::referenceScarceResources()
1362 scarceResourcesRefCount += 1;
1366 This function should be called after evaluation of the js expression is
1367 complete, and so the scarce resources may be freed safely.
1369 void QDeclarativeEnginePrivate::dereferenceScarceResources()
1371 Q_ASSERT(scarceResourcesRefCount > 0);
1372 scarceResourcesRefCount -= 1;
1374 // if the refcount is zero, then evaluation of the "top level"
1375 // expression must have completed. We can safely release the
1376 // scarce resources.
1377 if (scarceResourcesRefCount == 0) {
1378 // iterate through the list and release them all.
1379 // note that the actual SRD is owned by the JS engine,
1380 // so we cannot delete the SRD; but we can free the
1381 // memory used by the variant in the SRD.
1382 while (ScarceResourceData *sr = scarceResources.first()) {
1383 sr->data = QVariant();
1384 scarceResources.remove(sr);
1390 Adds \a path as a directory where the engine searches for
1391 installed modules in a URL-based directory structure.
1392 The \a path may be a local filesystem directory or a URL.
1394 The newly added \a path will be first in the importPathList().
1396 \sa setImportPathList(), {QML Modules}
1398 void QDeclarativeEngine::addImportPath(const QString& path)
1400 Q_D(QDeclarativeEngine);
1401 d->importDatabase.addImportPath(path);
1405 Returns the list of directories where the engine searches for
1406 installed modules in a URL-based directory structure.
1408 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1409 imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look
1410 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1411 provided by that module. A \c qmldir file is required for defining the
1412 type version mapping and possibly declarative extensions plugins.
1414 By default, the list contains the directory of the application executable,
1415 paths specified in the \c QML_IMPORT_PATH environment variable,
1416 and the builtin \c ImportsPath from QLibraryInfo.
1418 \sa addImportPath() setImportPathList()
1420 QStringList QDeclarativeEngine::importPathList() const
1422 Q_D(const QDeclarativeEngine);
1423 return d->importDatabase.importPathList();
1427 Sets \a paths as the list of directories where the engine searches for
1428 installed modules in a URL-based directory structure.
1430 By default, the list contains the directory of the application executable,
1431 paths specified in the \c QML_IMPORT_PATH environment variable,
1432 and the builtin \c ImportsPath from QLibraryInfo.
1434 \sa importPathList() addImportPath()
1436 void QDeclarativeEngine::setImportPathList(const QStringList &paths)
1438 Q_D(QDeclarativeEngine);
1439 d->importDatabase.setImportPathList(paths);
1444 Adds \a path as a directory where the engine searches for
1445 native plugins for imported modules (referenced in the \c qmldir file).
1447 By default, the list contains only \c ., i.e. the engine searches
1448 in the directory of the \c qmldir file itself.
1450 The newly added \a path will be first in the pluginPathList().
1452 \sa setPluginPathList()
1454 void QDeclarativeEngine::addPluginPath(const QString& path)
1456 Q_D(QDeclarativeEngine);
1457 d->importDatabase.addPluginPath(path);
1462 Returns the list of directories where the engine searches for
1463 native plugins for imported modules (referenced in the \c qmldir file).
1465 By default, the list contains only \c ., i.e. the engine searches
1466 in the directory of the \c qmldir file itself.
1468 \sa addPluginPath() setPluginPathList()
1470 QStringList QDeclarativeEngine::pluginPathList() const
1472 Q_D(const QDeclarativeEngine);
1473 return d->importDatabase.pluginPathList();
1477 Sets the list of directories where the engine searches for
1478 native plugins for imported modules (referenced in the \c qmldir file)
1481 By default, the list contains only \c ., i.e. the engine searches
1482 in the directory of the \c qmldir file itself.
1484 \sa pluginPathList() addPluginPath()
1486 void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
1488 Q_D(QDeclarativeEngine);
1489 d->importDatabase.setPluginPathList(paths);
1493 Imports the plugin named \a filePath with the \a uri provided.
1494 Returns true if the plugin was successfully imported; otherwise returns false.
1496 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1498 The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1500 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
1502 Q_D(QDeclarativeEngine);
1503 return d->importDatabase.importPlugin(filePath, uri, errors);
1507 Imports the plugin named \a filePath with the \a uri provided.
1508 Returns true if the plugin was successfully imported; otherwise returns false.
1510 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1512 The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1514 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1516 Q_D(QDeclarativeEngine);
1517 QList<QDeclarativeError> errors;
1518 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1519 if (!errors.isEmpty()) {
1521 for (int i = 0; i < errors.size(); ++i) {
1522 builtError = QString(QLatin1String("%1\n %2"))
1524 .arg(errors.at(i).toString());
1526 *errorString = builtError;
1532 \property QDeclarativeEngine::offlineStoragePath
1533 \brief the directory for storing offline user data
1535 Returns the directory where SQL and other offline
1538 QDeclarativeWebView and the SQL databases created with openDatabase()
1541 The default is QML/OfflineStorage in the platform-standard
1542 user application data directory.
1544 Note that the path may not currently exist on the filesystem, so
1545 callers wanting to \e create new files at this location should create
1546 it first - see QDir::mkpath().
1548 void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
1550 Q_D(QDeclarativeEngine);
1551 qt_qmlsqldatabase_setOfflineStoragePath(d->v8engine(), dir);
1554 QString QDeclarativeEngine::offlineStoragePath() const
1556 Q_D(const QDeclarativeEngine);
1557 return qt_qmlsqldatabase_getOfflineStoragePath(d->v8engine());
1560 static void voidptr_destructor(void *v)
1562 void **ptr = (void **)v;
1566 static void *voidptr_constructor(const void *v)
1571 return new void*(*(void **)v);
1575 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo)
1577 Q_Q(QDeclarativeEngine);
1579 if (!mo->superClass()) {
1580 QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo);
1581 propertyCache.insert(mo, rv);
1584 QDeclarativePropertyCache *super = cache(mo->superClass());
1585 QDeclarativePropertyCache *rv = super->copy(mo->propertyCount() + mo->methodCount() -
1586 mo->superClass()->propertyCount() -
1587 mo->superClass()->methodCount());
1589 propertyCache.insert(mo, rv);
1594 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
1595 QDeclarativeError &error)
1597 QList<QDeclarativeType *> types;
1599 int maxMinorVersion = 0;
1601 const QMetaObject *metaObject = type->metaObject();
1603 while (metaObject) {
1604 QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
1605 type->majorVersion(), minorVersion);
1607 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1613 metaObject = metaObject->superClass();
1616 if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1618 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1622 QDeclarativePropertyCache *raw = cache(type->metaObject());
1624 bool hasCopied = false;
1626 for (int ii = 0; ii < types.count(); ++ii) {
1627 QDeclarativeType *currentType = types.at(ii);
1631 int rev = currentType->metaObjectRevision();
1632 int moIndex = types.count() - 1 - ii;
1634 if (raw->allowedRevisionCache[moIndex] != rev) {
1639 raw->allowedRevisionCache[moIndex] = rev;
1643 // Test revision compatibility - the basic rule is:
1644 // * Anything that is excluded, cannot overload something that is not excluded *
1646 // Signals override:
1647 // * other signals and methods of the same name.
1648 // * properties named on<Signal Name>
1649 // * automatic <property name>Changed notify signals
1651 // Methods override:
1652 // * other methods of the same name
1654 // Properties override:
1655 // * other elements of the same name
1657 bool overloadError = false;
1658 QString overloadName;
1661 for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1662 !overloadError && iter != raw->stringCache.end();
1665 QDeclarativePropertyData *d = *iter;
1666 if (raw->isAllowedInRevision(d))
1667 continue; // Not excluded - no problems
1669 // check that a regular "name" overload isn't happening
1670 QDeclarativePropertyData *current = d;
1671 while (!overloadError && current) {
1672 current = d->overrideData(current);
1673 if (current && raw->isAllowedInRevision(current))
1674 overloadError = true;
1679 if (overloadError) {
1680 if (hasCopied) raw->release();
1682 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."));
1686 if (!hasCopied) raw->addref();
1687 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1689 if (minorVersion != maxMinorVersion) {
1691 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1697 QDeclarativeMetaType::ModuleApiInstance *
1698 QDeclarativeEnginePrivate::moduleApiInstance(const QDeclarativeMetaType::ModuleApi &module)
1700 Locker locker(this);
1702 QDeclarativeMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1704 a = new QDeclarativeMetaType::ModuleApiInstance;
1705 a->scriptCallback = module.script;
1706 a->qobjectCallback = module.qobject;
1707 moduleApiInstances.insert(module, a);
1713 bool QDeclarativeEnginePrivate::isQObject(int t)
1715 Locker locker(this);
1716 return m_compositeTypes.contains(t) || QDeclarativeMetaType::isQObject(t);
1719 QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1721 Locker locker(this);
1722 int t = v.userType();
1723 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1725 return *(QObject **)(v.constData());
1727 return QDeclarativeMetaType::toQObject(v, ok);
1731 QDeclarativeMetaType::TypeCategory QDeclarativeEnginePrivate::typeCategory(int t) const
1733 Locker locker(this);
1734 if (m_compositeTypes.contains(t))
1735 return QDeclarativeMetaType::Object;
1736 else if (m_qmlLists.contains(t))
1737 return QDeclarativeMetaType::List;
1739 return QDeclarativeMetaType::typeCategory(t);
1742 bool QDeclarativeEnginePrivate::isList(int t) const
1744 Locker locker(this);
1745 return m_qmlLists.contains(t) || QDeclarativeMetaType::isList(t);
1748 int QDeclarativeEnginePrivate::listType(int t) const
1750 Locker locker(this);
1751 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1752 if (iter != m_qmlLists.end())
1755 return QDeclarativeMetaType::listType(t);
1758 const QMetaObject *QDeclarativeEnginePrivate::rawMetaObjectForType(int t) const
1760 Locker locker(this);
1761 QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1762 if (iter != m_compositeTypes.end()) {
1763 return (*iter)->root;
1765 QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1766 return type?type->baseMetaObject():0;
1770 const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const
1772 Locker locker(this);
1773 QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1774 if (iter != m_compositeTypes.end()) {
1775 return (*iter)->root;
1777 QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1778 return type?type->metaObject():0;
1782 void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data)
1784 QByteArray name = data->root->className();
1786 QByteArray ptr = name + '*';
1787 QByteArray lst = "QDeclarativeListProperty<" + name + '>';
1789 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1790 voidptr_constructor);
1791 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1792 voidptr_constructor);
1796 Locker locker(this);
1797 m_qmlLists.insert(lst_type, ptr_type);
1798 m_compositeTypes.insert(ptr_type, data);
1801 bool QDeclarative_isFileCaseCorrect(const QString &fileName)
1803 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
1804 QFileInfo info(fileName);
1806 QString absolute = info.absoluteFilePath();
1808 #if defined(Q_OS_MAC)
1809 QString canonical = info.canonicalFilePath();
1810 #elif defined(Q_OS_WIN32)
1811 wchar_t buffer[1024];
1813 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1814 if (rv == 0 || rv >= 1024) return true;
1815 rv = ::GetLongPathName(buffer, buffer, 1024);
1816 if (rv == 0 || rv >= 1024) return true;
1818 QString canonical((QChar *)buffer);
1821 int absoluteLength = absolute.length();
1822 int canonicalLength = canonical.length();
1824 int length = qMin(absoluteLength, canonicalLength);
1825 for (int ii = 0; ii < length; ++ii) {
1826 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1827 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1829 if (a.toLower() != c.toLower())
1841 \fn QDeclarativeEngine *qmlEngine(const QObject *object)
1842 \relates QDeclarativeEngine
1844 Returns the QDeclarativeEngine associated with \a object, if any. This is equivalent to
1845 QDeclarativeEngine::contextForObject(object)->engine(), but more efficient.
1849 \fn QDeclarativeContext *qmlContext(const QObject *object)
1850 \relates QDeclarativeEngine
1852 Returns the QDeclarativeContext associated with \a object, if any. This is equivalent to
1853 QDeclarativeEngine::contextForObject(object).