diff --git a/common/database/database_connection.cpp b/common/database/database_connection.cpp index 118a8091db..e195502c01 100644 --- a/common/database/database_connection.cpp +++ b/common/database/database_connection.cpp @@ -448,7 +448,7 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable, { aResult[column] = fmt::format( "{:G}", results.get( i ) ); } - catch( nanodbc::null_access_error& e ) + catch( nanodbc::null_access_error& ) { // Column was empty (null) aResult[column] = std::string(); @@ -498,6 +498,8 @@ bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, const std::strin { wxLogTrace( traceDatabase, wxT( "SelectAll: `%s` - cache hit" ), aTable ); + aResults.reserve( cacheEntry.size() ); + for( auto &[ key, row ] : cacheEntry ) aResults.emplace_back( row ); @@ -605,7 +607,7 @@ bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, const std::strin { result[column] = fmt::format( "{:G}", results.get( j ) ); } - catch( nanodbc::null_access_error& e ) + catch( nanodbc::null_access_error& ) { // Column was empty (null) result[column] = std::string(); diff --git a/common/database/database_lib_settings.cpp b/common/database/database_lib_settings.cpp index f4685194f2..39929e7807 100644 --- a/common/database/database_lib_settings.cpp +++ b/common/database/database_lib_settings.cpp @@ -32,6 +32,17 @@ const int dblibSchemaVersion = 1; +DATABASE_FIELD_MAPPING::DATABASE_FIELD_MAPPING( std::string aColumn, std::string aName, + bool aVisibleOnAdd, bool aVisibleInChooser, + bool aShowName, bool aInheritProperties ) : + column( aColumn ), + name( aName ), name_wx( aName.c_str(), wxConvUTF8 ), visible_on_add( aVisibleOnAdd ), + visible_in_chooser( aVisibleInChooser ), show_name( aShowName ), + inherit_properties( aInheritProperties ) +{ +} + + DATABASE_LIB_SETTINGS::DATABASE_LIB_SETTINGS( const std::string& aFilename ) : JSON_SETTINGS( aFilename, SETTINGS_LOC::NONE, dblibSchemaVersion ) { @@ -113,11 +124,8 @@ DATABASE_LIB_SETTINGS::DATABASE_LIB_SETTINGS( const std::string& aFilename ) : bool inherit = fetchOrDefault( fieldJson, "inherit_properties" ); table.fields.emplace_back( - DATABASE_FIELD_MAPPING( - { - column, name, visible_on_add, visible_in_chooser, show_name, - inherit - } ) ); + DATABASE_FIELD_MAPPING( column, name, visible_on_add, + visible_in_chooser, show_name, inherit ) ); } } diff --git a/common/string_utils.cpp b/common/string_utils.cpp index 02d9bbe4f4..675da328e8 100644 --- a/common/string_utils.cpp +++ b/common/string_utils.cpp @@ -313,40 +313,40 @@ wxString UnescapeString( const wxString& aSource ) } else { - token.append( ch ); + token << ch; } } if( !terminated ) { - newbuf.append( wxT( "{" ) + UnescapeString( token ) ); + newbuf << wxT( "{" ) << UnescapeString( token ); } else if( prev == '$' || prev == '~' || prev == '^' || prev == '_' ) { - newbuf.append( wxT( "{" ) + UnescapeString( token ) + wxT( "}" ) ); + newbuf << wxT( "{" ) << UnescapeString( token ) << wxT( "}" ); } - else if( token == wxT( "dblquote" ) ) newbuf.append( wxT( "\"" ) ); - else if( token == wxT( "quote" ) ) newbuf.append( wxT( "'" ) ); - else if( token == wxT( "lt" ) ) newbuf.append( wxT( "<" ) ); - else if( token == wxT( "gt" ) ) newbuf.append( wxT( ">" ) ); - else if( token == wxT( "backslash" ) ) newbuf.append( wxT( "\\" ) ); - else if( token == wxT( "slash" ) ) newbuf.append( wxT( "/" ) ); - else if( token == wxT( "bar" ) ) newbuf.append( wxT( "|" ) ); - else if( token == wxT( "comma" ) ) newbuf.append( wxT( "," ) ); - else if( token == wxT( "colon" ) ) newbuf.append( wxT( ":" ) ); - else if( token == wxT( "space" ) ) newbuf.append( wxT( " " ) ); - else if( token == wxT( "dollar" ) ) newbuf.append( wxT( "$" ) ); - else if( token == wxT( "tab" ) ) newbuf.append( wxT( "\t" ) ); - else if( token == wxT( "return" ) ) newbuf.append( wxT( "\n" ) ); - else if( token == wxT( "brace" ) ) newbuf.append( wxT( "{" ) ); + else if( token == wxT( "dblquote" ) ) newbuf << wxT( "\"" ); + else if( token == wxT( "quote" ) ) newbuf << wxT( "'" ); + else if( token == wxT( "lt" ) ) newbuf << wxT( "<" ); + else if( token == wxT( "gt" ) ) newbuf << wxT( ">" ); + else if( token == wxT( "backslash" ) ) newbuf << wxT( "\\" ); + else if( token == wxT( "slash" ) ) newbuf << wxT( "/" ); + else if( token == wxT( "bar" ) ) newbuf << wxT( "|" ); + else if( token == wxT( "comma" ) ) newbuf << wxT( "," ); + else if( token == wxT( "colon" ) ) newbuf << wxT( ":" ); + else if( token == wxT( "space" ) ) newbuf << wxT( " " ); + else if( token == wxT( "dollar" ) ) newbuf << wxT( "$" ); + else if( token == wxT( "tab" ) ) newbuf << wxT( "\t" ); + else if( token == wxT( "return" ) ) newbuf << wxT( "\n" ); + else if( token == wxT( "brace" ) ) newbuf << wxT( "{" ); else { - newbuf.append( wxT( "{" ) + UnescapeString( token ) + wxT( "}" ) ); + newbuf << wxT( "{" ) << UnescapeString( token ) << wxT( "}" ); } } else { - newbuf.append( ch ); + newbuf << ch; } } @@ -785,11 +785,14 @@ int StrNumCmp( const wxString& aString1, const wxString& aString2, bool aIgnoreC // Any numerical comparisons to here are identical. if( aIgnoreCase ) { - if( wxToupper( c1 ) < wxToupper( c2 ) ) - return -1; + if( c1 != c2 ) + { + wxUniChar uc1 = wxToupper( c1 ); + wxUniChar uc2 = wxToupper( c2 ); - if( wxToupper( c1 ) > wxToupper( c2 ) ) - return 1; + if( uc1 != uc2 ) + return uc1 < uc2 ? -1 : 1; + } } else { diff --git a/common/template_fieldnames.cpp b/common/template_fieldnames.cpp index 4377e2a9e6..b5a75a796c 100644 --- a/common/template_fieldnames.cpp +++ b/common/template_fieldnames.cpp @@ -54,8 +54,16 @@ const wxString TEMPLATE_FIELDNAME::GetDefaultFieldName( int aFieldNdx, bool aTra case FOOTPRINT_FIELD: return s_CanonicalFootprint; // The footprint for use with Pcbnew case DATASHEET_FIELD: return s_CanonicalDatasheet; // Link to a datasheet for symbol case DESCRIPTION_FIELD: return s_CanonicalDescription; // The symbol description - default: return wxString::Format( wxT( "Field%d" ), aFieldNdx ); + default: break; } + + wxString str( wxS( "Field" ) ); +#if wxUSE_UNICODE_WCHAR + str << std::to_wstring( aFieldNdx ); +#else + str << std::to_string( aFieldNdx ); +#endif + return str; } switch( aFieldNdx ) diff --git a/eeschema/sch_io/database/sch_io_database.cpp b/eeschema/sch_io/database/sch_io_database.cpp index ff02badc2f..d8e2b47b69 100644 --- a/eeschema/sch_io/database/sch_io_database.cpp +++ b/eeschema/sch_io/database/sch_io_database.cpp @@ -568,6 +568,9 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName, for( LIB_FIELD* field : fields ) fieldsMap[field->GetName()] = field; + static const wxString c_valueFieldName( wxS( "Value" ) ); + static const wxString c_datasheetFieldName( wxS( "Datasheet" ) ); + for( const DATABASE_FIELD_MAPPING& mapping : aTable.fields ) { if( !aRow.count( mapping.column ) ) @@ -577,7 +580,7 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName, continue; } - std:: string strValue; + std::string strValue; try { @@ -589,7 +592,7 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName, wxString value( strValue.c_str(), wxConvUTF8 ); - if( mapping.name == wxT( "Value" ) ) + if( mapping.name_wx == c_valueFieldName ) { LIB_FIELD& field = symbol->GetValueField(); field.SetText( value ); @@ -601,7 +604,7 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName, } continue; } - else if( mapping.name == wxT( "Datasheet" ) ) + else if( mapping.name_wx == c_datasheetFieldName ) { LIB_FIELD& field = symbol->GetDatasheetField(); field.SetText( value ); @@ -621,16 +624,16 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName, LIB_FIELD* field; bool isNew = false; - if( fieldsMap.count( mapping.name ) ) + if( fieldsMap.count( mapping.name_wx ) ) { - field = fieldsMap[mapping.name]; + field = fieldsMap[mapping.name_wx]; } else { field = new LIB_FIELD( symbol->GetNextAvailableFieldId() ); - field->SetName( mapping.name ); + field->SetName( mapping.name_wx ); isNew = true; - fieldsMap[mapping.name] = field; + fieldsMap[mapping.name_wx] = field; } if( !mapping.inherit_properties || isNew ) @@ -643,13 +646,15 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName, field->SetText( value ); if( isNew ) - symbol->AddField( field ); + symbol->AddDrawItem( field, false ); - m_customFields.insert( mapping.name ); + m_customFields.insert( mapping.name_wx ); if( mapping.visible_in_chooser ) - m_defaultShownFields.insert( mapping.name ); + m_defaultShownFields.insert( mapping.name_wx ); } + symbol->GetDrawItems().sort(); + return symbol; } diff --git a/eeschema/sim/sim_model.cpp b/eeschema/sim/sim_model.cpp index dcb7d78b51..0dd6c5574b 100644 --- a/eeschema/sim/sim_model.cpp +++ b/eeschema/sim/sim_model.cpp @@ -1644,12 +1644,21 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject ) wxString prefix = aSymbol.GetPrefix(); T_field* valueField = aSymbol.FindField( wxT( "Value" ) ); std::vector sourcePins = aSymbol.GetAllLibPins(); + bool sourcePinsSorted = false; - std::sort( sourcePins.begin(), sourcePins.end(), - []( const LIB_PIN* lhs, const LIB_PIN* rhs ) - { - return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0; - } ); + auto lazySortSourcePins = [&sourcePins, &sourcePinsSorted]() + { + if( !sourcePinsSorted ) + { + std::sort( sourcePins.begin(), sourcePins.end(), + []( const LIB_PIN* lhs, const LIB_PIN* rhs ) + { + return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0; + } ); + } + + sourcePinsSorted = true; + }; FIELD_INFO deviceInfo; FIELD_INFO modelInfo; @@ -1740,6 +1749,8 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject ) wxStringSplit( legacyPins->GetText(), pinIndexes, ' ' ); + lazySortSourcePins(); + if( isPassive && pinIndexes.size() == 2 && sourcePins.size() == 2 ) { if( pinIndexes[0] == wxT( "2" ) ) @@ -1800,6 +1811,8 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject ) model = model.BeforeFirst( ' ', &modelLineParams ); modelInfo.m_Text = model; + lazySortSourcePins(); + SIM_LIBRARY::MODEL simModel = libMgr.CreateModel( lib, model.ToStdString(), emptyFields, sourcePins, reporter ); @@ -1873,6 +1886,8 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject ) if( pinMapInfo.IsEmpty() ) { + lazySortSourcePins(); + // Generate a default pin map from the SIM_MODEL's pins simModel->createPins( sourcePins ); pinMapInfo.m_Text = wxString( simModel->Serializer().GeneratePins() ); @@ -1979,7 +1994,10 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject ) // the default pin map from the symbol's pins. if( pinMapInfo.IsEmpty() ) + { + lazySortSourcePins(); pinMapInfo.m_Text = generateDefaultPinMapFromSymbol( sourcePins ); + } } if( !pinMapInfo.IsEmpty() ) diff --git a/eeschema/symbol_tree_model_adapter.cpp b/eeschema/symbol_tree_model_adapter.cpp index 723930a5d3..32ceb3fb07 100644 --- a/eeschema/symbol_tree_model_adapter.cpp +++ b/eeschema/symbol_tree_model_adapter.cpp @@ -163,13 +163,15 @@ bool SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector& aNick if( !parentDesc.IsEmpty() ) desc = wxString::Format( wxT( "%s (%s)" ), parentDesc, lib ); + UTF8 utf8Lib( lib ); + std::vector symbols; std::copy_if( libSymbols.begin(), libSymbols.end(), std::back_inserter( symbols ), - [&lib]( LIB_SYMBOL* aSym ) + [&utf8Lib]( LIB_SYMBOL* aSym ) { - return lib.IsSameAs( aSym->GetLibId().GetSubLibraryName() ); + return utf8Lib == aSym->GetLibId().GetSubLibraryName(); } ); addFunc( name, symbols, desc ); diff --git a/include/database/database_lib_settings.h b/include/database/database_lib_settings.h index 06de70ce49..c090011476 100644 --- a/include/database/database_lib_settings.h +++ b/include/database/database_lib_settings.h @@ -22,6 +22,7 @@ #define KICAD_DATABASE_LIB_SETTINGS_H #include +#include enum class DATABASE_SOURCE_TYPE @@ -44,12 +45,17 @@ struct DATABASE_SOURCE struct DATABASE_FIELD_MAPPING { - std::string column; ///< Database column name - std::string name; ///< KiCad field name - bool visible_on_add; ///< Whether to show the field when placing the symbol - bool visible_in_chooser; ///< Whether the column is shown by default in the chooser - bool show_name; ///< Whether or not to show the field name as well as its value - bool inherit_properties; ///< Whether or not to inherit properties from symbol field + const std::string column; ///< Database column name + const std::string name; ///< KiCad field name + const wxString name_wx; ///< KiCad field name (converted) + const bool visible_on_add; ///< Whether to show the field when placing the symbol + const bool visible_in_chooser; ///< Whether the column is shown by default in the chooser + const bool show_name; ///< Whether or not to show the field name as well as its value + const bool inherit_properties; ///< Whether or not to inherit properties from symbol field + + explicit DATABASE_FIELD_MAPPING( std::string aColumn, std::string aName, bool aVisibleOnAdd, + bool aVisibleInChooser, bool aShowName, + bool aInheritProperties ); };