void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier &, const QScriptValue &value) { QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj); QVariant v = QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value); if (o->objectType == QDeclarativeValueTypeObject::Reference) { QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj); ref->type->read(ref->object, ref->property); QMetaProperty p = ref->type->metaObject()->property(m_lastIndex); QDeclarativeBinding *newBinding = 0; if (value.isFunction() && !value.isRegExp()) { QDeclarativeContextData *ctxt = QDeclarativeEnginePrivate::get(engine)->getContext(context()); QDeclarativePropertyCache::Data cacheData; cacheData.flags = QDeclarativePropertyCache::Data::IsWritable; cacheData.propType = ref->object->metaObject()->property(ref->property).userType(); cacheData.coreIndex = ref->property; QDeclarativePropertyCache::ValueTypeData valueTypeData; valueTypeData.valueTypeCoreIdx = m_lastIndex; valueTypeData.valueTypePropType = p.userType(); newBinding = new QDeclarativeBinding(value, ref->object, ctxt); QScriptContextInfo ctxtInfo(context()); newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber()); QDeclarativeProperty prop = QDeclarativePropertyPrivate::restore(cacheData, valueTypeData, ref->object, ctxt); newBinding->setTarget(prop); if (newBinding->expression().contains(QLatin1String("this"))) newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject); } QDeclarativeAbstractBinding *delBinding = QDeclarativePropertyPrivate::setBinding(ref->object, ref->property, m_lastIndex, newBinding); if (delBinding) delBinding->destroy(); if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double) v = v.toInt(); p.write(ref->type, v); ref->type->write(ref->object, ref->property, 0); } else { QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj); copy->type->setValue(copy->value); QMetaProperty p = copy->type->metaObject()->property(m_lastIndex); p.write(copy->type, v); copy->value = copy->type->value(); } }
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); } } }