KiCad PCB EDA Suite
Loading...
Searching...
No Matches
design_block_lib_table.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) 2012-2024 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24
25#include <kiface_base.h>
26#include <env_vars.h>
27#include <lib_id.h>
28#include <lib_table_lexer.h>
29#include <paths.h>
30#include <pgm_base.h>
31#include <search_stack.h>
34#include <systemdirsappend.h>
36#include <design_block_info.h>
38#include <design_block.h>
39
40#include <wx/dir.h>
41#include <wx/hash.h>
42
43#define OPT_SEP '|'
44
49
54
55
56using namespace LIB_TABLE_T;
57
58
59static const wxChar global_tbl_name[] = wxT( "design-block-lib-table" );
60
61
63{
64 return LIB_TABLE_ROW::operator==( aRow ) && type == aRow.type;
65}
66
67
68void DESIGN_BLOCK_LIB_TABLE_ROW::SetType( const wxString& aType )
69{
71
74
75 plugin.reset();
76}
77
78
80 LIB_TABLE( aFallBackTable )
81{
82 // not copying fall back, simply search aFallBackTable separately
83 // if "nickName not found".
84}
85
86
87void DESIGN_BLOCK_LIB_TABLE::Parse( LIB_TABLE_LEXER* in )
88{
89 T tok;
90 wxString errMsg; // to collect error messages
91
92 // This table may be nested within a larger s-expression, or not.
93 // Allow for parser of that optional containing s-epression to have looked ahead.
94 if( in->CurTok() != T_design_block_lib_table )
95 {
96 in->NeedLEFT();
97
98 if( ( tok = in->NextTok() ) != T_design_block_lib_table )
99 in->Expecting( T_design_block_lib_table );
100 }
101
102 while( ( tok = in->NextTok() ) != T_RIGHT )
103 {
104 std::unique_ptr<DESIGN_BLOCK_LIB_TABLE_ROW> row =
105 std::make_unique<DESIGN_BLOCK_LIB_TABLE_ROW>();
106
107 if( tok == T_EOF )
108 in->Expecting( T_RIGHT );
109
110 if( tok != T_LEFT )
111 in->Expecting( T_LEFT );
112
113 // in case there is a "row integrity" error, tell where later.
114 int lineNum = in->CurLineNumber();
115 tok = in->NextTok();
116
117 // Optionally parse the current version number
118 if( tok == T_version )
119 {
120 in->NeedNUMBER( "version" );
121 m_version = std::stoi( in->CurText() );
122 in->NeedRIGHT();
123 continue;
124 }
125
126 if( tok != T_lib )
127 in->Expecting( T_lib );
128
129 // (name NICKNAME)
130 in->NeedLEFT();
131
132 if( ( tok = in->NextTok() ) != T_name )
133 in->Expecting( T_name );
134
135 in->NeedSYMBOLorNUMBER();
136
137 row->SetNickName( in->FromUTF8() );
138
139 in->NeedRIGHT();
140
141 // After (name), remaining (lib) elements are order independent, and in
142 // some cases optional.
143 bool sawType = false;
144 bool sawOpts = false;
145 bool sawDesc = false;
146 bool sawUri = false;
147 bool sawDisabled = false;
148
149 while( ( tok = in->NextTok() ) != T_RIGHT )
150 {
151 if( tok == T_EOF )
152 in->Unexpected( T_EOF );
153
154 if( tok != T_LEFT )
155 in->Expecting( T_LEFT );
156
157 tok = in->NeedSYMBOLorNUMBER();
158
159 switch( tok )
160 {
161 case T_uri:
162 if( sawUri )
163 in->Duplicate( tok );
164 sawUri = true;
165 in->NeedSYMBOLorNUMBER();
166 row->SetFullURI( in->FromUTF8() );
167 break;
168
169 case T_type:
170 if( sawType )
171 in->Duplicate( tok );
172 sawType = true;
173 in->NeedSYMBOLorNUMBER();
174 row->SetType( in->FromUTF8() );
175 break;
176
177 case T_options:
178 if( sawOpts )
179 in->Duplicate( tok );
180 sawOpts = true;
181 in->NeedSYMBOLorNUMBER();
182 row->SetOptions( in->FromUTF8() );
183 break;
184
185 case T_descr:
186 if( sawDesc )
187 in->Duplicate( tok );
188 sawDesc = true;
189 in->NeedSYMBOLorNUMBER();
190 row->SetDescr( in->FromUTF8() );
191 break;
192
193 case T_disabled:
194 if( sawDisabled )
195 in->Duplicate( tok );
196 sawDisabled = true;
197 row->SetEnabled( false );
198 break;
199
200 case T_hidden:
201 // Hiding design block libraries is not yet supported. Unclear what path can set this
202 // attribute, but clear it on load.
203 row->SetVisible();
204 break;
205
206 default: in->Unexpected( tok );
207 }
208
209 in->NeedRIGHT();
210 }
211
212 if( !sawType )
213 in->Expecting( T_type );
214
215 if( !sawUri )
216 in->Expecting( T_uri );
217
218 // All nickNames within this table fragment must be unique, so we do not use doReplace
219 // in doInsertRow(). (However a fallBack table can have a conflicting nickName and ours
220 // will supercede that one since in FindLib() we search this table before any fall back.)
221 wxString nickname = row->GetNickName(); // store it to be able to used it
222 // after row deletion if an error occurs
223 bool doReplace = false;
224 LIB_TABLE_ROW* tmp = row.release();
225
226 if( !doInsertRow( tmp, doReplace ) )
227 {
228 delete tmp; // The table did not take ownership of the row.
229
230 wxString msg = wxString::Format( _( "Duplicate library nickname '%s' found in "
231 "design block library table file line %d." ),
232 nickname, lineNum );
233
234 if( !errMsg.IsEmpty() )
235 errMsg << '\n';
236
237 errMsg << msg;
238 }
239 }
240
241 if( !errMsg.IsEmpty() )
242 THROW_IO_ERROR( errMsg );
243}
244
245
246bool DESIGN_BLOCK_LIB_TABLE::operator==( const DESIGN_BLOCK_LIB_TABLE& aDesignBlockTable ) const
247{
248 if( m_rows.size() == aDesignBlockTable.m_rows.size() )
249 {
250 for( unsigned i = 0; i < m_rows.size(); ++i )
251 {
253 != (DESIGN_BLOCK_LIB_TABLE_ROW&) aDesignBlockTable.m_rows[i] )
254 return false;
255 }
256
257 return true;
258 }
259
260 return false;
261}
262
263
264void DESIGN_BLOCK_LIB_TABLE::Format( OUTPUTFORMATTER* aOutput, int aIndentLevel ) const
265{
266 aOutput->Print( aIndentLevel, "(design_block_lib_table\n" );
267 aOutput->Print( aIndentLevel + 1, "(version %d)\n", m_version );
268
269 for( LIB_TABLE_ROWS_CITER it = m_rows.begin(); it != m_rows.end(); ++it )
270 it->Format( aOutput, aIndentLevel + 1 );
271
272 aOutput->Print( aIndentLevel, ")\n" );
273}
274
275
276long long DESIGN_BLOCK_LIB_TABLE::GenerateTimestamp( const wxString* aNickname )
277{
278 long long hash = 0;
279
280 if( aNickname )
281 {
282 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( *aNickname, true );
283
284 wxCHECK( row && row->plugin, hash );
285
286 return row->plugin->GetLibraryTimestamp( row->GetFullURI( true ) )
287 + wxHashTable::MakeKey( *aNickname );
288 }
289
290 for( const wxString& nickname : GetLogicalLibs() )
291 {
292 const DESIGN_BLOCK_LIB_TABLE_ROW* row = nullptr;
293
294 try
295 {
296 row = FindRow( nickname, true );
297 }
298 catch( ... )
299 {
300 // Do nothing if not found: just skip.
301 }
302
303 wxCHECK2( row && row->plugin, continue );
304
305 hash += row->plugin->GetLibraryTimestamp( row->GetFullURI( true ) )
306 + wxHashTable::MakeKey( nickname );
307 }
308
309 return hash;
310}
311
312
313void DESIGN_BLOCK_LIB_TABLE::DesignBlockEnumerate( wxArrayString& aDesignBlockNames,
314 const wxString& aNickname, bool aBestEfforts )
315{
316 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
317 wxASSERT( row->plugin );
318 row->plugin->DesignBlockEnumerate( aDesignBlockNames, row->GetFullURI( true ), aBestEfforts,
319 row->GetProperties() );
320}
321
322
323void DESIGN_BLOCK_LIB_TABLE::PrefetchLib( const wxString& aNickname )
324{
325 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
326 wxASSERT( row->plugin );
327 row->plugin->PrefetchLib( row->GetFullURI( true ), row->GetProperties() );
328}
329
330
332 bool aCheckIfEnabled )
333{
335 static_cast<DESIGN_BLOCK_LIB_TABLE_ROW*>( findRow( aNickname, aCheckIfEnabled ) );
336
337 if( !row )
338 {
339 wxString msg = wxString::Format(
340 _( "design-block-lib-table files contain no library named '%s'." ), aNickname );
341 THROW_IO_ERROR( msg );
342 }
343
344 if( !row->plugin )
346
347 return row;
348}
349
350
351static void setLibNickname( DESIGN_BLOCK* aModule, const wxString& aNickname,
352 const wxString& aDesignBlockName )
353{
354 // The library cannot know its own name, because it might have been renamed or moved.
355 // Therefore design blocks cannot know their own library nickname when residing in
356 // a design block library.
357 // Only at this API layer can we tell the design block about its actual library nickname.
358 if( aModule )
359 {
360 // remove "const"-ness, I really do want to set nickname without
361 // having to copy the LIB_ID and its two strings, twice each.
362 LIB_ID& dbid = (LIB_ID&) aModule->GetLibId();
363
364 // Catch any misbehaving plugin, which should be setting internal design block name properly:
365 wxASSERT( aDesignBlockName == dbid.GetLibItemName().wx_str() );
366
367 // and clearing nickname
368 wxASSERT( !dbid.GetLibNickname().size() );
369
370 dbid.SetLibNickname( aNickname );
371 }
372}
373
374
375const DESIGN_BLOCK*
377 const wxString& aDesignBlockName )
378{
379 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
380 wxASSERT( row->plugin );
381
382 return row->plugin->GetEnumeratedDesignBlock( row->GetFullURI( true ), aDesignBlockName,
383 row->GetProperties() );
384}
385
386
387bool DESIGN_BLOCK_LIB_TABLE::DesignBlockExists( const wxString& aNickname,
388 const wxString& aDesignBlockName )
389{
390 try
391 {
392 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
393 wxASSERT( row->plugin );
394
395 return row->plugin->DesignBlockExists( row->GetFullURI( true ), aDesignBlockName,
396 row->GetProperties() );
397 }
398 catch( ... )
399 {
400 return false;
401 }
402}
403
404
406 const wxString& aDesignBlockName,
407 bool aKeepUUID )
408{
409 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
410 wxASSERT( row->plugin );
411
412 DESIGN_BLOCK* ret = row->plugin->DesignBlockLoad( row->GetFullURI( true ), aDesignBlockName,
413 aKeepUUID, row->GetProperties() );
414
415 setLibNickname( ret, row->GetNickName(), aDesignBlockName );
416
417 return ret;
418}
419
420
423 const DESIGN_BLOCK* aDesignBlock, bool aOverwrite )
424{
425 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
426 wxASSERT( row->plugin );
427
428 if( !aOverwrite )
429 {
430 // Try loading the design block to see if it already exists, caller wants overwrite
431 // protection, which is atypical, not the default.
432
433 wxString DesignBlockname = aDesignBlock->GetLibId().GetLibItemName();
434
435 std::unique_ptr<DESIGN_BLOCK> design_block( row->plugin->DesignBlockLoad(
436 row->GetFullURI( true ), DesignBlockname, row->GetProperties() ) );
437
438 if( design_block.get() )
439 return SAVE_SKIPPED;
440 }
441
442 row->plugin->DesignBlockSave( row->GetFullURI( true ), aDesignBlock, row->GetProperties() );
443
444 return SAVE_OK;
445}
446
447
448void DESIGN_BLOCK_LIB_TABLE::DesignBlockDelete( const wxString& aNickname,
449 const wxString& aDesignBlockName )
450
451{
452 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
453 wxASSERT( row->plugin );
454 return row->plugin->DesignBlockDelete( row->GetFullURI( true ), aDesignBlockName,
455 row->GetProperties() );
456}
457
458
460{
461 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
462 wxASSERT( row->plugin );
463 return row->plugin->IsLibraryWritable( row->GetFullURI( true ) );
464}
465
466
467void DESIGN_BLOCK_LIB_TABLE::DesignBlockLibDelete( const wxString& aNickname )
468{
469 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
470 wxASSERT( row->plugin );
471 row->plugin->DeleteLibrary( row->GetFullURI( true ), row->GetProperties() );
472}
473
474
475void DESIGN_BLOCK_LIB_TABLE::DesignBlockLibCreate( const wxString& aNickname )
476{
477 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
478 wxASSERT( row->plugin );
479 row->plugin->CreateLibrary( row->GetFullURI( true ), row->GetProperties() );
480}
481
482
485 bool aKeepUUID )
486{
487 wxString nickname = aDesignBlockId.GetLibNickname();
488 wxString DesignBlockname = aDesignBlockId.GetLibItemName();
489
490 if( nickname.size() )
491 {
492 return DesignBlockLoad( nickname, DesignBlockname, aKeepUUID );
493 }
494
495 // nickname is empty, sequentially search (alphabetically) all libs/nicks for first match:
496 else
497 {
498 std::vector<wxString> nicks = GetLogicalLibs();
499
500 // Search each library going through libraries alphabetically.
501 for( unsigned i = 0; i < nicks.size(); ++i )
502 {
503 // DesignBlockLoad() returns NULL on not found, does not throw exception
504 // unless there's an IO_ERROR.
505 DESIGN_BLOCK* ret = DesignBlockLoad( nicks[i], DesignBlockname, aKeepUUID );
506
507 if( ret )
508 return ret;
509 }
510
511 return nullptr;
512 }
513}
514
515
517{
518 return ENV_VAR::GetVersionedEnvVarName( wxS( "DESIGN_BLOCK_DIR" ) );
519}
520
521
522class PCM_DESIGN_BLOCK_LIB_TRAVERSER final : public wxDirTraverser
523{
524public:
525 explicit PCM_DESIGN_BLOCK_LIB_TRAVERSER( const wxString& aPath, DESIGN_BLOCK_LIB_TABLE& aTable,
526 const wxString& aPrefix ) :
527 m_lib_table( aTable ),
528 m_path_prefix( aPath ), m_lib_prefix( aPrefix )
529 {
530 wxFileName f( aPath, wxS( "" ) );
531 m_prefix_dir_count = f.GetDirCount();
532 }
533
534 wxDirTraverseResult OnFile( const wxString& aFilePath ) override { return wxDIR_CONTINUE; }
535
536 wxDirTraverseResult OnDir( const wxString& dirPath ) override
537 {
538 wxFileName dir = wxFileName::DirName( dirPath );
539
540 // consider a directory to be a lib if it's name ends with the design block lib dir extension
541 // it is under $KICADn_3RD_PARTY/design_blocks/<pkgid>/ i.e. has nested level of at least +3
542 if( dirPath.EndsWith( wxS( "." ) + FILEEXT::KiCadDesignBlockLibPathExtension )
543 && dir.GetDirCount() >= m_prefix_dir_count + 3 )
544 {
545 wxString versionedPath = wxString::Format(
546 wxS( "${%s}" ), ENV_VAR::GetVersionedEnvVarName( wxS( "3RD_PARTY" ) ) );
547
548 wxArrayString parts = dir.GetDirs();
549 parts.RemoveAt( 0, m_prefix_dir_count );
550 parts.Insert( versionedPath, 0 );
551
552 wxString libPath = wxJoin( parts, '/' );
553
554 if( !m_lib_table.HasLibraryWithPath( libPath ) )
555 {
556 wxString name = parts.Last().substr( 0, parts.Last().length() - 7 );
557 wxString nickname = wxString::Format( wxS( "%s%s" ), m_lib_prefix, name );
558
559 if( m_lib_table.HasLibrary( nickname ) )
560 {
561 int increment = 1;
562 do
563 {
564 nickname =
565 wxString::Format( wxS( "%s%s_%d" ), m_lib_prefix, name, increment );
566 increment++;
567 } while( m_lib_table.HasLibrary( nickname ) );
568 }
569
571 nickname, libPath, wxT( "KiCad" ), wxEmptyString,
572 _( "Added by Plugin and Content Manager" ) ) );
573 }
574 }
575
576 return wxDIR_CONTINUE;
577 }
578
579private:
582 wxString m_lib_prefix;
584};
585
586
588{
589 bool tableExists = true;
590 wxFileName fn = GetGlobalTableFileName();
591
592 if( !fn.FileExists() )
593 {
594 tableExists = false;
595
596 if( !fn.DirExists() && !fn.Mkdir( 0x777, wxPATH_MKDIR_FULL ) )
597 {
598 THROW_IO_ERROR( wxString::Format( _( "Cannot create global library table path '%s'." ),
599 fn.GetPath() ) );
600 }
601
602 // Attempt to copy the default global file table from the KiCad
603 // template folder to the user's home configuration path.
604 SEARCH_STACK ss;
605
606 SystemDirsAppend( &ss );
607
608 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
609 std::optional<wxString> v =
610 ENV_VAR::GetVersionedEnvVarValue( envVars, wxT( "TEMPLATE_DIR" ) );
611
612 if( v && !v->IsEmpty() )
613 ss.AddPaths( *v, 0 );
614
615 wxString fileName = ss.FindValidPath( global_tbl_name );
616
617 // The fallback is to create an empty global design block table for the user to populate.
618 if( fileName.IsEmpty() || !::wxCopyFile( fileName, fn.GetFullPath(), false ) )
619 {
620 DESIGN_BLOCK_LIB_TABLE emptyTable;
621
622 emptyTable.Save( fn.GetFullPath() );
623 }
624 }
625
626 aTable.clear();
627 aTable.Load( fn.GetFullPath() );
628
631
632 const ENV_VAR_MAP& env = Pgm().GetLocalEnvVariables();
633 wxString packagesPath;
634
635 if( std::optional<wxString> v = ENV_VAR::GetVersionedEnvVarValue( env, wxT( "3RD_PARTY" ) ) )
636 packagesPath = *v;
637
638 if( settings->m_PcmLibAutoAdd )
639 {
640 // Scan for libraries in PCM packages directory
641
642 wxFileName d( packagesPath, wxS( "" ) );
643 d.AppendDir( wxS( "design_blocks" ) );
644
645 if( d.DirExists() )
646 {
647 PCM_DESIGN_BLOCK_LIB_TRAVERSER traverser( packagesPath, aTable,
648 settings->m_PcmLibPrefix );
649 wxDir dir( d.GetPath() );
650
651 dir.Traverse( traverser );
652 }
653 }
654
655 if( settings->m_PcmLibAutoRemove )
656 {
657 // Remove PCM libraries that no longer exist
658 std::vector<wxString> to_remove;
659
660 for( size_t i = 0; i < aTable.GetCount(); i++ )
661 {
662 LIB_TABLE_ROW& row = aTable.At( i );
663 wxString path = row.GetFullURI( true );
664
665 if( path.StartsWith( packagesPath ) && !wxDir::Exists( path ) )
666 to_remove.push_back( row.GetNickName() );
667 }
668
669 for( const wxString& nickName : to_remove )
670 aTable.RemoveRow( aTable.FindRow( nickName ) );
671 }
672
673 return tableExists;
674}
675
676
678{
679 return GDesignBlockTable;
680}
681
682
684{
685 return GDesignBlockList;
686}
687
688
690{
691 wxFileName fn;
692
693 fn.SetPath( PATHS::GetUserSettingsPath() );
694 fn.SetName( global_tbl_name );
695
696 return fn.GetFullPath();
697}
const char * name
Definition: DXF_plotter.cpp:57
@ KICAD_SEXP
S-expression KiCad file format.
static DESIGN_BLOCK_FILE_T EnumFromStr(const wxString &aFileType)
static DESIGN_BLOCK_IO * FindPlugin(DESIGN_BLOCK_FILE_T aFileType)
Hold a record identifying a library accessed by the appropriate design block library #PLUGIN object i...
void SetType(const wxString &aType) override
Change the type represented by this row.
void setPlugin(DESIGN_BLOCK_IO *aPlugin)
DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T type
IO_RELEASER< DESIGN_BLOCK_IO > plugin
bool operator==(const DESIGN_BLOCK_LIB_TABLE_ROW &aRow) const
void PrefetchLib(const wxString &aNickname)
If possible, prefetches the specified library (e.g.
void DesignBlockLibDelete(const wxString &aNickname)
bool operator==(const DESIGN_BLOCK_LIB_TABLE &aFpTable) const
long long GenerateTimestamp(const wxString *aNickname)
Generate a hashed timestamp representing the last-mod-times of the library indicated by aNickname,...
static wxString GetGlobalTableFileName()
const DESIGN_BLOCK * GetEnumeratedDesignBlock(const wxString &aNickname, const wxString &aDesignBlockName)
A version of DesignBlockLoad() for use after DesignBlockEnumerate() for more efficient cache manageme...
bool IsDesignBlockLibWritable(const wxString &aNickname)
Return true if the library given by aNickname is writable.
void DesignBlockDelete(const wxString &aNickname, const wxString &aDesignBlockName)
Delete the aDesignBlockName from the library given by aNickname.
void DesignBlockLibCreate(const wxString &aNickname)
DESIGN_BLOCK * DesignBlockLoad(const wxString &aNickname, const wxString &aDesignBlockName, bool aKeepUUID=false)
Load a design block having aDesignBlockName from the library given by aNickname.
virtual void Parse(LIB_TABLE_LEXER *aLexer) override
Parse the #LIB_TABLE_LEXER s-expression library table format into the appropriate LIB_TABLE_ROW objec...
SAVE_T
The set of return values from DesignBlockSave() below.
DESIGN_BLOCK_LIB_TABLE(DESIGN_BLOCK_LIB_TABLE *aFallBackTable=nullptr)
Build a design block library table by pre-pending this table fragment in front of aFallBackTable.
SAVE_T DesignBlockSave(const wxString &aNickname, const DESIGN_BLOCK *aDesignBlock, bool aOverwrite=true)
Write aDesignBlock to an existing library given by aNickname.
DESIGN_BLOCK * DesignBlockLoadWithOptionalNickname(const LIB_ID &aDesignBlockId, bool aKeepUUID=false)
Load a design block having aDesignBlockId with possibly an empty nickname.
bool DesignBlockExists(const wxString &aNickname, const wxString &aDesignBlockName)
Indicates whether or not the given design block already exists in the given library.
static DESIGN_BLOCK_LIST_IMPL & GetGlobalList()
static bool LoadGlobalTable(DESIGN_BLOCK_LIB_TABLE &aTable)
Load the global design block library table into aTable.
const DESIGN_BLOCK_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an DESIGN_BLOCK_LIB_TABLE_ROW if aNickName is found in this table or in any chained fall back ...
void DesignBlockEnumerate(wxArrayString &aDesignBlockNames, const wxString &aNickname, bool aBestEfforts)
Return a list of design block names contained within the library given by aNickname.
static const wxString GlobalPathEnvVariableName()
Return the name of the environment variable used to hold the directory of locally installed "KiCad sp...
static DESIGN_BLOCK_LIB_TABLE & GetGlobalLibTable()
virtual void Format(OUTPUTFORMATTER *aOutput, int aIndentLevel) const override
Generate the table in s-expression format to aOutput with an indentation level of aIndentLevel.
const LIB_ID & GetLibId() const
Definition: design_block.h:33
wxString m_PcmLibPrefix
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition: lib_id.cpp:99
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
const std::map< std::string, UTF8 > * GetProperties() const
Return the constant #PROPERTIES for this library (LIB_TABLE_ROW).
const wxString & GetNickName() const
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
bool operator==(const LIB_TABLE_ROW &r) const
Manage LIB_TABLE_ROW records (rows), and can be searched based on library nickname.
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
int m_version
Versioning to handle importing old tables.
LIB_TABLE_ROW & At(unsigned aIndex)
Get the 'n'th LIB_TABLE_ROW object.
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
LIB_TABLE_ROWS m_rows
Owning set of rows.
bool doInsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Performs the mechanics of inserting a row, but without locking or reindexing.
void Load(const wxString &aFileName)
Load the library table using the path defined by aFileName aFallBackTable.
bool HasLibraryWithPath(const wxString &aPath) const
Test for the existence of aPath in the library table.
bool RemoveRow(const LIB_TABLE_ROW *aRow)
Removes a row from the table and frees the pointer.
unsigned GetCount() const
Get the number of rows contained in the table.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
LIB_TABLE_ROW * findRow(const wxString &aNickname, bool aCheckIfEnabled=false) const
Return a LIB_TABLE_ROW if aNickname is found in this table or in any chained fallBack table fragment,...
An interface used to output 8 bit text in a convenient way.
Definition: richio.h:322
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition: richio.cpp:458
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
Definition: paths.cpp:531
PCM_DESIGN_BLOCK_LIB_TRAVERSER(const wxString &aPath, DESIGN_BLOCK_LIB_TABLE &aTable, const wxString &aPrefix)
wxDirTraverseResult OnFile(const wxString &aFilePath) override
wxDirTraverseResult OnDir(const wxString &dirPath) override
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
Definition: pgm_base.cpp:924
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:142
Look for files in a number of paths.
Definition: search_stack.h:43
void AddPaths(const wxString &aPaths, int aIndex=-1)
Insert or append path(s).
T * GetAppSettings()
Returns a handle to the a given settings by type If the settings have already been loaded,...
std::string::size_type size() const
Definition: utf8.h:111
wxString wx_str() const
Definition: utf8.cpp:45
static void setLibNickname(DESIGN_BLOCK *aModule, const wxString &aNickname, const wxString &aDesignBlockName)
static const wxChar global_tbl_name[]
DESIGN_BLOCK_LIB_TABLE GDesignBlockTable
The global design block library table.
DESIGN_BLOCK_LIST_IMPL GDesignBlockList
The global footprint info table.
#define _(s)
Functions related to environment variables, including help functions.
static const std::string KiCadDesignBlockLibPathExtension
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
LIB_TABLE_ROWS::const_iterator LIB_TABLE_ROWS_CITER
KICOMMON_API std::optional< wxString > GetVersionedEnvVarValue(const std::map< wxString, ENV_VAR_ITEM > &aMap, const wxString &aBaseName)
Attempts to retrieve the value of a versioned environment variable, such as KICAD8_TEMPLATE_DIR.
Definition: env_vars.cpp:83
KICOMMON_API wxString GetVersionedEnvVarName(const wxString &aBaseName)
Constructs a versioned environment variable based on this KiCad major version.
Definition: env_vars.cpp:74
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1060
see class PGM_BASE
void SystemDirsAppend(SEARCH_STACK *aSearchStack)
Append system places to aSearchStack in a platform specific way and pertinent to KiCad programs.
System directories search utilities.
Definition of file extensions used in Kicad.