refs #413 Decomposed metatype-related functions of CValueObject into a dedicated class Mixin::MetaType,

bypassing the old Policy::MetaType classes. The ultimate intention is to decompose all the aspects of
CValueObject into separate mixins in this manner, and have derived classes inherit from the mixins directly.
Splitting the responsibilities of CValueObject into separate classes will reduce the coupling between different
cross-cutting concerns and allow us to untangle the web of interdependencies and greatly simplify things.
This commit is contained in:
Mathew Sutcliffe
2015-04-29 01:31:06 +01:00
parent 6fd3c78d33
commit d9faa031d2
7 changed files with 99 additions and 74 deletions

View File

@@ -48,6 +48,11 @@
* \brief Iterator classes for the containers. * \brief Iterator classes for the containers.
*/ */
/*!
* \namespace BlackMisc::Mixin
* \brief Mixin classes which implement common operations for value classes.
*/
/*! /*!
* \namespace BlackMisc::Policy * \namespace BlackMisc::Policy
* \brief Policy classes for CValueObject. * \brief Policy classes for CValueObject.

View File

@@ -158,7 +158,7 @@ namespace BlackMisc
} }
//! \copydoc BlackMisc::CValueObject::getMetaTypeId //! \copydoc BlackMisc::CValueObject::getMetaTypeId
virtual int getMetaTypeId() const override { return qMetaTypeId<C<T>>(); } int getMetaTypeId() const { return qMetaTypeId<C<T>>(); }
//! \copydoc BlackMisc::CValueObject::marshallToDbus //! \copydoc BlackMisc::CValueObject::marshallToDbus
virtual void marshallToDbus(QDBusArgument &argument) const override virtual void marshallToDbus(QDBusArgument &argument) const override

View File

@@ -421,9 +421,6 @@ namespace BlackMisc
return str += "}"; return str += "}";
} }
//! \copydoc BlackMisc::CValueObject::getMetaTypeId
virtual int getMetaTypeId() const override { return qMetaTypeId<CDictionary>(); }
//! \copydoc BlackMisc::CValueObject::marshallToDbus //! \copydoc BlackMisc::CValueObject::marshallToDbus
virtual void marshallToDbus(QDBusArgument &argument) const override virtual void marshallToDbus(QDBusArgument &argument) const override
{ {

View File

@@ -109,14 +109,6 @@ namespace BlackMisc
return s; return s;
} }
/*
* metaTypeId
*/
int CPropertyIndexVariantMap::getMetaTypeId() const
{
return qMetaTypeId<CPropertyIndexVariantMap>();
}
/* /*
* Marshall to DBus * Marshall to DBus
*/ */
@@ -181,15 +173,6 @@ namespace BlackMisc
return CPropertyIndexList::fromImpl(this->m_values.keys()); return CPropertyIndexList::fromImpl(this->m_values.keys());
} }
/*
* Register metadata
*/
void CPropertyIndexVariantMap::registerMetadata()
{
qRegisterMetaType<CPropertyIndexVariantMap>();
qDBusRegisterMetaType<CPropertyIndexVariantMap>();
}
/* /*
* Hash * Hash
*/ */

View File

@@ -146,9 +146,6 @@ namespace BlackMisc
//! \copydoc CValueObject::convertFromQVariant //! \copydoc CValueObject::convertFromQVariant
virtual void convertFromQVariant(const QVariant &variant) override { BlackMisc::setFromQVariant(this, variant); } virtual void convertFromQVariant(const QVariant &variant) override { BlackMisc::setFromQVariant(this, variant); }
//! register metadata
static void registerMetadata();
protected: protected:
QMap<CPropertyIndex, CVariant> m_values; //!< values QMap<CPropertyIndex, CVariant> m_values; //!< values
@@ -157,9 +154,6 @@ namespace BlackMisc
//! \copydoc CValueObject::convertToQString //! \copydoc CValueObject::convertToQString
virtual QString convertToQString(bool i18n = false) const override; virtual QString convertToQString(bool i18n = false) const override;
//! \copydoc CValueObject::getMetaTypeId
virtual int getMetaTypeId() const override;
//! \copydoc CValueObject::marshallToDbus //! \copydoc CValueObject::marshallToDbus
virtual void marshallToDbus(QDBusArgument &argument) const override; virtual void marshallToDbus(QDBusArgument &argument) const override;

View File

