Browse Source

Move Bus Aliases to Project File

Rather than keeping bus aliases in each individual sheet, consolidate
them into a single project file location

Fixes https://gitlab.com/kicad/code/kicad/issues/15450
master
Seth Hillbrand 1 month ago
parent
commit
47422e19d9
  1. 43
      common/project/project_file.cpp
  2. 16
      eeschema/bus_alias.h
  3. 12
      eeschema/connection_graph.cpp
  4. 11
      eeschema/dialogs/dialog_label_properties.cpp
  5. 44
      eeschema/dialogs/dialog_schematic_setup.cpp
  6. 103
      eeschema/dialogs/panel_setup_buses.cpp
  7. 5
      eeschema/dialogs/panel_setup_buses.h
  8. 17
      eeschema/eeschema_config.cpp
  9. 53
      eeschema/erc/erc.cpp
  10. 10
      eeschema/erc/erc.h
  11. 3
      eeschema/sch_file_versions.h
  12. 2
      eeschema/sch_io/altium/sch_io_altium.cpp
  13. 1
      eeschema/sch_io/cadstar/cadstar_sch_archive_loader.cpp
  14. 23
      eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.cpp
  15. 1
      eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.h
  16. 2
      eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp
  17. 3
      eeschema/sch_screen.cpp
  18. 33
      eeschema/sch_screen.h
  19. 112
      eeschema/schematic.cpp
  20. 15
      eeschema/schematic.h
  21. 3
      include/project/project_file.h
  22. 2
      qa/tests/eeschema/erc/test_erc_global_labels.cpp
  23. 1
      qa/tests/eeschema/erc/test_erc_ground_pins.cpp
  24. 1
      qa/tests/eeschema/erc/test_erc_hierarchical_schematics.cpp
  25. 1
      qa/tests/eeschema/erc/test_erc_label_not_connected.cpp
  26. 1
      qa/tests/eeschema/erc/test_erc_multiple_pin_to_pin.cpp
  27. 1
      qa/tests/eeschema/erc/test_erc_no_connect.cpp
  28. 1
      qa/tests/eeschema/erc/test_erc_stacking_pins.cpp

43
common/project/project_file.cpp

@ -108,6 +108,49 @@ PROJECT_FILE::PROJECT_FILE( const wxString& aFullPath ) :
m_LegacyLibNames.push_back( entry.get<wxString>() );
}, {} ) );
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "schematic.bus_aliases",
[&]() -> nlohmann::json
{
nlohmann::json ret = nlohmann::json::object();
for( const auto& alias : m_BusAliases )
{
nlohmann::json members = nlohmann::json::array();
for( const wxString& member : alias.second )
members.push_back( member );
ret[ alias.first.ToStdString() ] = members;
}
return ret;
},
[&]( const nlohmann::json& aJson )
{
if( aJson.empty() || !aJson.is_object() )
return;
m_BusAliases.clear();
for( auto it = aJson.begin(); it != aJson.end(); ++it )
{
const nlohmann::json& membersJson = it.value();
if( !membersJson.is_array() )
continue;
std::vector<wxString> members;
for( const nlohmann::json& entry : membersJson )
{
if( entry.is_string() )
members.push_back( entry.get<wxString>() );
}
m_BusAliases.emplace( wxString::FromUTF8( it.key().c_str() ), std::move( members ) );
}
}, {} ) );
m_NetSettings = std::make_shared<NET_SETTINGS>( this, "net_settings" );
m_ComponentClassSettings =

16
eeschema/bus_alias.h

@ -27,15 +27,10 @@
#include <wx/string.h>
class SCH_SCREEN;
class BUS_ALIAS
{
public:
BUS_ALIAS( SCH_SCREEN* aParent = nullptr ) :
m_parent( aParent )
{ }
BUS_ALIAS() = default;
~BUS_ALIAS()
{ }
@ -51,18 +46,9 @@ public:
const std::vector<wxString>& Members() const { return m_members; }
std::vector<wxString>& Members() { return m_members; }
SCH_SCREEN* GetParent() { return m_parent; }
void SetParent( SCH_SCREEN* aParent ) { m_parent = aParent; }
protected:
wxString m_name;
std::vector<wxString> m_members;
/**
* Schematic Setup can edit aliases from all sheets, so we have to store a reference back
* to our parent so that the dialog can update the parent if aliases are changed or removed.
*/
SCH_SCREEN* m_parent;
};
#endif

