KiCad PCB EDA Suite
Loading...
Searching...
No Matches
footprint_library_adapter.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 * @author Jon Evans <[email protected]>
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
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
22
23#include <chrono>
24#include <env_vars.h>
25#include <footprint_info_impl.h>
26#include <thread_pool.h>
27#include <trace_helpers.h>
28#include <footprint.h>
29
30#include <magic_enum.hpp>
31#include <wx/hash.h>
32#include <wx/log.h>
33
34using namespace std::chrono_literals;
35
36
38
40
42
44
46
47
52
53
58
59
61{
62 return ENV_VAR::GetVersionedEnvVarName( wxS( "FOOTPRINT_DIR" ) );
63}
64
65
66void FOOTPRINT_LIBRARY_ADAPTER::enumerateLibrary( LIB_DATA* aLib, const wxString& aUri )
67{
68 wxArrayString namesAS;
69 std::map<std::string, UTF8> options = aLib->row->GetOptionsMap();
70 PCB_IO* plugin = pcbplugin( aLib );
71 wxString nickname = aLib->row->Nickname();
72
73 long long timestamp = plugin->GetLibraryTimestamp( aUri );
74
75 // Hold across the enumerate-then-borrow sequence: GetEnumeratedFootprint returns borrowed
76 // FP_CACHE pointers, so no other thread may rebuild the cache until we finish cloning.
77 std::lock_guard pluginGuard( pluginMutex( nickname ) );
78
79 // FootprintEnumerate populates the plugin's internal FP_CACHE with parsed footprints
80 plugin->FootprintEnumerate( namesAS, aUri, false, &options );
81
82 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
83 footprints.reserve( namesAS.size() );
84
85 // For plugins with internal caches (like kicad_sexpr), GetEnumeratedFootprint returns
86 // a borrowed pointer and ClearCachedFootprints handles cleanup. For other plugins,
87 // GetEnumeratedFootprint allocates new memory that we must delete after cloning.
88 const bool pluginCaches = plugin->CachesEnumeratedFootprints();
89
90 for( const wxString& footprintName : namesAS )
91 {
92 try
93 {
94 const FOOTPRINT* cached = plugin->GetEnumeratedFootprint( aUri, footprintName, &options );
95
96 if( !cached )
97 continue;
98
99 // Preserve disk UUIDs in the cache that serves keep-UUID loads
100 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( cached->Clone() );
101 footprint->SetParent( nullptr );
102 footprint->SetParentGroup( nullptr );
103
104 // For non-caching plugins, delete the allocated footprint now that we've cloned it
105 if( !pluginCaches )
106 delete cached;
107
108 LIB_ID id = footprint->GetFPID();
109 id.SetLibNickname( nickname );
110 footprint->SetFPID( id );
111 footprints.emplace_back( footprint );
112 }
113 catch( IO_ERROR& e )
114 {
115 wxLogTrace( traceLibraries, "FP: %s:%s enumeration error: %s",
116 nickname, footprintName, e.What() );
117 }
118 }
119
120 {
121 std::unique_lock lock( PreloadedFootprintsMutex );
122 PreloadedFootprints.Get()[nickname] = std::move( footprints );
123 PreloadedTimestamps.Get()[nickname] = timestamp;
124 }
125
126 // Clear the plugin's FP_CACHE now that we've copied footprints to PreloadedFootprints.
127 // This eliminates the double-caching that was consuming ~1.2GB of extra RAM.
128 plugin->ClearCachedFootprints( aUri );
129}
130
131
132std::optional<LIB_STATUS> FOOTPRINT_LIBRARY_ADAPTER::LoadOne( LIB_DATA* aLib )
133{
135
136 try
137 {
138 enumerateLibrary( aLib, getUri( aLib->row ) );
140 }
141 catch( IO_ERROR& e )
142 {
144 aLib->status.error = LIBRARY_ERROR( e.Problem(), e.Where() );
145 wxLogTrace( traceLibraries, "FP: %s: plugin threw exception: %s", aLib->row->Nickname(), e.What() );
146 }
147
148 return aLib->status;
149}
150
151
152std::optional<LIB_STATUS> FOOTPRINT_LIBRARY_ADAPTER::LoadOne( const wxString& nickname )
153{
155
156 if( result.has_value() )
157 return LoadOne( *result );
158
159 return LIB_STATUS{
160 .load_status = LOAD_STATUS::LOAD_ERROR,
161 .error = LIBRARY_ERROR( { result.error() } )
162 };
163}
164
165
166std::vector<FOOTPRINT*> FOOTPRINT_LIBRARY_ADAPTER::GetFootprints( const wxString& aNickname, bool aBestEfforts )
167{
168 std::vector<FOOTPRINT*> footprints;
169
170 std::shared_lock lock( PreloadedFootprintsMutex );
171 auto it = PreloadedFootprints.Get().find( aNickname );
172
173 if( it == PreloadedFootprints.Get().end() )
174 return footprints;
175
176 footprints.reserve( it->second.size() );
177
178 for( const auto& fp : it->second )
179 footprints.push_back( fp.get() );
180
181 return footprints;
182}
183
184
185
186std::vector<wxString> FOOTPRINT_LIBRARY_ADAPTER::GetFootprintNames( const wxString& aNickname, bool aBestEfforts )
187{
188 // TODO(JE) can we kill wxArrayString in internal API?
189 wxArrayString namesAS;
190 std::vector<wxString> names;
191
192 if( std::optional<const LIB_DATA*> maybeLib = fetchIfLoaded( aNickname ) )
193 {
194 const LIB_DATA* lib = *maybeLib;
195 std::map<std::string, UTF8> options = lib->row->GetOptionsMap();
196
197 try
198 {
199 std::lock_guard pluginGuard( pluginMutex( aNickname ) );
200
201 pcbplugin( lib )->FootprintEnumerate( namesAS, getUri( lib->row ), aBestEfforts, &options );
202 }
203 catch( IO_ERROR& e )
204 {
205 wxLogTrace( traceLibraries, "FP: Exception enumerating library %s: %s", lib->row->Nickname(), e.What() );
206
207 if( !aBestEfforts )
208 throw;
209 }
210 }
211
212 for( const wxString& name : namesAS )
213 names.emplace_back( name );
214
215 return names;
216}
217
218
219long long FOOTPRINT_LIBRARY_ADAPTER::GenerateTimestamp( const wxString* aNickname )
220{
221 long long hash = 0;
222
223 if( aNickname )
224 {
225 wxCHECK( HasLibrary( *aNickname, true ), hash );
226
227 if( std::optional<const LIB_DATA*> r = fetchIfLoaded( *aNickname ); r.has_value() )
228 {
229 PCB_IO* plugin = dynamic_cast<PCB_IO*>( ( *r )->plugin.get() );
230 wxCHECK( plugin, hash );
231 return plugin->GetLibraryTimestamp( LIBRARY_MANAGER::GetFullURI( ( *r )->row, true ) )
232 + wxHashTable::MakeKey( *aNickname );
233 }
234 }
235
236 for( const wxString& nickname : GetLibraryNames() )
237 {
238 if( std::optional<const LIB_DATA*> r = fetchIfLoaded( nickname ); r.has_value() )
239 {
240 wxCHECK2( ( *r )->plugin->IsPCB_IO(), continue );
241 PCB_IO* plugin = static_cast<PCB_IO*>( ( *r )->plugin.get() );
242 hash += plugin->GetLibraryTimestamp( LIBRARY_MANAGER::GetFullURI( ( *r )->row, true ) )
243 + wxHashTable::MakeKey( nickname );
244 }
245 }
246
247 return hash;
248}
249
250
252{
253 std::optional<LIB_DATA*> maybeLib = fetchIfLoaded( aNickname );
254
255 if( !maybeLib )
256 return;
257
258 LIB_DATA* lib = *maybeLib;
259 PCB_IO* plugin = dynamic_cast<PCB_IO*>( lib->plugin.get() );
260
261 if( !plugin )
262 return;
263
264 wxString uri = getUri( lib->row );
265 long long currentTimestamp = plugin->GetLibraryTimestamp( uri );
266
267 {
268 std::shared_lock lock( PreloadedFootprintsMutex );
269 auto tsIt = PreloadedTimestamps.Get().find( aNickname );
270
271 if( tsIt != PreloadedTimestamps.Get().end() && tsIt->second == currentTimestamp )
272 return;
273
274 wxLogTrace( traceLibraries, "FP: %s changed on disk, re-enumerating", aNickname );
275 }
276
277 try
278 {
279 enumerateLibrary( lib, uri );
280 }
281 catch( IO_ERROR& e )
282 {
283 std::unique_lock lock( PreloadedFootprintsMutex );
284 PreloadedFootprints.Get().erase( aNickname );
285 PreloadedTimestamps.Get().erase( aNickname );
286 throw;
287 }
288}
289
290
292{
293 for( const wxString& nickname : GetLibraryNames() )
294 {
295 // An unreadable library must not stop the others, nor escape into the caller.
296 try
297 {
298 RefreshLibraryIfChanged( nickname );
299 }
300 catch( const IO_ERROR& e )
301 {
302 wxLogTrace( traceLibraries, "FP: %s: refresh failed: %s", nickname, e.What() );
303 }
304 }
305}
306
307
308bool FOOTPRINT_LIBRARY_ADAPTER::FootprintExists( const wxString& aNickname, const wxString& aName )
309{
310 if( std::optional<const LIB_DATA*> maybeLib = fetchIfLoaded( aNickname ) )
311 {
312 const LIB_DATA* lib = *maybeLib;
313 std::map<std::string, UTF8> options = lib->row->GetOptionsMap();
314
315 std::lock_guard pluginGuard( pluginMutex( aNickname ) );
316
317 return pcbplugin( lib )->FootprintExists( getUri( lib->row ), aName, &options );
318 }
319
320 return false;
321}
322
323
324FOOTPRINT* FOOTPRINT_LIBRARY_ADAPTER::LoadFootprint( const wxString& aNickname, const wxString& aName, bool aKeepUUID )
325{
326 // First check if the footprint is in PreloadedFootprints and clone from there.
327 // This avoids re-parsing the file and keeps FP_CACHE from being repopulated.
328 if( fetchIfLoaded( aNickname ) )
329 {
330 std::shared_lock lock( PreloadedFootprintsMutex );
331 auto libIt = PreloadedFootprints.Get().find( aNickname );
332
333 if( libIt != PreloadedFootprints.Get().end() )
334 {
335 for( const auto& fp : libIt->second )
336 {
337 if( fp->GetFPID().GetLibItemName() == UTF8( aName ) )
338 {
340
341 if( aKeepUUID )
342 copy = static_cast<FOOTPRINT*>( fp->Clone() );
343 else
344 copy = static_cast<FOOTPRINT*>( fp->Duplicate( IGNORE_PARENT_GROUP ) );
345
346 copy->SetParent( nullptr );
347 return copy;
348 }
349 }
350 }
351 }
352
353 // Footprint not found in PreloadedFootprints, fall back to plugin.
354 // This re-parses the file but is needed for footprints not yet enumerated.
355 if( std::optional<const LIB_DATA*> lib = fetchIfLoaded( aNickname ) )
356 {
357 try
358 {
359 std::lock_guard pluginGuard( pluginMutex( aNickname ) );
360
361 if( std::unique_ptr<FOOTPRINT> footprint =
362 pcbplugin( *lib )->FootprintLoad( getUri( ( *lib )->row ), aName, aKeepUUID ) )
363 {
364 LIB_ID id = footprint->GetFPID();
365 id.SetLibNickname( ( *lib )->row->Nickname() );
366 footprint->SetFPID( id );
367 return footprint.release();
368 }
369 }
370 catch( const IO_ERROR& ioe )
371 {
372 wxLogTrace( traceLibraries, "LoadFootprint: error loading %s:%s: %s", aNickname, aName, ioe.What() );
373 }
374 }
375 else
376 {
377 wxLogTrace( traceLibraries, "LoadFootprint: requested library %s not loaded", aNickname );
378 }
379
380 return nullptr;
381}
382
383
385{
386 wxString nickname = aFootprintId.GetLibNickname();
387 wxString footprintName = aFootprintId.GetLibItemName();
388
389 if( nickname.size() )
390 return LoadFootprint( nickname, footprintName, aKeepUUID );
391
392 // nickname is empty, sequentially search (alphabetically) all libs/nicks for first match:
393 for( const wxString& library : GetLibraryNames() )
394 {
395 // FootprintLoad() returns NULL on not found, does not throw exception
396 // unless there's an IO_ERROR.
397 if( FOOTPRINT* ret = LoadFootprint( library, footprintName, aKeepUUID ) )
398 return ret;
399 }
400
401 return nullptr;
402}
403
404
406 const FOOTPRINT* aFootprint,
407 bool aOverwrite )
408{
409 wxCHECK( aFootprint, SAVE_SKIPPED );
410
411 if( std::optional<const LIB_DATA*> lib = fetchIfLoaded( aNickname ) )
412 {
413 // Serialize the load-check / save / cache-update sequence against a concurrent rebuild.
414 std::lock_guard pluginGuard( pluginMutex( aNickname ) );
415
416 if( !aOverwrite )
417 {
418 wxString fpname = aFootprint->GetFPID().GetLibItemName();
419
420 try
421 {
422 std::unique_ptr<FOOTPRINT> existing =
423 pcbplugin( *lib )->FootprintLoad( getUri( ( *lib )->row ), fpname, false );
424
425 if( existing )
426 return SAVE_SKIPPED;
427 }
428 catch( IO_ERROR& e )
429 {
430 wxLogTrace( traceLibraries, "SaveFootprint: error checking for existing footprint %s: %s",
431 aFootprint->GetFPIDAsString(), e.What() );
432 return SAVE_SKIPPED;
433 }
434 }
435
436 try
437 {
438 pcbplugin( *lib )->FootprintSave( getUri( ( *lib )->row ), aFootprint );
439 }
440 catch( IO_ERROR& e )
441 {
442 // Re-throw rather than returning SAVE_SKIPPED; swallowing a write failure (read-only
443 // file, full disk) would report a successful save while the file is unchanged.
444 wxLogTrace( traceLibraries, "SaveFootprint: error saving %s: %s",
445 aFootprint->GetFPIDAsString(), e.What() );
446 throw;
447 }
448
449 {
450 std::unique_lock lock( PreloadedFootprintsMutex );
451 auto it = PreloadedFootprints.Get().find( aNickname );
452
453 if( it != PreloadedFootprints.Get().end() )
454 {
455 wxString fpName = aFootprint->GetFPID().GetLibItemName();
456
457 if( aOverwrite )
458 {
459 auto& footprints = it->second;
460 std::erase_if( footprints,
461 [&fpName]( const std::unique_ptr<FOOTPRINT>& fp )
462 {
463 return fp->GetFPID().GetLibItemName().wx_str() == fpName;
464 } );
465 }
466
467 // Must match what FootprintSave() just wrote, UUIDs included
468 FOOTPRINT* clone = static_cast<FOOTPRINT*>( aFootprint->Clone() );
469 clone->SetParent( nullptr );
470 clone->SetParentGroup( nullptr );
471
472 LIB_ID id = clone->GetFPID();
473 id.SetLibNickname( aNickname );
474 clone->SetFPID( id );
475
476 it->second.emplace_back( clone );
477 }
478 }
479
480 return SAVE_OK;
481 }
482 else
483 {
484 wxLogTrace( traceLibraries, "SaveFootprint: requested library %s not loaded", aNickname );
485 return SAVE_SKIPPED;
486 }
487}
488
489
490void FOOTPRINT_LIBRARY_ADAPTER::DeleteFootprint( const wxString& aNickname, const wxString& aFootprintName )
491{
492 if( std::optional<const LIB_DATA*> lib = fetchIfLoaded( aNickname ) )
493 {
494 std::lock_guard pluginGuard( pluginMutex( aNickname ) );
495
496 try
497 {
498 pcbplugin( *lib )->FootprintDelete( getUri( ( *lib )->row ), aFootprintName );
499 }
500 catch( IO_ERROR& e )
501 {
502 wxLogTrace( traceLibraries, "DeleteFootprint: error deleting %s:%s: %s", aNickname,
503 aFootprintName, e.What() );
504 throw;
505 }
506
507 {
508 std::unique_lock lock( PreloadedFootprintsMutex );
509 auto it = PreloadedFootprints.Get().find( aNickname );
510
511 if( it != PreloadedFootprints.Get().end() )
512 {
513 auto& footprints = it->second;
514 std::erase_if( footprints,
515 [&aFootprintName]( const std::unique_ptr<FOOTPRINT>& fp )
516 {
517 return fp->GetFPID().GetLibItemName().wx_str() == aFootprintName;
518 } );
519 }
520 }
521 }
522 else
523 {
524 wxLogTrace( traceLibraries, "DeleteFootprint: requested library %s not loaded", aNickname );
525 }
526}
527
528
530{
531 // Route through fetchIfLoaded() so LOAD_ERROR sentinel entries, which carry a null
532 // plugin, are filtered out instead of dereferenced.
533 if( std::optional<const LIB_DATA*> lib = fetchIfLoaded( aLib ) )
534 {
535 std::lock_guard pluginGuard( pluginMutex( aLib ) );
536
537 return ( *lib )->plugin->IsLibraryWritable( getUri( ( *lib )->row ) );
538 }
539
540 return false;
541}
542
543
545{
547
548 if( type == PCB_IO_MGR::NESTED_TABLE )
549 {
550 wxString msg;
551 wxFileName fileName( m_manager.GetFullURI( row, true ) );
552
553 if( fileName.FileExists() )
554 return tl::unexpected( LIBRARY_TABLE_OK() );
555 else
556 msg = wxString::Format( _( "Nested table '%s' not found." ), row->URI() );
557
558 return tl::unexpected( LIBRARY_ERROR( msg ) );
559 }
560 else if( type == PCB_IO_MGR::PCB_FILE_UNKNOWN )
561 {
562 wxLogTrace( traceLibraries, "FP: Plugin type %s is unknown!", row->Type() );
563 wxString msg = wxString::Format( _( "Unknown library type %s " ), row->Type() );
564 return tl::unexpected( LIBRARY_ERROR( msg ) );
565 }
566
568 wxCHECK( plugin, tl::unexpected( LIBRARY_ERROR( _( "Internal error" ) ) ) );
569
570 wxLogTrace( traceLibraries, "FP: Library %s (%s) plugin created", row->Nickname(),
571 magic_enum::enum_name( row->Scope() ) );
572
573 return plugin;
574}
575
576
578{
579 // Note: can't use dynamic_cast across compile units on Mac
580 wxCHECK( aRow->plugin->IsPCB_IO(), nullptr );
581 PCB_IO* ret = static_cast<PCB_IO*>( aRow->plugin.get() );
582 return ret;
583}
const char * name
virtual void SetParentGroup(EDA_GROUP *aGroup)
Definition eda_item.h:115
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:153
bool IsFootprintLibWritable(const wxString &aNickname)
Return true if the library given by aNickname is writable.
void DeleteFootprint(const wxString &aNickname, const wxString &aFootprintName)
Deletes the aFootprintName from the library given by aNickname.
std::vector< FOOTPRINT * > GetFootprints(const wxString &aNickname, bool aBestEfforts=false)
Retrieves a list of footprints contained in a given loaded library.
void RefreshLibraryIfChanged(const wxString &aNickname)
Checks whether the library on disk has changed since it was last enumerated into PreloadedFootprints ...
static LEAK_AT_EXIT< std::shared_mutex > GlobalLibraryMutex
void enumerateLibrary(LIB_DATA *aLib, const wxString &aUri) override
Override in derived class to perform library-specific enumeration.
IO_BASE * plugin(const LIB_DATA *aRow) override
SAVE_T SaveFootprint(const wxString &aNickname, const FOOTPRINT *aFootprint, bool aOverwrite=true)
Write aFootprint to an existing library given by aNickname.
std::vector< wxString > GetFootprintNames(const wxString &aNickname, bool aBestEfforts=false)
Retrieves a list of footprint names contained in a given loaded library.
FOOTPRINT * LoadFootprint(const wxString &aNickname, const wxString &aName, bool aKeepUUID)
Load a FOOTPRINT having aName from the library given by aNickname.
static LEAK_AT_EXIT< std::map< wxString, LIB_DATA > > GlobalLibraries
static LEAK_AT_EXIT< std::map< wxString, long long > > PreloadedTimestamps
Filesystem timestamps from when PreloadedFootprints was last populated, guarded by PreloadedFootprint...
static PCB_IO * pcbplugin(const LIB_DATA *aRow)
FOOTPRINT * LoadFootprintWithOptionalNickname(const LIB_ID &aFootprintId, bool aKeepUUID)
Load a footprint having aFootprintId with possibly an empty nickname.
LIBRARY_RESULT< IO_BASE * > createPlugin(const LIBRARY_TABLE_ROW *row) override
Creates a concrete plugin for the given row.
FOOTPRINT_LIBRARY_ADAPTER(LIBRARY_MANAGER &aManager)
long long GenerateTimestamp(const wxString *aNickname)
Generates a filesystem timestamp / hash value for library(ies)
std::optional< LIB_STATUS > LoadOne(LIB_DATA *aLib) override
Loads or reloads the given library, if it exists.
SAVE_T
The set of return values from SaveSymbol() below.
static LEAK_AT_EXIT< std::map< wxString, std::vector< std::unique_ptr< FOOTPRINT > > > > PreloadedFootprints
Storage for preloaded footprints, indexed by library nickname.
bool FootprintExists(const wxString &aNickname, const wxString &aName)
static std::shared_mutex PreloadedFootprintsMutex
void SetFPID(const LIB_ID &aFPID)
Definition footprint.h:475
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
wxString GetFPIDAsString() const
Definition footprint.h:480
const LIB_ID & GetFPID() const
Definition footprint.h:474
virtual bool IsPCB_IO() const
Work-around for lack of dynamic_cast across compile units on Mac.
Definition io_base.h:84
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
virtual const wxString Problem() const
what was the problem?
virtual const wxString Where() const
where did the Problem() occur?
A wrapper for static data that should not be destroyed at program exit.
void evictOwnedGlobalEntries()
Erases this adapter's own entries (LIB_DATA::global_owner == this) from the process-wide globalLibs()...
LIBRARY_MANAGER_ADAPTER(LIBRARY_MANAGER &aManager)
Constructs a type-specific adapter into the library manager.
wxString getUri(const LIBRARY_TABLE_ROW *aRow) const
LIBRARY_RESULT< LIB_DATA * > loadIfNeeded(const wxString &aNickname)
Fetches a loaded library, triggering a load of that library if it isn't loaded yet.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library tables.
std::vector< wxString > GetLibraryNames() const
Returns a list of library nicknames that are available (skips any that failed to load)
static std::recursive_mutex & pluginMutex(const wxString &aNickname)
Serializes access to a library's shared plugin instance so its single mutable cache is not raced by c...
LIBRARY_MANAGER & m_manager
std::optional< const LIB_DATA * > fetchIfLoaded(const wxString &aNickname) const
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false)
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
LIBRARY_TABLE_SCOPE Scope() const
std::map< std::string, UTF8 > GetOptionsMap() const
const wxString & Type() const
const wxString & URI() const
const wxString & Nickname() const
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:113
const UTF8 & GetLibItemName() const
Definition lib_id.h:98
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition lib_id.h:83
static PCB_FILE_T EnumFromStr(const wxString &aFileType)
Return the PCB_FILE_T from the corresponding plugin type name: "kicad", "legacy", etc.
PCB_FILE_T
The set of file types that the PCB_IO_MGR knows about, and for which there has been a plugin written,...
Definition pcb_io_mgr.h:52
@ PCB_FILE_UNKNOWN
0 is not a legal menu id on Mac
Definition pcb_io_mgr.h:53
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a PCB_IO which the caller can use to import, export, save, or load design documents.
A base class that BOARD loading and saving plugins should derive from.
Definition pcb_io.h:77
virtual std::unique_ptr< FOOTPRINT > FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, bool aKeepUUID=false, const std::map< std::string, UTF8 > *aProperties=nullptr)
Load a footprint having aFootprintName from the aLibraryPath containing a library format that this PC...
Definition pcb_io.cpp:160
virtual void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, bool aBestEfforts, const std::map< std::string, UTF8 > *aProperties=nullptr)
Return a list of footprint names contained within the library at aLibraryPath.
Definition pcb_io.cpp:112
virtual bool FootprintExists(const wxString &aLibraryPath, const wxString &aFootprintName, const std::map< std::string, UTF8 > *aProperties=nullptr)
Check for the existence of a footprint.
Definition pcb_io.cpp:152
virtual void FootprintDelete(const wxString &aLibraryPath, const wxString &aFootprintName, const std::map< std::string, UTF8 > *aProperties=nullptr)
Delete aFootprintName from the library at aLibraryPath.
Definition pcb_io.cpp:177
virtual void FootprintSave(const wxString &aLibraryPath, const FOOTPRINT *aFootprint, const std::map< std::string, UTF8 > *aProperties=nullptr)
Write aFootprint to an existing library located at aLibraryPath.
Definition pcb_io.cpp:169
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition utf8.h:67
#define _(s)
#define IGNORE_PARENT_GROUP
Definition eda_item.h:55
Functions related to environment variables, including help functions.
const wxChar *const traceLibraries
Flag to enable library table and library manager tracing.
tl::expected< ResultType, LIBRARY_ERROR > LIBRARY_RESULT
KICOMMON_API wxString GetVersionedEnvVarName(const wxString &aBaseName)
Construct a versioned environment variable based on this KiCad major version.
Definition env_vars.cpp:78
Storage for an actual loaded library (including library content owned by the plugin)
LIB_STATUS status
std::unique_ptr< IO_BASE > plugin
const LIBRARY_TABLE_ROW * row
The overall status of a loaded or loading library.
std::optional< LIBRARY_ERROR > error
LOAD_STATUS load_status
wxString result
Test unit parsing edge cases and error handling.
wxLogTrace helper definitions.