Branch data Line data Source code
1 : : // Copyright (C) 2021 The Qt Company Ltd.
2 : : // Copyright (C) 2019 Luxoft Sweden AB
3 : : // Copyright (C) 2018 Pelagicore AG
4 : : // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5 : :
6 : : #include <qifqmlconversion_helper.h>
7 : :
8 : : #include <QtQml>
9 : : #include <private/qv4engine_p.h>
10 : : #include <private/qv4errorobject_p.h>
11 : : #include <private/qv4scopedvalue_p.h>
12 : :
13 : : QT_BEGIN_NAMESPACE
14 : :
15 : : using namespace Qt::StringLiterals;
16 : :
17 : 37 : void qtif_qmlOrCppWarning(const QObject *obj, const char *errorString)
18 : : {
19 [ + - ]: 74 : qtif_qmlOrCppWarning(obj, QLatin1String(errorString));
20 : 37 : }
21 : :
22 : 48 : void qtif_qmlOrCppWarning(const QObject *obj, const QString &errorString)
23 : : {
24 [ + + ]: 48 : if (!obj) {
25 [ + - ]: 8 : qWarning("%s", qPrintable(errorString));
26 : 4 : return;
27 : : }
28 : :
29 : : //If the object is not part of a javascript engine, print a normal warning
30 : 44 : QJSEngine *jsEngine = qjsEngine(obj);
31 [ + + ]: 44 : if (!jsEngine) {
32 [ + - ]: 78 : qWarning("%s", qPrintable(errorString));
33 : 39 : return;
34 : : }
35 : :
36 : : //Try to get more information about the current line of execution
37 : 5 : QV4::ExecutionEngine *v4 = jsEngine->handle();
38 : 5 : QV4::Scope scope(v4);
39 : 5 : QV4::Scoped<QV4::ErrorObject> error(scope);
40 : 5 : QV4::StackTrace trace = v4->stackTrace(1);
41 [ + - ]: 5 : if (!!error)
42 : 0 : trace = *error->d()->stackTrace;
43 : :
44 : : //If we don't have any information, let qmlWarning use its magic and find something
45 [ + - ]: 5 : if (trace.isEmpty()) {
46 : 5 : qmlWarning(obj) << errorString;
47 : 5 : return;
48 : : }
49 : :
50 : 0 : v4->throwError(errorString);
51 : 48 : }
52 : :
53 : : /*!
54 : : \relates QIfSimulationEngine
55 : :
56 : : Converts \a value from JSON to valid C++ types.
57 : :
58 : : The provided JSON value needs to follow the \l{IfSimulatorDataFormat}{IfSimulator Data
59 : : Format}.
60 : : */
61 : 340 : QVariant qtif_convertFromJSON(const QVariant &value)
62 : : {
63 [ + + + - ]: 340 : static const QString valueLiteral = u"value"_s;
64 [ + + + - ]: 340 : static const QString typeLiteral = u"type"_s;
65 : :
66 : 340 : QVariant val = value;
67 : : // First try to convert the values to a Map or a List
68 : : // This is needed as it could also store a QStringList or a Hash
69 [ + + ]: 340 : if (val.canConvert(QMetaType::fromType<QVariantMap>()))
70 : 58 : val.convert(QMetaType::fromType<QVariantMap>());
71 [ + + + + ]: 680 : if (val.metaType() != QMetaType::fromType<QString>() && val.canConvert(QMetaType::fromType<QVariantList>()))
72 : 57 : val.convert(QMetaType::fromType<QVariantList>());
73 : :
74 [ + + ]: 340 : if (val.metaType() == QMetaType::fromType<QVariantMap>()) {
75 : 58 : const QVariantMap map = val.toMap();
76 [ + + - + ]: 58 : if (map.contains(typeLiteral) && map.contains(valueLiteral)) {
77 : 78 : const QString type = map.value(typeLiteral).toString();
78 : 39 : const QVariant value = map.value(valueLiteral);
79 : :
80 [ + + ]: 39 : if (type == u"enum"_s) {
81 : 30 : QString enumValue = value.toString();
82 : 30 : const int lastIndex = int(enumValue.lastIndexOf(u"::"_s));
83 : 60 : const QString className = enumValue.left(lastIndex) + u"*"_s;
84 : 30 : QByteArray enumValueUtf8 = enumValue.right(enumValue.size() - lastIndex - 2).toUtf8();
85 [ + - ]: 60 : QMetaType metaType = QMetaType::fromName(className.toLatin1());
86 : 30 : const QMetaObject *mo = metaType.metaObject();
87 [ + + ]: 30 : if (Q_UNLIKELY(!mo)) {
88 : 1 : qWarning() << "Couldn't retrieve MetaObject for enum parsing:" << map;
89 : 2 : qWarning("Please make sure %s is registered in Qt's meta-type system: qRegisterMetaType<%s>()",
90 [ + - + - ]: 3 : qPrintable(className), qPrintable(className));
91 : 1 : return QVariant();
92 : : }
93 : :
94 [ + + ]: 55 : for (int i = mo->enumeratorOffset(); i < mo->enumeratorCount(); ++i) {
95 : 54 : QMetaEnum me = mo->enumerator(i);
96 : 54 : bool ok = false;
97 [ + - ]: 108 : int value = me.keysToValue(enumValueUtf8, &ok);
98 [ + + ]: 54 : if (ok) {
99 [ + - + - : 112 : return QVariant(QMetaType::fromName((QLatin1String(me.scope()) + u"::"_s + QLatin1String(me.enumName())).toLatin1()), &value);
+ - ]
100 : : }
101 : : }
102 : 1 : qWarning() << "Couldn't parse the enum definition" << map;
103 : 30 : return QVariant();
104 : 30 : } else {
105 [ + - ]: 18 : QMetaType metaType = QMetaType::fromName(type.toLatin1());
106 : 9 : const QMetaObject *mo = metaType.metaObject();
107 [ + + ]: 9 : if (Q_UNLIKELY(!mo)) {
108 : 1 : qWarning() << "Couldn't retrieve MetaObject for struct parsing:" << map;
109 : 2 : qWarning("Please make sure %s is registered in Qt's meta-type system: qRegisterMetaType<%s>()",
110 [ + - + - ]: 3 : qPrintable(type), qPrintable(type));
111 : 9 : return QVariant();
112 : : }
113 : :
114 : 8 : void *gadget = metaType.create();
115 [ - + ]: 16 : auto cleanup = qScopeGuard([gadget, metaType] { metaType.destroy(gadget); });
116 : :
117 [ - + ]: 8 : if (!Q_UNLIKELY(gadget)) {
118 [ # # ]: 0 : qWarning("Couldn't create a new instance of %s", metaType.name());
119 : 0 : return QVariant();
120 : : }
121 : :
122 : : /* Left here for debugging
123 : : for (int i = mo->methodOffset(); i < mo->methodCount(); ++i)
124 : : qDebug() << mo->method(i).methodSignature();
125 : : */
126 : :
127 : 8 : int moIdx = mo->indexOfMethod("fromJSON(QVariant)");
128 [ + + ]: 8 : if (Q_UNLIKELY(moIdx == -1)) {
129 [ + - ]: 2 : qWarning("Couldn't find method: %s::fromJSON(QVariant)\n"
130 : : "If your are using code created by the ifcodegen, please regenerate"
131 : : "your frontend code. See AUTOSUITE-1374 for why this is needed",
132 : : metaType.name());
133 : 1 : return QVariant();
134 : : }
135 : :
136 : 7 : mo->method(moIdx).invokeOnGadget(gadget, Q_ARG(QVariant, QVariant(value)));
137 : 7 : return QVariant(metaType, gadget);
138 : 8 : }
139 : 39 : }
140 : :
141 : 19 : QVariantMap convertedValues;
142 [ + - + - : 123 : for (auto i = map.constBegin(); i != map.constEnd(); ++i)
+ + ]
143 : 33 : convertedValues.insert(i.key(), qtif_convertFromJSON(i.value()));
144 : 19 : return convertedValues;
145 [ + + ]: 340 : } else if (val.metaType() == QMetaType::fromType<QVariantList>()) {
146 : 57 : QVariantList values = val.toList();
147 [ + + ]: 183 : for (auto i = values.begin(); i != values.end(); ++i)
148 : 126 : *i = qtif_convertFromJSON(*i);
149 : 57 : return values;
150 : 57 : }
151 : :
152 : 225 : return val;
153 : 340 : }
154 : :
155 : : QT_END_NAMESPACE
156 : :
157 : : #include "moc_qifqmlconversion_helper.cpp"
|