diff --git a/src/blackmisc/blackmiscfreefunctions.cpp b/src/blackmisc/blackmiscfreefunctions.cpp index 43396ab3c..f54d8be33 100644 --- a/src/blackmisc/blackmiscfreefunctions.cpp +++ b/src/blackmisc/blackmiscfreefunctions.cpp @@ -12,6 +12,7 @@ #include "settingsallclasses.h" #include "hwallclasses.h" #include "indexvariantmap.h" +#include "variant.h" #include "statusmessagelist.h" #include "audioallclasses.h" @@ -130,7 +131,9 @@ void BlackMisc::Hardware::registerMetadata() */ void BlackMisc::registerMetadata() { - // !! make sure the first id is correctly returned by + CVariant::registerMetadata(); // before the others because it's not a CValueObject + + // !! make sure the first valueobject id is correctly returned by // !! firstBlackMetaType CIndexVariantMap::registerMetadata(); diff --git a/src/blackmisc/variant.cpp b/src/blackmisc/variant.cpp new file mode 100644 index 000000000..8463ba544 --- /dev/null +++ b/src/blackmisc/variant.cpp @@ -0,0 +1,54 @@ +/* Copyright (C) 2014 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "variant.h" +#include "blackmiscfreefunctions.h" +#include +#include +#include + +namespace BlackMisc +{ + + void CVariant::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + QString CVariant::toString(bool i18n) const + { + if (type() == QVariant::UserType) + { + const CValueObject *s = CValueObject::fromQVariant(m_v); // FIXME this will return garbage if value is not a CValueObject + if (s) + { + return s->toQString(i18n); + } + } + return m_v.toString(); + } + + QDBusArgument &operator <<(QDBusArgument &arg, const CVariant &var) + { + arg.beginStructure(); + arg << QString(var.typeName()) << QDBusVariant(var.toQVariant()); + arg.endStructure(); + return arg; + } + + const QDBusArgument &operator >>(const QDBusArgument &arg, CVariant &var) + { + QString typeName; + QDBusVariant dbusVar; + arg.beginStructure(); + arg >> typeName >> dbusVar; + arg.endStructure(); + + var = fixQVariantFromDbusArgument(dbusVar.variant(), QMetaType::type(qPrintable(typeName))); + return arg; + } + +} // namespace \ No newline at end of file diff --git a/src/blackmisc/variant.h b/src/blackmisc/variant.h new file mode 100644 index 000000000..a01b776b4 --- /dev/null +++ b/src/blackmisc/variant.h @@ -0,0 +1,160 @@ +/* Copyright (C) 2014 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/*! + \file +*/ + +#ifndef BLACKMISC_VARIANT_H +#define BLACKMISC_VARIANT_H + +#include + +class QDBusArgument; + +namespace BlackMisc +{ + + /*! + * Wrapper class for QVariant, for more natural and transparent DBus integration. + */ + class CVariant + { + public: + //! Default constructor. + CVariant() {} + + //! Copy constructor. + CVariant(const CVariant &other) : m_v(other.m_v) {} + + //! Move constructor. + CVariant(CVariant &&other) : m_v(std::move(other.m_v)) {} + + //! Construct from a QVariant. + CVariant(const QVariant &var) : m_v(var) {} + + //! Move-construct from a QVariant. + CVariant(QVariant &&var) : m_v(std::move(var)) {} + + //! Construct a null variant of the given type. + CVariant(QVariant::Type type) : m_v(type) {} + + //! Construct a variant from the given type and opaque pointer. + CVariant(int typeId, const void *copy) : m_v(typeId, copy) {} + + //! Change the internal QVariant. + void reset(const QVariant &var) { m_v = var; } + + //! Change the internal QVariant. + void reset(QVariant &&var) { m_v = std::move(var); } + + //! Copy assignment operator. + CVariant &operator =(const CVariant &other) { m_v = other.m_v; return *this; } + + //! Move assignment operatior. + CVariant &operator =(CVariant &&other) { m_v = std::move(other.m_v); return *this; } + + //! Change the internal QVariant + CVariant &operator =(const QVariant &var) { m_v = var; return *this; } + + //! Change the internal QVariant + CVariant &operator =(QVariant &&var) { m_v = std::move(var); return *this; } + + //! Swap this variant with another. + void swap(CVariant &other) { m_v.swap(other.m_v); } + + //! Swap the internal QVariant with another. + void swap(QVariant &other) { m_v.swap(other); } + + //! Construct a variant from a value. + template static CVariant fromValue(T &&value) { return CVariant(QVariant::fromValue(std::forward(value))); } + + //! Synonym for fromValue(). + template static CVariant from(T &&value) { return CVariant(QVariant::fromValue(std::forward(value))); } + + //! Change the value. + template void setValue(T &&value) { m_v.setValue(std::forward(value)); } + + //! Synonym for setValue(). + template void set(T &&value) { m_v.setValue(std::forward(value)); } + + //! Return the value converted to the type T. + template T value() const { return m_v.value(); } + + //! Synonym for value(). + template T to() const { return m_v.value(); } + + //! Return the internal QVariant. + const QVariant &toQVariant() const { return m_v; } + + //! True if this variant can be converted to the type with the given metatype ID. + bool canConvert(int typeId) const { return m_v.canConvert(typeId); } + + //! True if this variant can be converted to the type T. + template bool canConvert() const { return m_v.canConvert(); } + + //! Convert this variant to the type with the given metatype ID and return true if successful. + bool convert(int typeId) { return m_v.convert(typeId); } + + //! Convert this variant to a QString. + QString toString(bool i18n = false) const; + + //! Convert this variant to a bool. + bool toBool() const { return m_v.toBool(); } + + //! Set the variant to null. + void clear() { m_v.clear(); } + + //! True if this variant is null. + bool isNull() const { return m_v.isNull(); } + + //! True if this variant is valid. + bool isValid() const { return m_v.isValid(); } + + //! Return the metatype ID of the value in this variant, or QMetaType::User if it is a user type. + QVariant::Type type() const { return m_v.type(); } + + //! Return the typename of the value in this variant. + const char *typeName() const { return m_v.typeName(); } + + //! Return the metatype ID of the value in this variant. + int userType() const { return m_v.userType(); } + + //! Equal operator. + bool operator ==(const CVariant &other) const { return m_v == other.m_v; } + + //! Not equal operator. + bool operator !=(const CVariant &other) const { return m_v != other.m_v; } + + //! Less than operator. + bool operator <(const CVariant &other) const { return m_v < other.m_v; } + + //! Less than or equal operator. + bool operator <=(const CVariant &other) const { return m_v <= other.m_v; } + + //! Greater than operator. + bool operator >(const CVariant &other) const { return m_v > other.m_v; } + + //! Greater than or equal operator. + bool operator >=(const CVariant &other) const { return m_v >= other.m_v; } + + //! Register metadata. + static void registerMetadata(); + + private: + QVariant m_v; + }; + + //! Marshall a variant to DBus. + QDBusArgument &operator <<(QDBusArgument &arg, const CVariant &var); + + //! Unmarshall a variant from DBus. + const QDBusArgument &operator >>(const QDBusArgument &arg, CVariant &var); + +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::CVariant) + +#endif // guard