12
eeschema/connection_graph.cpp

@ -1473,11 +1473,11 @@ void CONNECTION_GRAPH::buildItemSubGraphs()
// Recache all bus aliases for later use
wxCHECK_RET( m_schematic, wxS( "Connection graph cannot be built without schematic pointer" ) );
SCH_SCREENS screens( m_schematic->Root() );
m_bus_alias_cache.clear();
for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
for( const std::shared_ptr<BUS_ALIAS>& alias : m_schematic->GetAllBusAliases() )
{
for( const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
if( alias )
m_bus_alias_cache[alias->GetName()] = alias;
}
@ -2200,11 +2200,11 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
// Recache all bus aliases for later use
wxCHECK_RET( m_schematic, wxT( "Connection graph cannot be built without schematic pointer" ) );
SCH_SCREENS screens( m_schematic->Root() );
m_bus_alias_cache.clear();
for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
for( const std::shared_ptr<BUS_ALIAS>& alias : m_schematic->GetAllBusAliases() )
{
for( const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
if( alias )
m_bus_alias_cache[alias->GetName()] = alias;
}

11
eeschema/dialogs/dialog_label_properties.cpp

@ -299,9 +299,8 @@ bool DIALOG_LABEL_PROPERTIES::TransferDataToWindow()
if( m_currentLabel->Type() == SCH_GLOBAL_LABEL_T || m_currentLabel->Type() == SCH_LABEL_T )
{
// Load the combobox with the existing labels of the same type
std::set<wxString> existingLabels;
std::vector<std::shared_ptr<BUS_ALIAS>> busAliases;
SCH_SCREENS allScreens( m_Parent->Schematic().Root() );
std::set<wxString> existingLabels;
SCH_SCREENS allScreens( m_Parent->Schematic().Root() );
for( SCH_SCREEN* screen = allScreens.GetFirst(); screen; screen = allScreens.GetNext() )
{
@ -344,14 +343,10 @@ bool DIALOG_LABEL_PROPERTIES::TransferDataToWindow()
}
}
}
// Add bus aliases from the current screen
auto& sheetAliases = screen->GetBusAliases();
busAliases.insert( busAliases.end(), sheetAliases.begin(), sheetAliases.end() );
}
// Add bus aliases to label list
for( const std::shared_ptr<BUS_ALIAS>& busAlias : busAliases )
for( const std::shared_ptr<BUS_ALIAS>& busAlias : m_Parent->Schematic().GetAllBusAliases() )
existingLabels.insert( wxT( "{" ) + busAlias->GetName() + wxT( "}" ) );
for( const wxString& label : existingLabels )

44
eeschema/dialogs/dialog_schematic_setup.cpp

@ -253,50 +253,8 @@ void DIALOG_SCHEMATIC_SETUP::onAuxiliaryAction( wxCommandEvent& event )
if( importDlg.m_BusAliasesOpt->GetValue() )
{
// The bus aliases are stored on individual sheets, so we have to load the whole
// schematic for this one.
wxFileName schematicFn( projectFn );
schematicFn.SetExt( FILEEXT::KiCadSchematicFileExtension );
wxString fullFileName = schematicFn.GetFullPath();
wxString msg;
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
WX_PROGRESS_REPORTER progressReporter( this, _( "Load Bus Aliases" ), 1, PR_CAN_ABORT );
pi->SetProgressReporter( &progressReporter );
try
{
wxBusyCursor busy;
otherSch.SetRoot( pi->LoadSchematicFile( fullFileName, &otherSch ) );
// Make ${SHEETNAME} work on the root sheet until we properly support
// naming the root sheet
otherSch.Root().SetName( _( "Root" ) );
}
catch( const FUTURE_FORMAT_ERROR& ffe )
{
msg.Printf( _( "Error fetching bus aliases. Could not load schematic '%s'." ),
fullFileName );
progressReporter.Hide();
DisplayErrorMessage( this, msg, ffe.Problem() );
}
catch( const IO_ERROR& ioe )
{
msg.Printf( _( "Error fetching bus aliases. Could not load schematic '%s'." ),
fullFileName );
progressReporter.Hide();
DisplayErrorMessage( this, msg, ioe.What() );
}
// This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
// cause any issues on macOS and Windows. If it does, it will have to be conditionally
// compiled.
Raise();
static_cast<PANEL_SETUP_BUSES*>( m_treebook->ResolvePage( m_busesPage ) )
->ImportSettingsFrom( otherSch );
->ImportSettingsFrom( file.m_BusAliases );
}
if( importDlg.m_TextVarsOpt->GetValue() )

