diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2012-03-27 16:43:26 +0200 |
---|---|---|
committer | Kent Hansen <kent.hansen@nokia.com> | 2012-03-27 16:56:14 +0200 |
commit | 24fb8dc27eddfdd62bd2c3a6e863cbf433762cd6 (patch) | |
tree | 917eff8c50fe4699547b9de852ee53257c1585cf /src/qml | |
parent | 3e6a8eca00334df344a45f09afbcf8fd8e2b7c54 (diff) | |
parent | ffdbf216dc80b3d781307bb6b4b7150281c874a3 (diff) |
Merge master into api_changes
Conflicts:
src/qml/debugger/qqmlenginedebugservice.cpp
src/qml/debugger/qqmlprofilerservice_p.h
src/qml/qml/qqmlboundsignal.cpp
src/qml/qml/qqmlpropertycache.cpp
src/quick/util/qquickimageprovider.cpp
Change-Id: I0609aa5ed54c7769f1e2773a96a7cd43a69f133c
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/debugger/qqmldebug.h | 8 | ||||
-rw-r--r-- | src/qml/debugger/qqmlenginedebugservice.cpp | 52 | ||||
-rw-r--r-- | src/qml/debugger/qqmlprofilerservice_p.h | 33 | ||||
-rw-r--r-- | src/qml/qml/qqml.h | 19 | ||||
-rw-r--r-- | src/qml/qml/qqmlboundsignal.cpp | 122 | ||||
-rw-r--r-- | src/qml/qml/qqmlboundsignal_p.h | 58 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlcontext.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmldata_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 21 | ||||
-rw-r--r-- | src/qml/qml/qqmlerror.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlexpression.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlextensionplugin.cpp | 11 | ||||
-rw-r--r-- | src/qml/qml/qqmllist.cpp | 9 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype_p.h | 12 | ||||
-rw-r--r-- | src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlparserstatus.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlproperty.cpp | 51 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 24 | ||||
-rw-r--r-- | src/qml/qml/qqmlvme.cpp | 9 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4irbuilder.cpp | 20 |
23 files changed, 352 insertions, 134 deletions
diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h index 8036032150..318e0bd71f 100644 --- a/src/qml/debugger/qqmldebug.h +++ b/src/qml/debugger/qqmldebug.h @@ -51,12 +51,14 @@ QT_BEGIN_NAMESPACE struct Q_QML_EXPORT QQmlDebuggingEnabler { - QQmlDebuggingEnabler(); + QQmlDebuggingEnabler(bool printWarning = true); }; // Execute code in constructor before first QQmlEngine is instantiated -#if defined(QT_DECLARATIVE_DEBUG) -static QQmlDebuggingEnabler qmlEnableDebuggingHelper; +#if defined(QT_DECLARATIVE_DEBUG_NO_WARNING) +static QQmlDebuggingEnabler qmlEnableDebuggingHelper(false); +#elif defined(QT_DECLARATIVE_DEBUG) +static QQmlDebuggingEnabler qmlEnableDebuggingHelper(true); #endif QT_END_NAMESPACE diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp index 7f0bf7ca33..cd09b69e48 100644 --- a/src/qml/debugger/qqmlenginedebugservice.cpp +++ b/src/qml/debugger/qqmlenginedebugservice.cpp @@ -223,7 +223,7 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message, int childrenCount = children.count(); for (int ii = 0; ii < children.count(); ++ii) { - if (qobject_cast<QQmlContext*>(children[ii]) || QQmlBoundSignal::cast(children[ii])) + if (qobject_cast<QQmlContext*>(children[ii])) --childrenCount; } @@ -235,19 +235,41 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message, QObject *child = children.at(ii); if (qobject_cast<QQmlContext*>(child)) continue; - QQmlBoundSignal *signal = QQmlBoundSignal::cast(child); - if (signal) { - if (!dumpProperties) + if (recur) + buildObjectDump(message, child, recur, dumpProperties); + else + message << objectData(child); + } + + if (!dumpProperties) { + message << 0; + return; + } + + QList<int> propertyIndexes; + for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) { + if (object->metaObject()->property(ii).isScriptable()) + propertyIndexes << ii; + } + + QQmlData *ddata = QQmlData::get(object); + if (ddata && ddata->signalHandlers) { + QQmlAbstractBoundSignal *signalHandler = ddata->signalHandlers; + + while (signalHandler) { + if (!dumpProperties) { + signalHandler = signalHandler->m_nextSignal; continue; + } QQmlObjectProperty prop; prop.type = QQmlObjectProperty::SignalProperty; prop.hasNotifySignal = false; - QQmlExpression *expr = signal->expression(); + QQmlExpression *expr = signalHandler->expression(); if (expr) { prop.value = expr->expression(); QObject *scope = expr->scopeObject(); if (scope) { - QString methodName = QString::fromLatin1(scope->metaObject()->method(signal->index()).name()); + QString methodName = QString::fromLatin1(scope->metaObject()->method(signalHandler->index()).name()); if (!methodName.isEmpty()) { prop.name = QLatin1String("on") + methodName[0].toUpper() + methodName.mid(1); @@ -255,23 +277,9 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message, } } fakeProperties << prop; - } else { - if (recur) - buildObjectDump(message, child, recur, dumpProperties); - else - message << objectData(child); - } - } - if (!dumpProperties) { - message << 0; - return; - } - - QList<int> propertyIndexes; - for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) { - if (object->metaObject()->property(ii).isScriptable()) - propertyIndexes << ii; + signalHandler = signalHandler->m_nextSignal; + } } message << propertyIndexes.size() + fakeProperties.count(); diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h index 2b4cafb615..2e351792cc 100644 --- a/src/qml/debugger/qqmlprofilerservice_p.h +++ b/src/qml/debugger/qqmlprofilerservice_p.h @@ -205,16 +205,16 @@ struct QQmlHandlingSignalProfiler { { enabled = QQmlProfilerService::instance ? QQmlProfilerService::instance->profilingEnabled() : false; - if (enabled) { - QQmlProfilerService *service = QQmlProfilerService::instance; - service->startRange(QQmlProfilerService::HandlingSignal); - service->rangeData(QQmlProfilerService::HandlingSignal, - QString::fromLatin1(signal.methodSignature()) + QLatin1String(": ") - + expression->expression()); - service->rangeLocation(QQmlProfilerService::HandlingSignal, - expression->sourceFile(), expression->lineNumber(), - expression->columnNumber()); - } + if (enabled) + init(signal, expression); + } + + QQmlHandlingSignalProfiler(QObject *object, int index, QQmlExpression *expression) + { + enabled = QQmlProfilerService::instance + ? QQmlProfilerService::instance->profilingEnabled() : false; + if (enabled) + init(object->metaObject()->method(index), expression); } ~QQmlHandlingSignalProfiler() @@ -224,6 +224,19 @@ struct QQmlHandlingSignalProfiler { } bool enabled; + +private: + void init(const QMetaMethod &signal, QQmlExpression *expression) + { + QQmlProfilerService *service = QQmlProfilerService::instance; + service->startRange(QQmlProfilerService::HandlingSignal); + service->rangeData(QQmlProfilerService::HandlingSignal, + QString::fromLatin1(signal.methodSignature()) + QLatin1String(": ") + + expression->expression()); + service->rangeLocation(QQmlProfilerService::HandlingSignal, + expression->sourceFile(), expression->lineNumber(), + expression->columnNumber()); + } }; struct QQmlObjectCreatingProfiler { diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index 32da2c616e..5b500e0814 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -421,7 +421,7 @@ inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMi uri, versionMajor, versionMinor, - callback, 0 + callback, 0, 0 }; return QQmlPrivate::qmlregister(QQmlPrivate::ModuleApiRegistration, &api); @@ -435,7 +435,22 @@ inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMi uri, versionMajor, versionMinor, - 0, callback + 0, callback, 0 // unknown QObject instance type + }; + + return QQmlPrivate::qmlregister(QQmlPrivate::ModuleApiRegistration, &api); +} + +template <typename T> +inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMinor, + QObject *(*callback)(QQmlEngine *, QJSEngine *)) +{ + QQmlPrivate::RegisterModuleApi api = { + 1, + + uri, versionMajor, versionMinor, + + 0, callback, &T::staticMetaObject }; return QQmlPrivate::qmlregister(QQmlPrivate::ModuleApiRegistration, &api); diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index f7d0c00a5c..3a3bf403e6 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -55,6 +55,8 @@ #include <QtCore/qstringbuilder.h> #include <QtCore/qdebug.h> +Q_DECLARE_METATYPE(QJSValue) + QT_BEGIN_NAMESPACE class QQmlBoundSignalParameters : public QObject @@ -87,42 +89,45 @@ private: static int evaluateIdx = -1; -QQmlAbstractBoundSignal::QQmlAbstractBoundSignal(QObject *parent) -: QObject(parent) +QQmlAbstractBoundSignal::QQmlAbstractBoundSignal() +: m_prevSignal(0), m_nextSignal(0) { } QQmlAbstractBoundSignal::~QQmlAbstractBoundSignal() { + if (m_prevSignal) { + *m_prevSignal = m_nextSignal; + if (m_nextSignal) m_nextSignal->m_prevSignal = m_prevSignal; + m_prevSignal = 0; + m_nextSignal = 0; + } } -QQmlBoundSignal::QQmlBoundSignal(QObject *scope, const QMetaMethod &signal, - QObject *parent) -: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0) +void QQmlAbstractBoundSignal::addToObject() { - // This is thread safe. Although it may be updated by two threads, they - // will both set it to the same value - so the worst thing that can happen - // is that they both do the work to figure it out. Boo hoo. - if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount(); + Q_ASSERT(!m_prevSignal); + QObject *obj = object(); + Q_ASSERT(obj); - QQml_setParent_noEvent(this, parent); - QQmlPropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx); + QQmlData *data = QQmlData::get(obj, true); + + m_nextSignal = data->signalHandlers; + if (m_nextSignal) m_nextSignal->m_prevSignal = &m_nextSignal; + m_prevSignal = &data->signalHandlers; + data->signalHandlers = this; } -QQmlBoundSignal::QQmlBoundSignal(QQmlContext *ctxt, const QString &val, - QObject *scope, const QMetaMethod &signal, - QObject *parent) -: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0) +QQmlBoundSignal::QQmlBoundSignal(QObject *scope, const QMetaMethod &signal, + QObject *owner) +: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0), m_owner(owner) { // This is thread safe. Although it may be updated by two threads, they // will both set it to the same value - so the worst thing that can happen // is that they both do the work to figure it out. Boo hoo. if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount(); - QQml_setParent_noEvent(this, parent); QQmlPropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx); - - m_expression = new QQmlExpression(ctxt, scope, val); } QQmlBoundSignal::~QQmlBoundSignal() @@ -159,12 +164,6 @@ QQmlExpression *QQmlBoundSignal::setExpression(QQmlExpression *e) return rv; } -QQmlBoundSignal *QQmlBoundSignal::cast(QObject *o) -{ - QQmlAbstractBoundSignal *s = qobject_cast<QQmlAbstractBoundSignal*>(o); - return static_cast<QQmlBoundSignal *>(s); -} - int QQmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) { if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) { @@ -227,10 +226,14 @@ QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method, prop.setWritable(false); } else { QByteArray propType = type; - if ((QMetaType::typeFlags(t) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration) { + QMetaType::TypeFlags flags = QMetaType::typeFlags(t); + if (flags & QMetaType::IsEnumeration) { t = QVariant::Int; propType = "int"; - } else if (t == QMetaType::UnknownType) { + } else if (t == QMetaType::UnknownType || + (t >= int(QMetaType::User) && !(flags & QMetaType::PointerToQObject) && + t != qMetaTypeId<QJSValue>())) { + //the UserType clause is to catch registered QFlags QByteArray scope; QByteArray name; int scopeIdx = propType.lastIndexOf("::"); @@ -244,7 +247,7 @@ QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method, if (scope == "Qt") meta = &QObject::staticQtMetaObject; else - meta = parent->parent()->metaObject(); //### assumes parent->parent() + meta = static_cast<QQmlBoundSignal*>(parent)->object()->metaObject(); for (int i = meta->enumeratorCount() - 1; i >= 0; --i) { QMetaEnum m = meta->enumerator(i); if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) { @@ -297,6 +300,71 @@ int QQmlBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a) } } +//////////////////////////////////////////////////////////////////////// + +QQmlBoundSignalNoParams::QQmlBoundSignalNoParams(QObject *scope, const QMetaMethod &signal, + QObject *owner) +: m_expression(0), m_owner(owner), m_index(signal.methodIndex()), m_isEvaluating(false) +{ + callback = &subscriptionCallback; + QQmlNotifierEndpoint::connect(scope, m_index); +} + +QQmlBoundSignalNoParams::~QQmlBoundSignalNoParams() +{ + delete m_expression; + m_expression = 0; +} + +int QQmlBoundSignalNoParams::index() const +{ + return m_index; +} + +/*! + Returns the signal expression. +*/ +QQmlExpression *QQmlBoundSignalNoParams::expression() const +{ + return m_expression; +} + +/*! + Sets the signal expression to \a e. Returns the current signal expression, + or null if there is no signal expression. + + The QQmlBoundSignalNoParams instance takes ownership of \a e. The caller is + assumes ownership of the returned QQmlExpression. +*/ +QQmlExpression *QQmlBoundSignalNoParams::setExpression(QQmlExpression *e) +{ + QQmlExpression *rv = m_expression; + m_expression = e; + if (m_expression) m_expression->setNotifyOnValueChanged(false); + return rv; +} + +void QQmlBoundSignalNoParams::subscriptionCallback(QQmlNotifierEndpoint *e) +{ + QQmlBoundSignalNoParams *s = static_cast<QQmlBoundSignalNoParams*>(e); + if (!s->m_expression) + return; + + if (QQmlDebugService::isDebuggingEnabled()) + QV8DebugService::instance()->signalEmitted(QString::fromAscii(s->m_owner->metaObject()->method(s->m_index).methodSignature())); + + QQmlHandlingSignalProfiler prof(s->m_owner, s->m_index, s->m_expression); + + s->m_isEvaluating = true; + + if (s->m_expression && s->m_expression->engine()) { + QQmlExpressionPrivate::get(s->m_expression)->value(); + if (s->m_expression && s->m_expression->hasError()) + QQmlEnginePrivate::warning(s->m_expression->engine(), s->m_expression->error()); + } + s->m_isEvaluating = false; +} + QT_END_NAMESPACE #include <qqmlboundsignal.moc> diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h index 11386159cb..5fc8c3522f 100644 --- a/src/qml/qml/qqmlboundsignal_p.h +++ b/src/qml/qml/qqmlboundsignal_p.h @@ -57,36 +57,48 @@ #include <QtCore/qmetaobject.h> +#include <private/qqmlnotifier_p.h> #include <private/qobject_p.h> QT_BEGIN_NAMESPACE -class Q_QML_EXPORT QQmlAbstractBoundSignal : public QObject +class Q_QML_EXPORT QQmlAbstractBoundSignal { - Q_OBJECT public: - QQmlAbstractBoundSignal(QObject *parent = 0); - virtual ~QQmlAbstractBoundSignal() = 0; + QQmlAbstractBoundSignal(); + virtual ~QQmlAbstractBoundSignal(); + + virtual int index() const = 0; + virtual QQmlExpression *expression() const = 0; + virtual QQmlExpression *setExpression(QQmlExpression *) = 0; + virtual QObject *object() = 0; + + void addToObject(); + +private: + friend class QQmlData; + friend class QQmlPropertyPrivate; + friend class QQmlEngineDebugService; + QQmlAbstractBoundSignal **m_prevSignal; + QQmlAbstractBoundSignal *m_nextSignal; }; class QQmlBoundSignalParameters; -class Q_QML_EXPORT QQmlBoundSignal : public QQmlAbstractBoundSignal +class Q_QML_EXPORT QQmlBoundSignal : public QObject, + public QQmlAbstractBoundSignal { public: - QQmlBoundSignal(QObject *scope, const QMetaMethod &signal, QObject *parent); - QQmlBoundSignal(QQmlContext *ctxt, const QString &val, QObject *scope, - const QMetaMethod &signal, QObject *parent); + QQmlBoundSignal(QObject *scope, const QMetaMethod &signal, QObject *owner); virtual ~QQmlBoundSignal(); int index() const; QQmlExpression *expression() const; QQmlExpression *setExpression(QQmlExpression *); + QObject *object() { return m_owner; } bool isEvaluating() const { return m_isEvaluating; } - static QQmlBoundSignal *cast(QObject *); - protected: virtual int qt_metacall(QMetaObject::Call c, int id, void **a); @@ -96,8 +108,34 @@ private: bool m_paramsValid : 1; bool m_isEvaluating : 1; QQmlBoundSignalParameters *m_params; + QObject *m_owner; }; +class Q_QML_EXPORT QQmlBoundSignalNoParams : public QQmlAbstractBoundSignal, + public QQmlNotifierEndpoint +{ +public: + QQmlBoundSignalNoParams(QObject *scope, const QMetaMethod &signal, QObject *owner); + virtual ~QQmlBoundSignalNoParams(); + + int index() const; + + QQmlExpression *expression() const; + QQmlExpression *setExpression(QQmlExpression *); + QObject *object() { return m_owner; } + + static void subscriptionCallback(QQmlNotifierEndpoint *e); + + bool isEvaluating() const { return m_isEvaluating; } + +private: + QQmlExpression *m_expression; + QObject *m_owner; + int m_index; + bool m_isEvaluating; +}; + + QT_END_NAMESPACE #endif // QQMLBOUNDSIGNAL_P_H diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 416178e3e1..7bddaadcd0 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -110,8 +110,9 @@ static inline QString buildTypeNameForDebug(const QMetaObject *metaObject) /*! \class QQmlComponent - \since 4.7 + \since 5.0 \brief The QQmlComponent class encapsulates a QML component definition. + \inmodule QtQml \mainclass Components are reusable, encapsulated QML elements with well-defined interfaces. @@ -179,6 +180,8 @@ static inline QString buildTypeNameForDebug(const QMetaObject *metaObject) } \endcode + Note that the QtQuick 1 version is named QDeclarativeComponent. + \sa {Using QML Bindings in C++ Applications}, {Integrating QML Code with Existing Qt UI Code} */ diff --git a/src/qml/qml/qqmlcontext.h b/src/qml/qml/qqmlcontext.h index f6d8aa1d3a..4b11095ec2 100644 --- a/src/qml/qml/qqmlcontext.h +++ b/src/qml/qml/qqmlcontext.h @@ -98,7 +98,6 @@ private: friend class QQmlComponent; friend class QQmlComponentPrivate; friend class QQmlScriptPrivate; - friend class QQmlBoundSignalProxy; friend class QQmlContextData; QQmlContext(QQmlContextData *); QQmlContext(QQmlEngine *, bool); diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index 09d1a23510..e7e001c4f2 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -63,6 +63,7 @@ template <class Key, class T> class QHash; class QQmlGuardImpl; class QQmlCompiledData; class QQmlAbstractBinding; +class QQmlAbstractBoundSignal; class QQmlContext; class QQmlPropertyCache; class QQmlContextData; @@ -79,7 +80,7 @@ public: QQmlData() : ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), hasTaintedV8Object(false), isQueuedForDeletion(false), notifyList(0), context(0), outerContext(0), - bindings(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), + bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), v8objectid(0), propertyCache(0), guards(0), extendedData(0) { init(); @@ -136,6 +137,7 @@ public: QQmlContextData *outerContext; QQmlAbstractBinding *bindings; + QQmlAbstractBoundSignal *signalHandlers; // Linked list for QQmlContext::contextObjects QQmlData *nextContextObject; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 672996085f..955c8ce414 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -69,6 +69,7 @@ #include <private/qdebugmessageservice_p.h> #include "qqmlincubator.h" #include <private/qv8profilerservice_p.h> +#include <private/qqmlboundsignal_p.h> #include <QtCore/qstandardpaths.h> #include <QtCore/qsettings.h> @@ -507,7 +508,8 @@ QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine() /*! \class QQmlEngine - \since 4.7 + \since 5.0 + \inmodule QtQml \brief The QQmlEngine class provides an environment for instantiating QML components. \mainclass @@ -533,6 +535,8 @@ QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine() In this case, the Text item will be created in the engine's \l {QQmlEngine::rootContext()}{root context}. + Note that the QtQuick 1 version is called QDeclarativeEngine. + \sa QQmlComponent QQmlContext */ @@ -1020,10 +1024,11 @@ QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object, return qmlAttachedPropertiesObjectById(*idCache, object, create); } -QQmlDebuggingEnabler::QQmlDebuggingEnabler() +QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning) { #ifndef QQML_NO_DEBUG_PROTOCOL - if (!QQmlEnginePrivate::qml_debugging_enabled) { + if (!QQmlEnginePrivate::qml_debugging_enabled + && printWarning) { qDebug("QML debugging is enabled. Only use this in a safe environment."); } QQmlEnginePrivate::qml_debugging_enabled = true; @@ -1153,6 +1158,15 @@ void QQmlData::destroyed(QObject *object) binding = next; } + QQmlAbstractBoundSignal *signalHandler = signalHandlers; + while (signalHandler) { + QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal; + signalHandler->m_prevSignal = 0; + signalHandler->m_nextSignal = 0; + delete signalHandler; + signalHandler = next; + } + if (bindingBits) free(bindingBits); @@ -1690,6 +1704,7 @@ QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module) a = new QQmlMetaType::ModuleApiInstance; a->scriptCallback = module.script; a->qobjectCallback = module.qobject; + a->instanceMetaObject = module.instanceMetaObject; moduleApiInstances.insert(module, a); } diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp index 79424913f8..ce7fd01fdf 100644 --- a/src/qml/qml/qqmlerror.cpp +++ b/src/qml/qml/qqmlerror.cpp @@ -49,7 +49,8 @@ QT_BEGIN_NAMESPACE /*! \class QQmlError - \since 4.7 + \since 5.0 + \inmodule QtQml \brief The QQmlError class encapsulates a QML error. QQmlError includes a textual description of the error, as well @@ -69,6 +70,8 @@ QT_BEGIN_NAMESPACE ^ \endcode + Note that the QtQuick 1 version is named QDeclarativeError + \sa QQuickView::errors(), QQmlComponent::errors() */ class QQmlErrorPrivate diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index 60a0fe1c89..d760486605 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -137,7 +137,8 @@ QQmlExpressionPrivate::create(QQmlContextData *ctxt, QObject *object, /*! \class QQmlExpression - \since 4.7 + \since 5.0 + \inmodule QtQml \brief The QQmlExpression class evaluates JavaScript in a QML context. For example, given a file \c main.qml like this: @@ -161,6 +162,8 @@ QQmlExpressionPrivate::create(QQmlContextData *ctxt, QObject *object, QQmlExpression *expr = new QQmlExpression(engine->rootContext(), myObject, "width * 2"); int result = expr->evaluate().toInt(); // result = 400 \endcode + + Note that the QtQuick 1 version is called QDeclarativeExpression. */ /*! diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp index 86d9f9588d..73d74f9e21 100644 --- a/src/qml/qml/qqmlextensionplugin.cpp +++ b/src/qml/qml/qqmlextensionplugin.cpp @@ -44,7 +44,8 @@ QT_BEGIN_NAMESPACE /*! - \since 4.7 + \since 5.0 + \inmodule QtQml \class QQmlExtensionPlugin \brief The QQmlExtensionPlugin class provides an abstract base for custom QML extension plugins. @@ -75,7 +76,7 @@ QT_BEGIN_NAMESPACE as a new QML element. It provides the current time through \c hour and \c minute properties, like this: - \snippet examples/declarative/cppextensions/plugins/plugin.cpp 0 + \snippet examples/qml/cppextensions/plugins/plugin.cpp 0 \dots To make this class available as a QML type, create a plugin that registers @@ -83,9 +84,9 @@ QT_BEGIN_NAMESPACE module will be named \c com.nokia.TimeExample (as defined in the project file further below). - \snippet examples/declarative/cppextensions/plugins/plugin.cpp plugin + \snippet examples/qml/cppextensions/plugins/plugin.cpp plugin \codeline - \snippet examples/declarative/cppextensions/plugins/plugin.cpp export + \snippet examples/qml/cppextensions/plugins/plugin.cpp export This registers the \c TimeModel class with the 1.0 version of this plugin library, as a QML type called \c Time. The Q_ASSERT statement @@ -121,6 +122,8 @@ QT_BEGIN_NAMESPACE The \l {Tutorial: Writing QML extensions with C++} also contains a chapter on creating QML plugins. + Note that the QtQuick 1 version is called QDeclarativeExtensionPlugin. + \sa QQmlEngine::importPlugin(), {How to Create Qt Plugins} */ diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp index 00fd805ee0..ad28e38a64 100644 --- a/src/qml/qml/qqmllist.cpp +++ b/src/qml/qml/qqmllist.cpp @@ -87,7 +87,7 @@ void QQmlListReferencePrivate::release() /*! \class QQmlListReference -\since 4.7 +\since 5.0 \module QtQml \brief The QQmlListReference class allows the manipulation of QQmlListProperty properties. @@ -111,6 +111,8 @@ Attempting to add objects of the incorrect type to a list property will fail. Like with normal lists, when accessing a list element by index, it is the callers responsibility to ensure that it does not request an out of range element using the count() method before calling at(). + +The QtQuick 1 version of this class is named QDeclarativeListReference. */ /*! @@ -306,7 +308,8 @@ int QQmlListReference::count() const /*! \class QQmlListProperty -\since 4.7 +\since 5.0 +\inmodule QtQml \brief The QQmlListProperty class allows applications to expose list-like properties to QML. @@ -340,6 +343,8 @@ Q_PROPERTY(QQmlListProperty<Fruit> fruit READ fruit); QML list properties are typesafe - in this case \c {Fruit} is a QObject type that \c {Apple}, \c {Orange} and \c {Banana} all derive from. +The QtQuick 1 version of this class is named QDeclarativeListProperty. + \note QQmlListProperty can only be used for lists of QObject-derived object pointers. \sa {Object and List Property Types} diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 4af08c28bf..856f75fc16 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -908,6 +908,10 @@ int registerModuleApi(const QQmlPrivate::RegisterModuleApi &api) import.minor = api.versionMinor; import.script = api.scriptApi; import.qobject = api.qobjectApi; + import.instanceMetaObject = (api.qobjectApi && api.version >= 1) ? api.instanceMetaObject : 0; // BC with version 0. + + if (import.qobject && !import.instanceMetaObject) // BC - check import.iMO rather than api.iMO. + qWarning() << "qmlRegisterModuleApi(): sub-optimal: use the templated version of this function instead!"; int index = data->moduleApiCount++; diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index b715d0c8f2..03017cafab 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -115,20 +115,23 @@ public: struct ModuleApiInstance { ModuleApiInstance() - : scriptCallback(0), qobjectCallback(0), qobjectApi(0) {} + : scriptCallback(0), qobjectCallback(0), qobjectApi(0), instanceMetaObject(0) {} QJSValue (*scriptCallback)(QQmlEngine *, QJSEngine *); QObject *(*qobjectCallback)(QQmlEngine *, QJSEngine *); - QJSValue scriptApi; QObject *qobjectApi; + const QMetaObject *instanceMetaObject; + QJSValue scriptApi; + }; struct ModuleApi { inline ModuleApi(); inline bool operator==(const ModuleApi &) const; int major; int minor; - QJSValue (*script)(QQmlEngine *, QJSEngine *); QObject *(*qobject)(QQmlEngine *, QJSEngine *); + const QMetaObject *instanceMetaObject; + QJSValue (*script)(QQmlEngine *, QJSEngine *); }; static ModuleApi moduleApi(const QString &, int, int); static QHash<QString, QList<ModuleApi> > moduleApis(); @@ -247,8 +250,9 @@ QQmlMetaType::ModuleApi::ModuleApi() { major = 0; minor = 0; - script = 0; qobject = 0; + instanceMetaObject = 0; + script = 0; } bool QQmlMetaType::ModuleApi::operator==(const ModuleApi &other) const diff --git a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp index e5d0d708e2..4c31e557bc 100644 --- a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp +++ b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp @@ -45,7 +45,8 @@ QT_BEGIN_NAMESPACE /*! \class QQmlNetworkAccessManagerFactory - \since 4.7 + \since 5.0 + \inmodule QtQml \brief The QQmlNetworkAccessManagerFactory class creates QNetworkAccessManager instances for a QML engine. A QML engine uses QNetworkAccessManager for all network access. @@ -79,7 +80,9 @@ QT_BEGIN_NAMESPACE For more information about signals and threads, see \l {Threads and QObjects} and \l {Signals and Slots Across Threads}. - \sa {declarative/cppextensions/networkaccessmanagerfactory}{NetworkAccessManagerFactory example} + The QtQuick 1 version of this class is named QDeclarativeNetworkAccessManagerFactory. + + \sa {qml/cppextensions/networkaccessmanagerfactory}{NetworkAccessManagerFactory example} */ /*! diff --git a/src/qml/qml/qqmlparserstatus.cpp b/src/qml/qml/qqmlparserstatus.cpp index d4e415a069..8468a1da00 100644 --- a/src/qml/qml/qqmlparserstatus.cpp +++ b/src/qml/qml/qqmlparserstatus.cpp @@ -45,7 +45,8 @@ QT_BEGIN_NAMESPACE /*! \class QQmlParserStatus - \since 4.7 + \since 5.0 + \inmodule QtQml \brief The QQmlParserStatus class provides updates on the QML parser state. QQmlParserStatus provides a mechanism for classes instantiated by @@ -75,6 +76,8 @@ QT_BEGIN_NAMESPACE void componentComplete(); } \endcode + + The QtQuick 1.0 version of this class is named QDeclarativeParserStatus. */ /*! \internal */ diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index b4c6fc3a12..82da62ff45 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -246,6 +246,7 @@ namespace QQmlPrivate QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *); QObject *(*qobjectApi)(QQmlEngine *, QJSEngine *); + const QMetaObject *instanceMetaObject; }; enum RegistrationType { diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index d3778fa5c5..f68c345f3a 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -72,7 +72,8 @@ QT_BEGIN_NAMESPACE /*! \class QQmlProperty -\since 4.7 +\since 5.0 +\inmodule QtQml \brief The QQmlProperty class abstracts accessing properties on objects created from QML. As QML uses Qt's meta-type system all of the existing QMetaObject classes can be used to introspect @@ -108,6 +109,8 @@ qWarning() << "Current pixel size:" << property.read().toInt(); property.write(24); qWarning() << "Pixel size should now be 24:" << property.read().toInt(); \endcode + +The QtQuick 1 version of this class was named QDeclarativeProperty. */ /*! @@ -923,15 +926,17 @@ QQmlPropertyPrivate::signalExpression(const QQmlProperty &that) if (!(that.type() & QQmlProperty::SignalProperty)) return 0; - const QObjectList &children = that.d->object->children(); - - for (int ii = 0; ii < children.count(); ++ii) { - QObject *child = children.at(ii); + QQmlData *data = QQmlData::get(that.d->object); + if (!data) + return 0; - QQmlBoundSignal *signal = QQmlBoundSignal::cast(child); - if (signal && signal->index() == that.index()) - return signal->expression(); - } + QQmlAbstractBoundSignal *signalHandler = data->signalHandlers; + + while (signalHandler && signalHandler->index() != that.index()) + signalHandler = signalHandler->m_nextSignal; + + if (signalHandler) + return signalHandler->expression(); return 0; } @@ -952,19 +957,27 @@ QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that, return 0; } - const QObjectList &children = that.d->object->children(); - - for (int ii = 0; ii < children.count(); ++ii) { - QObject *child = children.at(ii); + QQmlData *data = QQmlData::get(that.d->object, 0 != expr); + if (!data) + return 0; - QQmlBoundSignal *signal = QQmlBoundSignal::cast(child); - if (signal && signal->index() == that.index()) - return signal->setExpression(expr); - } + QQmlAbstractBoundSignal *signalHandler = data->signalHandlers; + + while (signalHandler && signalHandler->index() != that.index()) + signalHandler = signalHandler->m_nextSignal; + + if (signalHandler) + return signalHandler->setExpression(expr); if (expr) { - QQmlBoundSignal *signal = new QQmlBoundSignal(that.d->object, that.method(), that.d->object); - return signal->setExpression(expr); + QQmlAbstractBoundSignal *signal = 0; + if (that.method().parameterTypes().count()) + signal = new QQmlBoundSignal(that.d->object, that.method(), that.d->object); + else + signal = new QQmlBoundSignalNoParams(that.d->object, that.method(), that.d->object); + QQmlExpression *oldExpr = signal->setExpression(expr); + signal->addToObject(); + return oldExpr; } else { return 0; } diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 4a1eb79213..1e8cfb6c20 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -680,7 +680,7 @@ struct StaticQtMetaObject : public QObject { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; } }; -static int EnumType(const QMetaObject *metaobj, const QByteArray &str) +static int EnumType(const QMetaObject *metaobj, const QByteArray &str, int type) { QByteArray scope; QByteArray name; @@ -701,7 +701,7 @@ static int EnumType(const QMetaObject *metaobj, const QByteArray &str) if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) return QVariant::Int; } - return QVariant::Invalid; + return type; } // Returns an array of the arguments for method \a index. The first entry in the array @@ -738,12 +738,16 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index, for (int ii = 0; ii < argc; ++ii) { int type = m.parameterType(ii); - if ((QMetaType::typeFlags(type) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration) + QMetaType::TypeFlags flags = QMetaType::typeFlags(type); + if (flags & QMetaType::IsEnumeration) type = QVariant::Int; - else if (type == QMetaType::UnknownType) { + else if (type == QMetaType::UnknownType || + (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) && + type != qMetaTypeId<QJSValue>())) { + //the UserType clause is to catch registered QFlags if (argTypeNames.isEmpty()) argTypeNames = m.parameterTypes(); - type = EnumType(object->metaObject(), argTypeNames.at(ii)); + type = EnumType(object->metaObject(), argTypeNames.at(ii), type); } if (type == QMetaType::UnknownType) { if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii); @@ -767,12 +771,16 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index, for (int ii = 0; ii < argc; ++ii) { int type = m.parameterType(ii); - if ((QMetaType::typeFlags(type) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration) + QMetaType::TypeFlags flags = QMetaType::typeFlags(type); + if (flags & QMetaType::IsEnumeration) type = QVariant::Int; - else if (type == QMetaType::UnknownType) { + else if (type == QMetaType::UnknownType || + (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) && + type != qMetaTypeId<QJSValue>())) { + //the UserType clause is to catch registered QFlags) if (argTypeNames.isEmpty()) argTypeNames = m.parameterTypes(); - type = EnumType(object->metaObject(), argTypeNames.at(ii)); + type = EnumType(object->metaObject(), argTypeNames.at(ii), type); } if (type == QMetaType::UnknownType) { if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii); diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 352684ed5e..5412315d31 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -724,10 +724,15 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, QMetaMethod signal = target->metaObject()->method(instr.signalIndex); - QQmlBoundSignal *bs = new QQmlBoundSignal(target, signal, target); - QQmlExpression *expr = + QQmlAbstractBoundSignal *bs = 0; + if (signal.parameterTypes().count()) + bs = new QQmlBoundSignal(target, signal, target); + else + bs = new QQmlBoundSignalNoParams(target, signal, target); + QQmlExpression *expr = new QQmlExpression(CTXT, context, DATAS.at(instr.value), true, COMP->name, instr.line, instr.column, *new QQmlExpressionPrivate); bs->setExpression(expr); + bs->addToObject(); QML_END_INSTR(StoreSignal) QML_BEGIN_INSTR(StoreImportedScript) diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp index ea4d1afbbc..453120c6c7 100644 --- a/src/qml/qml/v4/qv4irbuilder.cpp +++ b/src/qml/qml/v4/qv4irbuilder.cpp @@ -428,18 +428,18 @@ bool QV4IRBuilder::visit(AST::IdentifierExpression *ast) if (r.isValid()) { if (r.type) { _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column); - } /*else if (r.importNamespace) { + } else if (r.importNamespace) { QQmlMetaType::ModuleApiInstance *moduleApi = m_expression->importCache->moduleApi(r.importNamespace); - if (moduleApi) { - if (moduleApi->qobjectCallback) { - moduleApi->qobjectApi = moduleApi->qobjectCallback(QQmlEnginePrivate::get(m_engine), QQmlEnginePrivate::get(m_engine)); - moduleApi->qobjectCallback = 0; - moduleApi->scriptCallback = 0; - } - if (moduleApi->qobjectApi) - _expr.code = _block->MODULE_OBJECT(name, moduleApi->qobjectApi->metaObject(), IR::Name::MemberStorage, line, column); + if (moduleApi && moduleApi->instanceMetaObject) { + // Note: we don't need to check moduleApi->qobjectCallback here, since + // we did that check in registerModuleApi() in qqmlmetatype.cpp. + // We cannot create the QObject Module Api Instance here, + // as we might be running in a loader thread. + // Thus, V4 can only handle bindings which use Module APIs which + // were registered with the templated registration function. + _expr.code = _block->MODULE_OBJECT(name, moduleApi->instanceMetaObject, IR::Name::MemberStorage, line, column); } - }*/ //### we can't create the actual QObject here, as we may be running in a thread (can be reenabled once QTBUG-24894 is handled) + } // We don't support anything else } else { bool found = false; |