Initial import from the monolithic Qt.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativevaluetypescriptclass.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "private/qdeclarativevaluetypescriptclass_p.h"
43
44 #include "private/qdeclarativebinding_p.h"
45 #include "private/qdeclarativeproperty_p.h"
46 #include "private/qdeclarativeengine_p.h"
47 #include "private/qdeclarativeguard_p.h"
48
49 #include <QtScript/qscriptcontextinfo.h>
50
51 QT_BEGIN_NAMESPACE
52
53 struct QDeclarativeValueTypeObject : public QScriptDeclarativeClass::Object {
54     enum Type { Reference, Copy };
55     QDeclarativeValueTypeObject(Type t) : objectType(t) {}
56     Type objectType;
57     QDeclarativeValueType *type;
58 };
59
60 struct QDeclarativeValueTypeReference : public QDeclarativeValueTypeObject {
61     QDeclarativeValueTypeReference() : QDeclarativeValueTypeObject(Reference) {}
62     QDeclarativeGuard<QObject> object;
63     int property;
64 };
65
66 struct QDeclarativeValueTypeCopy : public QDeclarativeValueTypeObject {
67     QDeclarativeValueTypeCopy() : QDeclarativeValueTypeObject(Copy) {}
68     QVariant value;
69 };
70
71 QDeclarativeValueTypeScriptClass::QDeclarativeValueTypeScriptClass(QDeclarativeEngine *bindEngine)
72 : QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine)
73 {
74 }
75
76 QDeclarativeValueTypeScriptClass::~QDeclarativeValueTypeScriptClass()
77 {
78 }
79
80 QScriptValue QDeclarativeValueTypeScriptClass::newObject(QObject *object, int coreIndex, QDeclarativeValueType *type)
81 {
82     QDeclarativeValueTypeReference *ref = new QDeclarativeValueTypeReference;
83     ref->type = type;
84     ref->object = object;
85     ref->property = coreIndex;
86     QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
87     return QScriptDeclarativeClass::newObject(scriptEngine, this, ref);
88 }
89
90 QScriptValue QDeclarativeValueTypeScriptClass::newObject(const QVariant &v, QDeclarativeValueType *type)
91 {
92     QDeclarativeValueTypeCopy *copy = new QDeclarativeValueTypeCopy;
93     copy->type = type;
94     copy->value = v;
95     QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
96     return QScriptDeclarativeClass::newObject(scriptEngine, this, copy);
97 }
98
99 QScriptClass::QueryFlags 
100 QDeclarativeValueTypeScriptClass::queryProperty(Object *obj, const Identifier &name, 
101                                                 QScriptClass::QueryFlags)
102 {
103     QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
104
105     m_lastIndex = -1;
106
107     QByteArray propName = toString(name).toUtf8();
108
109     m_lastIndex = o->type->metaObject()->indexOfProperty(propName.constData());
110     if (m_lastIndex == -1)
111         return 0;
112
113     QScriptClass::QueryFlags rv = 0;
114
115     if (o->objectType == QDeclarativeValueTypeObject::Reference) {
116         QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(o);
117
118         if (!ref->object)
119             return 0;
120
121         QMetaProperty prop = ref->object->metaObject()->property(m_lastIndex);
122
123         rv = QScriptClass::HandlesReadAccess;
124         if (prop.isWritable())
125             rv |= QScriptClass::HandlesWriteAccess;
126     } else {
127         rv = QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess;
128     }
129
130     return rv;
131 }
132
133 QDeclarativeValueTypeScriptClass::Value QDeclarativeValueTypeScriptClass::property(Object *obj, const Identifier &)
134 {
135     QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
136
137     QVariant rv;
138     if (o->objectType == QDeclarativeValueTypeObject::Reference) {
139         QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj);
140
141         QMetaProperty p = ref->type->metaObject()->property(m_lastIndex);
142         ref->type->read(ref->object, ref->property);
143         rv = p.read(ref->type);
144     } else {
145         QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj);
146
147         QMetaProperty p = copy->type->metaObject()->property(m_lastIndex);
148         copy->type->setValue(copy->value);
149         rv = p.read(copy->type);
150     }
151
152     QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
153     return Value(scriptEngine, static_cast<QDeclarativeEnginePrivate *>(QObjectPrivate::get(engine))->scriptValueFromVariant(rv));
154 }
155
156 void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier &, 
157                                                    const QScriptValue &value)
158 {
159     QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
160
161     QVariant v = QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value);
162
163     if (o->objectType == QDeclarativeValueTypeObject::Reference) {
164         QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj);
165
166         ref->type->read(ref->object, ref->property);
167         QMetaProperty p = ref->type->metaObject()->property(m_lastIndex);
168
169         QDeclarativeBinding *newBinding = 0;
170         if (value.isFunction() && !value.isRegExp()) {
171             QDeclarativeContextData *ctxt = QDeclarativeEnginePrivate::get(engine)->getContext(context());
172
173             QDeclarativePropertyCache::Data cacheData;
174             cacheData.flags = QDeclarativePropertyCache::Data::IsWritable;
175             cacheData.propType = ref->object->metaObject()->property(ref->property).userType();
176             cacheData.coreIndex = ref->property;
177
178             QDeclarativePropertyCache::ValueTypeData valueTypeData;
179             valueTypeData.valueTypeCoreIdx = m_lastIndex;
180             valueTypeData.valueTypePropType = p.userType();
181
182             newBinding = new QDeclarativeBinding(value, ref->object, ctxt);
183             QScriptContextInfo ctxtInfo(context());
184             newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber());
185             QDeclarativeProperty prop = QDeclarativePropertyPrivate::restore(cacheData, valueTypeData, ref->object, ctxt);
186             newBinding->setTarget(prop);
187             if (newBinding->expression().contains(QLatin1String("this")))
188                 newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
189         }
190
191         QDeclarativeAbstractBinding *delBinding = 
192             QDeclarativePropertyPrivate::setBinding(ref->object, ref->property, m_lastIndex, newBinding);
193         if (delBinding) 
194             delBinding->destroy();
195
196         if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double) 
197             v = v.toInt();
198         p.write(ref->type, v);
199         ref->type->write(ref->object, ref->property, 0);
200
201     } else {
202         QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj);
203         copy->type->setValue(copy->value);
204         QMetaProperty p = copy->type->metaObject()->property(m_lastIndex);
205         p.write(copy->type, v);
206         copy->value = copy->type->value();
207     }
208 }
209
210 QVariant QDeclarativeValueTypeScriptClass::toVariant(Object *obj, bool *ok)
211 {
212     QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
213
214     if (o->objectType == QDeclarativeValueTypeObject::Reference) {
215         QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj);
216
217         if (ok) *ok = true;
218
219         if (ref->object) {
220             ref->type->read(ref->object, ref->property);
221             return ref->type->value();
222         }
223     } else {
224         QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj);
225         
226         if (ok) *ok = true;
227
228         return copy->value;
229     }
230
231     return QVariant();
232 }
233
234 QVariant QDeclarativeValueTypeScriptClass::toVariant(const QScriptValue &value)
235 {
236     Q_ASSERT(scriptClass(value) == this);
237
238     return toVariant(object(value), 0);
239 }
240
241 QT_END_NAMESPACE
242