diff --git a/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmUiCoreMat3d.h b/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmUiCoreMat3d.h index 8daeb01405..67e1b06a45 100644 --- a/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmUiCoreMat3d.h +++ b/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmUiCoreMat3d.h @@ -38,44 +38,7 @@ #include "cafPdmCoreMat3d.h" -#include "cafInternalPdmValueFieldSpecializations.h" -#include "cafPdmUiFieldSpecialization.h" #include "cafPdmUiItem.h" #include "cvfBase.h" #include "cvfMatrix3.h" - -namespace caf -{ -template <> -class PdmUiFieldSpecialization -{ -public: - /// Convert the field value into a QVariant - static QVariant convert( const cvf::Mat3d& value ) - { - return PdmValueFieldSpecialization::convert( value ); - } - - /// Set the field value from a QVariant - static void setFromVariant( const QVariant& variantValue, cvf::Mat3d& value ) - { - PdmValueFieldSpecialization::setFromVariant( variantValue, value ); - } - - static bool isDataElementEqual( const QVariant& variantValue, const QVariant& variantValue2 ) - { - return PdmValueFieldSpecialization::isEqual( variantValue, variantValue2 ); - } - - /// Methods to get a list of options for a field, specialized for AppEnum - static QList valueOptions( QString keyword, const cvf::Mat3d& ) - { - return QList(); - } - - /// Methods to retrieve the possible PdmObject pointed to by a field - static void childObjects( const PdmDataValueField&, std::vector* ) {} -}; - -} // end namespace caf diff --git a/Fwk/AppFwk/cafPdmCvf/cafPdmUiCoreColor3f.h b/Fwk/AppFwk/cafPdmCvf/cafPdmUiCoreColor3f.h index aa445248f5..21e0028c97 100644 --- a/Fwk/AppFwk/cafPdmCvf/cafPdmUiCoreColor3f.h +++ b/Fwk/AppFwk/cafPdmCvf/cafPdmUiCoreColor3f.h @@ -39,47 +39,10 @@ #include "cvfBase.h" #include "cvfColor3.h" -#include "cafInternalPdmValueFieldSpecializations.h" -#include "cafPdmUiFieldSpecialization.h" #include "cafPdmUiItem.h" #include "cafPdmCoreColor3f.h" -namespace caf -{ -template <> -class PdmUiFieldSpecialization -{ -public: - /// Convert the field value into a QVariant - static QVariant convert( const cvf::Color3f& value ) - { - return PdmValueFieldSpecialization::convert( value ); - } - - /// Set the field value from a QVariant - static void setFromVariant( const QVariant& variantValue, cvf::Color3f& value ) - { - PdmValueFieldSpecialization::setFromVariant( variantValue, value ); - } - - static bool isDataElementEqual( const QVariant& variantValue, const QVariant& variantValue2 ) - { - return PdmValueFieldSpecialization::isEqual( variantValue, variantValue2 ); - } - - /// Methods to get a list of options for a field, specialized for AppEnum - static QList valueOptions( QString keyword, const cvf::Color3f& ) - { - return QList(); - } - - /// Methods to retrieve the possible PdmObject pointed to by a field - static void childObjects( const PdmDataValueField&, std::vector* ) {} -}; - -} // end namespace caf - //-------------------------------------------------------------------------------------------------- // If the macro for registering the editor is put as the single statement // in a cpp file, a dummy static class must be used to make sure the compile unit diff --git a/Fwk/AppFwk/cafPdmCvf/cafPdmUiCoreMat4d.h b/Fwk/AppFwk/cafPdmCvf/cafPdmUiCoreMat4d.h index 1634d92ef0..1918024724 100644 --- a/Fwk/AppFwk/cafPdmCvf/cafPdmUiCoreMat4d.h +++ b/Fwk/AppFwk/cafPdmCvf/cafPdmUiCoreMat4d.h @@ -38,44 +38,7 @@ #include "cafPdmCoreMat4d.h" -#include "cafInternalPdmValueFieldSpecializations.h" -#include "cafPdmUiFieldSpecialization.h" #include "cafPdmUiItem.h" #include "cvfBase.h" #include "cvfMatrix4.h" - -namespace caf -{ -template <> -class PdmUiFieldSpecialization -{ -public: - /// Convert the field value into a QVariant - static QVariant convert( const cvf::Mat4d& value ) - { - return PdmValueFieldSpecialization::convert( value ); - } - - /// Set the field value from a QVariant - static void setFromVariant( const QVariant& variantValue, cvf::Mat4d& value ) - { - PdmValueFieldSpecialization::setFromVariant( variantValue, value ); - } - - static bool isDataElementEqual( const QVariant& variantValue, const QVariant& variantValue2 ) - { - return PdmValueFieldSpecialization::isEqual( variantValue, variantValue2 ); - } - - /// Methods to get a list of options for a field, specialized for AppEnum - static QList valueOptions( QString keyword, const cvf::Mat4d& ) - { - return QList(); - } - - /// Methods to retrieve the possible PdmObject pointed to by a field - static void childObjects( const PdmDataValueField&, std::vector* ) {} -}; - -} // end namespace caf diff --git a/Fwk/AppFwk/cafPdmCvf/cafPdmUiCoreVec3d.h b/Fwk/AppFwk/cafPdmCvf/cafPdmUiCoreVec3d.h index bc4d22c8f7..7832de51b2 100644 --- a/Fwk/AppFwk/cafPdmCvf/cafPdmUiCoreVec3d.h +++ b/Fwk/AppFwk/cafPdmCvf/cafPdmUiCoreVec3d.h @@ -38,48 +38,11 @@ #include "cafPdmCoreVec3d.h" -#include "cafInternalPdmValueFieldSpecializations.h" -#include "cafPdmUiFieldSpecialization.h" #include "cafPdmUiItem.h" #include "cvfBase.h" #include "cvfVector3.h" -namespace caf -{ -template <> -class PdmUiFieldSpecialization -{ -public: - /// Convert the field value into a QVariant - static QVariant convert( const cvf::Vec3d& value ) - { - return PdmValueFieldSpecialization::convert( value ); - } - - /// Set the field value from a QVariant - static void setFromVariant( const QVariant& variantValue, cvf::Vec3d& value ) - { - PdmValueFieldSpecialization::setFromVariant( variantValue, value ); - } - - static bool isDataElementEqual( const QVariant& variantValue, const QVariant& variantValue2 ) - { - return PdmValueFieldSpecialization::isEqual( variantValue, variantValue2 ); - } - - /// Methods to get a list of options for a field, specialized for AppEnum - static QList valueOptions( QString keyword, const cvf::Vec3d& ) - { - return QList(); - } - - /// Methods to retrieve the possible PdmObject pointed to by a field - static void childObjects( const PdmDataValueField&, std::vector* ) {} -}; - -} // end namespace caf - //-------------------------------------------------------------------------------------------------- // If the macro for registering the editor is put as the single statement // in a cpp file, a dummy static class must be used to make sure the compile unit diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafAppEnum.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafAppEnum.h index 7263c6fdcd..047053c4ab 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafAppEnum.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafAppEnum.h @@ -129,19 +129,34 @@ public: { } - static void setEnumSubset( caf::PdmFieldHandle* fieldKeyword, std::vector subset ) + static void setEnumSubset( caf::PdmFieldHandle* fieldHandle, std::vector subset ) { - if ( !fieldKeyword ) return; - m_enumSubset[fieldKeyword->keyword()] = subset; + if ( !fieldHandle ) return; + QString key = createEnumSubsetKey( fieldHandle ); + m_enumSubset[key] = subset; } - static std::vector enumSubset( QString fieldKeyword ) + static std::vector enumSubset( caf::PdmFieldHandle* fieldHandle ) { - auto it = m_enumSubset.find( fieldKeyword ); + if ( !fieldHandle ) return {}; + QString key = createEnumSubsetKey( fieldHandle ); + auto it = m_enumSubset.find( key ); if ( it != m_enumSubset.end() ) return it->second; return {}; } +private: + static QString createEnumSubsetKey( caf::PdmFieldHandle* fieldHandle ) + { + if ( !fieldHandle ) return QString(); + + // Create a unique key by combining the owner class name with the field keyword + // This prevents collisions when different object types use the same field keyword + QString ownerClass = fieldHandle->ownerClass(); + return ownerClass + "::" + fieldHandle->keyword(); + } + +public: operator T() const { return m_value; } T value() const { return m_value; } @@ -201,7 +216,7 @@ private: T m_value; - static std::map> m_enumSubset; + static std::map> m_enumSubset; // Key format: "ownerClass::fieldKeyword" //================================================================================================== /// A private class to handle the instance of the mapping vector. diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafInternalPdmValueFieldSpecializations.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafInternalPdmValueFieldSpecializations.h index aa67a1c01c..31cd0b230d 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafInternalPdmValueFieldSpecializations.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafInternalPdmValueFieldSpecializations.h @@ -12,6 +12,28 @@ namespace caf { +//================================================================================================== +/// Base class providing default implementations for PdmValueFieldSpecialization methods. +//================================================================================================== +struct PdmValueFieldSpecializationDefaults +{ + static bool isEqual( const QVariant& variantValue, const QVariant& variantValue2 ) + { + return variantValue == variantValue2; + } +}; + +//================================================================================================== +/// Helper base class providing standard QVariant conversion for simple types. +/// Useful for types that only need custom isEqual (like float/double with epsilon comparison). +//================================================================================================== +template +struct PdmValueFieldSpecializationStdConversion +{ + static QVariant convert( const T& value ) { return QVariant::fromValue( value ); } + static void setFromVariant( const QVariant& variantValue, T& value ) { value = variantValue.value(); } +}; + //================================================================================================== /// A proxy class that implements the generic QVariant interface for a field /// @@ -47,7 +69,7 @@ public: /// Partial specialization for caf::AppEnum //================================================================================================== template -class PdmValueFieldSpecialization> +class PdmValueFieldSpecialization> : public PdmValueFieldSpecializationDefaults { public: static QVariant convert( const caf::AppEnum& value ) @@ -61,11 +83,6 @@ public: { value = static_cast( variantValue.toInt() ); } - - static bool isEqual( const QVariant& variantValue, const QVariant& variantValue2 ) - { - return variantValue == variantValue2; - } }; //================================================================================================== @@ -97,7 +114,7 @@ public: /// Partial specialization for std::vector //================================================================================================== template -class PdmValueFieldSpecialization> +class PdmValueFieldSpecialization> : public PdmValueFieldSpecializationDefaults { public: static QVariant convert( const std::vector& value ) @@ -127,18 +144,13 @@ public: } } } - - static bool isEqual( const QVariant& variantValue, const QVariant& variantValue2 ) - { - return variantValue == variantValue2; - } }; //================================================================================================== /// Partial specialization for std::pair //================================================================================================== template -class PdmValueFieldSpecialization> +class PdmValueFieldSpecialization> : public PdmValueFieldSpecializationDefaults { public: static QVariant convert( const std::pair& value ) @@ -168,11 +180,6 @@ public: } } } - - static bool isEqual( const QVariant& variantValue, const QVariant& variantValue2 ) - { - return variantValue == variantValue2; - } }; //================================================================================================== @@ -199,13 +206,9 @@ public: /// Partial specialization for float //================================================================================================== template <> -class PdmValueFieldSpecialization +class PdmValueFieldSpecialization : public PdmValueFieldSpecializationStdConversion { public: - static QVariant convert( const float& value ) { return QVariant::fromValue( value ); } - - static void setFromVariant( const QVariant& variantValue, float& value ) { value = variantValue.value(); } - static bool isEqual( const QVariant& variantValue, const QVariant& variantValue2 ) { // See PdmFieldWriter::writeFieldData for the precision used when writing float values @@ -220,13 +223,9 @@ public: /// Partial specialization for double //================================================================================================== template <> -class PdmValueFieldSpecialization +class PdmValueFieldSpecialization : public PdmValueFieldSpecializationStdConversion { public: - static QVariant convert( const double& value ) { return QVariant::fromValue( value ); } - - static void setFromVariant( const QVariant& variantValue, double& value ) { value = variantValue.value(); } - static bool isEqual( const QVariant& variantValue, const QVariant& variantValue2 ) { // See PdmFieldWriter::writeFieldData for the precision used when writing double values diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/CMakeLists.txt index bb830a8891..927595c727 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/CMakeLists.txt @@ -27,6 +27,7 @@ set(PROJECT_FILES cafPdmChildArrayFieldHandleTest.cpp cafSignalTest.cpp cafPdmLoggingTest.cpp + cafAppEnumTest.cpp Child.cpp Child.h Parent.cpp diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/cafAppEnumTest.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/cafAppEnumTest.cpp new file mode 100644 index 0000000000..71dc2febb6 --- /dev/null +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/cafAppEnumTest.cpp @@ -0,0 +1,144 @@ +#include "gtest/gtest.h" + +#include "cafAppEnum.h" +#include "cafPdmDataValueField.h" +#include "cafPdmObjectHandle.h" + +// Define a test enum +enum class TestEnumType +{ + VALUE_A, + VALUE_B, + VALUE_C, + VALUE_D, + VALUE_E +}; + +namespace caf +{ +template <> +void AppEnum::setUp() +{ + addItem( TestEnumType::VALUE_A, "VALUE_A", "Value A" ); + addItem( TestEnumType::VALUE_B, "VALUE_B", "Value B" ); + addItem( TestEnumType::VALUE_C, "VALUE_C", "Value C" ); + addItem( TestEnumType::VALUE_D, "VALUE_D", "Value D" ); + addItem( TestEnumType::VALUE_E, "VALUE_E", "Value E" ); + setDefault( TestEnumType::VALUE_A ); +} +} // namespace caf + +// First test object with an enum field +class TestObject1 : public caf::PdmObjectHandle +{ +public: + TestObject1() + { + this->addField( &m_enumField, "EnumField" ); + m_enumField.setOwnerClass( "TestObject1" ); + m_enumField = TestEnumType::VALUE_A; + } + + caf::PdmDataValueField> m_enumField; +}; + +// Second test object with an enum field using the same keyword +class TestObject2 : public caf::PdmObjectHandle +{ +public: + TestObject2() + { + this->addField( &m_enumField, "EnumField" ); + m_enumField.setOwnerClass( "TestObject2" ); + m_enumField = TestEnumType::VALUE_B; + } + + caf::PdmDataValueField> m_enumField; +}; + +// Third test object to test uninitialized subset +class TestObject3 : public caf::PdmObjectHandle +{ +public: + TestObject3() + { + this->addField( &m_enumField, "UniqueEnumField" ); + m_enumField.setOwnerClass( "TestObject3" ); + m_enumField = TestEnumType::VALUE_C; + } + + caf::PdmDataValueField> m_enumField; +}; + +//-------------------------------------------------------------------------------------------------- +/// Test that two different objects can have the same field keyword with different enum subsets +//-------------------------------------------------------------------------------------------------- +TEST( AppEnumTest, EnumSubsetNoCollision ) +{ + TestObject1 obj1; + TestObject2 obj2; + + // Set different subsets for the same field keyword in different objects + std::vector subset1 = { TestEnumType::VALUE_A, TestEnumType::VALUE_B }; + std::vector subset2 = { TestEnumType::VALUE_C, TestEnumType::VALUE_D, TestEnumType::VALUE_E }; + + caf::AppEnum::setEnumSubset( &obj1.m_enumField, subset1 ); + caf::AppEnum::setEnumSubset( &obj2.m_enumField, subset2 ); + + // Retrieve the subsets + auto retrievedSubset1 = caf::AppEnum::enumSubset( &obj1.m_enumField ); + auto retrievedSubset2 = caf::AppEnum::enumSubset( &obj2.m_enumField ); + + // Verify that the subsets are correct and independent + ASSERT_EQ( 2, retrievedSubset1.size() ); + EXPECT_EQ( TestEnumType::VALUE_A, retrievedSubset1[0] ); + EXPECT_EQ( TestEnumType::VALUE_B, retrievedSubset1[1] ); + + ASSERT_EQ( 3, retrievedSubset2.size() ); + EXPECT_EQ( TestEnumType::VALUE_C, retrievedSubset2[0] ); + EXPECT_EQ( TestEnumType::VALUE_D, retrievedSubset2[1] ); + EXPECT_EQ( TestEnumType::VALUE_E, retrievedSubset2[2] ); +} + +//-------------------------------------------------------------------------------------------------- +/// Test that multiple instances of the same class share the same subset +//-------------------------------------------------------------------------------------------------- +TEST( AppEnumTest, EnumSubsetSameClass ) +{ + TestObject1 obj1a; + TestObject1 obj1b; + + // Set subset for first instance + std::vector subset = { TestEnumType::VALUE_A, TestEnumType::VALUE_C }; + caf::AppEnum::setEnumSubset( &obj1a.m_enumField, subset ); + + // Both instances should have the same subset since they have the same class name and field keyword + auto retrievedSubset1 = caf::AppEnum::enumSubset( &obj1a.m_enumField ); + auto retrievedSubset2 = caf::AppEnum::enumSubset( &obj1b.m_enumField ); + + ASSERT_EQ( 2, retrievedSubset1.size() ); + ASSERT_EQ( 2, retrievedSubset2.size() ); + EXPECT_EQ( TestEnumType::VALUE_A, retrievedSubset1[0] ); + EXPECT_EQ( TestEnumType::VALUE_C, retrievedSubset1[1] ); + EXPECT_EQ( TestEnumType::VALUE_A, retrievedSubset2[0] ); + EXPECT_EQ( TestEnumType::VALUE_C, retrievedSubset2[1] ); +} + +//-------------------------------------------------------------------------------------------------- +/// Test that null field handle returns empty subset +//-------------------------------------------------------------------------------------------------- +TEST( AppEnumTest, EnumSubsetNullHandle ) +{ + auto retrievedSubset = caf::AppEnum::enumSubset( nullptr ); + EXPECT_TRUE( retrievedSubset.empty() ); +} + +//-------------------------------------------------------------------------------------------------- +/// Test that requesting a subset that hasn't been set returns empty vector +//-------------------------------------------------------------------------------------------------- +TEST( AppEnumTest, EnumSubsetNotSet ) +{ + TestObject3 obj; + auto retrievedSubset = caf::AppEnum::enumSubset( &obj.m_enumField ); + EXPECT_TRUE( retrievedSubset.empty() ); +} diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmFieldTypeSpecializations.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmFieldTypeSpecializations.h index 8b1ff17289..fa3f406daa 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmFieldTypeSpecializations.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmFieldTypeSpecializations.h @@ -13,6 +13,35 @@ class PdmPointer; template class AppEnum; +//================================================================================================== +/// Helper base class for types that delegate all operations to PdmValueFieldSpecialization. +/// Inherit from this to avoid repeating the delegation boilerplate. +//================================================================================================== +template +struct PdmUiFieldSpecializationForValueSpec : public PdmUiFieldSpecializationDefaults +{ + static QVariant convert( const T& value ) { return PdmValueFieldSpecialization::convert( value ); } + + static void setFromVariant( const QVariant& variantValue, T& value ) + { + PdmValueFieldSpecialization::setFromVariant( variantValue, value ); + } + + static bool isDataElementEqual( const QVariant& variantValue, const QVariant& variantValue2 ) + { + return PdmValueFieldSpecialization::isEqual( variantValue, variantValue2 ); + } +}; + +//================================================================================================== +/// Primary template - delegates to PdmValueFieldSpecialization. +/// Types with custom PdmValueFieldSpecialization will automatically get correct behavior. +//================================================================================================== +template +class PdmUiFieldSpecialization : public PdmUiFieldSpecializationForValueSpec +{ +}; + //================================================================================================== /// Partial specialization for PdmField< PdmPointer > /// @@ -24,7 +53,7 @@ class AppEnum; //================================================================================================== template -class PdmUiFieldSpecialization> +class PdmUiFieldSpecialization> : public PdmUiFieldSpecializationDefaults { public: static QVariant convert( const PdmPointer& value ) @@ -41,11 +70,6 @@ public: { return variantValue.value>() == variantValue2.value>(); } - - static QList valueOptions( QString keyword, const PdmPointer& ) - { - return QList(); - } }; //================================================================================================== @@ -53,7 +77,7 @@ public: //================================================================================================== template -class PdmUiFieldSpecialization> +class PdmUiFieldSpecialization> : public PdmUiFieldSpecializationDefaults { public: static QVariant convert( const std::list& value ) @@ -85,13 +109,6 @@ public: { return PdmValueFieldSpecialization::isEqual( variantValue, variantValue2 ); } - - static QList valueOptions( QString keyword, const std::list& ) - { - return QList(); - } - - static void childObjects( const PdmDataValueField>&, std::vector* ) {} }; //================================================================================================== @@ -99,7 +116,7 @@ public: //================================================================================================== template -class PdmUiFieldSpecialization> +class PdmUiFieldSpecialization> : public PdmUiFieldSpecializationDefaults { public: static QVariant convert( const std::vector& value ) @@ -116,22 +133,13 @@ public: { return PdmValueFieldSpecialization::isEqual( variantValue, variantValue2 ); } - - static QList valueOptions( QString keyword, const std::vector& ) - { - return QList(); - } - - static void childObjects( const PdmDataValueField>& field, std::vector* objects ) - { - } }; //================================================================================================== /// Partial specialization for PdmField< caf::AppEnum > //================================================================================================== template -class PdmUiFieldSpecialization> +class PdmUiFieldSpecialization> : public PdmUiFieldSpecializationDefaults { public: static QVariant convert( const caf::AppEnum& value ) @@ -147,17 +155,12 @@ public: value = static_cast( variantValue.toInt() ); } - static bool isDataElementEqual( const QVariant& variantValue, const QVariant& variantValue2 ) - { - return variantValue == variantValue2; - } - - static QList valueOptions( QString keyword, const caf::AppEnum& appEnum ) + static QList valueOptions( PdmFieldHandle* fieldHandle, const caf::AppEnum& appEnum ) { QList optionList; // If a subset of the enum is defined, use that subset - auto enumValues = caf::AppEnum::enumSubset( keyword ); + auto enumValues = caf::AppEnum::enumSubset( fieldHandle ); if ( enumValues.empty() ) { // If no subset is defined, use all values @@ -173,17 +176,13 @@ public: return optionList; } - - static void childObjects( const PdmDataValueField>& field, std::vector* objects ) - { - } }; //================================================================================================== /// Partial specialization for PdmField>> //================================================================================================== template -class PdmUiFieldSpecialization> +class PdmUiFieldSpecialization> : public PdmUiFieldSpecializationDefaults { public: static QVariant convert( const std::pair& value ) @@ -195,29 +194,13 @@ public: { PdmValueFieldSpecialization>::setFromVariant( variantValue, value ); } - - static bool isDataElementEqual( const QVariant& variantValue, const QVariant& variantValue2 ) - { - return variantValue == variantValue2; - } - - static QList valueOptions( QString keyword, const std::pair& ) - { - QList optionList; - - return optionList; - } - - static void childObjects( const PdmDataValueField>& field, std::vector* objects ) - { - } }; //================================================================================================== /// Partial specialization for PdmField>> //================================================================================================== template -class PdmUiFieldSpecialization> +class PdmUiFieldSpecialization> : public PdmUiFieldSpecializationDefaults { public: /// Convert the field value into a QVariant @@ -247,59 +230,6 @@ public: PdmValueFieldSpecialization::setFromVariant( variantValue, valueOfType ); value = valueOfType; } - - static bool isDataElementEqual( const QVariant& variantValue, const QVariant& variantValue2 ) - { - return variantValue == variantValue2; - } - - /// Methods to get a list of options for a field, specialized for std::optional - static QList valueOptions( QString keyword, const std::optional& ) - { - QList optionList; - - return optionList; - } - - /// Methods to retrieve the possible PdmObject pointed to by a field - static void childObjects( const PdmDataValueField>& field, std::vector* objects ) - { - } -}; - -//================================================================================================== -/// Partial specialization for FilePath -//================================================================================================== - -template <> -class PdmUiFieldSpecialization -{ -public: - /// Convert the field value into a QVariant - static QVariant convert( const caf::FilePath& value ) - { - return PdmValueFieldSpecialization::convert( value ); - } - - /// Set the field value from a QVariant - static void setFromVariant( const QVariant& variantValue, caf::FilePath& value ) - { - return PdmValueFieldSpecialization::setFromVariant( variantValue, value ); - } - - static bool isDataElementEqual( const QVariant& variantValue, const QVariant& variantValue2 ) - { - return PdmValueFieldSpecialization::isEqual( variantValue, variantValue2 ); - } - - /// Methods to get a list of options for a field, specialized for caf::FilePath - static QList valueOptions( QString keyword, const caf::FilePath& ) - { - return QList(); - } - - /// Methods to retrieve the possible PdmObject pointed to by a field - static void childObjects( const PdmDataValueField& field, std::vector* objects ) {} }; } // End namespace caf diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl index f4c74efad5..a027087928 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl @@ -198,9 +198,8 @@ QList PdmFieldUiCap::valueOptions() const if ( m_optionEntryCache.empty() ) { - auto keyword = m_field->keyword(); m_optionEntryCache = - PdmUiFieldSpecialization::valueOptions( keyword, m_field->value() ); + PdmUiFieldSpecialization::valueOptions( m_field, m_field->value() ); } if ( !m_optionEntryCache.empty() && isAutoAddingOptionFromValue() ) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldSpecialization.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldSpecialization.h index a4453d7f08..509d1a0cea 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldSpecialization.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldSpecialization.h @@ -11,6 +11,30 @@ template class PdmDataValueField; class PdmOptionItemInfo; class PdmObjectHandle; +class PdmFieldHandle; + +//================================================================================================== +/// Base class providing default implementations for PdmUiFieldSpecialization methods. +/// Specializations can inherit from this to avoid repeating empty/simple implementations. +//================================================================================================== +struct PdmUiFieldSpecializationDefaults +{ + static bool isDataElementEqual( const QVariant& variantValue, const QVariant& variantValue2 ) + { + return variantValue == variantValue2; + } + + template + static QList valueOptions( PdmFieldHandle*, const T& ) + { + return QList(); + } + + template + static void childObjects( const PdmDataValueField&, std::vector* ) + { + } +}; //================================================================================================== /// A proxy class that implements the Gui interface of fields @@ -21,40 +45,14 @@ class PdmObjectHandle; /// /// When introducing a new type in a PdmField, you might need to implement a (partial)specialization /// of this class. +/// +/// The primary template delegates to PdmValueFieldSpecialization, so types with custom +/// PdmValueFieldSpecialization will automatically get the correct behavior without needing +/// an explicit PdmUiFieldSpecialization. //================================================================================================== template -class PdmUiFieldSpecialization -{ -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 - /// This is needed for the lookup regarding OptionValues - static bool isDataElementEqual( const QVariant& variantValue, const QVariant& variantValue2 ) - { - if ( variantValue.typeId() > QMetaType::User ) - { - return ( variantValue.value() == variantValue2.value() ); - } - else - { - return variantValue == variantValue2; - } - } - - /// Methods to get a list of options for a field - static QList valueOptions( QString keyword, const T& ) { return QList(); } - - /// Methods to retrieve the possible PdmObject pointed to by a field - static void childObjects( const PdmDataValueField&, std::vector* ) {} -}; +class PdmUiFieldSpecialization; // Forward declaration, defined in cafInternalPdmFieldTypeSpecializations.h } // End of namespace caf #include "cafInternalPdmFieldTypeSpecializations.h"