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 <design_block_info.h>
28#include <lib_id.h>
29#include <lib_table_lexer.h>
30#include <paths.h>
31#include <pgm_base.h>
32#include <search_stack.h>
35#include <systemdirsappend.h>
37#include <design_block.h>
38
39#include <wx/dir.h>
40#include <wx/hash.h>
41
42#define OPT_SEP '|'
43
48
53
54
55using namespace LIB_TABLE_T;
56
57
58static const wxChar global_tbl_name[] = wxT( "design-block-lib-table" );
59
60
62{
63 return LIB_TABLE_ROW::operator==( aRow ) && type == aRow.type;
64}
65
66
67void DESIGN_BLOCK_LIB_TABLE_ROW::SetType( const wxString& aType )
68{
70
73
74 plugin.reset();
75}
76
77
79 LIB_TABLE( aFallBackTable )
80{
81 // not copying fall back, simply search aFallBackTable separately
82 // if "nickName not found".
83}
84
85
86void DESIGN_BLOCK_LIB_TABLE::Parse( LIB_TABLE_LEXER* in )
87{
88 T tok;
89 wxString errMsg; // to collect error messages
90
91 // This table may be nested within a larger s-expression, or not.
92 // Allow for parser of that optional containing s-epression to have looked ahead.
93 if( in->CurTok() != T_design_block_lib_table )
94 {
95 in->NeedLEFT();
96
97 if( ( tok = in->NextTok() ) != T_design_block_lib_table )
98 in->Expecting( T_design_block_lib_table );
99 }
100
101 while( ( tok = in->NextTok() ) != T_RIGHT )
102 {
103 std::unique_ptr<DESIGN_BLOCK_LIB_TABLE_ROW> row =
104 std::make_unique<DESIGN_BLOCK_LIB_TABLE_ROW>();
105
106 if( tok == T_EOF )
107 in->Expecting( T_RIGHT );
108
109 if( tok != T_LEFT )
110 in->Expecting( T_LEFT );
111
112 // in case there is a "row integrity" error, tell where later.
113 int lineNum = in->CurLineNumber();
114 tok = in->NextTok();
115
116 // Optionally parse the current version number
117 if( tok == T_version )
118 {
119 in->NeedNUMBER( "version" );
120 m_version = std::stoi( in->CurText() );
121 in->NeedRIGHT();
122 continue;
123 }
124
125 if( tok != T_lib )
126 in->Expecting( T_lib );
127
128 // (name NICKNAME)
129 in->NeedLEFT();
130
131 if( ( tok = in->NextTok() ) != T_name )
132 in->Expecting( T_name );
133
134 in->NeedSYMBOLorNUMBER();
135
136 row->SetNickName( in->FromUTF8() );
137
138 in->NeedRIGHT();
139
140 // After (name), remaining (lib) elements are order independent, and in
141 // some cases optional.
142 bool sawType = false;
143 bool sawOpts = false;
144 bool sawDesc = false;
145 bool sawUri = false;
146 bool sawDisabled = false;
147
148 while( ( tok = in->NextTok() ) != T_RIGHT )
149 {
150 if( tok == T_EOF )
151 in->Unexpected( T_EOF );
152
153 if( tok != T_LEFT )
154 in->Expecting( T_LEFT );
155
156 tok = in->NeedSYMBOLorNUMBER();
157
158 switch( tok )
159 {
160 case T_uri:
161 if( sawUri )
162 in->Duplicate( tok );
163 sawUri = true;
164 in->NeedSYMBOLorNUMBER();
165 row->SetFullURI( in->FromUTF8() );
166 break;
167
168 case T_type:
169 if( sawType )
170 in->Duplicate( tok );
171 sawType = true;
172 in->NeedSYMBOLorNUMBER();
173 row->SetType( in->FromUTF8() );
174 break;
175
176 case T_options:
177 if( sawOpts )
178 in->Duplicate( tok );
179 sawOpts = true;
180 in->NeedSYMBOLorNUMBER();
181 row->SetOptions( in->FromUTF8() );
182 break;
183
184 case T_descr:
185 if( sawDesc )
186 in->Duplicate( tok );
187 sawDesc = true;
188 in->NeedSYMBOLorNUMBER();
189 row->SetDescr( in->FromUTF8() );
190 break;
191
192 case T_disabled:
193 if( sawDisabled )
194 in->Duplicate( tok );
195 sawDisabled = true;
196 row->SetEnabled( false );
197 break;
198
199 case T_hidden:
200 // Hiding design block libraries is not yet supported. Unclear what path can set this
201 // attribute, but clear it on load.
202 row->SetVisible();
203 break;
204
205 default: in->Unexpected( tok );
206 }
207
208 in->NeedRIGHT();
209 }
210
211 if( !sawType )
212 in->Expecting( T_type );
213
214 if( !sawUri )
215 in->Expecting( T_uri );
216
217 // All nickNames within this table fragment must be unique, so we do not use doReplace
218 // in doInsertRow(). (However a fallBack table can have a conflicting nickName and ours
219 // will supercede that one since in FindLib() we search this table before any fall back.)
220 wxString nickname = row->GetNickName(); // store it to be able to used it
221 // after row deletion if an error occurs
222 bool doReplace = false;
223 LIB_TABLE_ROW* tmp = row.release();
224
225 if( !doInsertRow( tmp, doReplace ) )
226 {
227 delete tmp; // The table did not take ownership of the row.
228
229 wxString msg = wxString::Format( _( "Duplicate library nickname '%s' found in "
230 "design block library table file line %d." ),
231 nickname, lineNum );
232
233 if( !errMsg.IsEmpty() )
234 errMsg << '\n';
235
236 errMsg << msg;
237 }
238 }
239
240 if( !errMsg.IsEmpty() )
241 THROW_IO_ERROR( errMsg );
242}
243
244
245bool DESIGN_BLOCK_LIB_TABLE::operator==( const DESIGN_BLOCK_LIB_TABLE& aDesignBlockTable ) const
246{
247 if( m_rows.size() == aDesignBlockTable.m_rows.size() )
248 {
249 for( unsigned i = 0; i < m_rows.size(); ++i )
250 {
252 != (DESIGN_BLOCK_LIB_TABLE_ROW&) aDesignBlockTable.m_rows[i] )
253 return false;
254 }
255
256 return true;
257 }
258
259 return false;
260}
261
262
263void DESIGN_BLOCK_LIB_TABLE::Format( OUTPUTFORMATTER* aOutput, int aIndentLevel ) const
264{
265 aOutput->Print( aIndentLevel, "(design_block_lib_table\n" );
266 aOutput->Print( aIndentLevel + 1, "(version %d)\n", m_version );
267
268 for( LIB_TABLE_ROWS_CITER it = m_rows.begin(); it != m_rows.end(); ++it )
269 it->Format( aOutput, aIndentLevel + 1 );
270
271 aOutput->Print( aIndentLevel, ")\n" );
272}
273
274
275long long DESIGN_BLOCK_LIB_TABLE::GenerateTimestamp( const wxString* aNickname )
276{
277 long long hash = 0;
278
279 if( aNickname )
280 {
281 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( *aNickname, true );
282
283 wxCHECK( row && row->plugin, hash );
284
285 return row->plugin->GetLibraryTimestamp( row->GetFullURI( true ) )
286 + wxHashTable::MakeKey( *aNickname );
287 }
288
289 for( const wxString& nickname : GetLogicalLibs() )
290 {
291 const DESIGN_BLOCK_LIB_TABLE_ROW* row = nullptr;
292
293 try
294 {
295 row = FindRow( nickname, true );
296 }
297 catch( ... )
298 {
299 // Do nothing if not found: just skip.
300 }
301
302 wxCHECK2( row && row->plugin, continue );
303
304 hash += row->plugin->GetLibraryTimestamp( row->GetFullURI( true ) )
305 + wxHashTable::MakeKey( nickname );
306 }
307
308 return hash;
309}
310
311
312void DESIGN_BLOCK_LIB_TABLE::DesignBlockEnumerate( wxArrayString& aDesignBlockNames,
313 const wxString& aNickname, bool aBestEfforts )
314{
315 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
316 wxASSERT( row->plugin );
317 row->plugin->DesignBlockEnumerate( aDesignBlockNames, row->GetFullURI( true ), aBestEfforts,
318 row->GetProperties() );
319}
320
321
322void DESIGN_BLOCK_LIB_TABLE::PrefetchLib( const wxString& aNickname )
323{
324 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
325 wxASSERT( row->plugin );
326 row->plugin->PrefetchLib( row->GetFullURI( true ), row->GetProperties() );
327}
328
329
331 bool aCheckIfEnabled )
332{
334 static_cast<DESIGN_BLOCK_LIB_TABLE_ROW*>( findRow( aNickname, aCheckIfEnabled ) );
335
336 if( !row )
337 {
338 wxString msg = wxString::Format(
339 _( "design-block-lib-table files contain no library named '%s'." ), aNickname );
340 THROW_IO_ERROR( msg );
341 }
342
343 if( !row->plugin )
345
346 return row;
347}
348
349
350static void setLibNickname( DESIGN_BLOCK* aModule, const wxString& aNickname,
351 const wxString& aDesignBlockName )
352{
353 // The library cannot know its own name, because it might have been renamed or moved.
354 // Therefore design blocks cannot know their own library nickname when residing in
355 // a design block library.
356 // Only at this API layer can we tell the design block about its actual library nickname.
357 if( aModule )
358 {
359 // remove "const"-ness, I really do want to set nickname without
360 // having to copy the LIB_ID and its two strings, twice each.
361 LIB_ID& dbid = (LIB_ID&) aModule->GetLibId();
362
363 // Catch any misbehaving plugin, which should be setting internal design block name properly:
364 wxASSERT( aDesignBlockName == dbid.GetLibItemName().wx_str() );
365
366 // and clearing nickname
367 wxASSERT( !dbid.GetLibNickname().size() );
368
369 dbid.SetLibNickname( aNickname );
370 }
371}
372
373
374const DESIGN_BLOCK*
376 const wxString& aDesignBlockName )
377{
378 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
379 wxASSERT( row->plugin );
380
381 return row->plugin->GetEnumeratedDesignBlock( row->GetFullURI( true ), aDesignBlockName,
382 row->GetProperties() );
383}
384
385
386bool DESIGN_BLOCK_LIB_TABLE::DesignBlockExists( const wxString& aNickname,
387 const wxString& aDesignBlockName )
388{
389 try
390 {
391 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
392 wxASSERT( row->plugin );
393
394 return row->plugin->DesignBlockExists( row->GetFullURI( true ), aDesignBlockName,
395 row->GetProperties() );
396 }
397 catch( ... )
398 {
399 return false;
400 }
401}
402
403
405 const wxString& aDesignBlockName,
406 bool aKeepUUID )
407{
408 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
409 wxASSERT( row->plugin );
410
411 DESIGN_BLOCK* ret = row->plugin->DesignBlockLoad( row->GetFullURI( true ), aDesignBlockName,
412 aKeepUUID, row->GetProperties() );
413
414 setLibNickname( ret, row->GetNickName(), aDesignBlockName );
415
416 return ret;
417}
418
419
422 const DESIGN_BLOCK* aDesignBlock, bool aOverwrite )
423{
424 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
425 wxASSERT( row->plugin );
426
427 if( !aOverwrite )
428 {
429 // Try loading the design block to see if it already exists, caller wants overwrite
430 // protection, which is atypical, not the default.
431
432 wxString DesignBlockname = aDesignBlock->GetLibId().GetLibItemName();
433
434 std::unique_ptr<DESIGN_BLOCK> design_block( row->plugin->DesignBlockLoad(
435 row->GetFullURI( true ), DesignBlockname, row->GetProperties() ) );
436
437 if( design_block.get() )
438 return SAVE_SKIPPED;
439 }
440
441 row->plugin->DesignBlockSave( row->GetFullURI( true ), aDesignBlock, row->GetProperties() );
442
443 return SAVE_OK;
444}
445
446
447void DESIGN_BLOCK_LIB_TABLE::DesignBlockDelete( const wxString& aNickname,
448 const wxString& aDesignBlockName )
449
450{
451 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
452 wxASSERT( row->plugin );
453 return row->plugin->DesignBlockDelete( row->GetFullURI( true ), aDesignBlockName,
454 row->GetProperties() );
455}
456
457
459{
460 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
461 wxASSERT( row->plugin );
462 return row->plugin->IsLibraryWritable( row->GetFullURI( true ) );
463}
464
465
466void DESIGN_BLOCK_LIB_TABLE::DesignBlockLibDelete( const wxString& aNickname )
467{
468 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
469 wxASSERT( row->plugin );
470 row->plugin->DeleteLibrary( row->GetFullURI( true ), row->GetProperties() );
471}
472
473
474void DESIGN_BLOCK_LIB_TABLE::DesignBlockLibCreate( const wxString& aNickname )
475{
476 const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
477 wxASSERT( row->plugin );
478 row->plugin->CreateLibrary( row->GetFullURI( true ), row->GetProperties() );
479}
480
481
484 bool aKeepUUID )
485{
486 wxString nickname = aDesignBlockId.GetLibNickname();
487 wxString DesignBlockname = aDesignBlockId.GetLibItemName();
488
489 if( nickname.size() )
490 {
491 return DesignBlockLoad( nickname, DesignBlockname, aKeepUUID );
492 }
493
494 // nickname is empty, sequentially search (alphabetically) all libs/nicks for first match:
495 else
496 {
497 std::vector<wxString> nicks = GetLogicalLibs();
498
499 // Search each library going through libraries alphabetically.
500 for( unsigned i = 0; i < nicks.size(); ++i )
501 {
502 // DesignBlockLoad() returns NULL on not found, does not throw exception
503 // unless there's an IO_ERROR.
504 DESIGN_BLOCK* ret = DesignBlockLoad( nicks[i], DesignBlockname, aKeepUUID );
505
506 if( ret )
507 return ret;
508 }
509
510 return nullptr;
511 }
512}
513
514
516{
517 return ENV_VAR::GetVersionedEnvVarName( wxS( "DESIGN_BLOCK_DIR" ) );
518}
519
520
521class PCM_DESIGN_BLOCK_LIB_TRAVERSER final : public wxDirTraverser
522{
523public:
524 explicit PCM_DESIGN_BLOCK_LIB_TRAVERSER( const wxString& aPath, DESIGN_BLOCK_LIB_TABLE& aTable,
525 const wxString& aPrefix ) :
526 m_lib_table( aTable ),
527 m_path_prefix( aPath ), m_lib_prefix( aPrefix )
528 {
529 wxFileName f( aPath, wxS( "" ) );
530 m_prefix_dir_count = f.GetDirCount();
531 }
532
533 wxDirTraverseResult OnFile( const wxString& aFilePath ) override { return wxDIR_CONTINUE; }
534
535 wxDirTraverseResult OnDir( const wxString& dirPath ) override
536 {
537 wxFileName dir = wxFileName::DirName( dirPath );
538
539 // consider a directory to be a lib if it's name ends with .pretty and
540 // it is under $KICADn_3RD_PARTY/design_blocks/<pkgid>/ i.e. has nested level of at least +3
541 if( dirPath.EndsWith( wxS( ".pretty" ) ) && dir.GetDirCount() >= m_prefix_dir_count + 3 )
542 {
543 wxString versionedPath = wxString::Format(
544 wxS( "${%s}" ), ENV_VAR::GetVersionedEnvVarName( wxS( "3RD_PARTY" ) ) );
545
546 wxArrayString parts = dir.GetDirs();
547 parts.RemoveAt( 0, m_prefix_dir_count );
548 parts.Insert( versionedPath, 0 );
549
550 wxString libPath = wxJoin( parts, '/' );
551
552 if( !m_lib_table.HasLibraryWithPath( libPath ) )
553 {
554 wxString name = parts.Last().substr( 0, parts.Last().length() - 7 );
555 wxString nickname = wxString::Format( wxS( "%s%s" ), m_lib_prefix, name );
556
557 if( m_lib_table.HasLibrary( nickname ) )
558 {
559 int increment = 1;
560 do
561 {
562 nickname =
563 wxString::Format( wxS( "%s%s_%d" ), m_lib_prefix, name, increment );
564 increment++;
565 } while( m_lib_table.HasLibrary( nickname ) );
566 }
567
569 nickname, libPath, wxT( "KiCad" ), wxEmptyString,
570 _( "Added by Plugin and Content Manager" ) ) );
571 }
572 }
573
574 return wxDIR_CONTINUE;
575 }
576
577private:
580 wxString m_lib_prefix;
582};
583
584
586{
587 bool tableExists = true;
588 wxFileName fn = GetGlobalTableFileName();
589
590 if( !fn.FileExists() )
591 {
592 tableExists = false;
593
594 if( !fn.DirExists() && !fn.Mkdir( 0x777, wxPATH_MKDIR_FULL ) )
595 {
596 THROW_IO_ERROR( wxString::Format( _( "Cannot create global library table path '%s'." ),
597 fn.GetPath() ) );
598 }
599
600 // Attempt to copy the default global file table from the KiCad
601 // template folder to the user's home configuration path.
602 SEARCH_STACK ss;
603
604 SystemDirsAppend( &ss );
605
606 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
607 std::optional<wxString> v =
608 ENV_VAR::GetVersionedEnvVarValue( envVars, wxT( "TEMPLATE_DIR" ) );
609
610 if( v && !v->IsEmpty() )
611 ss.AddPaths( *v, 0 );
612
613 wxString fileName = ss.FindValidPath( global_tbl_name );
614
615 // The fallback is to create an empty global design block table for the user to populate.
616 if( fileName.IsEmpty() || !::wxCopyFile( fileName, fn.GetFullPath(), false ) )
617 {
618 DESIGN_BLOCK_LIB_TABLE emptyTable;
619
620 emptyTable.Save( fn.GetFullPath() );
621 }
622 }
623
624 aTable.clear();
625 aTable.Load( fn.GetFullPath() );
626
629
630 const ENV_VAR_MAP& env = Pgm().GetLocalEnvVariables();
631 wxString packagesPath;
632
633 if( std::optional<wxString> v = ENV_VAR::GetVersionedEnvVarValue( env, wxT( "3RD_PARTY" ) ) )
634 packagesPath = *v;
635
636 if( settings->m_PcmLibAutoAdd )
637 {
638 // Scan for libraries in PCM packages directory
639
640 wxFileName d( packagesPath, wxS( "" ) );
641 d.AppendDir( wxS( "design_blocks" ) );
642
643 if( d.DirExists() )
644 {
645 PCM_DESIGN_BLOCK_LIB_TRAVERSER traverser( packagesPath, aTable,
646 settings->m_PcmLibPrefix );
647 wxDir dir( d.GetPath() );
648
649 dir.Traverse( traverser );
650 }
651 }
652
653 if( settings->m_PcmLibAutoRemove )
654 {
655 // Remove PCM libraries that no longer exist
656 std::vector<wxString> to_remove;
657
658 for( size_t i = 0; i < aTable.GetCount(); i++ )
659 {
660 LIB_TABLE_ROW& row = aTable.At( i );
661 wxString path = row.GetFullURI( true );
662
663 if( path.StartsWith( packagesPath ) && !wxDir::Exists( path ) )
664 to_remove.push_back( row.GetNickName() );
665 }
666
667 for( const wxString& nickName : to_remove )
668 aTable.RemoveRow( aTable.FindRow( nickName ) );
669 }
670
671 return tableExists;
672}
673
674
676{
677 return GDesignBlockTable;
678}
679
680
682{
683 return GDesignBlockList;
684}
685
686
688{
689 wxFileName fn;
690
691 fn.SetPath( PATHS::GetUserSettingsPath() );
692 fn.SetName( global_tbl_name );
693
694 return fn.GetFullPath();
695}
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.
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.