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() );
164 m_childTables.insert_or_assign( row.URI(), std::move( child ) );
169 processOneTable( aRootTable );
184 wxString tablePath = aTable.
Path();
191 const std::map<wxString, LIB_OVERRIDE>& overrides = it->second;
195 auto overIt = overrides.find( row.Nickname() );
197 if( overIt != overrides.end() )
199 row.SetDisabled( overIt->second.disabled );
200 row.SetHidden( overIt->second.hidden );
213 bool aDisabled,
bool aHidden )
218 wxCHECK( settings, );
220 if( !aDisabled && !aHidden )
226 settings->
m_LibOverrides[aTablePath][aNickname] = { aDisabled, aHidden };
235 wxCHECK( settings, );
242 tableIt->second.erase( aNickname );
244 if( tableIt->second.empty() )
256 default: wxCHECK(
false, wxEmptyString );
265 wxCHECK( !
m_tables.contains( aType ), );
274 wxFileName fn(
Pgm().GetSettingsManager().
Prj().GetProjectDirectory(),
tableFileName( aType ) );
286 const wxString& aPrefix ) :
292 wxFileName f( aBasePath,
"" );
298 .value_or(
nullptr );
302 wxDirTraverseResult
OnFile(
const wxString& aFilePath )
override
304 wxFileName file = wxFileName::FileName( aFilePath );
308 if( file.GetExt() == wxT(
"kicad_sym" )
315 return wxDIR_CONTINUE;
319 wxDirTraverseResult
OnDir(
const wxString& dirPath )
override
322 wxFileName dir = wxFileName::DirName( dirPath );
326 if( dirPath.EndsWith( wxS(
".pretty" ) )
332 else if( dirPath.EndsWith( designBlockExt )
339 return wxDIR_CONTINUE;
347 if( aTable->
HasRow( aNickname ) )
353 aNickname = wxString::Format(
"%s%s_%d",
m_lib_prefix, aBaseName, increment );
355 }
while( aTable->
HasRow( aNickname ) );
366 int aExtensionLength )
368 wxString versionedPath = wxString::Format( wxS(
"${%s}" ),
371 wxArrayString parts = aSource.GetDirs();
373 parts.Insert( versionedPath, 0 );
376 parts.Add( aSource.GetFullName() );
378 wxString libPath = wxJoin( parts,
'/' );
382 wxString
name = parts.Last().substr( 0, parts.Last().length() - aExtensionLength );
387 wxLogTrace(
traceLibraries,
"Manager: Adding PCM lib '%s' as '%s'", libPath, nickname );
399 wxLogTrace(
traceLibraries,
"Manager: Not adding existing PCM lib '%s'", libPath );
424 return fn.GetFullPath();
435 return fn.GetFullPath();
441 if( wxFileName fn( aPath ); fn.IsFileReadable() )
461 std::vector<LIBRARY_TABLE_TYPE> invalidTables;
471 invalidTables.emplace_back( tableType );
474 return invalidTables;
483 table.SetType( aType );
484 table.Rows().clear();
488 if( !defaultLib.IsFileReadable() )
490 wxLogTrace(
traceLibraries,
"Warning: couldn't read default library table for %s at '%s'",
491 magic_enum::enum_name( aType ), defaultLib.GetFullPath() );
494 if( aPopulateDefaultLibraries )
500 chained.
SetURI( defaultLib.GetFullPath() );
506 table.Format( &formatter );
525 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
526 adapter->GlobalTablesChanged( aTablesToLoad );
534 wxCHECK( settings, );
542 wxFileName d( *packagesPath,
"" );
547 wxDir dir( d.GetPath() );
549 dir.Traverse( traverser );
553 table->Save().map_error(
556 wxLogTrace(
traceLibraries, wxT(
"Warning: save failed after PCM auto-add: %s" ),
563 auto cleanupRemovedPCMLibraries =
571 auto toErase = std::ranges::remove_if(
table->Rows(),
574 if( !IsPcmManagedRow( aRow ) )
577 wxString path = GetFullURI( &aRow, true );
578 return !wxFileName::Exists( path );
581 bool hadRemovals = !toErase.empty();
582 table->Rows().erase( toErase.begin(), toErase.end() );
586 table->Save().map_error(
589 wxLogTrace(
traceLibraries, wxT(
"Warning: save failed after PCM auto-remove: %s" ),
621 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
622 adapter->ProjectChanged();
630 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
631 adapter->AbortAsyncLoad();
636 std::unique_ptr<LIBRARY_MANAGER_ADAPTER>&& aAdapter )
640 wxCHECK_MSG( !
m_adapters.contains( aType ), ,
"You should only register an adapter once!" );
678 wxCHECK_MSG(
false, std::nullopt,
"Table() requires a single scope" );
685 magic_enum::enum_name( aType ) );
697 if( !
Pgm().GetSettingsManager().
Prj().IsNullProject() )
712 bool aIncludeInvalid )
const
714 std::map<wxString, LIBRARY_TABLE_ROW*> rows;
715 std::vector<wxString> rowOrder;
717 std::list<std::ranges::ref_view<const std::map<LIBRARY_TABLE_TYPE, std::unique_ptr<LIBRARY_TABLE>>>> tables;
722 tables = { std::views::all(
m_tables ) };
737 std::function<void(
const std::unique_ptr<LIBRARY_TABLE>&,
bool parentHidden)> processTable =
738 [&](
const std::unique_ptr<LIBRARY_TABLE>& aTable,
const bool parentHidden )
740 if( aTable->Type() != aType )
743 if( aTable->IsOk() || aIncludeInvalid )
747 if( row.IsOk() || aIncludeInvalid )
751 row.SetHidden(
true );
766 if( !rows.contains( row.Nickname() ) )
767 rowOrder.emplace_back( row.Nickname() );
769 rows[ row.Nickname() ] = &row;
776 for(
const std::unique_ptr<LIBRARY_TABLE>&
table :
777 std::views::join( tables ) | std::views::values )
779 processTable(
table,
false );
782 std::vector<LIBRARY_TABLE_ROW*> ret;
784 for(
const wxString& row : rowOrder )
785 ret.emplace_back( rows[row] );
796 auto key = std::make_tuple( aType, aScope, aNickname );
804 if( row->Nickname() == aNickname )
807 m_rowCache[std::make_tuple( aType, aScope, aNickname )] = row;
817 const wxString& aUri,
833 if( std::optional<LIBRARY_MANAGER_ADAPTER*> adapter =
Adapter( aType ); adapter )
834 ( *adapter )->ReloadLibraryEntry( aNickname, aScope );
839 const wxString& aNickname )
841 if( std::optional<LIBRARY_MANAGER_ADAPTER*> adapter =
Adapter( aType ); adapter )
842 return ( *adapter )->LoadLibraryEntry( aNickname );
849 std::initializer_list<LIBRARY_TABLE_TYPE> aTablesToLoad )
858 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
859 adapter->ProjectTablesChanged( aTablesToLoad );
862 if( wxFileName::IsDirReadable( aProjectPath ) )
877 wxLogTrace(
traceLibraries,
"New project path %s is not readable, not loading project tables", aProjectPath );
887 for(
const std::unique_ptr<LIBRARY_MANAGER_ADAPTER>& adapter :
m_adapters | std::views::values )
888 adapter->ProjectTablesReloaded( aTablesToLoad );
894 std::initializer_list<LIBRARY_TABLE_TYPE> aTablesToLoad )
911 if( std::optional<const LIBRARY_TABLE_ROW*>
result =
GetRow( aType, aNickname ) )
933 return path.GetFullPath();
944 const wxString& uri = aRow.
URI();
946 if( !uri.StartsWith( wxS(
"${" ) ) )
949 size_t end = uri.find( wxS(
'}' ) );
951 if(
end == wxString::npos ||
end <= 2 )
954 wxString varName = uri.SubString( 2,
end - 1 );
956 return varName.Matches( wxS(
"KICAD*_3RD_PARTY" ) );
963 if( aURI1.Find(
"://" ) != wxNOT_FOUND )
966 return aURI1 == aURI2;
970 const wxFileName fn1( aURI1 );
971 const wxFileName fn2( aURI2 );
1036 bool me = aChangedTables.size() == 0;
1040 if( type ==
Type() )
1061 bool me = aChangedTables.size() == 0;
1065 if( type ==
Type() )
1080 std::initializer_list<LIBRARY_TABLE_TYPE> aChangedTables )
1082 bool me = aChangedTables.size() == 0;
1086 if( type ==
Type() )
1105 [
this](
const auto& aEntry )
1121 if( loadedRow->
URI() == aRow.
URI() && loadedRow->
Type() == aRow.
Type() )
1138 std::optional<LIB_STATUS> status =
LoadOne( &lib );
1140 if( status.has_value() )
1144 if( status.value().error.has_value() )
1155 aRow.
SetOk(
false );
1180 return row->Nickname();
1183 return std::nullopt;
1189 std::vector<wxString> ret;
1190 std::vector<LIBRARY_TABLE_ROW*> rows =
m_manager.Rows(
Type() );
1192 wxLogTrace(
traceLibraries,
"GetLibraryNames: checking %zu rows from table", rows.size() );
1196 wxString nickname = row->Nickname();
1197 std::optional<const LIB_DATA*> loaded =
fetchIfLoaded( nickname );
1200 ret.emplace_back( nickname );
1203 wxLogTrace(
traceLibraries,
"GetLibraryNames: returning %zu of %zu libraries", ret.size(), rows.size() );
1210 std::optional<const LIB_DATA*> r =
fetchIfLoaded( aNickname );
1213 return !aCheckEnabled || !r.value()->row->Disabled();
1242 if( std::optional<const LIB_DATA*> optRow =
fetchIfLoaded( aNickname ); optRow )
1243 return ( *optRow )->row->Description();
1245 return std::nullopt;
1250 bool aIncludeInvalid )
const
1264 const wxString& aUri,
1301 return std::nullopt;
1304 return loaded /
static_cast<float>( total );
1310 wxLogTrace(
traceLibraries,
"BlockUntilLoaded: entry, acquiring m_loadMutex" );
1311 std::unique_lock<std::mutex> asyncLock(
m_loadMutex );
1315 for(
const std::future<void>& future :
m_futures )
1318 wxLogTrace(
traceLibraries,
"BlockUntilLoaded: all futures complete, loadCount=%zu, loadTotal=%zu",
1349 return it->second.status.error;
1356 return it->second.status.error;
1359 return std::nullopt;
1365 std::vector<std::pair<wxString, LIB_STATUS>> ret;
1369 if( row->Disabled() )
1374 ret.emplace_back( std::make_pair( row->Nickname(), *
result ) );
1379 ret.emplace_back( std::make_pair( row->Nickname(),
1382 .error =
LIBRARY_ERROR(
_(
"Library not found in library table" ) )
1399 if( !errors.IsEmpty() )
1400 errors += wxS(
"\n" );
1402 errors += wxString::Format(
_(
"Library '%s': %s" ),
1403 nickname, status.error->message );
1418 return std::nullopt;
1426 std::shared_mutex& aMutex )
1428 bool wasLoaded =
false;
1431 std::unique_lock lock( aMutex );
1432 auto it = aTarget.find( aNickname );
1434 if( it != aTarget.end() && it->second.plugin )
1437 aTarget.erase( it );
1445 if( !
result.has_value() )
1447 wxLogTrace(
traceLibraries,
"ReloadLibraryEntry: failed to reload %s (%s): %s",
1448 aNickname, magic_enum::enum_name( aScopeToReload ),
1449 result.error().message );
1499 wxLogTrace(
traceLibraries,
"CreateLibrary: IO_ERROR for %s: %s",
1500 aNickname, ioe.
What() );
1503 catch(
const std::exception& e )
1505 wxLogTrace(
traceLibraries,
"CreateLibrary: std::exception for %s: %s",
1506 aNickname, e.what() );
1511 wxLogTrace(
traceLibraries,
"CreateLibrary: library row '%s' not found", aNickname );
1532 return std::nullopt;
1544 return std::nullopt;
1548 return std::nullopt;
1562 return std::nullopt;
1574 return std::nullopt;
1578 return std::nullopt;
1584 std::map<wxString, LIB_DATA>& aTarget,
1585 std::shared_mutex& aMutex )
1587 bool present =
false;
1590 std::shared_lock lock( aMutex );
1591 present = aTarget.contains( aNickname ) && aTarget.at( aNickname ).plugin;
1599 wxLogTrace(
traceLibraries,
"Library %s (%s) not yet loaded, will attempt...",
1600 aNickname, magic_enum::enum_name( aScope ) );
1604 std::unique_lock lock( aMutex );
1607 aTarget[ row->
Nickname() ].row = row;
1610 return &aTarget.at( aNickname );
1614 return tl::unexpected(
plugin.error() );
1621 std::shared_lock lock( aMutex );
1622 return &aTarget.at( aNickname );
1639 wxString msg = wxString::Format(
_(
"Library %s not found" ), aNickname );
1650 return it->second.status;
1657 return it->second.status;
1660 return std::nullopt;
1666 std::unique_lock<std::mutex> asyncLock(
m_loadMutex, std::try_to_lock );
1672 []( std::future<void>& aFuture )
1674 return aFuture.valid()
1675 && aFuture.wait_for( 0s ) == std::future_status::ready;
1680 wxLogTrace(
traceLibraries,
"Cannot AsyncLoad, futures from a previous call remain!" );
1684 std::vector<LIBRARY_TABLE_ROW*> rows =
m_manager.Rows(
Type() );
1691 wxLogTrace(
traceLibraries,
"AsyncLoad: no libraries left to load; exiting" );
1698 [&](
const wxString& aLib, std::map<wxString, LIB_DATA>& aMap, std::shared_mutex& aMutex )
1700 std::shared_lock lock( aMutex );
1702 if(
auto it = aMap.find( aLib ); it != aMap.end() )
1704 LOAD_STATUS status = it->second.status.load_status;
1722 auto workQueue = std::make_shared<std::vector<LOAD_WORK>>();
1723 workQueue->reserve( rows.size() );
1727 wxString nickname = row->Nickname();
1742 workQueue->emplace_back( LOAD_WORK{ nickname, scope,
getUri( row ) } );
1745 if( workQueue->empty() )
1747 wxLogTrace(
traceLibraries,
"AsyncLoad: all libraries already loaded; exiting" );
1754 size_t poolSize =
tp.get_thread_count();
1755 size_t maxLoadThreads = std::max<size_t>( 1, poolSize > 2 ? poolSize - 2 : 1 );
1756 size_t numWorkers = std::min( maxLoadThreads, workQueue->size() );
1758 auto workIndex = std::make_shared<std::atomic<size_t>>( 0 );
1760 wxLogTrace(
traceLibraries,
"AsyncLoad: %zu libraries to load, using %zu worker threads (pool has %zu)",
1761 workQueue->size(), numWorkers, poolSize );
1763 for(
size_t w = 0; w < numWorkers; ++w )
1766 [
this, workQueue, workIndex]()
1770 if( m_abort.load() )
1773 size_t idx = workIndex->fetch_add( 1 );
1775 if( idx >= workQueue->size() )
1778 const LOAD_WORK& work = ( *workQueue )[idx];
1779 LIBRARY_RESULT<LIB_DATA*> result = loadIfNeeded( work.nickname );
1781 if( result.has_value() )
1783 LIB_DATA* lib = *result;
1788 std::unique_lock lock(
1789 work.scope == LIBRARY_TABLE_SCOPE::GLOBAL
1791 : m_librariesMutex );
1792 lib->status.load_status = LOAD_STATUS::LOADING;
1795 enumerateLibrary( lib, work.uri );
1798 std::unique_lock lock(
1799 work.scope == LIBRARY_TABLE_SCOPE::GLOBAL
1801 : m_librariesMutex );
1802 lib->status.load_status = LOAD_STATUS::LOADED;
1805 catch( IO_ERROR& e )
1807 std::unique_lock lock(
1808 work.scope == LIBRARY_TABLE_SCOPE::GLOBAL
1810 : m_librariesMutex );
1811 lib->status.load_status = LOAD_STATUS::LOAD_ERROR;
1812 lib->status.error = LIBRARY_ERROR( { e.What() } );
1813 wxLogTrace( traceLibraries,
"%s: plugin threw exception: %s",
1814 work.nickname, e.What() );
1819 std::unique_lock lock(
1820 work.scope == LIBRARY_TABLE_SCOPE::GLOBAL
1822 : m_librariesMutex );
1824 std::map<wxString, LIB_DATA>& target =
1825 ( work.scope == LIBRARY_TABLE_SCOPE::GLOBAL ) ? globalLibs()
1828 target[work.nickname].status = LIB_STATUS( {
1829 .load_status = LOAD_STATUS::LOAD_ERROR,
1830 .error = result.error()
1836 }, BS::pr::lowest ) );
1839 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
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
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 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().