1 /****************************************************************************
3 ** Copyright (C) 2012 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"
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/qmetaobject.h>
78 #include <QNetworkAccessManager>
80 #include <QMetaObject>
81 #include <QtCore/qcoreapplication.h>
82 #include <QtCore/qdir.h>
83 #include <QtCore/qmutex.h>
84 #include <QtNetwork/qnetworkconfigmanager.h>
86 #include <private/qobject_p.h>
88 #include <private/qdeclarativelocale_p.h>
90 #ifdef Q_OS_WIN // for %APPDATA%
91 #include <qt_windows.h>
95 #define CSIDL_APPDATA 0x001a // <username>\Application Data
98 Q_DECLARE_METATYPE(QDeclarativeProperty)
102 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
104 QDeclarativeEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
105 QDeclarativeValueTypeFactory::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 bool QDeclarativeEnginePrivate::qml_debugging_enabled = false;
165 void QDeclarativeEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
167 qmlRegisterType<QDeclarativeComponent>(uri,versionMajor,versionMinor,"Component");
168 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
169 qmlRegisterType<QDeclarativeListElement>(uri, versionMajor, versionMinor,"ListElement");
170 qmlRegisterCustomType<QDeclarativeListModel>(uri, versionMajor, versionMinor,"ListModel", new QDeclarativeListModelParser);
171 qmlRegisterType<QDeclarativeWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
174 void QDeclarativeEnginePrivate::defineModule()
176 registerBaseTypes("QtQuick", 2, 0);
177 qmlRegisterType<QDeclarativeBinding>();
178 qmlRegisterUncreatableType<QDeclarativeApplication>("QtQuick",2,0,"Application", QDeclarativeApplication::tr("Application is an abstract class"));
179 qmlRegisterUncreatableType<QDeclarativeLocale>("QtQuick",2,0,"Locale",QDeclarativeEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
183 \qmlclass Qt QDeclarativeEnginePrivate
184 \ingroup qml-utility-elements
185 \brief The QML global Qt object provides useful enums and functions from Qt.
187 \keyword QmlGlobalQtObject
189 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
191 The \c Qt object is a global object with utility functions, properties and enums.
193 It is not instantiable; to use it, call the members of the global \c Qt object directly.
200 color: Qt.rgba(1, 0, 0, 1)
201 text: Qt.md5("hello, world")
208 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
209 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
213 The Qt object also contains helper functions for creating objects of specific
214 data types. This is primarily useful when setting the properties of an item
215 when the property has one of the following types:
218 \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()}
219 \o \c rect - use \l{Qt::rect()}{Qt.rect()}
220 \o \c point - use \l{Qt::point()}{Qt.point()}
221 \o \c size - use \l{Qt::size()}{Qt.size()}
222 \o \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
225 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
227 \section1 Date/Time Formatters
229 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
232 \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
233 \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
234 \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
237 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
240 \section1 Dynamic Object Creation
241 The following functions on the global object allow you to dynamically create QML
242 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
246 \o \l{Qt::createComponent()}{object Qt.createComponent(url)}
247 \o \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
253 \qmlproperty object Qt::application
256 The \c application object provides access to global application state
257 properties shared by many QML components.
263 \o \c application.active
265 This read-only property indicates whether the application is the top-most and focused
266 application, and the user is able to interact with the application. The property
267 is false when the application is in the background, the device keylock or screen
268 saver is active, the screen backlight is turned off, or the global system dialog
269 is being displayed on top of the application. It can be used for stopping and
270 pausing animations, timers and active processing of data in order to save device
271 battery power and free device memory and processor load when the application is not
275 \o \c application.layoutDirection
277 This read-only property can be used to query the default layout direction of the
278 application. On system start-up, the default layout direction depends on the
279 application's language. The property has a value of \c Qt.RightToLeft in locales
280 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
281 where the reading direction flows from left to right. You can bind to this
282 property to customize your application layouts to support both layout directions.
287 \o Qt.LeftToRight - Text and graphics elements should be positioned
289 \o Qt.RightToLeft - Text and graphics elements should be positioned
294 \o \c application.inputPanel
296 This read-only property allows access to application's QInputPanel object
297 and all its properties and slots. See the QInputPanel documentation for
301 The following example uses the \c application object to indicate
302 whether the application is currently active:
304 \snippet doc/src/snippets/declarative/application.qml document
310 \qmlmethod object Qt::include(string url, jsobject callback)
312 Includes another JavaScript file. This method can only be used from within JavaScript files,
313 and not regular QML files.
315 This imports all functions from \a url into the current script's namespace.
317 Qt.include() returns an object that describes the status of the operation. The object has
318 a single property, \c {status}, that is set to one of the following values:
321 \header \o Symbol \o Value \o Description
322 \row \o result.OK \o 0 \o The include completed successfully.
323 \row \o result.LOADING \o 1 \o Data is being loaded from the network.
324 \row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url.
325 \row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code.
326 An additional \c exception property will be set in this case.
329 The \c status property will be updated as the operation progresses.
331 If provided, \a callback is invoked when the operation completes. The callback is passed
332 the same object as is returned from the Qt.include() call.
334 // Qt.include() is implemented in qv8include.cpp
337 QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
338 : propertyCapture(0), rootContext(0), isDebugging(false),
339 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
340 cleanup(0), erroredBindings(0), inProgressCreations(0),
341 workerScriptEngine(0), activeVME(0),
342 networkAccessManager(0), networkAccessManagerFactory(0),
343 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
344 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
348 QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate()
350 Q_ASSERT(inProgressCreations == 0);
353 QDeclarativeCleanup *c = cleanup;
355 if (cleanup) cleanup->prev = &cleanup;
361 doDeleteInEngineThread();
363 if (incubationController) incubationController->d = 0;
364 incubationController = 0;
369 for(QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
371 for(QHash<const QMetaObject *, QDeclarativePropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
373 for(QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
375 for(QHash<QDeclarativeMetaType::ModuleApi, QDeclarativeMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
376 delete (*iter)->qobjectApi;
381 void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *o)
383 QObjectPrivate *p = QObjectPrivate::get(o);
384 if (p->declarativeData) {
385 QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
386 if (d->ownContext && d->context) {
387 d->context->destroy();
393 void QDeclarativeData::destroyed(QAbstractDeclarativeData *d, QObject *o)
395 static_cast<QDeclarativeData *>(d)->destroyed(o);
398 void QDeclarativeData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
400 static_cast<QDeclarativeData *>(d)->parentChanged(o, p);
403 void QDeclarativeData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
405 static_cast<QDeclarativeData *>(d)->objectNameChanged(o);
408 void QDeclarativeData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
410 QDeclarativeData *ddata = QDeclarativeData::get(object, false);
411 if (!ddata) return; // Probably being deleted
413 QDeclarativeNotifierEndpoint *ep = ddata->notify(index);
414 if (ep) QDeclarativeNotifier::emitNotify(ep);
417 void QDeclarativeEnginePrivate::init()
419 Q_Q(QDeclarativeEngine);
421 static bool firstTime = true;
423 // This is a nasty hack as QNetworkAccessManager will issue a
424 // BlockingQueuedConnection to the main thread if it is initialized for the
425 // first time on a non-main thread. This can cause a lockup if the main thread
426 // is blocking on the thread that initialize the network access manager.
427 QNetworkConfigurationManager man;
429 qmlRegisterType<QDeclarativeComponent>("QML", 1, 0, "Component");
434 qRegisterMetaType<QVariant>("QVariant");
435 qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString");
436 qRegisterMetaType<QJSValue>("QJSValue");
437 qRegisterMetaType<QDeclarativeComponent::Status>("QDeclarativeComponent::Status");
438 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
439 qRegisterMetaType<QList<int> >("QList<int>");
440 qRegisterMetaType<QDeclarativeV8Handle>("QDeclarativeV8Handle");
442 QDeclarativeData::init();
444 v8engine()->setEngine(q);
446 rootContext = new QDeclarativeContext(q,true);
448 if (QCoreApplication::instance()->thread() == q->thread() &&
449 QDeclarativeEngineDebugService::isDebuggingEnabled()) {
451 QDeclarativeEngineDebugService::instance()->addEngine(q);
452 QV8DebugService::initialize(v8engine());
453 QV8ProfilerService::initialize();
454 QDeclarativeDebugTrace::initialize();
455 QDebugMessageService::instance();
459 QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine()
461 Q_Q(QDeclarativeEngine);
462 if (!workerScriptEngine)
463 workerScriptEngine = new QDeclarativeWorkerScriptEngine(q);
464 return workerScriptEngine;
468 \class QDeclarativeEngine
470 \brief The QDeclarativeEngine class provides an environment for instantiating QML components.
473 Each QML component is instantiated in a QDeclarativeContext.
474 QDeclarativeContext's are essential for passing data to QML
475 components. In QML, contexts are arranged hierarchically and this
476 hierarchy is managed by the QDeclarativeEngine.
478 Prior to creating any QML components, an application must have
479 created a QDeclarativeEngine to gain access to a QML context. The
480 following example shows how to create a simple Text item.
483 QDeclarativeEngine engine;
484 QDeclarativeComponent component(&engine);
485 component.setData("import QtQuick 1.0\nText { text: \"Hello world!\" }", QUrl());
486 QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create());
488 //add item to view, etc
492 In this case, the Text item will be created in the engine's
493 \l {QDeclarativeEngine::rootContext()}{root context}.
495 \sa QDeclarativeComponent QDeclarativeContext
499 Create a new QDeclarativeEngine with the given \a parent.
501 QDeclarativeEngine::QDeclarativeEngine(QObject *parent)
502 : QJSEngine(*new QDeclarativeEnginePrivate(this), parent)
504 Q_D(QDeclarativeEngine);
509 Destroys the QDeclarativeEngine.
511 Any QDeclarativeContext's created on this engine will be
512 invalidated, but not destroyed (unless they are parented to the
513 QDeclarativeEngine object).
515 QDeclarativeEngine::~QDeclarativeEngine()
517 Q_D(QDeclarativeEngine);
518 if (d->isDebugging) {
519 QDeclarativeEngineDebugService::instance()->remEngine(this);
522 // if we are the parent of any of the qobject module api instances,
523 // we need to remove them from our internal list, in order to prevent
524 // a segfault in engine private dtor.
525 QList<QDeclarativeMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
526 QObject *currQObjectApi = 0;
527 QDeclarativeMetaType::ModuleApiInstance *currInstance = 0;
528 foreach (const QDeclarativeMetaType::ModuleApi &key, keys) {
529 currInstance = d->moduleApiInstances.value(key);
530 currQObjectApi = currInstance->qobjectApi;
531 if (this->children().contains(currQObjectApi)) {
532 delete currQObjectApi;
534 d->moduleApiInstances.remove(key);
538 // ensure we clean up QObjects with JS ownership
541 if (d->incubationController)
542 d->incubationController->d = 0;
545 /*! \fn void QDeclarativeEngine::quit()
546 This signal is emitted when the QML loaded by the engine would like to quit.
549 /*! \fn void QDeclarativeEngine::warnings(const QList<QDeclarativeError> &warnings)
550 This signal is emitted when \a warnings messages are generated by QML.
554 Clears the engine's internal component cache.
556 Normally the QDeclarativeEngine caches components loaded from qml
557 files. This method clears this cache and forces the component to be
560 void QDeclarativeEngine::clearComponentCache()
562 Q_D(QDeclarativeEngine);
563 d->typeLoader.clearCache();
567 Returns the engine's root context.
569 The root context is automatically created by the QDeclarativeEngine.
570 Data that should be available to all QML component instances
571 instantiated by the engine should be put in the root context.
573 Additional data that should only be available to a subset of
574 component instances should be added to sub-contexts parented to the
577 QDeclarativeContext *QDeclarativeEngine::rootContext() const
579 Q_D(const QDeclarativeEngine);
580 return d->rootContext;
584 Sets the \a factory to use for creating QNetworkAccessManager(s).
586 QNetworkAccessManager is used for all network access by QML. By
587 implementing a factory it is possible to create custom
588 QNetworkAccessManager with specialized caching, proxy and cookie
591 The factory must be set before executing the engine.
593 void QDeclarativeEngine::setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *factory)
595 Q_D(QDeclarativeEngine);
596 QMutexLocker locker(&d->mutex);
597 d->networkAccessManagerFactory = factory;
601 Returns the current QDeclarativeNetworkAccessManagerFactory.
603 \sa setNetworkAccessManagerFactory()
605 QDeclarativeNetworkAccessManagerFactory *QDeclarativeEngine::networkAccessManagerFactory() const
607 Q_D(const QDeclarativeEngine);
608 return d->networkAccessManagerFactory;
611 void QDeclarativeEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
614 activeVME->finalizeCallbacks.append(qMakePair(QDeclarativeGuard<QObject>(obj), index));
616 void *args[] = { 0 };
617 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
621 QNetworkAccessManager *QDeclarativeEnginePrivate::createNetworkAccessManager(QObject *parent) const
623 QMutexLocker locker(&mutex);
624 QNetworkAccessManager *nam;
625 if (networkAccessManagerFactory) {
626 nam = networkAccessManagerFactory->create(parent);
628 nam = new QNetworkAccessManager(parent);
634 QNetworkAccessManager *QDeclarativeEnginePrivate::getNetworkAccessManager() const
636 Q_Q(const QDeclarativeEngine);
637 if (!networkAccessManager)
638 networkAccessManager = createNetworkAccessManager(const_cast<QDeclarativeEngine*>(q));
639 return networkAccessManager;
643 Returns a common QNetworkAccessManager which can be used by any QML
644 element instantiated by this engine.
646 If a QDeclarativeNetworkAccessManagerFactory has been set and a
647 QNetworkAccessManager has not yet been created, the
648 QDeclarativeNetworkAccessManagerFactory will be used to create the
649 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
650 will have no proxy or cache set.
652 \sa setNetworkAccessManagerFactory()
654 QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
656 Q_D(const QDeclarativeEngine);
657 return d->getNetworkAccessManager();
662 Sets the \a provider to use for images requested via the \e
663 image: url scheme, with host \a providerId. The QDeclarativeEngine
664 takes ownership of \a provider.
666 Image providers enable support for pixmap and threaded image
667 requests. See the QDeclarativeImageProvider documentation for details on
668 implementing and using image providers.
670 All required image providers should be added to the engine before any
671 QML sources files are loaded.
673 \sa removeImageProvider()
675 void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativeImageProvider *provider)
677 Q_D(QDeclarativeEngine);
678 QMutexLocker locker(&d->mutex);
679 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QDeclarativeImageProvider>(provider));
683 Returns the QDeclarativeImageProvider set for \a providerId.
685 Returns the provider if it was found; otherwise returns 0.
687 QDeclarativeImageProvider *QDeclarativeEngine::imageProvider(const QString &providerId) const
689 Q_D(const QDeclarativeEngine);
690 QMutexLocker locker(&d->mutex);
691 return d->imageProviders.value(providerId).data();
695 Removes the QDeclarativeImageProvider for \a providerId.
697 \sa addImageProvider()
699 void QDeclarativeEngine::removeImageProvider(const QString &providerId)
701 Q_D(QDeclarativeEngine);
702 QMutexLocker locker(&d->mutex);
703 d->imageProviders.take(providerId);
706 QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProviderType(const QUrl &url)
708 QMutexLocker locker(&mutex);
709 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
712 return provider->imageType();
713 return QDeclarativeImageProvider::Invalid;
716 QDeclarativeTextureFactory *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
718 QMutexLocker locker(&mutex);
719 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
722 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
723 return provider->requestTexture(imageId, size, req_size);
728 QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
730 QMutexLocker locker(&mutex);
732 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
735 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
736 image = provider->requestImage(imageId, size, req_size);
741 QPixmap QDeclarativeEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
743 QMutexLocker locker(&mutex);
745 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
748 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
749 pixmap = provider->requestPixmap(imageId, size, req_size);
755 Return the base URL for this engine. The base URL is only used to
756 resolve components when a relative URL is passed to the
757 QDeclarativeComponent constructor.
759 If a base URL has not been explicitly set, this method returns the
760 application's current working directory.
764 QUrl QDeclarativeEngine::baseUrl() const
766 Q_D(const QDeclarativeEngine);
767 if (d->baseUrl.isEmpty()) {
768 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
775 Set the base URL for this engine to \a url.
779 void QDeclarativeEngine::setBaseUrl(const QUrl &url)
781 Q_D(QDeclarativeEngine);
786 Returns true if warning messages will be output to stderr in addition
787 to being emitted by the warnings() signal, otherwise false.
789 The default value is true.
791 bool QDeclarativeEngine::outputWarningsToStandardError() const
793 Q_D(const QDeclarativeEngine);
794 return d->outputWarningsToStdErr;
798 Set whether warning messages will be output to stderr to \a enabled.
800 If \a enabled is true, any warning messages generated by QML will be
801 output to stderr and emitted by the warnings() signal. If \a enabled
802 is false, on the warnings() signal will be emitted. This allows
803 applications to handle warning output themselves.
805 The default value is true.
807 void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled)
809 Q_D(QDeclarativeEngine);
810 d->outputWarningsToStdErr = enabled;
814 Attempt to free unused memory.
816 void QDeclarativeEngine::collectGarbage()
822 Returns the QDeclarativeContext for the \a object, or 0 if no
823 context has been set.
825 When the QDeclarativeEngine instantiates a QObject, the context is
828 QDeclarativeContext *QDeclarativeEngine::contextForObject(const QObject *object)
833 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
835 QDeclarativeData *data =
836 static_cast<QDeclarativeData *>(priv->declarativeData);
840 else if (data->outerContext)
841 return data->outerContext->asQDeclarativeContext();
847 Sets the QDeclarativeContext for the \a object to \a context.
848 If the \a object already has a context, a warning is
849 output, but the context is not changed.
851 When the QDeclarativeEngine instantiates a QObject, the context is
854 void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContext *context)
856 if (!object || !context)
859 QDeclarativeData *data = QDeclarativeData::get(object, true);
861 qWarning("QDeclarativeEngine::setContextForObject(): Object already has a QDeclarativeContext");
865 QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
866 contextData->addObject(object);
870 \enum QDeclarativeEngine::ObjectOwnership
872 Ownership controls whether or not QML automatically destroys the
873 QObject when the object is garbage collected by the JavaScript
874 engine. The two ownership options are:
876 \value CppOwnership The object is owned by C++ code, and will
877 never be deleted by QML. The JavaScript destroy() method cannot be
878 used on objects with CppOwnership. This option is similar to
879 QScriptEngine::QtOwnership.
881 \value JavaScriptOwnership The object is owned by JavaScript.
882 When the object is returned to QML as the return value of a method
883 call or property access, QML will delete the object if there are no
884 remaining JavaScript references to it and it has no
885 QObject::parent(). This option is similar to
886 QScriptEngine::ScriptOwnership.
888 Generally an application doesn't need to set an object's ownership
889 explicitly. QML uses a heuristic to set the default object
890 ownership. By default, an object that is created by QML has
891 JavaScriptOwnership. The exception to this are the root objects
892 created by calling QDeclarativeCompnent::create() or
893 QDeclarativeComponent::beginCreate() which have CppOwnership by
894 default. The ownership of these root-level objects is considered to
895 have been transferred to the C++ caller.
897 Objects not-created by QML have CppOwnership by default. The
898 exception to this is objects returned from a C++ method call. The
899 ownership of these objects is passed to JavaScript.
901 Calling setObjectOwnership() overrides the default ownership
902 heuristic used by QML.
906 Sets the \a ownership of \a object.
908 void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
913 QDeclarativeData *ddata = QDeclarativeData::get(object, true);
917 ddata->indestructible = (ownership == CppOwnership)?true:false;
918 ddata->explicitIndestructibleSet = true;
922 Returns the ownership of \a object.
924 QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object)
929 QDeclarativeData *ddata = QDeclarativeData::get(object, false);
933 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
936 bool QDeclarativeEngine::event(QEvent *e)
938 Q_D(QDeclarativeEngine);
939 if (e->type() == QEvent::User)
940 d->doDeleteInEngineThread();
942 return QJSEngine::event(e);
945 void QDeclarativeEnginePrivate::doDeleteInEngineThread()
947 QFieldList<Deletable, &Deletable::next> list;
949 list.copyAndClear(toDeleteInEngineThread);
952 while (Deletable *d = list.takeFirst())
956 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
958 QDeclarativeData *data = QDeclarativeData::get(object);
960 if (data && data->deferredComponent) {
961 if (QDeclarativeDebugService::isDebuggingEnabled()) {
962 QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
963 QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
964 QString typeName = type ? type->qmlTypeName() : QString::fromUtf8(object->metaObject()->className());
965 QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, typeName);
966 if (data->outerContext)
967 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, data->outerContext->url, data->lineNumber, data->columnNumber);
969 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine);
971 QDeclarativeComponentPrivate::ConstructionState state;
972 QDeclarativeComponentPrivate::beginDeferred(ep, object, &state);
974 data->deferredComponent->release();
975 data->deferredComponent = 0;
977 QDeclarativeComponentPrivate::complete(ep, &state);
978 QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
982 QDeclarativeContext *qmlContext(const QObject *obj)
984 return QDeclarativeEngine::contextForObject(obj);
987 QDeclarativeEngine *qmlEngine(const QObject *obj)
989 QDeclarativeData *data = QDeclarativeData::get(obj, false);
990 if (!data || !data->context)
992 return data->context->engine;
995 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
997 QDeclarativeData *data = QDeclarativeData::get(object);
999 return 0; // Attached properties are only on objects created by QML
1001 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1005 QDeclarativeAttachedPropertiesFunc pf = QDeclarativeMetaType::attachedPropertiesFuncById(id);
1009 rv = pf(const_cast<QObject *>(object));
1012 data->attachedProperties()->insert(id, rv);
1017 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1018 const QMetaObject *attachedMetaObject, bool create)
1021 *idCache = QDeclarativeMetaType::attachedPropertiesFuncId(attachedMetaObject);
1023 if (*idCache == -1 || !object)
1026 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1029 QDeclarativeDebuggingEnabler::QDeclarativeDebuggingEnabler()
1031 #ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
1032 if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
1033 qWarning("Qml debugging is enabled. Only use this in a safe environment!");
1035 QDeclarativeEnginePrivate::qml_debugging_enabled = true;
1040 class QDeclarativeDataExtended {
1042 QDeclarativeDataExtended();
1043 ~QDeclarativeDataExtended();
1045 QHash<int, QObject *> attachedProperties;
1046 QDeclarativeNotifier objectNameNotifier;
1049 QDeclarativeDataExtended::QDeclarativeDataExtended()
1053 QDeclarativeDataExtended::~QDeclarativeDataExtended()
1057 void QDeclarativeData::NotifyList::layout(QDeclarativeNotifierEndpoint *endpoint)
1060 layout(endpoint->next);
1062 int index = endpoint->sourceSignal;
1063 index = qMin(index, 0xFFFF - 1);
1065 endpoint->next = notifies[index];
1066 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1067 endpoint->prev = ¬ifies[index];
1068 notifies[index] = endpoint;
1071 void QDeclarativeData::NotifyList::layout()
1073 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1076 QDeclarativeNotifierEndpoint **old = notifies;
1077 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QDeclarativeNotifierEndpoint*);
1078 notifies = (QDeclarativeNotifierEndpoint**)realloc(notifies, reallocSize);
1079 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1080 sizeof(QDeclarativeNotifierEndpoint*);
1081 memset(notifies + notifiesSize, 0, memsetSize);
1083 if (notifies != old) {
1084 for (int ii = 0; ii < notifiesSize; ++ii)
1086 notifies[ii]->prev = ¬ifies[ii];
1089 notifiesSize = maximumTodoIndex + 1;
1094 maximumTodoIndex = 0;
1098 void QDeclarativeData::addNotify(int index, QDeclarativeNotifierEndpoint *endpoint)
1101 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1102 notifyList->connectionMask = 0;
1103 notifyList->maximumTodoIndex = 0;
1104 notifyList->notifiesSize = 0;
1105 notifyList->todo = 0;
1106 notifyList->notifies = 0;
1109 Q_ASSERT(!endpoint->isConnected());
1111 index = qMin(index, 0xFFFF - 1);
1112 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1114 if (index < notifyList->notifiesSize) {
1116 endpoint->next = notifyList->notifies[index];
1117 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1118 endpoint->prev = ¬ifyList->notifies[index];
1119 notifyList->notifies[index] = endpoint;
1122 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1124 endpoint->next = notifyList->todo;
1125 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1126 endpoint->prev = ¬ifyList->todo;
1127 notifyList->todo = endpoint;
1131 QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const
1133 if (!extendedData) extendedData = new QDeclarativeDataExtended;
1134 return &extendedData->objectNameNotifier;
1137 QHash<int, QObject *> *QDeclarativeData::attachedProperties() const
1139 if (!extendedData) extendedData = new QDeclarativeDataExtended;
1140 return &extendedData->attachedProperties;
1143 void QDeclarativeData::destroyed(QObject *object)
1145 if (deferredComponent)
1146 deferredComponent->release();
1148 if (nextContextObject)
1149 nextContextObject->prevContextObject = prevContextObject;
1150 if (prevContextObject)
1151 *prevContextObject = nextContextObject;
1153 QDeclarativeAbstractBinding *binding = bindings;
1155 QDeclarativeAbstractBinding *next = binding->m_nextBinding;
1156 binding->m_prevBinding = 0;
1157 binding->m_nextBinding = 0;
1166 propertyCache->release();
1168 if (ownContext && context)
1172 QDeclarativeGuard<QObject> *guard = static_cast<QDeclarativeGuard<QObject> *>(guards);
1173 *guard = (QObject *)0;
1174 guard->objectDestroyed(object);
1178 while (notifyList->todo)
1179 notifyList->todo->disconnect();
1180 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1181 while (QDeclarativeNotifierEndpoint *ep = notifyList->notifies[ii])
1184 free(notifyList->notifies);
1189 delete extendedData;
1191 v8object.Clear(); // The WeakReference handler will clean the actual handle
1197 void QDeclarativeData::parentChanged(QObject *object, QObject *parent)
1203 void QDeclarativeData::objectNameChanged(QObject *)
1205 if (extendedData) objectNameNotifier()->notify();
1208 bool QDeclarativeData::hasBindingBit(int bit) const
1210 if (bindingBitsSize > bit)
1211 return bindingBits[bit / 32] & (1 << (bit % 32));
1216 void QDeclarativeData::clearBindingBit(int bit)
1218 if (bindingBitsSize > bit)
1219 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1222 void QDeclarativeData::setBindingBit(QObject *obj, int bit)
1224 if (bindingBitsSize <= bit) {
1225 int props = obj->metaObject()->propertyCount();
1226 Q_ASSERT(bit < props);
1228 int arraySize = (props + 31) / 32;
1229 int oldArraySize = bindingBitsSize / 32;
1231 bindingBits = (quint32 *)realloc(bindingBits,
1232 arraySize * sizeof(quint32));
1234 memset(bindingBits + oldArraySize,
1236 sizeof(quint32) * (arraySize - oldArraySize));
1238 bindingBitsSize = arraySize * 32;
1241 bindingBits[bit / 32] |= (1 << (bit % 32));
1244 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1246 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1247 if (url.authority().isEmpty())
1248 return QLatin1Char(':') + url.path();
1251 return url.toLocalFile();
1255 static QString toLocalFile(const QString &url)
1257 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1260 QString file = url.mid(7);
1262 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1264 // magic for drives on windows
1265 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1271 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1273 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1274 if (url.length() > 4)
1275 return QLatin1Char(':') + url.mid(4);
1279 return toLocalFile(url);
1282 void QDeclarativeEnginePrivate::sendQuit()
1284 Q_Q(QDeclarativeEngine);
1286 if (q->receivers(SIGNAL(quit())) == 0) {
1287 qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it.");
1291 static void dumpwarning(const QDeclarativeError &error)
1293 qWarning().nospace() << qPrintable(error.toString());
1296 static void dumpwarning(const QList<QDeclarativeError> &errors)
1298 for (int ii = 0; ii < errors.count(); ++ii)
1299 dumpwarning(errors.at(ii));
1302 void QDeclarativeEnginePrivate::warning(const QDeclarativeError &error)
1304 Q_Q(QDeclarativeEngine);
1305 q->warnings(QList<QDeclarativeError>() << error);
1306 if (outputWarningsToStdErr)
1310 void QDeclarativeEnginePrivate::warning(const QList<QDeclarativeError> &errors)
1312 Q_Q(QDeclarativeEngine);
1313 q->warnings(errors);
1314 if (outputWarningsToStdErr)
1315 dumpwarning(errors);
1318 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QDeclarativeError &error)
1321 QDeclarativeEnginePrivate::get(engine)->warning(error);
1326 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QList<QDeclarativeError> &error)
1329 QDeclarativeEnginePrivate::get(engine)->warning(error);
1334 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QDeclarativeError &error)
1337 engine->warning(error);
1342 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QList<QDeclarativeError> &error)
1345 engine->warning(error);
1351 This function should be called prior to evaluation of any js expression,
1352 so that scarce resources are not freed prematurely (eg, if there is a
1353 nested javascript expression).
1355 void QDeclarativeEnginePrivate::referenceScarceResources()
1357 scarceResourcesRefCount += 1;
1361 This function should be called after evaluation of the js expression is
1362 complete, and so the scarce resources may be freed safely.
1364 void QDeclarativeEnginePrivate::dereferenceScarceResources()
1366 Q_ASSERT(scarceResourcesRefCount > 0);
1367 scarceResourcesRefCount -= 1;
1369 // if the refcount is zero, then evaluation of the "top level"
1370 // expression must have completed. We can safely release the
1371 // scarce resources.
1372 if (scarceResourcesRefCount == 0) {
1373 // iterate through the list and release them all.
1374 // note that the actual SRD is owned by the JS engine,
1375 // so we cannot delete the SRD; but we can free the
1376 // memory used by the variant in the SRD.
1377 while (ScarceResourceData *sr = scarceResources.first()) {
1378 sr->data = QVariant();
1379 scarceResources.remove(sr);
1385 Adds \a path as a directory where the engine searches for
1386 installed modules in a URL-based directory structure.
1387 The \a path may be a local filesystem directory or a URL.
1389 The newly added \a path will be first in the importPathList().
1391 \sa setImportPathList(), {QML Modules}
1393 void QDeclarativeEngine::addImportPath(const QString& path)
1395 Q_D(QDeclarativeEngine);
1396 d->importDatabase.addImportPath(path);
1400 Returns the list of directories where the engine searches for
1401 installed modules in a URL-based directory structure.
1403 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1404 imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look
1405 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1406 provided by that module. A \c qmldir file is required for defining the
1407 type version mapping and possibly declarative extensions plugins.
1409 By default, the list contains the directory of the application executable,
1410 paths specified in the \c QML_IMPORT_PATH environment variable,
1411 and the builtin \c ImportsPath from QLibraryInfo.
1413 \sa addImportPath() setImportPathList()
1415 QStringList QDeclarativeEngine::importPathList() const
1417 Q_D(const QDeclarativeEngine);
1418 return d->importDatabase.importPathList();
1422 Sets \a paths as the list of directories where the engine searches for
1423 installed modules in a URL-based directory structure.
1425 By default, the list contains the directory of the application executable,
1426 paths specified in the \c QML_IMPORT_PATH environment variable,
1427 and the builtin \c ImportsPath from QLibraryInfo.
1429 \sa importPathList() addImportPath()
1431 void QDeclarativeEngine::setImportPathList(const QStringList &paths)
1433 Q_D(QDeclarativeEngine);
1434 d->importDatabase.setImportPathList(paths);
1439 Adds \a path as a directory where the engine searches for
1440 native plugins for imported modules (referenced in the \c qmldir file).
1442 By default, the list contains only \c ., i.e. the engine searches
1443 in the directory of the \c qmldir file itself.
1445 The newly added \a path will be first in the pluginPathList().
1447 \sa setPluginPathList()
1449 void QDeclarativeEngine::addPluginPath(const QString& path)
1451 Q_D(QDeclarativeEngine);
1452 d->importDatabase.addPluginPath(path);
1457 Returns the list of directories where the engine searches for
1458 native plugins for imported modules (referenced in the \c qmldir file).
1460 By default, the list contains only \c ., i.e. the engine searches
1461 in the directory of the \c qmldir file itself.
1463 \sa addPluginPath() setPluginPathList()
1465 QStringList QDeclarativeEngine::pluginPathList() const
1467 Q_D(const QDeclarativeEngine);
1468 return d->importDatabase.pluginPathList();
1472 Sets the list of directories where the engine searches for
1473 native plugins for imported modules (referenced in the \c qmldir file)
1476 By default, the list contains only \c ., i.e. the engine searches
1477 in the directory of the \c qmldir file itself.
1479 \sa pluginPathList() addPluginPath()
1481 void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
1483 Q_D(QDeclarativeEngine);
1484 d->importDatabase.setPluginPathList(paths);
1488 Imports the plugin named \a filePath with the \a uri provided.
1489 Returns true if the plugin was successfully imported; otherwise returns false.
1491 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1493 The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1495 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
1497 Q_D(QDeclarativeEngine);
1498 return d->importDatabase.importPlugin(filePath, uri, errors);
1502 Imports the plugin named \a filePath with the \a uri provided.
1503 Returns true if the plugin was successfully imported; otherwise returns false.
1505 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1507 The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1509 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1511 Q_D(QDeclarativeEngine);
1512 QList<QDeclarativeError> errors;
1513 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1514 if (!errors.isEmpty()) {
1516 for (int i = 0; i < errors.size(); ++i) {
1517 builtError = QString(QLatin1String("%1\n %2"))
1519 .arg(errors.at(i).toString());
1521 *errorString = builtError;
1527 \property QDeclarativeEngine::offlineStoragePath
1528 \brief the directory for storing offline user data
1530 Returns the directory where SQL and other offline
1533 QDeclarativeWebView and the SQL databases created with openDatabase()
1536 The default is QML/OfflineStorage in the platform-standard
1537 user application data directory.
1539 Note that the path may not currently exist on the filesystem, so
1540 callers wanting to \e create new files at this location should create
1541 it first - see QDir::mkpath().
1543 void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
1545 Q_D(QDeclarativeEngine);
1546 qt_qmlsqldatabase_setOfflineStoragePath(d->v8engine(), dir);
1549 QString QDeclarativeEngine::offlineStoragePath() const
1551 Q_D(const QDeclarativeEngine);
1552 return qt_qmlsqldatabase_getOfflineStoragePath(d->v8engine());
1555 static void voidptr_destructor(void *v)
1557 void **ptr = (void **)v;
1561 static void *voidptr_constructor(const void *v)
1566 return new void*(*(void **)v);
1570 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo)
1572 Q_Q(QDeclarativeEngine);
1574 if (!mo->superClass()) {
1575 QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo);
1576 propertyCache.insert(mo, rv);
1579 QDeclarativePropertyCache *super = cache(mo->superClass());
1580 QDeclarativePropertyCache *rv = super->copyAndAppend(q, mo);
1581 propertyCache.insert(mo, rv);
1586 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
1587 QDeclarativeError &error)
1589 QList<QDeclarativeType *> types;
1591 int maxMinorVersion = 0;
1593 const QMetaObject *metaObject = type->metaObject();
1595 while (metaObject) {
1596 QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
1597 type->majorVersion(), minorVersion);
1599 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1605 metaObject = metaObject->superClass();
1608 if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1610 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1614 QDeclarativePropertyCache *raw = cache(type->metaObject());
1616 bool hasCopied = false;
1618 for (int ii = 0; ii < types.count(); ++ii) {
1619 QDeclarativeType *currentType = types.at(ii);
1623 int rev = currentType->metaObjectRevision();
1624 int moIndex = types.count() - 1 - ii;
1626 if (raw->allowedRevisionCache[moIndex] != rev) {
1631 raw->allowedRevisionCache[moIndex] = rev;
1635 // Test revision compatibility - the basic rule is:
1636 // * Anything that is excluded, cannot overload something that is not excluded *
1638 // Signals override:
1639 // * other signals and methods of the same name.
1640 // * properties named on<Signal Name>
1641 // * automatic <property name>Changed notify signals
1643 // Methods override:
1644 // * other methods of the same name
1646 // Properties override:
1647 // * other elements of the same name
1649 bool overloadError = false;
1650 QString overloadName;
1653 for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1654 !overloadError && iter != raw->stringCache.end();
1657 QDeclarativePropertyData *d = *iter;
1658 if (raw->isAllowedInRevision(d))
1659 continue; // Not excluded - no problems
1661 // check that a regular "name" overload isn't happening
1662 QDeclarativePropertyData *current = d;
1663 while (!overloadError && current) {
1664 current = d->overrideData(current);
1665 if (current && raw->isAllowedInRevision(current))
1666 overloadError = true;
1671 if (overloadError) {
1672 if (hasCopied) raw->release();
1674 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."));
1678 if (!hasCopied) raw->addref();
1679 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1681 if (minorVersion != maxMinorVersion) {
1683 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1689 QDeclarativeMetaType::ModuleApiInstance *
1690 QDeclarativeEnginePrivate::moduleApiInstance(const QDeclarativeMetaType::ModuleApi &module)
1692 Locker locker(this);
1694 QDeclarativeMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1696 a = new QDeclarativeMetaType::ModuleApiInstance;
1697 a->scriptCallback = module.script;
1698 a->qobjectCallback = module.qobject;
1699 moduleApiInstances.insert(module, a);
1705 bool QDeclarativeEnginePrivate::isQObject(int t)
1707 Locker locker(this);
1708 return m_compositeTypes.contains(t) || QDeclarativeMetaType::isQObject(t);
1711 QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1713 Locker locker(this);
1714 int t = v.userType();
1715 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1717 return *(QObject **)(v.constData());
1719 return QDeclarativeMetaType::toQObject(v, ok);
1723 QDeclarativeMetaType::TypeCategory QDeclarativeEnginePrivate::typeCategory(int t) const
1725 Locker locker(this);
1726 if (m_compositeTypes.contains(t))
1727 return QDeclarativeMetaType::Object;
1728 else if (m_qmlLists.contains(t))
1729 return QDeclarativeMetaType::List;
1731 return QDeclarativeMetaType::typeCategory(t);
1734 bool QDeclarativeEnginePrivate::isList(int t) const
1736 Locker locker(this);
1737 return m_qmlLists.contains(t) || QDeclarativeMetaType::isList(t);
1740 int QDeclarativeEnginePrivate::listType(int t) const
1742 Locker locker(this);
1743 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1744 if (iter != m_qmlLists.end())
1747 return QDeclarativeMetaType::listType(t);
1750 const QMetaObject *QDeclarativeEnginePrivate::rawMetaObjectForType(int t) const
1752 Locker locker(this);
1753 QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1754 if (iter != m_compositeTypes.end()) {
1755 return (*iter)->root;
1757 QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1758 return type?type->baseMetaObject():0;
1762 const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const
1764 Locker locker(this);
1765 QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1766 if (iter != m_compositeTypes.end()) {
1767 return (*iter)->root;
1769 QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1770 return type?type->metaObject():0;
1774 void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data)
1776 QByteArray name = data->root->className();
1778 QByteArray ptr = name + '*';
1779 QByteArray lst = "QDeclarativeListProperty<" + name + '>';
1781 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1782 voidptr_constructor);
1783 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1784 voidptr_constructor);
1788 Locker locker(this);
1789 m_qmlLists.insert(lst_type, ptr_type);
1790 m_compositeTypes.insert(ptr_type, data);
1793 bool QDeclarative_isFileCaseCorrect(const QString &fileName)
1795 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1796 QFileInfo info(fileName);
1797 const QString absolute = info.absoluteFilePath();
1799 #if defined(Q_OS_MAC)
1800 const QString canonical = info.canonicalFilePath();
1801 #elif defined(Q_OS_WIN)
1802 wchar_t buffer[1024];
1804 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1805 if (rv == 0 || rv >= 1024) return true;
1806 rv = ::GetLongPathName(buffer, buffer, 1024);
1807 if (rv == 0 || rv >= 1024) return true;
1809 const QString canonical = QString::fromWCharArray(buffer);
1812 const int absoluteLength = absolute.length();
1813 const int canonicalLength = canonical.length();
1815 const int length = qMin(absoluteLength, canonicalLength);
1816 for (int ii = 0; ii < length; ++ii) {
1817 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1818 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1820 if (a.toLower() != c.toLower())
1832 \fn QDeclarativeEngine *qmlEngine(const QObject *object)
1833 \relates QDeclarativeEngine
1835 Returns the QDeclarativeEngine associated with \a object, if any. This is equivalent to
1836 QDeclarativeEngine::contextForObject(object)->engine(), but more efficient.
1840 \fn QDeclarativeContext *qmlContext(const QObject *object)
1841 \relates QDeclarativeEngine
1843 Returns the QDeclarativeContext associated with \a object, if any. This is equivalent to
1844 QDeclarativeEngine::contextForObject(object).