103
eeschema/dialogs/panel_setup_buses.cpp

@ -19,9 +19,11 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <widgets/wx_grid.h>
#include <widgets/std_bitmap_button.h>
#include <confirm.h>
#include <project/project_file.h>
#include <sch_edit_frame.h>
#include <schematic.h>
#include <dialogs/panel_setup_buses.h>
@ -92,40 +94,30 @@ PANEL_SETUP_BUSES::~PANEL_SETUP_BUSES()
}
void PANEL_SETUP_BUSES::loadAliases( const SCHEMATIC& aSchematic )
void PANEL_SETUP_BUSES::loadAliases()
{
auto contains =
[&]( const std::shared_ptr<BUS_ALIAS>& alias ) -> bool
{
wxString aName = alias->GetName();
std::vector<wxString> aMembers = alias->Members();
std::sort( aMembers.begin(), aMembers.end() );
m_aliases.clear();
for( const std::shared_ptr<BUS_ALIAS>& candidate : m_aliases )
{
wxString bName = candidate->GetName();
std::vector<wxString> bMembers = candidate->Members();
const auto& projectAliases = m_frame->Prj().GetProjectFile().m_BusAliases;
std::sort( bMembers.begin(), bMembers.end() );
std::vector<std::pair<wxString, std::vector<wxString>>> aliasList( projectAliases.begin(),
projectAliases.end() );
if( aName == bName && aMembers == bMembers )
return true;
}
std::sort( aliasList.begin(), aliasList.end(),
[]( const std::pair<wxString, std::vector<wxString>>& a,
const std::pair<wxString, std::vector<wxString>>& b )
{
return a.first.CmpNoCase( b.first ) < 0;
} );
return false;
};
for( const auto& alias : aliasList )
{
std::shared_ptr<BUS_ALIAS> entry = std::make_shared<BUS_ALIAS>();
SCH_SCREENS screens( aSchematic.Root() );
entry->SetName( alias.first );
entry->Members() = alias.second;
// collect aliases from each open sheet
for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() )
{
for( const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
{
if( !contains( alias ) )
m_aliases.push_back( alias->Clone() );
}
m_aliases.push_back( entry );
}
int ii = 0;
@ -142,7 +134,7 @@ void PANEL_SETUP_BUSES::loadAliases( const SCHEMATIC& aSchematic )
bool PANEL_SETUP_BUSES::TransferDataToWindow()
{
loadAliases( m_frame->Schematic() );
loadAliases();
return true;
}
@ -159,13 +151,7 @@ bool PANEL_SETUP_BUSES::TransferDataFromWindow()
// Associate the respective members with the last alias that is active.
updateAliasMembers( m_lastAlias );
SCH_SCREENS screens( m_frame->Schematic().Root() );
for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() )
screen->ClearBusAliases();
for( const std::shared_ptr<BUS_ALIAS>& alias : m_aliases )
alias->GetParent()->AddBusAlias( alias );
m_frame->Schematic().SetBusAliases( m_aliases );
return true;
}
@ -179,8 +165,8 @@ void PANEL_SETUP_BUSES::OnAddAlias( wxCommandEvent& aEvent )
m_aliasesGrid->OnAddRow(
[&]() -> std::pair<int, int>
{
// New aliases get stored on the currently visible sheet
m_aliases.push_back( std::make_shared<BUS_ALIAS>( m_frame->GetScreen() ) );
// New aliases are stored at the project level
m_aliases.push_back( std::make_shared<BUS_ALIAS>() );
int row = m_aliasesGrid->GetNumberRows();
@ -285,8 +271,7 @@ void PANEL_SETUP_BUSES::OnAliasesGridCellChanging( wxGridEvent& event )
if( ii == event.GetRow() )
continue;
if( name == m_aliasesGrid->GetCellValue( ii, 0 )
&& m_aliases[ row ]->GetParent() == m_aliases[ ii ]->GetParent() )
if( name == m_aliasesGrid->GetCellValue( ii, 0 ) )
{
m_errorMsg = wxString::Format( _( "Alias name '%s' already in use." ), name );
m_errorGrid = m_aliasesGrid;
@ -357,12 +342,6 @@ void PANEL_SETUP_BUSES::doReloadMembersGrid()
wxString source;
wxString membersLabel;
if( alias->GetParent() )
{
wxFileName sheet_name( alias->GetParent()->GetFileName() );
source.Printf( wxS( "(" ) + sheet_name.GetFullName() + wxS( ")" ) );
}
membersLabel.Printf( m_membersLabelTemplate, m_lastAliasName );
m_source->SetLabel( source );
@ -483,13 +462,39 @@ void PANEL_SETUP_BUSES::OnUpdateUI( wxUpdateUIEvent& event )
}
void PANEL_SETUP_BUSES::ImportSettingsFrom( const SCHEMATIC& aOtherSchematic )
void PANEL_SETUP_BUSES::ImportSettingsFrom( const std::map<wxString, std::vector<wxString>>& aAliases )
{
loadAliases( aOtherSchematic );
m_aliases.clear();
std::vector<std::pair<wxString, std::vector<wxString>>> aliasList( aAliases.begin(),
aAliases.end() );
std::sort( aliasList.begin(), aliasList.end(),
[]( const std::pair<wxString, std::vector<wxString>>& a,
const std::pair<wxString, std::vector<wxString>>& b )
{
return a.first.CmpNoCase( b.first ) < 0;
} );
for( const auto& alias : aliasList )
{
std::shared_ptr<BUS_ALIAS> entry = std::make_shared<BUS_ALIAS>();
entry->SetName( alias.first );
entry->Members() = alias.second;
m_aliases.push_back( entry );
}
int ii = 0;
m_aliasesGrid->ClearRows();
m_aliasesGrid->AppendRows( m_aliases.size() );
// New aliases get stored on the currently visible sheet
for( const std::shared_ptr<BUS_ALIAS>& alias : m_aliases )
alias->SetParent( m_frame->GetScreen() );
m_aliasesGrid->SetCellValue( ii++, 0, alias->GetName() );
m_membersBook->SetSelection( 1 );
}

5
eeschema/dialogs/panel_setup_buses.h

@ -27,7 +27,6 @@
#include <bus_alias.h>
class SCH_EDIT_FRAME;
class SCH_SCREEN;
class BUS_ALIAS;
class PANEL_SETUP_BUSES : public PANEL_SETUP_BUSES_BASE
@ -40,7 +39,7 @@ public:
bool TransferDataFromWindow() override;
bool TransferDataToWindow() override;
void ImportSettingsFrom( const SCHEMATIC& aOtherSchematic );
void ImportSettingsFrom( const std::map<wxString, std::vector<wxString>>& aAliases );
protected:
void OnAddAlias( wxCommandEvent& aEvent ) override;
@ -52,7 +51,7 @@ protected:
void OnSizeGrid( wxSizeEvent& event ) override;
void OnUpdateUI( wxUpdateUIEvent& event ) override;
void loadAliases( const SCHEMATIC& aSchematic );
void loadAliases();
void reloadMembersGridOnIdle( wxIdleEvent& aEvent );

17
eeschema/eeschema_config.cpp

@ -116,14 +116,7 @@ void SCH_EDIT_FRAME::ShowSchematicSetupDialog( const wxString& aInitialPage )
return;
}
SCH_SCREENS screens( Schematic().Root() );
std::vector<std::shared_ptr<BUS_ALIAS>> oldAliases;
for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() )
{
for( const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
oldAliases.push_back( alias );
}
std::map<wxString, std::vector<wxString>> oldAliases = Prj().GetProjectFile().m_BusAliases;
DIALOG_SCHEMATIC_SETUP dlg( this );
@ -158,13 +151,7 @@ void SCH_EDIT_FRAME::ShowSchematicSetupDialog( const wxString& aInitialPage )
GetCanvas()->GetView()->MarkDirty();
GetCanvas()->GetView()->UpdateAllItems( KIGFX::REPAINT );
std::vector<std::shared_ptr<BUS_ALIAS>> newAliases;
for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() )
{
for( const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
newAliases.push_back( alias );
}
std::map<wxString, std::vector<wxString>> newAliases = Prj().GetProjectFile().m_BusAliases;
if( oldAliases != newAliases )
RecalculateConnections( nullptr, GLOBAL_CLEANUP );

53
eeschema/erc/erc.cpp

@ -436,51 +436,6 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
}
int ERC_TESTER::TestConflictingBusAliases()
{
wxString msg;
int err_count = 0;
std::vector<std::shared_ptr<BUS_ALIAS>> aliases;
for( SCH_SCREEN* screen = m_screens.GetFirst(); screen; screen = m_screens.GetNext() )
{
const auto& screen_aliases = screen->GetBusAliases();
for( const std::shared_ptr<BUS_ALIAS>& alias : screen_aliases )
{
std::vector<wxString> aliasMembers = alias->Members();
std::sort( aliasMembers.begin(), aliasMembers.end() );
for( const std::shared_ptr<BUS_ALIAS>& test : aliases )
{
std::vector<wxString> testMembers = test->Members();
std::sort( testMembers.begin(), testMembers.end() );
if( alias->GetName() == test->GetName() && aliasMembers != testMembers )
{
msg.Printf( _( "Bus alias %s has conflicting definitions on %s and %s" ),
alias->GetName(),
alias->GetParent()->GetFileName(),
test->GetParent()->GetFileName() );
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_BUS_ALIAS_CONFLICT );
ercItem->SetErrorMessage( msg );
SCH_MARKER* marker = new SCH_MARKER( std::move( ercItem ), VECTOR2I() );
test->GetParent()->Append( marker );
++err_count;
}
}
}
aliases.insert( aliases.end(), screen_aliases.begin(), screen_aliases.end() );
}
return err_count;
}
int ERC_TESTER::TestMultiunitFootprints()
{
int errors = 0;
@ -1939,14 +1894,6 @@ void ERC_TESTER::RunTests( DS_PROXY_VIEW_ITEM* aDrawingSheet, SCH_EDIT_FRAME* aE
TestDuplicateSheetNames( true );
}
if( m_settings.IsTestEnabled( ERCE_BUS_ALIAS_CONFLICT ) )
{
if( aProgressReporter )
aProgressReporter->AdvancePhase( _( "Checking bus conflicts..." ) );
TestConflictingBusAliases();
}
// The connection graph has a whole set of ERC checks it can run
if( aProgressReporter )
aProgressReporter->AdvancePhase( _( "Checking conflicts..." ) );

10
eeschema/erc/erc.h

@ -77,16 +77,6 @@ public:
*/
void TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet );
/**
* Check that there are no conflicting bus alias definitions in the schematic.
*
* (for example, two hierarchical sub-sheets contain different definitions for
* the same bus alias)
*
* @return the error count
*/
int TestConflictingBusAliases();
/**
* Test if all units of each multiunit symbol have the same footprint assigned.
* @return The error count.

3
eeschema/sch_file_versions.h

@ -56,7 +56,8 @@
//#define SEXPR_SYMBOL_LIB_FILE_VERSION 20250318 // ~ no longer means empty text
//#define SEXPR_SYMBOL_LIB_FILE_VERSION 20250324 // Jumper pin groups
//#define SEXPR_SYMBOL_LIB_FILE_VERSION 20250829 // Rounded Rectangles
#define SEXPR_SYMBOL_LIB_FILE_VERSION 20250901 // Stacked Pin notation
//#define SEXPR_SYMBOL_LIB_FILE_VERSION 20250901 // Stacked Pin notation
#define SEXPR_SYMBOL_LIB_FILE_VERSION 20250925 // Bus alias in Project File
/**
* Schematic file version.

2
eeschema/sch_io/altium/sch_io_altium.cpp

@ -623,7 +623,7 @@ void SCH_IO_ALTIUM::CreateAliases()
for( auto& [_, harness] : m_altiumHarnesses )
{
std::shared_ptr<BUS_ALIAS> alias = std::make_shared<BUS_ALIAS>( screen );
std::shared_ptr<BUS_ALIAS> alias = std::make_shared<BUS_ALIAS>();
alias->SetName( harness.m_name );
for( HARNESS::HARNESS_PORT& port : harness.m_ports )

1
eeschema/sch_io/cadstar/cadstar_sch_archive_loader.cpp

@ -1030,7 +1030,6 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadBusses()
std::shared_ptr<BUS_ALIAS> kiBusAlias = std::make_shared<BUS_ALIAS>();
kiBusAlias->SetName( bus.Name );
kiBusAlias->SetParent( screen );
screen->AddBusAlias( kiBusAlias );
m_busesMap.insert( { bus.ID, kiBusAlias } );

23
eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.cpp

@ -403,9 +403,6 @@ void SCH_IO_KICAD_SEXPR::Format( SCH_SHEET* aSheet )
m_out->Print( ")" );
for( const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
saveBusAlias( alias );
// Enforce item ordering
auto cmp =
[]( const SCH_ITEM* a, const SCH_ITEM* b )
@ -1494,26 +1491,6 @@ void SCH_IO_KICAD_SEXPR::saveGroup( SCH_GROUP* aGroup )
}
void SCH_IO_KICAD_SEXPR::saveBusAlias( std::shared_ptr<BUS_ALIAS> aAlias )
{
wxCHECK_RET( aAlias != nullptr, "BUS_ALIAS* is NULL" );
wxString members;
for( const wxString& member : aAlias->Members() )
{
if( !members.IsEmpty() )
members += wxS( " " );
members += m_out->Quotew( member );
}
m_out->Print( "(bus_alias %s (members %s))",
m_out->Quotew( aAlias->GetName() ).c_str(),
TO_UTF8( members ) );
}
void SCH_IO_KICAD_SEXPR::saveInstances( const std::vector<SCH_SHEET_INSTANCE>& aInstances )
{
if( aInstances.size() )

1
eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.h

@ -160,7 +160,6 @@ private:
void saveTextBox( SCH_TEXTBOX* aText );
void saveTable( SCH_TABLE* aTable );
void saveGroup( SCH_GROUP* aGroup );
void saveBusAlias( std::shared_ptr<BUS_ALIAS> aAlias );
void saveInstances( const std::vector<SCH_SHEET_INSTANCE>& aSheets );
void cacheLib( const wxString& aLibraryFileName, const std::map<std::string, UTF8>* aProperties );

2
eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp

@ -4840,7 +4840,7 @@ void SCH_IO_KICAD_SEXPR_PARSER::parseBusAlias( SCH_SCREEN* aScreen )
wxCHECK( aScreen, /* void */ );
T token;
std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>();
wxString alias;
wxString member;

