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
}
Exemple #2
0
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*)));
            }
        }
    }
}