diff --git a/src/blackmisc/blackmisc.h b/src/blackmisc/blackmisc.h index 186f0a7b8..248d1f295 100644 --- a/src/blackmisc/blackmisc.h +++ b/src/blackmisc/blackmisc.h @@ -48,6 +48,11 @@ * \brief Iterator classes for the containers. */ +/*! + * \namespace BlackMisc::Mixin + * \brief Mixin classes which implement common operations for value classes. + */ + /*! * \namespace BlackMisc::Policy * \brief Policy classes for CValueObject. diff --git a/src/blackmisc/containerbase.h b/src/blackmisc/containerbase.h index b2c471293..a939c3c49 100644 --- a/src/blackmisc/containerbase.h +++ b/src/blackmisc/containerbase.h @@ -158,7 +158,7 @@ namespace BlackMisc } //! \copydoc BlackMisc::CValueObject::getMetaTypeId - virtual int getMetaTypeId() const override { return qMetaTypeId>(); } + int getMetaTypeId() const { return qMetaTypeId>(); } //! \copydoc BlackMisc::CValueObject::marshallToDbus virtual void marshallToDbus(QDBusArgument &argument) const override diff --git a/src/blackmisc/dictionary.h b/src/blackmisc/dictionary.h index 8c0ece4ca..21c7a3cba 100644 --- a/src/blackmisc/dictionary.h +++ b/src/blackmisc/dictionary.h @@ -421,9 +421,6 @@ namespace BlackMisc return str += "}"; } - //! \copydoc BlackMisc::CValueObject::getMetaTypeId - virtual int getMetaTypeId() const override { return qMetaTypeId(); } - //! \copydoc BlackMisc::CValueObject::marshallToDbus virtual void marshallToDbus(QDBusArgument &argument) const override { diff --git a/src/blackmisc/propertyindexvariantmap.cpp b/src/blackmisc/propertyindexvariantmap.cpp index 874c6a7a8..4ee64f68b 100644 --- a/src/blackmisc/propertyindexvariantmap.cpp +++ b/src/blackmisc/propertyindexvariantmap.cpp @@ -109,14 +109,6 @@ namespace BlackMisc return s; } - /* - * metaTypeId - */ - int CPropertyIndexVariantMap::getMetaTypeId() const - { - return qMetaTypeId(); - } - /* * Marshall to DBus */ @@ -181,15 +173,6 @@ namespace BlackMisc return CPropertyIndexList::fromImpl(this->m_values.keys()); } - /* - * Register metadata - */ - void CPropertyIndexVariantMap::registerMetadata() - { - qRegisterMetaType(); - qDBusRegisterMetaType(); - } - /* * Hash */ diff --git a/src/blackmisc/propertyindexvariantmap.h b/src/blackmisc/propertyindexvariantmap.h index 9206a9187..74970a850 100644 --- a/src/blackmisc/propertyindexvariantmap.h +++ b/src/blackmisc/propertyindexvariantmap.h @@ -146,9 +146,6 @@ namespace BlackMisc //! \copydoc CValueObject::convertFromQVariant virtual void convertFromQVariant(const QVariant &variant) override { BlackMisc::setFromQVariant(this, variant); } - //! register metadata - static void registerMetadata(); - protected: QMap m_values; //!< values @@ -157,9 +154,6 @@ namespace BlackMisc //! \copydoc CValueObject::convertToQString virtual QString convertToQString(bool i18n = false) const override; - //! \copydoc CValueObject::getMetaTypeId - virtual int getMetaTypeId() const override; - //! \copydoc CValueObject::marshallToDbus virtual void marshallToDbus(QDBusArgument &argument) const override; diff --git a/src/blackmisc/valueobject.h b/src/blackmisc/valueobject.h index 41053ede0..84a502d56 100644 --- a/src/blackmisc/valueobject.h +++ b/src/blackmisc/valueobject.h @@ -119,9 +119,6 @@ namespace BlackMisc //! From JSON static void convertFromJson(const QJsonObject &) {} - //! Is a - static bool isA(int) { return false; } - //! Marshall to DBus static void marshallToDbus(QDBusArgument &) {} @@ -185,6 +182,66 @@ namespace BlackMisc using Json = Policy::Json::Own; //!< JSon policy }; + namespace Mixin + { + + /*! + * CRTP class template from which a derived class can inherit common methods dealing with the metatype of the class. + */ + template + class MetaType + { + public: + //! Register metadata + static void registerMetadata() + { + Private::MetaTypeHelper::maybeRegisterMetaType(); + } + + //! Returns the Qt meta type ID of this object. + int getMetaTypeId() const + { + return Private::MetaTypeHelper::maybeGetMetaTypeId(); + } + + //! Returns true if this object is an instance of the class with the given meta type ID, or one of its subclasses. + bool isA(int metaTypeId) const + { + if (metaTypeId == QMetaType::UnknownType) { return false; } + if (metaTypeId == getMetaTypeId()) { return true; } + return baseIsA(static_cast(derived()), metaTypeId); + } + + //! Method to return CVariant + CVariant toCVariant() const; + + //! Set from CVariant + void convertFromCVariant(const CVariant &variant); + + //! Return QVariant, used with DBus QVariant lists + //! \todo remove virtual + virtual QVariant toQVariant() const + { + return Private::MetaTypeHelper::maybeToQVariant(*derived()); + } + + //! Set from QVariant + //! \todo remove virtual + virtual void convertFromQVariant(const QVariant &variant) + { + return Private::MetaTypeHelper::maybeConvertFromQVariant(*derived(), variant); + } + + private: + const Derived *derived() const { return static_cast(this); } + Derived *derived() { return static_cast(this); } + + template static bool baseIsA(const Base2 *base, int metaTypeId) { return base->isA(metaTypeId); } + static bool baseIsA(const CEmpty *, int) { return false; } + }; + + } + /*! * Standard implementation of CValueObject using meta tuple system. * @@ -197,13 +254,13 @@ namespace BlackMisc */ template class CValueObject : public Base, + public Mixin::MetaType, private CValueObjectPolicy::Equals::template Ops, private CValueObjectPolicy::LessThan::template Ops, private CValueObjectPolicy::Compare::template Ops { static_assert(std::is_same::value || IsValueObject::value, "Base must be either CEmpty or derived from CValueObject"); - using MetaTypePolicy = typename CValueObjectPolicy::MetaType; using HashPolicy = typename CValueObjectPolicy::Hash; using DBusPolicy = typename CValueObjectPolicy::DBus; using JsonPolicy = typename CValueObjectPolicy::Json; @@ -333,11 +390,11 @@ namespace BlackMisc //! \return number of values changed, with skipEqualValues equal values will not be changed CPropertyIndexList apply(const BlackMisc::CPropertyIndexVariantMap &indexMap, bool skipEqualValues = false); // implemented later due to cyclic include dependency - //! Method to return CVariant - CVariant toCVariant() const; + //! \copydoc BlackMisc::Mixin::MetaType::toCVariant + using Mixin::MetaType::toCVariant; - //! Set from CVariant - void convertFromCVariant(const CVariant &variant); + //! \copydoc BlackMisc::Mixin::MetaType::convertFromCVariant + using Mixin::MetaType::convertFromCVariant; //! Value hash, allows comparisons between QVariants virtual uint getValueHash() const @@ -359,17 +416,11 @@ namespace BlackMisc JsonPolicy::deserializeImpl(json, *derived()); } - //! Virtual method to return QVariant, used with DBus QVariant lists - virtual QVariant toQVariant() const - { - return Private::MetaTypeHelper::maybeToQVariant(*derived()); - } + //! \copydoc BlackMisc::Mixin::MetaType::toQVariant + using Mixin::MetaType::toQVariant; - //! Set from QVariant - virtual void convertFromQVariant(const QVariant &variant) - { - Private::MetaTypeHelper::maybeConvertFromQVariant(*derived(), variant); - } + //! \copydoc BlackMisc::Mixin::MetaType::convertFromQVariant + using Mixin::MetaType::convertFromQVariant; //! Set property by index virtual void setPropertyByIndex(const CVariant &variant, const CPropertyIndex &index) { PropertyIndexPolicy::setPropertyByIndex(*derived(), variant, index); } @@ -383,11 +434,11 @@ namespace BlackMisc //! Is given variant equal to value of property index? virtual bool equalsPropertyByIndex(const CVariant &compareValue, const CPropertyIndex &index) const { return PropertyIndexPolicy::equalsPropertyByIndex(*derived(), compareValue, index); } - //! Register metadata - static void registerMetadata() - { - MetaTypePolicy::template registerImpl(); - } + //! \copydoc BlackMisc::Mixin::MetaType::isA + using Mixin::MetaType::isA; + + //! \copydoc BlackMisc::Mixin::MetaType::registerMetadata + using Mixin::MetaType::registerMetadata; protected: template @@ -410,22 +461,8 @@ namespace BlackMisc //! String for streaming operators virtual QString stringForStreaming() const { return this->convertToQString(); } - //! Returns the Qt meta type ID of this object. - virtual int getMetaTypeId() const - { - return Private::MetaTypeHelper::maybeGetMetaTypeId(); - } - - /*! - * Returns true if this object is an instance of the class with the given meta type ID, - * or one of its subclasses. - */ - virtual bool isA(int metaTypeId) const - { - if (metaTypeId == QMetaType::UnknownType) { return false; } - if (metaTypeId == maybeGetMetaTypeId()) { return true; } - return BaseOrDummy::isA(metaTypeId); - } + //! \copydoc BlackMisc::Mixin::MetaType::getMetaTypeId + using Mixin::MetaType::getMetaTypeId; public: //! Marshall to DBus @@ -458,15 +495,18 @@ namespace BlackMisc // TODO Implementations of templates that must appear after those includes, should be moved at the same time that policies are refactored. namespace BlackMisc { - template - CVariant CValueObject::toCVariant() const + namespace Mixin { - return CVariant(this->toQVariant()); - } - template - void CValueObject::convertFromCVariant(const CVariant &variant) - { - this->convertFromQVariant(variant.getQVariant()); + template + CVariant MetaType::toCVariant() const + { + return CVariant(derived()->toQVariant()); + } + template + void MetaType::convertFromCVariant(const CVariant &variant) + { + derived()->convertFromQVariant(variant.getQVariant()); + } } template CPropertyIndexList CValueObject::apply(const BlackMisc::CPropertyIndexVariantMap &indexMap, bool skipEqualValues) diff --git a/src/blackmisc/valueobject_private.h b/src/blackmisc/valueobject_private.h index bee0915d0..b896a8a07 100644 --- a/src/blackmisc/valueobject_private.h +++ b/src/blackmisc/valueobject_private.h @@ -15,6 +15,7 @@ #include "blackmisc/blackmiscexport.h" #include #include +#include #include #include @@ -24,6 +25,9 @@ namespace BlackMisc class CVariant; class CPropertyIndex; + template + void registerMetaValueType(); + namespace Private { //! \private Needed so we can copy forward-declared CVariant. @@ -133,6 +137,7 @@ namespace BlackMisc struct MetaTypeHelperImpl { static Q_DECL_CONSTEXPR int maybeGetMetaTypeId() { return qMetaTypeId(); } + static void maybeRegisterMetaType() { qRegisterMetaType(); qDBusRegisterMetaType(); registerMetaValueType(); } static QVariant maybeToQVariant(const T &obj) { return QVariant::fromValue(obj); } static void maybeConvertFromQVariant(T &obj, const QVariant &var) { BlackMisc::setFromQVariant(&obj, var); } }; @@ -142,6 +147,7 @@ namespace BlackMisc struct MetaTypeHelperImpl { static Q_DECL_CONSTEXPR int maybeGetMetaTypeId() { return QMetaType::UnknownType; } + static void maybeRegisterMetaType() {} static QVariant maybeToQVariant(const T &) { return {}; } static void maybeConvertFromQVariant(T &, const QVariant &) {} };