mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-05-05 09:45:44 +08:00
refs #345 A second template parameter in CValueObjectStdTuple allows to select the base class, for inheritance hierarchies.
This commit is contained in:
@@ -258,4 +258,12 @@ namespace BlackMisc
|
|||||||
argument.endStructure();
|
argument.endStructure();
|
||||||
return argument;
|
return argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implementations of pure virtual functions
|
||||||
|
*/
|
||||||
|
uint CValueObject::getValueHash() const { return 0; }
|
||||||
|
int CValueObject::compareImpl(const CValueObject &) const { return 0; }
|
||||||
|
void CValueObject::marshallToDbus(QDBusArgument &) const {}
|
||||||
|
void CValueObject::unmarshallFromDbus(const QDBusArgument &) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,6 +158,9 @@ namespace BlackMisc
|
|||||||
friend int compare(const CValueObject &v1, const CValueObject &v2);
|
friend int compare(const CValueObject &v1, const CValueObject &v2);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
//! Root
|
||||||
|
using base_type = CValueObject;
|
||||||
|
|
||||||
//! Base class enums
|
//! Base class enums
|
||||||
enum ColumnIndex
|
enum ColumnIndex
|
||||||
{
|
{
|
||||||
@@ -275,9 +278,13 @@ namespace BlackMisc
|
|||||||
* Standard implementation of CValueObject using meta tuple system.
|
* Standard implementation of CValueObject using meta tuple system.
|
||||||
*
|
*
|
||||||
* \tparam Derived The class which is inheriting from this one (CRTP).
|
* \tparam Derived The class which is inheriting from this one (CRTP).
|
||||||
|
* \tparam Base The class which this one shall inherit from (default is CValueObject,
|
||||||
|
* but this can be changed to create a deeper inheritance hierarchy).
|
||||||
*/
|
*/
|
||||||
template <class Derived> class CValueObjectStdTuple : public CValueObject
|
template <class Derived, class Base = CValueObject> class CValueObjectStdTuple : public Base
|
||||||
{
|
{
|
||||||
|
static_assert(std::is_base_of<CValueObject, Base>::value, "Base must be derived from CValueObject");
|
||||||
|
|
||||||
friend bool operator ==(const Derived &a, const Derived &b)
|
friend bool operator ==(const Derived &a, const Derived &b)
|
||||||
{
|
{
|
||||||
return equals(a, b);
|
return equals(a, b);
|
||||||
@@ -289,34 +296,39 @@ namespace BlackMisc
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
//! Base class
|
||||||
|
using base_type = Base;
|
||||||
|
|
||||||
//! \copydoc CValueObject::getValueHash()
|
//! \copydoc CValueObject::getValueHash()
|
||||||
virtual uint getValueHash() const override
|
virtual uint getValueHash() const override
|
||||||
{
|
{
|
||||||
return qHash(TupleConverter<Derived>::toMetaTuple(*derived()));
|
return qHash(TupleConverter<Derived>::toMetaTuple(*derived())) ^ Base::getValueHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \copydoc CValueObject::toJson
|
//! \copydoc CValueObject::toJson
|
||||||
virtual QJsonObject toJson() const override
|
virtual QJsonObject toJson() const override
|
||||||
{
|
{
|
||||||
return BlackMisc::serializeJson(TupleConverter<Derived>::toMetaTuple(*derived()));
|
QJsonObject json = BlackMisc::serializeJson(TupleConverter<Derived>::toMetaTuple(*derived()));
|
||||||
|
return Json::appendJsonObject(json, Base::toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \copydoc CValueObject::convertFromJson
|
//! \copydoc CValueObject::convertFromJson
|
||||||
virtual void convertFromJson(const QJsonObject &json) override
|
virtual void convertFromJson(const QJsonObject &json) override
|
||||||
{
|
{
|
||||||
|
Base::convertFromJson(json);
|
||||||
BlackMisc::deserializeJson(json, TupleConverter<Derived>::toMetaTuple(*derived()));
|
BlackMisc::deserializeJson(json, TupleConverter<Derived>::toMetaTuple(*derived()));
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \copydoc CValueObject::toQVariant()
|
//! \copydoc CValueObject::toQVariant()
|
||||||
virtual QVariant toQVariant() const override
|
virtual QVariant toQVariant() const override
|
||||||
{
|
{
|
||||||
return QVariant::fromValue(*derived());
|
return maybeToQVariant(IsRegisteredQMetaType<Derived>());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \copydoc CValueObject::convertFromQVariant
|
//! \copydoc CValueObject::convertFromQVariant
|
||||||
virtual void convertFromQVariant(const QVariant &variant) override
|
virtual void convertFromQVariant(const QVariant &variant) override
|
||||||
{
|
{
|
||||||
BlackMisc::setFromQVariant(derived(), variant);
|
return maybeConvertFromQVariant(variant, IsRegisteredQMetaType<Derived>());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Register metadata
|
//! Register metadata
|
||||||
@@ -330,6 +342,11 @@ namespace BlackMisc
|
|||||||
//! Default constructor.
|
//! Default constructor.
|
||||||
CValueObjectStdTuple() = default;
|
CValueObjectStdTuple() = default;
|
||||||
|
|
||||||
|
//! Template constructor, forwards all arguments to base class constructor.
|
||||||
|
//! \todo When our compilers support C++11 inheriting constructors, use those instead.
|
||||||
|
template <typename T, typename... Ts, typename = typename std::enable_if<! std::is_same<CValueObjectStdTuple, typename std::decay<T>::type>::value>::type>
|
||||||
|
CValueObjectStdTuple(T &&first, Ts &&... args) : Base(std::forward<T>(first), std::forward<Ts>(args)...) {}
|
||||||
|
|
||||||
//! Copy constructor.
|
//! Copy constructor.
|
||||||
CValueObjectStdTuple(const CValueObjectStdTuple &) = default;
|
CValueObjectStdTuple(const CValueObjectStdTuple &) = default;
|
||||||
|
|
||||||
@@ -339,32 +356,37 @@ namespace BlackMisc
|
|||||||
//! \copydoc CValueObject::getMetaTypeId
|
//! \copydoc CValueObject::getMetaTypeId
|
||||||
virtual int getMetaTypeId() const override
|
virtual int getMetaTypeId() const override
|
||||||
{
|
{
|
||||||
return qMetaTypeId<Derived>();
|
return maybeGetMetaTypeId(IsRegisteredQMetaType<Derived>());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \copydoc CValueObject::isA
|
//! \copydoc CValueObject::isA
|
||||||
virtual bool isA(int metaTypeId) const override
|
virtual bool isA(int metaTypeId) const override
|
||||||
{
|
{
|
||||||
if (metaTypeId == qMetaTypeId<Derived>()) { return true; }
|
if (metaTypeId == QMetaType::UnknownType) { return false; }
|
||||||
return this->CValueObject::isA(metaTypeId);
|
if (metaTypeId == maybeGetMetaTypeId(IsRegisteredQMetaType<Derived>())) { return true; }
|
||||||
|
return Base::isA(metaTypeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \copydoc CValueObject::compareImpl
|
//! \copydoc CValueObject::compareImpl
|
||||||
virtual int compareImpl(const CValueObject &other) const override
|
virtual int compareImpl(const CValueObject &other) const override
|
||||||
{
|
{
|
||||||
const auto &otherDerived = static_cast<const Derived &>(other);
|
const auto &otherDerived = static_cast<const Derived &>(other);
|
||||||
return compare(TupleConverter<Derived>::toMetaTuple(*derived()), TupleConverter<Derived>::toMetaTuple(otherDerived));
|
int result = compare(TupleConverter<Derived>::toMetaTuple(*derived()), TupleConverter<Derived>::toMetaTuple(otherDerived));
|
||||||
|
if (result) return result;
|
||||||
|
return Base::compareImpl(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \copydoc CValueObject::marshallToDbus()
|
//! \copydoc CValueObject::marshallToDbus()
|
||||||
virtual void marshallToDbus(QDBusArgument &argument) const override
|
virtual void marshallToDbus(QDBusArgument &argument) const override
|
||||||
{
|
{
|
||||||
|
Base::marshallToDbus(argument);
|
||||||
argument << TupleConverter<Derived>::toMetaTuple(*derived());
|
argument << TupleConverter<Derived>::toMetaTuple(*derived());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \copydoc CValueObject::unmarshallFromDbus()
|
//! \copydoc CValueObject::unmarshallFromDbus()
|
||||||
virtual void unmarshallFromDbus(const QDBusArgument &argument) override
|
virtual void unmarshallFromDbus(const QDBusArgument &argument) override
|
||||||
{
|
{
|
||||||
|
Base::unmarshallFromDbus(argument);
|
||||||
argument >> TupleConverter<Derived>::toMetaTuple(*derived());
|
argument >> TupleConverter<Derived>::toMetaTuple(*derived());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,6 +401,15 @@ namespace BlackMisc
|
|||||||
if (&a == &b) { return true; }
|
if (&a == &b) { return true; }
|
||||||
return TupleConverter<Derived>::toMetaTuple(a) == TupleConverter<Derived>::toMetaTuple(b);
|
return TupleConverter<Derived>::toMetaTuple(a) == TupleConverter<Derived>::toMetaTuple(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fallbacks in case Derived is not a registered meta type
|
||||||
|
template <class T> using IsRegisteredQMetaType = std::integral_constant<bool, QMetaTypeId<T>::Defined>;
|
||||||
|
static int maybeGetMetaTypeId(std::true_type) { return qMetaTypeId<Derived>(); }
|
||||||
|
static int maybeGetMetaTypeId(std::false_type) { return QMetaType::UnknownType; }
|
||||||
|
QVariant maybeToQVariant(std::true_type) const { return QVariant::fromValue(*derived()); }
|
||||||
|
QVariant maybeToQVariant(std::false_type) const { return {}; }
|
||||||
|
void maybeConvertFromQVariant(const QVariant &variant, std::true_type) { BlackMisc::setFromQVariant(derived(), variant); }
|
||||||
|
void maybeConvertFromQVariant(const QVariant &variant, std::false_type) { Q_UNUSED(variant); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
Reference in New Issue
Block a user