Exemplo n.º 1
0
QDeclarativePropertyCache::Data *QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj, 
                                                   const QString &name, Data &local)
{
    QDeclarativePropertyCache::Data *rv = 0;

    if (!engine) {
        local = QDeclarativePropertyCache::create(obj->metaObject(), name);
        if (local.isValid())
            rv = &local;
    } else {
        QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);

        QDeclarativePropertyCache *cache = 0;
        QDeclarativeData *ddata = QDeclarativeData::get(obj);
        if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine)
            cache = ddata->propertyCache;
        if (!cache) {
            cache = enginePrivate->cache(obj);
            if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; }
        }

        if (cache) {
            rv = cache->property(name);
        } else {
            local = QDeclarativePropertyCache::create(obj->metaObject(), name);
            if (local.isValid())
                rv = &local;
        }
    }

    return rv;
}
Exemplo n.º 2
0
QStringList QDeclarativeObjectScriptClass::propertyNames(Object *object)
{
    QObject *obj = toQObject(object);
    if (!obj)
        return QStringList();

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

    QDeclarativePropertyCache *cache = 0;
    QDeclarativeData *ddata = QDeclarativeData::get(obj);
    if (ddata)
        cache = ddata->propertyCache;
    if (!cache) {
        cache = enginePrivate->cache(obj);
        if (cache) {
            if (ddata) { cache->addref(); ddata->propertyCache = cache; }
        } else {
            // Not cachable - fall back to QMetaObject (eg. dynamic meta object)
            // XXX QDeclarativeOpenMetaObject has a cache, so this is suboptimal.
            // XXX This is a workaround for QTBUG-9420.
            const QMetaObject *mo = obj->metaObject();
            QStringList r;
            int pc = mo->propertyCount();
            int po = mo->propertyOffset();
            for (int i=po; i<pc; ++i)
                r += QString::fromUtf8(mo->property(i).name());
            return r;
        }
    }
    return cache->propertyNames();
}
QDeclarativePropertyCache::Data *
QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj, 
                                    const QHashedV8String &name, Data &local)
{
    // XXX Optimize for worker script case where engine isn't available
    QDeclarativePropertyCache *cache = 0;
    if (engine) {
        QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);

        QDeclarativeData *ddata = QDeclarativeData::get(obj);
        if (ddata && ddata->propertyCache)
            cache = ddata->propertyCache;
        if (!cache) {
            cache = ep->cache(obj);
            if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; }
        }
    }

    QDeclarativePropertyCache::Data *rv = 0;

    if (cache) {
        rv = cache->property(name);
    } else {
        QString strname = QV8Engine::toStringStatic(name.string());
        // QString strname = ep->v8engine()->toString(name);
        local = QDeclarativePropertyCache::create(obj->metaObject(), strname);
        if (local.isValid())
            rv = &local;
    }

    return rv;
}
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;
    }
}
Exemplo n.º 5
0
void QDeclarativeBehavior::setTarget(const QDeclarativeProperty &property)
{
    Q_D(QDeclarativeBehavior);
    d->property = property;
    d->currentValue = property.read();
    if (d->animation)
        d->animation->setDefaultTarget(property);

    QDeclarativeEnginePrivate *engPriv = QDeclarativeEnginePrivate::get(qmlEngine(this));
    engPriv->registerFinalizedParserStatusObject(this, this->metaObject()->indexOfSlot("componentFinalized()"));
}
QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
{
    Q_Q(QDeclarativeExpression);

    if (!context() || !context()->isValid()) {
        qWarning("QDeclarativeExpression: Attempted to evaluate an expression in an invalid context");
        return QVariant();
    }

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

    return ep->scriptValueToVariant(scriptValue(secondaryScope, isUndefined), qMetaTypeId<QList<QObject*> >());
}
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();
    }
}
QDeclarativeListReference QDeclarativeListReferencePrivate::init(const QDeclarativeListProperty<QObject> &prop, int propType, QDeclarativeEngine *engine)
{
    QDeclarativeListReference rv;

    if (!prop.object) return rv;

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

    int listType = p?p->listType(propType):QDeclarativeMetaType::listType(propType);
    if (listType == -1) return rv;

    rv.d = new QDeclarativeListReferencePrivate;
    rv.d->object = prop.object;
    rv.d->elementType = p?p->rawMetaObjectForType(listType):QDeclarativeMetaType::qmlType(listType)->baseMetaObject();
    rv.d->property = prop;
    rv.d->propertyType = propType;

    return rv;
}
/*!
Constructs a QDeclarativeListReference for \a object's \a property.  If \a property is not a list
property, an invalid QDeclarativeListReference is created.  If \a object is destroyed after 
the reference is constructed, it will automatically become invalid.  That is, it is safe to hold
QDeclarativeListReference instances even after \a object is deleted.

Passing \a engine is required to access some QML created list properties.  If in doubt, and an engine
is available, pass it.
*/
QDeclarativeListReference::QDeclarativeListReference(QObject *object, const char *property, QDeclarativeEngine *engine)
: d(0)
{
    if (!object || !property) return;

    QDeclarativePropertyCache::Data local;
    QDeclarativePropertyCache::Data *data = 
        QDeclarativePropertyCache::property(engine, object, QLatin1String(property), local);

    if (!data || !(data->flags & QDeclarativePropertyCache::Data::IsQList)) return;

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

    int listType = p?p->listType(data->propType):QDeclarativeMetaType::listType(data->propType);
    if (listType == -1) return;

    d = new QDeclarativeListReferencePrivate;
    d->object = object;
    d->elementType = p?p->rawMetaObjectForType(listType):QDeclarativeMetaType::qmlType(listType)->baseMetaObject();
    d->propertyType = data->propType;

    void *args[] = { &d->property, 0 };
    QMetaObject::metacall(object, QMetaObject::ReadProperty, data->coreIndex, args);
}
Exemplo n.º 10
0
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);
}
Exemplo n.º 11
0
void QDeclarativeObjectScriptClass::setProperty(QObject *obj,
                                                const Identifier &name,
                                                const QScriptValue &value,
                                                QScriptContext *context,
                                                QDeclarativeContextData *evalContext)
{
    Q_UNUSED(name);

    Q_ASSERT(obj);
    Q_ASSERT(lastData);
    Q_ASSERT(context);

    if (!lastData->isValid()) {
        QString error = QLatin1String("Cannot assign to non-existent property \"") +
                        toString(name) + QLatin1Char('\"');
        context->throwError(error);
        return;
    }

    if (!(lastData->flags & QDeclarativePropertyCache::Data::IsWritable) && 
        !(lastData->flags & QDeclarativePropertyCache::Data::IsQList)) {
        QString error = QLatin1String("Cannot assign to read-only property \"") +
                        toString(name) + QLatin1Char('\"');
        context->throwError(error);
        return;
    }

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

    if (!evalContext) {
        // Global object, QScriptContext activation object, QDeclarativeContext object
        QScriptValue scopeNode = scopeChainValue(context, -3);
        if (scopeNode.isValid()) {
            Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass);

            evalContext = enginePriv->contextClass->contextFromValue(scopeNode);
        }
    }

    QDeclarativeAbstractBinding *delBinding =
        QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, 0);
    if (delBinding)
        delBinding->destroy();

    if (value.isNull() && lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
        QObject *o = 0;
        int status = -1;
        int flags = 0;
        void *argv[] = { &o, 0, &status, &flags };
        QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, argv);
    } else if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) {
        void *a[] = { 0 };
        QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a);
    } else if (value.isUndefined() && lastData->propType == qMetaTypeId<QVariant>()) {
        QDeclarativePropertyPrivate::write(obj, *lastData, QVariant(), evalContext);
    } else if (value.isUndefined()) {
        QString error = QLatin1String("Cannot assign [undefined] to ") +
                        QLatin1String(QMetaType::typeName(lastData->propType));
        context->throwError(error);
    } else {
        QVariant v;
        if (lastData->flags & QDeclarativePropertyCache::Data::IsQList)
            v = enginePriv->scriptValueToVariant(value, qMetaTypeId<QList<QObject *> >());
        else
            v = enginePriv->scriptValueToVariant(value, lastData->propType);

        if (!QDeclarativePropertyPrivate::write(obj, *lastData, v, evalContext)) {
            const char *valueType = 0;
            if (v.userType() == QVariant::Invalid) valueType = "null";
            else valueType = QMetaType::typeName(v.userType());

            QString error = QLatin1String("Cannot assign ") +
                            QLatin1String(valueType) +
                            QLatin1String(" to ") +
                            QLatin1String(QMetaType::typeName(lastData->propType));
            context->throwError(error);
        }
    }
}
Exemplo n.º 12
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));
        }
    }
}
Exemplo n.º 13
0
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);
        }
    }
}
Exemplo n.º 14
0
void QDeclarativeObjectScriptClass::setProperty(QObject *obj,
                                                const Identifier &name,
                                                const QScriptValue &value,
                                                QScriptContext *context,
                                                QDeclarativeContextData *evalContext)
{
    Q_UNUSED(name);

    Q_ASSERT(obj);
    Q_ASSERT(lastData);
    Q_ASSERT(context);

    if (!lastData->isValid()) {
        QString error = QLatin1String("Cannot assign to non-existent property \"") +
                        toString(name) + QLatin1Char('\"');
        context->throwError(error);
        return;
    }

    if (!(lastData->flags & QDeclarativePropertyCache::Data::IsWritable) && 
        !(lastData->flags & QDeclarativePropertyCache::Data::IsQList)) {
        QString error = QLatin1String("Cannot assign to read-only property \"") +
                        toString(name) + QLatin1Char('\"');
        context->throwError(error);
        return;
    }

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

    if (!evalContext) {
        // Global object, QScriptContext activation object, QDeclarativeContext object
        QScriptValue scopeNode = scopeChainValue(context, -3);
        if (scopeNode.isValid()) {
            Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass);

            evalContext = enginePriv->contextClass->contextFromValue(scopeNode);
        }
    }

    QDeclarativeBinding *newBinding = 0;
    if (value.isFunction() && !value.isRegExp()) {
        QScriptContextInfo ctxtInfo(context);
        QDeclarativePropertyCache::ValueTypeData valueTypeData;

        newBinding = new QDeclarativeBinding(value, obj, evalContext);
        newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber());
        newBinding->setTarget(QDeclarativePropertyPrivate::restore(*lastData, valueTypeData, obj, evalContext));
        if (newBinding->expression().contains(QLatin1String("this")))
            newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
    }

    QDeclarativeAbstractBinding *delBinding =
        QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, newBinding);
    if (delBinding)
        delBinding->destroy();

    if (value.isNull() && lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
        QObject *o = 0;
        int status = -1;
        int flags = 0;
        void *argv[] = { &o, 0, &status, &flags };
        QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, argv);
    } else if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) {
        void *a[] = { 0 };
        QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a);
    } else if (value.isUndefined() && lastData->propType == qMetaTypeId<QVariant>()) {
        QDeclarativePropertyPrivate::write(obj, *lastData, QVariant(), evalContext);
    } else if (value.isUndefined()) {
        QString error = QLatin1String("Cannot assign [undefined] to ") +
                        QLatin1String(QMetaType::typeName(lastData->propType));
        context->throwError(error);
    } else if (value.isFunction() && !value.isRegExp()) {
        // this is handled by the binding creation above
    } else {
        //### expand optimization for other known types
        if (lastData->propType == QMetaType::Int && value.isNumber()) {
            int rawValue = qRoundDouble(value.toNumber());
            int status = -1;
            int flags = 0;
            void *a[] = { (void *)&rawValue, 0, &status, &flags };
            QMetaObject::metacall(obj, QMetaObject::WriteProperty,
                                  lastData->coreIndex, a);
            return;
        } else if (lastData->propType == QMetaType::QReal && value.isNumber()) {
            qreal rawValue = qreal(value.toNumber());
            int status = -1;
            int flags = 0;
            void *a[] = { (void *)&rawValue, 0, &status, &flags };
            QMetaObject::metacall(obj, QMetaObject::WriteProperty,
                                  lastData->coreIndex, a);
            return;
        } else if (lastData->propType == QMetaType::QString && value.isString()) {
            const QString &rawValue = value.toString();
            int status = -1;
            int flags = 0;
            void *a[] = { (void *)&rawValue, 0, &status, &flags };
            QMetaObject::metacall(obj, QMetaObject::WriteProperty,
                                  lastData->coreIndex, a);
            return;
        }

        QVariant v;
        if (lastData->flags & QDeclarativePropertyCache::Data::IsQList)
            v = enginePriv->scriptValueToVariant(value, qMetaTypeId<QList<QObject *> >());
        else
            v = enginePriv->scriptValueToVariant(value, lastData->propType);

        if (!QDeclarativePropertyPrivate::write(obj, *lastData, v, evalContext)) {
            const char *valueType = 0;
            if (v.userType() == QVariant::Invalid) valueType = "null";
            else valueType = QMetaType::typeName(v.userType());

            QString error = QLatin1String("Cannot assign ") +
                            QLatin1String(valueType) +
                            QLatin1String(" to ") +
                            QLatin1String(QMetaType::typeName(lastData->propType));
            context->throwError(error);
        }
    }
}
Exemplo n.º 15
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;
}
Exemplo n.º 16
0
void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
{
    Q_D(QDeclarativeBinding);

    if (!d->enabled || !d->context() || !d->context()->isValid()) 
        return;

    if (!d->updating) {
        d->updating = true;
        bool wasDeleted = false;
        d->deleted = &wasDeleted;

        if (d->property.propertyType() == qMetaTypeId<QDeclarativeBinding *>()) {

            int idx = d->property.index();
            Q_ASSERT(idx != -1);

            QDeclarativeBinding *t = this;
            int status = -1;
            void *a[] = { &t, 0, &status, &flags };
            QMetaObject::metacall(d->property.object(),
                                  QMetaObject::WriteProperty,
                                  idx, a);

            if (wasDeleted)
                return;

        } else {
            QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(d->context()->engine);

            bool isUndefined = false;
            QVariant value;

            QScriptValue scriptValue = d->scriptValue(0, &isUndefined);
            if (wasDeleted)
                return;

            if (d->property.propertyTypeCategory() == QDeclarativeProperty::List) {
                value = ep->scriptValueToVariant(scriptValue, qMetaTypeId<QList<QObject *> >());
            } else if (scriptValue.isNull() && 
                       d->property.propertyTypeCategory() == QDeclarativeProperty::Object) {
                value = QVariant::fromValue((QObject *)0);
            } else {
                value = ep->scriptValueToVariant(scriptValue, d->property.propertyType());
                if (value.userType() == QMetaType::QObjectStar && !qvariant_cast<QObject*>(value)) {
                    // If the object is null, we extract the predicted type.  While this isn't
                    // 100% reliable, in many cases it gives us better error messages if we
                    // assign this null-object to an incompatible property
                    int type = ep->objectClass->objectType(scriptValue);
                    QObject *o = 0;
                    value = QVariant(type, (void *)&o);
                }
            }


            if (d->error.isValid()) {

            } else if (isUndefined && d->property.isResettable()) {

                d->property.reset();

            } else if (isUndefined && d->property.propertyType() == qMetaTypeId<QVariant>()) {

                QDeclarativePropertyPrivate::write(d->property, QVariant(), flags);

            } else if (isUndefined) {

                QUrl url = QUrl(d->url);
                int line = d->line;
                if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));

                d->error.setUrl(url);
                d->error.setLine(line);
                d->error.setColumn(-1);
                d->error.setDescription(QLatin1String("Unable to assign [undefined] to ") +
                                        QLatin1String(QMetaType::typeName(d->property.propertyType())) +
                                        QLatin1String(" ") + d->property.name());

            } else if (!scriptValue.isRegExp() && scriptValue.isFunction()) {

                QUrl url = QUrl(d->url);
                int line = d->line;
                if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));

                d->error.setUrl(url);
                d->error.setLine(line);
                d->error.setColumn(-1);
                d->error.setDescription(QLatin1String("Unable to assign a function to a property."));

            } else if (d->property.object() &&
                       !QDeclarativePropertyPrivate::write(d->property, value, flags)) {

                if (wasDeleted)
                    return;

                QUrl url = QUrl(d->url);
                int line = d->line;
                if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));

                const char *valueType = 0;
                if (value.userType() == QVariant::Invalid) valueType = "null";
                else valueType = QMetaType::typeName(value.userType());

                d->error.setUrl(url);
                d->error.setLine(line);
                d->error.setColumn(-1);
                d->error.setDescription(QLatin1String("Unable to assign ") +
                                        QLatin1String(valueType) +
                                        QLatin1String(" to ") +
                                        QLatin1String(QMetaType::typeName(d->property.propertyType())));
            }

            if (wasDeleted)
                return;

            if (d->error.isValid()) {
               if (!d->addError(ep)) ep->warning(this->error());
            } else {
                d->removeError();
            }
        }

        d->updating = false;
        d->deleted = 0;
    } else {
        qmlInfo(d->property.object()) << tr("Binding loop detected for property \"%1\"").arg(d->property.name());
    }
}
Exemplo n.º 17
0
void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object::ScriptBlock &script)
{
    if (!engine)
        return;

    QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
    QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);

    const QString &code = script.code;
    const QString &url = script.file;
    const QDeclarativeParser::Object::ScriptBlock::Pragmas &pragmas = script.pragmas;

    Q_ASSERT(!url.isEmpty());

    if (pragmas & QDeclarativeParser::Object::ScriptBlock::Shared) {

        QHash<QString, QScriptValue>::Iterator iter = enginePriv->m_sharedScriptImports.find(url);
        if (iter == enginePriv->m_sharedScriptImports.end()) {
            QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);

            scriptContext->pushScope(enginePriv->contextClass->newUrlContext(url));
            scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject());

            QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine);
            scriptContext->pushScope(scope);

            scriptEngine->evaluate(code, url, 1);

            if (scriptEngine->hasUncaughtException()) {
                QDeclarativeError error;
                QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
                enginePriv->warning(error);
            }

            scriptEngine->popContext();

            iter = enginePriv->m_sharedScriptImports.insert(url, scope);
        }

        importedScripts.append(*iter);

    } else {

        QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);

        scriptContext->pushScope(enginePriv->contextClass->newUrlContext(this, 0, url));
        scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject());

        QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine);
        scriptContext->pushScope(scope);

        scriptEngine->evaluate(code, url, 1);

        if (scriptEngine->hasUncaughtException()) {
            QDeclarativeError error;
            QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
            enginePriv->warning(error);
        }

        scriptEngine->popContext();

        importedScripts.append(scope);

    }
}