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 <QMetaSequence>
16 #include <QMetaType>
17 #include <QPixmap>
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() = default;
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  void setValue(T &&value)
145  {
146  m_v.setValue(std::forward<T>(value));
147  }
148 
150  template <typename T>
151  T value() const
152  {
153  return to(tag<T>());
154  }
155 
159  template <typename T>
160  T valueOrDefault(T def) const
161  {
162  return canConvert<T>() ? value<T>() : def;
163  }
164 
166  const QVariant &getQVariant() const { return m_v; }
167 
169  operator const QVariant &() const { return m_v; }
170 
172  operator QVariant() && { return std::move(m_v); }
173 
175  bool canConvert(int typeId) const;
176 
178  template <typename T>
179  bool canConvert() const
180  {
181  return canConvert(qMetaTypeId<T>());
182  }
183 
185  bool convert(int typeId);
186 
188  QString convertToQString(bool i18n = false) const;
189 
191  bool isIntegral() const;
192 
194  bool isArithmetic() const;
195 
197  bool toBool() const { return m_v.toBool(); }
198 
200  int toInt(bool *ok = nullptr) const { return m_v.toInt(ok); }
201 
203  qlonglong toLongLong(bool *ok = nullptr) const { return m_v.toLongLong(ok); }
204 
206  qulonglong toULongLong(bool *ok = nullptr) const { return m_v.toULongLong(ok); }
207 
209  qint64 toQInt64(bool *ok = nullptr) const;
210 
212  double toDouble(bool *ok = nullptr) const { return m_v.toDouble(ok); }
213 
215  QDateTime toDateTime() const { return m_v.toDateTime(); }
216 
218  QUrl toUrl() const { return m_v.toUrl(); }
219 
221  void clear() { m_v.clear(); }
222 
224  bool isNull() const { return m_v.isNull(); }
225 
227  bool isValid() const { return m_v.isValid(); }
228 
231  {
232  const int type = m_v.typeId();
233  return type >= QMetaType::Type::User ? QMetaType::Type::User : static_cast<QMetaType::Type>(type);
234  }
235 
237  const char *typeName() const { return m_v.typeName(); }
238 
240  int userType() const { return m_v.userType(); }
241 
243  QMetaType metaType() const { return QMetaType(userType()); }
244 
247 
250 
252  void convertFromJson(const QJsonObject &json);
253 
256  const QString &prefix);
257 
260 
262  void convertFromMemoizedJson(const QJsonObject &json, bool allowFallbackToJson);
263 
266  const QString &prefix);
267 
269  void marshallToDbus(QDBusArgument &argument) const;
270 
272  void unmarshallFromDbus(const QDBusArgument &argument);
273 
275  void marshalToDataStream(QDataStream &stream) const;
276 
279 
281  friend int compare(const CVariant &a, const CVariant &b) { return compareImpl(a, b); }
282 
284  void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant);
285 
288 
290  bool equalsPropertyByIndex(const CVariant &compareValue, CPropertyIndexRef index) const;
291 
293  QPixmap toPixmap() const;
294 
297 
299  static void registerMetadata();
300 
302  int getMetaTypeId() const;
303 
306 
308  bool isA(int metaTypeId) const;
309 
311  bool matches(const CVariant &event) const;
312 
313  private:
314  QVariant m_v;
315 
316  private_ns::IValueObjectMetaInfo *getValueObjectMetaInfo() const
317  {
318  return private_ns::getValueObjectMetaInfo(m_v);
319  }
320  void *data() { return m_v.data(); }
321  const void *data() const { return m_v.data(); }
322 
323  static int compareImpl(const CVariant &, const CVariant &);
324  size_t getValueHash() const;
325 
326  template <typename T>
327  T to(tag<T>) const
328  {
329  auto copy = *this;
330  copy.convert(qMetaTypeId<T>());
331  return *static_cast<const T *>(copy.data());
332  }
333  template <typename T>
334  QList<T> to(tag<QList<T>>) const
335  {
336  return toImpl<QList<T>>();
337  }
338  template <typename T>
339  CSequence<T> to(tag<CSequence<T>>) const
340  {
341  return toImpl<CSequence<T>>();
342  }
343  template <typename T>
344  T toImpl() const
345  {
346  using VT = typename T::value_type;
347  T result;
348  if (isVariantList())
349  {
350  for (const auto &v : m_v.value<QVector<CVariant>>()) { result.push_back(v.value<VT>()); }
351  }
352  else
353  {
354  for (const auto &v : m_v.value<QMetaSequence::Iterable>()) { result.push_back(v.value<VT>()); }
355  }
356  return result;
357  }
358  bool isVariantList() const;
359  };
360 } // namespace swift::misc
361 
362 Q_DECLARE_METATYPE(swift::misc::CVariant)
363 
364 namespace swift::misc::private_ns
365 {
367  template <typename T>
368  void MetaTypeHelper<T>::maybeRegisterMetaList()
369  {
370  if constexpr (canConvertVariantList<T>(0))
371  {
373  QMetaType(qMetaTypeId<QVector<CVariant>>())))
374  {
375  return;
376  }
377 
378  QMetaType::registerConverter<T, QVector<CVariant>>([](const T &list) -> QVector<CVariant> {
379  return list.transform([](const typename T::value_type &v) { return CVariant::fromValue(v); });
380  });
381  QMetaType::registerConverter<QVector<CVariant>, T>([](const QVector<CVariant> &list) -> T {
382  return makeRange(list).transform([](const CVariant &v) { return v.value<typename T::value_type>(); });
383  });
384  }
385  }
387 } // namespace swift::misc::private_ns
388 
389 #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
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:144
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:151
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:160
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:212
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:179
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:243
CVariant()=default
Default constructor.
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
CVariant & operator=(const QVariant &var)
Change the internal QVariant.
Definition: variant.h:115
QUrl toUrl() const
Convert this variant to QUrl.
Definition: variant.h:218
int userType() const
Return the metatype ID of the value in this variant.
Definition: variant.h:240
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::fromValue() instead....
bool isValid() const
True if this variant is valid.
Definition: variant.h:227
bool toBool() const
Convert this variant to a bool.
Definition: variant.h:197
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:206
QDateTime toDateTime() const
Convert this variant to QDateTime.
Definition: variant.h:215
const char * typeName() const
Return the typename of the value in this variant.
Definition: variant.h:237
void clear()
Set the variant to null.
Definition: variant.h:221
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:166
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:230
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:281
qlonglong toLongLong(bool *ok=nullptr) const
Convert this variant to a longlong integer.
Definition: variant.h:203
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.
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:200
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:224
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.