#pragma once #include "cafAppEnum.h" #include "cafFilePath.h" #include "cafPdmPointer.h" #include #include #include #include namespace caf { //================================================================================================== /// A proxy class that implements the generic QVariant interface for a field /// /// This class collects methods that need specialization when introducing a new type in a PdmField. /// Having those methods in a separate class makes it possible to "partially specialize" the methods /// for container classes etc. since partial specialization of template functions is not C++ as of yet. /// /// When introducing a new type in a PdmField, you might need to implement a (partial)specialization /// of this class. //================================================================================================== template class PdmValueFieldSpecialization { public: /// Convert the field value into a QVariant static QVariant convert(const T& value) { return QVariant::fromValue(value); } /// Set the field value from a QVariant static void setFromVariant(const QVariant& variantValue, T& value) { value = variantValue.value(); } /// Check equality between QVariants that carries a Field Value. /// The == operator will normally work, but does not support custom types in the QVariant /// See http://qt-project.org/doc/qt-4.8/qvariant.html#operator-eq-eq-64 /// Using the == between the real types is more safe. static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2) { return variantValue.value() == variantValue2.value(); } }; //================================================================================================== /// Partial specialization for caf::AppEnum //================================================================================================== template class PdmValueFieldSpecialization > { public: static QVariant convert(const caf::AppEnum& value) { T enumValue = value; // Explicit cast to an int before storage in a QVariant. This allows the use of enum class instead of enum return QVariant(static_cast(enumValue)); } static void setFromVariant(const QVariant& variantValue, caf::AppEnum& value) { value = static_cast(variantValue.toInt()); } static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2) { return variantValue == variantValue2; } }; //================================================================================================== /// Partial specialization for caf::PdmPointer /// Used internally to avoid havning to declare everything Q_DECLARE_METATYPE() /// User must use PdmPtrField or PdmChildField //================================================================================================== template class PdmValueFieldSpecialization > { public: static QVariant convert(const PdmPointer& value) { return QVariant::fromValue(PdmPointer(value.rawPtr())); } static void setFromVariant(const QVariant& variantValue, caf::PdmPointer& value) { value.setRawPtr(variantValue.value >().rawPtr()); } static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2) { return variantValue.value >() == variantValue2.value >() ; } }; //================================================================================================== /// Partial specialization for std::vector //================================================================================================== template class PdmValueFieldSpecialization > { public: static QVariant convert(const std::vector& value) { QList returnList; typename std::vector::const_iterator it; for (it = value.begin(); it != value.end() ; ++it) { returnList.push_back(PdmValueFieldSpecialization::convert(*it)); } return returnList; } static void setFromVariant(const QVariant& variantValue, std::vector& value) { if (variantValue.canConvert< QList >()) { value.clear(); QList lst = variantValue.toList(); for (int i = 0; i < lst.size(); ++i) { T val; PdmValueFieldSpecialization::setFromVariant(lst[i], val); value.push_back(val); } } } static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2) { return variantValue == variantValue2; } }; //================================================================================================== /// Partial specialization for caf::FilePath //================================================================================================== template <> class PdmValueFieldSpecialization { public: static QVariant convert(const FilePath& value) { return QVariant(value.path()); } static void setFromVariant(const QVariant& variantValue, FilePath& value) { value.setPath(variantValue.toString()); } static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2) { return variantValue.toString() == variantValue2.toString(); } }; } // End of namespace caf