diff options
Diffstat (limited to 'src/qml/qml/qqmltypewrapper.cpp')
-rw-r--r-- | src/qml/qml/qqmltypewrapper.cpp | 147 |
1 files changed, 116 insertions, 31 deletions
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index d4e1910a72..404bc0612e 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -52,16 +52,17 @@ QT_BEGIN_NAMESPACE using namespace QV4; -DEFINE_OBJECT_VTABLE(QmlTypeWrapper); +DEFINE_OBJECT_VTABLE(QQmlTypeWrapper); +DEFINE_OBJECT_VTABLE(QQmlScopedEnumWrapper); -void Heap::QmlTypeWrapper::init() +void Heap::QQmlTypeWrapper::init() { Object::init(); mode = IncludeEnums; object.init(); } -void Heap::QmlTypeWrapper::destroy() +void Heap::QQmlTypeWrapper::destroy() { QQmlType::derefHandle(typePrivate); typePrivate = nullptr; @@ -71,17 +72,17 @@ void Heap::QmlTypeWrapper::destroy() Object::destroy(); } -QQmlType Heap::QmlTypeWrapper::type() const +QQmlType Heap::QQmlTypeWrapper::type() const { return QQmlType(typePrivate); } -bool QmlTypeWrapper::isSingleton() const +bool QQmlTypeWrapper::isSingleton() const { return d()->type().isSingleton(); } -QObject* QmlTypeWrapper::singletonObject() const +QObject* QQmlTypeWrapper::singletonObject() const { if (!isSingleton()) return 0; @@ -92,7 +93,7 @@ QObject* QmlTypeWrapper::singletonObject() const return siinfo->qobjectApi(e); } -QVariant QmlTypeWrapper::toVariant() const +QVariant QQmlTypeWrapper::toVariant() const { QObject *qobjectSingleton = singletonObject(); if (qobjectSingleton) @@ -104,13 +105,13 @@ QVariant QmlTypeWrapper::toVariant() const // Returns a type wrapper for type t on o. This allows access of enums, and attached properties. -ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, const QQmlType &t, - Heap::QmlTypeWrapper::TypeNameMode mode) +ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, const QQmlType &t, + Heap::QQmlTypeWrapper::TypeNameMode mode) { Q_ASSERT(t.isValid()); Scope scope(engine); - Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>()); + Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>()); w->d()->mode = mode; w->d()->object = o; w->d()->typePrivate = t.priv(); QQmlType::refHandle(w->d()->typePrivate); @@ -119,14 +120,14 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, c // Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a // namespace. -ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const QQmlImportRef *importNamespace, - Heap::QmlTypeWrapper::TypeNameMode mode) +ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const QQmlImportRef *importNamespace, + Heap::QQmlTypeWrapper::TypeNameMode mode) { Q_ASSERT(t); Q_ASSERT(importNamespace); Scope scope(engine); - Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>()); + Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>()); w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t; w->d()->importNamespace = importNamespace; t->addref(); return w.asReturnedValue(); @@ -160,14 +161,14 @@ static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *n return v4->throwTypeError(message); } -ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty) +ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty) { - Q_ASSERT(m->as<QmlTypeWrapper>()); + Q_ASSERT(m->as<QQmlTypeWrapper>()); - QV4::ExecutionEngine *v4 = static_cast<const QmlTypeWrapper *>(m)->engine(); + QV4::ExecutionEngine *v4 = static_cast<const QQmlTypeWrapper *>(m)->engine(); QV4::Scope scope(v4); - Scoped<QmlTypeWrapper> w(scope, static_cast<const QmlTypeWrapper *>(m)); + Scoped<QQmlTypeWrapper> w(scope, static_cast<const QQmlTypeWrapper *>(m)); if (hasProperty) *hasProperty = true; @@ -189,7 +190,7 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope if (qobjectSingleton) { // check for enum value - const bool includeEnums = w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums; + const bool includeEnums = w->d()->mode == Heap::QQmlTypeWrapper::IncludeEnums; if (includeEnums && name->startsWithUpper()) { const int value = enumForSingleton(v4, name, qobjectSingleton, type); if (value != -1) @@ -227,6 +228,15 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope if (ok) return QV4::Primitive::fromInt32(value).asReturnedValue(); + value = type.scopedEnumIndex(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); + if (ok) { + Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocObject<QQmlScopedEnumWrapper>()); + enumWrapper->d()->typePrivate = type.priv(); + QQmlType::refHandle(enumWrapper->d()->typePrivate); + enumWrapper->d()->scopeEnumIndex = value; + return enumWrapper.asReturnedValue(); + } + // Fall through to base implementation } else if (w->d()->object) { @@ -283,13 +293,13 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope } -void QmlTypeWrapper::put(Managed *m, String *name, const Value &value) +bool QQmlTypeWrapper::put(Managed *m, String *name, const Value &value) { - Q_ASSERT(m->as<QmlTypeWrapper>()); - QmlTypeWrapper *w = static_cast<QmlTypeWrapper *>(m); + Q_ASSERT(m->as<QQmlTypeWrapper>()); + QQmlTypeWrapper *w = static_cast<QQmlTypeWrapper *>(m); QV4::ExecutionEngine *v4 = w->engine(); if (v4->hasException) - return; + return false; QV4::Scope scope(v4); QQmlContextData *context = v4->callingQmlContext(); @@ -300,7 +310,8 @@ void QmlTypeWrapper::put(Managed *m, String *name, const Value &value) QQmlEngine *e = scope.engine->qmlEngine(); QObject *ao = qmlAttachedPropertiesObjectById(type.attachedPropertiesId(QQmlEnginePrivate::get(e)), object); if (ao) - QV4::QObjectWrapper::setQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value); + return QV4::QObjectWrapper::setQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value); + return false; } else if (type.isSingleton()) { QQmlEngine *e = scope.engine->qmlEngine(); QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo(); @@ -308,21 +319,23 @@ void QmlTypeWrapper::put(Managed *m, String *name, const Value &value) QObject *qobjectSingleton = siinfo->qobjectApi(e); if (qobjectSingleton) { - QV4::QObjectWrapper::setQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value); + return QV4::QObjectWrapper::setQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value); } else if (!siinfo->scriptApi(e).isUndefined()) { QV4::ScopedObject apiprivate(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e))); if (!apiprivate) { QString error = QLatin1String("Cannot assign to read-only property \"") + name->toQString() + QLatin1Char('\"'); v4->throwError(error); - return; + return false; } else { - apiprivate->put(name, value); + return apiprivate->put(name, value); } } } + + return false; } -PropertyAttributes QmlTypeWrapper::query(const Managed *m, String *name) +PropertyAttributes QQmlTypeWrapper::query(const Managed *m, String *name) { // ### Implement more efficiently. bool hasProperty = false; @@ -330,11 +343,11 @@ PropertyAttributes QmlTypeWrapper::query(const Managed *m, String *name) return hasProperty ? Attr_Data : Attr_Invalid; } -bool QmlTypeWrapper::isEqualTo(Managed *a, Managed *b) +bool QQmlTypeWrapper::isEqualTo(Managed *a, Managed *b) { - Q_ASSERT(a->as<QV4::QmlTypeWrapper>()); - QV4::QmlTypeWrapper *qmlTypeWrapperA = static_cast<QV4::QmlTypeWrapper *>(a); - if (QV4::QmlTypeWrapper *qmlTypeWrapperB = b->as<QV4::QmlTypeWrapper>()) + Q_ASSERT(a->as<QV4::QQmlTypeWrapper>()); + QV4::QQmlTypeWrapper *qmlTypeWrapperA = static_cast<QV4::QQmlTypeWrapper *>(a); + if (QV4::QQmlTypeWrapper *qmlTypeWrapperB = b->as<QV4::QQmlTypeWrapper>()) return qmlTypeWrapperA->toVariant() == qmlTypeWrapperB->toVariant(); else if (QV4::QObjectWrapper *qobjectWrapper = b->as<QV4::QObjectWrapper>()) return qmlTypeWrapperA->toVariant().value<QObject*>() == qobjectWrapper->object(); @@ -342,4 +355,76 @@ bool QmlTypeWrapper::isEqualTo(Managed *a, Managed *b) return false; } +ReturnedValue QQmlTypeWrapper::instanceOf(const Object *typeObject, const Value &var) +{ + Q_ASSERT(typeObject->as<QV4::QQmlTypeWrapper>()); + const QV4::QQmlTypeWrapper *typeWrapper = static_cast<const QV4::QQmlTypeWrapper *>(typeObject); + QV4::ExecutionEngine *engine = typeObject->internalClass()->engine; + QQmlEnginePrivate *qenginepriv = QQmlEnginePrivate::get(engine->qmlEngine()); + + // can only compare a QObject* against a QML type + const QObjectWrapper *wrapper = var.as<QObjectWrapper>(); + if (!wrapper) + return engine->throwTypeError(); + + // in case the wrapper outlived the QObject* + const QObject *wrapperObject = wrapper->object(); + if (!wrapperObject) + return engine->throwTypeError(); + + const int myTypeId = typeWrapper->d()->type().typeId(); + QQmlMetaObject myQmlType; + if (myTypeId == 0) { + // we're a composite type; a composite type cannot be equal to a + // non-composite object instance (Rectangle{} is never an instance of + // CustomRectangle) + QQmlData *theirDData = QQmlData::get(wrapperObject, /*create=*/false); + Q_ASSERT(theirDData); // must exist, otherwise how do we have a QObjectWrapper for it?! + if (!theirDData->compilationUnit) + return Encode(false); + + QQmlTypeData *td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl()); + CompiledData::CompilationUnit *cu = td->compilationUnit(); + myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId); + } else { + myQmlType = qenginepriv->metaObjectForType(myTypeId); + } + + const QMetaObject *theirType = wrapperObject->metaObject(); + + return QV4::Encode(QQmlMetaObject::canConvert(theirType, myQmlType)); +} + +void Heap::QQmlScopedEnumWrapper::destroy() +{ + QQmlType::derefHandle(typePrivate); + typePrivate = nullptr; + Object::destroy(); +} + +QQmlType Heap::QQmlScopedEnumWrapper::type() const +{ + return QQmlType(typePrivate); +} + +ReturnedValue QQmlScopedEnumWrapper::get(const Managed *m, String *name, bool *hasProperty) +{ + Q_ASSERT(m->as<QQmlScopedEnumWrapper>()); + const QQmlScopedEnumWrapper *resource = static_cast<const QQmlScopedEnumWrapper *>(m); + QV4::ExecutionEngine *v4 = resource->engine(); + QV4::Scope scope(v4); + + QQmlType type = resource->d()->type(); + int index = resource->d()->scopeEnumIndex; + + bool ok = false; + int value = type.scopedEnumValue(QQmlEnginePrivate::get(v4->qmlEngine()), index, name, &ok); + if (hasProperty) + *hasProperty = ok; + if (ok) + return QV4::Primitive::fromInt32(value).asReturnedValue(); + + return Encode::undefined(); +} + QT_END_NAMESPACE |