ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *hasProperty) { Q_ASSERT(m->as<QQmlValueTypeWrapper>()); const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m); QV4::ExecutionEngine *v4 = r->engine(); // Note: readReferenceValue() can change the reference->type. if (const QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) { if (!reference->readReferenceValue()) return Primitive::undefinedValue().asReturnedValue(); } QQmlPropertyData *result = r->d()->propertyCache->property(name, 0, 0); if (!result) return Object::get(m, name, hasProperty); if (hasProperty) *hasProperty = true; if (result->isFunction()) // calling a Q_INVOKABLE function of a value type return QV4::QObjectMethod::create(v4->rootContext(), r, result->coreIndex); #define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \ if (result->propType == metatype) { \ cpptype v; \ void *args[] = { &v, 0 }; \ metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args); \ return QV4::Encode(constructor(v)); \ } const QMetaObject *metaObject = r->d()->propertyCache->metaObject(); int index = result->coreIndex; QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::ReadProperty, &metaObject, &index); void *gadget = r->d()->gadgetPtr; // These four types are the most common used by the value type wrappers VALUE_TYPE_LOAD(QMetaType::QReal, qreal, qreal); VALUE_TYPE_LOAD(QMetaType::Int, int, int); VALUE_TYPE_LOAD(QMetaType::QString, QString, v4->newString); VALUE_TYPE_LOAD(QMetaType::Bool, bool, bool); QVariant v; void *args[] = { Q_NULLPTR, Q_NULLPTR }; if (result->propType == QMetaType::QVariant) { args[0] = &v; } else { v = QVariant(result->propType, static_cast<void *>(Q_NULLPTR)); args[0] = v.data(); } metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args); return v4->fromVariant(v); #undef VALUE_TYPE_ACCESSOR }
void QQuickOpenGLShaderEffectCommon::connectPropertySignals(QQuickItem *item, const QMetaObject *itemMetaObject, Key::ShaderType shaderType) { QQmlPropertyCache *propCache = QQmlData::ensurePropertyCache(qmlEngine(item), item); for (int i = 0; i < uniformData[shaderType].size(); ++i) { if (signalMappers[shaderType].at(i) == 0) continue; const UniformData &d = uniformData[shaderType].at(i); QQmlPropertyData *pd = propCache->property(QString::fromUtf8(d.name), nullptr, nullptr); if (pd && !pd->isFunction()) { if (pd->notifyIndex() == -1) { qWarning("QQuickOpenGLShaderEffect: property '%s' does not have notification method!", d.name.constData()); } else { auto *mapper = signalMappers[shaderType].at(i); mapper->setSignalIndex(itemMetaObject->property(d.propertyIndex).notifySignal().methodIndex()); Q_ASSERT(item->metaObject() == itemMetaObject); bool ok = QObjectPrivate::connectImpl(item, pd->notifyIndex(), item, nullptr, mapper, Qt::AutoConnection, nullptr, itemMetaObject); if (!ok) qWarning() << "Failed to connect to property" << itemMetaObject->property(d.propertyIndex).name() << "(" << d.propertyIndex << ", signal index" << pd->notifyIndex() << ") of item" << item; } } else { // If the source is set via a dynamic property, like the layer is, then we need this // check to disable the warning. if (!item->property(d.name).isValid()) qWarning("QQuickOpenGLShaderEffect: '%s' does not have a matching property!", d.name.constData()); } if (d.specialType == UniformData::Sampler || d.specialType == UniformData::SamplerExternal) { QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(d.value)); if (source) { if (item->window()) QQuickItemPrivate::get(source)->refWindow(item->window()); QObject::connect(source, SIGNAL(destroyed(QObject*)), host, SLOT(sourceDestroyed(QObject*))); } } } }