24 #include "customtyperegistry_p.h"
25 #include "metaenumvariable_p.h"
27 #include <QtCore/QDebug>
29 #include <QAssociativeIterable>
31 #include <QJsonObject>
32 #include <QJsonDocument>
33 #include <QSequentialIterable>
37 Q_GLOBAL_STATIC(CustomTypeRegistry, customTypes)
39 void Cutelee::MetaType::internalLock() {
return customTypes()->mutex.lock(); }
41 void Cutelee::MetaType::internalUnlock()
43 return customTypes()->mutex.unlock();
46 void Cutelee::MetaType::registerLookUpOperator(
int id, LookupFunction f)
51 customTypes()->registerLookupOperator(
id, f);
54 static QVariant doQobjectLookUp(
const QObject *
const object,
59 if (property == QStringLiteral(
"children")) {
60 const auto childList =
object->children();
61 if (childList.isEmpty())
63 QVariantList children;
65 auto it = childList.constBegin();
66 const auto end = childList.constEnd();
67 for (; it != end; ++it)
68 children.append(QVariant::fromValue(*it));
72 if (property == QStringLiteral(
"objectName")) {
73 return object->objectName();
76 auto metaObj =
object->metaObject();
79 for (
auto i = 0; i < metaObj->propertyCount(); ++i) {
82 mp = metaObj->property(i);
84 if (QString::fromUtf8(mp.name()) != property)
87 if (mp.isEnumType()) {
88 MetaEnumVariable mev(mp.enumerator(), mp.read(
object).value<
int>());
89 return QVariant::fromValue(mev);
92 return mp.read(
object);
95 for (
auto i = 0; i < metaObj->enumeratorCount(); ++i) {
96 me = metaObj->enumerator(i);
98 if (QLatin1String(me.name()) == property) {
99 MetaEnumVariable mev(me);
100 return QVariant::fromValue(mev);
103 const auto value = me.keyToValue(property.toLatin1().constData());
108 const MetaEnumVariable mev(me, value);
110 return QVariant::fromValue(mev);
112 return object->property(property.toUtf8().constData());
115 static QVariant doJsonArrayLookUp(
const QJsonArray &list,
118 if (property == QLatin1String(
"count") || property == QLatin1String(
"size")) {
123 const int listIndex =
property.toInt(&ok);
124 if (!ok || listIndex >= list.size()) {
128 return list.at(listIndex).toVariant();
131 static QVariant doJsonObjectLookUp(
const QJsonObject &obj,
134 if (property == QLatin1String(
"count") || property == QLatin1String(
"size")) {
138 if (property == QLatin1String(
"items")) {
140 list.reserve(obj.size());
141 for (
auto it = obj.constBegin(); it != obj.constEnd(); ++it) {
142 list.push_back(QVariantList{it.key(), it.value().toVariant()});
147 if (property == QLatin1String(
"keys")) {
151 if (property == QLatin1String(
"values")) {
153 list.reserve(obj.size());
154 for (
auto it = obj.constBegin(); it != obj.constEnd(); ++it) {
155 list.push_back(it.value().toVariant());
160 return obj.value(property).toVariant();
166 if (
object.canConvert<QObject *>()) {
167 return doQobjectLookUp(
object.value<QObject *>(), property);
169 if (
object.userType() == QMetaType::QJsonDocument) {
170 const auto doc =
object.toJsonDocument();
171 if (doc.isObject()) {
172 return doJsonObjectLookUp(doc.object(), property);
175 return doJsonArrayLookUp(doc.array(), property);
179 if (
object.userType() == QMetaType::QJsonValue) {
180 const auto val =
object.toJsonValue();
182 switch (val.type()) {
183 case QJsonValue::Bool:
185 case QJsonValue::Double:
186 return val.toDouble();
187 case QJsonValue::String:
188 return val.toString();
189 case QJsonValue::Array:
190 return doJsonArrayLookUp(val.toArray(), property);
191 case QJsonValue::Object:
192 return doJsonObjectLookUp(val.toObject(), property);
197 if (
object.userType() == QMetaType::QJsonArray) {
198 return doJsonArrayLookUp(
object.toJsonArray(), property);
200 if (
object.userType() == QMetaType::QJsonObject) {
201 return doJsonObjectLookUp(
object.toJsonObject(), property);
203 if (
object.canConvert<QVariantList>()) {
204 auto iter =
object.value<QSequentialIterable>();
205 if (property == QStringLiteral(
"size")
206 ||
property == QStringLiteral(
"count")) {
211 const auto listIndex =
property.toInt(&ok);
213 if (!ok || listIndex >= iter.size()) {
217 return iter.at(listIndex);
219 if (
object.canConvert<QVariantHash>()) {
221 auto iter =
object.value<QAssociativeIterable>();
223 auto mappedValue = iter.value(property);
224 if (mappedValue.isValid())
227 if (property == QStringLiteral(
"size")
228 ||
property == QStringLiteral(
"count")) {
232 if (property == QStringLiteral(
"items")) {
233 auto it = iter.begin();
234 const auto end = iter.end();
236 for (; it != end; ++it) {
237 list.push_back(QVariantList{it.key(), it.value()});
242 if (property == QStringLiteral(
"keys")) {
243 auto it = iter.begin();
244 const auto end = iter.end();
246 for (; it != end; ++it) {
247 list.push_back(it.key());
252 if (property == QStringLiteral(
"values")) {
253 auto it = iter.begin();
254 const auto end = iter.end();
256 for (; it != end; ++it) {
257 list.push_back(it.value());
264 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
265 auto mo = QMetaType::metaObjectForType(
object.userType());
267 auto mo = QMetaType(
object.userType()).metaObject();
270 QMetaType mt(
object.userType());
271 if (mt.flags().testFlag(QMetaType::IsGadget)) {
272 const auto idx = mo->indexOfProperty(property.toUtf8().constData());
274 const auto mp = mo->property(idx);
275 if (mp.isEnumType()) {
276 MetaEnumVariable mev(mp.enumerator(), mp.readOnGadget(
object.constData()).value<
int>());
277 return QVariant::fromValue(mev);
279 return mp.readOnGadget(
object.constData());
283 for (
auto i = 0; i < mo->enumeratorCount(); ++i) {
284 me = mo->enumerator(i);
286 if (QLatin1String(me.name()) == property) {
287 MetaEnumVariable mev(me);
288 return QVariant::fromValue(mev);
291 const auto value = me.keyToValue(property.toLatin1().constData());
297 MetaEnumVariable mev(me, value);
298 return QVariant::fromValue(mev);
303 return customTypes()->lookup(
object, property);
306 bool Cutelee::MetaType::lookupAlreadyRegistered(
int id)
308 return customTypes()->lookupAlreadyRegistered(
id);
The Cutelee namespace holds all public Cutelee API.