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(f: int(qRound(d: factor*100.)));
116 return QVariant::fromValue(value: color);
117 }
118
119 QVariant darker(const QVariant &var, qreal factor) override
120 {
121 QColor color = var.value<QColor>();
122 color = color.darker(f: int(qRound(d: factor*100.)));
123 return QVariant::fromValue(value: 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(value: QColor::fromRgbF(r, g, b, a: 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(c: QLatin1Char(',')) == 1) {
171 int index = s.indexOf(c: QLatin1Char(','));
172
173 bool xGood, yGood;
174 float xCoord = s.leftRef(n: index).toFloat(ok: &xGood);
175 float yCoord = s.midRef(position: index + 1).toFloat(ok: &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(c: QLatin1Char(',')) == 2) {
190 int index = s.indexOf(c: QLatin1Char(','));
191 int index2 = s.indexOf(c: QLatin1Char(','), from: index+1);
192
193 bool xGood, yGood, zGood;
194 float xCoord = s.leftRef(n: index).toFloat(ok: &xGood);
195 float yCoord = s.midRef(position: index + 1, n: index2 - index - 1).toFloat(ok: &yGood);
196 float zCoord = s.midRef(position: index2 + 1).toFloat(ok: &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(c: QLatin1Char(',')) == 3) {
211 int index = s.indexOf(c: QLatin1Char(','));
212 int index2 = s.indexOf(c: QLatin1Char(','), from: index+1);
213 int index3 = s.indexOf(c: QLatin1Char(','), from: index2+1);
214
215 bool xGood, yGood, zGood, wGood;
216 float xCoord = s.leftRef(n: index).toFloat(ok: &xGood);
217 float yCoord = s.midRef(position: index + 1, n: index2 - index - 1).toFloat(ok: &yGood);
218 float zCoord = s.midRef(position: index2 + 1, n: index3 - index2 - 1).toFloat(ok: &zGood);
219 float wCoord = s.midRef(position: index3 + 1).toFloat(ok: &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(c: QLatin1Char(',')) == 3) {
234 int index = s.indexOf(c: QLatin1Char(','));
235 int index2 = s.indexOf(c: QLatin1Char(','), from: index+1);
236 int index3 = s.indexOf(c: QLatin1Char(','), from: index2+1);
237
238 bool sGood, xGood, yGood, zGood;
239 qreal sCoord = s.leftRef(n: index).toDouble(ok: &sGood);
240 qreal xCoord = s.midRef(position: index+1, n: index2-index-1).toDouble(ok: &xGood);
241 qreal yCoord = s.midRef(position: index2+1, n: index3-index2-1).toDouble(ok: &yGood);
242 qreal zCoord = s.midRef(position: index3+1).toDouble(ok: &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(c: 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(ch: QLatin1Char(','));
262 matValues[i] = mutableStr.left(n: cidx).toDouble(ok: &vOK);
263 mutableStr = mutableStr.mid(pos: 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 QColorSpace colorSpaceFromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok)
277 {
278 if (ok)
279 *ok = false;
280 QColorSpace 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 vName(scope, obj->get(name: (s = v4->newString(QStringLiteral("namedColorSpace")))));
292 if (vName->isInt32()) {
293 if (ok)
294 *ok = true;
295 return QColorSpace((QColorSpace::NamedColorSpace)vName->toInt32());
296 }
297
298 QV4::ScopedValue vPri(scope, obj->get(name: (s = v4->newString(QStringLiteral("primaries")))));
299 QV4::ScopedValue vTra(scope, obj->get(name: (s = v4->newString(QStringLiteral("transferFunction")))));
300 if (!vPri->isInt32() || !vTra->isInt32()) {
301 if (ok)
302 *ok = false;
303 return retn;
304 }
305
306 QColorSpace::Primaries pri = static_cast<QColorSpace::Primaries>(vPri->integerValue());
307 QColorSpace::TransferFunction tra = static_cast<QColorSpace::TransferFunction>(vTra->integerValue());
308 float gamma = 0.0f;
309 if (tra == QColorSpace::TransferFunction::Gamma) {
310 QV4::ScopedValue vGam(scope, obj->get(name: (s = v4->newString(QStringLiteral("gamma")))));
311 if (!vGam->isNumber()) {
312 if (ok)
313 *ok = false;
314 return retn;
315 }
316 gamma = vGam->toNumber();
317 }
318 if (ok) *ok = true;
319 return QColorSpace(pri, tra, gamma);
320 }
321
322 static QFont fontFromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok)
323 {
324 if (ok)
325 *ok = false;
326 QFont retn;
327 QV4::Scope scope(v4);
328 QV4::ScopedObject obj(scope, object);
329 if (!obj) {
330 if (ok)
331 *ok = false;
332 return retn;
333 }
334
335 QV4::ScopedString s(scope);
336
337 QV4::ScopedValue vbold(scope, obj->get(name: (s = v4->newString(QStringLiteral("bold")))));
338 QV4::ScopedValue vcap(scope, obj->get(name: (s = v4->newString(QStringLiteral("capitalization")))));
339 QV4::ScopedValue vfam(scope, obj->get(name: (s = v4->newString(QStringLiteral("family")))));
340 QV4::ScopedValue vstyle(scope, obj->get(name: (s = v4->newString(QStringLiteral("styleName")))));
341 QV4::ScopedValue vital(scope, obj->get(name: (s = v4->newString(QStringLiteral("italic")))));
342 QV4::ScopedValue vlspac(scope, obj->get(name: (s = v4->newString(QStringLiteral("letterSpacing")))));
343 QV4::ScopedValue vpixsz(scope, obj->get(name: (s = v4->newString(QStringLiteral("pixelSize")))));
344 QV4::ScopedValue vpntsz(scope, obj->get(name: (s = v4->newString(QStringLiteral("pointSize")))));
345 QV4::ScopedValue vstrk(scope, obj->get(name: (s = v4->newString(QStringLiteral("strikeout")))));
346 QV4::ScopedValue vundl(scope, obj->get(name: (s = v4->newString(QStringLiteral("underline")))));
347 QV4::ScopedValue vweight(scope, obj->get(name: (s = v4->newString(QStringLiteral("weight")))));
348 QV4::ScopedValue vwspac(scope, obj->get(name: (s = v4->newString(QStringLiteral("wordSpacing")))));
349 QV4::ScopedValue vhint(scope, obj->get(name: (s = v4->newString(QStringLiteral("hintingPreference")))));
350 QV4::ScopedValue vkerning(scope, obj->get(name: (s = v4->newString(QStringLiteral("kerning")))));
351 QV4::ScopedValue vshaping(scope, obj->get(name: (s = v4->newString(QStringLiteral("preferShaping")))));
352
353 // pull out the values, set ok to true if at least one valid field is given.
354 if (vbold->isBoolean()) {
355 retn.setBold(vbold->booleanValue());
356 if (ok) *ok = true;
357 }
358 if (vcap->isInt32()) {
359 retn.setCapitalization(static_cast<QFont::Capitalization>(vcap->integerValue()));
360 if (ok) *ok = true;
361 }
362 if (vfam->isString()) {
363 retn.setFamily(vfam->toQString());
364 if (ok) *ok = true;
365 }
366 if (vstyle->isString()) {
367 retn.setStyleName(vstyle->toQString());
368 if (ok) *ok = true;
369 }
370 if (vital->isBoolean()) {
371 retn.setItalic(vital->booleanValue());
372 if (ok) *ok = true;
373 }
374 if (vlspac->isNumber()) {
375 retn.setLetterSpacing(type: QFont::AbsoluteSpacing, spacing: vlspac->asDouble());
376 if (ok) *ok = true;
377 }
378 if (vpixsz->isInt32()) {
379 retn.setPixelSize(vpixsz->integerValue());
380 if (ok) *ok = true;
381 }
382 if (vpntsz->isNumber()) {
383 retn.setPointSize(vpntsz->asDouble());
384 if (ok) *ok = true;
385 }
386 if (vstrk->isBoolean()) {
387 retn.setStrikeOut(vstrk->booleanValue());
388 if (ok) *ok = true;
389 }
390 if (vundl->isBoolean()) {
391 retn.setUnderline(vundl->booleanValue());
392 if (ok) *ok = true;
393 }
394 if (vweight->isInt32()) {
395 retn.setWeight(static_cast<QFont::Weight>(vweight->integerValue()));
396 if (ok) *ok = true;
397 }
398 if (vwspac->isNumber()) {
399 retn.setWordSpacing(vwspac->asDouble());
400 if (ok) *ok = true;
401 }
402 if (vhint->isInt32()) {
403 retn.setHintingPreference(static_cast<QFont::HintingPreference>(vhint->integerValue()));
404 if (ok) *ok = true;
405 }
406 if (vkerning->isBoolean()) {
407 retn.setKerning(vkerning->booleanValue());
408 if (ok) *ok = true;
409 }
410 if (vshaping->isBoolean()) {
411 bool enable = vshaping->booleanValue();
412 if (enable)
413 retn.setStyleStrategy(static_cast<QFont::StyleStrategy>(retn.styleStrategy() & ~QFont::PreferNoShaping));
414 else
415 retn.setStyleStrategy(static_cast<QFont::StyleStrategy>(retn.styleStrategy() | QFont::PreferNoShaping));
416 }
417
418 return retn;
419 }
420
421 static QMatrix4x4 matrix4x4FromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok)
422 {
423 if (ok)
424 *ok = false;
425 QV4::Scope scope(v4);
426 QV4::ScopedArrayObject array(scope, object);
427 if (!array)
428 return QMatrix4x4();
429
430 if (array->getLength() != 16)
431 return QMatrix4x4();
432
433 float matVals[16];
434 QV4::ScopedValue v(scope);
435 for (quint32 i = 0; i < 16; ++i) {
436 v = array->get(idx: i);
437 if (!v->isNumber())
438 return QMatrix4x4();
439 matVals[i] = v->asDouble();
440 }
441
442 if (ok) *ok = true;
443 return QMatrix4x4(matVals);
444 }
445
446 const QMetaObject *getMetaObjectForMetaType(int type) override
447 {
448 switch (type) {
449 case QMetaType::QColor:
450 return &QQuickColorValueType::staticMetaObject;
451 case QMetaType::QColorSpace:
452 return &QQuickColorSpaceValueType::staticMetaObject;
453 case QMetaType::QFont:
454 return &QQuickFontValueType::staticMetaObject;
455 case QMetaType::QVector2D:
456 return &QQuickVector2DValueType::staticMetaObject;
457 case QMetaType::QVector3D:
458 return &QQuickVector3DValueType::staticMetaObject;
459 case QMetaType::QVector4D:
460 return &QQuickVector4DValueType::staticMetaObject;
461 case QMetaType::QQuaternion:
462 return &QQuickQuaternionValueType::staticMetaObject;
463 case QMetaType::QMatrix4x4:
464 return &QQuickMatrix4x4ValueType::staticMetaObject;
465 default:
466 break;
467 }
468
469 return nullptr;
470 }
471
472 bool init(int type, QVariant& dst) override
473 {
474 switch (type) {
475 case QMetaType::QColor:
476 dst.setValue<QColor>(QColor());
477 return true;
478 case QMetaType::QColorSpace:
479 dst.setValue<QColorSpace>(QColorSpace());
480 return true;
481 case QMetaType::QFont:
482 dst.setValue<QFont>(QFont());
483 return true;
484 case QMetaType::QVector2D:
485 dst.setValue<QVector2D>(QVector2D());
486 return true;
487 case QMetaType::QVector3D:
488 dst.setValue<QVector3D>(QVector3D());
489 return true;
490 case QMetaType::QVector4D:
491 dst.setValue<QVector4D>(QVector4D());
492 return true;
493 case QMetaType::QQuaternion:
494 dst.setValue<QQuaternion>(QQuaternion());
495 return true;
496 case QMetaType::QMatrix4x4:
497 dst.setValue<QMatrix4x4>(QMatrix4x4());
498 return true;
499 default: break;
500 }
501
502 return false;
503 }
504
505 bool create(int type, int argc, const void *argv[], QVariant *v) override
506 {
507 switch (type) {
508 case QMetaType::QFont: // must specify via js-object.
509 break;
510 case QMetaType::QVector2D:
511 if (argc == 1) {
512 const float *xy = reinterpret_cast<const float*>(argv[0]);
513 QVector2D v2(xy[0], xy[1]);
514 *v = QVariant(v2);
515 return true;
516 }
517 break;
518 case QMetaType::QVector3D:
519 if (argc == 1) {
520 const float *xyz = reinterpret_cast<const float*>(argv[0]);
521 QVector3D v3(xyz[0], xyz[1], xyz[2]);
522 *v = QVariant(v3);
523 return true;
524 }
525 break;
526 case QMetaType::QVector4D:
527 if (argc == 1) {
528 const float *xyzw = reinterpret_cast<const float*>(argv[0]);
529 QVector4D v4(xyzw[0], xyzw[1], xyzw[2], xyzw[3]);
530 *v = QVariant(v4);
531 return true;
532 }
533 break;
534 case QMetaType::QQuaternion:
535 if (argc == 1) {
536 const qreal *sxyz = reinterpret_cast<const qreal*>(argv[0]);
537 QQuaternion q(sxyz[0], sxyz[1], sxyz[2], sxyz[3]);
538 *v = QVariant(q);
539 return true;
540 }
541 break;
542 case QMetaType::QMatrix4x4:
543 if (argc == 0) {
544 QMatrix4x4 m;
545 *v = QVariant(m);
546 return true;
547 } else if (argc == 1) {
548 const qreal *vals = reinterpret_cast<const qreal*>(argv[0]);
549 QMatrix4x4 m(vals[0], vals[1], vals[2], vals[3],
550 vals[4], vals[5], vals[6], vals[7],
551 vals[8], vals[9], vals[10], vals[11],
552 vals[12], vals[13], vals[14], vals[15]);
553 *v = QVariant(m);
554 return true;
555 }
556 break;
557 default: break;
558 }
559
560 return false;
561 }
562
563 template<typename T>
564 bool createFromStringTyped(void *data, size_t dataSize, T initValue)
565 {
566 ASSERT_VALID_SIZE(dataSize, sizeof(T));
567 T *t = reinterpret_cast<T *>(data);
568 new (t) T(initValue);
569 return true;
570 }
571
572 bool createFromString(int type, const QString &s, void *data, size_t dataSize) override
573 {
574 bool ok = false;
575
576 switch (type) {
577 case QMetaType::QColor:
578 return createFromStringTyped<QColor>(data, dataSize, initValue: QColor(s));
579 case QMetaType::QVector2D:
580 return createFromStringTyped<QVector2D>(data, dataSize, initValue: vector2DFromString(s, ok: &ok));
581 case QMetaType::QVector3D:
582 return createFromStringTyped<QVector3D>(data, dataSize, initValue: vector3DFromString(s, ok: &ok));
583 case QMetaType::QVector4D:
584 return createFromStringTyped<QVector4D>(data, dataSize, initValue: vector4DFromString(s, ok: &ok));
585 case QMetaType::QQuaternion:
586 return createFromStringTyped<QQuaternion>(data, dataSize, initValue: quaternionFromString(s, ok: &ok));
587 case QMetaType::QMatrix4x4:
588 return createFromStringTyped<QMatrix4x4>(data, dataSize, initValue: matrix4x4FromString(s, ok: &ok));
589 default: break;
590 }
591
592 return false;
593 }
594
595 bool createStringFrom(int type, const void *data, QString *s) override
596 {
597 if (type == QMetaType::QColor) {
598 const QColor *color = reinterpret_cast<const QColor *>(data);
599 new (s) QString(QVariant(*color).toString());
600 return true;
601 }
602
603 return false;
604 }
605
606 bool variantFromString(const QString &s, QVariant *v) override
607 {
608 QColor c(s);
609 if (c.isValid()) {
610 *v = QVariant::fromValue(value: c);
611 return true;
612 }
613
614 bool ok = false;
615
616 QVector2D v2 = vector2DFromString(s, ok: &ok);
617 if (ok) {
618 *v = QVariant::fromValue(value: v2);
619 return true;
620 }
621
622 QVector3D v3 = vector3DFromString(s, ok: &ok);
623 if (ok) {
624 *v = QVariant::fromValue(value: v3);
625 return true;
626 }
627
628 QVector4D v4 = vector4DFromString(s, ok: &ok);
629 if (ok) {
630 *v = QVariant::fromValue(value: v4);
631 return true;
632 }
633
634 QQuaternion q = quaternionFromString(s, ok: &ok);
635 if (ok) {
636 *v = QVariant::fromValue(value: q);
637 return true;
638 }
639
640 QMatrix4x4 m = matrix4x4FromString(s, ok: &ok);
641 if (ok) {
642 *v = QVariant::fromValue(value: m);
643 return true;
644 }
645
646 return false;
647 }
648
649 bool variantFromString(int type, const QString &s, QVariant *v) override
650 {
651 bool ok = false;
652
653 switch (type) {
654 case QMetaType::QColor:
655 {
656 QColor c(s);
657 *v = QVariant::fromValue(value: c);
658 return true;
659 }
660 case QMetaType::QVector2D:
661 {
662 *v = QVariant::fromValue(value: vector2DFromString(s, ok: &ok));
663 return true;
664 }
665 case QMetaType::QVector3D:
666 {
667 *v = QVariant::fromValue(value: vector3DFromString(s, ok: &ok));
668 return true;
669 }
670 case QMetaType::QVector4D:
671 {
672 *v = QVariant::fromValue(value: vector4DFromString(s, ok: &ok));
673 return true;
674 }
675 case QMetaType::QQuaternion:
676 {
677 *v = QVariant::fromValue(value: quaternionFromString(s, ok: &ok));
678 return true;
679 }
680 case QMetaType::QMatrix4x4:
681 {
682 *v = QVariant::fromValue(value: matrix4x4FromString(s, ok: &ok));
683 return true;
684 }
685 default:
686 break;
687 }
688
689 return false;
690 }
691
692 bool variantFromJsObject(int type, const QV4::Value &object, QV4::ExecutionEngine *v4, QVariant *v) override
693 {
694 QV4::Scope scope(v4);
695#ifndef QT_NO_DEBUG
696 QV4::ScopedObject obj(scope, object);
697 Q_ASSERT(obj);
698#endif
699 bool ok = false;
700 switch (type) {
701 case QMetaType::QColorSpace:
702 *v = QVariant::fromValue(value: colorSpaceFromObject(object, v4, ok: &ok));
703 break;
704 case QMetaType::QFont:
705 *v = QVariant::fromValue(value: fontFromObject(object, v4, ok: &ok));
706 break;
707 case QMetaType::QMatrix4x4:
708 *v = QVariant::fromValue(value: matrix4x4FromObject(object, v4, ok: &ok));
709 default: break;
710 }
711
712 return ok;
713 }
714
715 template<typename T>
716 bool typedEqual(const void *lhs, const QVariant& rhs)
717 {
718 return (*(reinterpret_cast<const T *>(lhs)) == rhs.value<T>());
719 }
720
721 bool equal(int type, const void *lhs, const QVariant &rhs) override
722 {
723 switch (type) {
724 case QMetaType::QColor:
725 return typedEqual<QColor>(lhs, rhs);
726 case QMetaType::QColorSpace:
727 return typedEqual<QColorSpace>(lhs, rhs);
728 case QMetaType::QFont:
729 return typedEqual<QFont>(lhs, rhs);
730 case QMetaType::QVector2D:
731 return typedEqual<QVector2D>(lhs, rhs);
732 case QMetaType::QVector3D:
733 return typedEqual<QVector3D>(lhs, rhs);
734 case QMetaType::QVector4D:
735 return typedEqual<QVector4D>(lhs, rhs);
736 case QMetaType::QQuaternion:
737 return typedEqual<QQuaternion>(lhs, rhs);
738 case QMetaType::QMatrix4x4:
739 return typedEqual<QMatrix4x4>(lhs, rhs);
740 default: break;
741 }
742
743 return false;
744 }
745
746 template<typename T>
747 bool typedStore(const void *src, void *dst, size_t dstSize)
748 {
749 ASSERT_VALID_SIZE(dstSize, sizeof(T));
750 const T *srcT = reinterpret_cast<const T *>(src);
751 T *dstT = reinterpret_cast<T *>(dst);
752 new (dstT) T(*srcT);
753 return true;
754 }
755
756 bool store(int type, const void *src, void *dst, size_t dstSize) override
757 {
758 Q_UNUSED(dstSize);
759 switch (type) {
760 case QMetaType::QColor:
761 {
762 Q_ASSERT(dstSize >= sizeof(QColor));
763 const QRgb *rgb = reinterpret_cast<const QRgb *>(src);
764 QColor *color = reinterpret_cast<QColor *>(dst);
765 new (color) QColor(QColor::fromRgba(rgba: *rgb));
766 return true;
767 }
768 default: break;
769 }
770
771 return false;
772 }
773
774 template<typename T>
775 bool typedRead(const QVariant& src, int dstType, void *dst)
776 {
777 T *dstT = reinterpret_cast<T *>(dst);
778 if (src.userType() == dstType) {
779 *dstT = src.value<T>();
780 } else {
781 *dstT = T();
782 }
783 return true;
784 }
785
786 bool read(const QVariant &src, void *dst, int dstType) override
787 {
788 switch (dstType) {
789 case QMetaType::QColor:
790 return typedRead<QColor>(src, dstType, dst);
791 case QMetaType::QColorSpace:
792 return typedRead<QColorSpace>(src, dstType, dst);
793 case QMetaType::QFont:
794 return typedRead<QFont>(src, dstType, dst);
795 case QMetaType::QVector2D:
796 return typedRead<QVector2D>(src, dstType, dst);
797 case QMetaType::QVector3D:
798 return typedRead<QVector3D>(src, dstType, dst);
799 case QMetaType::QVector4D:
800 return typedRead<QVector4D>(src, dstType, dst);
801 case QMetaType::QQuaternion:
802 return typedRead<QQuaternion>(src, dstType, dst);
803 case QMetaType::QMatrix4x4:
804 return typedRead<QMatrix4x4>(src, dstType, dst);
805 default: break;
806 }
807
808 return false;
809 }
810
811 template<typename T>
812 bool typedWrite(const void *src, QVariant& dst)
813 {
814 const T *srcT = reinterpret_cast<const T *>(src);
815 if (dst.value<T>() != *srcT) {
816 dst = *srcT;
817 return true;
818 }
819 return false;
820 }
821
822 bool write(int type, const void *src, QVariant& dst) override
823 {
824 switch (type) {
825 case QMetaType::QColor:
826 return typedWrite<QColor>(src, dst);
827 case QMetaType::QColorSpace:
828 return typedWrite<QColorSpace>(src, dst);
829 case QMetaType::QFont:
830 return typedWrite<QFont>(src, dst);
831 case QMetaType::QVector2D:
832 return typedWrite<QVector2D>(src, dst);
833 case QMetaType::QVector3D:
834 return typedWrite<QVector3D>(src, dst);
835 case QMetaType::QVector4D:
836 return typedWrite<QVector4D>(src, dst);
837 case QMetaType::QQuaternion:
838 return typedWrite<QQuaternion>(src, dst);
839 case QMetaType::QMatrix4x4:
840 return typedWrite<QMatrix4x4>(src, dst);
841 default: break;
842 }
843
844 return false;
845 }
846#undef ASSERT_VALID_SIZE
847};
848
849
850class QQuickGuiProvider : public QQmlGuiProvider
851{
852public:
853 QQuickApplication *application(QObject *parent) override
854 {
855 return new QQuickApplication(parent);
856 }
857
858#if QT_CONFIG(im)
859 QInputMethod *inputMethod() override
860 {
861 QInputMethod *im = qGuiApp->inputMethod();
862 QQmlEngine::setObjectOwnership(im, QQmlEngine::CppOwnership);
863 return im;
864 }
865#endif
866
867 QStyleHints *styleHints() override
868 {
869 QStyleHints *sh = qGuiApp->styleHints();
870 QQmlEngine::setObjectOwnership(sh, QQmlEngine::CppOwnership);
871 return sh;
872 }
873
874 QStringList fontFamilies() override
875 {
876 QFontDatabase database;
877 return database.families();
878 }
879
880 bool openUrlExternally(QUrl &url) override
881 {
882#ifndef QT_NO_DESKTOPSERVICES
883 return QDesktopServices::openUrl(url);
884#else
885 Q_UNUSED(url);
886 return false;
887#endif
888 }
889
890 QString pluginName() const override
891 {
892 return QGuiApplication::platformName();
893 }
894};
895
896
897static QQuickValueTypeProvider *getValueTypeProvider()
898{
899 static QQuickValueTypeProvider valueTypeProvider;
900 return &valueTypeProvider;
901}
902
903static QQuickColorProvider *getColorProvider()
904{
905 static QQuickColorProvider colorProvider;
906 return &colorProvider;
907}
908
909static QQuickGuiProvider *getGuiProvider()
910{
911 static QQuickGuiProvider guiProvider;
912 return &guiProvider;
913}
914
915void QQuick_initializeProviders()
916{
917 QQml_addValueTypeProvider(getValueTypeProvider());
918 QQml_setColorProvider(getColorProvider());
919 QQml_setGuiProvider(getGuiProvider());
920}
921
922void QQuick_deinitializeProviders()
923{
924 QQml_removeValueTypeProvider(getValueTypeProvider());
925 QQml_setColorProvider(nullptr); // technically, another plugin may have overridden our providers
926 QQml_setGuiProvider(nullptr); // but we cannot handle that case in a sane way.
927}
928
929QT_END_NAMESPACE
930

source code of qtdeclarative/src/quick/util/qquickglobal.cpp