diff --git a/src/blackmisc/tuple.h b/src/blackmisc/tuple.h index 179064878..435a6d7d3 100644 --- a/src/blackmisc/tuple.h +++ b/src/blackmisc/tuple.h @@ -54,6 +54,7 @@ template <> class TupleConverter : TupleConverterBase \ { \ friend class T; \ + friend class BlackMisc::CValueObjectStdTuple; \ static_assert(Private::HasEnabledTupleConversion::value, \ "Missing BLACK_ENABLE_TUPLE_CONVERSION macro in " #T); \ static auto toTuple(const T &o) -> decltype(BlackMisc::tie MEMBERS) \ diff --git a/src/blackmisc/valueobject.h b/src/blackmisc/valueobject.h index c60ccd7a8..d80401130 100644 --- a/src/blackmisc/valueobject.h +++ b/src/blackmisc/valueobject.h @@ -16,6 +16,7 @@ #include "tuple.h" #include "json.h" #include "variant.h" +#include "blackmiscfreefunctions.h" #include #include #include @@ -270,6 +271,87 @@ namespace BlackMisc }; + //! Standard tuple enabled value object + //! CRTP based approach to avoid repetitive code + template class CValueObjectStdTuple : public BlackMisc::CValueObject + { + + public: + + //! Default constructor. + CValueObjectStdTuple() : CValueObject() {} + + //! \copydoc CValueObject::getValueHash() + virtual uint getValueHash() const override + { + return qHash(TupleConverter::toMetaTuple(*derived())); + } + + //! \copydoc CValueObject::toJson + virtual QJsonObject toJson() const override + { + return BlackMisc::serializeJson(TupleConverter::toMetaTuple(*derived())); + } + + //! \copydoc CValueObject::convertFromJson + virtual void convertFromJson(const QJsonObject &json) override + { + BlackMisc::deserializeJson(json, TupleConverter::toMetaTuple(*derived())); + } + + //! \copydoc CValueObject::toQVariant() + virtual QVariant toQVariant() const override { return QVariant::fromValue(*derived()); } + + //! \copydoc CValueObject::convertFromQVariant + virtual void convertFromQVariant(const QVariant &variant) override { BlackMisc::setFromQVariant(derived(), variant); } + + //! Register metadata + static void registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + protected: + + //! \copydoc CValueObject::getMetaTypeId + virtual int getMetaTypeId() const override { return qMetaTypeId(); } + + //! \copydoc CValueObject::isA + virtual bool isA(int metaTypeId) const override + { + if (metaTypeId == qMetaTypeId()) { return true; } + return this->CValueObject::isA(metaTypeId); + } + + //! \copydoc CValueObject::compareImpl(CValueObject &otherBase) + virtual int compareImpl(const CValueObject &otherBase) const override + { + const VO &other = static_cast(otherBase); + return compare(TupleConverter::toMetaTuple(*derived()), TupleConverter::toMetaTuple(other)); + } + + //! \copydoc CValueObject::marshallToDbus() + virtual void marshallToDbus(QDBusArgument &argument) const override + { + argument << TupleConverter::toMetaTuple(*derived()); + } + + //! \copydoc CValueObject::unmarshallFromDbus() + virtual void unmarshallFromDbus(const QDBusArgument &argument) override + { + argument >> TupleConverter::toMetaTuple(*derived()); + } + + private: + //! Easy access to derived class (CRTP template parameter) + VO const *derived() const { return static_cast(this); } + + //! Easy access to derived class (CRTP template parameter) + VO *derived() { return static_cast(this); } + + }; + /*! * Non-member non-friend operator for streaming T objects to QDBusArgument. * Needed because we can't rely on the friend operator in some cases due to