Doc: Enabling Qt QML linking to Qt Quick.
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlvaluetype.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qqmlvaluetype_p.h"
43 #include "qqmlmetatype_p.h"
44
45 #include <private/qqmlglobal_p.h>
46 #include <QtCore/qdebug.h>
47
48 QT_BEGIN_NAMESPACE
49
50 namespace {
51
52 struct QQmlValueTypeFactoryImpl
53 {
54     QQmlValueTypeFactoryImpl();
55     ~QQmlValueTypeFactoryImpl();
56
57     bool isValueType(int idx);
58
59     QQmlValueType *createValueType(int);
60     QQmlValueType *valueType(int);
61
62     QQmlValueType *valueTypes[QVariant::UserType];
63     QHash<int, QQmlValueType *> userTypes;
64     QMutex mutex;
65 };
66
67 QQmlValueTypeFactoryImpl::QQmlValueTypeFactoryImpl()
68 {
69     for (unsigned int ii = 0; ii < QVariant::UserType; ++ii)
70         valueTypes[ii] = 0;
71 }
72
73 QQmlValueTypeFactoryImpl::~QQmlValueTypeFactoryImpl()
74 {
75     qDeleteAll(valueTypes, valueTypes + QVariant::UserType);
76     qDeleteAll(userTypes);
77 }
78
79 bool QQmlValueTypeFactoryImpl::isValueType(int idx)
80 {
81     if (idx >= (int)QVariant::UserType) {
82         return (valueType(idx) != 0);
83     } else if (idx >= 0
84             && idx != QVariant::StringList
85             && idx != QMetaType::QObjectStar
86             && idx != QMetaType::VoidStar
87             && idx != QMetaType::QVariant) {
88         return true;
89     }
90
91     return false;
92 }
93
94 QQmlValueType *QQmlValueTypeFactoryImpl::createValueType(int t)
95 {
96     QQmlValueType *rv = 0;
97
98     switch (t) {
99     case QVariant::Point:
100         rv = new QQmlPointValueType;
101         break;
102     case QVariant::PointF:
103         rv = new QQmlPointFValueType;
104         break;
105     case QVariant::Size:
106         rv = new QQmlSizeValueType;
107         break;
108     case QVariant::SizeF:
109         rv = new QQmlSizeFValueType;
110         break;
111     case QVariant::Rect:
112         rv = new QQmlRectValueType;
113         break;
114     case QVariant::RectF:
115         rv = new QQmlRectFValueType;
116         break;
117     case QVariant::EasingCurve:
118         rv = new QQmlEasingValueType;
119         break;
120     default:
121         rv = QQml_valueTypeProvider()->createValueType(t);
122         break;
123     }
124
125     Q_ASSERT(!rv || rv->metaObject()->propertyCount() < 32);
126     return rv;
127 }
128
129 QQmlValueType *QQmlValueTypeFactoryImpl::valueType(int idx)
130 {
131     if (idx >= (int)QVariant::UserType) {
132         // Protect the hash with a mutex
133         mutex.lock();
134
135         QHash<int, QQmlValueType *>::iterator it = userTypes.find(idx);
136         if (it == userTypes.end()) {
137             it = userTypes.insert(idx, createValueType(idx));
138         }
139
140         mutex.unlock();
141         return *it;
142     }
143
144     QQmlValueType *rv = valueTypes[idx];
145     if (!rv) {
146         // No need for mutex protection - the most we can lose is a valueType instance
147
148         // TODO: Investigate the performance/memory characteristics of
149         // removing the preallocated array
150         if ((rv = createValueType(idx))) {
151             valueTypes[idx] = rv;
152         }
153     }
154
155     return rv;
156 }
157
158 }
159
160 Q_GLOBAL_STATIC(QQmlValueTypeFactoryImpl, factoryImpl);
161
162 bool QQmlValueTypeFactory::isValueType(int idx)
163 {
164     return factoryImpl()->isValueType(idx);
165 }
166
167 QQmlValueType *QQmlValueTypeFactory::valueType(int idx)
168 {
169     return factoryImpl()->valueType(idx);
170 }
171
172 void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor, int versionMinor)
173 {
174     qmlRegisterValueTypeEnums<QQmlEasingValueType>(uri, versionMajor, versionMinor, "Easing");
175 }
176
177
178 QQmlValueType::QQmlValueType(int userType, QObject *parent)
179 : QObject(parent), m_userType(userType)
180 {
181 }
182
183 QQmlPointFValueType::QQmlPointFValueType(QObject *parent)
184     : QQmlValueTypeBase<QPointF>(QMetaType::QPointF, parent)
185 {
186 }
187
188 QString QQmlPointFValueType::toString() const
189 {
190     return QString(QLatin1String("QPointF(%1, %2)")).arg(v.x()).arg(v.y());
191 }
192
193 qreal QQmlPointFValueType::x() const
194 {
195     return v.x();
196 }
197
198 qreal QQmlPointFValueType::y() const
199 {
200     return v.y();
201 }
202
203 void QQmlPointFValueType::setX(qreal x)
204 {
205     v.setX(x);
206 }
207
208 void QQmlPointFValueType::setY(qreal y)
209 {
210     v.setY(y);
211 }
212
213
214 QQmlPointValueType::QQmlPointValueType(QObject *parent)
215     : QQmlValueTypeBase<QPoint>(QMetaType::QPoint, parent)
216 {
217 }
218
219 QString QQmlPointValueType::toString() const
220 {
221     return QString(QLatin1String("QPoint(%1, %2)")).arg(v.x()).arg(v.y());
222 }
223
224 int QQmlPointValueType::x() const
225 {
226     return v.x();
227 }
228
229 int QQmlPointValueType::y() const
230 {
231     return v.y();
232 }
233
234 void QQmlPointValueType::setX(int x)
235 {
236     v.setX(x);
237 }
238
239 void QQmlPointValueType::setY(int y)
240 {
241     v.setY(y);
242 }
243
244
245 QQmlSizeFValueType::QQmlSizeFValueType(QObject *parent)
246     : QQmlValueTypeBase<QSizeF>(QMetaType::QSizeF, parent)
247 {
248 }
249
250 QString QQmlSizeFValueType::toString() const
251 {
252     return QString(QLatin1String("QSizeF(%1, %2)")).arg(v.width()).arg(v.height());
253 }
254
255 qreal QQmlSizeFValueType::width() const
256 {
257     return v.width();
258 }
259
260 qreal QQmlSizeFValueType::height() const
261 {
262     return v.height();
263 }
264
265 void QQmlSizeFValueType::setWidth(qreal w)
266 {
267     v.setWidth(w);
268 }
269
270 void QQmlSizeFValueType::setHeight(qreal h)
271 {
272     v.setHeight(h);
273 }
274
275
276 QQmlSizeValueType::QQmlSizeValueType(QObject *parent)
277     : QQmlValueTypeBase<QSize>(QMetaType::QSize, parent)
278 {
279 }
280
281 QString QQmlSizeValueType::toString() const
282 {
283     return QString(QLatin1String("QSize(%1, %2)")).arg(v.width()).arg(v.height());
284 }
285
286 int QQmlSizeValueType::width() const
287 {
288     return v.width();
289 }
290
291 int QQmlSizeValueType::height() const
292 {
293     return v.height();
294 }
295
296 void QQmlSizeValueType::setWidth(int w)
297 {
298     v.setWidth(w);
299 }
300
301 void QQmlSizeValueType::setHeight(int h)
302 {
303     v.setHeight(h);
304 }
305
306
307 QQmlRectFValueType::QQmlRectFValueType(QObject *parent)
308     : QQmlValueTypeBase<QRectF>(QMetaType::QRectF, parent)
309 {
310 }
311
312 QString QQmlRectFValueType::toString() const
313 {
314     return QString(QLatin1String("QRectF(%1, %2, %3, %4)")).arg(v.x()).arg(v.y()).arg(v.width()).arg(v.height());
315 }
316
317 qreal QQmlRectFValueType::x() const
318 {
319     return v.x();
320 }
321
322 qreal QQmlRectFValueType::y() const
323 {
324     return v.y();
325 }
326
327 void QQmlRectFValueType::setX(qreal x)
328 {
329     v.moveLeft(x);
330 }
331
332 void QQmlRectFValueType::setY(qreal y)
333 {
334     v.moveTop(y);
335 }
336
337 qreal QQmlRectFValueType::width() const
338 {
339     return v.width();
340 }
341
342 qreal QQmlRectFValueType::height() const
343 {
344     return v.height();
345 }
346
347 void QQmlRectFValueType::setWidth(qreal w)
348 {
349     v.setWidth(w);
350 }
351
352 void QQmlRectFValueType::setHeight(qreal h)
353 {
354     v.setHeight(h);
355 }
356
357
358 QQmlRectValueType::QQmlRectValueType(QObject *parent)
359     : QQmlValueTypeBase<QRect>(QMetaType::QRect, parent)
360 {
361 }
362
363 QString QQmlRectValueType::toString() const
364 {
365     return QString(QLatin1String("QRect(%1, %2, %3, %4)")).arg(v.x()).arg(v.y()).arg(v.width()).arg(v.height());
366 }
367
368 int QQmlRectValueType::x() const
369 {
370     return v.x();
371 }
372
373 int QQmlRectValueType::y() const
374 {
375     return v.y();
376 }
377
378 void QQmlRectValueType::setX(int x)
379 {
380     v.moveLeft(x);
381 }
382
383 void QQmlRectValueType::setY(int y)
384 {
385     v.moveTop(y);
386 }
387
388 int QQmlRectValueType::width() const
389 {
390     return v.width();
391 }
392
393 int QQmlRectValueType::height() const
394 {
395     return v.height();
396 }
397
398 void QQmlRectValueType::setWidth(int w)
399 {
400     v.setWidth(w);
401 }
402
403 void QQmlRectValueType::setHeight(int h)
404 {
405     v.setHeight(h);
406 }
407
408
409 QQmlEasingValueType::QQmlEasingValueType(QObject *parent)
410     : QQmlValueTypeBase<QEasingCurve>(QMetaType::QEasingCurve, parent)
411 {
412 }
413
414 QString QQmlEasingValueType::toString() const
415 {
416     return QString(QLatin1String("QEasingCurve(%1, %2, %3, %4)")).arg(v.type()).arg(v.amplitude()).arg(v.overshoot()).arg(v.period());
417 }
418
419 QQmlEasingValueType::Type QQmlEasingValueType::type() const
420 {
421     return (QQmlEasingValueType::Type)v.type();
422 }
423
424 qreal QQmlEasingValueType::amplitude() const
425 {
426     return v.amplitude();
427 }
428
429 qreal QQmlEasingValueType::overshoot() const
430 {
431     return v.overshoot();
432 }
433
434 qreal QQmlEasingValueType::period() const
435 {
436     return v.period();
437 }
438
439 void QQmlEasingValueType::setType(QQmlEasingValueType::Type type)
440 {
441     v.setType((QEasingCurve::Type)type);
442 }
443
444 void QQmlEasingValueType::setAmplitude(qreal amplitude)
445 {
446     v.setAmplitude(amplitude);
447 }
448
449 void QQmlEasingValueType::setOvershoot(qreal overshoot)
450 {
451     v.setOvershoot(overshoot);
452 }
453
454 void QQmlEasingValueType::setPeriod(qreal period)
455 {
456     v.setPeriod(period);
457 }
458
459 void QQmlEasingValueType::setBezierCurve(const QVariantList &customCurveVariant)
460 {
461     if (customCurveVariant.isEmpty())
462         return;
463
464     QVariantList variantList = customCurveVariant;
465     if ((variantList.count() % 6) == 0) {
466         bool allRealsOk = true;
467         QList<qreal> reals;
468         for (int i = 0; i < variantList.count(); i++) {
469             bool ok;
470             const qreal real = variantList.at(i).toReal(&ok);
471             reals.append(real);
472             if (!ok)
473                 allRealsOk = false;
474         }
475         if (allRealsOk) {
476             QEasingCurve newEasingCurve(QEasingCurve::BezierSpline);
477             for (int i = 0; i < reals.count() / 6; i++) {
478                 const qreal c1x = reals.at(i * 6);
479                 const qreal c1y = reals.at(i * 6 + 1);
480                 const qreal c2x = reals.at(i * 6 + 2);
481                 const qreal c2y = reals.at(i * 6 + 3);
482                 const qreal c3x = reals.at(i * 6 + 4);
483                 const qreal c3y = reals.at(i * 6 + 5);
484
485                 const QPointF c1(c1x, c1y);
486                 const QPointF c2(c2x, c2y);
487                 const QPointF c3(c3x, c3y);
488
489                 newEasingCurve.addCubicBezierSegment(c1, c2, c3);
490                 v = newEasingCurve;
491             }
492         }
493     }
494 }
495
496 QVariantList QQmlEasingValueType::bezierCurve() const
497 {
498     QVariantList rv;
499     QVector<QPointF> points = v.toCubicSpline();
500     for (int ii = 0; ii < points.count(); ++ii)
501         rv << QVariant(points.at(ii).x()) << QVariant(points.at(ii).y());
502     return rv;
503 }
504
505 QT_END_NAMESPACE