swift
variant.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #ifndef SWIFT_MISC_VARIANT_H
7 #define SWIFT_MISC_VARIANT_H
8 
9 #include <algorithm>
10 #include <type_traits>
11 
12 #include <QDBusArgument>
13 #include <QDateTime>
14 #include <QJsonObject>
15 #include <QMetaType>
16 #include <QPixmap>
17 #include <QSequentialIterable>
18 #include <QString>
19 #include <QVariant>
20 #include <QtGlobal>
21 
22 #include "misc/icons.h"
23 #include "misc/inheritancetraits.h"
26 #include "misc/mixin/mixindbus.h"
27 #include "misc/mixin/mixinjson.h"
28 #include "misc/mixin/mixinstring.h"
29 #include "misc/range.h"
30 #include "misc/swiftmiscexport.h"
31 #include "misc/variantprivate.h"
32 
33 namespace swift::misc
34 {
35  class CIcon;
36  class CPropertyIndex;
37 
45  template <typename T>
47  {
48  if (QMetaType::hasRegisteredConverterFunction<T, private_ns::IValueObjectMetaInfo *>()) { return; }
49  bool ok = QMetaType::registerConverter<T, private_ns::IValueObjectMetaInfo *>(
50  private_ns::CValueObjectMetaInfo<T>::instance);
51  Q_ASSERT(ok);
52  Q_UNUSED(ok);
53  }
54 
60  public mixin::EqualsByCompare<CVariant>,
61  public mixin::LessThanByCompare<CVariant>,
62  public mixin::DBusOperators<CVariant>,
63  public mixin::DataStreamOperators<CVariant>,
64  public mixin::JsonOperators<CVariant>,
65  public mixin::String<CVariant>
66  {
67  template <typename>
68  struct tag
69  {};
70 
71  public:
73  CVariant() {}
74 
76  CVariant(const CVariant &) = default;
77 
79  CVariant(CVariant &&other) noexcept = default;
80 
82  CVariant(const QVariant &var) : m_v(var) {}
83 
85  CVariant(QVariant &&var) noexcept : m_v(std::move(var)) {}
86 
88  CVariant(QVariant::Type type) : m_v(type) {}
89 
91  CVariant(int) = delete;
92 
94  CVariant(const QString &string) : m_v(string) {}
95 
97  CVariant(const char *string) : m_v(string) {}
98 
100  CVariant(int typeId, const void *copy) : m_v(QMetaType(typeId), copy) {}
101 
103  friend size_t qHash(const CVariant &var) { return var.getValueHash(); }
104 
106  void reset(const QVariant &var) { m_v = var; }
107 
109  void reset(QVariant &&var) { m_v = std::move(var); }
110 
112  CVariant &operator=(const CVariant &other) = default;
113 
115  CVariant &operator=(CVariant &&other) noexcept = default;
116 
118  CVariant &operator=(const QVariant &var)
119  {
120  m_v = var;
121  return *this;
122  }
123 
125  CVariant &operator=(QVariant &&var) noexcept
126  {
127  m_v = std::move(var);
128  return *this;
129  }
130 
132  void swap(CVariant &other) noexcept { m_v.swap(other.m_v); }
133 
135  void swap(QVariant &other) noexcept { m_v.swap(other); }
136 
138  template <typename T>
139  static CVariant fromValue(T &&value)
140  {
141  static_assert(!std::is_same_v<CVariant, std::decay_t<T>>, "CVariant is an illegal type!");
142  return CVariant(QVariant::fromValue(std::forward<T>(value)));
143  }
144 
146  template <typename T>
147  static CVariant from(T &&value)
148  {
149  static_assert(!std::is_same_v<CVariant, std::decay_t<T>>, "CVariant is an illegal type!");
150  return CVariant(QVariant::fromValue(std::forward<T>(value)));
151  }
152 
154  template <typename T>
155  void setValue(T &&value)
156  {
157  m_v.setValue(std::forward<T>(value));
158  }
159 
161  template <typename T>
162  void set(T &&value)
163  {
164  m_v.setValue(std::forward<T>(value));
165  }
166 
168  template <typename T>
169  T value() const
170  {
171  return to(tag<T>());
172  }
173 
175  template <typename T>
176  T to() const
177  {
178  return to(tag<T>());
179  }
180 
184  template <typename T>
185  T valueOrDefault(T def) const
186  {
187  return canConvert<T>() ? value<T>() : def;
188  }
189 
191  const QVariant &getQVariant() const { return m_v; }
192 
194  operator const QVariant &() const { return m_v; }
195 
197  operator QVariant() && { return std::move(m_v); }
198 
200  bool canConvert(int typeId) const;
201 
203  template <typename T>
204  bool canConvert() const
205  {
206  return canConvert(qMetaTypeId<T>());
207  }
208 
210  bool convert(int typeId);
211 
213  QString convertToQString(bool i18n = false) const;
214 
216  bool isIntegral() const;
217 
219  bool isArithmetic() const;
220 
222  bool toBool() const { return m_v.toBool(); }
223 
225  int toInt(bool *ok = nullptr) const { return m_v.toInt(ok); }
226 
228  qlonglong toLongLong(bool *ok = nullptr) const { return m_v.toLongLong(ok); }
229 
231  qulonglong toULongLong(bool *ok = nullptr) const { return m_v.toULongLong(ok); }
232 
234  qint64 toQInt64(bool *ok = nullptr) const;
235 
237  double toDouble(bool *ok = nullptr) const { return m_v.toDouble(ok); }
238 
240  QDateTime toDateTime() const { return m_v.toDateTime(); }
241 
243  QUrl toUrl() const { return m_v.toUrl(); }
244 
246  void clear() { m_v.clear(); }
247 
249  bool isNull() const { return m_v.isNull(); }
250 
252  bool isValid() const { return m_v.isValid(); }
253 
255  QMetaType::Type type() const { return static_cast<QMetaType::Type>(m_v.type()); }
256 
258  const char *typeName() const { return m_v.typeName(); }
259 
261  int userType() const { return m_v.userType(); }
262 
264  QMetaType metaType() const { return QMetaType(userType()); }
265 
267  QJsonObject toJson() const;
268 
270  QString toJsonString(QJsonDocument::JsonFormat format = QJsonDocument::Indented) const;
271 
273  void convertFromJson(const QJsonObject &json);
274 
276  CStatusMessage convertFromJsonNoThrow(const QJsonObject &json, const CLogCategoryList &categories,
277  const QString &prefix);
278 
280  QJsonObject toMemoizedJson() const;
281 
283  void convertFromMemoizedJson(const QJsonObject &json, bool allowFallbackToJson);
284 
286  CStatusMessage convertFromMemoizedJsonNoThrow(const QJsonObject &json, const CLogCategoryList &categories,
287  const QString &prefix);
288 
290  void marshallToDbus(QDBusArgument &argument) const;
291 
293  void unmarshallFromDbus(const QDBusArgument &argument);
294 
296  void marshalToDataStream(QDataStream &stream) const;
297 
299  void unmarshalFromDataStream(QDataStream &stream);
300 
302  friend int compare(const CVariant &a, const CVariant &b) { return compareImpl(a, b); }
303 
305  void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant);
306 
309 
311  bool equalsPropertyByIndex(const CVariant &compareValue, CPropertyIndexRef index) const;
312 
314  QPixmap toPixmap() const;
315 
318 
320  static void registerMetadata();
321 
323  int getMetaTypeId() const;
324 
326  QString getClassName() const;
327 
329  bool isA(int metaTypeId) const;
330 
332  bool matches(const CVariant &event) const;
333 
334  private:
335  QVariant m_v;
336 
337  private_ns::IValueObjectMetaInfo *getValueObjectMetaInfo() const
338  {
339  return private_ns::getValueObjectMetaInfo(m_v);
340  }
341  void *data() { return m_v.data(); }
342  const void *data() const { return m_v.data(); }
343 
344  static int compareImpl(const CVariant &, const CVariant &);
345  size_t getValueHash() const;
346 
347  template <typename T>
348  T to(tag<T>) const
349  {
350  auto copy = *this;
351  copy.convert(qMetaTypeId<T>());
352  return *static_cast<const T *>(copy.data());
353  }
354  template <typename T>
355  QList<T> to(tag<QList<T>>) const
356  {
357  return toImpl<QList<T>>();
358  }
359  template <typename T>
360  CSequence<T> to(tag<CSequence<T>>) const
361  {
362  return toImpl<CSequence<T>>();
363  }
364  template <typename T>
365  T toImpl() const
366  {
367  using VT = typename T::value_type;
368  T result;
369  if (isVariantList())
370  {
371  for (const auto &v : m_v.value<QVector<CVariant>>()) { result.push_back(v.value<VT>()); }
372  }
373  else
374  {
375  for (const auto &v : m_v.value<QSequentialIterable>()) { result.push_back(v.value<VT>()); }
376  }
377  return result;
378  }
379  bool isVariantList() const;
380  };
381 } // namespace swift::misc
382 
383 Q_DECLARE_METATYPE(swift::misc::CVariant)
384 
385 namespace swift::misc::private_ns
386 {
388  template <typename T>
389  void MetaTypeHelper<T>::maybeRegisterMetaList()
390  {
391  if constexpr (canConvertVariantList<T>(0))
392  {
393  if (QMetaType::hasRegisteredConverterFunction(QMetaType(qMetaTypeId<T>()),
394  QMetaType(qMetaTypeId<QVector<CVariant>>())))
395  {
396  return;
397  }
398 
399  QMetaType::registerConverter<T, QVector<CVariant>>([](const T &list) -> QVector<CVariant> {
400  return list.transform([](const typename T::value_type &v) { return CVariant::from(v); });
401  });
402  QMetaType::registerConverter<QVector<CVariant>, T>([](const QVector<CVariant> &list) -> T {
403  return makeRange(list).transform([](const CVariant &v) { return v.to<typename T::value_type>(); });
404  });
405  }
406  }
408 } // namespace swift::misc::private_ns
409 
410 #endif // SWIFT_MISC_VARIANT_H
IconIndex
Index for each icon, allows to send them via DBus, efficiently store them, etc.
Definition: icons.h:32
A sequence of log categories.
Non-owning reference to a CPropertyIndex with a subset of its features.
Streamable status message, e.g.
Wrapper around QVariant which provides transparent access to CValueObject methods of the contained ob...
Definition: variant.h:66
CVariant(QVariant::Type type)
Construct a null variant of the given type.
Definition: variant.h:88
T to() const
Synonym for value().
Definition: variant.h:176
friend size_t qHash(const CVariant &var)
qHash overload, needed for storing value in a QSet.
Definition: variant.h:103
void reset(const QVariant &var)
Change the internal QVariant.
Definition: variant.h:106
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
Set property by index.
CVariant(QVariant &&var) noexcept
Move-construct from a QVariant.
Definition: variant.h:85
void setValue(T &&value)
Change the value.
Definition: variant.h:155
CVariant(const QVariant &var)
Construct from a QVariant.
Definition: variant.h:82
void marshallToDbus(QDBusArgument &argument) const
Marshall without begin/endStructure, for when composed within another object.
static CVariant fromValue(T &&value)
Construct a variant from a value.
Definition: variant.h:139
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.
Definition: variant.h:169
T valueOrDefault(T def) const
Returns the value converted to the type T, or a default if it can not be converted.
Definition: variant.h:185
bool isIntegral() const
True if this variant's type is an integral type.
double toDouble(bool *ok=nullptr) const
Convert this variant to double.
Definition: variant.h:237
QJsonObject toMemoizedJson() const
To compact JSON format.
CVariant & operator=(QVariant &&var) noexcept
Change the internal QVariant.
Definition: variant.h:125
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.
Definition: variant.h:204
QString getClassName() const
Class name.
CVariant & operator=(const CVariant &other)=default
Copy assignment operator.
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.
QMetaType metaType() const
Return the QMetaType of the type in this variant.
Definition: variant.h:264
bool convert(int typeId)
Convert this variant to the type with the given metatype ID and return true if successful.
void swap(QVariant &other) noexcept
Swap the internal QVariant with another.
Definition: variant.h:135
void set(T &&value)
Synonym for setValue().
Definition: variant.h:162
CVariant & operator=(const QVariant &var)
Change the internal QVariant.
Definition: variant.h:118
QUrl toUrl() const
Convert this variant to QUrl.
Definition: variant.h:243
int userType() const
Return the metatype ID of the value in this variant.
Definition: variant.h:261
CVariant(int typeId, const void *copy)
Construct a variant from the given type and opaque pointer.
Definition: variant.h:100
CVariant(int)=delete
Avoid unexpected implicit cast to QVariant::Type. (Use CVariant::from() instead.)
bool isValid() const
True if this variant is valid.
Definition: variant.h:252
bool toBool() const
Convert this variant to a bool.
Definition: variant.h:222
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?
qulonglong toULongLong(bool *ok=nullptr) const
Convert this variant to a unsigned longlong integer.
Definition: variant.h:231
QDateTime toDateTime() const
Convert this variant to QDateTime.
Definition: variant.h:240
const char * typeName() const
Return the typename of the value in this variant.
Definition: variant.h:258
void clear()
Set the variant to null.
Definition: variant.h:246
bool isArithmetic() const
True if this variant's type is an integral or floating-point type.
const QVariant & getQVariant() const
Return the internal QVariant.
Definition: variant.h:191
CVariant(const char *string)
Implicit conversion from C string.
Definition: variant.h:97
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.
Definition: variant.h:255
CVariant(CVariant &&other) noexcept=default
Move constructor.
friend int compare(const CVariant &a, const CVariant &b)
Return negative, zero, or positive if a is less than, equal to, or greater than b.
Definition: variant.h:302
qlonglong toLongLong(bool *ok=nullptr) const
Convert this variant to a longlong integer.
Definition: variant.h:228
CVariant & operator=(CVariant &&other) noexcept=default
Move assignment operatior.
void swap(CVariant &other) noexcept
Swap this variant with another.
Definition: variant.h:132
void reset(QVariant &&var)
Change the internal QVariant.
Definition: variant.h:109
void marshalToDataStream(QDataStream &stream) const
Marshal a value to a QDataStream.
static CVariant from(T &&value)
Synonym for fromValue().
Definition: variant.h:147
CVariant()
Default constructor.
Definition: variant.h:73
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.
Definition: variant.h:225
CVariant(const QString &string)
Implicit conversion from QString.
Definition: variant.h:94
QPixmap toPixmap() const
Corresponding pixmap.
bool isNull() const
True if this variant is null.
Definition: variant.h:249
bool canConvert(int typeId) const
True if this variant can be converted to the type with the given metatype ID.
int getMetaTypeId() const
Returns the Qt meta type ID of this object.
CVariant(const CVariant &)=default
Copy constructor.
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.
CRTP class template which will generate marshalling operators for a derived class with its own marsha...
Definition: mixindbus.h:39
CRTP class template to generate non-member QDataStream streaming operators.
CRTP class template from which a derived class can inherit operator== implemented using its compare f...
Definition: mixincompare.h:32
CRTP class template which will generate marshalling operators for a derived class with its own marsha...
Definition: mixinjson.h:37
CRTP class template from which a derived class can inherit operator< implemented using its compare fu...
Definition: mixincompare.h:116
CRTP class template from which a derived class can inherit string streaming operations.
Definition: mixinstring.h:31
Free functions in swift::misc.
auto makeRange(I begin, I2 end) -> CRange< I >
Returns a CRange constructed from begin and end iterators of deduced types.
Definition: range.h:316
void registerMetaValueType()
This registers the value type T with the swift::misc:: meta type system, making it available for use ...
Definition: variant.h:46
#define SWIFT_MISC_EXPORT
Export a class or function from the library.