Add static function to define a subset of enums to be used for AppEnum

Add a static map between field keyword and a subset of enum values to be displayed in the GUI
If a subset is defined, automatically calculate value options for this subset, otherwise, use all enums
Improve the macro so it is possible to use the `EnumType` instead of `AppEnum<EnumType>` when defining the default value
This commit is contained in:
Magne Sjaastad 2025-02-08 09:24:55 +01:00 committed by GitHub
parent 72f898a589
commit 7e523e340a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 208 additions and 32 deletions

View File

@ -69,7 +69,10 @@ public:
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( const cvf::Mat3d& ) { return QList<PdmOptionItemInfo>(); }
static QList<PdmOptionItemInfo> valueOptions( QString keyword, const cvf::Mat3d& )
{
return QList<PdmOptionItemInfo>();
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects( const PdmDataValueField<cvf::Mat3d>&, std::vector<PdmObjectHandle*>* ) {}

View File

@ -69,7 +69,10 @@ public:
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( const cvf::Color3f& ) { return QList<PdmOptionItemInfo>(); }
static QList<PdmOptionItemInfo> valueOptions( QString keyword, const cvf::Color3f& )
{
return QList<PdmOptionItemInfo>();
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects( const PdmDataValueField<cvf::Color3f>&, std::vector<PdmObjectHandle*>* ) {}

View File

@ -69,7 +69,10 @@ public:
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( const cvf::Mat4d& ) { return QList<PdmOptionItemInfo>(); }
static QList<PdmOptionItemInfo> valueOptions( QString keyword, const cvf::Mat4d& )
{
return QList<PdmOptionItemInfo>();
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects( const PdmDataValueField<cvf::Mat4d>&, std::vector<PdmObjectHandle*>* ) {}

View File

@ -69,7 +69,10 @@ public:
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( const cvf::Vec3d& ) { return QList<PdmOptionItemInfo>(); }
static QList<PdmOptionItemInfo> valueOptions( QString keyword, const cvf::Vec3d& )
{
return QList<PdmOptionItemInfo>();
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects( const PdmDataValueField<cvf::Vec3d>&, std::vector<PdmObjectHandle*>* ) {}

View File

@ -41,6 +41,7 @@
#include <QString>
#include <QStringList>
#include <map>
#include <vector>
namespace caf
@ -95,6 +96,16 @@ namespace caf
/// options.push_back(caf::PdmOptionItemInfo(caf::AppEnum<TestEnumType>::uiTextFromIndex(i),
/// caf::AppEnum<TestEnumType>::fromIndex(i)));
/// }
///
/// Subset of enums:
///
/// Define a subset of the enum to be used in a field. Assign a value from the subset to make sure the field
/// contains a valid value when the constructor is done.
///
/// CAF_PDM_InitField( &m_enum2Field, "Enum2Field", MyEnumType::T6, "Subset using setEnumSubset()" );
/// caf::AppEnum<MyEnumType>::setEnumSubset( m_enum2Field.keyword(), { MyEnumType::T2, MyEnumType::T6 } );
///
///
//==================================================================================================
class AppEnumInterface
@ -117,6 +128,15 @@ public:
{
}
static void setEnumSubset( QString fieldKeyword, std::vector<T> subset ) { m_enumSubset[fieldKeyword] = subset; }
static std::vector<T> enumSubset( QString fieldKeyword )
{
auto it = m_enumSubset.find( fieldKeyword );
if ( it != m_enumSubset.end() ) return it->second;
return {};
}
operator T() const { return m_value; }
T value() const { return m_value; }
@ -176,6 +196,8 @@ private:
T m_value;
static std::map<QString, std::vector<T>> m_enumSubset;
//==================================================================================================
/// A private class to handle the instance of the mapping vector.
/// all access methods could have been placed directly in the \class AppEnum class,
@ -354,4 +376,7 @@ private:
};
};
template <class T>
std::map<QString, std::vector<T>> AppEnum<T>::m_enumSubset;
} // namespace caf

View File

@ -157,23 +157,6 @@ public:
PdmObject();
~PdmObject() override {}
/// Adds field to the internal data structure and sets the file keyword and Ui information
/// Consider this method private. Please use the CAF_PDM_InitField() macro instead
template <typename FieldDataType>
void addFieldUi( PdmField<FieldDataType>* field,
const QString& keyword,
const FieldDataType& defaultValue,
PdmUiItemInfo* fieldDescription )
{
addFieldUiNoDefault( field, keyword, fieldDescription );
field->setDefaultValue( defaultValue );
*field = defaultValue;
}
/// Does the same as the above method, but omits the default value.
/// Consider this method private. Please use the CAF_PDM_InitFieldNoDefault() macro instead.
void addFieldUiNoDefault( PdmFieldHandle* field, const QString& keyword, PdmUiItemInfo* fieldDescription );
/// Returns _this_ if _this_ has requested class keyword
/// Traverses parents recursively and returns first parent of the requested
/// type.
@ -187,6 +170,40 @@ public:
/// Gets all children matching class keyword. Not recursive.
void childrenFromClassKeyword( const QString& classKeyword, std::vector<PdmObject*>& children ) const;
/// Adds field to the internal data structure and sets the file keyword and Ui information
/// Consider this method private. Please use the CAF_PDM_InitField() macro instead
template <typename FieldDataType>
void addFieldUi( PdmField<FieldDataType>* field,
const QString& keyword,
const FieldDataType& defaultValue,
PdmUiItemInfo* fieldDescription )
{
addFieldUiNoDefault( field, keyword, fieldDescription );
field->setDefaultValue( defaultValue );
*field = defaultValue;
}
/// Template specialization for AppEnum to make it possible to use an enum value as the default value.
///
/// In the header file:
/// caf::PdmField<caf::AppEnum<MyEnumType>> m_enum2Field;
/// In the source file:
/// CAF_PDM_InitField( &m_enum2Field, "m_enum2Field", MyEnumType::T6, "Subset using setEnumSubset()" );
///
template <typename FieldDataType>
void addFieldUi( PdmField<AppEnum<FieldDataType>>* field,
const QString& keyword,
const FieldDataType& defaultValue,
PdmUiItemInfo* fieldDescription )
{
auto defaultAppEnum = AppEnum<FieldDataType>( defaultValue );
addFieldUi( field, keyword, defaultAppEnum, fieldDescription );
}
/// Does the same as the above method, but omits the default value.
/// Consider this method private. Please use the CAF_PDM_InitFieldNoDefault() macro instead.
void addFieldUiNoDefault( PdmFieldHandle* field, const QString& keyword, PdmUiItemInfo* fieldDescription );
protected:
PdmObjectHandle* doCopyObject() const override;
};

