refs #247 CVariant can inherit from CValueObjectStdTuple.

But if valueobject.h includes variant.h then it would create a circular dependency.
This commit is contained in:
Mathew Sutcliffe
2014-11-14 00:12:47 +00:00
parent f68fc32f3d
commit 155b957cee
11 changed files with 88 additions and 132 deletions

View File

@@ -115,7 +115,7 @@ namespace BlackGui
else if (variant.canConvert<CStatusMessage>())
this->displayStatusMessage(variant.value<CStatusMessage>(), displayTimeMs);
else
this->displayStringMessage(variant.toString(), displayTimeMs);
this->displayStringMessage(variant.toQString(), displayTimeMs);
}
/*

View File

@@ -353,11 +353,8 @@ QVariant BlackMisc::fixQVariantFromDbusArgument(const QVariant &variant, int loc
}
}
}
else
{
qWarning() << "fixQVariantFromDbusArgument called with unsupported type";
return variant;
}
qWarning() << "fixQVariantFromDbusArgument called with unsupported type";
return variant;
}
/*

View File

@@ -43,7 +43,7 @@ namespace BlackMisc
QString CNameVariantPair::convertToQString(bool i18n) const
{
QString s(this->m_name);
s.append(" ").append(this->m_variant.toString(i18n));
s.append(" ").append(this->m_variant.toQString(i18n));
return s;
}

View File

@@ -60,7 +60,7 @@ namespace BlackMisc
s.append('{').append(index.toQString(i18n)).append(": ");
s.append("(").append(QString::number(v.userType())).append(") ");
QString vs = v.toString(i18n);
QString vs = v.toQString(i18n);
s.append(vs);
s.append('}');
}

View File

@@ -92,7 +92,7 @@ namespace BlackMisc
{
if (command == CSettingUtilities::CmdUpdate())
{
QString v = value.toString();
QString v = value.toQString();
changedFlag = (v != this->m_bookingServiceUrl);
this->m_bookingServiceUrl = v;
return CLogMessage(CLogCategory::settingsUpdate()).info("booking URL%1 changed") << (changedFlag ? "" : " not");

View File

@@ -259,6 +259,14 @@ namespace BlackMisc
return argument;
}
/*
* to CVariant
*/
CVariant CValueObject::toCVariant() const
{
return CVariant(this->toQVariant());
}
/*
* Implementations of pure virtual functions
*/

View File

