25#include <magic_enum.hpp>
29#include <unordered_set>
39using namespace std::chrono_literals;
61 std::vector<LIBRARY_TABLE_TYPE> aTablesToLoad )
80 wxCHECK_MSG(
false,
m_tables,
"Invalid scope passed to loadTables" );
84 std::map<LIBRARY_TABLE_TYPE, std::unique_ptr<LIBRARY_TABLE>>& aTarget = getTarget();
86 if( aTablesToLoad.size() == 0 )
91 aTarget.erase( type );
95 if( fn.IsFileReadable() )
97 std::unique_ptr<LIBRARY_TABLE>
table = std::make_unique<LIBRARY_TABLE>( fn, aScope );
99 if(
table->Type() != type )
101 auto actualName = magic_enum::enum_name(
table->Type() );
102 auto expectedName = magic_enum::enum_name( type );
103 wxLogWarning( wxS(
"Library table '%s' has type %s but expected %s; skipping" ),
105 wxString( actualName.data(), actualName.size() ),
106 wxString( expectedName.data(), expectedName.size() ) );
110 aTarget[type] = std::move(
table );
115 wxLogTrace(
traceLibraries,
"No library table found at %s", fn.GetFullPath() );
123 std::unordered_set<wxString> seenTables;
128 seenTables.insert( aTable.Path() );
137 wxFileName file(
ExpandURI( row.URI(),
Pgm().GetSettingsManager().
Prj() ) );
140 file.MakeAbsolute( wxFileName( aTable.Path() ).GetPath() );
143 wxString src = file.GetFullPath();
145 if( seenTables.contains( src ) )
147 wxLogTrace(
traceLibraries,
"Library table %s has already been loaded!", src );
149 row.SetErrorDescription(
_(
"A reference to this library table already exists" ) );
153 auto child = std::make_unique<LIBRARY_TABLE>( file, aRootTable.
Scope() );
155 processOneTable( *child );
160 row.SetErrorDescription( child->ErrorDescription() );
165 m_childTables.insert_or_assign( row.URI(), std::move( child ) );
170 processOneTable( aRootTable );
185 wxString tablePath = aTable.
Path();
192 const std::map<wxString, LIB_OVERRIDE>& overrides = it->second;
196 auto overIt = overrides.find( row.Nickname() );
198 if( overIt != overrides.end() )
200 row.SetDisabled( overIt->second.disabled );
201 row.SetHidden( overIt->second.hidden );
214 bool aDisabled,
bool aHidden )
219 wxCHECK( settings, );
221 if( !aDisabled && !aHidden )
227 settings->
m_LibOverrides[aTablePath][aNickname] = { aDisabled, aHidden };
236 wxCHECK( settings, );
243 tableIt->second.erase( aNickname );
245 if( tableIt->second.empty() )
257 default: wxCHECK(
false, wxEmptyString );
266 wxCHECK( !
m_tables.contains( aType ), );
275 wxFileName fn(
Pgm().GetSettingsManager().
Prj().GetProjectDirectory(),
tableFileName( aType ) );
287 const wxString& aPrefix ) :
293 wxFileName f( aBasePath,
"" );
299 .value_or(
nullptr );
303 wxDirTraverseResult
OnFile(
const wxString& aFilePath )
override
305 wxFileName file = wxFileName::FileName( aFilePath );
309 if( file.GetExt() == wxT(
"kicad_sym" )
316 return wxDIR_CONTINUE;
320 wxDirTraverseResult
OnDir(
const wxString& dirPath )
override
323 wxFileName dir = wxFileName::DirName( dirPath );
327 if( dirPath.EndsWith( wxS(
".pretty" ) )
333 else if( dirPath.EndsWith( designBlockExt )
340 return wxDIR_CONTINUE;
348 if( aTable->
HasRow( aNickname ) )
354 aNickname = wxString::Format(
"%s%s_%d",
m_lib_prefix, aBaseName, increment );
356 }
while( aTable->
HasRow( aNickname ) );
367 int aExtensionLength )
369 wxString versionedPath = wxString::Format( wxS(
"${%s}" ),
372 wxArrayString parts = aSource.GetDirs();
374 parts.Insert( versionedPath, 0 );
377 parts.Add( aSource.GetFullName() );
379 wxString libPath = wxJoin( parts,
'/' );
383 wxString
name = parts.Last().substr( 0, parts.Last().length() - aExtensionLength );
388 wxLogTrace(
traceLibraries,
"Manager: Adding PCM lib '%s' as '%s'", libPath, nickname );
400 wxLogTrace(
traceLibraries,
"Manager: Not adding existing PCM lib '%s'", libPath );
425 return fn.GetFullPath();
436 return fn.GetFullPath();
444 return wxString::Format( wxS(
"${%s}/%s" ), templateDirVar,
tableFileName( aType ) );
458 auto it = common->m_Env.vars.find( templateDirVar );
460 if( it != common->m_Env.vars.end() && it->second.GetDefinedExternally() )
470 if( wxFileName fn( aPath ); fn.IsFileReadable() )
490 std::vector<LIBRARY_TABLE_TYPE> invalidTables;
500 invalidTables.emplace_back( tableType );
503 return invalidTables;
512 table.SetType( aType );
513 table.Rows().clear();
517 if( aPopulateDefaultLibraries && defaultLib.IsFileReadable() )
525 else if( aPopulateDefaultLibraries )
527 auto typeName = magic_enum::enum_name( aType );
528 wxLogTrace(
traceLibraries,
"No stock library table for %s at '%s'; creating empty global table",
529 wxString( typeName.data(), typeName.size() ), defaultLib.GetFullPath() );
535 table.Format( &formatter );
554 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
555 adapter->GlobalTablesChanged( aTablesToLoad );
563 wxCHECK( settings, );
571 wxFileName d( *packagesPath,
"" );
576 wxDir dir( d.GetPath() );
578 dir.Traverse( traverser );
582 table->Save().map_error(
585 wxLogTrace(
traceLibraries, wxT(
"Warning: save failed after PCM auto-add: %s" ),
592 auto cleanupRemovedPCMLibraries =
600 auto toErase = std::ranges::remove_if(
table->Rows(),
603 if( !IsPcmManagedRow( aRow ) )
606 wxString path = GetFullURI( &aRow, true );
607 return !wxFileName::Exists( path );
610 bool hadRemovals = !toErase.empty();
611 table->Rows().erase( toErase.begin(), toErase.end() );
615 table->Save().map_error(
618 wxLogTrace(
traceLibraries, wxT(
"Warning: save failed after PCM auto-remove: %s" ),
650 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
651 adapter->ProjectChanged();
659 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
660 adapter->AbortAsyncLoad();
665 std::unique_ptr<LIBRARY_MANAGER_ADAPTER>&& aAdapter )
669 wxCHECK_MSG( !
m_adapters.contains( aType ), ,
"You should only register an adapter once!" );
707 wxCHECK_MSG(
false, std::nullopt,
"Table() requires a single scope" );
714 magic_enum::enum_name( aType ) );
726 if( !
Pgm().GetSettingsManager().
Prj().IsNullProject() )
741 bool aIncludeInvalid )
const
743 std::map<wxString, LIBRARY_TABLE_ROW*> rows;
744 std::vector<wxString> rowOrder;
746 std::list<std::ranges::ref_view<const std::map<LIBRARY_TABLE_TYPE, std::unique_ptr<LIBRARY_TABLE>>>> tables;
751 tables = { std::views::all(
m_tables ) };
766 std::function<void(
const std::unique_ptr<LIBRARY_TABLE>&,
bool parentHidden)> processTable =
767 [&](
const std::unique_ptr<LIBRARY_TABLE>& aTable,
const bool parentHidden )
769 if( aTable->Type() != aType )
772 if( aTable->IsOk() || aIncludeInvalid )
776 if( row.IsOk() || aIncludeInvalid )
780 row.SetHidden(
true );
795 if( !rows.contains( row.Nickname() ) )
796 rowOrder.emplace_back( row.Nickname() );
798 rows[ row.Nickname() ] = &row;
805 for(
const std::unique_ptr<LIBRARY_TABLE>&
table :
806 std::views::join( tables ) | std::views::values )
808 processTable(
table,
false );
811 std::vector<LIBRARY_TABLE_ROW*> ret;
813 for(
const wxString& row : rowOrder )
814 ret.emplace_back( rows[row] );
825 auto key = std::make_tuple( aType, aScope, aNickname );
833 if( row->Nickname() == aNickname )
836 m_rowCache[std::make_tuple( aType, aScope, aNickname )] = row;
846 const wxString& aUri,
862 if( std::optional<LIBRARY_MANAGER_ADAPTER*> adapter =
Adapter( aType ); adapter )
863 ( *adapter )->ReloadLibraryEntry( aNickname, aScope );
868 const wxString& aNickname )
870 if( std::optional<LIBRARY_MANAGER_ADAPTER*> adapter =
Adapter( aType ); adapter )
871 return ( *adapter )->LoadLibraryEntry( aNickname );
878 std::initializer_list<LIBRARY_TABLE_TYPE> aTablesToLoad )
887 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
888 adapter->ProjectTablesChanged( aTablesToLoad );
891 if( wxFileName::IsDirReadable( aProjectPath ) )
906 wxLogTrace(
traceLibraries,
"New project path %s is not readable, not loading project tables", aProjectPath );
916 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
917 adapter->ProjectTablesReloaded( aTablesToLoad );
923 std::initializer_list<LIBRARY_TABLE_TYPE> aTablesToLoad )
940 if( std::optional<const LIBRARY_TABLE_ROW*>
result =
GetRow( aType, aNickname ) )
962 return path.GetFullPath();
973 const wxString& uri = aRow.
URI();
975 if( !uri.StartsWith( wxS(
"${" ) ) )
978 size_t end = uri.find( wxS(
'}' ) );
980 if(
end == wxString::npos ||
end <= 2 )
983 wxString varName = uri.SubString( 2,
end - 1 );
985 return varName.Matches( wxS(
"KICAD*_3RD_PARTY" ) );
992 if( aURI1.Find(
"://" ) != wxNOT_FOUND )
995 return aURI1 == aURI2;
999 const wxFileName fn1( aURI1 );
1000 const wxFileName fn2( aURI2 );
1065 bool me = aChangedTables.size() == 0;
1069 if( type ==
Type() )
1098 if( it->second.global_owner ==
this )
1108 bool me = aChangedTables.size() == 0;
1112 if( type ==
Type() )
1127 std::initializer_list<LIBRARY_TABLE_TYPE> aChangedTables )
1129 bool me = aChangedTables.size() == 0;
1133 if( type ==
Type() )
1152 [
this](
const auto& aEntry )
1168 if( loadedRow->
URI() == aRow.
URI() && loadedRow->
Type() == aRow.
Type() )
1185 std::optional<LIB_STATUS> status =
LoadOne( &lib );
1187 if( status.has_value() )
1191 if( status.value().error.has_value() )
1202 aRow.
SetOk(
false );
1227 return row->Nickname();
1230 return std::nullopt;
1236 std::vector<wxString> ret;
1237 std::vector<LIBRARY_TABLE_ROW*> rows =
m_manager.Rows(
Type() );
1239 wxLogTrace(
traceLibraries,
"GetLibraryNames: checking %zu rows from table", rows.size() );
1243 wxString nickname = row->Nickname();
1244 std::optional<const LIB_DATA*> loaded =
fetchIfLoaded( nickname );
1247 ret.emplace_back( nickname );
1250 wxLogTrace(
traceLibraries,
"GetLibraryNames: returning %zu of %zu libraries", ret.size(), rows.size() );
1257 std::optional<const LIB_DATA*> r =
fetchIfLoaded( aNickname );
1260 return !aCheckEnabled || !r.value()->row->Disabled();
1289 if( std::optional<const LIB_DATA*> optRow =
fetchIfLoaded( aNickname ); optRow )
1290 return ( *optRow )->row->Description();
1292 return std::nullopt;
1297 bool aIncludeInvalid )
const
1311 const wxString& aUri,
1348 return std::nullopt;
1351 return loaded /
static_cast<float>( total );
1357 wxLogTrace(
traceLibraries,
"BlockUntilLoaded: entry, acquiring m_loadMutex" );
1358 std::unique_lock<std::mutex> asyncLock(
m_loadMutex );
1362 for(
const std::future<void>& future :
m_futures )
1365 wxLogTrace(
traceLibraries,
"BlockUntilLoaded: all futures complete, loadCount=%zu, loadTotal=%zu",
1396 return it->second.status.error;
1403 return it->second.status.error;
1406 return std::nullopt;
1412 std::vector<std::pair<wxString, LIB_STATUS>> ret;
1416 if( row->Disabled() )
1421 ret.emplace_back( std::make_pair( row->Nickname(), *
result ) );
1426 ret.emplace_back( std::make_pair( row->Nickname(),
1429 .error =
LIBRARY_ERROR(
_(
"Library not found in library table" ) )
1446 if( !errors.IsEmpty() )
1447 errors += wxS(
"\n" );
1449 errors += wxString::Format(
_(
"Library '%s': %s" ),
1450 nickname, status.error->message );
1465 return std::nullopt;
1473 std::shared_mutex& aMutex )
1475 bool wasLoaded =
false;
1478 std::unique_lock lock( aMutex );
1479 auto it = aTarget.find( aNickname );
1481 if( it != aTarget.end() && it->second.plugin )
1484 aTarget.erase( it );
1492 if( !
result.has_value() )
1494 wxLogTrace(
traceLibraries,
"ReloadLibraryEntry: failed to reload %s (%s): %s",
1495 aNickname, magic_enum::enum_name( aScopeToReload ),
1496 result.error().message );
1546 wxLogTrace(
traceLibraries,
"CreateLibrary: IO_ERROR for %s: %s",
1547 aNickname, ioe.
What() );
1550 catch(
const std::exception& e )
1552 wxLogTrace(
traceLibraries,
"CreateLibrary: std::exception for %s: %s",
1553 aNickname, e.what() );
1558 wxLogTrace(
traceLibraries,
"CreateLibrary: library row '%s' not found", aNickname );
1579 return std::nullopt;
1591 return std::nullopt;
1595 return std::nullopt;
1609 return std::nullopt;
1621 return std::nullopt;
1625 return std::nullopt;
1631 std::map<wxString, LIB_DATA>& aTarget,
1632 std::shared_mutex& aMutex )
1634 bool present =
false;
1637 std::shared_lock lock( aMutex );
1638 present = aTarget.contains( aNickname ) && aTarget.at( aNickname ).plugin;
1646 wxLogTrace(
traceLibraries,
"Library %s (%s) not yet loaded, will attempt...",
1647 aNickname, magic_enum::enum_name( aScope ) );
1651 std::unique_lock lock( aMutex );
1654 aTarget[ row->
Nickname() ].row = row;
1658 aTarget[ row->
Nickname() ].global_owner =
this;
1660 return &aTarget.at( aNickname );
1664 return tl::unexpected(
plugin.error() );
1671 std::shared_lock lock( aMutex );
1672 return &aTarget.at( aNickname );
1689 wxString msg = wxString::Format(
_(
"Library %s not found" ), aNickname );
1700 return it->second.status;
1707 return it->second.status;
1710 return std::nullopt;
1716 std::unique_lock<std::mutex> asyncLock(
m_loadMutex, std::try_to_lock );
1722 []( std::future<void>& aFuture )
1724 return aFuture.valid()
1725 && aFuture.wait_for( 0s ) == std::future_status::ready;
1730 wxLogTrace(
traceLibraries,
"Cannot AsyncLoad, futures from a previous call remain!" );
1734 std::vector<LIBRARY_TABLE_ROW*> rows =
m_manager.Rows(
Type() );
1741 wxLogTrace(
traceLibraries,
"AsyncLoad: no libraries left to load; exiting" );
1748 [&](
const wxString& aLib, std::map<wxString, LIB_DATA>& aMap, std::shared_mutex& aMutex )
1750 std::shared_lock lock( aMutex );
1752 if(
auto it = aMap.find( aLib ); it != aMap.end() )
1754 LOAD_STATUS status = it->second.status.load_status;
1772 auto workQueue = std::make_shared<std::vector<LOAD_WORK>>();
1773 workQueue->reserve( rows.size() );
1777 wxString nickname = row->Nickname();
1792 workQueue->emplace_back( LOAD_WORK{ nickname, scope,
getUri( row ) } );
1795 if( workQueue->empty() )
1797 wxLogTrace(
traceLibraries,
"AsyncLoad: all libraries already loaded; exiting" );
1804 size_t poolSize =
tp.get_thread_count();
1805 size_t maxLoadThreads = std::max<size_t>( 1, poolSize > 2 ? poolSize - 2 : 1 );
1806 size_t numWorkers = std::min( maxLoadThreads, workQueue->size() );
1808 auto workIndex = std::make_shared<std::atomic<size_t>>( 0 );
1810 wxLogTrace(
traceLibraries,
"AsyncLoad: %zu libraries to load, using %zu worker threads (pool has %zu)",
1811 workQueue->size(), numWorkers, poolSize );
1813 for(
size_t w = 0; w < numWorkers; ++w )
1816 [
this, workQueue, workIndex]()
1820 if( m_abort.load() )
1823 size_t idx = workIndex->fetch_add( 1 );
1825 if( idx >= workQueue->size() )
1828 const LOAD_WORK& work = ( *workQueue )[idx];
1829 LIBRARY_RESULT<LIB_DATA*> result = loadIfNeeded( work.nickname );
1831 if( result.has_value() )
1833 LIB_DATA* lib = *result;
1838 std::unique_lock lock(
1839 work.scope == LIBRARY_TABLE_SCOPE::GLOBAL
1841 : m_librariesMutex );
1842 lib->status.load_status = LOAD_STATUS::LOADING;
1845 enumerateLibrary( lib, work.uri );
1848 std::unique_lock lock(
1849 work.scope == LIBRARY_TABLE_SCOPE::GLOBAL
1851 : m_librariesMutex );
1852 lib->status.load_status = LOAD_STATUS::LOADED;
1855 catch( IO_ERROR& e )
1857 std::unique_lock lock(
1858 work.scope == LIBRARY_TABLE_SCOPE::GLOBAL
1860 : m_librariesMutex );
1861 lib->status.load_status = LOAD_STATUS::LOAD_ERROR;
1862 lib->status.error = LIBRARY_ERROR( { e.What() } );
1863 wxLogTrace( traceLibraries,
"%s: plugin threw exception: %s",
1864 work.nickname, e.What() );
1869 std::unique_lock lock(
1870 work.scope == LIBRARY_TABLE_SCOPE::GLOBAL
1872 : m_librariesMutex );
1874 std::map<wxString, LIB_DATA>& target =
1875 ( work.scope == LIBRARY_TABLE_SCOPE::GLOBAL ) ? globalLibs()
1878 target[work.nickname].status = LIB_STATUS( {
1879 .load_status = LOAD_STATUS::LOAD_ERROR,
1880 .error = result.error()
1886 }, BS::pr::lowest ) );
1889 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()
std::map< wxString, std::map< wxString, LIB_OVERRIDE > > m_LibOverrides
Overrides for libraries in read-only nested tables.
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
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.
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 StockTableTokenizedURI(LIBRARY_TABLE_TYPE aType)
static wxString ExpandURI(const wxString &aShortURI, const PROJECT &aProject)
std::mutex m_rowCacheMutex
void ClearLibOverride(const wxString &aTablePath, const wxString &aNickname)
Removes any override for a library that no longer needs one.
std::optional< LIBRARY_MANAGER_ADAPTER * > Adapter(LIBRARY_TABLE_TYPE aType) const
void applyLibOverrides(LIBRARY_TABLE &aTable)
Applies user overrides (disabled/hidden) to rows of a read-only nested table.
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 ApplyLibOverrides(LIBRARY_TABLE &aTable)
Applies stored user overrides (disabled/hidden) to rows of a read-only table.
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 SetLibOverride(const wxString &aTablePath, const wxString &aNickname, bool aDisabled, bool aHidden)
Set a user override for a library in a read-only nested table.
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 StockTableReferenceURI(LIBRARY_TABLE_TYPE aType)
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
bool IsReadOnly() const
Returns true if the underlying file exists but is not writable.
LIBRARY_TABLE_ROW & InsertRow()
Builds a new row and inserts it at the end of the table; returning a reference to the row.
const wxString & Path() const
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.
const std::deque< LIBRARY_TABLE_ROW > & Rows() const
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().