From 75f46068e19296611e177fb42174cd656351ba9f Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Fri, 1 May 2015 19:20:38 +0100 Subject: [PATCH] refs #413 Decomposed property indexing functions of CValueObject into Mixin::Index. --- src/blackmisc/valueobject.h | 244 +++++++++++++++++++++--------------- 1 file changed, 140 insertions(+), 104 deletions(-) diff --git a/src/blackmisc/valueobject.h b/src/blackmisc/valueobject.h index e3243bc26..41ee99915 100644 --- a/src/blackmisc/valueobject.h +++ b/src/blackmisc/valueobject.h @@ -616,6 +616,62 @@ namespace BlackMisc Derived *derived() { return static_cast(this); } }; + /*! + * CRTP class template from which a derived class can inherit property indexing functions. + */ + template + class Index + { + public: + //! Update by variant map + //! \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 + + //! Set property by index + virtual void setPropertyByIndex(const CVariant &variant, const CPropertyIndex &index); // implemented later due to cyclic include dependency + + //! Property by index + virtual CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const; // implemented later due to cyclic include dependency + + //! Property by index as String + virtual QString propertyByIndexAsString(const CPropertyIndex &index, bool i18n = false) const; // implemented later due to cyclic include dependency + + //! Is given variant equal to value of property index? + virtual bool equalsPropertyByIndex(const CVariant &compareValue, const CPropertyIndex &index) const; // implemented later due to cyclic include dependency + + private: + const Derived *derived() const { return static_cast(this); } + Derived *derived() { return static_cast(this); } + }; + + /*! + * Specialization of Index for classes further down an inheritance hierarchy. + */ + template + class Index + { + public: + //! Update by variant map + //! \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 + + //! Set property by index + virtual void setPropertyByIndex(const CVariant &variant, const CPropertyIndex &index) { derived()->Derived::base_type::setPropertyByIndex(variant, index); } + + //! Property by index + virtual CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const; // implemented later due to cyclic include dependency + + //! Property by index as String + virtual QString propertyByIndexAsString(const CPropertyIndex &index, bool i18n = false) const { return derived()->Derived::base_type::propertyByIndexAsString(index, i18n); } + + //! Is given variant equal to value of property index? + virtual bool equalsPropertyByIndex(const CVariant &compareValue, const CPropertyIndex &index) const { return derived()->Derived::base_type::equalsPropertyByIndex(compareValue, index); } + + private: + const Derived *derived() const { return static_cast(this); } + Derived *derived() { return static_cast(this); } + }; + } /*! @@ -637,12 +693,11 @@ namespace BlackMisc public Mixin::EqualsByTuple::value>, public Mixin::LessThanByTuple::value>, public Mixin::CompareByTuple::value>, - public Mixin::String + public Mixin::String, + public Mixin::Index::value> { static_assert(std::is_same::value || IsValueObject::value, "Base must be either CEmpty or derived from CValueObject"); - using PropertyIndexPolicy = typename CValueObjectPolicy::PropertyIndex; - public: //! Base class using base_type = Base; @@ -667,9 +722,8 @@ namespace BlackMisc //! \copydoc BlackMisc::Mixin::String::toStdString using Mixin::String::toStdString; - //! Update by variant map - //! \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 + //! \copydoc BlackMisc::Mixin::Index::apply + using Mixin::Index::value>::apply; //! \copydoc BlackMisc::Mixin::MetaType::toCVariant using Mixin::MetaType::toCVariant; @@ -689,17 +743,17 @@ namespace BlackMisc //! \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); } + //! \copydoc BlackMisc::Mixin::Index::setPropertyByIndex + using Mixin::Index::value>::setPropertyByIndex; - //! Property by index - virtual CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const; // implemented later due to cyclic include dependency + //! \copydoc BlackMisc::Mixin::Index::propertyByIndex + using Mixin::Index::value>::propertyByIndex; - //! Property by index as String - virtual QString propertyByIndexAsString(const CPropertyIndex &index, bool i18n = false) const { return PropertyIndexPolicy::propertyByIndexAsString(*derived(), index, i18n); } + //! \copydoc BlackMisc::Mixin::Index::propertyByIndexAsString + using Mixin::Index::value>::propertyByIndexAsString; - //! 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); } + //! \copydoc BlackMisc::Mixin::Index::equalsPropertyByIndex + using Mixin::Index::value>::equalsPropertyByIndex; //! \copydoc BlackMisc::Mixin::MetaType::isA using Mixin::MetaType::isA; @@ -708,9 +762,6 @@ namespace BlackMisc using Mixin::MetaType::registerMetadata; protected: - template - friend struct Private::CValueObjectMetaInfo; - //! Default constructor. CValueObject() = default; @@ -737,10 +788,6 @@ namespace BlackMisc //! \copydoc BlackMisc::Mixin::DBusByTuple::unmarshallFromDbus using Mixin::DBusByTuple::value>::unmarshallFromDbus; - - private: - const Derived *derived() const { return static_cast(this); } - Derived *derived() { return static_cast(this); } }; } // namespace @@ -766,97 +813,86 @@ namespace BlackMisc { derived()->convertFromQVariant(variant.getQVariant()); } - } - template - CPropertyIndexList CValueObject::apply(const BlackMisc::CPropertyIndexVariantMap &indexMap, bool skipEqualValues) - { - CPropertyIndexList result; - PropertyIndexPolicy::apply(*derived(), indexMap, result, skipEqualValues); - return result; - } - template - CVariant CValueObject::propertyByIndex(const BlackMisc::CPropertyIndex &index) const - { - CVariant result; - PropertyIndexPolicy::propertyByIndex(*derived(), index, result); - return result; - } - namespace Policy - { - namespace PropertyIndex + template + CPropertyIndexList Index::apply(const BlackMisc::CPropertyIndexVariantMap &indexMap, bool skipEqualValues) { - template - void Default::apply(T &obj, const CPropertyIndexVariantMap &indexMap, CPropertyIndexList &o_changed, bool skipEqualValues, Default::EnableIfEmptyBase) - { - if (indexMap.isEmpty()) return; + return derived()->Derived::base_type::apply(indexMap, skipEqualValues); + } + template + CVariant Index::propertyByIndex(const BlackMisc::CPropertyIndex &index) const + { + return derived()->Derived::base_type::propertyByIndex(index); + } + template + CPropertyIndexList Index::apply(const BlackMisc::CPropertyIndexVariantMap &indexMap, bool skipEqualValues) + { + if (indexMap.isEmpty()) return {}; - const auto &map = indexMap.map(); - for (auto it = map.begin(); it != map.end(); ++it) - { - const CVariant value = it.value().toCVariant(); - const CPropertyIndex index = it.key(); - if (skipEqualValues) - { - bool equal = obj.equalsPropertyByIndex(value, index); - if (equal) { continue; } - } - obj.setPropertyByIndex(value, index); - o_changed.push_back(index); - } - } - template - void Default::setPropertyByIndex(T &obj, const CVariant &variant, const CPropertyIndex &index, Default::EnableIfEmptyBase) + CPropertyIndexList changed; + const auto &map = indexMap.map(); + for (auto it = map.begin(); it != map.end(); ++it) { - if (index.isMyself()) + const CVariant value = it.value().toCVariant(); + const CPropertyIndex index = it.key(); + if (skipEqualValues) { - obj.convertFromCVariant(variant); - return; + bool equal = derived()->equalsPropertyByIndex(value, index); + if (equal) { continue; } } + derived()->setPropertyByIndex(value, index); + changed.push_back(index); + } + return changed; + } + template + void Index::setPropertyByIndex(const CVariant &variant, const CPropertyIndex &index) + { + if (index.isMyself()) + { + derived()->convertFromCVariant(variant); + return; + } - // not all classes have implemented nesting - const QString m = QString("Property by index not found (setter), index: ").append(index.toQString()); - qFatal("%s", qPrintable(m)); - } - template - void Default::propertyByIndex(const T &obj, const CPropertyIndex &index, CVariant &o_property, Default::EnableIfEmptyBase) + // not all classes have implemented nesting + const QString m = QString("Property by index not found (setter), index: ").append(index.toQString()); + qFatal("%s", qPrintable(m)); + } + template + CVariant Index::propertyByIndex(const CPropertyIndex &index) const + { + if (index.isMyself()) { - if (index.isMyself()) - { - o_property = obj.toCVariant(); - return; - } - using Base = CValueObject; - auto i = index.frontCasted::ColumnIndex>(); - switch (i) - { - case Base::IndexIcon: - o_property = CVariant::from(obj.toIcon()); - return; - case Base::IndexPixmap: - o_property = CVariant::from(obj.toPixmap()); - return; - case Base::IndexString: - o_property = CVariant(obj.toQString()); - return; - default: - break; - } + return derived()->toCVariant(); + } + using Base = CValueObject; + auto i = index.frontCasted::ColumnIndex>(); + switch (i) + { + case Base::IndexIcon: + return CVariant::from(derived()->toIcon()); + case Base::IndexPixmap: + return CVariant::from(derived()->toPixmap()); + case Base::IndexString: + return CVariant(derived()->toQString()); + default: + break; + } - // not all classes have implemented nesting - const QString m = QString("Property by index not found, index: ").append(index.toQString()); - qFatal("%s", qPrintable(m)); - } - template - QString Default::propertyByIndexAsString(const T &obj, const CPropertyIndex &index, bool i18n, Default::EnableIfEmptyBase) - { - // default implementation, requires propertyByIndex - return obj.propertyByIndex(index).toQString(i18n); - } - template - bool Default::equalsPropertyByIndex(const T &obj, const CVariant &compareValue, const CPropertyIndex &index, Default::EnableIfEmptyBase) - { - return obj.propertyByIndex(index) == compareValue; - } + // not all classes have implemented nesting + const QString m = QString("Property by index not found, index: ").append(index.toQString()); + qFatal("%s", qPrintable(m)); + return {}; + } + template + QString Index::propertyByIndexAsString(const CPropertyIndex &index, bool i18n) const + { + // default implementation, requires propertyByIndex + return derived()->propertyByIndex(index).toQString(i18n); + } + template + bool Index::equalsPropertyByIndex(const CVariant &compareValue, const CPropertyIndex &index) const + { + return derived()->propertyByIndex(index) == compareValue; } } }