3
eeschema/sch_screen.cpp

@ -1433,7 +1433,8 @@ void SCH_SCREEN::FixupEmbeddedData()
void SCH_SCREEN::AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias )
{
m_aliases.insert( aAlias );
if( SCHEMATIC* schematic = Schematic() )
schematic->AddBusAlias( aAlias );
}

33
eeschema/sch_screen.h

@ -506,26 +506,10 @@ public:
void FixupEmbeddedData();
/**
* Add a bus alias definition (and transfers ownership of the pointer).
* Add a bus alias definition.
*/
void AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias );
/**
* Remove all bus alias definitions.
*/
void ClearBusAliases()
{
m_aliases.clear();
}
/**
* Return a set of bus aliases defined in this screen.
*/
auto& GetBusAliases() const
{
return m_aliases;
}
const std::vector<SCH_SYMBOL_INSTANCE>& GetSymbolInstances() const
{
return m_symbolInstances;
@ -662,18 +646,6 @@ private:
*/
size_t getLibSymbolNameMatches( const SCH_SYMBOL& aSymbol, std::vector<wxString>& aMatches );
/**
* Compare two #BUS_ALIAS objects by name. For sorting in the set.
*/
struct BusAliasCmp
{
bool operator()( const std::shared_ptr<BUS_ALIAS>& a,
const std::shared_ptr<BUS_ALIAS>& b ) const
{
return a->GetName() < b->GetName();
}
};
public:
/**
* last value for the zoom level, useful in Eeschema when changing the current displayed
@ -712,9 +684,6 @@ private:
/// Flag to indicate the file associated with this screen has been created.
bool m_fileExists;
/// List of bus aliases stored in this screen.
std::set< std::shared_ptr< BUS_ALIAS >, BusAliasCmp > m_aliases;
/// Library symbols required for this schematic.
std::map<wxString, LIB_SYMBOL*> m_libSymbols;

112
eeschema/schematic.cpp

@ -17,6 +17,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <set>
#include <bus_alias.h>
#include <commit.h>
#include <connection_graph.h>
@ -149,6 +151,10 @@ void SCHEMATIC::Reset()
m_connectionGraph->Reset();
m_currentSheet->clear();
m_busAliases.clear();
updateProjectBusAliases();
}
@ -178,6 +184,8 @@ void SCHEMATIC::SetProject( PROJECT* aPrj )
project.m_SchematicSettings->LoadFromFile();
project.m_SchematicSettings->m_NgspiceSettings->LoadFromFile();
project.m_ErcSettings->LoadFromFile();
loadBusAliasesFromProject();
}
}
@ -231,6 +239,7 @@ void SCHEMATIC::SetRoot( SCH_SHEET* aRootSheet )
m_hierarchy = BuildSheetListSortedByPageNumbers();
m_connectionGraph->Reset();
}
@ -436,19 +445,110 @@ std::vector<SCH_MARKER*> SCHEMATIC::ResolveERCExclusions()
std::shared_ptr<BUS_ALIAS> SCHEMATIC::GetBusAlias( const wxString& aLabel ) const
{
for( const SCH_SHEET_PATH& sheet : Hierarchy() )
for( const std::shared_ptr<BUS_ALIAS>& alias : m_busAliases )
{
for( const std::shared_ptr<BUS_ALIAS>& alias : sheet.LastScreen()->GetBusAliases() )
{
if( alias->GetName() == aLabel )
return alias;
}
if( alias && alias->GetName() == aLabel )
return alias;
}
return nullptr;
}
void SCHEMATIC::AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias )
{
if( !aAlias )
return;
auto sameDefinition = [&]( const std::shared_ptr<BUS_ALIAS>& candidate ) -> bool
{
return candidate && candidate->GetName() == aAlias->GetName()
&& candidate->Members() == aAlias->Members();
};
auto it = std::find_if( m_busAliases.begin(), m_busAliases.end(), sameDefinition );
if( it != m_busAliases.end() )
return;
m_busAliases.push_back( aAlias );
updateProjectBusAliases();
}
void SCHEMATIC::SetBusAliases( const std::vector<std::shared_ptr<BUS_ALIAS>>& aAliases )
{
m_busAliases.clear();
for( const std::shared_ptr<BUS_ALIAS>& alias : aAliases )
{
if( !alias )
continue;
std::shared_ptr<BUS_ALIAS> clone = alias->Clone();
auto sameDefinition = [&]( const std::shared_ptr<BUS_ALIAS>& candidate ) -> bool
{
return candidate && candidate->GetName() == clone->GetName()
&& candidate->Members() == clone->Members();
};
if( std::find_if( m_busAliases.begin(), m_busAliases.end(), sameDefinition ) != m_busAliases.end() )
continue;
m_busAliases.push_back( clone );
}
updateProjectBusAliases();
}
void SCHEMATIC::loadBusAliasesFromProject()
{
m_busAliases.clear();
if( !m_project )
return;
const auto& projectAliases = m_project->GetProjectFile().m_BusAliases;
for( const auto& alias : projectAliases )
{
std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>();
busAlias->SetName( alias.first );
busAlias->Members() = alias.second;
m_busAliases.push_back( busAlias );
}
}
void SCHEMATIC::updateProjectBusAliases()
{
if( !m_project )
return;
auto& projectAliases = m_project->GetProjectFile().m_BusAliases;
projectAliases.clear();
std::set<wxString> seen;
for( const std::shared_ptr<BUS_ALIAS>& alias : m_busAliases )
{
if( !alias )
continue;
if( !seen.insert( alias->GetName() ).second )
continue;
projectAliases.emplace( alias->GetName(), alias->Members() );
}
}
std::set<wxString> SCHEMATIC::GetNetClassAssignmentCandidates()
{
std::set<wxString> names;

15
eeschema/schematic.h

@ -200,6 +200,15 @@ public:
*/
std::shared_ptr<BUS_ALIAS> GetBusAlias( const wxString& aLabel ) const;
void AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias );
void SetBusAliases( const std::vector<std::shared_ptr<BUS_ALIAS>>& aAliases );
const std::vector<std::shared_ptr<BUS_ALIAS>>& GetAllBusAliases() const
{
return m_busAliases;
}
/**
* Return the set of netname candidates for netclass assignment.
*
@ -481,6 +490,12 @@ private:
* What currently "Holds" the schematic, i.e. a edit frame if available
*/
SCHEMATIC_HOLDER* m_schematicHolder;
void loadBusAliasesFromProject();
void updateProjectBusAliases();
std::vector<std::shared_ptr<BUS_ALIAS>> m_busAliases;
};
#endif

