void QDeclarativeListAccessor::setList(const QVariant &v, QDeclarativeEngine *engine)
{
    d = v;

    QDeclarativeEnginePrivate *enginePrivate = engine?QDeclarativeEnginePrivate::get(engine):0;

    if (!d.isValid()) {
        m_type = Invalid;
    } else if (d.userType() == QVariant::StringList) {
        m_type = StringList;
    } else if (d.userType() == QMetaType::QVariantList) {
        m_type = VariantList;
    } else if (d.canConvert(QVariant::Int)) {
        m_type = Integer;
    } else if ((!enginePrivate && QDeclarativeMetaType::isQObject(d.userType())) ||
               (enginePrivate && enginePrivate->isQObject(d.userType()))) {
        QObject *data = enginePrivate?enginePrivate->toQObject(v):QDeclarativeMetaType::toQObject(v);
        d = QVariant::fromValue(data);
        m_type = Instance;
    } else if (d.userType() == qMetaTypeId<QDeclarativeListReference>()) {
        m_type = ListProperty;
    } else {
        m_type = Instance;
    }
}
Exemple #2
0
bool QDeclarativePropertyPrivate::write(QObject *object, const QDeclarativePropertyCache::Data &property, 
                                            const QVariant &value, QDeclarativeContextData *context, 
                                            WriteFlags flags)
{
    int coreIdx = property.coreIndex;
    int status = -1;    //for dbus

    if (property.flags & QDeclarativePropertyCache::Data::IsEnumType) {
        QMetaProperty prop = object->metaObject()->property(property.coreIndex);
        QVariant v = value;
        // Enum values come through the script engine as doubles
        if (value.userType() == QVariant::Double) { 
            double integral;
            double fractional = modf(value.toDouble(), &integral);
            if (qFuzzyIsNull(fractional))
                v.convert(QVariant::Int);
        }
        return writeEnumProperty(prop, coreIdx, object, v, flags);
    }

    int propertyType = property.propType;
    int variantType = value.userType();

    QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(context);

    if (propertyType == QVariant::Url) {

        QUrl u;
        bool found = false;
        if (variantType == QVariant::Url) {
            u = value.toUrl();
            found = true;
        } else if (variantType == QVariant::ByteArray) {
            u = QUrl(QString::fromUtf8(value.toByteArray()));
            found = true;
        } else if (variantType == QVariant::String) {
            u = QUrl(value.toString());
            found = true;
        }

        if (!found)
            return false;

        if (context && u.isRelative() && !u.isEmpty())
            u = context->resolvedUrl(u);
        int status = -1;
        void *argv[] = { &u, 0, &status, &flags };
        QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv);

    } else if (variantType == propertyType) {

        void *a[] = { (void *)value.constData(), 0, &status, &flags };
        QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);

    } else if (qMetaTypeId<QVariant>() == propertyType) {

        void *a[] = { (void *)&value, 0, &status, &flags };
        QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);

    } else if (property.flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {

        const QMetaObject *valMo = rawMetaObjectForType(enginePriv, value.userType());
        
        if (!valMo)
            return false;

        QObject *o = *(QObject **)value.constData();
        const QMetaObject *propMo = rawMetaObjectForType(enginePriv, propertyType);

        if (o) valMo = o->metaObject();

        if (canConvert(valMo, propMo)) {
            void *args[] = { &o, 0, &status, &flags };
            QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, 
                                  args);
        } else if (!o && canConvert(propMo, valMo)) {
            // In the case of a null QObject, we assign the null if there is 
            // any change that the null variant type could be up or down cast to 
            // the property type.
            void *args[] = { &o, 0, &status, &flags };
            QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, 
                                  args);
        } else {
            return false;
        }

    } else if (property.flags & QDeclarativePropertyCache::Data::IsQList) {

        const QMetaObject *listType = 0;
        if (enginePriv) {
            listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType));
        } else {
            QDeclarativeType *type = QDeclarativeMetaType::qmlType(QDeclarativeMetaType::listType(property.propType));
            if (!type) return false;
            listType = type->baseMetaObject();
        }
        if (!listType) return false;

        QDeclarativeListProperty<void> prop;
        void *args[] = { &prop, 0 };
        QMetaObject::metacall(object, QMetaObject::ReadProperty, coreIdx, args);

        if (!prop.clear) return false;

        prop.clear(&prop);

        if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
            const QList<QObject *> &list = qvariant_cast<QList<QObject *> >(value);

            for (int ii = 0; ii < list.count(); ++ii) {
                QObject *o = list.at(ii);
                if (o && !canConvert(o->metaObject(), listType))
                    o = 0;
                prop.append(&prop, (void *)o);
            }
        } else {
            QObject *o = enginePriv?enginePriv->toQObject(value):QDeclarativeMetaType::toQObject(value);
            if (o && !canConvert(o->metaObject(), listType))
                o = 0;
            prop.append(&prop, (void *)o);
        }

    } else {
        Q_ASSERT(variantType != propertyType);

        QVariant v = value;
        if (v.convert((QVariant::Type)propertyType)) {
            void *a[] = { (void *)v.constData(), 0, &status, &flags};
            QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
        } else if ((uint)propertyType >= QVariant::UserType && variantType == QVariant::String) {
            QDeclarativeMetaType::StringConverter con = QDeclarativeMetaType::customStringConverter(propertyType);
            if (!con)
                return false;

            QVariant v = con(value.toString());
            if (v.userType() == propertyType) {
                void *a[] = { (void *)v.constData(), 0, &status, &flags};
                QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
            }
        } else if (variantType == QVariant::String) {
            bool ok = false;
            QVariant v = QDeclarativeStringConverters::variantFromString(value.toString(), propertyType, &ok);
            if (!ok)
                return false;

            void *a[] = { (void *)v.constData(), 0, &status, &flags};
            QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
        } else {
            return false;
        }
    }

    return true;
}
void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, const QScriptValue &value)
{
    if (type != 0) { cleanup(); type = 0; }

    if (callType == qMetaTypeId<QScriptValue>()) {
        qscriptValuePtr = new (&allocData) QScriptValue(value);
        type = qMetaTypeId<QScriptValue>();
    } else if (callType == QMetaType::Int) {
        intValue = quint32(value.toInt32());
        type = callType;
    } else if (callType == QMetaType::UInt) {
        intValue = quint32(value.toUInt32());
        type = callType;
    } else if (callType == QMetaType::Bool) {
        boolValue = value.toBool();
        type = callType;
    } else if (callType == QMetaType::Double) {
        doubleValue = double(value.toNumber());
        type = callType;
    } else if (callType == QMetaType::Float) {
        floatValue = float(value.toNumber());
        type = callType;
    } else if (callType == QMetaType::QString) {
        if (value.isNull() || value.isUndefined())
            qstringPtr = new (&allocData) QString();
        else
            qstringPtr = new (&allocData) QString(value.toString());
        type = callType;
    } else if (callType == QMetaType::QObjectStar) {
        qobjectPtr = value.toQObject();
        type = callType;
    } else if (callType == qMetaTypeId<QVariant>()) {
        QVariant other = QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value);
        qvariantPtr = new (&allocData) QVariant(other);
        type = callType;
    } else if (callType == qMetaTypeId<QList<QObject*> >()) {
        qlistPtr = new (&allocData) QList<QObject *>(); 
        if (value.isArray()) {
            int length = value.property(QLatin1String("length")).toInt32();
            for (int ii = 0; ii < length; ++ii) {
                QScriptValue arrayItem = value.property(ii);
                QObject *d = arrayItem.toQObject();
                qlistPtr->append(d);
            }
        } else if (QObject *d = value.toQObject()) {
            qlistPtr->append(d);
        }
        type = callType;
    } else {
        qvariantPtr = new (&allocData) QVariant();
        type = -1;

        QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine);
        QVariant v = priv->scriptValueToVariant(value);
        if (v.userType() == callType) {
            *qvariantPtr = v;
        } else if (v.canConvert((QVariant::Type)callType)) {
            *qvariantPtr = v;
            qvariantPtr->convert((QVariant::Type)callType);
        } else if (const QMetaObject *mo = priv->rawMetaObjectForType(callType)) {
            QObject *obj = priv->toQObject(v);
            
            if (obj) {
                const QMetaObject *objMo = obj->metaObject();
                while (objMo && objMo != mo) objMo = objMo->superClass();
                if (!objMo) obj = 0;
            }

            *qvariantPtr = QVariant(callType, &obj);
        } else {
            *qvariantPtr = QVariant(callType, (void *)0);
        }
    }
}