From dc2816a91c293ba2625b04b5492004a9a1af1d58 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 25 Aug 2025 11:09:19 +0200 Subject: [PATCH] Adds new virtual method `configureCapabilities` to `PdmFieldHandle` This makes it possible to configure the capabilities of a field one place and avoids duplication. Extends scripting capabilities by introducing a `dataType` method to `PdmAbstractFieldScriptingCapability`. This allows the Python generator to retrieve the data type of a field directly from its scriptability, providing a more flexible and extensible way to determine the data type for scripting purposes. --- ...cafPdmAbstractFieldScriptingCapability.cpp | 8 ++++ .../cafPdmAbstractFieldScriptingCapability.h | 1 + .../cafPdmScripting/cafPdmPythonGenerator.cpp | 7 +++- .../cafMockObjects.cpp | 21 ++++++++-- .../cafMockObjects.h | 38 +++++++++++++++++++ .../cafPdmCore/cafPdmFieldHandle.cpp | 8 ++++ .../cafPdmCore/cafPdmFieldHandle.h | 2 + Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h | 2 + .../cafInternalPdmUiFieldCapability.h | 6 +++ .../cafInternalPdmUiFieldCapability.inl | 6 +++ .../cafPdmUiCore/cafPdmUiFieldHandle.cpp | 8 ++++ .../cafPdmUiCore/cafPdmUiFieldHandle.h | 5 +++ 12 files changed, 108 insertions(+), 4 deletions(-) diff --git a/Fwk/AppFwk/cafPdmScripting/cafPdmAbstractFieldScriptingCapability.cpp b/Fwk/AppFwk/cafPdmScripting/cafPdmAbstractFieldScriptingCapability.cpp index 72a2e1190b..909a9ed38b 100644 --- a/Fwk/AppFwk/cafPdmScripting/cafPdmAbstractFieldScriptingCapability.cpp +++ b/Fwk/AppFwk/cafPdmScripting/cafPdmAbstractFieldScriptingCapability.cpp @@ -106,3 +106,11 @@ QStringList PdmAbstractFieldScriptingCapability::enumScriptTexts() const { return QStringList(); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString PdmAbstractFieldScriptingCapability::dataType() const +{ + return {}; +} diff --git a/Fwk/AppFwk/cafPdmScripting/cafPdmAbstractFieldScriptingCapability.h b/Fwk/AppFwk/cafPdmScripting/cafPdmAbstractFieldScriptingCapability.h index 72595fd452..3e962ece5f 100644 --- a/Fwk/AppFwk/cafPdmScripting/cafPdmAbstractFieldScriptingCapability.h +++ b/Fwk/AppFwk/cafPdmScripting/cafPdmAbstractFieldScriptingCapability.h @@ -69,6 +69,7 @@ public: static QString helpString( const QString& existingTooltip, const QString& keyword ); virtual QStringList enumScriptTexts() const; + virtual QString dataType() const; protected: PdmFieldHandle* m_owner; diff --git a/Fwk/AppFwk/cafPdmScripting/cafPdmPythonGenerator.cpp b/Fwk/AppFwk/cafPdmScripting/cafPdmPythonGenerator.cpp index 54ad05411b..70d64f88c3 100644 --- a/Fwk/AppFwk/cafPdmScripting/cafPdmPythonGenerator.cpp +++ b/Fwk/AppFwk/cafPdmScripting/cafPdmPythonGenerator.cpp @@ -140,7 +140,12 @@ QString caf::PdmPythonGenerator::generate( PdmObjectFactory* factory, std::vecto auto pdmChildArrayField = dynamic_cast( field ); if ( pdmValueField ) { - QString dataType = PdmPythonGenerator::dataTypeString( field, false ); + QString dataType = scriptability->dataType(); + if ( dataType.isEmpty() ) + { + dataType = PdmPythonGenerator::dataTypeString( field, false ); + } + if ( field->xmlCapability()->isVectorField() ) { dataType = QString( "List[%1]" ).arg( dataType ); diff --git a/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.cpp b/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.cpp index 436b538843..09d30642f0 100644 --- a/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.cpp +++ b/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.cpp @@ -11,10 +11,26 @@ void AppEnum::setUp() addItem( InheritedDemoObj::T3, "T3", "A B letter" ); setDefault( InheritedDemoObj::T1 ); } + +template <> +void AppEnum::setUp() +{ + addItem( MyEnum::T1, "T1", "T1" ); + addItem( MyEnum::T2, "T2", "T2" ); + addItem( MyEnum::T3, "T3", "T3" ); + addItem( MyEnum::T4, "T4", "T4" ); + addItem( MyEnum::T5, "T5", "T5" ); + addItem( MyEnum::T6, "T6", "T6" ); + setDefault( MyEnum::T1 ); +} } // namespace caf CAF_PDM_SOURCE_INIT( SimpleObj, "SimpleObj" ); +namespace caf +{ +} // namespace caf + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -28,13 +44,11 @@ SimpleObj::SimpleObj() CAF_PDM_InitField( &m_dir, "Dir", 123.56, "Direction", "", "Tooltip", "WhatsThis" ); CAF_PDM_InitField( &m_up, "Up", 0.0, "Up value", "", "Tooltip", "WhatsThis" ); CAF_PDM_InitFieldNoDefault( &m_numbers, "Numbers", "Important Numbers", "", "Tooltip", "WhatsThis" ); -#if 1 m_proxyDouble.registerSetMethod( this, &SimpleObj::setDoubleMember ); m_proxyDouble.registerGetMethod( this, &SimpleObj::doubleMember ); addUiCapabilityToField( &m_proxyDouble ); addXmlCapabilityToField( &m_proxyDouble ); CAF_PDM_InitFieldNoDefault( &m_proxyDouble, "ProxyDouble", "ProxyDouble" ); -#endif } //-------------------------------------------------------------------------------------------------- @@ -131,8 +145,9 @@ InheritedDemoObj::InheritedDemoObj() CAF_PDM_InitScriptableFieldNoDefault( &m_texts, "Texts", "Some words" ); CAF_PDM_InitScriptableFieldNoDefault( &m_numbers, "Numbers", "Some words" ); CAF_PDM_InitScriptableFieldNoDefault( &m_optionalNumber, "OptionalNumber", "Optional Number" ); - CAF_PDM_InitFieldNoDefault( &m_testEnumField, "TestEnumValue", "An Enum" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_myAppEnum, "MyAppEnumValue", "My App Enum" ); + CAF_PDM_InitFieldNoDefault( &m_simpleObjectsField, "SimpleObjects", "SimpleObjectsField", diff --git a/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.h b/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.h index bdf615441f..a70afad881 100644 --- a/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.h +++ b/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.h @@ -23,6 +23,43 @@ #include /// Demo objects to show the usage of the Pdm system +enum class MyEnum +{ + T1, + T2, + T3, + T4, + T5, + T6 +}; + +// This is a specialized class that can be used to implement custom behavior in configureCapabilities +// It is required to have a specialization of PdmFieldScriptingCapability for this class, as the new class +// MyAppEnumField is not known to the template +class MyAppEnumField : public caf::PdmField> +{ +public: + MyAppEnumField() { + + }; + + void configureCapabilities() override {}; +}; + +namespace caf +{ +template <> +class PdmFieldScriptingCapability : public PdmFieldScriptingCapability>> +{ +public: + PdmFieldScriptingCapability( MyAppEnumField* field, const QString& fieldName, bool giveOwnership ) + : PdmFieldScriptingCapability>>( field, fieldName, giveOwnership ) + { + } + + QString dataType() const override { return "str"; } +}; +}; // namespace caf class SimpleObj : public caf::PdmObject { @@ -62,6 +99,7 @@ public: caf::PdmField m_doubleField; caf::PdmField m_intField; caf::PdmField m_textField; + MyAppEnumField m_myAppEnum; caf::PdmChildField m_simpleObjPtrField; caf::PdmChildField m_simpleObjPtrField2; diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.cpp index c9e829e89e..e2178856fb 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.cpp @@ -32,6 +32,14 @@ PdmFieldHandle::~PdmFieldHandle() } } +//-------------------------------------------------------------------------------------------------- +/// This function is called to configure capabilities for the field handle. This can be used to avoid duplicated code +/// when setting options for *.uiCapability() and *.xmlCapability(). +//-------------------------------------------------------------------------------------------------- +void PdmFieldHandle::configureCapabilities() +{ +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.h index b181b4f4f3..9ee7eaa016 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.h @@ -21,6 +21,8 @@ public: PdmFieldHandle() { m_ownerObject = nullptr; } virtual ~PdmFieldHandle(); + virtual void configureCapabilities(); + QString keyword() const { return m_keyword; } bool matchesKeyword( const QString& keyword ) const; PdmObjectHandle* ownerObject(); diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h index 1256528c64..a60cfad94c 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h @@ -110,6 +110,7 @@ class PdmObjectCapability; \ addXmlCapabilityToField( field ); \ addUiCapabilityToField( field ); \ + configureCapabilities( field ); \ registerClassWithField( classKeyword(), field ); \ \ static caf::PdmUiItemInfo objDescr( uiName, QString( iconResourceName ), toolTip, whatsThis, keyword ); \ @@ -139,6 +140,7 @@ class PdmObjectCapability; \ addXmlCapabilityToField( field ); \ addUiCapabilityToField( field ); \ + configureCapabilities( field ); \ registerClassWithField( classKeyword(), field ); \ \ static caf::PdmUiItemInfo objDescr( uiName, QString( iconResourceName ), toolTip, whatsThis, keyword ); \ diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.h index 47ffa2ce5f..f0822d0d52 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.h @@ -97,6 +97,12 @@ void addUiCapabilityToField( FieldType* field ) } } +template +void configureCapabilities( FieldType* field ) +{ + field->configureCapabilities(); +} + } // End of namespace caf #include "cafInternalPdmUiFieldCapability.inl" diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl index 90a98f0f46..9d89dcfa0c 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl @@ -188,6 +188,12 @@ QList PdmFieldUiCap::valueOptions() const m_optionEntryCache = uiObj( m_field->ownerObject() )->calculateValueOptions( this->m_field ); } + // Check if the field can provide value option + if ( m_optionEntryCache.empty() && m_valueOptionsGenerator ) + { + m_optionEntryCache = m_valueOptionsGenerator(); + } + // If we got no options, use the options defined by the type. Normally only caf::AppEnum type if ( m_optionEntryCache.empty() ) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp index e29523feef..a95cdfe44e 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp @@ -235,6 +235,14 @@ void PdmUiFieldHandle::setAttributes( const std::vector()>& valueOptionsGenerator ) +{ + m_valueOptionsGenerator = valueOptionsGenerator; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.h index 3022ce1e45..65a36b6780 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.h @@ -38,6 +38,11 @@ public: std::vector> attributes() const override; void setAttributes( const std::vector>& attributes ) override; + void setValueOptionsGenerator( const std::function()>& valueOptionsGenerator ); + +protected: + std::function()> m_valueOptionsGenerator; + private: friend class PdmUiCommandSystemProxy; friend class CmdFieldChangeExec;