1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2016 BasysKom GmbH.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtQuick module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include <private/qquickvaluetypes_p.h>
42#include <private/qquickapplication_p.h>
43#include <private/qqmlglobal_p.h>
44
45#include <QtGui/QGuiApplication>
46#include <QtGui/qdesktopservices.h>
47#include <QtGui/qfontdatabase.h>
48#include <QtGui/qstylehints.h>
49
50#include <private/qv4engine_p.h>
51#include <private/qv4object_p.h>
52
53#ifdef Q_CC_MSVC
54// MSVC2010 warns about 'unused variable t', even if it's used in t->~T()
55# pragma warning( disable : 4189 )
56#endif
57
58QT_BEGIN_NAMESPACE
59
60class QQuickColorProvider : public QQmlColorProvider
61{
62public:
63 QVariant colorFromString(const QString &s, bool *ok) override
64 {
65 QColor c(s);
66 if (c.isValid()) {
67 if (ok) *ok = true;
68 return QVariant(c);
69 }
70
71 if (ok) *ok = false;
72 return QVariant();
73 }
74
75 unsigned rgbaFromString(const QString &s, bool *ok) override
76 {
77 QColor c(s);
78 if (c.isValid()) {
79 if (ok) *ok = true;
80 return c.rgba();
81 }
82
83 if (ok) *ok = false;
84 return 0;
85 }
86
87 QString stringFromRgba(unsigned rgba)
88 {
89 QColor c(QColor::fromRgba(rgba));
90 if (c.isValid()) {
91 return QVariant(c).toString();
92 }
93
94 return QString();
95 }
96
97 QVariant fromRgbF(double r, double g, double b, double a) override
98 {
99 return QVariant(QColor::fromRgbF(r, g, b, a));
100 }
101
102 QVariant fromHslF(double h, double s, double l, double a) override
103 {
104 return QVariant(QColor::fromHslF(h, s, l, a));
105 }
106
107 QVariant fromHsvF(double h, double s, double v, double a) override
108 {
109 return QVariant(QColor::fromHsvF(h, s, v, a));
110 }
111
112 QVariant lighter(const QVariant &var, qreal factor) override
113 {
114 QColor color = var.value<QColor>();
115 color = color.lighter(int(qRound(factor*100.)));
116 return QVariant::fromValue(color);
117 }
118
119 QVariant darker(const QVariant &var, qreal factor) override
120 {
121 QColor color = var.value<QColor>();
122 color = color.darker(int(qRound(factor*100.)));
123 return QVariant::fromValue(color);
124 }
125
126 QVariant tint(const QVariant &baseVar, const QVariant &tintVar) override
127 {
128 QColor tintColor = tintVar.value<QColor>();
129
130 int tintAlpha = tintColor.alpha();
131 if (tintAlpha == 0xFF) {
132 return tintVar;
133 } else if (tintAlpha == 0x00) {
134 return baseVar;
135 }
136
137 // tint the base color and return the final color
138 QColor baseColor = baseVar.value<QColor>();
139 qreal a = tintColor.alphaF();
140 qreal inv_a = 1.0 - a;
141
142 qreal r = tintColor.redF() * a + baseColor.redF() * inv_a;
143 qreal g = tintColor.greenF() * a + baseColor.greenF() * inv_a;
144 qreal b = tintColor.blueF() * a + baseColor.blueF() * inv_a;
145
146 return QVariant::fromValue(QColor::fromRgbF(r, g, b, a + inv_a * baseColor.alphaF()));
147 }
148};
149
150
151// Note: The functions in this class provide handling only for the types
152// that the QML engine will currently actually call them for, so many
153// appear incompletely implemented. For some functions, the implementation
154// would be obvious, but for others (particularly create and createFromString)
155// the exact semantics are unknown. For this reason unused functionality
156// has been omitted.
157
158class QQuickValueTypeProvider : public QQmlValueTypeProvider
159{
160public:
161
162#if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
163 #define ASSERT_VALID_SIZE(size, min) Q_UNUSED(size)
164#else
165 #define ASSERT_VALID_SIZE(size, min) Q_ASSERT(size >= min)
166#endif
167
168 static QVector2D vector2DFromString(const QString &s, bool *ok)
169 {
170 if (s.count(QLatin1Char(',')) == 1) {
171 int index = s.indexOf(QLatin1Char(','));
172
173 bool xGood, yGood;
174 float xCoord = s.leftRef(index).toFloat(&xGood);
175 float yCoord = s.midRef(index + 1).toFloat(&yGood);
176
177 if (xGood && yGood) {
178 if (ok) *ok = true;
179 return QVector2D(xCoord, yCoord);
180 }
181 }
182
183 if (ok) *ok = false;
184 return QVector2D();
185 }
186
187 static QVector3D vector3DFromString(const QString &s, bool *ok)
188 {
189 if (s.count(QLatin1Char(',')) == 2) {
190 int index = s.indexOf(QLatin1Char(','));
191 int index2 = s.indexOf(QLatin1Char(','), index+1);
192
193 bool xGood, yGood, zGood;
194 float xCoord = s.leftRef(index).toFloat(&xGood);
195 float yCoord = s.midRef(index + 1, index2 - index - 1).toFloat(&yGood);
196 float zCoord = s.midRef(index2 + 1).toFloat(&zGood);
197
198 if (xGood && yGood && zGood) {
199 if (ok) *ok = true;
200 return QVector3D(xCoord, yCoord, zCoord);
201 }
202 }
203
204 if (ok) *ok = false;
205 return QVector3D();
206 }
207
208 static QVector4D vector4DFromString(const QString &s, bool *ok)
209 {
210 if (s.count(QLatin1Char(',')) == 3) {
211 int index = s.indexOf(QLatin1Char(','));
212 int index2 = s.indexOf(QLatin1Char(','), index+1);
213 int index3 = s.indexOf(QLatin1Char(','), index2+1);
214
215 bool xGood, yGood, zGood, wGood;
216 float xCoord = s.leftRef(index).toFloat(&xGood);
217 float yCoord = s.midRef(index + 1, index2 - index - 1).toFloat(&yGood);
218 float zCoord = s.midRef(index2 + 1, index3 - index2 - 1).toFloat(&zGood);
219 float wCoord = s.midRef(index3 + 1).toFloat(&wGood);
220
221 if (xGood && yGood && zGood && wGood) {
222 if (ok) *ok = true;
223 return QVector4D(xCoord, yCoord, zCoord, wCoord);
224 }
225 }
226
227 if (ok) *ok = false;
228 return QVector4D();
229 }
230
231 static QQuaternion quaternionFromString(const QString &s, bool *ok)
232 {
233 if (s.count(QLatin1Char(',')) == 3) {
234 int index = s.indexOf(QLatin1Char(','));
235 int index2 = s.indexOf(QLatin1Char(','), index+1);
236 int index3 = s.indexOf(QLatin1Char(','), index2+1);
237
238 bool sGood, xGood, yGood, zGood;
239 qreal sCoord = s.leftRef(index).toDouble(&sGood);
240 qreal xCoord = s.midRef(index+1, index2-index-1).toDouble(&xGood);
241 qreal yCoord = s.midRef(index2+1, index3-index2-1).toDouble(&yGood);
242 qreal zCoord = s.midRef(index3+1).toDouble(&zGood);
243
244 if (sGood && xGood && yGood && zGood) {
245 if (ok) *ok = true;
246 return QQuaternion(sCoord, xCoord, yCoord, zCoord);
247 }
248 }
249
250 if (ok) *ok = false;
251 return QQuaternion();
252 }
253
254 static QMatrix4x4 matrix4x4FromString(const QString &s, bool *ok)
255 {
256 if (s.count(QLatin1Char(',')) == 15) {
257 float matValues[16];
258 bool vOK = true;
259 QStringRef mutableStr(&s);
260 for (int i = 0; vOK && i < 16; ++i) {
261 int cidx = mutableStr.indexOf(QLatin1Char(','));
262 matValues[i] = mutableStr.left(cidx).toDouble(&vOK);
263 mutableStr = mutableStr.mid(cidx + 1);
264 }
265
266 if (vOK) {
267 if (ok) *ok = true;
268 return QMatrix4x4(matValues);
269 }
270 }
271
272 if (ok) *ok = false;
273 return QMatrix4x4();
274 }
275
276 static QFont fontFromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok)
277 {
278 if (ok)
279 *ok = false;
280 QFont retn;
281 QV4::Scope scope(v4);
282 QV4::ScopedObject obj(scope, object);
283 if (!obj) {
284 if (ok)
285 *ok = false;
286 return retn;
287 }
288
289 QV4::ScopedString s(scope);
290
291 QV4::ScopedValue vbold(scope, obj->get((s = v4->newString(QStringLiteral("bold")))));
292 QV4::ScopedValue vcap(scope, obj->get((s = v4->newString(QStringLiteral("capitalization")))));
293 QV4::ScopedValue vfam(scope, obj->get((s = v4->newString(QStringLiteral("family")))));
294 QV4::ScopedValue vstyle(scope, obj->get((s = v4->newString(QStringLiteral("styleName")))));
295 QV4::ScopedValue vital(scope, obj->get((s = v4->newString(QStringLiteral("italic")))));
296 QV4::ScopedValue vlspac(scope, obj->get((s = v4->newString(QStringLiteral("letterSpacing")))));
297 QV4::ScopedValue vpixsz(scope, obj->get((s = v4->newString(QStringLiteral("pixelSize")))));
298 QV4::ScopedValue vpntsz(scope, obj->get((s = v4->newString(QStringLiteral("pointSize")))));
299 QV4::ScopedValue vstrk(scope, obj->get((s = v4->newString(QStringLiteral("strikeout")))));
300 QV4::ScopedValue vundl(scope, obj->get((s = v4->newString(QStringLiteral("underline")))));
301 QV4::ScopedValue vweight(scope, obj->get((s = v4->newString(QStringLiteral("weight")))));
302 QV4::ScopedValue vwspac(scope, obj->get((s = v4->newString(QStringLiteral("wordSpacing")))));
303 QV4::ScopedValue vhint(scope, obj->get((s = v4->newString(QStringLiteral("hintingPreference")))));
304 QV4::ScopedValue vkerning(scope, obj->get((s = v4->newString(QStringLiteral("kerning")))));
305 QV4::ScopedValue vshaping(scope, obj->get((s = v4->newString(QStringLiteral("preferShaping")))));
306
307 // pull out the values, set ok to true if at least one valid field is given.
308 if (vbold->isBoolean()) {
309 retn.setBold(vbold->booleanValue());
310 if (ok) *ok = true;
311 }
312 if (vcap->isInt32()) {
313 retn.setCapitalization(static_cast<QFont::Capitalization>(vcap->integerValue()));
314 if (ok) *ok = true;
315 }
316 if (vfam->isString()) {
317 retn.setFamily(vfam->toQString());
318 if (ok) *ok = true;
319 }
320 if (vstyle->isString()) {
321 retn.setStyleName(vstyle->toQString());
322 if (ok) *ok = true;
323 }
324 if (vital->isBoolean()) {
325 retn.setItalic(vital->booleanValue());
326 if (ok) *ok = true;
327 }
328 if (vlspac->isNumber()) {
329 retn.setLetterSpacing(QFont::AbsoluteSpacing, vlspac->asDouble());
330 if (ok) *ok = true;
331 }
332 if (vpixsz->isInt32()) {
333 retn.setPixelSize(vpixsz->integerValue());
334 if (ok) *ok = true;
335 }
336 if (vpntsz->isNumber()) {
337 retn.setPointSize(vpntsz->asDouble());
338 if (ok) *ok = true;
339 }
340 if (vstrk->isBoolean()) {
341 retn.setStrikeOut(vstrk->booleanValue());
342 if (ok) *ok = true;
343 }
344 if (vundl->isBoolean()) {
345 retn.setUnderline(vundl->booleanValue());
346 if (ok) *ok = true;
347 }
348 if (vweight->isInt32()) {
349 retn.setWeight(static_cast<QFont::Weight>(vweight->integerValue()));
350 if (ok) *ok = true;
351 }
352 if (vwspac->isNumber()) {
353 retn.setWordSpacing(vwspac->asDouble());
354 if (ok) *ok = true;
355 }
356 if (vhint->isInt32()) {
357 retn.setHintingPreference(static_cast<QFont::HintingPreference>(vhint->integerValue()));
358 if (ok) *ok = true;
359 }
360 if (vkerning->isBoolean()) {
361 retn.setKerning(vkerning->booleanValue());
362 if (ok) *ok = true;
363 }
364 if (vshaping->isBoolean()) {
365 bool enable = vshaping->booleanValue();
366 if (enable)
367 retn.setStyleStrategy(static_cast<QFont::StyleStrategy>(retn.styleStrategy() & ~QFont::PreferNoShaping));
368 else
369 retn.setStyleStrategy(static_cast<QFont::StyleStrategy>(retn.styleStrategy() | QFont::PreferNoShaping));
370 }
371
372 return retn;
373 }
374
375 static QMatrix4x4 matrix4x4FromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok)
376 {
377 if (ok)
378 *ok = false;
379 QV4::Scope scope(v4);
380 QV4::ScopedArrayObject array(scope, object);
381 if (!array)
382 return QMatrix4x4();
383
384 if (array->getLength() != 16)
385 return QMatrix4x4();
386
387 float matVals[16];
388 QV4::ScopedValue v(scope);
389 for (quint32 i = 0; i < 16; ++i) {
390 v = array->get(i);
391 if (!v->isNumber())
392 return QMatrix4x4();
393 matVals[i] = v->asDouble();
394 }
395
396 if (ok) *ok = true;
397 return QMatrix4x4(matVals);
398 }
399
400 const QMetaObject *getMetaObjectForMetaType(int type) override
401 {
402 switch (type) {
403 case QMetaType::QColor:
404 return &QQuickColorValueType::staticMetaObject;
405 case QMetaType::QFont:
406 return &QQuickFontValueType::staticMetaObject;
407 case QMetaType::QVector2D:
408 return &QQuickVector2DValueType::staticMetaObject;
409 case QMetaType::QVector3D:
410 return &QQuickVector3DValueType::staticMetaObject;
411 case QMetaType::QVector4D:
412 return &QQuickVector4DValueType::staticMetaObject;
413 case QMetaType::QQuaternion:
414 return &QQuickQuaternionValueType::staticMetaObject;
415 case QMetaType::QMatrix4x4:
416 return &QQuickMatrix4x4ValueType::staticMetaObject;
417 default:
418 break;
419 }
420
421 return nullptr;
422 }
423
424 bool init(int type, QVariant& dst) override
425 {
426 switch (type) {
427 case QMetaType::QColor:
428 dst.setValue<QColor>(QColor());
429 return true;
430 case QMetaType::QFont:
431 dst.setValue<QFont>(QFont());
432 return true;
433 case QMetaType::QVector2D:
434 dst.setValue<QVector2D>(QVector2D());
435 return true;
436 case QMetaType::QVector3D:
437 dst.setValue<QVector3D>(QVector3D());
438 return true;
439 case QMetaType::QVector4D:
440 dst.setValue<QVector4D>(QVector4D());
441 return true;
442 case QMetaType::QQuaternion:
443 dst.setValue<QQuaternion>(QQuaternion());
444 return true;
445 case QMetaType::QMatrix4x4:
446 dst.setValue<QMatrix4x4>(QMatrix4x4());
447 return true;
448 default: break;
449 }
450
451 return false;
452 }
453
454 bool create(int type, int argc, const void *argv[], QVariant *v) override
455 {
456 switch (type) {
457 case QMetaType::QFont: // must specify via js-object.
458 break;
459 case QMetaType::QVector2D:
460 if (argc == 1) {
461 const float *xy = reinterpret_cast<const float*>(argv[0]);
462 QVector2D v2(xy[0], xy[1]);
463 *v = QVariant(v2);
464 return true;
465 }
466 break;
467 case QMetaType::QVector3D:
468 if (argc == 1) {
469 const float *xyz = reinterpret_cast<const float*>(argv[0]);
470 QVector3D v3(xyz[0], xyz[1], xyz[2]);
471 *v = QVariant(v3);
472 return true;
473 }
474 break;
475 case QMetaType::QVector4D:
476 if (argc == 1) {
477 const float *xyzw = reinterpret_cast<const float*>(argv[0]);
478 QVector4D v4(xyzw[0], xyzw[1], xyzw[2], xyzw[3]);
479 *v = QVariant(v4);
480 return true;
481 }
482 break;
483 case QMetaType::QQuaternion:
484 if (argc == 1) {
485 const qreal *sxyz = reinterpret_cast<const qreal*>(argv[0]);
486 QQuaternion q(sxyz[0], sxyz[1], sxyz[2], sxyz[3]);
487 *v = QVariant(q);
488 return true;
489 }
490 break;
491 case QMetaType::QMatrix4x4:
492 if (argc == 0) {
493 QMatrix4x4 m;
494 *v = QVariant(m);
495 return true;
496 } else if (argc == 1) {
497 const qreal *vals = reinterpret_cast<const qreal*>(argv[0]);
498 QMatrix4x4 m(vals[0], vals[1], vals[2], vals[3],
499 vals[4], vals[5], vals[6], vals[7],
500 vals[8], vals[9], vals[10], vals[11],
501 vals[12], vals[13], vals[14], vals[15]);
502 *v = QVariant(m);
503 return true;
504 }
505 break;
506 default: break;
507 }
508
509 return false;
510 }
511
512 template<typename T>
513 bool createFromStringTyped(void *data, size_t dataSize, T initValue)
514 {
515 ASSERT_VALID_SIZE(dataSize, sizeof(T));
516 T *t = reinterpret_cast<T *>(data);
517 new (t) T(initValue);
518 return true;
519 }
520
521 bool createFromString(int type, const QString &s, void *data, size_t dataSize) override
522 {
523 bool ok = false;
524
525 switch (type) {
526 case QMetaType::QColor:
527 return createFromStringTyped<QColor>(data, dataSize, QColor(s));
528 case QMetaType::QVector2D:
529 return createFromStringTyped<QVector2D>(data, dataSize, vector2DFromString(s, &ok));
530 case QMetaType::QVector3D:
531 return createFromStringTyped<QVector3D>(data, dataSize, vector3DFromString(s, &ok));
532 case QMetaType::QVector4D:
533 return createFromStringTyped<QVector4D>(data, dataSize, vector4DFromString(s, &ok));
534 case QMetaType::QQuaternion:
535 return createFromStringTyped<QQuaternion>(data, dataSize, quaternionFromString(s, &ok));
536 case QMetaType::QMatrix4x4:
537 return createFromStringTyped<QMatrix4x4>(data, dataSize, matrix4x4FromString(s, &ok));
538 default: break;
539 }
540
541 return false;
542 }
543
544 bool createStringFrom(int type, const void *data, QString *s) override
545 {
546 if (type == QMetaType::QColor) {
547 const QColor *color = reinterpret_cast<const QColor *>(data);
548 new (s) QString(QVariant(*color).toString());
549 return true;
550 }
551
552 return false;
553 }
554
555 bool variantFromString(const QString &s, QVariant *v) override
556 {
557 QColor c(s);
558 if (c.isValid()) {
559 *v = QVariant::fromValue(c);
560 return true;
561 }
562
563 bool ok = false;
564
565 QVector2D v2 = vector2DFromString(s, &ok);
566 if (ok) {
567 *v = QVariant::fromValue(v2);
568 return true;
569 }
570
571 QVector3D v3 = vector3DFromString(s, &ok);
572 if (ok) {
573 *v = QVariant::fromValue(v3);
574 return true;
575 }
576
577 QVector4D v4 = vector4DFromString(s, &ok);
578 if (ok) {
579 *v = QVariant::fromValue(v4);
580 return true;
581 }
582
583 QQuaternion q = quaternionFromString(s, &ok);
584 if (ok) {
585 *v = QVariant::fromValue(q);
586 return true;
587 }
588
589 QMatrix4x4 m = matrix4x4FromString(s, &ok);
590 if (ok) {
591 *v = QVariant::fromValue(m);
592 return true;
593 }
594
595 return false;
596 }
597
598 bool variantFromString(int type, const QString &s, QVariant *v) override
599 {
600 bool ok = false;
601
602 switch (type) {
603 case QMetaType::QColor:
604 {
605 QColor c(s);
606 *v = QVariant::fromValue(c);
607 return true;
608 }
609 case QMetaType::QVector2D:
610 {
611 *v = QVariant::fromValue(vector2DFromString(s, &ok));
612 return true;
613 }
614 case QMetaType::QVector3D:
615 {
616 *v = QVariant::fromValue(vector3DFromString(s, &ok));
617 return true;
618 }
619 case QMetaType::QVector4D:
620 {
621 *v = QVariant::fromValue(vector4DFromString(s, &ok));
622 return true;
623 }
624 case QMetaType::QQuaternion:
625 {
626 *v = QVariant::fromValue(quaternionFromString(s, &ok));
627 return true;
628 }
629 case QMetaType::QMatrix4x4:
630 {
631 *v = QVariant::fromValue(matrix4x4FromString(s, &ok));
632 return true;
633 }
634 default:
635 break;
636 }
637
638 return false;
639 }
640
641 bool variantFromJsObject(int type, const QV4::Value &object, QV4::ExecutionEngine *v4, QVariant *v) override
642 {
643 QV4::Scope scope(v4);
644#ifndef QT_NO_DEBUG
645 QV4::ScopedObject obj(scope, object);
646 Q_ASSERT(obj);
647#endif
648 bool ok = false;
649 switch (type) {
650 case QMetaType::QFont:
651 *v = QVariant::fromValue(fontFromObject(object, v4, &ok));
652 break;
653 case QMetaType::QMatrix4x4:
654 *v = QVariant::fromValue(matrix4x4FromObject(object, v4, &ok));
655 default: break;
656 }
657
658 return ok;
659 }
660
661 template<typename T>
662 bool typedEqual(const void *lhs, const QVariant& rhs)
663 {
664 return (*(reinterpret_cast<const T *>(lhs)) == rhs.value<T>());
665 }
666
667 bool equal(int type, const void *lhs, const QVariant &rhs) override
668 {
669 switch (type) {
670 case QMetaType::QColor:
671 return typedEqual<QColor>(lhs, rhs);
672 case QMetaType::QFont:
673 return typedEqual<QFont>(lhs, rhs);
674 case QMetaType::QVector2D:
675 return typedEqual<QVector2D>(lhs, rhs);
676 case QMetaType::QVector3D:
677 return typedEqual<QVector3D>(lhs, rhs);
678 case QMetaType::QVector4D:
679 return typedEqual<QVector4D>(lhs, rhs);
680 case QMetaType::QQuaternion:
681 return typedEqual<QQuaternion>(lhs, rhs);
682 case QMetaType::QMatrix4x4:
683 return typedEqual<QMatrix4x4>(lhs, rhs);
684 default: break;
685 }
686
687 return false;
688 }
689
690 template<typename T>
691 bool typedStore(const void *src, void *dst, size_t dstSize)
692 {
693 ASSERT_VALID_SIZE(dstSize, sizeof(T));
694 const T *srcT = reinterpret_cast<const T *>(src);
695 T *dstT = reinterpret_cast<T *>(dst);
696 new (dstT) T(*srcT);
697 return true;
698 }
699
700 bool store(int type, const void *src, void *dst, size_t dstSize) override
701 {
702 Q_UNUSED(dstSize);
703 switch (type) {
704 case QMetaType::QColor:
705 {
706 Q_ASSERT(dstSize >= sizeof(QColor));
707 const QRgb *rgb = reinterpret_cast<const QRgb *>(src);
708 QColor *color = reinterpret_cast<QColor *>(dst);
709 new (color) QColor(QColor::fromRgba(*rgb));
710 return true;
711 }
712 default: break;
713 }
714
715 return false;
716 }
717
718 template<typename T>
719 bool typedRead(const QVariant& src, int dstType, void *dst)
720 {
721 T *dstT = reinterpret_cast<T *>(dst);
722 if (src.type() == static_cast<uint>(dstType)) {
723 *dstT = src.value<T>();
724 } else {
725 *dstT = T();
726 }
727 return true;
728 }
729
730 bool read(const QVariant &src, void *dst, int dstType) override
731 {
732 switch (dstType) {
733 case QMetaType::QColor:
734 return typedRead<QColor>(src, dstType, dst);
735 case QMetaType::QFont:
736 return typedRead<QFont>(src, dstType, dst);
737 case QMetaType::QVector2D:
738 return typedRead<QVector2D>(src, dstType, dst);
739 case QMetaType::QVector3D:
740 return typedRead<QVector3D>(src, dstType, dst);
741 case QMetaType::QVector4D:
742 return typedRead<QVector4D>(src, dstType, dst);
743 case QMetaType::QQuaternion:
744 return typedRead<QQuaternion>(src, dstType, dst);
745 case QMetaType::QMatrix4x4:
746 return typedRead<QMatrix4x4>(src, dstType, dst);
747 default: break;
748 }
749
750 return false;
751 }
752
753 template<typename T>
754 bool typedWrite(const void *src, QVariant& dst)
755 {
756 const T *srcT = reinterpret_cast<const T *>(src);
757 if (dst.value<T>() != *srcT) {
758 dst = *srcT;
759 return true;
760 }
761 return false;
762 }
763
764 bool write(int type, const void *src, QVariant& dst) override
765 {
766 switch (type) {
767 case QMetaType::QColor:
768 return typedWrite<QColor>(src, dst);
769 case QMetaType::QFont:
770 return typedWrite<QFont>(src, dst);
771 case QMetaType::QVector2D:
772 return typedWrite<QVector2D>(src, dst);
773 case QMetaType::QVector3D:
774 return typedWrite<QVector3D>(src, dst);
775 case QMetaType::QVector4D:
776 return typedWrite<QVector4D>(src, dst);
777 case QMetaType::QQuaternion:
778 return typedWrite<QQuaternion>(src, dst);
779 case QMetaType::QMatrix4x4:
780 return typedWrite<QMatrix4x4>(src, dst);
781 default: break;
782 }
783
784 return false;
785 }
786#undef ASSERT_VALID_SIZE
787};
788
789
790class QQuickGuiProvider : public QQmlGuiProvider
791{
792public:
793 QQuickApplication *application(QObject *parent) override
794 {
795 return new QQuickApplication(parent);
796 }
797
798#if QT_CONFIG(im)
799 QInputMethod *inputMethod() override
800 {
801 QInputMethod *im = qGuiApp->inputMethod();
802 QQmlEngine::setObjectOwnership(im, QQmlEngine::CppOwnership);
803 return im;
804 }
805#endif
806
807 QStyleHints *styleHints() override
808 {
809 QStyleHints *sh = qGuiApp->styleHints();
810 QQmlEngine::setObjectOwnership(sh, QQmlEngine::CppOwnership);
811 return sh;
812 }
813
814 QStringList fontFamilies() override
815 {
816 QFontDatabase database;
817 return database.families();
818 }
819
820 bool openUrlExternally(QUrl &url) override
821 {
822#ifndef QT_NO_DESKTOPSERVICES
823 return QDesktopServices::openUrl(url);
824#else
825 Q_UNUSED(url);
826 return false;
827#endif
828 }
829
830 QString pluginName() const override
831 {
832 return QGuiApplication::platformName();
833 }
834};
835
836
837static QQuickValueTypeProvider *getValueTypeProvider()
838{
839 static QQuickValueTypeProvider valueTypeProvider;
840 return &valueTypeProvider;
841}
842
843static QQuickColorProvider *getColorProvider()
844{
845 static QQuickColorProvider colorProvider;
846 return &colorProvider;
847}
848
849static QQuickGuiProvider *getGuiProvider()
850{
851 static QQuickGuiProvider guiProvider;
852 return &guiProvider;
853}
854
855void QQuick_initializeProviders()
856{
857 QQml_addValueTypeProvider(getValueTypeProvider());
858 QQml_setColorProvider(getColorProvider());
859 QQml_setGuiProvider(getGuiProvider());
860}
861
862void QQuick_deinitializeProviders()
863{
864 QQml_removeValueTypeProvider(getValueTypeProvider());
865 QQml_setColorProvider(nullptr); // technically, another plugin may have overridden our providers
866 QQml_setGuiProvider(nullptr); // but we cannot handle that case in a sane way.
867}
868
869QT_END_NAMESPACE
870