View File

@ -42,7 +42,10 @@ public:
return variantValue.value<PdmPointer<PdmObjectHandle>>() == variantValue2.value<PdmPointer<PdmObjectHandle>>();
}
static QList<PdmOptionItemInfo> valueOptions( const PdmPointer<T>& ) { return QList<PdmOptionItemInfo>(); }
static QList<PdmOptionItemInfo> valueOptions( QString keyword, const PdmPointer<T>& )
{
return QList<PdmOptionItemInfo>();
}
};
//==================================================================================================
@ -87,7 +90,10 @@ public:
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( const std::list<T>& ) { return QList<PdmOptionItemInfo>(); }
static QList<PdmOptionItemInfo> valueOptions( QString keyword, const std::list<T>& )
{
return QList<PdmOptionItemInfo>();
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects( const PdmDataValueField<std::list<T>>&, std::vector<PdmObjectHandle*>* ) {}
@ -120,7 +126,10 @@ public:
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( const std::vector<T>& ) { return QList<PdmOptionItemInfo>(); }
static QList<PdmOptionItemInfo> valueOptions( QString keyword, const std::vector<T>& )
{
return QList<PdmOptionItemInfo>();
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects( const PdmDataValueField<std::vector<T>>& field, std::vector<PdmObjectHandle*>* objects )
@ -156,14 +165,23 @@ public:
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( const caf::AppEnum<T>& )
static QList<PdmOptionItemInfo> valueOptions( QString keyword, const caf::AppEnum<T>& appEnum )
{
QList<PdmOptionItemInfo> optionList;
for ( size_t i = 0; i < caf::AppEnum<T>::size(); ++i )
// If a subset of the enum is defined, use that subset
auto enumValues = caf::AppEnum<T>::enumSubset( keyword );
if ( enumValues.empty() )
{
T enumVal = caf::AppEnum<T>::fromIndex( i );
optionList.push_back( PdmOptionItemInfo( caf::AppEnum<T>::uiTextFromIndex( i ), static_cast<int>( enumVal ) ) );
// If no subset is defined, use all values
for ( size_t i = 0; i < caf::AppEnum<T>::size(); ++i )
{
enumValues.push_back( caf::AppEnum<T>::fromIndex( i ) );
}
}
for ( auto enumValue : enumValues )
{
optionList.push_back( PdmOptionItemInfo( caf::AppEnum<T>::uiText( enumValue ), static_cast<int>( enumValue ) ) );
}
return optionList;
@ -197,7 +215,7 @@ public:
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( const std::pair<T, U>& )
static QList<PdmOptionItemInfo> valueOptions( QString keyword, const std::pair<T, U>& )
{
QList<PdmOptionItemInfo> optionList;
@ -236,7 +254,10 @@ public:
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( const caf::FilePath& ) { return QList<PdmOptionItemInfo>(); }
static QList<PdmOptionItemInfo> valueOptions( QString keyword, const caf::FilePath& )
{
return QList<PdmOptionItemInfo>();
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects( const PdmDataValueField<caf::FilePath>& field, std::vector<PdmObjectHandle*>* objects ) {}

View File

@ -192,7 +192,9 @@ QList<PdmOptionItemInfo> PdmFieldUiCap<FieldType>::valueOptions() const
if ( m_optionEntryCache.empty() )
{
m_optionEntryCache = PdmUiFieldSpecialization<typename FieldType::FieldDataType>::valueOptions( m_field->value() );
auto keyword = m_field->keyword();
m_optionEntryCache =
PdmUiFieldSpecialization<typename FieldType::FieldDataType>::valueOptions( keyword, m_field->value() );
}
if ( !m_optionEntryCache.empty() && isAutoAddingOptionFromValue() )

View File

@ -56,7 +56,7 @@ public:
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( const T& ) { return QList<PdmOptionItemInfo>(); }
static QList<PdmOptionItemInfo> valueOptions( QString keyword, const T& ) { return QList<PdmOptionItemInfo>(); }
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects( const PdmDataValueField<T>&, std::vector<PdmObjectHandle*>* ) {}

View File

@ -0,0 +1,62 @@
#include "ApplicationEnum.h"
#include "cafPdmUiListEditor.h"
#include "cafPdmUiTreeSelectionEditor.h"
template <>
void caf::AppEnum<ApplicationEnum::MyEnumType>::setUp()
{
addItem( ApplicationEnum::MyEnumType::T1, "T1", "T 1" );
addItem( ApplicationEnum::MyEnumType::T2, "T2", "T 2" );
addItem( ApplicationEnum::MyEnumType::T3, "T3", "T 3" );
addItem( ApplicationEnum::MyEnumType::T4, "T4", "T 4" );
addItem( ApplicationEnum::MyEnumType::T5, "T5", "T 5" );
addItem( ApplicationEnum::MyEnumType::T6, "T5", "T 6" );
addItem( ApplicationEnum::MyEnumType::T7, "T6", "T 7" );
setDefault( ApplicationEnum::MyEnumType::T4 );
}
CAF_PDM_SOURCE_INIT( ApplicationEnum, "ApplicationEnum" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ApplicationEnum::ApplicationEnum()
{
CAF_PDM_InitObject( "Application Enum", "", "", "" );
// Enum field displaying all defined enums
CAF_PDM_InitFieldNoDefault( &m_enumField, "EnumField", "All Enums" );
// Enum field displaying a subset of the defined enums using the static function setEnumSubset()
CAF_PDM_InitField( &m_enum2Field, "Enum2Field", MyEnumType::T6, "Subset using setEnumSubset()" );
caf::AppEnum<MyEnumType>::setEnumSubset( m_enum2Field.keyword(), { MyEnumType::T2, MyEnumType::T6 } );
// Enum field displaying a subset of the defined enums using calculateValueOptions()
CAF_PDM_InitFieldNoDefault( &m_enum3Field, "Enum3Field", "Subset using calculateValueOptions()" );
m_enum3Field = MyEnumType::T2;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> ApplicationEnum::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
{
if ( fieldNeedingOptions == &m_enum3Field )
{
QList<caf::PdmOptionItemInfo> options;
options.push_back(
caf::PdmOptionItemInfo( caf::AppEnum<ApplicationEnum::MyEnumType>::uiText( ApplicationEnum::MyEnumType::T2 ),
ApplicationEnum::MyEnumType::T2 ) );
options.push_back(
caf::PdmOptionItemInfo( caf::AppEnum<ApplicationEnum::MyEnumType>::uiText( ApplicationEnum::MyEnumType::T3 ),
ApplicationEnum::MyEnumType::T3 ) );
return options;
}
return {};
}

View File

@ -0,0 +1,32 @@
#pragma once
#include "cafPdmField.h"
#include "cafPdmObject.h"
class ApplicationEnum : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
enum class MyEnumType
{
T1,
T2,
T3,
T4,
T5,
T6,
T7
};
public:
ApplicationEnum();
private:
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
private:
caf::PdmField<caf::AppEnum<MyEnumType>> m_enumField;
caf::PdmField<caf::AppEnum<MyEnumType>> m_enum2Field;
caf::PdmField<caf::AppEnum<MyEnumType>> m_enum3Field;
};

View File

@ -42,6 +42,8 @@ set(PROJECT_FILES
TamComboBox.cpp
LineEditAndPushButtons.h
LineEditAndPushButtons.cpp
ApplicationEnum.h
ApplicationEnum.cpp
)
qt_add_executable(

View File

@ -3,6 +3,7 @@
#include "MainWindow.h"
#include "ApplicationEnum.h"
#include "CustomObjectEditor.h"
#include "LineEditAndPushButtons.h"
#include "ManyGroups.h"
@ -1332,6 +1333,8 @@ void MainWindow::buildTestModel()
demoObj2->m_objectList.push_back( new SmallDemoPdmObject() );
delete smallObj3;
m_testRoot->objects.push_back( new ApplicationEnum );
}
//--------------------------------------------------------------------------------------------------