From 1340cec0495fdae68cdac9db301846783ba0bd54 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Mon, 16 Mar 2015 18:20:01 +0000 Subject: [PATCH] refs #356 Extended CValueObjectStdTuple with policy for property indexing. --- src/blackmisc/valueobject.h | 24 ++++++ src/blackmisc/valueobject_policy.h | 120 +++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) diff --git a/src/blackmisc/valueobject.h b/src/blackmisc/valueobject.h index de28dff8a..cd7d38798 100644 --- a/src/blackmisc/valueobject.h +++ b/src/blackmisc/valueobject.h @@ -255,6 +255,7 @@ namespace BlackMisc using Hash = Policy::Hash::Inherit; //!< Hash policy using DBus = Policy::DBus::Inherit; //!< DBus policy using Json = Policy::Json::Inherit; //!< JSON policy + using PropertyIndex = Policy::PropertyIndex::Default; //!< PropertyIndex policy }; /*! @@ -271,6 +272,7 @@ namespace BlackMisc using Hash = Policy::Hash::MetaTuple; //!< Hash policy using DBus = Policy::DBus::MetaTuple; //!< DBus policy using Json = Policy::Json::MetaTuple; //!< JSon policy + using PropertyIndex = Policy::PropertyIndex::Default; //!< PropertyIndex policy }; /*! @@ -295,11 +297,21 @@ namespace BlackMisc using HashPolicy = typename CValueObjectStdTuplePolicy::Hash; using DBusPolicy = typename CValueObjectStdTuplePolicy::DBus; using JsonPolicy = typename CValueObjectStdTuplePolicy::Json; + using PropertyIndexPolicy = typename CValueObjectStdTuplePolicy::PropertyIndex; public: //! Base class using base_type = Base; + //! 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) + { + CPropertyIndexList result; + PropertyIndexPolicy::apply(*derived(), indexMap, result, skipEqualValues); + return result; + } + //! \copydoc CValueObject::getValueHash() virtual uint getValueHash() const override { @@ -332,6 +344,18 @@ namespace BlackMisc return maybeConvertFromQVariant(variant, IsRegisteredQMetaType()); } + //! Set property by index + virtual void setPropertyByIndex(const CVariant &variant, const CPropertyIndex &index) { PropertyIndexPolicy::setPropertyByIndex(*derived(), variant, index); } + + //! Property by index + virtual CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const { CVariant result; PropertyIndexPolicy::propertyByIndex(*derived(), index, result); return result; } + + //! Property by index as String + virtual QString propertyByIndexAsString(const CPropertyIndex &index, bool i18n = false) const { return PropertyIndexPolicy::propertyByIndexAsString(*derived(), index, i18n); } + + //! 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() { diff --git a/src/blackmisc/valueobject_policy.h b/src/blackmisc/valueobject_policy.h index 0f3caadac..2edfc4185 100644 --- a/src/blackmisc/valueobject_policy.h +++ b/src/blackmisc/valueobject_policy.h @@ -18,6 +18,9 @@ namespace BlackMisc { + class CPropertyIndexList; + class CPropertyIndexVariantMap; + template struct CValueObjectStdTuplePolicy; @@ -358,6 +361,123 @@ namespace BlackMisc static void deserializeImpl(const QJsonObject &, T &) {} }; } + + namespace PropertyIndex + { + //! CValueObjectStdTuple policy for PropertyIndex related methods + struct Default + { + //! \private + template + using EnableIfEmptyBase = typename std::enable_if::value>::type *; + + //! \private + template + using DisableIfEmptyBase = typename std::enable_if::value>::type *; + + //! \copydoc CValueObjectStdTuple::apply + //! @{ + template + static void apply(T &obj, const CPropertyIndexVariantMap &indexMap, CPropertyIndexList &o_changed, bool skipEqualValues, DisableIfEmptyBase = nullptr) { o_changed = obj.T::base_type::apply(indexMap, skipEqualValues); } + template + static void apply(T &obj, const CPropertyIndexVariantMap &indexMap, CPropertyIndexList &o_changed, bool skipEqualValues, EnableIfEmptyBase = nullptr) + { + 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); + } + } + //! @} + + //! \copydoc CValueObjectStdTuple::setPropertyByIndex + //! @{ + template + static void setPropertyByIndex(T &obj, const CVariant &variant, const CPropertyIndex &index, DisableIfEmptyBase = nullptr) { return obj.T::base_type::setPropertyByIndex(variant, index); } + template + static void setPropertyByIndex(T &obj, const CVariant &variant, const CPropertyIndex &index, EnableIfEmptyBase = nullptr) + { + if (index.isMyself()) + { + obj.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)); + } + //! @} + + //! \copydoc CValueObjectStdTuple::propertyByIndex + //! @{ + template + static void propertyByIndex(const T &obj, const CPropertyIndex &index, CVariant &o_property, DisableIfEmptyBase = nullptr) { o_property = obj.T::base_type::propertyByIndex(index); } + template + static void propertyByIndex(const T &obj, const CPropertyIndex &index, CVariant &o_property, EnableIfEmptyBase = nullptr) + { + if (index.isMyself()) + { + o_property = obj.toCVariant(); + return; + } + using Base = CValueObjectStdTuple; + auto i = index.frontCasted(); + switch (i) + { + case Base::IndexIcon: + o_property = CVariant::from(obj.toIcon()); + break; + case Base::IndexPixmap: + o_property = CVariant::from(obj.toPixmap()); + break; + case Base::IndexString: + o_property = CVariant(obj.toQString()); + break; + 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)); + } + //! @} + + //! \copydoc CValueObjectStdTuple::propertyByIndexAsString + //! @{ + template + static QString propertyByIndexAsString(const T &obj, const CPropertyIndex &index, bool i18n, DisableIfEmptyBase = nullptr) { return obj.T::base_type::propertyByIndexAsString(index, i18n); } + template + static QString propertyByIndexAsString(const T &obj, const CPropertyIndex &index, bool i18n, EnableIfEmptyBase = nullptr) + { + // default implementation, requires propertyByIndex + return obj.propertyByIndex(index).toQString(i18n); + } + //! @} + + //! \copydoc CValueObjectStdTuple::equalsPropertyByIndex + //! @{ + template + static bool equalsPropertyByIndex(const T &obj, const CVariant &compareValue, const CPropertyIndex &index, DisableIfEmptyBase = nullptr) { return obj.T::base_type::equalsPropertyByIndex(compareValue, index); } + template + static bool equalsPropertyByIndex(const T &obj, const CVariant &compareValue, const CPropertyIndex &index, EnableIfEmptyBase = nullptr) + { + return obj.propertyByIndex(index) == compareValue; + } + //! @} + }; + } } }