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(int) = delete;
89 
91  CVariant(const QString &string) : m_v(string) {}
92 
94  CVariant(const char *string) : m_v(string) {}
95 
97  CVariant(int typeId, const void *copy) : m_v(QMetaType(typeId), copy) {}
98 
100  friend size_t qHash(const CVariant &var) { return var.getValueHash(); }
101 
103  void reset(const QVariant &var) { m_v = var; }
104 
106  void reset(QVariant &&var) { m_v = std::move(var); }
107 
109  CVariant &operator=(const CVariant &other) = default;
110 
112  CVariant &operator=(CVariant &&other) noexcept = default;
113 
116  {
117  m_v = var;
118  return *this;
119  }
120 
122  CVariant &operator=(QVariant &&var) noexcept
123  {
124  m_v = std::move(var);
125  return *this;
126  }
127 
129  void swap(CVariant &other) noexcept { m_v.swap(other.m_v); }
130 
132  void swap(QVariant &other) noexcept { m_v.swap(other); }
133 
135  template <typename T>
136  static CVariant fromValue(T &&value)
137  {
138  static_assert(!std::is_same_v<CVariant, std::decay_t<T>>, "CVariant is an illegal type!");
139  return CVariant(QVariant::fromValue(std::forward<T>(value)));
140  }
141 
143  template <typename T>
144  static CVariant from(T &&value)
145  {
146  static_assert(!std::is_same_v<CVariant, std::decay_t<T>>, "CVariant is an illegal type!");
147  return CVariant(QVariant::fromValue(std::forward<T>(value)));
148  }
149 
151  template <typename T>
152  void setValue(T &&value)
153  {
154  m_v.setValue(std::forward<T>(value));
155  }
156 
158  template <typename T>
159  void set(T &&value)
160  {
161  m_v.setValue(std::forward<T>(value));
162  }
163 
165  template <typename T>
166  T value() const
167  {
168  return to(tag<T>());
169  }
170 
172  template <typename T>
173  T to() const
174  {
175  return to(tag<T>());
176  }
177 
181  template <typename T>
182  T valueOrDefault(T def) const
183  {
184  return canConvert<T>() ? value<T>() : def;
185  }
186 
188  const QVariant &getQVariant() const { return m_v; }
189 
191  operator const QVariant &() const { return m_v; }
192 
194  operator QVariant() && { return std::move(m_v); }
195 
197  bool canConvert(int typeId) const;
198 
200  template <typename T>
201  bool canConvert() const
202  {
203  return canConvert(qMetaTypeId<T>());
204  }
205 
207  bool convert(int typeId);
208 
210  QString convertToQString(bool i18n = false) const;
211 
213  bool isIntegral() const;
214 
216  bool isArithmetic() const;
217 
219  bool toBool() const { return m_v.toBool(); }
220 
222  int toInt(bool *ok = nullptr) const { return m_v.toInt(ok); }
223 
225  qlonglong toLongLong(bool *ok = nullptr) const { return m_v.toLongLong(ok); }
226 
228  qulonglong toULongLong(bool *ok = nullptr) const { return m_v.toULongLong(ok); }
229 
231  qint64 toQInt64(bool *ok = nullptr) const;
232 
234  double toDouble(bool *ok = nullptr) const { return m_v.toDouble(ok); }
235 
237  QDateTime toDateTime() const { return m_v.toDateTime(); }
238 
240  QUrl toUrl() const { return m_v.toUrl(); }
241 
243  void clear() { m_v.clear(); }
244 
246  bool isNull() const { return m_v.isNull(); }
247 
249  bool isValid() const { return m_v.isValid(); }
250 
253  {
254  const int type = m_v.typeId();
255  return type >= QMetaType::Type::User ? QMetaType::Type::User : static_cast<QMetaType::Type>(type);
256  }
257 
259  const char *typeName() const { return m_v.typeName(); }
260 
262  int userType() const { return m_v.userType(); }
263 
265  QMetaType metaType() const { return QMetaType(userType()); }
266 
269 
272 
274  void convertFromJson(const QJsonObject &json);
275 
278  const QString &prefix);
279 
282 
284  void convertFromMemoizedJson(const QJsonObject &json, bool allowFallbackToJson);
285 
288  const QString &prefix);
289 
291  void marshallToDbus(QDBusArgument &argument) const;
292 
294  void unmarshallFromDbus(const QDBusArgument &argument);
295 
297  void marshalToDataStream(QDataStream &stream) const;
298 
301 
303  friend int compare(const CVariant &a, const CVariant &b) { return compareImpl(a, b); }
304 
306  void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant);
307 
310 
312  bool equalsPropertyByIndex(const CVariant &compareValue, CPropertyIndexRef index) const;
313 
315  QPixmap toPixmap() const;
316 
319 
321  static void registerMetadata();
322 
324  int getMetaTypeId() const;
325 
328 
330  bool isA(int metaTypeId) const;
331 
333  bool matches(const CVariant &event) const;
334 
335  private:
336  QVariant m_v;
337 
338  private_ns::IValueObjectMetaInfo *getValueObjectMetaInfo() const
339  {
340  return private_ns::getValueObjectMetaInfo(m_v);
341  }
342  void *data() { return m_v.data(); }
343  const void *data() const { return m_v.data(); }
344 
345  static int compareImpl(const CVariant &, const CVariant &);
346  size_t getValueHash() const;
347 
348  template <typename T>
349  T to(tag<T>) const
350  {
351  auto copy = *this;
352  copy.convert(qMetaTypeId<T>());
353  return *static_cast<const T *>(copy.data());
354  }
355  template <typename T>
356  QList<T> to(tag<QList<T>>) const
357  {
358  return toImpl<QList<T>>();
359  }
360  template <typename T>
361  CSequence<T> to(tag<CSequence<T>>) const
362  {
363  return toImpl<CSequence<T>>();
364  }
365  template <typename T>
366  T toImpl() const
367  {
368  using VT = typename T::value_type;
369  T result;
370  if (isVariantList())
371  {
372  for (const auto &v : m_v.value<QVector<CVariant>>()) { result.push_back(v.value<VT>()); }
373  }
374  else
375  {
376  for (const auto &v : m_v.value<QSequentialIterable>()) { result.push_back(v.value<VT>()); }
377  }
378  return result;
379  }
380  bool isVariantList() const;
381  };
382 } // namespace swift::misc
383 
384 Q_DECLARE_METATYPE(swift::misc::CVariant)
385 
386 namespace swift::misc::private_ns
387 {
389  template <typename T>
390  void MetaTypeHelper<T>::maybeRegisterMetaList()
391  {
392  if constexpr (canConvertVariantList<T>(0))
393  {
395  QMetaType(qMetaTypeId<QVector<CVariant>>())))
396  {
397  return;
398  }
399 
400  QMetaType::registerConverter<T, QVector<CVariant>>([](const T &list) -> QVector<CVariant> {
401  return list.transform([](const typename T::value_type &v) { return CVariant::from(v); });
402  });
403  QMetaType::registerConverter<QVector<CVariant>, T>([](const QVector<CVariant> &list) -> T {
404  return makeRange(list).transform([](const CVariant &v) { return v.to<typename T::value_type>(); });
405  });
406  }
407  }
409 } // namespace swift::misc::private_ns
410 
411 #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
T to() const
Synonym for value().
Definition: variant.h:173
friend size_t qHash(const CVariant &var)
qHash overload, needed for storing value in a QSet.
Definition: variant.h:100
void reset(const QVariant &var)
Change the internal QVariant.
Definition: variant.h:103
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:152
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:136
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:166
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:182
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:234
QJsonObject toMemoizedJson() const
To compact JSON format.
CVariant & operator=(QVariant &&var) noexcept
Change the internal QVariant.
Definition: variant.h:122
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:201
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:265
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:132
void set(T &&value)
Synonym for setValue().
Definition: variant.h:159
CVariant & operator=(const QVariant &var)
Change the internal QVariant.
Definition: variant.h:115
QUrl toUrl() const
Convert this variant to QUrl.
Definition: variant.h:240
int userType() const
Return the metatype ID of the value in this variant.
Definition: variant.h:262
CVariant(int typeId, const void *copy)
Construct a variant from the given type and opaque pointer.
Definition: variant.h:97
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:249
bool toBool() const
Convert this variant to a bool.
Definition: variant.h:219
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:228
QDateTime toDateTime() const
Convert this variant to QDateTime.
Definition: variant.h:237
const char * typeName() const
Return the typename of the value in this variant.
Definition: variant.h:259
void clear()
Set the variant to null.
Definition: variant.h:243
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:188
CVariant(const char *string)
Implicit conversion from C string.
Definition: variant.h:94
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:252
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:303
qlonglong toLongLong(bool *ok=nullptr) const
Convert this variant to a longlong integer.
Definition: variant.h:225
CVariant & operator=(CVariant &&other) noexcept=default
Move assignment operatior.
void swap(CVariant &other) noexcept
Swap this variant with another.
Definition: variant.h:129
void reset(QVariant &&var)
Change the internal QVariant.
Definition: variant.h:106
void marshalToDataStream(QDataStream &stream) const
Marshal a value to a QDataStream.
static CVariant from(T &&value)
Synonym for fromValue().
Definition: variant.h:144
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:222
CVariant(const QString &string)
Implicit conversion from QString.
Definition: variant.h:91
QPixmap toPixmap() const
Corresponding pixmap.
bool isNull() const
True if this variant is null.
Definition: variant.h:246
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:29
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
void push_back(QList< T >::parameter_type value)
bool hasRegisteredConverterFunction()
void * data()
QVariant fromValue(T &&value)
T value() const &const
#define SWIFT_MISC_EXPORT
Export a class or function from the library.