diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/doc/src/cppintegration/data.qdoc | 27 | ||||
-rw-r--r-- | src/qml/jsapi/qjsengine.cpp | 7 | ||||
-rw-r--r-- | src/qml/jsapi/qjsengine_p.h | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype.cpp | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper.cpp | 13 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/v8/qv8engine.cpp | 18 |
7 files changed, 67 insertions, 7 deletions
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc index c083d63e51..26d3060318 100644 --- a/src/qml/doc/src/cppintegration/data.qdoc +++ b/src/qml/doc/src/cppintegration/data.qdoc @@ -307,6 +307,33 @@ them with default constructed values, do not use the indexed delete operator ("delete sequence[i]") but instead use the \c {splice} function ("sequence.splice(startIndex, deleteCount)"). +\section2 Value types + +Some value types in Qt such as QPoint are represented in JavaScript as objects +that have the same properties and functions like in the C++ API. The same +representation is possible with custom C++ value types. To enable a custom +value type with the QML engine, the class declaration needs to be annotated +with \c{Q_GADGET}. Properties that are intended to be visible in the JavaScript +representation need to be declared with \c Q_PROPERTY. Similarly functions need +to be marked with \c Q_INVOKABLE. This is the same with QObject based C++ APIs. +For example, the \c Actor class below is annotated as gadget and has +properties: + +\code + class Actor + { + Q_GADGET + Q_PROPERTY(QString name READ name WRITE setName) + public: + QString name() const { return m_name; } + void setName(const QString &name) { m_name = name; } + + private: + QString m_name; + } + + Q_DECLARE_METATYPE(Actor) +\endcode \section1 Enumeration Types diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index 09891019c5..8525aedb6c 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -530,7 +530,7 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr) Creates a QJSValue with the given \a value. - \sa fromScriptValue() + \sa fromScriptValue(), newVariant() */ /*! \fn T QJSEngine::fromScriptValue(const QJSValue &value) @@ -541,6 +541,11 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr) */ +QJSEnginePrivate *QJSEnginePrivate::get(QV4::ExecutionEngine *e) +{ + return e->v8Engine->publicEngine()->d_func(); +} + QJSEnginePrivate::~QJSEnginePrivate() { for (QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter) diff --git a/src/qml/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h index eba8ffb4be..3f7e91bffe 100644 --- a/src/qml/jsapi/qjsengine_p.h +++ b/src/qml/jsapi/qjsengine_p.h @@ -54,6 +54,10 @@ QT_BEGIN_NAMESPACE class QQmlPropertyCache; +namespace QV4 { +struct ExecutionEngine; +} + class QJSEnginePrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QJSEngine) @@ -61,6 +65,7 @@ class QJSEnginePrivate : public QObjectPrivate public: static QJSEnginePrivate* get(QJSEngine*e) { return e->d_func(); } static const QJSEnginePrivate* get(const QJSEngine*e) { return e->d_func(); } + static QJSEnginePrivate* get(QV4::ExecutionEngine *e); QJSEnginePrivate() : mutex(QMutex::Recursive) {} ~QJSEnginePrivate(); diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index e22e0f8fdc..e901a9c0d7 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -107,6 +107,9 @@ const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t) break; } + QMetaType metaType(t); + if (metaType.flags() & QMetaType::IsGadget) + return metaType.metaObject(); return 0; } diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 8ed1169ec7..00b206f0dc 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -133,7 +133,7 @@ bool QQmlValueTypeReference::readReferenceValue() const if (QQmlValueTypeFactory::isValueType(variantReferenceType)) { QQmlPropertyCache *cache = 0; if (const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(variantReferenceType)) - cache = QQmlEnginePrivate::get(engine())->cache(mo); + cache = QJSEnginePrivate::get(engine())->cache(mo); if (d()->gadgetPtr) QMetaType::destroy(d()->metaType, d()->gadgetPtr); d()->gadgetPtr = 0; @@ -177,7 +177,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype); r->setPrototype(proto); r->d()->object = object; r->d()->property = property; - r->d()->propertyCache = QQmlEnginePrivate::get(engine)->cache(metaObject); + r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject); r->d()->metaType = typeId; r->d()->gadgetPtr = QMetaType::create(r->d()->metaType); return r->asReturnedValue(); @@ -191,7 +191,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->alloc<QQmlValueTypeWrapper>(engine)); ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype); r->setPrototype(proto); - r->d()->propertyCache = QQmlEnginePrivate::get(engine)->cache(metaObject); + r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject); r->d()->metaType = typeId; r->d()->gadgetPtr = QMetaType::create(r->d()->metaType); r->d()->setValue(value); @@ -206,6 +206,13 @@ QVariant QQmlValueTypeWrapper::toVariant() const return d()->toVariant(); } +void QQmlValueTypeWrapper::toGadget(void *data) const +{ + int typeId = d()->metaType; + QMetaType::destruct(typeId, data); + QMetaType::construct(typeId, data, d()->gadget()); +} + void QQmlValueTypeWrapper::destroy(Heap::Base *that) { Heap::QQmlValueTypeWrapper *w = static_cast<Heap::QQmlValueTypeWrapper *>(that); diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h index ad883266bd..2d0fbcbf52 100644 --- a/src/qml/qml/qqmlvaluetypewrapper_p.h +++ b/src/qml/qml/qqmlvaluetypewrapper_p.h @@ -84,6 +84,7 @@ public: static ReturnedValue create(ExecutionEngine *engine, const QVariant &, const QMetaObject *metaObject, int typeId); QVariant toVariant() const; + void toGadget(void *data) const; bool isEqual(const QVariant& value); static ReturnedValue get(Managed *m, String *name, bool *hasProperty); diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index cf66c5c2f3..0a309c2775 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -700,10 +700,14 @@ QV4::ReturnedValue QV8Engine::metaTypeToJS(int type, const void *data) QByteArray typeName = QMetaType::typeName(type); if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(data)) { return QV4::Encode::null(); - } else { - // Fall back to wrapping in a QVariant. - return QV4::Encode(m_v4Engine->newVariantObject(QVariant(type, data))); } + QMetaType mt(type); + if (mt.flags() & QMetaType::IsGadget) { + Q_ASSERT(mt.metaObject()); + return QV4::QQmlValueTypeWrapper::create(m_v4Engine, QVariant(type, data), mt.metaObject(), type); + } + // Fall back to wrapping in a QVariant. + return QV4::Encode(m_v4Engine->newVariantObject(QVariant(type, data))); } } Q_UNREACHABLE(); @@ -835,6 +839,14 @@ bool QV8Engine::metaTypeFromJS(const QV4::ValueRef value, int type, void *data) ; } + { + QV4::Scoped<QV4::QQmlValueTypeWrapper> vtw(scope, value); + if (vtw && vtw->d()->metaType == type) { + vtw->toGadget(data); + return true; + } + } + #if 0 if (isQtVariant(value)) { const QVariant &var = variantValue(value); |