QScriptDeclarativeClass::Value MetaCallArgument::toValue(QDeclarativeEngine *e)
{
    QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(e);

    if (type == qMetaTypeId<QScriptValue>()) {
        return QScriptDeclarativeClass::Value(engine, *qscriptValuePtr);
    } else if (type == QMetaType::Int) {
        return QScriptDeclarativeClass::Value(engine, int(intValue));
    } else if (type == QMetaType::UInt) {
        return QScriptDeclarativeClass::Value(engine, uint(intValue));
    } else if (type == QMetaType::Bool) {
        return QScriptDeclarativeClass::Value(engine, boolValue);
    } else if (type == QMetaType::Double) {
        return QScriptDeclarativeClass::Value(engine, doubleValue);
    } else if (type == QMetaType::Float) {
        return QScriptDeclarativeClass::Value(engine, floatValue);
    } else if (type == QMetaType::QString) {
        return QScriptDeclarativeClass::Value(engine, *qstringPtr);
    } else if (type == QMetaType::QObjectStar) {
        if (qobjectPtr)
            QDeclarativeData::get(qobjectPtr, true)->setImplicitDestructible();
        QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e);
        return QScriptDeclarativeClass::Value(engine, priv->objectClass->newQObject(qobjectPtr));
    } else if (type == qMetaTypeId<QList<QObject *> >()) {
        QList<QObject *> &list = *qlistPtr;
        QScriptValue rv = engine->newArray(list.count());
        QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e);
        for (int ii = 0; ii < list.count(); ++ii) {
            QObject *object = list.at(ii);
            QDeclarativeData::get(object, true)->setImplicitDestructible();
            rv.setProperty(ii, priv->objectClass->newQObject(object));
        }
        return QScriptDeclarativeClass::Value(engine, rv);
    } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
        QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(e);
        QScriptValue rv = ep->scriptValueFromVariant(*qvariantPtr);
        if (rv.isQObject()) {
            QObject *object = rv.toQObject();
            if (object)
                QDeclarativeData::get(object, true)->setImplicitDestructible();
        }
        return QScriptDeclarativeClass::Value(engine, rv);
    } else {
        return QScriptDeclarativeClass::Value();
    }
}
int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
{
    int id = _id;
    if(c == QMetaObject::WriteProperty) {
        int flags = *reinterpret_cast<int*>(a[3]);
        if (!(flags & QDeclarativePropertyPrivate::BypassInterceptor)
            && !aInterceptors.isEmpty()
            && aInterceptors.testBit(id)) {
            QPair<int, QDeclarativePropertyValueInterceptor*> pair = interceptors.value(id);
            int valueIndex = pair.first;
            QDeclarativePropertyValueInterceptor *vi = pair.second;
            int type = property(id).userType();

            if (type != QVariant::Invalid) {
                if (valueIndex != -1) {
                    QDeclarativeEnginePrivate *ep = ctxt?QDeclarativeEnginePrivate::get(ctxt->engine):0;
                    QDeclarativeValueType *valueType = 0;
                    if (ep) valueType = ep->valueTypes[type];
                    else valueType = QDeclarativeValueTypeFactory::valueType(type);
                    Q_ASSERT(valueType);

                    valueType->setValue(QVariant(type, a[0]));
                    QMetaProperty valueProp = valueType->metaObject()->property(valueIndex);
                    vi->write(valueProp.read(valueType));

                    if (!ep) delete valueType;
                    return -1;
                } else {
                    vi->write(QVariant(type, a[0]));
                    return -1;
                }
            }
        }
    }
    if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) {
        if (id >= propOffset) {
            id -= propOffset;

            if (id < metaData->propertyCount) {
               int t = (metaData->propertyData() + id)->propertyType;
                bool needActivate = false;

                if (t == -1) {

                    if (c == QMetaObject::ReadProperty) {
                        *reinterpret_cast<QVariant *>(a[0]) = readVarPropertyAsVariant(id);
                    } else if (c == QMetaObject::WriteProperty) {
                        writeVarProperty(id, *reinterpret_cast<QVariant *>(a[0]));
                    }

                } else {

                    if (c == QMetaObject::ReadProperty) {
                        switch(t) {
                        case QVariant::Int:
                            *reinterpret_cast<int *>(a[0]) = data[id].asInt();
                            break;
                        case QVariant::Bool:
                            *reinterpret_cast<bool *>(a[0]) = data[id].asBool();
                            break;
                        case QVariant::Double:
                            *reinterpret_cast<double *>(a[0]) = data[id].asDouble();
                            break;
                        case QVariant::String:
                            *reinterpret_cast<QString *>(a[0]) = data[id].asQString();
                            break;
                        case QVariant::Url:
                            *reinterpret_cast<QUrl *>(a[0]) = data[id].asQUrl();
                            break;
                        case QVariant::Color:
                            *reinterpret_cast<QColor *>(a[0]) = data[id].asQColor();
                            break;
                        case QVariant::Date:
                            *reinterpret_cast<QDate *>(a[0]) = data[id].asQDate();
                            break;
                        case QVariant::DateTime:
                            *reinterpret_cast<QDateTime *>(a[0]) = data[id].asQDateTime();
                            break;
                        case QMetaType::QObjectStar:
                            *reinterpret_cast<QObject **>(a[0]) = data[id].asQObject();
                            break;
                        default:
                            break;
                        }
                        if (t == qMetaTypeId<QDeclarativeListProperty<QObject> >()) {
                            int listIndex = data[id].asInt();
                            const List *list = &listProperties.at(listIndex);
                            *reinterpret_cast<QDeclarativeListProperty<QObject> *>(a[0]) = 
                                QDeclarativeListProperty<QObject>(object, (void *)list,
                                                                  list_append, list_count, list_at, 
                                                                  list_clear);
                        }

                    } else if (c == QMetaObject::WriteProperty) {

                        switch(t) {
                        case QVariant::Int:
                            needActivate = *reinterpret_cast<int *>(a[0]) != data[id].asInt();
                            data[id].setValue(*reinterpret_cast<int *>(a[0]));
                            break;
                        case QVariant::Bool:
                            needActivate = *reinterpret_cast<bool *>(a[0]) != data[id].asBool();
                            data[id].setValue(*reinterpret_cast<bool *>(a[0]));
                            break;
                        case QVariant::Double:
                            needActivate = *reinterpret_cast<double *>(a[0]) != data[id].asDouble();
                            data[id].setValue(*reinterpret_cast<double *>(a[0]));
                            break;
                        case QVariant::String:
                            needActivate = *reinterpret_cast<QString *>(a[0]) != data[id].asQString();
                            data[id].setValue(*reinterpret_cast<QString *>(a[0]));
                            break;
                        case QVariant::Url:
                            needActivate = *reinterpret_cast<QUrl *>(a[0]) != data[id].asQUrl();
                            data[id].setValue(*reinterpret_cast<QUrl *>(a[0]));
                            break;
                        case QVariant::Color:
                            needActivate = *reinterpret_cast<QColor *>(a[0]) != data[id].asQColor();
                            data[id].setValue(*reinterpret_cast<QColor *>(a[0]));
                            break;
                        case QVariant::Date:
                            needActivate = *reinterpret_cast<QDate *>(a[0]) != data[id].asQDate();
                            data[id].setValue(*reinterpret_cast<QDate *>(a[0]));
                            break;
                        case QVariant::DateTime:
                            needActivate = *reinterpret_cast<QDateTime *>(a[0]) != data[id].asQDateTime();
                            data[id].setValue(*reinterpret_cast<QDateTime *>(a[0]));
                            break;
                        case QMetaType::QObjectStar:
                            needActivate = *reinterpret_cast<QObject **>(a[0]) != data[id].asQObject();
                            data[id].setValue(*reinterpret_cast<QObject **>(a[0]));
                            break;
                        default:
                            break;
                        }
                    }

                }

                if (c == QMetaObject::WriteProperty && needActivate) {
                    activate(object, methodOffset + id, 0);
                }

                return -1;
            }

            id -= metaData->propertyCount;

            if (id < metaData->aliasCount) {

                QDeclarativeVMEMetaData::AliasData *d = metaData->aliasData() + id;

                if (d->flags & QML_ALIAS_FLAG_PTR && c == QMetaObject::ReadProperty) 
                        *reinterpret_cast<void **>(a[0]) = 0;

                if (!ctxt) return -1;

                QDeclarativeContext *context = ctxt->asQDeclarativeContext();
                QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(context);

                QObject *target = ctxtPriv->data->idValues[d->contextIdx].data();
                if (!target) 
                    return -1;

                connectAlias(id);

                if (d->isObjectAlias()) {
                    *reinterpret_cast<QObject **>(a[0]) = target;
                    return -1;
                } 
                
                // Remove binding (if any) on write
                if(c == QMetaObject::WriteProperty) {
                    int flags = *reinterpret_cast<int*>(a[3]);
                    if (flags & QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite) {
                        QDeclarativeData *targetData = QDeclarativeData::get(target);
                        if (targetData && targetData->hasBindingBit(d->propertyIndex())) {
                            QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(target, d->propertyIndex(), d->isValueTypeAlias()?d->valueTypeIndex():-1, 0);
                            if (binding) binding->destroy();
                        }
                    }
                }
                
                if (d->isValueTypeAlias()) {
                    // Value type property
                    QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);

                    QDeclarativeValueType *valueType = ep->valueTypes[d->valueType()];
                    Q_ASSERT(valueType);

                    valueType->read(target, d->propertyIndex());
                    int rv = QMetaObject::metacall(valueType, c, d->valueTypeIndex(), a);
                    
                    if (c == QMetaObject::WriteProperty)
                        valueType->write(target, d->propertyIndex(), 0x00);

                    return rv;

                } else {
                    return QMetaObject::metacall(target, c, d->propertyIndex(), a);
                }

            }
            return -1;

        }

    } else if(c == QMetaObject::InvokeMetaMethod) {

        if (id >= methodOffset) {

            id -= methodOffset;
            int plainSignals = metaData->signalCount + metaData->propertyCount +
                               metaData->aliasCount;
            if (id < plainSignals) {
                QMetaObject::activate(object, _id, a);
                return -1;
            }

            id -= plainSignals;

            if (id < metaData->methodCount) {
                if (!ctxt->engine)
                    return -1; // We can't run the method

                QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);

                QScriptValue function = method(id);

                QScriptValueList args;
                QDeclarativeVMEMetaData::MethodData *data = metaData->methodData() + id;
                if (data->parameterCount) {
                    for (int ii = 0; ii < data->parameterCount; ++ii) {
                        args << ep->scriptValueFromVariant(*(QVariant *)a[ii + 1]);
                    }
                }
                QScriptValue rv = function.call(ep->objectClass->newQObject(object), args);

                if (a[0]) *reinterpret_cast<QVariant *>(a[0]) = ep->scriptValueToVariant(rv);

                return -1;
            }
            return -1;
        }
    }

    if (parent)
        return parent->metaCall(c, _id, a);
    else
        return object->qt_metacall(c, _id, a);
}
Exemple #3
0
QDeclarativeObjectScriptClass::Value
QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name)
{
    QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);

    if (name == m_destroyId.identifier)
        return Value(scriptEngine, m_destroy);
    else if (name == m_toStringId.identifier)
        return Value(scriptEngine, m_toString);

    if (lastData && !lastData->isValid())
        return Value();

    Q_ASSERT(obj);

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

    if (lastTNData) {

        if (lastTNData->type)
            return Value(scriptEngine, enginePriv->typeNameClass->newObject(obj, lastTNData->type));
        else
            return Value(scriptEngine, enginePriv->typeNameClass->newObject(obj, lastTNData->typeNamespace));

    } else if (lastData->flags & QDeclarativePropertyCache::Data::IsFunction) {
        if (lastData->flags & QDeclarativePropertyCache::Data::IsVMEFunction) {
            return Value(scriptEngine, ((QDeclarativeVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex));
        } else {
            // Uncomment to use QtScript method call logic
            // QScriptValue sobj = scriptEngine->newQObject(obj);
            // return Value(scriptEngine, sobj.property(toString(name)));
            return Value(scriptEngine, methods.newMethod(obj, lastData));
        }
    } else {
        if (enginePriv->captureProperties && !(lastData->flags & QDeclarativePropertyCache::Data::IsConstant)) {
            enginePriv->capturedProperties <<
                QDeclarativeEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex);
        }

        if (QDeclarativeValueTypeFactory::isValueType((uint)lastData->propType)) {
            QDeclarativeValueType *valueType = enginePriv->valueTypes[lastData->propType];
            if (valueType)
                return Value(scriptEngine, enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType));
        }

        if (lastData->flags & QDeclarativePropertyCache::Data::IsQList) {
            return Value(scriptEngine, enginePriv->listClass->newList(obj, lastData->coreIndex, lastData->propType));
        } else if (lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
            QObject *rv = 0;
            void *args[] = { &rv, 0 };
            QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
            return Value(scriptEngine, newQObject(rv, lastData->propType));
        } else if (lastData->flags & QDeclarativePropertyCache::Data::IsQScriptValue) {
            QScriptValue rv = scriptEngine->nullValue();
            void *args[] = { &rv, 0 };
            QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
            return Value(scriptEngine, rv);
        } else if (lastData->propType == QMetaType::QReal) {
            qreal rv = 0;
            void *args[] = { &rv, 0 };
            QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
            return Value(scriptEngine, rv);
        } else if (lastData->propType == QMetaType::Int) {
            int rv = 0;
            void *args[] = { &rv, 0 };
            QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
            return Value(scriptEngine, rv);
        } else if (lastData->propType == QMetaType::Bool) {
            bool rv = false;
            void *args[] = { &rv, 0 };
            QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
            return Value(scriptEngine, rv);
        } else if (lastData->propType == QMetaType::QString) {
            QString rv;
            void *args[] = { &rv, 0 };
            QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
            return Value(scriptEngine, rv);
        } else if (lastData->propType == QMetaType::UInt) {
            uint rv = 0;
            void *args[] = { &rv, 0 };
            QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
            return Value(scriptEngine, rv);
        } else if (lastData->propType == QMetaType::Float) {
            float rv = 0;
            void *args[] = { &rv, 0 };
            QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
            return Value(scriptEngine, rv);
        } else if (lastData->propType == QMetaType::Double) {
            double rv = 0;
            void *args[] = { &rv, 0 };
            QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
            return Value(scriptEngine, rv);
        } else {
            QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj);
            return Value(scriptEngine, enginePriv->scriptValueFromVariant(var));
        }
    }
}