Adds support for std::optional PdmFields

This commit is contained in:
Magne Sjaastad committed 2025-08-07 15:45:09 +02:00
1 parent e8805df3ff
commit 871973d02a
13 files changed
+289 -41

No files matched your search

@@ -317,6 +317,59 @@ struct PdmFieldScriptingCapabilityIOHandler<AppEnum<T>>
}
};
template <typename T>
struct PdmFieldScriptingCapabilityIOHandler<std::optional<T>>
{
static void writeToField( std::optional<T>& fieldValue,
QTextStream& inputStream,
PdmScriptIOMessages* errorMessageContainer,
bool stringsAreQuoted = true )
{
QString textValue;
PdmFieldScriptingCapabilityIOHandler<QString>::writeToField( textValue,
inputStream,
errorMessageContainer,
stringsAreQuoted );
textValue.remove( '"' );
if ( !textValue.isEmpty() )
{
QTextStream singleValueStream( &textValue );
T singleValue;
bool noStringQuotes = false;
PdmFieldScriptingCapabilityIOHandler<T>::writeToField( singleValue,
singleValueStream,
errorMessageContainer,
noStringQuotes );
fieldValue = singleValue;
}
else
{
fieldValue.reset();
}
}
static void readFromField( const std::optional<T>& fieldValue,
QTextStream& outputStream,
bool quoteStrings = true,
bool quoteNonBuiltins = false )
{
QString textValue;
if ( fieldValue.has_value() )
{
QTextStream singleValueStream( &textValue );
singleValueStream << fieldValue.value();
}
else
{
textValue = "";
}
PdmFieldScriptingCapabilityIOHandler<QString>::readFromField( textValue, outputStream, quoteStrings, quoteNonBuiltins );
}
};
template <typename T>
struct PdmFieldScriptingCapabilityIOHandler<std::vector<T>>
{
@@ -192,15 +192,14 @@ QString caf::PdmPythonGenerator::generate( PdmObjectFactory* factory, std::vecto
}
else
{
QString valueString = getDefaultValue( field );
if ( valueString == "None" )
QString defaultValue = getDefaultValue( field );
if ( !dataType.contains( "Optional" ) && defaultValue == "None" )
{
dataType = QString( "Optional[%1]" ).arg( dataType );
}
QString fieldCode =
QString( " self.%1: %2 = %3\n" ).arg( snake_field_name ).arg( dataType ).arg( valueString );
QString( " self.%1: %2 = %3\n" ).arg( snake_field_name ).arg( dataType ).arg( defaultValue );
QString fullComment;
{
@@ -312,7 +311,7 @@ QString caf::PdmPythonGenerator::generate( PdmObjectFactory* factory, std::vecto
if ( isList ) dataType = QString( "List[%1]" ).arg( dataType );
QString defaultValue = getDefaultValue( field );
if ( defaultValue == "None" )
if ( !dataType.contains( "Optional" ) && defaultValue == "None" )
{
dataType = QString( "Optional[%1]" ).arg( dataType );
}
@@ -508,7 +507,7 @@ QString PdmPythonGenerator::getDefaultValue( PdmFieldHandle* field )
scriptability->readFromField( valueStream, true, true );
}
if ( valueString.isEmpty() )
if ( valueString == "\"\"" || valueString.isEmpty() )
{
valueString = defaultValue;
}
@@ -556,6 +555,11 @@ QString PdmPythonGenerator::dataTypeString( const PdmFieldHandle* field, bool us
{ QString::fromStdString( typeid( QString ).name() ), "str" },
{ QString::fromStdString( typeid( caf::FilePath ).name() ), "str" },
{ QString::fromStdString( typeid( std::vector<double> ).name() ), "List[float]" },
{ QString::fromStdString( typeid( std::optional<double> ).name() ), "Optional[double]" },
{ QString::fromStdString( typeid( std::optional<float> ).name() ), "Optional[float]" },
{ QString::fromStdString( typeid( std::optional<int> ).name() ), "Optional[int]" },
{ QString::fromStdString( typeid( std::optional<bool> ).name() ), "Optional[bool]" },
{ QString::fromStdString( typeid( std::optional<QString> ).name() ), "Optional[str]" },
};
#ifndef CAF_EXCLUDE_CVF
@@ -130,6 +130,8 @@ 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_InitFieldNoDefault( &m_simpleObjectsField,
"SimpleObjects",
@@ -81,8 +81,9 @@ public:
InheritedDemoObj();
caf::PdmField<std::vector<QString>> m_texts;
caf::PdmField<std::vector<double>> m_numbers;
caf::PdmField<std::vector<QString>> m_texts;
caf::PdmField<std::vector<double>> m_numbers;
caf::PdmField<std::optional<double>> m_optionalNumber;
caf::PdmField<caf::AppEnum<TestEnumType>> m_testEnumField;
caf::PdmChildArrayField<SimpleObj*> m_simpleObjectsField;
@@ -126,3 +126,60 @@ TEST( PdmFieldSerialization, ValueList )
EXPECT_FLOAT_EQ( floatValues[i], result[i] );
}
}
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
TEST( PdmFieldSerialization, OptionalValues )
{
{
std::optional<QString> optionalString = std::nullopt;
QString text;
QTextStream stream( &text );
caf::PdmScriptIOMessages messages;
bool stringsAreQuoted = true;
caf::PdmFieldScriptingCapabilityIOHandler<std::optional<QString>>::readFromField( optionalString,
stream,
&messages,
stringsAreQuoted );
const QString expected = "\"\"";
EXPECT_STREQ( expected.toStdString().c_str(), text.toStdString().c_str() );
std::optional<QString> result;
caf::PdmFieldScriptingCapabilityIOHandler<std::optional<QString>>::writeToField( result,
stream,
&messages,
stringsAreQuoted );
EXPECT_FALSE( result.has_value() );
}
{
QString sourceText = "Test string with spaces";
std::optional<QString> optionalString = sourceText;
QString text;
QTextStream stream( &text );
caf::PdmScriptIOMessages messages;
bool stringsAreQuoted = true;
caf::PdmFieldScriptingCapabilityIOHandler<std::optional<QString>>::readFromField( optionalString,
stream,
&messages,
stringsAreQuoted );
const QString expected = "\"Test string with spaces\"";
EXPECT_STREQ( expected.toStdString().c_str(), text.toStdString().c_str() );
std::optional<QString> result;
caf::PdmFieldScriptingCapabilityIOHandler<std::optional<QString>>::writeToField( result,
stream,
&messages,
stringsAreQuoted );
EXPECT_STREQ( sourceText.toStdString().c_str(), result.value().toStdString().c_str() );
}
}