8 #include <QDBusArgument>
9 #include <QDBusVariant>
10 #include <QDataStream>
30 int qMetaTypeId_CVariantList = -1;
32 private_ns::IValueObjectMetaInfo *private_ns::getValueObjectMetaInfo(
int typeId)
34 return getValueObjectMetaInfo(QVariant(QMetaType(typeId),
nullptr));
37 private_ns::IValueObjectMetaInfo *private_ns::getValueObjectMetaInfo(
const QVariant &v)
39 return v.value<IValueObjectMetaInfo *>();
44 if (m_v.canConvert(typeId)) {
return true; }
45 if (typeId == qMetaTypeId_CVariantList)
47 return m_v.canConvert<QVector<CVariant>>() || m_v.canConvert<QVariantList>();
49 if (
userType() == qMetaTypeId_CVariantList)
51 return QVariant::fromValue(QVector<CVariant>()).canConvert(typeId) ||
52 QVariant(QMetaType(typeId),
nullptr).canConvert<QVariantList>();
59 if (!m_v.canConvert(typeId))
62 if (typeId == qMetaTypeId_CVariantList)
64 if (m_v.canConvert<QVector<CVariant>>())
66 if (!m_v.convert(qMetaTypeId<QVector<CVariant>>())) {
return false; }
68 else if (m_v.canConvert<QVariantList>())
70 QVector<CVariant> vec;
71 const auto seqit = m_v.value<QSequentialIterable>();
72 vec.reserve(seqit.size());
73 for (
auto it = seqit.begin(); it != seqit.end(); ++it) { vec.push_back(*it); }
76 else {
return false; }
78 if (
userType() == qMetaTypeId_CVariantList)
80 if (QVariant::fromValue(QVector<CVariant>()).canConvert(typeId))
82 if (!m_v.convert(qMetaTypeId<QVector<CVariant>>())) {
return false; }
84 else {
return false; }
87 return m_v.convert(typeId);
90 bool CVariant::isVariantList()
const {
return userType() == qMetaTypeId_CVariantList; }
94 auto *meta = getValueObjectMetaInfo();
95 if (meta) {
return meta->toQString(data(), i18n); }
96 return m_v.toString();
103 case QMetaType::Bool:
104 case QMetaType::Char:
105 case QMetaType::UChar:
106 case QMetaType::SChar:
107 case QMetaType::Short:
108 case QMetaType::UShort:
110 case QMetaType::UInt:
111 case QMetaType::Long:
112 case QMetaType::ULong:
113 case QMetaType::LongLong:
114 case QMetaType::ULongLong:
return true;
115 default:
return false;
126 if (this->
type() == QMetaType::LongLong) {
return this->
toLongLong(ok); }
127 return this->
toInt(ok);
130 int CVariant::compareImpl(
const CVariant &a,
const CVariant &b)
132 if (a.userType() < b.userType()) {
return -1; }
133 if (a.userType() > b.userType()) {
return 1; }
134 auto *aMeta = a.getValueObjectMetaInfo();
135 auto *bMeta = b.getValueObjectMetaInfo();
140 const void *casted =
nullptr;
141 if (casted = aMeta->upCastTo(a.data(), bMeta->getMetaTypeId()); casted)
143 return bMeta->compareImpl(casted, b.data());
145 if (casted = bMeta->upCastTo(b.data(), aMeta->getMetaTypeId()); casted)
147 return aMeta->compareImpl(a.data(), casted);
149 CLogMessage(&a).warning(
150 u
"Comparing two CVariants containing unrelated value objects: %1 (%2) and %3 (%4)")
151 << a.typeName() << a.userType() << b.typeName() << b.userType();
154 catch (
const private_ns::CVariantException &ex)
156 CLogMessage(&a).debug() << ex.what();
160 const QPartialOrdering order = QVariant::compare(a.m_v, b.m_v);
161 if (order == QPartialOrdering::Less) {
return -1; }
162 if (order == QPartialOrdering::Greater) {
return 1; }
169 json.insert(
"type", this->
typeName());
173 case QVariant::Invalid: json.insert(
"value", 0);
break;
174 case QVariant::Int: json.insert(
"value", m_v.toInt());
break;
175 case QVariant::UInt: json.insert(
"value", m_v.toInt());
break;
176 case QVariant::Bool: json.insert(
"value", m_v.toBool());
break;
177 case QVariant::Double: json.insert(
"value", m_v.toDouble());
break;
178 case QVariant::LongLong: json.insert(
"value", m_v.toLongLong());
break;
179 case QVariant::ULongLong: json.insert(
"value", m_v.toLongLong());
break;
180 case QVariant::String: json.insert(
"value", m_v.toString());
break;
181 case QVariant::Char: json.insert(
"value", m_v.toString());
break;
182 case QVariant::ByteArray: json.insert(
"value", m_v.toString());
break;
183 case QVariant::DateTime: json.insert(
"value", m_v.toDateTime().toString(Qt::ISODate));
break;
184 case QVariant::Date: json.insert(
"value", m_v.toDate().toString(Qt::ISODate));
break;
185 case QVariant::Time: json.insert(
"value", m_v.toTime().toString(Qt::ISODate));
break;
186 case QVariant::StringList: json.insert(
"value", QJsonArray::fromStringList(m_v.toStringList()));
break;
190 auto *meta = getValueObjectMetaInfo();
191 if (meta) { json.insert(
"value", meta->toJson(data())); }
192 else if (m_v.canConvert<QString>()) { json.insert(
"value", m_v.toString()); }
195 CLogMessage(
this).warning(u
"Unsupported CVariant type for toJson: %1 (%2)")
199 catch (
const private_ns::CVariantException &ex)
201 CLogMessage(
this).debug() << ex.what();
209 QJsonDocument jsonDoc(
toJson());
210 return jsonDoc.toJson(format);
217 const QJsonValue typeValue = json.value(
"type");
218 if (typeValue.isUndefined()) {
throw CJsonException(
"Missing 'type'"); }
219 const QString
typeName = typeValue.toString();
225 const int typeId = QMetaType::type(qPrintable(
typeName));
227 const QJsonValue
value = json.value(
"value");
228 if (
value.isUndefined()) {
throw CJsonException(
"Missing 'value'"); }
231 case QVariant::Invalid:
throw CJsonException(
"Type not recognized by QMetaType");
232 case QVariant::Int: m_v.setValue(
value.toInt());
break;
233 case QVariant::UInt: m_v.setValue<uint>(
static_cast<uint
>(
value.toInt()));
break;
234 case QVariant::Bool: m_v.setValue(
value.toBool());
break;
235 case QVariant::Double: m_v.setValue(
value.toDouble());
break;
236 case QVariant::LongLong: m_v.setValue(
static_cast<qlonglong
>(
value.toDouble()));
break;
237 case QVariant::ULongLong: m_v.setValue(
static_cast<qulonglong
>(
value.toDouble()));
break;
238 case QVariant::String: m_v.setValue(
value.toString());
break;
239 case QVariant::Char: m_v.setValue(
value.toString().size() > 0 ?
value.toString().at(0) :
'\0');
break;
240 case QVariant::ByteArray: m_v.setValue(
value.toString().toLatin1());
break;
241 case QVariant::DateTime: m_v.setValue(
fromStringUtc(
value.toString(), Qt::ISODate));
break;
242 case QVariant::Date: m_v.setValue(QDate::fromString(
value.toString(), Qt::ISODate));
break;
243 case QVariant::Time: m_v.setValue(QTime::fromString(
value.toString(), Qt::ISODate));
break;
244 case QVariant::StringList: m_v.setValue(QVariant(
value.toArray().toVariantList()).toStringList());
break;
248 auto *meta = private_ns::getValueObjectMetaInfo(typeId);
251 CJsonScope scope(
"value");
253 m_v = QVariant(QMetaType(typeId),
nullptr);
256 meta->convertFromMemoizedJson(
value.toObject(), data(),
true);
258 else if (QMetaType::hasRegisteredConverterFunction(QMetaType(qMetaTypeId<QString>()),
261 m_v.setValue(
value.toString());
262 if (!m_v.convert(typeId)) {
throw CJsonException(
"Failed to convert from JSON string"); }
264 else {
throw CJsonException(
"Type not supported by convertFromJson"); }
266 catch (
const private_ns::CVariantException &ex)
268 throw CJsonException(ex.what());
274 const QString &prefix)
280 catch (
const CJsonException &ex)
289 auto *meta = getValueObjectMetaInfo();
295 json.insert(
"type", this->
typeName());
296 json.insert(
"value", meta->toMemoizedJson(data()));
299 catch (
const private_ns::CVariantException &ex)
301 CLogMessage(
this).debug() << ex.what();
310 QJsonValue typeValue = json.value(
"type");
311 if (typeValue.isUndefined()) {
throw CJsonException(
"Missing 'type'"); }
312 QString
typeName = typeValue.toString();
318 int typeId = QMetaType::type(qPrintable(
typeName));
320 auto *meta = private_ns::getValueObjectMetaInfo(typeId);
325 QJsonValue
value = json.value(
"value");
326 if (
value.isUndefined()) {
throw CJsonException(
"Missing 'value'"); }
328 CJsonScope scope(
"value");
329 m_v = QVariant(QMetaType(typeId),
nullptr);
330 meta->convertFromMemoizedJson(
value.toObject(), data(), allowFallbackToJson);
332 catch (
const private_ns::CVariantException &ex)
334 throw CJsonException(ex.what());
341 const QString &prefix)
347 catch (
const CJsonException &ex)
354 size_t CVariant::getValueHash()
const
358 case QVariant::Invalid:
return 0;
359 case QVariant::Int:
return qHash(m_v.toInt());
360 case QVariant::UInt:
return qHash(m_v.toUInt());
361 case QVariant::Bool:
return qHash(m_v.toUInt());
362 case QVariant::Double:
return qHash(m_v.toUInt());
363 case QVariant::LongLong:
return qHash(m_v.toLongLong());
364 case QVariant::ULongLong:
return qHash(m_v.toULongLong());
365 case QVariant::String:
return qHash(m_v.toString());
366 case QVariant::Char:
return qHash(m_v.toChar());
367 case QVariant::ByteArray:
return qHash(m_v.toByteArray());
371 auto *meta = getValueObjectMetaInfo();
372 if (meta) {
return meta->getValueHash(data()); }
373 else if (m_v.canConvert<QString>()) {
return qHash(m_v.toString()); }
376 CLogMessage(
this).warning(u
"Unsupported CVariant type for getValueHash: %1 (%2)")
381 catch (
const private_ns::CVariantException &ex)
383 CLogMessage(
this).debug() << ex.what();
392 else { arg << QString() << QDBusVariant(QVariant(0)); }
400 QVariant fixQVariantFromDbusArgument(
const QVariant &variant,
int localUserType,
const QString &typeName);
401 QVariant complexQtTypeFromDbusArgument(
const QDBusArgument &argument,
int type);
407 QDBusVariant dbusVar;
413 *
this = fixQVariantFromDbusArgument(dbusVar.variant(), QMetaType::type(qPrintable(
typeName)),
typeName);
423 auto *meta = getValueObjectMetaInfo();
427 meta->setPropertyByIndex(data(), variant, index);
429 catch (
const private_ns::CVariantException &ex)
431 CLogMessage(
this).debug() << ex.what();
437 auto *meta = getValueObjectMetaInfo();
442 meta->propertyByIndex(data(), result, index);
445 catch (
const private_ns::CVariantException &ex)
447 CLogMessage(
this).debug() << ex.what();
454 auto *meta = getValueObjectMetaInfo();
458 return meta->equalsPropertyByIndex(data(), compareValue, index);
460 catch (
const private_ns::CVariantException &ex)
462 CLogMessage(
this).debug() << ex.what();
469 auto *meta = getValueObjectMetaInfo();
470 if (!meta) {
return {}; }
475 catch (
const private_ns::CVariantException &ex)
477 CLogMessage(
this).debug() << ex.what();
478 return CIcons::StandardIconError16;
484 if (m_v.type() == QVariant::Pixmap) {
return m_v.value<QPixmap>(); }
485 if (m_v.type() == QVariant::Image) {
return QPixmap::fromImage(m_v.value<QImage>()); }
486 if (m_v.type() == QVariant::Icon) {
return iconToPixmap(m_v.value<QIcon>()); }
488 return CIcon(
toIcon()).toPixmap();
499 if (metaTypeId == QMetaType::UnknownType) {
return false; }
506 if (!
isValid()) {
return false; }
507 auto *meta = getValueObjectMetaInfo();
510 CLogMessage(
this).warning(u
"Invalid type for CVariant::matches: %1") <<
typeName();
515 return meta->matches(data(),
value);
517 catch (
const private_ns::CVariantException &ex)
519 CLogMessage(
this).debug() << ex.what();
524 QVariant fixQVariantFromDbusArgument(
const QVariant &variant,
int localUserType,
const QString &typeName)
526 if (localUserType ==
static_cast<int>(QVariant::Invalid))
528 CLogMessage(&variant).warning(u
"Invalid type for unmarshall: %1") << typeName;
532 if (!variant.canConvert<QDBusArgument>()) {
return variant; }
536 const QDBusArgument arg = variant.value<QDBusArgument>();
537 constexpr
int userType =
static_cast<int>(QVariant::UserType);
538 if (localUserType < userType)
541 return complexQtTypeFromDbusArgument(arg, localUserType);
543 else if (QMetaType(localUserType).flags() & QMetaType::IsEnumeration)
545 arg.beginStructure();
550 QVariant valueVariant = QVariant::fromValue(i);
551 bool ok = valueVariant.convert(localUserType);
552 Q_ASSERT_X(ok, Q_FUNC_INFO,
"int could not be converted to enum");
558 QVariant valueVariant(QMetaType(localUserType),
nullptr);
559 auto *meta = private_ns::getValueObjectMetaInfo(valueVariant);
562 meta->unmarshall(arg, valueVariant.data());
565 Q_ASSERT_X(
false, Q_FUNC_INFO,
"no meta");
570 QVariant complexQtTypeFromDbusArgument(
const QDBusArgument &argument,
int type)
576 case QMetaType::QDateTime:
580 return QVariant::fromValue(dt);
582 case QMetaType::QDate:
586 return QVariant::fromValue(date);
588 case QMetaType::QTime:
592 return QVariant::fromValue(time);
596 const char *name = QMetaType::typeName(type);
597 qFatal(
"Type cannot be resolved: %s (%d)", name ? name :
"", type);
IconIndex
Index for each icon, allows to send them via DBus, efficiently store them, etc.
Non-owning reference to a CPropertyIndex with a subset of its features.
static CStatusMessage fromJsonException(const CJsonException &ex, const CLogCategoryList &categories, const QString &prefix)
Object from JSON exception message.
friend size_t qHash(const CVariant &var)
qHash overload, needed for storing value in a QSet.
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
Set property by index.
void marshallToDbus(QDBusArgument &argument) const
Marshall without begin/endStructure, for when composed within another object.
CStatusMessage convertFromMemoizedJsonNoThrow(const QJsonObject &json, const CLogCategoryList &categories, const QString &prefix)
Call convertFromMemoizedJson, catch any CJsonException that is thrown and return it as CStatusMessage...
T value() const
Return the value converted to the type T.
bool isIntegral() const
True if this variant's type is an integral type.
QJsonObject toMemoizedJson() const
To compact JSON format.
CIcons::IconIndex toIcon() const
As icon, not implemented by all classes.
void unmarshalFromDataStream(QDataStream &stream)
Unmarshal a value from a QDataStream.
static void registerMetadata()
Register metadata.
qint64 toQInt64(bool *ok=nullptr) const
COnvert to qint64, which is used for all timestamps.
bool canConvert() const
True if this variant can be converted to the type T.
QString getClassName() const
Class name.
void convertFromMemoizedJson(const QJsonObject &json, bool allowFallbackToJson)
From compact JSON format.
void unmarshallFromDbus(const QDBusArgument &argument)
Unmarshall without begin/endStructure, for when composed within another object.
bool convert(int typeId)
Convert this variant to the type with the given metatype ID and return true if successful.
int userType() const
Return the metatype ID of the value in this variant.
bool isValid() const
True if this variant is valid.
void convertFromJson(const QJsonObject &json)
Assign from JSON object.
QVariant propertyByIndex(swift::misc::CPropertyIndexRef index) const
Property by index.
bool equalsPropertyByIndex(const CVariant &compareValue, CPropertyIndexRef index) const
Is given variant equal to value of property index?
const char * typeName() const
Return the typename of the value in this variant.
bool isArithmetic() const
True if this variant's type is an integral or floating-point type.
const QVariant & getQVariant() const
Return the internal QVariant.
bool matches(const CVariant &event) const
If this is an event subscription, return true if it matches the given event.
QMetaType::Type type() const
Return the metatype ID of the value in this variant, or QMetaType::User if it is a user type.
qlonglong toLongLong(bool *ok=nullptr) const
Convert this variant to a longlong integer.
void marshalToDataStream(QDataStream &stream) const
Marshal a value to a QDataStream.
CVariant()
Default constructor.
QString convertToQString(bool i18n=false) const
Cast as QString.
CStatusMessage convertFromJsonNoThrow(const QJsonObject &json, const CLogCategoryList &categories, const QString &prefix)
Call convertFromJson, catch any CJsonException that is thrown and return it as CStatusMessage.
int toInt(bool *ok=nullptr) const
Convert this variant to an integer.
QPixmap toPixmap() const
Corresponding pixmap.
int getMetaTypeId() const
Returns the Qt meta type ID of this object.
bool isA(int metaTypeId) const
Returns true if this object is an instance of the class with the given meta type ID,...
QJsonObject toJson() const
Cast to JSON object.
QString toJsonString(QJsonDocument::JsonFormat format=QJsonDocument::Indented) const
Convenience function JSON as string.
Free functions in swift::misc.
SWIFT_MISC_EXPORT QPixmap iconToPixmap(const QIcon &icon)
Icon to pixmap.
SWIFT_MISC_EXPORT QDateTime fromStringUtc(const QString &dateTimeString, const QString &format)
Same as QDateTime::fromString but QDateTime will be set to UTC.