1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtQml/private/qjsvalue_p.h>
5#include <QtQml/private/qqmlglobal_p.h>
6#include <QtQml/private/qqmlmetatype_p.h>
7#include <QtQml/qqmlengine.h>
8
9#include <QtCore/private/qvariant_p.h>
10#include <QtCore/qcoreapplication.h>
11#include <QtCore/qdebug.h>
12#include <QtCore/qstringlist.h>
13
14QT_BEGIN_NAMESPACE
15
16// Pre-filter the metatype before poking QQmlMetaType::qmlType() and locking its mutex.
17static bool isConstructibleMetaType(const QMetaType metaType)
18{
19 switch (metaType.id()) {
20 // The builtins are not constructible this way.
21 case QMetaType::Void:
22 case QMetaType::Nullptr:
23 case QMetaType::QVariant:
24 case QMetaType::Int:
25 case QMetaType::UInt:
26 case QMetaType::LongLong:
27 case QMetaType::ULongLong:
28 case QMetaType::Float:
29 case QMetaType::Double:
30 case QMetaType::Long:
31 case QMetaType::ULong:
32 case QMetaType::Short:
33 case QMetaType::UShort:
34 case QMetaType::Char:
35 case QMetaType::SChar:
36 case QMetaType::UChar:
37 case QMetaType::QChar:
38 case QMetaType::QString:
39 case QMetaType::Bool:
40 case QMetaType::QDateTime:
41 case QMetaType::QDate:
42 case QMetaType::QTime:
43 case QMetaType::QUrl:
44 case QMetaType::QRegularExpression:
45 case QMetaType::QByteArray:
46 case QMetaType::QLocale:
47 return false;
48 default:
49 break;
50 }
51
52 // QJSValue is also builtin
53 if (metaType == QMetaType::fromType<QJSValue>())
54 return false;
55
56 // We also don't want to construct pointers of any kind, or lists, or enums.
57 if (metaType.flags() &
58 (QMetaType::PointerToQObject
59 | QMetaType::IsEnumeration
60 | QMetaType::SharedPointerToQObject
61 | QMetaType::WeakPointerToQObject
62 | QMetaType::TrackingPointerToQObject
63 | QMetaType::IsUnsignedEnumeration
64 | QMetaType::PointerToGadget
65 | QMetaType::IsPointer
66 | QMetaType::IsQmlList)) {
67 return false;
68 }
69
70 return true;
71}
72
73static void *createVariantData(QMetaType type, QVariant *variant)
74{
75 const QtPrivate::QMetaTypeInterface *iface = type.iface();
76 QVariant::Private *d = &variant->data_ptr();
77 Q_ASSERT(d->is_null && !d->is_shared);
78 *d = QVariant::Private(iface);
79 if (QVariant::Private::canUseInternalSpace(type: iface))
80 return d->data.data;
81
82 // This is not exception safe.
83 // If your value type throws an exception from its ctor bad things will happen anyway.
84 d->data.shared = QVariant::PrivateShared::create(size: iface->size, align: iface->alignment);
85 d->is_shared = true;
86 return d->data.shared->data();
87}
88
89static void callConstructor(
90 const QMetaObject *targetMetaObject, int i, void *source, void *target)
91{
92 void *p[] = { target, source };
93 targetMetaObject->static_metacall(QMetaObject::ConstructInPlace, i, p);
94}
95
96template<typename Allocate>
97static void fromVerifiedType(
98 const QMetaObject *targetMetaObject, int ctorIndex, void *source, Allocate &&allocate)
99{
100 const QMetaMethod ctor = targetMetaObject->constructor(index: ctorIndex);
101 Q_ASSERT_X(ctor.parameterCount() == 1, "fromVerifiedType",
102 "Value type constructor must take exactly one argument");
103 callConstructor(targetMetaObject, ctorIndex, source, allocate());
104}
105
106
107template<typename Allocate, typename Retrieve>
108static bool fromMatchingType(
109 const QMetaObject *targetMetaObject, Allocate &&allocate, Retrieve &&retrieve)
110{
111 for (int i = 0, end = targetMetaObject->constructorCount(); i < end; ++i) {
112 const QMetaMethod ctor = targetMetaObject->constructor(index: i);
113 if (ctor.parameterCount() != 1)
114 continue;
115
116 const QMetaType parameterType = ctor.parameterMetaType(index: 0);
117
118 if (retrieve(parameterType, [&](QMetaType sourceMetaType, void *sourceData) {
119 if (sourceMetaType == parameterType) {
120 callConstructor(targetMetaObject, i, sourceData, allocate());
121 return true;
122 }
123
124 if (const QMetaObject *parameterMetaObject = parameterType.metaObject()) {
125 if (const QMetaObject *sourceMetaObject = sourceMetaType.metaObject();
126 sourceMetaObject && sourceMetaObject->inherits(metaObject: parameterMetaObject)) {
127 // Allow construction from derived types.
128 callConstructor(targetMetaObject, i, sourceData, allocate());
129 return true;
130 }
131 }
132
133 // Do not recursively try to create parameters here. This may end up in infinite recursion.
134
135 // At this point, s should be a builtin type. For builtin types
136 // the QMetaType converters are good enough.
137 QVariant converted(parameterType);
138 if (QMetaType::convert(fromType: sourceMetaType, from: sourceData, toType: parameterType, to: converted.data())) {
139 callConstructor(targetMetaObject, i, converted.data(), allocate());
140 return true;
141 }
142
143 return false;
144 })) {
145 return true;
146 }
147 }
148
149 return false;
150}
151
152template<typename Allocate>
153static bool fromMatchingType(
154 const QMetaObject *targetMetaObject, const QV4::Value &source, Allocate &&allocate)
155{
156 return fromMatchingType(
157 targetMetaObject, std::forward<Allocate>(allocate),
158 [&](QMetaType parameterType, auto callback) {
159 QVariant variant = QV4::ExecutionEngine::toVariant(value: source, typeHint: parameterType);
160 return callback(variant.metaType(), variant.data());
161 });
162}
163
164template<typename Allocate>
165static bool fromMatchingType(
166 const QMetaObject *targetMetaObject, QVariant source, Allocate &&allocate)
167{
168 return fromMatchingType(targetMetaObject, std::forward<Allocate>(allocate),
169 [&](QMetaType, auto callback) {
170 return callback(source.metaType(), source.data());
171 });
172}
173
174template<typename Allocate>
175static bool fromString(const QMetaObject *mo, QString s, Allocate &&allocate)
176{
177 for (int i = 0, end = mo->constructorCount(); i < end; ++i) {
178 const QMetaMethod ctor = mo->constructor(index: i);
179 if (ctor.parameterCount() != 1)
180 continue;
181
182 if (ctor.parameterMetaType(index: 0) == QMetaType::fromType<QString>()) {
183 callConstructor(mo, i, &s, allocate());
184 return true;
185 }
186 }
187
188 return false;
189}
190
191template<typename Get, typename Convert>
192static bool doWriteProperty(const QMetaProperty &metaProperty, void *target,
193 Get &&get, Convert &&convert)
194{
195 const QMetaType propertyType = metaProperty.metaType();
196 QVariant property = get(propertyType);
197 if (property.metaType() == propertyType) {
198 metaProperty.writeOnGadget(gadget: target, value: std::move(property));
199 return true;
200 }
201
202 QVariant converted = convert(propertyType);
203 if (converted.isValid()) {
204 metaProperty.writeOnGadget(gadget: target, value: std::move(converted));
205 return true;
206 }
207
208 converted = QVariant(propertyType);
209 if (QMetaType::convert(fromType: property.metaType(), from: property.constData(),
210 toType: propertyType, to: converted.data())) {
211 metaProperty.writeOnGadget(gadget: target, value: std::move(converted));
212 return true;
213 }
214
215 return false;
216}
217
218static void doWriteProperties(
219 const QMetaObject *targetMetaObject, void *target, const QV4::Value &source)
220{
221 const QV4::Object *o = static_cast<const QV4::Object *>(&source);
222 QV4::Scope scope(o->engine());
223 QV4::ScopedObject object(scope, o);
224
225 for (int i = 0; i < targetMetaObject->propertyCount(); ++i) {
226 const QMetaProperty metaProperty = targetMetaObject->property(index: i);
227 const QString propertyName = QString::fromUtf8(utf8: metaProperty.name());
228
229 QV4::ScopedString v4PropName(scope, scope.engine->newString(s: propertyName));
230 QV4::ScopedValue v4PropValue(scope, object->get(name: v4PropName));
231
232 // We assume that data is freshly constructed.
233 // There is no point in reset()'ing properties of a freshly created object.
234 if (v4PropValue->isUndefined())
235 continue;
236
237 if (doWriteProperty(metaProperty, target, get: [&](const QMetaType &propertyType) {
238 return QV4::ExecutionEngine::toVariant(value: v4PropValue, typeHint: propertyType);
239 }, convert: [&](const QMetaType &propertyType) {
240 return QQmlValueTypeProvider::createValueType(v4PropValue, propertyType);
241 })) {
242 continue;
243 }
244
245 const QMetaType propertyType = metaProperty.metaType();
246 QVariant property = QV4::ExecutionEngine::toVariant(value: v4PropValue, typeHint: propertyType);
247 if (property.metaType() == propertyType) {
248 metaProperty.writeOnGadget(gadget: target, value: std::move(property));
249 continue;
250 }
251
252 QVariant converted = QQmlValueTypeProvider::createValueType(v4PropValue, propertyType);
253 if (converted.isValid()) {
254 metaProperty.writeOnGadget(gadget: target, value: std::move(converted));
255 continue;
256 }
257
258 converted = QVariant(propertyType);
259 if (QMetaType::convert(fromType: property.metaType(), from: property.constData(),
260 toType: propertyType, to: converted.data())) {
261 metaProperty.writeOnGadget(gadget: target, value: std::move(converted));
262 continue;
263 }
264
265 qWarning().noquote()
266 << QLatin1String("Could not convert %1 to %2 for property %3")
267 .arg(args: v4PropValue->toQStringNoThrow(), args: QString::fromUtf8(utf8: propertyType.name()),
268 args: propertyName);
269 }
270}
271
272static QVariant byProperties(
273 const QMetaObject *targetMetaObject, QMetaType metaType, const QV4::Value &source)
274{
275 if (!source.isObject() || !targetMetaObject)
276 return QVariant();
277
278 QVariant result(metaType);
279 doWriteProperties(targetMetaObject, target: result.data(), source);
280 return result;
281}
282
283template<typename Read>
284static void doWriteProperties(
285 const QMetaObject *targetMetaObject, void *target,
286 const QMetaObject *sourceMetaObject, Read &&read)
287{
288 for (int i = 0; i < targetMetaObject->propertyCount(); ++i) {
289 const QMetaProperty metaProperty = targetMetaObject->property(index: i);
290
291 const int sourceProperty = sourceMetaObject->indexOfProperty(name: metaProperty.name());
292
293 // We assume that data is freshly constructed.
294 // There is no point in reset()'ing properties of a freshly created object.
295 if (sourceProperty == -1)
296 continue;
297
298 const QMetaType propertyType = metaProperty.metaType();
299 QVariant property = read(sourceMetaObject, sourceProperty);
300 if (property.metaType() == propertyType) {
301 metaProperty.writeOnGadget(gadget: target, value: std::move(property));
302 continue;
303 }
304
305 QVariant converted = QQmlValueTypeProvider::createValueType(property, propertyType);
306 if (converted.isValid()) {
307 metaProperty.writeOnGadget(gadget: target, value: std::move(converted));
308 continue;
309 }
310
311 converted = QVariant(propertyType);
312 if (QMetaType::convert(fromType: property.metaType(), from: property.constData(),
313 toType: propertyType, to: converted.data())) {
314 metaProperty.writeOnGadget(gadget: target, value: std::move(converted));
315 continue;
316 }
317
318 qWarning().noquote()
319 << QLatin1String("Could not convert %1 to %2 for property %3")
320 .arg(args: property.toString(), args: QString::fromUtf8(utf8: propertyType.name()),
321 args: QString::fromUtf8(utf8: metaProperty.name()));
322 }
323}
324
325
326static void doWriteProperties(const QMetaObject *targetMeta, void *target, QObject *source)
327{
328 doWriteProperties(
329 targetMetaObject: targetMeta, target, sourceMetaObject: source->metaObject(),
330 read: [source](const QMetaObject *sourceMetaObject, int sourceProperty) {
331 return sourceMetaObject->property(index: sourceProperty).read(obj: source);
332 });
333}
334
335static QVariant byProperties(
336 const QMetaObject *targetMetaObject, QMetaType targetMetaType, QObject *source)
337{
338 if (!source || !targetMetaObject)
339 return QVariant();
340
341 QVariant result(targetMetaType);
342 doWriteProperties(targetMeta: targetMetaObject, target: result.data(), source);
343 return result;
344}
345
346static QVariant byProperties(
347 const QMetaObject *targetMetaObject, QMetaType targetMetaType,
348 const QMetaObject *sourceMetaObject, const void *source)
349{
350 if (!source || !sourceMetaObject || !targetMetaObject)
351 return QVariant();
352
353 QVariant result(targetMetaType);
354 doWriteProperties(
355 targetMetaObject, target: result.data(), sourceMetaObject,
356 read: [source](const QMetaObject *sourceMetaObject, int sourceProperty) {
357 return sourceMetaObject->property(index: sourceProperty).readOnGadget(gadget: source);
358 });
359 return result;
360}
361
362template<typename Map>
363void doWriteProperties(const QMetaObject *targetMetaObject, void *target, const Map &source)
364{
365 for (int i = 0; i < targetMetaObject->propertyCount(); ++i) {
366 const QMetaProperty metaProperty = targetMetaObject->property(index: i);
367
368 // We assume that data is freshly constructed.
369 // There is no point in reset()'ing properties of a freshly created object.
370 const auto it = source.constFind(QString::fromUtf8(utf8: metaProperty.name()));
371 if (it == source.constEnd())
372 continue;
373
374 const QMetaType propertyType = metaProperty.metaType();
375 QVariant property = *it;
376 if (property.metaType() == propertyType) {
377 metaProperty.writeOnGadget(gadget: target, value: std::move(property));
378 continue;
379 }
380
381 QVariant converted = QQmlValueTypeProvider::createValueType(property, propertyType);
382 if (converted.isValid()) {
383 metaProperty.writeOnGadget(gadget: target, value: std::move(converted));
384 continue;
385 }
386
387 converted = QVariant(propertyType);
388 if (QMetaType::convert(fromType: property.metaType(), from: property.constData(),
389 toType: propertyType, to: converted.data())) {
390 metaProperty.writeOnGadget(gadget: target, value: std::move(converted));
391 continue;
392 }
393
394 qWarning().noquote()
395 << QLatin1String("Could not convert %1 to %2 for property %3")
396 .arg(args: property.toString(), args: QString::fromUtf8(utf8: propertyType.name()),
397 args: QString::fromUtf8(utf8: metaProperty.name()));
398 }
399}
400
401template<typename Map>
402QVariant byProperties(
403 const QMetaObject *targetMetaObject, QMetaType targetMetaType, const Map &source)
404{
405 QVariant result(targetMetaType);
406 doWriteProperties(targetMetaObject, result.data(), source);
407 return result;
408}
409
410static QVariant byProperties(
411 const QMetaObject *targetMetaObject, QMetaType targetMetaType, const QVariant &source)
412{
413 if (!targetMetaObject)
414 return QVariant();
415
416 if (source.metaType() == QMetaType::fromType<QJSValue>()) {
417 QJSValue val = source.value<QJSValue>();
418 return byProperties(
419 targetMetaObject, metaType: targetMetaType, source: QV4::Value(QJSValuePrivate::asReturnedValue(jsval: &val)));
420 }
421
422 if (source.metaType() == QMetaType::fromType<QVariantMap>()) {
423 return byProperties(
424 targetMetaObject, targetMetaType,
425 source: *static_cast<const QVariantMap *>(source.constData()));
426 }
427
428 if (source.metaType() == QMetaType::fromType<QVariantHash>()) {
429 return byProperties(
430 targetMetaObject, targetMetaType,
431 source: *static_cast<const QVariantHash *>(source.constData()));
432 }
433
434 if (source.metaType().flags() & QMetaType::PointerToQObject)
435 return byProperties(targetMetaObject, targetMetaType, source: source.value<QObject *>());
436
437 if (const QMetaObject *sourceMeta = QQmlMetaType::metaObjectForValueType(type: source.metaType()))
438 return byProperties(targetMetaObject, targetMetaType, sourceMetaObject: sourceMeta, source: source.constData());
439
440 return QVariant();
441}
442
443/*!
444 * \internal
445 * Specialization that creates the value type in place at \a target, which is expected to be
446 * already initialized. This is more efficient if we can do byProperties() since it can use a
447 * pre-constructed object. It also avoids the creation of a QVariant in most cases. It is less
448 * efficient if you're going to create a QVariant anyway.
449 */
450bool QQmlValueTypeProvider::createValueType(
451 QMetaType targetMetaType, void *target, const QV4::Value &source)
452{
453 if (!isConstructibleMetaType(metaType: targetMetaType))
454 return false;
455
456 auto destruct = [targetMetaType, target]() {
457 targetMetaType.destruct(data: target);
458 return target;
459 };
460
461 const QQmlType type = QQmlMetaType::qmlType(metaType: targetMetaType);
462 if (const QMetaObject *targetMeta = QQmlMetaType::metaObjectForValueType(qmlType: type)) {
463 const auto warn = [&]() {
464 qWarning().noquote()
465 << "Could not find any constructor for value type"
466 << targetMeta->className() << "to call with value" << source.toQStringNoThrow();
467 };
468
469 if (type.canPopulateValueType()) {
470 if (source.isObject() && targetMeta) {
471 doWriteProperties(targetMetaObject: targetMeta, target, source);
472 return true;
473 }
474 if (type.canConstructValueType()) {
475 if (fromMatchingType(targetMetaObject: targetMeta, source, allocate&: destruct))
476 return true;
477 warn();
478
479 }
480 } else if (type.canConstructValueType()) {
481 if (fromMatchingType(targetMetaObject: targetMeta, source, allocate&: destruct))
482 return true;
483 warn();
484 }
485 }
486
487 if (const auto valueTypeFunction = type.createValueTypeFunction()) {
488 const QVariant result
489 = valueTypeFunction(QJSValuePrivate::fromReturnedValue(d: source.asReturnedValue()));
490 if (result.metaType() == targetMetaType) {
491 targetMetaType.construct(where: destruct(), copy: result.constData());
492 return true;
493 }
494 }
495
496 return false;
497}
498
499bool QQmlValueTypeProvider::createValueType(
500 QMetaType targetMetaType, void *target, QMetaType sourceMetaType, void *source)
501{
502 if (sourceMetaType == QMetaType::fromType<QJSValue>()) {
503 const QJSValue *val = static_cast<const QJSValue *>(source);
504 return createValueType(
505 targetMetaType, target, source: QV4::Value(QJSValuePrivate::asReturnedValue(jsval: val)));
506 }
507
508 if (!isConstructibleMetaType(metaType: targetMetaType))
509 return false;
510
511 auto destruct = [targetMetaType, target]() {
512 targetMetaType.destruct(data: target);
513 return target;
514 };
515
516 const QQmlType type = QQmlMetaType::qmlType(metaType: targetMetaType);
517 if (const QMetaObject *targetMetaObject = QQmlMetaType::metaObjectForValueType(qmlType: type)) {
518 const auto warn = [&]() {
519 qWarning().noquote()
520 << "Could not find any constructor for value type"
521 << targetMetaObject->className() << "to call with value" << source;
522 };
523
524 if (type.canPopulateValueType()) {
525
526 if (const QMetaObject *sourceMetaObject
527 = QQmlMetaType::metaObjectForValueType(type: sourceMetaType)) {
528 doWriteProperties(
529 targetMetaObject, target, sourceMetaObject,
530 read: [&source](const QMetaObject *sourceMetaObject, int sourceProperty) {
531 return sourceMetaObject->property(index: sourceProperty).readOnGadget(gadget: source);
532 });
533 return true;
534 }
535
536 if (sourceMetaType == QMetaType::fromType<QVariantMap>()) {
537 doWriteProperties(
538 targetMetaObject, target, source: *static_cast<const QVariantMap *>(source));
539 return true;
540 }
541
542 if (sourceMetaType == QMetaType::fromType<QVariantHash>()) {
543 doWriteProperties(
544 targetMetaObject, target, source: *static_cast<const QVariantHash *>(source));
545 return true;
546 }
547
548 if (sourceMetaType.flags() & QMetaType::PointerToQObject) {
549 doWriteProperties(targetMeta: targetMetaObject, target, source: *static_cast<QObject *const *>(source));
550 return true;
551 }
552 }
553
554 if (type.canConstructValueType()) {
555 if (fromMatchingType(targetMetaObject, allocate&: destruct, retrieve: [&](QMetaType, auto callback) {
556 return callback(sourceMetaType, source);
557 })) {
558 return true;
559 }
560 warn();
561 }
562 }
563
564 return false;
565}
566
567QVariant QQmlValueTypeProvider::constructValueType(
568 QMetaType resultMetaType, const QMetaObject *resultMetaObject,
569 int ctorIndex, void *ctorArg)
570{
571 QVariant result;
572 fromVerifiedType(targetMetaObject: resultMetaObject, ctorIndex, source: ctorArg,
573 allocate: [&]() { return createVariantData(type: resultMetaType, variant: &result); });
574 return result;
575}
576
577static QVariant fromJSValue(const QQmlType &type, const QJSValue &s, QMetaType metaType)
578{
579 if (const auto valueTypeFunction = type.createValueTypeFunction()) {
580 const QVariant result = valueTypeFunction(s);
581 if (result.metaType() == metaType)
582 return result;
583 }
584
585 return QVariant();
586}
587
588QVariant QQmlValueTypeProvider::createValueType(const QJSValue &s, QMetaType metaType)
589{
590 if (!isConstructibleMetaType(metaType))
591 return QVariant();
592 return fromJSValue(type: QQmlMetaType::qmlType(metaType), s, metaType);
593}
594
595QVariant QQmlValueTypeProvider::createValueType(const QString &s, QMetaType metaType)
596{
597 if (!isConstructibleMetaType(metaType))
598 return QVariant();
599 const QQmlType type = QQmlMetaType::qmlType(metaType);
600 const QMetaObject *mo = QQmlMetaType::metaObjectForValueType(qmlType: type);
601 if (mo && type.canConstructValueType()) {
602 QVariant result;
603 if (fromString(mo, s, allocate: [&]() { return createVariantData(type: metaType, variant: &result); }))
604 return result;
605 }
606
607 return fromJSValue(type, s, metaType);
608}
609
610QVariant QQmlValueTypeProvider::createValueType(const QV4::Value &s, QMetaType metaType)
611{
612 if (!isConstructibleMetaType(metaType))
613 return QVariant();
614 const QQmlType type = QQmlMetaType::qmlType(metaType);
615 if (const QMetaObject *mo = QQmlMetaType::metaObjectForValueType(qmlType: type)) {
616 const auto warn = [&]() {
617 qWarning().noquote()
618 << "Could not find any constructor for value type"
619 << mo->className() << "to call with value" << s.toQStringNoThrow();
620 };
621
622 if (type.canPopulateValueType()) {
623 QVariant result = byProperties(targetMetaObject: mo, metaType, source: s);
624 if (result.isValid())
625 return result;
626 if (type.canConstructValueType()) {
627 if (fromMatchingType(targetMetaObject: mo, source: s, allocate: [&]() { return createVariantData(type: metaType, variant: &result); }))
628 return result;
629 warn();
630 }
631 } else if (type.canConstructValueType()) {
632 QVariant result;
633 if (fromMatchingType(targetMetaObject: mo, source: s, allocate: [&]() { return createVariantData(type: metaType, variant: &result); }))
634 return result;
635 warn();
636 }
637 }
638
639 return fromJSValue(type, s: QJSValuePrivate::fromReturnedValue(d: s.asReturnedValue()), metaType);
640
641}
642
643/*!
644 * \internal
645 * This should only be called with either builtin types or wrapped QJSValues as source.
646 */
647QVariant QQmlValueTypeProvider::createValueType(const QVariant &s, QMetaType metaType)
648{
649 if (!isConstructibleMetaType(metaType))
650 return QVariant();
651 const QQmlType type = QQmlMetaType::qmlType(metaType);
652 if (const QMetaObject *mo = QQmlMetaType::metaObjectForValueType(qmlType: type)) {
653 const auto warn = [&]() {
654 qWarning().noquote()
655 << "Could not find any constructor for value type"
656 << mo->className() << "to call with value" << s;
657 };
658
659 if (type.canPopulateValueType()) {
660 QVariant result = byProperties(targetMetaObject: mo, targetMetaType: metaType, source: s);
661 if (result.isValid())
662 return result;
663 if (type.canConstructValueType()) {
664 if (fromMatchingType(targetMetaObject: mo, source: s, allocate: [&]() { return createVariantData(type: metaType, variant: &result); }))
665 return result;
666 warn();
667 }
668 } else if (type.canConstructValueType()) {
669 QVariant result;
670 if (fromMatchingType(targetMetaObject: mo, source: s, allocate: [&]() { return createVariantData(type: metaType, variant: &result); }))
671 return result;
672 warn();
673 }
674 }
675
676 return QVariant();
677}
678
679QQmlColorProvider::~QQmlColorProvider() {}
680QVariant QQmlColorProvider::colorFromString(const QString &, bool *ok) { if (ok) *ok = false; return QVariant(); }
681unsigned QQmlColorProvider::rgbaFromString(const QString &, bool *ok) { if (ok) *ok = false; return 0; }
682QVariant QQmlColorProvider::fromRgbF(double, double, double, double) { return QVariant(); }
683QVariant QQmlColorProvider::fromHslF(double, double, double, double) { return QVariant(); }
684QVariant QQmlColorProvider::fromHsvF(double, double, double, double) { return QVariant(); }
685QVariant QQmlColorProvider::lighter(const QVariant &, qreal) { return QVariant(); }
686QVariant QQmlColorProvider::darker(const QVariant &, qreal) { return QVariant(); }
687QVariant QQmlColorProvider::alpha(const QVariant &, qreal)
688{
689 return QVariant();
690}
691QVariant QQmlColorProvider::tint(const QVariant &, const QVariant &) { return QVariant(); }
692
693static QQmlColorProvider *colorProvider = nullptr;
694
695Q_QML_PRIVATE_EXPORT QQmlColorProvider *QQml_setColorProvider(QQmlColorProvider *newProvider)
696{
697 QQmlColorProvider *old = colorProvider;
698 colorProvider = newProvider;
699 return old;
700}
701
702static QQmlColorProvider **getColorProvider(void)
703{
704 if (colorProvider == nullptr) {
705 qWarning() << "Warning: QQml_colorProvider: no color provider has been set!";
706 static QQmlColorProvider nullColorProvider;
707 colorProvider = &nullColorProvider;
708 }
709
710 return &colorProvider;
711}
712
713Q_AUTOTEST_EXPORT QQmlColorProvider *QQml_colorProvider(void)
714{
715 static QQmlColorProvider **providerPtr = getColorProvider();
716 return *providerPtr;
717}
718
719
720QQmlGuiProvider::~QQmlGuiProvider() {}
721QQmlApplication *QQmlGuiProvider::application(QObject *parent)
722{
723 return new QQmlApplication(parent);
724}
725QStringList QQmlGuiProvider::fontFamilies() { return QStringList(); }
726bool QQmlGuiProvider::openUrlExternally(const QUrl &) { return false; }
727
728QObject *QQmlGuiProvider::inputMethod()
729{
730 // We don't have any input method code by default
731 QObject *o = new QObject();
732 o->setObjectName(QStringLiteral("No inputMethod available"));
733 QQmlEngine::setObjectOwnership(o, QQmlEngine::JavaScriptOwnership);
734 return o;
735}
736
737QObject *QQmlGuiProvider::styleHints()
738{
739 QObject *o = new QObject();
740 o->setObjectName(QStringLiteral("No styleHints available"));
741 QQmlEngine::setObjectOwnership(o, QQmlEngine::JavaScriptOwnership);
742 return o;
743}
744
745QString QQmlGuiProvider::pluginName() const { return QString(); }
746
747static QQmlGuiProvider *guiProvider = nullptr;
748
749Q_QML_PRIVATE_EXPORT QQmlGuiProvider *QQml_setGuiProvider(QQmlGuiProvider *newProvider)
750{
751 QQmlGuiProvider *old = guiProvider;
752 guiProvider = newProvider;
753 return old;
754}
755
756static QQmlGuiProvider **getGuiProvider(void)
757{
758 if (guiProvider == nullptr) {
759 static QQmlGuiProvider nullGuiProvider; //Still provides an application with no GUI support
760 guiProvider = &nullGuiProvider;
761 }
762
763 return &guiProvider;
764}
765
766Q_AUTOTEST_EXPORT QQmlGuiProvider *QQml_guiProvider(void)
767{
768 static QQmlGuiProvider **providerPtr = getGuiProvider();
769 return *providerPtr;
770}
771
772//Docs in qqmlengine.cpp
773QQmlApplication::QQmlApplication(QObject *parent)
774 : QObject(*(new QQmlApplicationPrivate),parent)
775{
776 connect(sender: QCoreApplication::instance(), SIGNAL(aboutToQuit()),
777 receiver: this, SIGNAL(aboutToQuit()));
778 connect(sender: QCoreApplication::instance(), SIGNAL(applicationNameChanged()),
779 receiver: this, SIGNAL(nameChanged()));
780 connect(sender: QCoreApplication::instance(), SIGNAL(applicationVersionChanged()),
781 receiver: this, SIGNAL(versionChanged()));
782 connect(sender: QCoreApplication::instance(), SIGNAL(organizationNameChanged()),
783 receiver: this, SIGNAL(organizationChanged()));
784 connect(sender: QCoreApplication::instance(), SIGNAL(organizationDomainChanged()),
785 receiver: this, SIGNAL(domainChanged()));
786}
787
788QQmlApplication::QQmlApplication(QQmlApplicationPrivate &dd, QObject *parent)
789 : QObject(dd, parent)
790{
791 connect(sender: QCoreApplication::instance(), SIGNAL(aboutToQuit()),
792 receiver: this, SIGNAL(aboutToQuit()));
793 connect(sender: QCoreApplication::instance(), SIGNAL(applicationNameChanged()),
794 receiver: this, SIGNAL(nameChanged()));
795 connect(sender: QCoreApplication::instance(), SIGNAL(applicationVersionChanged()),
796 receiver: this, SIGNAL(versionChanged()));
797 connect(sender: QCoreApplication::instance(), SIGNAL(organizationNameChanged()),
798 receiver: this, SIGNAL(organizationChanged()));
799 connect(sender: QCoreApplication::instance(), SIGNAL(organizationDomainChanged()),
800 receiver: this, SIGNAL(domainChanged()));
801}
802
803QStringList QQmlApplication::args()
804{
805 Q_D(QQmlApplication);
806 if (!d->argsInit) {
807 d->argsInit = true;
808 d->args = QCoreApplication::arguments();
809 }
810 return d->args;
811}
812
813QString QQmlApplication::name() const
814{
815 return QCoreApplication::instance()->applicationName();
816}
817
818QString QQmlApplication::version() const
819{
820 return QCoreApplication::instance()->applicationVersion();
821}
822
823QString QQmlApplication::organization() const
824{
825 return QCoreApplication::instance()->organizationName();
826}
827
828QString QQmlApplication::domain() const
829{
830 return QCoreApplication::instance()->organizationDomain();
831}
832
833void QQmlApplication::setName(const QString &arg)
834{
835 QCoreApplication::instance()->setApplicationName(arg);
836}
837
838void QQmlApplication::setVersion(const QString &arg)
839{
840 QCoreApplication::instance()->setApplicationVersion(arg);
841}
842
843void QQmlApplication::setOrganization(const QString &arg)
844{
845 QCoreApplication::instance()->setOrganizationName(arg);
846}
847
848void QQmlApplication::setDomain(const QString &arg)
849{
850 QCoreApplication::instance()->setOrganizationDomain(arg);
851}
852
853bool qmlobject_can_cast(QObject *object, const QMetaObject *mo)
854{
855 Q_ASSERT(object);
856 Q_ASSERT(mo);
857 auto ddata = QQmlData::get(object, create: false);
858 if (!ddata || ! ddata->propertyCache)
859 return object->metaObject()->inherits(metaObject: mo);
860 return ddata->propertyCache->firstCppMetaObject()->inherits(metaObject: mo);
861}
862
863QT_END_NAMESPACE
864
865#include "moc_qqmlglobal_p.cpp"
866

source code of qtdeclarative/src/qml/qml/qqmlglobal.cpp