QObject* QmlTypeWrapper::singletonObject() const { if (!isSingleton()) return 0; QQmlEngine *e = engine()->qmlEngine(); QQmlType::SingletonInstanceInfo *siinfo = d()->type->singletonInstanceInfo(); siinfo->init(e); return siinfo->qobjectApi(e); }
QVariant QmlTypeWrapper::toVariant() const { if (d()->type && d()->type->isSingleton()) { QQmlEngine *e = engine()->qmlEngine(); QQmlType::SingletonInstanceInfo *siinfo = d()->type->singletonInstanceInfo(); siinfo->init(e); // note: this will also create QJSValue singleton which isn't strictly required. QObject *qobjectSingleton = siinfo->qobjectApi(e); if (qobjectSingleton) { return QVariant::fromValue<QObject*>(qobjectSingleton); } } // only QObject Singleton Type can be converted to a variant. return QVariant(); }
// find even more QMetaObjects by instantiating QML types and running // over the instances foreach (QQmlType *ty, QQmlMetaType::qmlTypes()) { if (skip.contains(ty)) continue; if (ty->isExtendedType()) continue; if (!ty->isCreatable()) continue; if (ty->typeName() == "QQmlComponent") continue; QString tyName = ty->qmlTypeName(); tyName = tyName.mid(tyName.lastIndexOf(QLatin1Char('/')) + 1); if (tyName.isEmpty()) continue; inObjectInstantiation = tyName; QObject *object = 0; if (ty->isSingleton()) { QQmlType::SingletonInstanceInfo *siinfo = ty->singletonInstanceInfo(); if (siinfo->qobjectCallback) { siinfo->init(engine); collectReachableMetaObjects(object, &metas); object = siinfo->qobjectApi(engine); } else { inObjectInstantiation.clear(); continue; // we don't handle QJSValue singleton types. } } else { object = ty->create(); } inObjectInstantiation.clear(); if (object) collectReachableMetaObjects(object, &metas); else qWarning() << "Could not create" << tyName; }
void QmlTypeWrapper::put(Managed *m, String *name, const Value &value) { Q_ASSERT(m->as<QmlTypeWrapper>()); QmlTypeWrapper *w = static_cast<QmlTypeWrapper *>(m); QV4::ExecutionEngine *v4 = w->engine(); if (v4->hasException) return; QV4::Scope scope(v4); QQmlContextData *context = v4->v8Engine->callingContext(); QQmlType *type = w->d()->type; if (type && !type->isSingleton() && w->d()->object) { QObject *object = w->d()->object; QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object); if (ao) QV4::QObjectWrapper::setQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value); } else if (type && type->isSingleton()) { QQmlEngine *e = scope.engine->qmlEngine(); QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo(); siinfo->init(e); QObject *qobjectSingleton = siinfo->qobjectApi(e); if (qobjectSingleton) { 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; } else { apiprivate->put(name, value); } } } }
ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty) { Q_ASSERT(m->as<QmlTypeWrapper>()); QV4::ExecutionEngine *v4 = static_cast<QmlTypeWrapper *>(m)->engine(); QV4::Scope scope(v4); Scoped<QmlTypeWrapper> w(scope, static_cast<QmlTypeWrapper *>(m)); if (hasProperty) *hasProperty = true; QQmlContextData *context = v4->v8Engine->callingContext(); QObject *object = w->d()->object; if (w->d()->type) { QQmlType *type = w->d()->type; // singleton types are handled differently to other types. if (type->isSingleton()) { QQmlEngine *e = v4->qmlEngine(); QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo(); siinfo->init(e); QObject *qobjectSingleton = siinfo->qobjectApi(e); if (qobjectSingleton) { // check for enum value if (name->startsWithUpper()) { if (w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums) { // ### Optimize QByteArray enumName = name->toQString().toUtf8(); const QMetaObject *metaObject = qobjectSingleton->metaObject(); for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { QMetaEnum e = metaObject->enumerator(ii); bool ok; int value = e.keyToValue(enumName.constData(), &ok); if (ok) return QV4::Primitive::fromInt32(value).asReturnedValue(); } } } // check for property. return QV4::QObjectWrapper::getQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty); } else if (!siinfo->scriptApi(e).isUndefined()) { // NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable. QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e))); if (!!o) return o->get(name); } // Fall through to base implementation } else { if (name->startsWithUpper()) { bool ok = false; int value = type->enumValue(name, &ok); if (ok) return QV4::Primitive::fromInt32(value).asReturnedValue(); // Fall through to base implementation } else if (w->d()->object) { QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object); if (ao) return QV4::QObjectWrapper::getQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty); // Fall through to base implementation } // Fall through to base implementation } // Fall through to base implementation } else if (w->d()->typeNamespace) { Q_ASSERT(w->d()->importNamespace); QQmlTypeNameCache::Result r = w->d()->typeNamespace->query(name, w->d()->importNamespace); if (r.isValid()) { if (r.type) { return create(scope.engine, object, r.type, w->d()->mode); } else if (r.scriptIndex != -1) { QV4::ScopedObject scripts(scope, context->importedScripts.valueRef()); return scripts->getIndexed(r.scriptIndex); } else if (r.importNamespace) { return create(scope.engine, object, context->imports, r.importNamespace); } return QV4::Encode::undefined(); } // Fall through to base implementation } else { Q_ASSERT(!"Unreachable"); } if (hasProperty) *hasProperty = false; return Object::get(m, name, hasProperty); }