24#include "customtyperegistry_p.h"
25#include "metaenumvariable_p.h"
27#include <QtCore/QDebug>
29#include <QAssociativeIterable>
32#include <QJsonDocument>
33#include <QSequentialIterable>
37Q_GLOBAL_STATIC(CustomTypeRegistry, customTypes)
39void Cutelee::MetaType::internalLock() {
return customTypes()->mutex.lock(); }
41void Cutelee::MetaType::internalUnlock()
43 return customTypes()->mutex.unlock();
46void Cutelee::MetaType::registerLookUpOperator(
int id, LookupFunction f)
51 customTypes()->registerLookupOperator(
id, f);
54static 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());
115static 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();
131static 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>() ||
220 object.canConvert<QVariantMap>()) {
222 auto iter =
object.value<QAssociativeIterable>();
224 if (property == QStringLiteral(
"size")
225 || property == QStringLiteral(
"count")) {
229 if (property == QStringLiteral(
"items")) {
230 auto it = iter.begin();
231 const auto end = iter.end();
233 for (; it != end; ++it) {
234 list.push_back(QVariantList{it.key(), it.value()});
239 if (property == QStringLiteral(
"keys")) {
240 auto it = iter.begin();
241 const auto end = iter.end();
243 for (; it != end; ++it) {
244 list.push_back(it.key());
249 if (property == QStringLiteral(
"values")) {
250 auto it = iter.begin();
251 const auto end = iter.end();
253 for (; it != end; ++it) {
254 list.push_back(it.value());
259 auto mappedValue = iter.value(property);
260 if (mappedValue.isValid())
265 auto mo = QMetaType(
object.userType()).metaObject();
267 QMetaType mt(
object.userType());
268 if (mt.flags().testFlag(QMetaType::IsGadget)) {
269 const auto idx = mo->indexOfProperty(property.toUtf8().constData());
271 const auto mp = mo->property(idx);
272 if (mp.isEnumType()) {
273 MetaEnumVariable mev(mp.enumerator(), mp.readOnGadget(
object.constData()).value<
int>());
274 return QVariant::fromValue(mev);
276 return mp.readOnGadget(
object.constData());
280 for (
auto i = 0; i < mo->enumeratorCount(); ++i) {
281 me = mo->enumerator(i);
283 if (QLatin1String(me.name()) == property) {
284 MetaEnumVariable mev(me);
285 return QVariant::fromValue(mev);
288 const auto value = me.keyToValue(property.toLatin1().constData());
294 MetaEnumVariable mev(me, value);
295 return QVariant::fromValue(mev);
300 return customTypes()->lookup(
object, property);
303bool Cutelee::MetaType::lookupAlreadyRegistered(
int id)
305 return customTypes()->lookupAlreadyRegistered(
id);
The Cutelee namespace holds all public Cutelee API.