@@ -119,9 +119,6 @@ namespace BlackMisc
//! From JSON //! From JSON
static void convertFromJson(const QJsonObject &) {} static void convertFromJson(const QJsonObject &) {}
//! Is a
static bool isA(int) { return false; }
//! Marshall to DBus //! Marshall to DBus
static void marshallToDbus(QDBusArgument &) {} static void marshallToDbus(QDBusArgument &) {}
@@ -185,6 +182,66 @@ namespace BlackMisc
using Json = Policy::Json::Own; //!< JSon policy 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 Derived>
class MetaType
{
public:
//! Register metadata
static void registerMetadata()
{
Private::MetaTypeHelper<Derived>::maybeRegisterMetaType();
}
//! Returns the Qt meta type ID of this object.
int getMetaTypeId() const
{
return Private::MetaTypeHelper<Derived>::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<const typename Derived::base_type *>(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<Derived>::maybeToQVariant(*derived());
}
//! Set from QVariant
//! \todo remove virtual
virtual void convertFromQVariant(const QVariant &variant)
{
return Private::MetaTypeHelper<Derived>::maybeConvertFromQVariant(*derived(), variant);
}
private:
const Derived *derived() const { return static_cast<const Derived *>(this); }
Derived *derived() { return static_cast<Derived *>(this); }
template <typename Base2> 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. * Standard implementation of CValueObject using meta tuple system.
* *
@@ -197,13 +254,13 @@ namespace BlackMisc
*/ */
template <class Derived, class Base /*= CEmpty*/> class CValueObject : template <class Derived, class Base /*= CEmpty*/> class CValueObject :
public Base, public Base,
public Mixin::MetaType<Derived>,
private CValueObjectPolicy<Derived>::Equals::template Ops<Derived, Base>, private CValueObjectPolicy<Derived>::Equals::template Ops<Derived, Base>,
private CValueObjectPolicy<Derived>::LessThan::template Ops<Derived, Base>, private CValueObjectPolicy<Derived>::LessThan::template Ops<Derived, Base>,
private CValueObjectPolicy<Derived>::Compare::template Ops<Derived, Base> private CValueObjectPolicy<Derived>::Compare::template Ops<Derived, Base>
{ {
static_assert(std::is_same<CEmpty, Base>::value || IsValueObject<Base>::value, "Base must be either CEmpty or derived from CValueObject"); static_assert(std::is_same<CEmpty, Base>::value || IsValueObject<Base>::value, "Base must be either CEmpty or derived from CValueObject");
using MetaTypePolicy = typename CValueObjectPolicy<Derived>::MetaType;
using HashPolicy = typename CValueObjectPolicy<Derived>::Hash; using HashPolicy = typename CValueObjectPolicy<Derived>::Hash;
using DBusPolicy = typename CValueObjectPolicy<Derived>::DBus; using DBusPolicy = typename CValueObjectPolicy<Derived>::DBus;
using JsonPolicy = typename CValueObjectPolicy<Derived>::Json; using JsonPolicy = typename CValueObjectPolicy<Derived>::Json;
@@ -333,11 +390,11 @@ namespace BlackMisc
//! \return number of values changed, with skipEqualValues equal values will not be changed //! \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 CPropertyIndexList apply(const BlackMisc::CPropertyIndexVariantMap &indexMap, bool skipEqualValues = false); // implemented later due to cyclic include dependency
//! Method to return CVariant //! \copydoc BlackMisc::Mixin::MetaType::toCVariant
CVariant toCVariant() const; using Mixin::MetaType<Derived>::toCVariant;
//! Set from CVariant //! \copydoc BlackMisc::Mixin::MetaType::convertFromCVariant
void convertFromCVariant(const CVariant &variant); using Mixin::MetaType<Derived>::convertFromCVariant;
//! Value hash, allows comparisons between QVariants //! Value hash, allows comparisons between QVariants
virtual uint getValueHash() const virtual uint getValueHash() const
@@ -359,17 +416,11 @@ namespace BlackMisc
JsonPolicy::deserializeImpl(json, *derived()); JsonPolicy::deserializeImpl(json, *derived());
} }
//! Virtual method to return QVariant, used with DBus QVariant lists //! \copydoc BlackMisc::Mixin::MetaType::toQVariant
virtual QVariant toQVariant() const using Mixin::MetaType<Derived>::toQVariant;
{
return Private::MetaTypeHelper<Derived>::maybeToQVariant(*derived());
}
//! Set from QVariant //! \copydoc BlackMisc::Mixin::MetaType::convertFromQVariant
virtual void convertFromQVariant(const QVariant &variant) using Mixin::MetaType<Derived>::convertFromQVariant;
{
Private::MetaTypeHelper<Derived>::maybeConvertFromQVariant(*derived(), variant);
}
//! Set property by index //! Set property by index
virtual void setPropertyByIndex(const CVariant &variant, const CPropertyIndex &index) { PropertyIndexPolicy::setPropertyByIndex(*derived(), variant, 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? //! 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); } virtual bool equalsPropertyByIndex(const CVariant &compareValue, const CPropertyIndex &index) const { return PropertyIndexPolicy::equalsPropertyByIndex(*derived(), compareValue, index); }
//! Register metadata //! \copydoc BlackMisc::Mixin::MetaType::isA
static void registerMetadata() using Mixin::MetaType<Derived>::isA;
{
MetaTypePolicy::template registerImpl<Derived>(); //! \copydoc BlackMisc::Mixin::MetaType::registerMetadata
} using Mixin::MetaType<Derived>::registerMetadata;
protected: protected:
template <typename T> template <typename T>
@@ -410,22 +461,8 @@ namespace BlackMisc
//! String for streaming operators //! String for streaming operators
virtual QString stringForStreaming() const { return this->convertToQString(); } virtual QString stringForStreaming() const { return this->convertToQString(); }
//! Returns the Qt meta type ID of this object. //! \copydoc BlackMisc::Mixin::MetaType::getMetaTypeId
virtual int getMetaTypeId() const using Mixin::MetaType<Derived>::getMetaTypeId;
{
return Private::MetaTypeHelper<Derived>::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<Derived>()) { return true; }
return BaseOrDummy::isA(metaTypeId);
}
public: public:
//! Marshall to DBus //! 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. // TODO Implementations of templates that must appear after those includes, should be moved at the same time that policies are refactored.
namespace BlackMisc namespace BlackMisc
{ {
template <class Derived, class Base> namespace Mixin
CVariant CValueObject<Derived, Base>::toCVariant() const
{ {
return CVariant(this->toQVariant()); template <class Derived>
} CVariant MetaType<Derived>::toCVariant() const
template <class Derived, class Base> {
void CValueObject<Derived, Base>::convertFromCVariant(const CVariant &variant) return CVariant(derived()->toQVariant());
{ }
this->convertFromQVariant(variant.getQVariant()); template <class Derived>
void MetaType<Derived>::convertFromCVariant(const CVariant &variant)
{
derived()->convertFromQVariant(variant.getQVariant());
}
} }
template <class Derived, class Base> template <class Derived, class Base>
CPropertyIndexList CValueObject<Derived, Base>::apply(const BlackMisc::CPropertyIndexVariantMap &indexMap, bool skipEqualValues) CPropertyIndexList CValueObject<Derived, Base>::apply(const BlackMisc::CPropertyIndexVariantMap &indexMap, bool skipEqualValues)

View File

@@ -15,6 +15,7 @@
#include "blackmisc/blackmiscexport.h" #include "blackmisc/blackmiscexport.h"
#include <QString> #include <QString>
#include <QMetaType> #include <QMetaType>
#include <QDBusMetaType>
#include <QDBusArgument> #include <QDBusArgument>
#include <QJsonObject> #include <QJsonObject>
@@ -24,6 +25,9 @@ namespace BlackMisc
class CVariant; class CVariant;
class CPropertyIndex; class CPropertyIndex;
template <typename T>
void registerMetaValueType();
namespace Private namespace Private
{ {
//! \private Needed so we can copy forward-declared CVariant. //! \private Needed so we can copy forward-declared CVariant.
@@ -133,6 +137,7 @@ namespace BlackMisc
struct MetaTypeHelperImpl struct MetaTypeHelperImpl
{ {
static Q_DECL_CONSTEXPR int maybeGetMetaTypeId() { return qMetaTypeId<T>(); } static Q_DECL_CONSTEXPR int maybeGetMetaTypeId() { return qMetaTypeId<T>(); }
static void maybeRegisterMetaType() { qRegisterMetaType<T>(); qDBusRegisterMetaType<T>(); registerMetaValueType<T>(); }
static QVariant maybeToQVariant(const T &obj) { return QVariant::fromValue(obj); } static QVariant maybeToQVariant(const T &obj) { return QVariant::fromValue(obj); }
static void maybeConvertFromQVariant(T &obj, const QVariant &var) { BlackMisc::setFromQVariant(&obj, var); } static void maybeConvertFromQVariant(T &obj, const QVariant &var) { BlackMisc::setFromQVariant(&obj, var); }
}; };
@@ -142,6 +147,7 @@ namespace BlackMisc
struct MetaTypeHelperImpl<T, /* IsRegisteredMetaType = */ false> struct MetaTypeHelperImpl<T, /* IsRegisteredMetaType = */ false>
{ {
static Q_DECL_CONSTEXPR int maybeGetMetaTypeId() { return QMetaType::UnknownType; } static Q_DECL_CONSTEXPR int maybeGetMetaTypeId() { return QMetaType::UnknownType; }
static void maybeRegisterMetaType() {}
static QVariant maybeToQVariant(const T &) { return {}; } static QVariant maybeToQVariant(const T &) { return {}; }
static void maybeConvertFromQVariant(T &, const QVariant &) {} static void maybeConvertFromQVariant(T &, const QVariant &) {}
}; };