From dd8b52af932a59a17d07daa1841308fbbbc586c8 Mon Sep 17 00:00:00 2001 From: Jon Evans Date: Wed, 22 Mar 2023 21:24:24 -0400 Subject: [PATCH] Be more flexible about extracting booleans from database Fixes https://gitlab.com/kicad/code/kicad/-/issues/14376 --- .../database/sch_database_plugin.cpp | 87 +++++++++++++++++-- .../database/sch_database_plugin.h | 2 + 2 files changed, 83 insertions(+), 6 deletions(-) diff --git a/eeschema/sch_plugins/database/sch_database_plugin.cpp b/eeschema/sch_plugins/database/sch_database_plugin.cpp index eb1f63b92d..3671e322cf 100644 --- a/eeschema/sch_plugins/database/sch_database_plugin.cpp +++ b/eeschema/sch_plugins/database/sch_database_plugin.cpp @@ -292,6 +292,55 @@ void SCH_DATABASE_PLUGIN::ensureConnection() } +std::optional SCH_DATABASE_PLUGIN::boolFromAny( const std::any& aVal ) +{ + try + { + bool val = std::any_cast( aVal ); + return val; + } + catch( const std::bad_any_cast& ) + { + } + + try + { + int val = std::any_cast( aVal ); + return static_cast( val ); + } + catch( const std::bad_any_cast& ) + { + } + + try + { + wxString strval( std::any_cast( aVal ).c_str(), wxConvUTF8 ); + + if( strval.IsEmpty() ) + return std::nullopt; + + strval.MakeLower(); + + for( const wxString& trueVal : { wxS( "true" ), wxS( "yes" ), wxS( "y" ), wxS( "1" ) } ) + { + if( strval.Matches( trueVal ) ) + return true; + } + + for( const wxString& falseVal : { wxS( "false" ), wxS( "no" ), wxS( "n" ), wxS( "0" ) } ) + { + if( strval.Matches( falseVal ) ) + return false; + } + } + catch( const std::bad_any_cast& ) + { + } + + return std::nullopt; +} + + LIB_SYMBOL* SCH_DATABASE_PLUGIN::loadSymbolFromRow( const wxString& aSymbolName, const DATABASE_LIB_TABLE& aTable, const DATABASE_CONNECTION::ROW& aRow ) @@ -300,12 +349,15 @@ LIB_SYMBOL* SCH_DATABASE_PLUGIN::loadSymbolFromRow( const wxString& aSymbolName, if( aRow.count( aTable.symbols_col ) ) { + LIB_SYMBOL* originalSymbol = nullptr; + // TODO: Support multiple options for symbol std::string symbolIdStr = std::any_cast( aRow.at( aTable.symbols_col ) ); LIB_ID symbolId; symbolId.Parse( std::any_cast( aRow.at( aTable.symbols_col ) ) ); - LIB_SYMBOL* originalSymbol = m_libTable->LoadSymbol( symbolId ); + if( symbolId.IsValid() ) + originalSymbol = m_libTable->LoadSymbol( symbolId ); if( originalSymbol ) { @@ -314,6 +366,11 @@ LIB_SYMBOL* SCH_DATABASE_PLUGIN::loadSymbolFromRow( const wxString& aSymbolName, symbol = originalSymbol->Duplicate(); symbol->SetSourceLibId( symbolId ); } + else if( !symbolId.IsValid() ) + { + wxLogTrace( traceDatabase, wxT( "loadSymboFromRow: source symbol id '%s' is invalid, " + "will create empty symbol" ), symbolIdStr ); + } else { wxLogTrace( traceDatabase, wxT( "loadSymboFromRow: source symbol '%s' not found, " @@ -376,15 +433,33 @@ LIB_SYMBOL* SCH_DATABASE_PLUGIN::loadSymbolFromRow( const wxString& aSymbolName, if( !aTable.properties.exclude_from_board.empty() && aRow.count( aTable.properties.exclude_from_board ) ) { - bool exclude = std::any_cast( aRow.at( aTable.properties.exclude_from_board ) ); - symbol->SetIncludeOnBoard( !exclude ); + std::optional val = boolFromAny( aRow.at( aTable.properties.exclude_from_board ) ); + + if( val ) + { + symbol->SetIncludeOnBoard( !( *val ) ); + } + else + { + wxLogTrace( traceDatabase, wxT( "loadSymbolFromRow: exclude_from_board value for %s " + "could not be cast to a boolean" ), aSymbolName ); + } } if( !aTable.properties.exclude_from_bom.empty() && aRow.count( aTable.properties.exclude_from_bom ) ) { - bool exclude = std::any_cast( aRow.at( aTable.properties.exclude_from_bom ) ); - symbol->SetIncludeInBom( !exclude ); + std::optional val = boolFromAny( aRow.at( aTable.properties.exclude_from_bom ) ); + + if( val ) + { + symbol->SetIncludeInBom( !( *val ) ); + } + else + { + wxLogTrace( traceDatabase, wxT( "loadSymbolFromRow: exclude_from_bom value for %s " + "could not be cast to a boolean" ), aSymbolName ); + } } std::vector fields; @@ -399,7 +474,7 @@ LIB_SYMBOL* SCH_DATABASE_PLUGIN::loadSymbolFromRow( const wxString& aSymbolName, { if( !aRow.count( mapping.column ) ) { - wxLogTrace( traceDatabase, wxT( "loadSymboFromRow: field %s not found in result" ), + wxLogTrace( traceDatabase, wxT( "loadSymbolFromRow: field %s not found in result" ), mapping.column ); continue; } diff --git a/eeschema/sch_plugins/database/sch_database_plugin.h b/eeschema/sch_plugins/database/sch_database_plugin.h index a2f6cfeff2..0c7b04873f 100644 --- a/eeschema/sch_plugins/database/sch_database_plugin.h +++ b/eeschema/sch_plugins/database/sch_database_plugin.h @@ -103,6 +103,8 @@ private: const DATABASE_LIB_TABLE& aTable, const DATABASE_CONNECTION::ROW& aRow ); + static std::optional boolFromAny( const std::any& aVal ); + SYMBOL_LIB_TABLE* m_libTable; std::unique_ptr m_settings;