diff --git a/src/blackmisc/icon.h b/src/blackmisc/icon.h index e12876572..2a85e2699 100644 --- a/src/blackmisc/icon.h +++ b/src/blackmisc/icon.h @@ -79,6 +79,12 @@ namespace BlackMisc int m_rotateDegrees = 0; QString m_descriptiveText; }; + + namespace Private + { + //! \private Needed so we can copy forward-declared CIcon. + inline void assign(CIcon &a, const CIcon &b) { a = b; } + } } // namespace BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::CIcon, (o.m_index, o.m_descriptiveText)) diff --git a/src/blackmisc/valueobject_private.h b/src/blackmisc/valueobject_private.h index c644f04fb..5be7c865b 100644 --- a/src/blackmisc/valueobject_private.h +++ b/src/blackmisc/valueobject_private.h @@ -25,6 +25,7 @@ namespace BlackMisc class CEmpty; class CVariant; class CPropertyIndex; + class CIcon; template void registerMetaValueType(); @@ -34,6 +35,9 @@ namespace BlackMisc //! \private Needed so we can copy forward-declared CVariant. void assign(CVariant &, const CVariant &); + //! \private Needed so we can copy forward-declared CIcon. + void assign(CIcon &, const CIcon &); + //! \private Abstract base class representing the set of operations supported by a particular value type. struct BLACKMISC_EXPORT IValueObjectMetaInfo { @@ -50,6 +54,7 @@ namespace BlackMisc virtual void propertyByIndex(const void *object, CVariant &o_variant, const BlackMisc::CPropertyIndex &index) const = 0; virtual QString propertyByIndexAsString(const void *object, const CPropertyIndex &index, bool i18n) const = 0; virtual bool equalsPropertyByIndex(const void *object, const CVariant &compareValue, const CPropertyIndex &index) const = 0; + virtual void toIcon(const void *object, CIcon &o_icon) const = 0; }; //! \private Fallback in case qHash is not defined for T. @@ -65,13 +70,28 @@ namespace BlackMisc struct CValueObjectMetaInfo : public IValueObjectMetaInfo { // http://en.wikibooks.org/wiki/More_C++_Idioms/Member_Detector - struct Fallback { int toJson, convertFromJson; }; + struct Fallback { int toJson, convertFromJson, setPropertyByIndex, propertyByIndex, propertyByIndexAsString, equalsPropertyByIndex, toIcon; }; template struct int_t { typedef int type; }; template struct Derived : public U, public Fallback {}; - template static QJsonObject toJsonHelper(const U &, typename int_t<&Derived::toJson>::type) { return {}; } +# define DISABLE_IF_HAS(MEMBER) typename int_t<&Derived::MEMBER>::type + + template static QJsonObject toJsonHelper(const U &, DISABLE_IF_HAS(toJson)) { return {}; } template static QJsonObject toJsonHelper(const U &object, ...) { return object.toJson(); } - template static void convertFromJsonHelper(const QJsonObject &, U &, typename int_t<&Derived::convertFromJson>::type) {} + template static void convertFromJsonHelper(const QJsonObject &, U &, DISABLE_IF_HAS(convertFromJson)) {} template static void convertFromJsonHelper(const QJsonObject &json, U &object, ...) { object.convertFromJson(json); } + template static void setPropertyByIndexHelper(U &, const CVariant &, const CPropertyIndex &, DISABLE_IF_HAS(setPropertyByIndex)) {} + template static void setPropertyByIndexHelper(U &object, const CVariant &variant, const CPropertyIndex &index, ...) { object.setPropertyByIndex(variant, index); } + template static void propertyByIndexHelper(CVariant &, const U &, const CPropertyIndex &, DISABLE_IF_HAS(propertyByIndex)) {} + template static void propertyByIndexHelper(CVariant &o_variant, const U &object, const CPropertyIndex &index, ...) { assign(o_variant, object.propertyByIndex(index)); } + template static QString propertyByIndexAsStringHelper(const U &, const CPropertyIndex &, bool, DISABLE_IF_HAS(propertyByIndexAsString)) { return {}; } + template static QString propertyByIndexAsStringHelper(const U &object, const CPropertyIndex &index, bool i18n, ...) { return object.propertyByIndexAsString(index, i18n); } + template static bool equalsPropertyByIndexHelper(const U &, const CVariant &, const CPropertyIndex &, DISABLE_IF_HAS(equalsPropertyByIndex)) { return false; } + template static bool equalsPropertyByIndexHelper(const U &object, const CVariant &variant, const CPropertyIndex &index, ...) { return object.equalsPropertyByIndex(variant, index); } + template static void toIconHelper(const U &, CIcon &, DISABLE_IF_HAS(toIcon)) {} + template static void toIconHelper(const U &, CIcon &, typename std::enable_if::value, int>::type) {} // CIcon is incomplete when CValueObjectMetaInfo is instantiated + template static void toIconHelper(const U &object, CIcon &o_icon, ...) { assign(o_icon, object.toIcon()); } + +# undef DISABLE_IF_HAS virtual QString toQString(const void *object, bool i18n) const override { @@ -108,19 +128,23 @@ namespace BlackMisc } virtual void setPropertyByIndex(void *object, const CVariant &variant, const CPropertyIndex &index) const override { - cast(object).setPropertyByIndex(variant, index); + setPropertyByIndexHelper(cast(object), variant, index, 0); } virtual void propertyByIndex(const void *object, CVariant &o_variant, const BlackMisc::CPropertyIndex &index) const override { - assign(o_variant, cast(object).propertyByIndex(index)); + propertyByIndexHelper(o_variant, cast(object), index, 0); } virtual QString propertyByIndexAsString(const void *object, const CPropertyIndex &index, bool i18n) const override { - return cast(object).propertyByIndexAsString(index, i18n); + return propertyByIndexAsStringHelper(cast(object), index, i18n, 0); } virtual bool equalsPropertyByIndex(const void *object, const CVariant &compareValue, const CPropertyIndex &index) const override { - return cast(object).equalsPropertyByIndex(compareValue, index); + return equalsPropertyByIndexHelper(cast(object), compareValue, index, 0); + } + virtual void toIcon(const void *object, CIcon &o_icon) const override + { + toIconHelper(cast(object), o_icon, 0); } static const T &cast(const void *object) { return *static_cast(object); } diff --git a/src/blackmisc/variant.cpp b/src/blackmisc/variant.cpp index 7b8289033..ce76aa88d 100644 --- a/src/blackmisc/variant.cpp +++ b/src/blackmisc/variant.cpp @@ -9,6 +9,7 @@ #include "variant.h" #include "blackmiscfreefunctions.h" +#include "icon.h" #include #include #include @@ -216,4 +217,18 @@ namespace BlackMisc return meta->equalsPropertyByIndex(data(), compareValue, index); } + CIcon CVariant::toIcon() const + { + auto *meta = getValueObjectMetaInfo(); + if (! meta) { return {}; } + CIcon result; + meta->toIcon(data(), result); + return result; + } + + QPixmap CVariant::toPixmap() const + { + return toIcon().toPixmap(); + } + } // namespace diff --git a/src/blackmisc/variant.h b/src/blackmisc/variant.h index 444610270..3e4d106f3 100644 --- a/src/blackmisc/variant.h +++ b/src/blackmisc/variant.h @@ -26,6 +26,8 @@ class QDBusArgument; namespace BlackMisc { + class CIcon; + /*! * Wrapper around QVariant which provides transparent access to CValueObject methods * of the contained object if it is registered with BlackMisc::registerMetaValueType. @@ -199,6 +201,12 @@ namespace BlackMisc //! \copydoc CValueObject::equalsPropertyByIndex bool equalsPropertyByIndex(const CVariant &compareValue, const CPropertyIndex &index) const; + //! \copydoc CValueObject::toPixmap + QPixmap toPixmap() const; + + //! \copydoc CValueObject::toIcon + CIcon toIcon() const; + private: QVariant m_v;