22#include <unordered_set>
23#include <wx/datetime.h>
26#include <boost/algorithm/string.hpp>
38 m_libTable( nullptr ),
53 const wxString& aLibraryPath,
54 const std::map<std::string, UTF8>* aProperties )
56 std::vector<LIB_SYMBOL*> symbols;
60 aSymbolNameList.Add( symbol->GetName() );
65 const wxString& aLibraryPath,
66 const std::map<std::string, UTF8>* aProperties )
68 wxCHECK_RET(
m_libTable,
"Database plugin missing library table handle!" );
76 bool powerSymbolsOnly = ( aProperties &&
84 if( !powerSymbolsOnly || symbol->
IsPower() )
85 aSymbolList.emplace_back( symbol );
91 const wxString& aAliasName,
92 const std::map<std::string, UTF8>* aProperties )
110 std::string tableName =
"";
111 std::string symbolName( aAliasName.ToUTF8() );
113 if( aAliasName.Contains(
'/' ) )
115 tableName = std::string( aAliasName.BeforeFirst(
'/' ).ToUTF8() );
116 symbolName = std::string( aAliasName.AfterFirst(
'/' ).ToUTF8() );
119 std::vector<const DATABASE_LIB_TABLE*> tablesToTry;
123 if( tableIter.
name == tableName )
124 tablesToTry.emplace_back( &tableIter );
127 if( tablesToTry.empty() )
129 wxLogTrace(
traceDatabase, wxT(
"LoadSymbol: table '%s' not found in config" ), tableName );
138 if(
m_conn->SelectOne( table->table, std::make_pair( table->key_col, symbolName ),
142 wxLogTrace(
traceDatabase, wxT(
"LoadSymbol: SelectOne (%s, %s) found in %s" ),
143 table->key_col, symbolName, table->table );
147 wxLogTrace(
traceDatabase, wxT(
"LoadSymbol: SelectOne (%s, %s) failed for table %s" ),
148 table->key_col, symbolName, table->table );
152 wxCHECK( foundTable,
nullptr );
164 std::set<wxString> tableNames;
168 if( tableNames.count( tableIter.
name ) )
171 aNames.emplace_back( tableIter.
name );
172 tableNames.insert( tableIter.
name );
186 std::back_inserter( aNames ) );
197 if( aErrorMsg && ( !
m_conn || !
m_conn->IsConnected() ) )
206 long long currentTimestampSeconds = wxDateTime::Now().GetValue().GetValue() / 1000;
216 std::vector<DATABASE_CONNECTION::ROW> results;
220 if( !
m_conn->GetLastError().empty() )
222 wxString msg = wxString::Format(
_(
"Error reading database table %s: %s" ),
232 if( !result.count( table.
key_col ) )
235 std::string prefix = table.
name.empty() ?
"" : fmt::format(
"{}/", table.
name );
236 wxString
name( fmt::format(
"{}{}", prefix,
237 std::any_cast<std::string>( result[table.
key_col] ) ) );
257 wxString msg = wxString::Format(
258 _(
"Could not load database library: settings file %s missing or invalid" ),
267 std::string
path( aSettingsPath.ToUTF8() );
280 wxASSERT_MSG( aSettingsPath ==
m_settings->GetFilename(),
281 "Path changed for database library without re-initializing plugin!" );
285 wxLogTrace(
traceDatabase, wxT(
"ensureSettings: no settings but no valid path!" ) );
292 wxCHECK_RET(
m_settings,
"Call ensureSettings before ensureConnection!" );
298 wxString msg = wxString::Format(
299 _(
"Could not load database library: could not connect to database %s (%s)" ),
309 wxCHECK_RET(
m_settings,
"Call ensureSettings before connect()!" );
316 if(
m_settings->m_Source.connection_string.empty() )
325 std::string cs =
m_settings->m_Source.connection_string;
326 std::string basePath( wxFileName(
m_settings->GetFilename() ).GetPath().ToUTF8() );
330 boost::replace_all( cs,
"${CWD}", basePath );
332 m_conn = std::make_unique<DATABASE_CONNECTION>( cs,
m_settings->m_Source.timeout );
335 if( !
m_conn->IsConnected() )
344 std::set<std::string> columns;
346 columns.insert( tableIter.
key_col );
358 columns.insert( field.
column );
360 m_conn->CacheTableInfo( tableIter.
table, columns );
372 bool val = std::any_cast<bool>( aVal );
375 catch(
const std::bad_any_cast& )
381 int val = std::any_cast<int>( aVal );
382 return static_cast<bool>( val );
384 catch(
const std::bad_any_cast& )
390 wxString strval( std::any_cast<std::string>( aVal ).c_str(), wxConvUTF8 );
392 if( strval.IsEmpty() )
397 for(
const auto& trueVal : { wxS(
"true" ), wxS(
"yes" ), wxS(
"y" ), wxS(
"1" ) } )
399 if( strval.Matches( trueVal ) )
403 for(
const auto& falseVal : { wxS(
"false" ), wxS(
"no" ), wxS(
"n" ), wxS(
"0" ) } )
405 if( strval.Matches( falseVal ) )
409 catch(
const std::bad_any_cast& )
421 std::unique_ptr<LIB_SYMBOL> symbol =
nullptr;
428 std::string symbolIdStr = std::any_cast<std::string>( aRow.at( aTable.
symbols_col ) );
430 symbolId.
Parse( std::any_cast<std::string>( aRow.at( aTable.
symbols_col ) ) );
437 wxLogTrace(
traceDatabase, wxT(
"loadSymbolFromRow: found original symbol '%s'" ),
439 symbol.reset( originalSymbol->
Duplicate() );
440 symbol->SetSourceLibId( symbolId );
444 wxLogTrace(
traceDatabase, wxT(
"loadSymboFromRow: source symbol id '%s' is invalid, "
445 "will create empty symbol" ), symbolIdStr );
449 wxLogTrace(
traceDatabase, wxT(
"loadSymboFromRow: source symbol '%s' not found, "
450 "will create empty symbol" ), symbolIdStr );
458 symbol.reset(
new LIB_SYMBOL( aSymbolName ) );
462 symbol->SetName( aSymbolName );
465 LIB_ID libId = symbol->GetLibId();
467 symbol->SetLibId( libId );
471 std::string footprints = std::any_cast<std::string>( aRow.at( aTable.
footprints_col ) );
473 wxString footprintsStr = wxString( footprints.c_str(), wxConvUTF8 );
474 wxArrayString footprintsList;
475 wxStringTokenizer tokenizer( footprintsStr,
';' );
477 while( tokenizer.HasMoreTokens() )
478 footprintsList.Add( tokenizer.GetNextToken() );
480 if( footprintsList.size() > 0 )
481 symbol->GetFootprintField().SetText( footprintsList[0] );
483 symbol->SetFPFilters( footprintsList );
487 wxLogTrace(
traceDatabase, wxT(
"loadSymboFromRow: footprint field %s not found." ),
496 symbol->SetDescription( value );
501 wxString value( std::any_cast<std::string>( aRow.at( aTable.
properties.
keywords ) ).c_str(),
503 symbol->SetKeyWords( value );
512 wxArrayString filters;
513 filters.push_back( value );
514 symbol->SetFPFilters( filters );
524 symbol->SetExcludedFromSim( *val );
528 wxLogTrace(
traceDatabase, wxT(
"loadSymbolFromRow: exclude_from_sim value for %s "
529 "could not be cast to a boolean" ), aSymbolName );
540 symbol->SetExcludedFromBoard( *val );
544 wxLogTrace(
traceDatabase, wxT(
"loadSymbolFromRow: exclude_from_board value for %s "
545 "could not be cast to a boolean" ), aSymbolName );
556 symbol->SetExcludedFromBOM( *val );
560 wxLogTrace(
traceDatabase, wxT(
"loadSymbolFromRow: exclude_from_bom value for %s "
561 "could not be cast to a boolean" ), aSymbolName );
565 std::vector<SCH_FIELD*> fields;
566 symbol->GetFields( fields );
568 std::unordered_map<wxString, SCH_FIELD*> fieldsMap;
571 fieldsMap[field->GetName()] = field;
573 static const wxString c_valueFieldName( wxS(
"Value" ) );
574 static const wxString c_datasheetFieldName( wxS(
"Datasheet" ) );
578 if( !aRow.count( mapping.
column ) )
580 wxLogTrace(
traceDatabase, wxT(
"loadSymbolFromRow: field %s not found in result" ),
589 strValue = std::any_cast<std::string>( aRow.at( mapping.
column ) );
591 catch( std::bad_any_cast& )
595 wxString value(
strValue.c_str(), wxConvUTF8 );
597 if( mapping.
name_wx == c_valueFieldName )
599 SCH_FIELD& field = symbol->GetValueField();
609 else if( mapping.
name_wx == c_datasheetFieldName )
611 SCH_FIELD& field = symbol->GetDatasheetField();
629 if( fieldsMap.count( mapping.
name_wx ) )
631 field = fieldsMap[mapping.
name_wx];
635 field =
new SCH_FIELD(
nullptr, symbol->GetNextAvailableFieldId() );
638 fieldsMap[mapping.
name_wx] = field;
651 symbol->AddDrawItem( field,
false );
659 symbol->GetDrawItems().sort();
std::map< std::string, std::any > ROW
virtual void SetVisible(bool aVisible)
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
bool IsValid() const
Check if this LID_ID is valid.
void SetSubLibraryName(const UTF8 &aName)
Define a library symbol object.
bool IsPower() const override
virtual LIB_SYMBOL * Duplicate() const
Create a copy of a LIB_SYMBOL and assigns unique KIIDs to the copy and its children.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
void SetAutoAdded(bool aAutoAdded)
void SetName(const wxString &aName)
void SetText(const wxString &aText) override
void SetNameShown(bool aShown=true)
void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
std::unique_ptr< DATABASE_CONNECTION > m_conn
Generally will be null if no valid connection is established.
void GetDefaultSymbolFields(std::vector< wxString > &aNames) override
Retrieves a list of (custom) field names that should be shown by default for this library in the symb...
void ensureSettings(const wxString &aSettingsPath)
bool TestConnection(wxString *aErrorMsg=nullptr)
std::map< wxString, std::unique_ptr< LIB_SYMBOL > > m_nameToSymbolcache
SYMBOL_LIB_TABLE * m_libTable
std::set< wxString > m_defaultShownFields
virtual ~SCH_IO_DATABASE()
void GetSubLibraryNames(std::vector< wxString > &aNames) override
Retrieves a list of sub-libraries in this library.
std::unique_ptr< DATABASE_LIB_SETTINGS > m_settings
static std::optional< bool > boolFromAny(const std::any &aVal)
long long m_cacheTimestamp
void GetAvailableSymbolFields(std::vector< wxString > &aNames) override
Retrieves a list of (custom) field names that are present on symbols in this library.
std::unique_ptr< LIB_SYMBOL > loadSymbolFromRow(const wxString &aSymbolName, const DATABASE_LIB_TABLE &aTable, const DATABASE_CONNECTION::ROW &aRow)
std::set< wxString > m_customFields
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aAliasName, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
Base class that schematic file and library loading and saving plugins should derive from.
static const char * PropPowerSymsOnly
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
const char *const traceDatabase
#define THROW_IO_ERROR(msg)
static std::string strValue(double aValue)
bool visible_in_chooser
Whether the column is shown by default in the chooser.
std::string column
Database column name.
bool inherit_properties
Whether or not to inherit properties from symbol field.
bool visible_on_add
Whether to show the field when placing the symbol.
bool show_name
Whether or not to show the field name as well as its value.
wxString name_wx
KiCad field name (converted)
A database library table will be mapped to a sub-library provided by the database library entry in th...
std::string key_col
Unique key column name (will form part of the LIB_ID)
std::string name
KiCad library nickname (will form part of the LIB_ID)
std::string symbols_col
Column name containing KiCad symbol refs.
std::string footprints_col
Column name containing KiCad footprint refs.
std::vector< DATABASE_FIELD_MAPPING > fields
std::string table
Database table to pull content from.
MAPPABLE_SYMBOL_PROPERTIES properties
std::string footprint_filters
std::string exclude_from_sim
std::string exclude_from_board
std::string exclude_from_bom