Symbol editor: allow editing all related symbols from the treeview

This makes it more straightforward to edit a group of related symbols
(related = all derived from the same parent, including the parent).

Relates-To: https://gitlab.com/kicad/code/kicad/-/issues/21067
Relates-To: https://gitlab.com/kicad/code/kicad/-/issues/9742
Relates-To: https://gitlab.com/kicad/code/kicad/-/issues/11506
This commit is contained in:
John Beard 2025-09-02 20:53:07 +08:00
parent 9b14434fc3
commit b34746e06b
5 changed files with 99 additions and 15 deletions

View File

@ -959,6 +959,13 @@ TOOL_ACTION ACTIONS::showLibraryTable( TOOL_ACTION_ARGS()
.FriendlyName( _( "Library Table" ) )
.Icon( BITMAPS::table ) );
TOOL_ACTION ACTIONS::showRelatedLibraryTable( TOOL_ACTION_ARGS()
.Name( "common.Control.showRelatedLibraryTable" )
.Scope( AS_GLOBAL )
.FriendlyName( _( "Edit Related Symbols as Table" ) )
.Tooltip( _( "Edit all symbols related to the selected symbol in a table" ) )
.Icon( BITMAPS::table ) );
TOOL_ACTION ACTIONS::showLibraryTree( TOOL_ACTION_ARGS()
.Name( "common.Control.showLibraryTree" )
.Scope( AS_GLOBAL )

View File

@ -744,6 +744,15 @@ bool SYMBOL_LIBRARY_MANAGER:: HasDerivedSymbols( const wxString& aSymbolName,
}
size_t SYMBOL_LIBRARY_MANAGER::GetDerivedSymbolNames( const wxString& aSymbolName, const wxString& aLibraryName,
wxArrayString& aList )
{
LIB_BUFFER& libBuf = getLibraryBuffer( aLibraryName );
return libBuf.GetDerivedSymbolNames( aSymbolName, aList );
}
size_t SYMBOL_LIBRARY_MANAGER::GetLibraryCount() const
{
return symTable()->GetLogicalLibs().size();
@ -1237,24 +1246,53 @@ size_t LIB_BUFFER::GetDerivedSymbolNames( const wxString& aSymbolName, wxArraySt
{
wxCHECK( !aSymbolName.IsEmpty(), 0 );
// Parent: children map
std::unordered_map<LIB_SYMBOL_SPTR, std::vector<LIB_SYMBOL_SPTR>> derivedMap;
// Iterate the library once to resolve all derived symbol links.
// This means we only need to iterate the library once, and we can then look up the links
// as needed.
for( std::shared_ptr<SYMBOL_BUFFER>& entry : m_symbols )
{
const LIB_SYMBOL& symbol = entry->GetSymbol();
if( symbol.IsDerived() )
LIB_SYMBOL_SPTR symbol = entry->GetSymbol().SharedPtr();
if( symbol->IsDerived() )
{
LIB_SYMBOL_SPTR parent = symbol.GetParent().lock();
LIB_SYMBOL_SPTR parent = symbol->GetParent().lock();
// Check for inherited symbol without a valid parent.
wxCHECK2( parent, continue );
if( parent->GetName() == aSymbolName )
{
aList.Add( symbol.GetName() );
derivedMap[parent].emplace_back( std::move( symbol ) );
}
}
GetDerivedSymbolNames( symbol.GetName(), aList );
}
const auto visit = [&]( LIB_SYMBOL& aSymbol )
{
aList.Add( aSymbol.GetName() );
};
// Assign to std::function to allow recursion
const std::function<void( LIB_SYMBOL_SPTR& )> getDerived =
[&]( LIB_SYMBOL_SPTR& aSymbol )
{
auto it = derivedMap.find( aSymbol );
if( it != derivedMap.end() )
{
for( LIB_SYMBOL_SPTR& derivedSymbol : it->second )
{
visit( *derivedSymbol );
// Recurse to get symbols derived from this one
getDerived( derivedSymbol );
}
}
};
// Start the recursion at the top
LIB_SYMBOL_SPTR symbol = GetSymbol( aSymbolName )->SharedPtr();
getDerived( symbol );
return aList.GetCount();
}

View File

@ -389,6 +389,11 @@ public:
*/
bool HasDerivedSymbols( const wxString& aSymbolName, const wxString& aLibraryName );
/**
* Fetch all of the symbols derived from a \a aSymbolName into \a aList.
*/
size_t GetDerivedSymbolNames( const wxString& aSymbolName, const wxString& aLibraryName, wxArrayString& aList );
size_t GetLibraryCount() const;
protected:

View File

@ -218,6 +218,7 @@ bool SYMBOL_EDITOR_CONTROL::Init()
}
ctxMenu.AddItem( ACTIONS::showLibraryTable, librarySelectedCondition, 300 );
ctxMenu.AddItem( ACTIONS::showRelatedLibraryTable, symbolSelectedCondition, 300 );
libraryTreeTool->AddContextMenuItems( &ctxMenu );
}
@ -916,14 +917,45 @@ int SYMBOL_EDITOR_CONTROL::ChangeUnit( const TOOL_EVENT& aEvent )
}
static void CollectRelatedSymbols( LIB_SYMBOL_LIBRARY_MANAGER& libMgr, const wxString& aLibName, const LIB_SYMBOL& sym,
wxArrayString& aSymbolNames )
{
LIB_SYMBOL_SPTR root = sym.SharedPtr();
while( root->IsDerived() )
{
LIB_SYMBOL_SPTR parent = root->GetParent().lock();
wxCHECK2( parent, /*void*/ );
root = parent;
}
aSymbolNames.Add( root->GetName() );
// Now we have the root symbol, collect all its derived symbols
libMgr.GetDerivedSymbolNames( root->GetName(), aLibName, aSymbolNames );
}
int SYMBOL_EDITOR_CONTROL::ShowLibraryTable( const TOOL_EVENT& aEvent )
{
SYMBOL_EDIT_FRAME* editFrame = getEditFrame<SYMBOL_EDIT_FRAME>();
LIB_SYMBOL_LIBRARY_MANAGER& libMgr = editFrame->GetLibManager();
wxString libName = editFrame->GetTreeLIBID().GetLibNickname();
// Get all symbol names from the library manager
wxArrayString symbolNames;
if( aEvent.IsAction( &ACTIONS::showRelatedLibraryTable ) )
{
LIB_ID symId = editFrame->GetTargetLibId();
const LIB_SYMBOL* sym = libMgr.GetBufferedSymbol( symId.GetLibItemName(), libName );
wxCHECK2( sym, /*void*/ );
CollectRelatedSymbols( libMgr, libName, *sym, symbolNames );
}
else
{
// Get all symbol names from the library manager
editFrame->GetLibManager().GetSymbolNames( libName, symbolNames );
}
DIALOG_LIB_FIELDS dlg( editFrame, libName, symbolNames );
dlg.SetTitle( _( "Library Fields" ) );
@ -977,6 +1009,7 @@ void SYMBOL_EDITOR_CONTROL::setTransitions()
Go( &SYMBOL_EDITOR_CONTROL::TogglePinAltIcons, SCH_ACTIONS::togglePinAltIcons.MakeEvent() );
Go( &SYMBOL_EDITOR_CONTROL::ShowLibraryTable, ACTIONS::showLibraryTable.MakeEvent() );
Go( &SYMBOL_EDITOR_CONTROL::ShowLibraryTable, ACTIONS::showRelatedLibraryTable.MakeEvent() );
Go( &SYMBOL_EDITOR_CONTROL::ChangeUnit, SCH_ACTIONS::previousUnit.MakeEvent() );
Go( &SYMBOL_EDITOR_CONTROL::ChangeUnit, SCH_ACTIONS::nextUnit.MakeEvent() );

View File

@ -265,6 +265,7 @@ public:
static TOOL_ACTION showProperties;
static TOOL_ACTION showDatasheet;
static TOOL_ACTION showLibraryTable;
static TOOL_ACTION showRelatedLibraryTable;
// Internal
static TOOL_ACTION updateMenu;