@@ -15,7 +15,6 @@
#include "dbus.h"
#include "tuple.h"
#include "json.h"
#include "variant.h"
#include "blackmiscfreefunctions.h"
#include "valueobject_private.h"
#include "valueobject_policy.h"
@@ -37,6 +36,7 @@ namespace BlackMisc
class CPropertyIndexList;
class CPropertyIndexVariantMap;
class CIcon;
class CVariant;
namespace PhysicalQuantities
{
@@ -175,8 +175,8 @@ namespace BlackMisc
//! Virtual method to return QVariant, used with DBus QVariant lists
virtual QVariant toQVariant() const = 0;
//! Virtual method to return CVariant
virtual CVariant toCVariant() const { return CVariant(this->toQVariant()); }
//! Method to return CVariant
CVariant toCVariant() const;
//! Equals another CValueObject in QVariant?
virtual bool equalsQVariant(const QVariant &qVariant) const;

View File

@@ -38,12 +38,20 @@ namespace BlackMisc
namespace MetaType
{
//! CValueObjectStdTuple registerMetadata policy which only registers with QMetaType and QtDBus
struct QMetaTypeAndDBusOnly
{
//! Register with QMetaType
template <class T, class...>
static void registerImpl() { qRegisterMetaType<T>(); qDBusRegisterMetaType<T>(); }
};
//! CValueObjectStdTuple default registerMetadata policy
struct Default
{
//! Register with QMetaType
template <class T, class...>
static void registerImpl() { qRegisterMetaType<T>(); qDBusRegisterMetaType<T>(); maybeRegisterMetaValueType<T>(); }
static void registerImpl() { QMetaTypeAndDBusOnly::registerImpl<T>(); maybeRegisterMetaValueType<T>(); }
private:
template <class T>

View File

@@ -8,7 +8,6 @@
*/
#include "variant.h"
#include "valueobject.h"
#include "blackmiscfreefunctions.h"
#include <QDBusArgument>
#include <QDBusMetaType>
@@ -26,13 +25,7 @@ namespace BlackMisc
return v.value<IValueObjectMetaInfo *>();
}
void CVariant::registerMetadata()
{
qRegisterMetaType<CVariant>();
qDBusRegisterMetaType<CVariant>();
}
QString CVariant::toString(bool i18n) const
QString CVariant::convertToQString(bool i18n) const
{
auto *meta = getValueObjectMetaInfo();
if (meta)
@@ -42,22 +35,24 @@ namespace BlackMisc
return m_v.toString();
}
int BlackMisc::compare(const CVariant &a, const CVariant &b)
int CVariant::compareImpl(const CValueObject &otherBase) const
{
if (a.userType() < b.userType()) { return -1; }
if (a.userType() > b.userType()) { return 1; }
auto *metaA = a.getValueObjectMetaInfo();
auto *metaB = b.getValueObjectMetaInfo();
if (metaA && metaB)
const auto &other = static_cast<const CVariant &>(otherBase);
if (userType() < other.userType()) { return -1; }
if (userType() > other.userType()) { return 1; }
auto *meta = getValueObjectMetaInfo();
auto *otherMeta = other.getValueObjectMetaInfo();
if (meta && otherMeta)
{
const void *casted = nullptr;
if ((casted = metaA->upCastTo(a.data(), metaB->getMetaTypeId())))
if ((casted = meta->upCastTo(data(), otherMeta->getMetaTypeId())))
{
return metaB->compare(casted, b.data());
return otherMeta->compare(casted, other.data());
}
else if ((casted = metaB->upCastTo(b.data(), metaA->getMetaTypeId())))
else if ((casted = otherMeta->upCastTo(other.data(), meta->getMetaTypeId())))
{
return metaA->compare(a.data(), casted);
return meta->compare(data(), casted);
}
else
{
@@ -65,8 +60,8 @@ namespace BlackMisc
return 0;
}
}
if (a.m_v < b.m_v) { return -1; }
if (a.m_v > b.m_v) { return 1; }
if (m_v < other.m_v) { return -1; }
if (m_v > other.m_v) { return 1; }
return 0;
}
@@ -106,7 +101,7 @@ namespace BlackMisc
return json;
}
void CVariant::fromJson(const QJsonObject &json)
void CVariant::convertFromJson(const QJsonObject &json)
{
QString typeName = json.value("type").toString();
int typeId = QMetaType::type(qPrintable(typeName));
@@ -179,23 +174,17 @@ namespace BlackMisc
}
}
QDBusArgument &operator <<(QDBusArgument &arg, const CVariant &var)
void CVariant::marshallToDbus(QDBusArgument &arg) const
{
arg.beginStructure();
arg << QString(var.typeName()) << QDBusVariant(var.toQVariant());
arg.endStructure();
return arg;
arg << QString(typeName()) << QDBusVariant(getQVariant());
}
const QDBusArgument &operator >>(const QDBusArgument &arg, CVariant &var)
void CVariant::unmarshallFromDbus(const QDBusArgument &arg)
{
QString typeName;
QDBusVariant dbusVar;
arg.beginStructure();
arg >> typeName >> dbusVar;
arg.endStructure();
var = fixQVariantFromDbusArgument(dbusVar.variant(), QMetaType::type(qPrintable(typeName)));
return arg;
*this = fixQVariantFromDbusArgument(dbusVar.variant(), QMetaType::type(qPrintable(typeName)));
}
} // namespace

View File