3
include/project/project_file.h

@ -155,6 +155,9 @@ public:
wxArrayString m_LegacyLibNames;
/// Bus alias definitions for the schematic project
std::map<wxString, std::vector<wxString>> m_BusAliases;
/**
* CvPcb params
*/

2
qa/tests/eeschema/erc/test_erc_global_labels.cpp

@ -69,7 +69,6 @@ BOOST_FIXTURE_TEST_CASE( ERCGlobalLabels, ERC_REGRESSION_TEST_FIXTURE )
m_schematic->ConnectionGraph()->RunERC();
ERC_TESTER tester( m_schematic.get() );
tester.TestConflictingBusAliases();
tester.TestMultUnitPinConflicts();
tester.TestMultiunitFootprints();
tester.TestNoConnectPins();
@ -120,7 +119,6 @@ BOOST_FIXTURE_TEST_CASE( ERCSingleGlobalLabels, ERC_REGRESSION_TEST_FIXTURE )
m_schematic->ConnectionGraph()->RunERC();
ERC_TESTER tester( m_schematic.get() );
tester.TestConflictingBusAliases();
tester.TestMultUnitPinConflicts();
tester.TestMultiunitFootprints();
tester.TestNoConnectPins();

1
qa/tests/eeschema/erc/test_erc_ground_pins.cpp

