25#include <magic_enum.hpp>
29#include <unordered_set>
39using namespace std::chrono_literals;
60 std::vector<LIBRARY_TABLE_TYPE> aTablesToLoad )
79 wxCHECK_MSG(
false,
m_tables,
"Invalid scope passed to loadTables" );
83 std::map<LIBRARY_TABLE_TYPE, std::unique_ptr<LIBRARY_TABLE>>& aTarget = getTarget();
85 if( aTablesToLoad.size() == 0 )
90 aTarget.erase( type );
94 if( fn.IsFileReadable() )
96 std::unique_ptr<LIBRARY_TABLE>
table = std::make_unique<LIBRARY_TABLE>( fn, aScope );
98 if(
table->Type() != type )
100 auto actualName = magic_enum::enum_name(
table->Type() );
101 auto expectedName = magic_enum::enum_name( type );
102 wxLogWarning( wxS(
"Library table '%s' has type %s but expected %s; skipping" ),
104 wxString( actualName.data(), actualName.size() ),
105 wxString( expectedName.data(), expectedName.size() ) );
109 aTarget[type] = std::move(
table );
114 wxLogTrace(
traceLibraries,
"No library table found at %s", fn.GetFullPath() );
122 std::unordered_set<wxString> seenTables;
127 seenTables.insert( aTable.Path() );
136 wxFileName file(
ExpandURI( row.URI(),
Pgm().GetSettingsManager().
Prj() ) );
139 file.MakeAbsolute( wxFileName( aTable.Path() ).GetPath() );
142 wxString src = file.GetFullPath();
144 if( seenTables.contains( src ) )
146 wxLogTrace(
traceLibraries,
"Library table %s has already been loaded!", src );
148 row.SetErrorDescription(
_(
"A reference to this library table already exists" ) );
152 auto child = std::make_unique<LIBRARY_TABLE>( file, aRootTable.
Scope() );
154 processOneTable( *child );
159 row.SetErrorDescription( child->ErrorDescription() );
162 m_childTables.insert_or_assign( row.URI(), std::move( child ) );
167 processOneTable( aRootTable );
178 default: wxCHECK(
false, wxEmptyString );
187 wxCHECK( !
m_tables.contains( aType ), );
196 wxFileName fn(
Pgm().GetSettingsManager().
Prj().GetProjectDirectory(),
tableFileName( aType ) );
208 const wxString& aPrefix ) :
214 wxFileName f( aBasePath,
"" );
220 .value_or(
nullptr );
224 wxDirTraverseResult
OnFile(
const wxString& aFilePath )
override
226 wxFileName file = wxFileName::FileName( aFilePath );
230 if( file.GetExt() == wxT(
"kicad_sym" )
237 return wxDIR_CONTINUE;
241 wxDirTraverseResult
OnDir(
const wxString& dirPath )
override
244 wxFileName dir = wxFileName::DirName( dirPath );
248 if( dirPath.EndsWith( wxS(
".pretty" ) )
254 else if( dirPath.EndsWith( designBlockExt )
261 return wxDIR_CONTINUE;
269 if( aTable->
HasRow( aNickname ) )
275 aNickname = wxString::Format(
"%s%s_%d",
m_lib_prefix, aBaseName, increment );
277 }
while( aTable->
HasRow( aNickname ) );
288 int aExtensionLength )
290 wxString versionedPath = wxString::Format( wxS(
"${%s}" ),
293 wxArrayString parts = aSource.GetDirs();
295 parts.Insert( versionedPath, 0 );
298 parts.Add( aSource.GetFullName() );
300 wxString libPath = wxJoin( parts,
'/' );
304 wxString
name = parts.Last().substr( 0, parts.Last().length() - aExtensionLength );
309 wxLogTrace(
traceLibraries,
"Manager: Adding PCM lib '%s' as '%s'", libPath, nickname );
321 wxLogTrace(
traceLibraries,
"Manager: Not adding existing PCM lib '%s'", libPath );
346 return fn.GetFullPath();
357 return fn.GetFullPath();
363 if( wxFileName fn( aPath ); fn.IsFileReadable() )
383 std::vector<LIBRARY_TABLE_TYPE> invalidTables;
393 invalidTables.emplace_back( tableType );
396 return invalidTables;
405 table.SetType( aType );
406 table.Rows().clear();
410 if( !defaultLib.IsFileReadable() )
412 wxLogTrace(
traceLibraries,
"Warning: couldn't read default library table for %s at '%s'",
413 magic_enum::enum_name( aType ), defaultLib.GetFullPath() );
416 if( aPopulateDefaultLibraries )
422 chained.
SetURI( defaultLib.GetFullPath() );
428 table.Format( &formatter );
447 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
448 adapter->GlobalTablesChanged( aTablesToLoad );
456 wxCHECK( settings, );
464 wxFileName d( *packagesPath,
"" );
469 wxDir dir( d.GetPath() );
471 dir.Traverse( traverser );
475 table->Save().map_error(
478 wxLogTrace(
traceLibraries, wxT(
"Warning: save failed after PCM auto-add: %s" ),
485 auto cleanupRemovedPCMLibraries =
491 auto toErase = std::ranges::remove_if(
table->Rows(),
494 if( !IsPcmManagedRow( aRow ) )
497 wxString path = GetFullURI( &aRow, true );
498 return !wxFileName::Exists( path );
501 bool hadRemovals = !toErase.empty();
502 table->Rows().erase( toErase.begin(), toErase.end() );
506 table->Save().map_error(
509 wxLogTrace(
traceLibraries, wxT(
"Warning: save failed after PCM auto-remove: %s" ),
541 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
542 adapter->ProjectChanged();
550 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
551 adapter->AbortAsyncLoad();
556 std::unique_ptr<LIBRARY_MANAGER_ADAPTER>&& aAdapter )
560 wxCHECK_MSG( !
m_adapters.contains( aType ), ,
"You should only register an adapter once!" );
598 wxCHECK_MSG(
false, std::nullopt,
"Table() requires a single scope" );
605 magic_enum::enum_name( aType ) );
617 if( !
Pgm().GetSettingsManager().
Prj().IsNullProject() )
632 bool aIncludeInvalid )
const
634 std::map<wxString, LIBRARY_TABLE_ROW*> rows;
635 std::vector<wxString> rowOrder;
637 std::list<std::ranges::ref_view<const std::map<LIBRARY_TABLE_TYPE, std::unique_ptr<LIBRARY_TABLE>>>> tables;
642 tables = { std::views::all(
m_tables ) };
657 std::function<void(
const std::unique_ptr<LIBRARY_TABLE>&,
bool parentHidden)> processTable =
658 [&](
const std::unique_ptr<LIBRARY_TABLE>& aTable,
const bool parentHidden )
660 if( aTable->Type() != aType )
663 if( aTable->IsOk() || aIncludeInvalid )
667 if( row.IsOk() || aIncludeInvalid )
671 row.SetHidden(
true );
686 if( !rows.contains( row.Nickname() ) )
687 rowOrder.emplace_back( row.Nickname() );
689 rows[ row.Nickname() ] = &row;
696 for(
const std::unique_ptr<LIBRARY_TABLE>&
table :
697 std::views::join( tables ) | std::views::values )
699 processTable(
table,
false );
702 std::vector<LIBRARY_TABLE_ROW*> ret;
704 for(
const wxString& row : rowOrder )
705 ret.emplace_back( rows[row] );
716 auto key = std::make_tuple( aType, aScope, aNickname );
724 if( row->Nickname() == aNickname )
727 m_rowCache[std::make_tuple( aType, aScope, aNickname )] = row;
737 const wxString& aUri,
753 if( std::optional<LIBRARY_MANAGER_ADAPTER*> adapter =
Adapter( aType ); adapter )
754 ( *adapter )->ReloadLibraryEntry( aNickname, aScope );
759 const wxString& aNickname )
761 if( std::optional<LIBRARY_MANAGER_ADAPTER*> adapter =
Adapter( aType ); adapter )
762 return ( *adapter )->LoadLibraryEntry( aNickname );
769 std::initializer_list<LIBRARY_TABLE_TYPE> aTablesToLoad )
778 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
779 adapter->ProjectTablesChanged( aTablesToLoad );
782 if( wxFileName::IsDirReadable( aProjectPath ) )
797 wxLogTrace(
traceLibraries,
"New project path %s is not readable, not loading project tables", aProjectPath );
807 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
808 adapter->ProjectTablesReloaded( aTablesToLoad );
814 std::initializer_list<LIBRARY_TABLE_TYPE> aTablesToLoad )
831 if( std::optional<const LIBRARY_TABLE_ROW*>
result =
GetRow( aType, aNickname ) )
853 return path.GetFullPath();
864 const wxString& uri = aRow.
URI();
866 if( !uri.StartsWith( wxS(
"${" ) ) )
869 size_t end = uri.find( wxS(
'}' ) );
871 if(
end == wxString::npos ||
end <= 2 )
874 wxString varName = uri.SubString( 2,
end - 1 );
876 return varName.Matches( wxS(
"KICAD*_3RD_PARTY" ) );
883 if( aURI1.Find(
"://" ) != wxNOT_FOUND )
886 return aURI1 == aURI2;
890 const wxFileName fn1( aURI1 );
891 const wxFileName fn2( aURI2 );
956 bool me = aChangedTables.size() == 0;
981 bool me = aChangedTables.size() == 0;
1000 std::initializer_list<LIBRARY_TABLE_TYPE> aChangedTables )
1002 bool me = aChangedTables.size() == 0;
1006 if( type ==
Type() )
1025 [
this](
const auto& aEntry )
1041 if( loadedRow->
URI() == aRow.
URI() && loadedRow->
Type() == aRow.
Type() )
1058 std::optional<LIB_STATUS> status =
LoadOne( &lib );
1060 if( status.has_value() )
1064 if( status.value().error.has_value() )
1075 aRow.
SetOk(
false );
1100 return row->Nickname();
1103 return std::nullopt;
1109 std::vector<wxString> ret;
1110 std::vector<LIBRARY_TABLE_ROW*> rows =
m_manager.Rows(
Type() );
1112 wxLogTrace(
traceLibraries,
"GetLibraryNames: checking %zu rows from table", rows.size() );
1116 wxString nickname = row->Nickname();
1117 std::optional<const LIB_DATA*> loaded =
fetchIfLoaded( nickname );
1120 ret.emplace_back( nickname );
1123 wxLogTrace(
traceLibraries,
"GetLibraryNames: returning %zu of %zu libraries", ret.size(), rows.size() );
1130 std::optional<const LIB_DATA*> r =
fetchIfLoaded( aNickname );
1133 return !aCheckEnabled || !r.value()->row->Disabled();
1162 if( std::optional<const LIB_DATA*> optRow =
fetchIfLoaded( aNickname ); optRow )
1163 return ( *optRow )->row->Description();
1165 return std::nullopt;
1170 bool aIncludeInvalid )
const
1184 const wxString& aUri,
1221 return std::nullopt;
1224 return loaded /
static_cast<float>( total );
1230 wxLogTrace(
traceLibraries,
"BlockUntilLoaded: entry, acquiring m_loadMutex" );
1231 std::unique_lock<std::mutex> asyncLock(
m_loadMutex );
1235 for(
const std::future<void>& future :
m_futures )
1238 wxLogTrace(
traceLibraries,
"BlockUntilLoaded: all futures complete, loadCount=%zu, loadTotal=%zu",
1269 return it->second.status.error;
1276 return it->second.status.error;
1279 return std::nullopt;
1285 std::vector<std::pair<wxString, LIB_STATUS>> ret;
1289 if( row->Disabled() )
1294 ret.emplace_back( std::make_pair( row->Nickname(), *
result ) );
1299 ret.emplace_back( std::make_pair( row->Nickname(),
1302 .error =
LIBRARY_ERROR(
_(
"Library not found in library table" ) )
1319 if( !errors.IsEmpty() )
1320 errors += wxS(
"\n" );
1322 errors += wxString::Format(
_(
"Library '%s': %s" ),
1323 nickname, status.error->message );
1338 return std::nullopt;
1346 std::shared_mutex& aMutex )
1348 bool wasLoaded =
false;
1351 std::unique_lock lock( aMutex );
1352 auto it = aTarget.find( aNickname );
1354 if( it != aTarget.end() && it->second.plugin )
1357 aTarget.erase( it );
1365 if( !
result.has_value() )
1367 wxLogTrace(
traceLibraries,
"ReloadLibraryEntry: failed to reload %s (%s): %s",
1368 aNickname, magic_enum::enum_name( aScopeToReload ),
1369 result.error().message );
1419 wxLogTrace(
traceLibraries,
"CreateLibrary: IO_ERROR for %s: %s",
1420 aNickname, ioe.
What() );
1423 catch(
const std::exception& e )
1425 wxLogTrace(
traceLibraries,
"CreateLibrary: std::exception for %s: %s",
1426 aNickname, e.what() );
1431 wxLogTrace(
traceLibraries,
"CreateLibrary: library row '%s' not found", aNickname );
1452 return std::nullopt;
1464 return std::nullopt;
1468 return std::nullopt;
1482 return std::nullopt;
1494 return std::nullopt;
1498 return std::nullopt;
1504 std::map<wxString, LIB_DATA>& aTarget,
1505 std::shared_mutex& aMutex )
1507 bool present =
false;
1510 std::shared_lock lock( aMutex );
1511 present = aTarget.contains( aNickname ) && aTarget.at( aNickname ).plugin;
1519 wxLogTrace(
traceLibraries,
"Library %s (%s) not yet loaded, will attempt...",
1520 aNickname, magic_enum::enum_name( aScope ) );
1524 std::unique_lock lock( aMutex );
1527 aTarget[ row->
Nickname() ].row = row;
1530 return &aTarget.at( aNickname );
1534 return tl::unexpected(
plugin.error() );
1541 std::shared_lock lock( aMutex );
1542 return &aTarget.at( aNickname );
1559 wxString msg = wxString::Format(
_(
"Library %s not found" ), aNickname );
1570 return it->second.status;
1577 return it->second.status;
1580 return std::nullopt;
1586 std::unique_lock<std::mutex> asyncLock(
m_loadMutex, std::try_to_lock );
1592 []( std::future<void>& aFuture )
1594 return aFuture.valid()
1595 && aFuture.wait_for( 0s ) == std::future_status::ready;
1600 wxLogTrace(
traceLibraries,
"Cannot AsyncLoad, futures from a previous call remain!" );
1604 std::vector<LIBRARY_TABLE_ROW*> rows =
m_manager.Rows(
Type() );
1611 wxLogTrace(
traceLibraries,
"AsyncLoad: no libraries left to load; exiting" );
1618 [&](
const wxString& aLib, std::map<wxString, LIB_DATA>& aMap, std::shared_mutex& aMutex )
1620 std::shared_lock lock( aMutex );
1622 if(
auto it = aMap.find( aLib ); it != aMap.end() )
1624 LOAD_STATUS status = it->second.status.load_status;
1642 auto workQueue = std::make_shared<std::vector<LOAD_WORK>>();
1643 workQueue->reserve( rows.size() );
1647 wxString nickname = row->Nickname();
1662 workQueue->emplace_back( LOAD_WORK{ nickname, scope,
getUri( row ) } );
1665 if( workQueue->empty() )
1667 wxLogTrace(
traceLibraries,
"AsyncLoad: all libraries already loaded; exiting" );
1674 size_t poolSize =
tp.get_thread_count();
1675 size_t maxLoadThreads = std::max<size_t>( 1, poolSize > 2 ? poolSize - 2 : 1 );
1676 size_t numWorkers = std::min( maxLoadThreads, workQueue->size() );
1678 auto workIndex = std::make_shared<std::atomic<size_t>>( 0 );
1680 wxLogTrace(
traceLibraries,
"AsyncLoad: %zu libraries to load, using %zu worker threads (pool has %zu)",
1681 workQueue->size(), numWorkers, poolSize );
1683 for(
size_t w = 0; w < numWorkers; ++w )
1686 [
this, workQueue, workIndex]()
1690 if( m_abort.load() )
1693 size_t idx = workIndex->fetch_add( 1 );
1695 if( idx >= workQueue->size() )
1698 const LOAD_WORK& work = ( *workQueue )[idx];
1699 LIBRARY_RESULT<LIB_DATA*> result = loadIfNeeded( work.nickname );
1701 if( result.has_value() )
1703 LIB_DATA* lib = *result;
1708 std::unique_lock lock(
1709 work.scope == LIBRARY_TABLE_SCOPE::GLOBAL
1711 : m_librariesMutex );
1712 lib->status.load_status = LOAD_STATUS::LOADING;
1715 enumerateLibrary( lib, work.uri );
1718 std::unique_lock lock(
1719 work.scope == LIBRARY_TABLE_SCOPE::GLOBAL
1721 : m_librariesMutex );
1722 lib->status.load_status = LOAD_STATUS::LOADED;
1725 catch( IO_ERROR& e )
1727 std::unique_lock lock(
1728 work.scope == LIBRARY_TABLE_SCOPE::GLOBAL
1730 : m_librariesMutex );
1731 lib->status.load_status = LOAD_STATUS::LOAD_ERROR;
1732 lib->status.error = LIBRARY_ERROR( { e.What() } );
1733 wxLogTrace( traceLibraries,
"%s: plugin threw exception: %s",
1734 work.nickname, e.What() );
1739 std::unique_lock lock(
1740 work.scope == LIBRARY_TABLE_SCOPE::GLOBAL
1742 : m_librariesMutex );
1744 std::map<wxString, LIB_DATA>& target =
1745 ( work.scope == LIBRARY_TABLE_SCOPE::GLOBAL ) ? globalLibs()
1748 target[work.nickname].status = LIB_STATUS( {
1749 .load_status = LOAD_STATUS::LOAD_ERROR,
1750 .error = result.error()
1756 }, BS::pr::lowest ) );
1759 wxLogTrace(
traceLibraries,
"Started async load of %zu libraries", workQueue->size() );
virtual bool DeleteLibrary(const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr)
Delete an existing library and returns true, or if library does not exist returns false,...
virtual bool IsLibraryWritable(const wxString &aLibraryPath)
Return true if the library at aLibraryPath is writable.
virtual void CreateLibrary(const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr)
Create a new empty library at aLibraryPath empty.
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()
The interface used by the classes that actually can load IO plugins for the different parts of KiCad ...
std::optional< float > AsyncLoadProgress() const
Returns async load progress between 0.0 and 1.0, or nullopt if load is not in progress.
virtual std::optional< LIB_STATUS > LoadOne(LIB_DATA *aLib)=0
void resetProjectCache()
Aborts pending loads and resets every project-scope cache entry in place (plugin and row cleared,...
virtual std::optional< LIBRARY_ERROR > LibraryError(const wxString &aNickname) const
void ReloadLibraryEntry(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH)
std::optional< LIB_STATUS > GetLibraryStatus(const wxString &aNickname) const
Returns the status of a loaded library, or nullopt if the library hasn't been loaded (yet)
virtual ~LIBRARY_MANAGER_ADAPTER()
std::optional< LIBRARY_TABLE * > ProjectTable() const
Retrieves the project library table for this adapter type, or nullopt if one doesn't exist.
void AbortAsyncLoad()
Aborts any async load in progress; blocks until fully done aborting.
void ProjectTablesChanged(std::initializer_list< LIBRARY_TABLE_TYPE > aChangedTables={})
Notify the adapter that the project library tables are about to be rebuilt.
LIBRARY_TABLE * GlobalTable() const
Retrieves the global library table for this adapter type.
virtual std::shared_mutex & globalLibsMutex()=0
LIBRARY_MANAGER_ADAPTER(LIBRARY_MANAGER &aManager)
Constructs a type-specific adapter into the library manager.
void CheckTableRow(LIBRARY_TABLE_ROW &aRow)
bool IsLibraryLoaded(const wxString &aNickname)
std::vector< LIBRARY_TABLE_ROW * > Rows(LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH, bool aIncludeInvalid=false) const
Like LIBRARY_MANAGER::Rows but filtered to the LIBRARY_TABLE_TYPE of this adapter.
std::optional< LIBRARY_TABLE_ROW * > FindRowByURI(const wxString &aUri, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::FindRowByURI but filtered to the LIBRARY_TABLE_TYPE of this adapter.
virtual std::map< wxString, LIB_DATA > & globalLibs()=0
virtual LIBRARY_TABLE_TYPE Type() const =0
The type of library table this adapter works with.
bool DeleteLibrary(const wxString &aNickname)
Deletes the given library from disk if it exists; returns true if deleted.
LIBRARY_RESULT< LIB_DATA * > loadIfNeeded(const wxString &aNickname)
Fetches a loaded library, triggering a load of that library if it isn't loaded yet.
wxString GetLibraryLoadErrors() const
Returns all library load errors as newline-separated strings for display.
std::optional< wxString > FindLibraryByURI(const wxString &aURI) const
std::shared_mutex m_librariesMutex
LIBRARY_MANAGER & Manager() const
void abortLoad()
Aborts any async load in progress; blocks until fully done aborting.
std::optional< wxString > GetLibraryDescription(const wxString &aNickname) const
virtual LIBRARY_RESULT< IO_BASE * > createPlugin(const LIBRARY_TABLE_ROW *row)=0
Creates a concrete plugin for the given row.
void GlobalTablesChanged(std::initializer_list< LIBRARY_TABLE_TYPE > aChangedTables={})
Notify the adapter that the global library tables have changed.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library tables.
std::optional< LIBRARY_TABLE_ROW * > GetRow(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::GetRow but filtered to the LIBRARY_TABLE_TYPE of this adapter.
std::map< wxString, LIB_DATA > m_libraries
virtual IO_BASE * plugin(const LIB_DATA *aRow)=0
std::vector< wxString > GetLibraryNames() const
Returns a list of library nicknames that are available (skips any that failed to load)
virtual void ProjectChanged()
Notify the adapter that the active project has changed.
LIBRARY_RESULT< LIB_DATA * > loadFromScope(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope, std::map< wxString, LIB_DATA > &aTarget, std::shared_mutex &aMutex)
std::vector< std::future< void > > m_futures
static wxString getUri(const LIBRARY_TABLE_ROW *aRow)
bool CreateLibrary(const wxString &aNickname)
Creates the library (i.e. saves to disk) for the given row if it exists.
void AsyncLoad()
Loads all available libraries for this adapter type in the background.
virtual bool IsWritable(const wxString &aNickname) const
Return true if the given nickname exists and is not a read-only library.
std::vector< std::pair< wxString, LIB_STATUS > > GetLibraryStatuses() const
Returns a list of all library nicknames and their status (even if they failed to load)
std::atomic< size_t > m_loadTotal
void ProjectTablesReloaded(std::initializer_list< LIBRARY_TABLE_TYPE > aChangedTables={})
Complements ProjectTablesChanged by erasing project-scope cache entries whose nicknames no longer app...
std::atomic< size_t > m_loadCount
LIBRARY_MANAGER & m_manager
std::optional< LIB_STATUS > LoadLibraryEntry(const wxString &aNickname)
Synchronously loads the named library to LOADED state.
std::optional< const LIB_DATA * > fetchIfLoaded(const wxString &aNickname) const
void ReloadTables(LIBRARY_TABLE_SCOPE aScope, std::initializer_list< LIBRARY_TABLE_TYPE > aTablesToLoad={})
static wxString ExpandURI(const wxString &aShortURI, const PROJECT &aProject)
std::mutex m_rowCacheMutex
std::optional< LIBRARY_MANAGER_ADAPTER * > Adapter(LIBRARY_TABLE_TYPE aType) const
std::map< wxString, std::unique_ptr< LIBRARY_TABLE > > m_childTables
Map of full URI to table object for tables that are referenced by global or project tables.
void loadNestedTables(LIBRARY_TABLE &aTable)
std::map< ROW_CACHE_KEY, LIBRARY_TABLE_ROW * > m_rowCache
bool RemoveAdapter(LIBRARY_TABLE_TYPE aType, LIBRARY_MANAGER_ADAPTER *aAdapter)
void ReloadLibraryEntry(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH)
static bool UrisAreEquivalent(const wxString &aURI1, const wxString &aURI2)
std::mutex m_adaptersMutex
std::optional< LIBRARY_TABLE * > Table(LIBRARY_TABLE_TYPE aType, LIBRARY_TABLE_SCOPE aScope)
Retrieves a given table; creating a new empty project table if a valid project is loaded and the give...
void RegisterAdapter(LIBRARY_TABLE_TYPE aType, std::unique_ptr< LIBRARY_MANAGER_ADAPTER > &&aAdapter)
static wxString DefaultGlobalTablePath(LIBRARY_TABLE_TYPE aType)
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...
static std::vector< LIBRARY_TABLE_TYPE > InvalidGlobalTables()
void createEmptyTable(LIBRARY_TABLE_TYPE aType, LIBRARY_TABLE_SCOPE aScope)
void AbortAsyncLoads()
Abort any async library loading operations in progress.
std::optional< LIB_STATUS > LoadLibraryEntry(LIBRARY_TABLE_TYPE aType, const wxString &aNickname)
Synchronously loads the named library to LOADED state for the given type.
static bool GlobalTablesValid()
std::map< LIBRARY_TABLE_TYPE, std::unique_ptr< LIBRARY_TABLE > > m_projectTables
std::optional< LIBRARY_TABLE_ROW * > FindRowByURI(LIBRARY_TABLE_TYPE aType, const wxString &aUri, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
void LoadProjectTables(std::initializer_list< LIBRARY_TABLE_TYPE > aTablesToLoad={})
(Re)loads the project library tables in the given list, or all tables if no list is given
static bool CreateGlobalTable(LIBRARY_TABLE_TYPE aType, bool aPopulateDefaultLibraries)
void loadTables(const wxString &aTablePath, LIBRARY_TABLE_SCOPE aScope, std::vector< LIBRARY_TABLE_TYPE > aTablesToLoad={})
static wxString tableFileName(LIBRARY_TABLE_TYPE aType)
static bool IsPcmManagedRow(const LIBRARY_TABLE_ROW &aRow)
Return true if a library table row was added by the Plugin and Content Manager.
std::vector< LIBRARY_TABLE_ROW * > Rows(LIBRARY_TABLE_TYPE aType, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH, bool aIncludeInvalid=false) const
Returns a flattened list of libraries of the given type.
void LoadGlobalTables(std::initializer_list< LIBRARY_TABLE_TYPE > aTablesToLoad={})
(Re)loads the global library tables in the given list, or all tables if no list is given
std::map< LIBRARY_TABLE_TYPE, std::unique_ptr< LIBRARY_TABLE > > m_tables
static wxString StockTablePath(LIBRARY_TABLE_TYPE aType)
std::optional< LIBRARY_TABLE_ROW * > GetRow(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH)
void ProjectChanged()
Notify all adapters that the project has changed.
static bool IsTableValid(const wxString &aPath)
std::map< LIBRARY_TABLE_TYPE, std::unique_ptr< LIBRARY_MANAGER_ADAPTER > > m_adapters
void SetNickname(const wxString &aNickname)
void SetOk(bool aOk=true)
void SetType(const wxString &aType)
void SetErrorDescription(const wxString &aDescription)
std::map< std::string, UTF8 > GetOptionsMap() const
void SetDescription(const wxString &aDescription)
const wxString & Type() const
static const wxString TABLE_TYPE_NAME
void SetURI(const wxString &aUri)
const wxString & URI() const
const wxString & Nickname() const
LIBRARY_TABLE_ROW & InsertRow()
Builds a new row and inserts it at the end of the table; returning a reference to the row.
LIBRARY_TABLE_SCOPE Scope() const
bool HasRow(const wxString &aNickname) const
bool HasRowWithURI(const wxString &aUri, const PROJECT &aProject, bool aSubstituted=false) const
Returns true if the given (fully-expanded) URI exists as a library in this table.
static wxString GetStockTemplatesPath()
Gets the stock (install) templates path.
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
LIBRARY_TABLE * m_designBlockTable
std::set< LIBRARY_TABLE * > m_modified
LIBRARY_MANAGER & m_manager
std::set< LIBRARY_TABLE * > Modified() const
const PROJECT & m_project
PCM_LIB_TRAVERSER(const wxString &aBasePath, LIBRARY_MANAGER &aManager, const wxString &aPrefix)
void ensureUnique(LIBRARY_TABLE *aTable, const wxString &aBaseName, wxString &aNickname) const
LIBRARY_TABLE * m_symbolTable
wxDirTraverseResult OnDir(const wxString &dirPath) override
Handles footprint library and design block library directories, minimum nest level 3.
void addRowIfNecessary(LIBRARY_TABLE *aTable, const wxFileName &aSource, ADD_MODE aMode, int aExtensionLength)
LIBRARY_TABLE * m_fpTable
wxDirTraverseResult OnFile(const wxString &aFilePath) override
Handles symbol library files, minimum nest level 2.
size_t m_prefix_dir_count
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
virtual SETTINGS_MANAGER & GetSettingsManager() const
Container for project specific data.
T * GetAppSettings(const char *aFilename)
Return a handle to the a given settings by type.
static void ResolvePossibleSymlinks(wxFileName &aFilename)
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Functions related to environment variables, including help functions.
static const std::string KiCadDesignBlockLibPathExtension
static const std::string SymbolLibraryTableFileName
static const std::string DesignBlockLibraryTableFileName
static const std::string FootprintLibraryTableFileName
const wxChar *const traceLibraries
Flag to enable library table and library manager tracing.
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
LOAD_STATUS
Status of a library load managed by a library adapter.
tl::expected< ResultType, LIBRARY_ERROR > LIBRARY_RESULT
KICOMMON_API std::optional< wxString > GetVersionedEnvVarValue(const std::map< wxString, ENV_VAR_ITEM > &aMap, const wxString &aBaseName)
Attempt to retrieve the value of a versioned environment variable, such as KICAD8_TEMPLATE_DIR.
KICOMMON_API wxString GetVersionedEnvVarName(const wxString &aBaseName)
Construct a versioned environment variable based on this KiCad major version.
PGM_BASE & Pgm()
The global program "get" accessor.
std::vector< LIBRARY_TABLE > tables
Storage for an actual loaded library (including library content owned by the plugin)
std::unique_ptr< IO_BASE > plugin
const LIBRARY_TABLE_ROW * row
The overall status of a loaded or loading library.
std::vector< std::vector< std::string > > table
wxString result
Test unit parsing edge cases and error handling.
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::priority_thread_pool thread_pool
wxLogTrace helper definitions.
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().