@@ -12,6 +12,7 @@
#ifndef BLACKMISC_VARIANT_H
#define BLACKMISC_VARIANT_H
#include "valueobject.h"
#include <QVariant>
#include <QDateTime>
#include <QJsonValueRef>
@@ -23,22 +24,35 @@ class QDBusArgument;
namespace BlackMisc
{
class CVariant;
//! \private
template <> struct CValueObjectStdTuplePolicy<CVariant> : public CValueObjectStdTuplePolicy<>
{
using MetaType = Policy::MetaType::QMetaTypeAndDBusOnly;
using Equals = Policy::Equals::OwnEquals;
using LessThan = Policy::LessThan::OwnLessThan;
using Compare = Policy::Compare::Own;
using Hash = Policy::Hash::Own;
using DBus = Policy::DBus::Own;
using Json = Policy::Json::Own;
};
/*!
* Wrapper around QVariant which provides transparent access to CValueObject methods
* of the contained object if it is registered with BlackMisc::registerMetaValueType.
*/
class CVariant
class CVariant : public CValueObjectStdTuple<CVariant>
{
public:
//! Default constructor.
CVariant() {}
//! Copy constructor.
CVariant(const CVariant &other) : m_v(other.m_v) {}
CVariant(const CVariant &other) : CValueObjectStdTuple(other), m_v(other.m_v) {}
//! Move constructor.
CVariant(CVariant &&other) : m_v(std::move(other.m_v)) {}
CVariant(CVariant &&other) : CValueObjectStdTuple(std::move(other)), m_v(std::move(other.m_v)) {}
//! Construct from a QVariant.
CVariant(const QVariant &var) : m_v(var) {}
@@ -52,8 +66,8 @@ namespace BlackMisc
//! Construct a variant from the given type and opaque pointer.
CVariant(int typeId, const void *copy) : m_v(typeId, copy) {}
//! Value hash
uint getValueHash() const;
//! \copydoc CValueObject::getValueHash
virtual uint getValueHash() const override;
//! Change the internal QVariant.
void reset(const QVariant &var) { m_v = var; }
@@ -98,7 +112,13 @@ namespace BlackMisc
template <typename T> T to() const { return m_v.value<T>(); }
//! Return the internal QVariant.
const QVariant &toQVariant() const { return m_v; }
const QVariant &getQVariant() const { return m_v; }
//! \copydoc CValueObject::toQVariant
virtual QVariant toQVariant() const override { return getQVariant(); }
//! \copydoc CValueObject::convertFromQVariant
virtual void convertFromQVariant(const QVariant &v) override { m_v = 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); }
@@ -109,8 +129,8 @@ namespace BlackMisc
//! 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;
//! \copydoc CValueObject::convertToQString
virtual QString convertToQString(bool i18n = false) const override;
//! Convert this variant to a bool.
bool toBool() const { return m_v.toBool(); }
@@ -142,35 +162,26 @@ namespace BlackMisc
//! Return the metatype ID of the value in this variant.
int userType() const { return m_v.userType(); }
//! To JSON
QJsonObject toJson() const;
//! \copydoc CValueObject::toJson
virtual QJsonObject toJson() const override;
//! From JSON
void fromJson(const QJsonObject &json);
//! \copydoc CValueObject::convertFromJson
virtual void convertFromJson(const QJsonObject &json) override;
//! \copydoc CValueObject::marshallToDbus
virtual void marshallToDbus(QDBusArgument &argument) const override;
//! \copydoc CValueObject::unmarshallFromDbus
virtual void unmarshallFromDbus(const QDBusArgument &argument) override;
//! Equal operator.
friend bool operator ==(const CVariant &a, const CVariant &b) { return compare(a, b) == 0; }
//! Not equal operator.
friend bool operator !=(const CVariant &a, const CVariant &b) { return !(a == b); }
//! Less than operator.
friend bool operator <(const CVariant &a, const CVariant &b) { return compare(a, b) < 0; }
//! Less than or equal operator.
friend bool operator <=(const CVariant &a, const CVariant &b) { return !(b < a); }
//! Greater than operator.
friend bool operator >(const CVariant &a, const CVariant &b) { return b < a; }
//! Greater than or equal operator.
friend bool operator >=(const CVariant &a, const CVariant &b) { return !(a < b); }
//! Arbitrary comparison
friend int compare(const CVariant &a, const CVariant &b);
//! Register metadata.
static void registerMetadata();
//! \copydoc CValueObject::compareImpl
virtual int compareImpl(const CValueObject &other) const override;
private:
QVariant m_v;
@@ -180,63 +191,6 @@ namespace BlackMisc
const void *data() const { return m_v.data(); }
};
//! 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);
//! Non member, non friend operator >> for JSON
inline QJsonArray &operator<<(QJsonArray &json, const BlackMisc::CVariant &variant)
{
json.append(variant.toJson());
return json;
}
/*!
* \brief Non member, non friend operator << for JSON
* \param json
* \param value as pair name/value
* \return
*/
inline QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, BlackMisc::CVariant> &value)
{
json.insert(value.first, QJsonValue(value.second.toJson()));
return json;
}
//! Non member, non friend operator >> for JSON
inline const QJsonObject &operator>>(const QJsonObject &json, BlackMisc::CVariant &variant)
{
variant.fromJson(json);
return json;
}
//! Non member, non friend operator >> for JSON
inline const QJsonValue &operator>>(const QJsonValue &json, BlackMisc::CVariant &variant)
{
variant.fromJson(json.toObject());
return json;
}
//! Non member, non friend operator >> for JSON
inline const QJsonValueRef &operator>>(const QJsonValueRef &json, BlackMisc::CVariant &variant)
{
variant.fromJson(json.toObject());
return json;
}
//! qHash overload, needed for storing CVariant with tupel system
inline uint qHash(const BlackMisc::CVariant &value, uint seed = 0)
{
return ::qHash(value.getValueHash(), seed);
}
// Needed so that our qHash overload doesn't hide the qHash overloads in the global namespace.
// This will be safe as long as no global qHash has the same signature as ours.
// Alternative would be to qualify all our invokations of the global qHash as ::qHash.
using ::qHash;
} // namespace
Q_DECLARE_METATYPE(BlackMisc::CVariant)