@ -407,7 +407,6 @@ BOOST_FIXTURE_TEST_CASE( ERCGroundPinComprehensive, ERC_GROUND_PIN_TEST_FIXTURE
ERC_TESTER tester( m_schematic.get() );
// Run all ERC tests to ensure ground pin test integrates properly
tester.TestConflictingBusAliases();
tester.TestMultUnitPinConflicts();
tester.TestMultiunitFootprints();
tester.TestMissingUnits();

1
qa/tests/eeschema/erc/test_erc_hierarchical_schematics.cpp

@ -66,7 +66,6 @@ BOOST_FIXTURE_TEST_CASE( ERCHierarchicalSchematics, ERC_REGRESSION_TEST_FIXTURE
m_schematic->ConnectionGraph()->RunERC();
ERC_TESTER tester( m_schematic.get() );
tester.TestConflictingBusAliases();
tester.TestMultUnitPinConflicts();
tester.TestMultiunitFootprints();
tester.TestNoConnectPins();

1
qa/tests/eeschema/erc/test_erc_label_not_connected.cpp

@ -70,7 +70,6 @@ BOOST_FIXTURE_TEST_CASE( ERCLabelNotConnected, ERC_REGRESSION_TEST_FIXTURE )
m_schematic->ConnectionGraph()->RunERC();
ERC_TESTER tester( m_schematic.get() );
tester.TestConflictingBusAliases();
tester.TestMultUnitPinConflicts();
tester.TestMultiunitFootprints();
tester.TestNoConnectPins();

1
qa/tests/eeschema/erc/test_erc_multiple_pin_to_pin.cpp

@ -59,7 +59,6 @@ BOOST_FIXTURE_TEST_CASE( ERCMultiplePinToPin, ERC_REGRESSION_TEST_FIXTURE )
m_schematic->ConnectionGraph()->RunERC();
ERC_TESTER tester( m_schematic.get() );
tester.TestConflictingBusAliases();
tester.TestMultUnitPinConflicts();
tester.TestMultiunitFootprints();
tester.TestNoConnectPins();

1
qa/tests/eeschema/erc/test_erc_no_connect.cpp

@ -72,7 +72,6 @@ BOOST_FIXTURE_TEST_CASE( ERCNoConnect, ERC_REGRESSION_TEST_FIXTURE )
m_schematic->ConnectionGraph()->RunERC();
ERC_TESTER tester( m_schematic.get() );
tester.TestConflictingBusAliases();
tester.TestMultUnitPinConflicts();
tester.TestMultiunitFootprints();
tester.TestNoConnectPins();

1
qa/tests/eeschema/erc/test_erc_stacking_pins.cpp

@ -63,7 +63,6 @@ BOOST_FIXTURE_TEST_CASE( ERCStackingPins, ERC_REGRESSION_TEST_FIXTURE )
m_schematic->ConnectionGraph()->RunERC();
ERC_TESTER tester( m_schematic.get() );
tester.TestConflictingBusAliases();
tester.TestMultUnitPinConflicts();
tester.TestMultiunitFootprints();
tester.TestNoConnectPins();

Loading…
Cancel
Save