blob: 304fc460bd314af127a0073ac4fead154558038f [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "private/qdeclarativevaluetypescriptclass_p.h"
#include "private/qdeclarativebinding_p.h"
#include "private/qdeclarativeproperty_p.h"
#include "private/qdeclarativeengine_p.h"
#include "private/qdeclarativeguard_p.h"
#include <QtScript/qscriptcontextinfo.h>
QT_BEGIN_NAMESPACE
struct QDeclarativeValueTypeObject : public QScriptDeclarativeClass::Object {
enum Type { Reference, Copy };
QDeclarativeValueTypeObject(Type t) : objectType(t) {}
Type objectType;
QDeclarativeValueType *type;
};
struct QDeclarativeValueTypeReference : public QDeclarativeValueTypeObject {
QDeclarativeValueTypeReference() : QDeclarativeValueTypeObject(Reference) {}
QDeclarativeGuard<QObject> object;
int property;
};
struct QDeclarativeValueTypeCopy : public QDeclarativeValueTypeObject {
QDeclarativeValueTypeCopy() : QDeclarativeValueTypeObject(Copy) {}
QVariant value;
};
QDeclarativeValueTypeScriptClass::QDeclarativeValueTypeScriptClass(QDeclarativeEngine *bindEngine)
: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine)
{
}
QDeclarativeValueTypeScriptClass::~QDeclarativeValueTypeScriptClass()
{
}
QScriptValue QDeclarativeValueTypeScriptClass::newObject(QObject *object, int coreIndex, QDeclarativeValueType *type)
{
QDeclarativeValueTypeReference *ref = new QDeclarativeValueTypeReference;
ref->type = type;
ref->object = object;
ref->property = coreIndex;
QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
return QScriptDeclarativeClass::newObject(scriptEngine, this, ref);
}
QScriptValue QDeclarativeValueTypeScriptClass::newObject(const QVariant &v, QDeclarativeValueType *type)
{
QDeclarativeValueTypeCopy *copy = new QDeclarativeValueTypeCopy;
copy->type = type;
copy->value = v;
QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
return QScriptDeclarativeClass::newObject(scriptEngine, this, copy);
}
QScriptClass::QueryFlags
QDeclarativeValueTypeScriptClass::queryProperty(Object *obj, const Identifier &name,
QScriptClass::QueryFlags)
{
QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
m_lastIndex = -1;
QByteArray propName = toString(name).toUtf8();
m_lastIndex = o->type->metaObject()->indexOfProperty(propName.constData());
if (m_lastIndex == -1)
return 0;
QScriptClass::QueryFlags rv = 0;
if (o->objectType == QDeclarativeValueTypeObject::Reference) {
QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(o);
if (!ref->object)
return 0;
QMetaProperty prop = ref->object->metaObject()->property(m_lastIndex);
rv = QScriptClass::HandlesReadAccess;
if (prop.isWritable())
rv |= QScriptClass::HandlesWriteAccess;
} else {
rv = QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess;
}
return rv;
}
QDeclarativeValueTypeScriptClass::Value QDeclarativeValueTypeScriptClass::property(Object *obj, const Identifier &)
{
QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
QVariant rv;
if (o->objectType == QDeclarativeValueTypeObject::Reference) {
QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj);
QMetaProperty p = ref->type->metaObject()->property(m_lastIndex);
ref->type->read(ref->object, ref->property);
rv = p.read(ref->type);
} else {
QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj);
QMetaProperty p = copy->type->metaObject()->property(m_lastIndex);
copy->type->setValue(copy->value);
rv = p.read(copy->type);
}
QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
return Value(scriptEngine, static_cast<QDeclarativeEnginePrivate *>(QObjectPrivate::get(engine))->scriptValueFromVariant(rv));
}
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();
}
}
QVariant QDeclarativeValueTypeScriptClass::toVariant(Object *obj, bool *ok)
{
QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
if (o->objectType == QDeclarativeValueTypeObject::Reference) {
QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj);
if (ok) *ok = true;
if (ref->object) {
ref->type->read(ref->object, ref->property);
return ref->type->value();
}
} else {
QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj);
if (ok) *ok = true;
return copy->value;
}
return QVariant();
}
QVariant QDeclarativeValueTypeScriptClass::toVariant(const QScriptValue &value)
{
Q_ASSERT(scriptClass(value) == this);
return toVariant(object(value), 0);
}
QT_END_NAMESPACE