KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_io_database.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2022 Jon Evans <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <iostream>
22#include <unordered_set>
23#include <utility>
24#include <wx/datetime.h>
25#include <wx/log.h>
26
27#include <boost/algorithm/string.hpp>
28
32#include <fmt.h>
33#include <ki_exception.h>
34#include <lib_symbol.h>
35
36#include "sch_io_database.h"
37
39
40
42 SCH_IO( wxS( "Database library" ) ),
43 m_adapter( nullptr ),
44 m_settings(),
45 m_conn()
46{
49}
50
51
55
56
57void SCH_IO_DATABASE::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
58 const wxString& aLibraryPath,
59 const std::map<std::string, UTF8>* aProperties )
60{
61 std::vector<LIB_SYMBOL*> symbols;
62 EnumerateSymbolLib( symbols, aLibraryPath, aProperties );
63
64 for( LIB_SYMBOL* symbol : symbols )
65 aSymbolNameList.Add( symbol->GetName() );
66}
67
68
69void SCH_IO_DATABASE::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
70 const wxString& aLibraryPath,
71 const std::map<std::string, UTF8>* aProperties )
72{
73 wxCHECK_RET( m_adapter, "Database plugin missing library manager adapter handle!" );
74 ensureSettings( aLibraryPath );
76 cacheLib();
77
78 if( !m_conn )
80
81 bool powerSymbolsOnly = ( aProperties && aProperties->contains( SYMBOL_LIBRARY_ADAPTER::PropPowerSymsOnly ) );
82
83 for( auto const& pair : m_nameToSymbolcache )
84 {
85 LIB_SYMBOL* symbol = pair.second.get();
86
87 if( !powerSymbolsOnly || symbol->IsPower() )
88 aSymbolList.emplace_back( symbol );
89 }
90}
91
92
93LIB_SYMBOL* SCH_IO_DATABASE::LoadSymbol( const wxString& aLibraryPath,
94 const wxString& aAliasName,
95 const std::map<std::string, UTF8>* aProperties )
96{
97 wxCHECK_MSG( m_adapter, nullptr, "Database plugin missing library manager adapter handle!" );
98 ensureSettings( aLibraryPath );
100
101 if( !m_conn )
103
104 cacheLib();
105
106 /*
107 * Table names are tricky, in order to allow maximum flexibility to the user.
108 * The slash character is used as a separator between a table name and symbol name, but symbol
109 * names may also contain slashes and table names may now also be empty (which results in the
110 * slash being dropped in the symbol name when placing a new symbol). So, if a slash is found,
111 * we check if the string before the slash is a valid table name. If not, we assume the table
112 * name is blank if our config has an entry for the null table.
113 */
114
115 std::string tableName;
116 std::string symbolName( aAliasName.ToUTF8() );
117
118 auto sanitizedIt = m_sanitizedNameMap.find( aAliasName );
119
120 if( sanitizedIt != m_sanitizedNameMap.end() )
121 {
122 tableName = sanitizedIt->second.first;
123 symbolName = sanitizedIt->second.second;
124 }
125 else
126 {
127 tableName.clear();
128
129 if( aAliasName.Contains( '/' ) )
130 {
131 tableName = std::string( aAliasName.BeforeFirst( '/' ).ToUTF8() );
132 symbolName = std::string( aAliasName.AfterFirst( '/' ).ToUTF8() );
133 }
134 }
135
136 std::vector<const DATABASE_LIB_TABLE*> tablesToTry;
137
138 for( const DATABASE_LIB_TABLE& tableIter : m_settings->m_Tables )
139 {
140 if( tableIter.name == tableName )
141 tablesToTry.emplace_back( &tableIter );
142 }
143
144 if( tablesToTry.empty() )
145 {
146 wxLogTrace( traceDatabase, wxT( "LoadSymbol: table '%s' not found in config" ), tableName );
147 return nullptr;
148 }
149
150 const DATABASE_LIB_TABLE* foundTable = nullptr;
152
153 for( const DATABASE_LIB_TABLE* table : tablesToTry )
154 {
155 if( m_conn->SelectOne( table->table, std::make_pair( table->key_col, symbolName ),
156 result ) )
157 {
158 foundTable = table;
159 wxLogTrace( traceDatabase, wxT( "LoadSymbol: SelectOne (%s, %s) found in %s" ),
160 table->key_col, symbolName, table->table );
161 }
162 else
163 {
164 wxLogTrace( traceDatabase, wxT( "LoadSymbol: SelectOne (%s, %s) failed for table %s" ),
165 table->key_col, symbolName, table->table );
166 }
167 }
168
169 wxCHECK( foundTable, nullptr );
170
171 return loadSymbolFromRow( aAliasName, *foundTable, result ).release();
172}
173
174
175void SCH_IO_DATABASE::GetSubLibraryNames( std::vector<wxString>& aNames )
176{
177 ensureSettings( wxEmptyString );
178
179 aNames.clear();
180
181 std::set<wxString> tableNames;
182
183 for( const DATABASE_LIB_TABLE& tableIter : m_settings->m_Tables )
184 {
185 if( tableNames.count( tableIter.name ) )
186 continue;
187
188 aNames.emplace_back( tableIter.name );
189 tableNames.insert( tableIter.name );
190 }
191}
192
193
194void SCH_IO_DATABASE::GetAvailableSymbolFields( std::vector<wxString>& aNames )
195{
196 std::copy( m_customFields.begin(), m_customFields.end(), std::back_inserter( aNames ) );
197}
198
199
200void SCH_IO_DATABASE::GetDefaultSymbolFields( std::vector<wxString>& aNames )
201{
202 std::copy( m_defaultShownFields.begin(), m_defaultShownFields.end(),
203 std::back_inserter( aNames ) );
204}
205
206
207bool SCH_IO_DATABASE::TestConnection( wxString* aErrorMsg )
208{
209 if( m_conn && m_conn->IsConnected() )
210 return true;
211
212 connect();
213
214 if( aErrorMsg && ( !m_conn || !m_conn->IsConnected() ) )
215 *aErrorMsg = m_lastError;
216
217 return m_conn && m_conn->IsConnected();
218}
219
220
222{
223 long long currentTimestampSeconds = wxDateTime::Now().GetValue().GetValue() / 1000;
224
225 if( m_adapter->GetModifyHash() == m_cacheModifyHash
226 && ( currentTimestampSeconds - m_cacheTimestamp ) < m_settings->m_Cache.max_age )
227 {
228 return;
229 }
230
231 std::map<wxString, std::unique_ptr<LIB_SYMBOL>> newSymbolCache;
232 std::map<wxString, std::pair<std::string, std::string>> newSanitizedNameMap;
233
234 for( const DATABASE_LIB_TABLE& table : m_settings->m_Tables )
235 {
236 std::vector<DATABASE_CONNECTION::ROW> results;
237
238 if( !m_conn->SelectAll( table.table, table.key_col, results ) )
239 {
240 if( !m_conn->GetLastError().empty() )
241 {
242 wxString msg = wxString::Format( _( "Error reading database table %s: %s" ),
243 table.table, m_conn->GetLastError() );
244 THROW_IO_ERROR( msg );
245 }
246
247 continue;
248 }
249
250 for( DATABASE_CONNECTION::ROW& result : results )
251 {
252 if( !result.count( table.key_col ) )
253 continue;
254
255 std::string rawName = std::any_cast<std::string>( result[table.key_col] );
256 UTF8 sanitizedName = LIB_ID::FixIllegalChars( rawName, false );
257 std::string sanitizedKey = sanitizedName.c_str();
258 std::string prefix = table.name.empty() ? "" : fmt::format( "{}/", table.name );
259 std::string sanitizedDisplayName = fmt::format( "{}{}", prefix, sanitizedKey );
260 wxString name( sanitizedDisplayName );
261
262 newSanitizedNameMap[name] = std::make_pair( table.name, rawName );
263
264 std::unique_ptr<LIB_SYMBOL> symbol = loadSymbolFromRow( name, table, result );
265
266 if( symbol )
267 newSymbolCache[symbol->GetName()] = std::move( symbol );
268 }
269 }
270
271 m_nameToSymbolcache = std::move( newSymbolCache );
272 m_sanitizedNameMap = std::move( newSanitizedNameMap );
273
274 m_cacheTimestamp = currentTimestampSeconds;
275 m_cacheModifyHash = m_adapter->GetModifyHash();
276}
277
278void SCH_IO_DATABASE::ensureSettings( const wxString& aSettingsPath )
279{
280 auto tryLoad =
281 [&]()
282 {
283 if( !m_settings->LoadFromFile() )
284 {
285 wxString msg = wxString::Format(
286 _( "Could not load database library: settings file %s missing or invalid" ),
287 aSettingsPath );
288
289 THROW_IO_ERROR( msg );
290 }
291 };
292
293 if( !m_settings && !aSettingsPath.IsEmpty() )
294 {
295 std::string path( aSettingsPath.ToUTF8() );
296 m_settings = std::make_unique<DATABASE_LIB_SETTINGS>( path );
297 m_settings->SetReadOnly( true );
298
299 tryLoad();
300 }
301 else if( !m_conn && m_settings )
302 {
303 // If we have valid settings but no connection yet; reload settings in case user is editing
304 tryLoad();
305 }
306 else if( m_conn && m_settings && !aSettingsPath.IsEmpty() )
307 {
308 wxASSERT_MSG( aSettingsPath == m_settings->GetFilename(),
309 "Path changed for database library without re-initializing plugin!" );
310 }
311 else if( !m_settings )
312 {
313 wxLogTrace( traceDatabase, wxT( "ensureSettings: no settings but no valid path!" ) );
314 }
315}
316
317
319{
320 wxCHECK_RET( m_settings, "Call ensureSettings before ensureConnection!" );
321
322 connect();
323
324 if( !m_conn || !m_conn->IsConnected() )
325 {
326 wxString msg = wxString::Format(
327 _( "Could not load database library: could not connect to database %s (%s)" ),
328 m_settings->m_Source.dsn, m_lastError );
329
330 THROW_IO_ERROR( msg );
331 }
332}
333
334
336{
337 wxCHECK_RET( m_settings, "Call ensureSettings before connect()!" );
338
339 if( m_conn && !m_conn->IsConnected() )
340 m_conn.reset();
341
342 if( !m_conn )
343 {
344 if( m_settings->m_Source.connection_string.empty() )
345 {
346 m_conn = std::make_unique<DATABASE_CONNECTION>( m_settings->m_Source.dsn,
347 m_settings->m_Source.username,
348 m_settings->m_Source.password,
349 m_settings->m_Source.timeout );
350 }
351 else
352 {
353 std::string cs = m_settings->m_Source.connection_string;
354 std::string basePath( wxFileName( m_settings->GetFilename() ).GetPath().ToUTF8() );
355
356 // Database drivers that use files operate on absolute paths, so provide a mechanism
357 // for specifying on-disk databases that live next to the kicad_dbl file
358 boost::replace_all( cs, "${CWD}", basePath );
359
360 m_conn = std::make_unique<DATABASE_CONNECTION>( cs, m_settings->m_Source.timeout );
361 }
362
363 if( !m_conn->IsConnected() )
364 {
365 m_lastError = m_conn->GetLastError();
366 m_conn.reset();
367 return;
368 }
369
370 for( const DATABASE_LIB_TABLE& tableIter : m_settings->m_Tables )
371 {
372 std::set<std::string> columns;
373
374 columns.insert( boost::to_lower_copy( tableIter.key_col ) );
375 columns.insert( boost::to_lower_copy( tableIter.footprints_col ) );
376 columns.insert( boost::to_lower_copy( tableIter.symbols_col ) );
377
378 columns.insert( boost::to_lower_copy( tableIter.properties.description ) );
379 columns.insert( boost::to_lower_copy( tableIter.properties.footprint_filters ) );
380 columns.insert( boost::to_lower_copy( tableIter.properties.keywords ) );
381 columns.insert( boost::to_lower_copy( tableIter.properties.exclude_from_sim ) );
382 columns.insert( boost::to_lower_copy( tableIter.properties.exclude_from_bom ) );
383 columns.insert( boost::to_lower_copy( tableIter.properties.exclude_from_board ) );
384
385 for( const DATABASE_FIELD_MAPPING& field : tableIter.fields )
386 columns.insert( boost::to_lower_copy( field.column ) );
387
388 m_conn->CacheTableInfo( tableIter.table, columns );
389 }
390
391 m_conn->SetCacheParams( m_settings->m_Cache.max_size, m_settings->m_Cache.max_age );
392 }
393}
394
395
396std::optional<bool> SCH_IO_DATABASE::boolFromAny( const std::any& aVal )
397{
398 try
399 {
400 bool val = std::any_cast<bool>( aVal );
401 return val;
402 }
403 catch( const std::bad_any_cast& )
404 {
405 }
406
407 try
408 {
409 int val = std::any_cast<int>( aVal );
410 return static_cast<bool>( val );
411 }
412 catch( const std::bad_any_cast& )
413 {
414 }
415
416 try
417 {
418 wxString strval( std::any_cast<std::string>( aVal ).c_str(), wxConvUTF8 );
419
420 if( strval.IsEmpty() )
421 return std::nullopt;
422
423 strval.MakeLower();
424
425 for( const auto& trueVal : { wxS( "true" ), wxS( "yes" ), wxS( "y" ), wxS( "1" ) } )
426 {
427 if( strval.Matches( trueVal ) )
428 return true;
429 }
430
431 for( const auto& falseVal : { wxS( "false" ), wxS( "no" ), wxS( "n" ), wxS( "0" ) } )
432 {
433 if( strval.Matches( falseVal ) )
434 return false;
435 }
436 }
437 catch( const std::bad_any_cast& )
438 {
439 }
440
441 return std::nullopt;
442}
443
444
445std::unique_ptr<LIB_SYMBOL> SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName,
446 const DATABASE_LIB_TABLE& aTable,
447 const DATABASE_CONNECTION::ROW& aRow )
448{
449 std::unique_ptr<LIB_SYMBOL> symbol = nullptr;
450
451 if( aRow.count( aTable.symbols_col ) )
452 {
453 LIB_SYMBOL* originalSymbol = nullptr;
454
455 // TODO: Support multiple options for symbol
456 std::string symbolIdStr = std::any_cast<std::string>( aRow.at( aTable.symbols_col ) );
457 LIB_ID symbolId;
458 symbolId.Parse( std::any_cast<std::string>( aRow.at( aTable.symbols_col ) ) );
459
460 if( symbolId.IsValid() )
461 originalSymbol = m_adapter->LoadSymbol( symbolId );
462
463 if( originalSymbol )
464 {
465 wxLogTrace( traceDatabase, wxT( "loadSymbolFromRow: found original symbol '%s'" ),
466 symbolIdStr );
467 symbol.reset( originalSymbol->Duplicate() );
468 symbol->SetSourceLibId( symbolId );
469 }
470 else if( !symbolId.IsValid() )
471 {
472 wxLogTrace( traceDatabase, wxT( "loadSymboFromRow: source symbol id '%s' is invalid, "
473 "will create empty symbol" ), symbolIdStr );
474 }
475 else
476 {
477 wxLogTrace( traceDatabase, wxT( "loadSymboFromRow: source symbol '%s' not found, "
478 "will create empty symbol" ), symbolIdStr );
479 }
480 }
481
482 if( !symbol )
483 {
484 // Actual symbol not found: return metadata only; error will be indicated in the
485 // symbol chooser
486 symbol.reset( new LIB_SYMBOL( aSymbolName ) );
487 }
488 else
489 {
490 symbol->SetName( aSymbolName );
491 }
492
493 LIB_ID libId = symbol->GetLibId();
494 libId.SetSubLibraryName( aTable.name );;
495 symbol->SetLibId( libId );
496 wxArrayString footprintsList;
497
498 if( aRow.count( aTable.footprints_col ) )
499 {
500 std::string footprints = std::any_cast<std::string>( aRow.at( aTable.footprints_col ) );
501
502 wxString footprintsStr = wxString( footprints.c_str(), wxConvUTF8 );
503 wxStringTokenizer tokenizer( footprintsStr, ";\t\r\n", wxTOKEN_STRTOK );
504
505 while( tokenizer.HasMoreTokens() )
506 footprintsList.Add( tokenizer.GetNextToken() );
507
508 if( footprintsList.size() > 0 )
509 symbol->GetFootprintField().SetText( footprintsList[0] );
510 }
511 else
512 {
513 wxLogTrace( traceDatabase, wxT( "loadSymboFromRow: footprint field %s not found." ),
514 aTable.footprints_col );
515 }
516
517 if( !aTable.properties.description.empty() && aRow.count( aTable.properties.description ) )
518 {
519 wxString value(
520 std::any_cast<std::string>( aRow.at( aTable.properties.description ) ).c_str(),
521 wxConvUTF8 );
522 symbol->SetDescription( value );
523 }
524
525 if( !aTable.properties.keywords.empty() && aRow.count( aTable.properties.keywords ) )
526 {
527 wxString value( std::any_cast<std::string>( aRow.at( aTable.properties.keywords ) ).c_str(),
528 wxConvUTF8 );
529 symbol->SetKeyWords( value );
530 }
531
532 if( !aTable.properties.footprint_filters.empty()
533 && aRow.count( aTable.properties.footprint_filters ) )
534 {
535 wxString value( std::any_cast<std::string>( aRow.at( aTable.properties.footprint_filters ) )
536 .c_str(),
537 wxConvUTF8 );
538 footprintsList.push_back( value );
539 }
540
541 symbol->SetFPFilters( footprintsList );
542
543 if( !aTable.properties.exclude_from_sim.empty()
544 && aRow.count( aTable.properties.exclude_from_sim ) )
545 {
546 std::optional<bool> val = boolFromAny( aRow.at( aTable.properties.exclude_from_sim ) );
547
548 if( val )
549 {
550 symbol->SetExcludedFromSim( *val );
551 }
552 else
553 {
554 wxLogTrace( traceDatabase, wxT( "loadSymbolFromRow: exclude_from_sim value for %s "
555 "could not be cast to a boolean" ), aSymbolName );
556 }
557 }
558
559 if( !aTable.properties.exclude_from_board.empty()
560 && aRow.count( aTable.properties.exclude_from_board ) )
561 {
562 std::optional<bool> val = boolFromAny( aRow.at( aTable.properties.exclude_from_board ) );
563
564 if( val )
565 {
566 symbol->SetExcludedFromBoard( *val );
567 }
568 else
569 {
570 wxLogTrace( traceDatabase, wxT( "loadSymbolFromRow: exclude_from_board value for %s "
571 "could not be cast to a boolean" ), aSymbolName );
572 }
573 }
574
575 if( !aTable.properties.exclude_from_bom.empty()
576 && aRow.count( aTable.properties.exclude_from_bom ) )
577 {
578 std::optional<bool> val = boolFromAny( aRow.at( aTable.properties.exclude_from_bom ) );
579
580 if( val )
581 {
582 symbol->SetExcludedFromBOM( *val );
583 }
584 else
585 {
586 wxLogTrace( traceDatabase, wxT( "loadSymbolFromRow: exclude_from_bom value for %s "
587 "could not be cast to a boolean" ), aSymbolName );
588 }
589 }
590
591 std::vector<SCH_FIELD*> fields;
592 symbol->GetFields( fields );
593
594 std::unordered_map<wxString, SCH_FIELD*> fieldsMap;
595
596 for( SCH_FIELD* field : fields )
597 fieldsMap[field->GetName()] = field;
598
599 static const wxString c_valueFieldName( wxS( "Value" ) );
600 static const wxString c_datasheetFieldName( wxS( "Datasheet" ) );
601
602 for( const DATABASE_FIELD_MAPPING& mapping : aTable.fields )
603 {
604 if( !aRow.count( mapping.column ) )
605 {
606 wxLogTrace( traceDatabase, wxT( "loadSymbolFromRow: field %s not found in result" ),
607 mapping.column );
608 continue;
609 }
610
611 std::string strValue;
612
613 try
614 {
615 strValue = std::any_cast<std::string>( aRow.at( mapping.column ) );
616 }
617 catch( std::bad_any_cast& )
618 {
619 }
620
621 wxString value( strValue.c_str(), wxConvUTF8 );
622
623 if( mapping.name_wx == c_valueFieldName )
624 {
625 SCH_FIELD& field = symbol->GetValueField();
626 field.SetText( value );
627
628 if( !mapping.inherit_properties )
629 {
630 field.SetVisible( mapping.visible_on_add );
631 field.SetNameShown( mapping.show_name );
632 }
633 continue;
634 }
635 else if( mapping.name_wx == c_datasheetFieldName )
636 {
637 SCH_FIELD& field = symbol->GetDatasheetField();
638 field.SetText( value );
639
640 if( !mapping.inherit_properties )
641 {
642 field.SetVisible( mapping.visible_on_add );
643 field.SetNameShown( mapping.show_name );
644
645 if( mapping.visible_on_add )
646 field.SetAutoAdded( true );
647 }
648
649 continue;
650 }
651
652 SCH_FIELD* field;
653 bool isNew = false;
654
655 if( fieldsMap.count( mapping.name_wx ) )
656 {
657 field = fieldsMap[mapping.name_wx];
658 }
659 else
660 {
661 field = new SCH_FIELD( nullptr, FIELD_T::USER );
662 field->SetName( mapping.name_wx );
663 isNew = true;
664 fieldsMap[mapping.name_wx] = field;
665 }
666
667 if( !mapping.inherit_properties || isNew )
668 {
669 field->SetVisible( mapping.visible_on_add );
670 field->SetAutoAdded( true );
671 field->SetNameShown( mapping.show_name );
672 }
673
674 field->SetText( value );
675
676 if( isNew )
677 symbol->AddDrawItem( field, false );
678
679 m_customFields.insert( mapping.name_wx );
680
681 if( mapping.visible_in_chooser )
682 m_defaultShownFields.insert( mapping.name_wx );
683 }
684
685 symbol->GetDrawItems().sort();
686
687 return symbol;
688}
689
690
692{
693 return new DIALOG_DATABASE_LIB_SETTINGS( aParent, this );
694}
const char * name
std::map< std::string, std::any > ROW
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition dialog_shim.h:68
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:397
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition lib_id.cpp:52
bool IsValid() const
Check if this LID_ID is valid.
Definition lib_id.h:172
void SetSubLibraryName(const UTF8 &aName)
Definition lib_id.h:131
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
Definition lib_id.cpp:192
Define a library symbol object.
Definition lib_symbol.h:85
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.
Definition lib_symbol.h:100
void SetAutoAdded(bool aAutoAdded)
Definition sch_field.h:220
void SetName(const wxString &aName)
void SetText(const wxString &aText) override
void SetNameShown(bool aShown=true)
Definition sch_field.h:202
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
std::map< wxString, std::pair< std::string, std::string > > m_sanitizedNameMap
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)
SYMBOL_LIBRARY_ADAPTER * m_adapter
long long m_cacheTimestamp
DIALOG_SHIM * CreateConfigurationDialog(wxWindow *aParent) override
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...
SCH_IO(const wxString &aName)
Definition sch_io.h:375
static const char * PropPowerSymsOnly
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition utf8.h:72
const char * c_str() const
Definition utf8.h:109
const char *const traceDatabase
#define _(s)
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
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
@ USER
The field ID hasn't been set yet; field is invalid.
wxString result
Test unit parsing edge cases and error handling.