Split part of RecalculateConnections to SCHEMATIC, fix cli loader to call RecalculateConnections which fixes rules areas

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20528
This commit is contained in:
Marek Roszko 2025-06-05 20:15:51 -04:00 committed by Mark Roszko
parent e95ae05dcf
commit e29df06568
5 changed files with 324 additions and 268 deletions

View File

@ -26,12 +26,15 @@
#include <connection_graph.h>
#include <locale_io.h>
#include <schematic.h>
#include <sch_commit.h>
#include <sch_edit_frame.h>
#include <sch_label.h>
#include <sch_io/sch_io.h>
#include <sch_io/sch_io_mgr.h>
#include <settings/settings_manager.h>
#include <wildcards_and_files_ext.h>
#include <tool/tool_manager.h>
#include <kiface_base.h>
#include <wx/app.h>
@ -189,6 +192,21 @@ SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( const wxString& aFileName,
schematic->ConnectionGraph()->Reset();
TOOL_MANAGER* toolManager = new TOOL_MANAGER;
toolManager->SetEnvironment( schematic, nullptr, nullptr, Kiface().KifaceSettings(), nullptr );
SCH_COMMIT dummyCommit( toolManager );
schematic->RecalculateConnections( &dummyCommit, GLOBAL_CLEANUP, toolManager,
[&]( SCH_GLOBALLABEL* label )
{
for( SCH_FIELD& field : label->GetFields() )
field.ClearBoundingBoxCache();
label->ClearBoundingBoxCache();
} );
schematic->ResolveERCExclusionsPostUpdate();
schematic->SetSheetNumberAndCount();
schematic->RecomputeIntersheetRefs( []( SCH_GLOBALLABEL* aGlobal )
{

View File

@ -1768,31 +1768,6 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FL
{
wxString highlightedConn = GetHighlightedConnection();
bool hasHighlightedConn = !highlightedConn.IsEmpty();
SCHEMATIC_SETTINGS& settings = Schematic().Settings();
SCH_SHEET_LIST list = Schematic().Hierarchy();
SCH_COMMIT localCommit( m_toolManager );
if( !aCommit )
aCommit = &localCommit;
PROF_TIMER timer;
// Ensure schematic graph is accurate
if( aCleanupFlags == LOCAL_CLEANUP )
{
Schematic().CleanUp( aCommit, GetScreen() );
}
else if( aCleanupFlags == GLOBAL_CLEANUP )
{
for( const SCH_SHEET_PATH& sheet : list )
Schematic().CleanUp( aCommit, sheet.LastScreen() );
}
timer.Stop();
wxLogTrace( "CONN_PROFILE", "SchematicCleanUp() %0.4f ms", timer.msecs() );
if( settings.m_IntersheetRefsShow )
RecomputeIntersheetRefs();
std::function<void( SCH_ITEM* )> changeHandler =
[&]( SCH_ITEM* aChangedItem ) -> void
@ -1818,239 +1793,19 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FL
}
};
if( !ADVANCED_CFG::GetCfg().m_IncrementalConnectivity || aCleanupFlags == GLOBAL_CLEANUP
|| m_undoList.m_CommandsList.empty()|| Schematic().ConnectionGraph()->IsMinor() )
{
// Clear all resolved netclass caches in case labels have changed
Prj().GetProjectFile().NetSettings()->ClearAllCaches();
// Update all rule areas so we can cascade implied connectivity changes
std::unordered_set<SCH_SCREEN*> all_screens;
for( const SCH_SHEET_PATH& path : list )
all_screens.insert( path.LastScreen() );
SCH_RULE_AREA::UpdateRuleAreasInScreens( all_screens, GetCanvas()->GetView() );
// Recalculate all connectivity
Schematic().ConnectionGraph()->Recalculate( list, true, &changeHandler );
}
else
{
struct CHANGED_ITEM
{
SCH_ITEM* item;
SCH_ITEM* linked_item;
SCH_SCREEN* screen;
};
PICKED_ITEMS_LIST* changed_list = m_undoList.m_CommandsList.back();
// Final change sets
std::set<SCH_ITEM*> changed_items;
std::set<VECTOR2I> pts;
std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> item_paths;
// Working change sets
std::unordered_set<SCH_SCREEN*> changed_screens;
std::set<std::pair<SCH_RULE_AREA*, SCH_SCREEN*>> changed_rule_areas;
std::vector<CHANGED_ITEM> changed_connectable_items;
// Lambda to add an item to the connectivity update sets
auto addItemToChangeSet = [&changed_items, &pts, &item_paths]( CHANGED_ITEM itemData )
{
std::vector<SCH_SHEET_PATH>& paths = itemData.screen->GetClientSheetPaths();
std::vector<VECTOR2I> tmp_pts = itemData.item->GetConnectionPoints();
pts.insert( tmp_pts.begin(), tmp_pts.end() );
changed_items.insert( itemData.item );
for( SCH_SHEET_PATH& path : paths )
item_paths.insert( std::make_pair( path, itemData.item ) );
if( !itemData.linked_item || !itemData.linked_item->IsConnectable() )
return;
tmp_pts = itemData.linked_item->GetConnectionPoints();
pts.insert( tmp_pts.begin(), tmp_pts.end() );
changed_items.insert( itemData.linked_item );
// We have to directly add the pins here because the link may not exist on the schematic
// anymore and so won't be picked up by GetScreen()->Items().Overlapping() below.
if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( itemData.linked_item ) )
Schematic().RecalculateConnections(
aCommit, aCleanupFlags, m_toolManager,
[&]( SCH_GLOBALLABEL* label )
{
std::vector<SCH_PIN*> pins = symbol->GetPins();
changed_items.insert( pins.begin(), pins.end() );
}
for( SCH_FIELD& field : label->GetFields() )
field.ClearBoundingBoxCache();
for( SCH_SHEET_PATH& path : paths )
item_paths.insert( std::make_pair( path, itemData.linked_item ) );
};
// Get all changed connectable items and determine all changed screens
for( unsigned ii = 0; ii < changed_list->GetCount(); ++ii )
{
switch( changed_list->GetPickedItemStatus( ii ) )
{
// Only care about changed, new, and deleted items, the other
// cases are not connectivity-related
case UNDO_REDO::CHANGED:
case UNDO_REDO::NEWITEM:
case UNDO_REDO::DELETED:
break;
default:
continue;
}
SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( changed_list->GetPickedItem( ii ) );
if( item )
{
SCH_SCREEN* screen =
static_cast<SCH_SCREEN*>( changed_list->GetScreenForItem( ii ) );
changed_screens.insert( screen );
if( item->Type() == SCH_RULE_AREA_T )
{
SCH_RULE_AREA* ruleArea = static_cast<SCH_RULE_AREA*>( item );
// Clear item and directive associations for this rule area
ruleArea->ResetDirectivesAndItems( GetCanvas()->GetView() );
changed_rule_areas.insert( { ruleArea, screen } );
}
else if( item->IsConnectable() )
{
SCH_ITEM* linked_item =
dynamic_cast<SCH_ITEM*>( changed_list->GetPickedItemLink( ii ) );
changed_connectable_items.push_back( { item, linked_item, screen } );
}
}
}
// Update rule areas in changed screens to propagate any directive connectivity changes
std::vector<std::pair<SCH_RULE_AREA*, SCH_SCREEN*>> forceUpdateRuleAreas =
SCH_RULE_AREA::UpdateRuleAreasInScreens( changed_screens, GetCanvas()->GetView() );
std::for_each( forceUpdateRuleAreas.begin(), forceUpdateRuleAreas.end(),
[&]( std::pair<SCH_RULE_AREA*, SCH_SCREEN*>& updatedRuleArea )
{
changed_rule_areas.insert( updatedRuleArea );
} );
// If a SCH_RULE_AREA was changed, we need to add all past and present contained items to
// update their connectivity
for( const std::pair<SCH_RULE_AREA*, SCH_SCREEN*>& changedRuleArea : changed_rule_areas )
{
for( SCH_ITEM* containedItem :
changedRuleArea.first->GetPastAndPresentContainedItems() )
{
addItemToChangeSet( { containedItem, nullptr, changedRuleArea.second } );
}
}
// Add all changed items, and associated items, to the change set
for( CHANGED_ITEM& changed_item_data : changed_connectable_items )
{
addItemToChangeSet( changed_item_data );
// If a SCH_DIRECTIVE_LABEL was changed which is attached to a SCH_RULE_AREA, we need
// to add the contained items to the change set to force update of their connectivity
if( changed_item_data.item->Type() == SCH_DIRECTIVE_LABEL_T )
{
const std::vector<VECTOR2I> labelConnectionPoints =
changed_item_data.item->GetConnectionPoints();
EE_RTREE::EE_TYPE candidateRuleAreas =
changed_item_data.screen->Items().Overlapping(
SCH_RULE_AREA_T, changed_item_data.item->GetBoundingBox() );
for( SCH_ITEM* candidateRuleArea : candidateRuleAreas )
{
SCH_RULE_AREA* ruleArea = static_cast<SCH_RULE_AREA*>( candidateRuleArea );
std::vector<SHAPE*> borderShapes = ruleArea->MakeEffectiveShapes( true );
if( ruleArea->GetPolyShape().CollideEdge( labelConnectionPoints[0], nullptr,
5 ) )
{
for( SCH_ITEM* containedItem : ruleArea->GetPastAndPresentContainedItems() )
addItemToChangeSet(
{ containedItem, nullptr, changed_item_data.screen } );
}
}
}
}
for( const VECTOR2I& pt: pts )
{
for( SCH_ITEM* item : GetScreen()->Items().Overlapping( pt ) )
{
// Leave this check in place. Overlapping items are not necessarily connectable.
if( !item->IsConnectable() )
continue;
if( item->Type() == SCH_LINE_T )
{
if( item->HitTest( pt ) )
changed_items.insert( item );
}
else if( item->Type() == SCH_SYMBOL_T && item->IsConnected( pt ) )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
std::vector<SCH_PIN*> pins = symbol->GetPins();
changed_items.insert( pins.begin(), pins.end() );
}
else if( item->Type() == SCH_SHEET_T )
{
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
wxCHECK2( sheet, continue );
std::vector<SCH_SHEET_PIN*> sheetPins = sheet->GetPins();
changed_items.insert( sheetPins.begin(), sheetPins.end() );
}
else
{
if( item->IsConnected( pt ) )
changed_items.insert( item );
}
}
}
std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> all_items =
Schematic().ConnectionGraph()->ExtractAffectedItems( changed_items );
all_items.insert( item_paths.begin(), item_paths.end() );
CONNECTION_GRAPH new_graph( &Schematic() );
new_graph.SetLastCodes( Schematic().ConnectionGraph() );
std::shared_ptr<NET_SETTINGS> netSettings = Prj().GetProjectFile().NetSettings();
std::set<wxString> affectedNets;
for( auto&[ path, item ] : all_items )
{
wxCHECK2( item, continue );
item->SetConnectivityDirty();
SCH_CONNECTION* conn = item->Connection();
if( conn )
{
affectedNets.insert( conn->Name() );
}
}
// Reset resolved netclass cache for this connection
for( const wxString& netName : affectedNets )
netSettings->ClearCacheForNet( netName );
new_graph.Recalculate( list, false, &changeHandler );
Schematic().ConnectionGraph()->Merge( new_graph );
}
label->ClearBoundingBoxCache();
GetCanvas()->GetView()->Update( label );
},
GetCanvas()->GetView(),
&changeHandler,
m_undoList.m_CommandsList.empty() ? nullptr : m_undoList.m_CommandsList.back() );
GetCanvas()->GetView()->UpdateAllItemsConditionally(
[&]( KIGFX::VIEW_ITEM* aItem ) -> int
@ -2102,9 +1857,6 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FL
RefreshNetNavigator();
m_highlightedConnChanged = false;
}
if( !localCommit.Empty() )
localCommit.Push( _( "Schematic Cleanup" ) );
}

View File

@ -76,14 +76,6 @@ enum SCH_SEARCH_T
};
enum SCH_CLEANUP_FLAGS
{
NO_CLEANUP,
LOCAL_CLEANUP,
GLOBAL_CLEANUP
};
wxDECLARE_EVENT( EDA_EVT_SCHEMATIC_CHANGING, wxCommandEvent );
wxDECLARE_EVENT( EDA_EVT_SCHEMATIC_CHANGED, wxCommandEvent );

View File

@ -22,10 +22,12 @@
#include <connection_graph.h>
#include <core/ignore.h>
#include <core/kicad_algo.h>
#include <core/profile.h>
#include <sch_collectors.h>
#include <erc/erc_settings.h>
#include <font/outline_font.h>
#include <netlist_exporter_spice.h>
#include <progress_reporter.h>
#include <project.h>
#include <project/net_settings.h>
#include <project/project_file.h>
@ -37,10 +39,14 @@
#include <sch_line.h>
#include <sch_marker.h>
#include <sch_no_connect.h>
#include <sch_rule_area.h>
#include <sch_screen.h>
#include <sch_sheet_pin.h>
#include <sch_selection_tool.h>
#include <sim/spice_settings.h>
#include <sim/spice_value.h>
#include <tool/tool_manager.h>
#include <undo_redo_container.h>
#include <wx/log.h>
@ -1069,7 +1075,7 @@ bool SCHEMATIC::BreakSegmentsOnJunctions( SCH_COMMIT* aCommit, SCH_SCREEN* aScre
void SCHEMATIC::CleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen )
{
SCH_SELECTION_TOOL* selectionTool = m_schematicHolder->GetSelectionTool();
SCH_SELECTION_TOOL* selectionTool = m_schematicHolder ? m_schematicHolder->GetSelectionTool() : nullptr;
std::vector<SCH_LINE*> lines;
std::vector<SCH_JUNCTION*> junctions;
std::vector<SCH_NO_CONNECT*> ncs;
@ -1255,4 +1261,267 @@ void SCHEMATIC::CleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen )
}
}
}
}
void SCHEMATIC::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FLAGS aCleanupFlags,
TOOL_MANAGER* aToolManager,
const std::function<void( SCH_GLOBALLABEL* )>& aIntersheetRefItemCallback,
KIGFX::SCH_VIEW* aSchView,
std::function<void( SCH_ITEM* )>* aChangedItemHandler,
PICKED_ITEMS_LIST* aLastChangeList )
{
SCHEMATIC_SETTINGS& settings = Settings();
SCH_SHEET_LIST list = Hierarchy();
SCH_COMMIT localCommit( aToolManager );
if( !aCommit )
aCommit = &localCommit;
PROF_TIMER timer;
// Ensure schematic graph is accurate
if( aCleanupFlags == LOCAL_CLEANUP )
{
CleanUp( aCommit, GetCurrentScreen() );
}
else if( aCleanupFlags == GLOBAL_CLEANUP )
{
for( const SCH_SHEET_PATH& sheet : list )
CleanUp( aCommit, sheet.LastScreen() );
}
timer.Stop();
wxLogTrace( "CONN_PROFILE", "SchematicCleanUp() %0.4f ms", timer.msecs() );
if( settings.m_IntersheetRefsShow )
RecomputeIntersheetRefs( aIntersheetRefItemCallback );
if( !ADVANCED_CFG::GetCfg().m_IncrementalConnectivity
|| aCleanupFlags == GLOBAL_CLEANUP
|| aLastChangeList == nullptr
|| ConnectionGraph()->IsMinor() )
{
// Clear all resolved netclass caches in case labels have changed
Prj().GetProjectFile().NetSettings()->ClearAllCaches();
// Update all rule areas so we can cascade implied connectivity changes
std::unordered_set<SCH_SCREEN*> all_screens;
for( const SCH_SHEET_PATH& path : list )
all_screens.insert( path.LastScreen() );
SCH_RULE_AREA::UpdateRuleAreasInScreens( all_screens, aSchView );
// Recalculate all connectivity
ConnectionGraph()->Recalculate( list, true, aChangedItemHandler );
}
else
{
struct CHANGED_ITEM
{
SCH_ITEM* item;
SCH_ITEM* linked_item;
SCH_SCREEN* screen;
};
// Final change sets
std::set<SCH_ITEM*> changed_items;
std::set<VECTOR2I> pts;
std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> item_paths;
// Working change sets
std::unordered_set<SCH_SCREEN*> changed_screens;
std::set<std::pair<SCH_RULE_AREA*, SCH_SCREEN*>> changed_rule_areas;
std::vector<CHANGED_ITEM> changed_connectable_items;
// Lambda to add an item to the connectivity update sets
auto addItemToChangeSet = [&changed_items, &pts, &item_paths]( CHANGED_ITEM itemData )
{
std::vector<SCH_SHEET_PATH>& paths = itemData.screen->GetClientSheetPaths();
std::vector<VECTOR2I> tmp_pts = itemData.item->GetConnectionPoints();
pts.insert( tmp_pts.begin(), tmp_pts.end() );
changed_items.insert( itemData.item );
for( SCH_SHEET_PATH& path : paths )
item_paths.insert( std::make_pair( path, itemData.item ) );
if( !itemData.linked_item || !itemData.linked_item->IsConnectable() )
return;
tmp_pts = itemData.linked_item->GetConnectionPoints();
pts.insert( tmp_pts.begin(), tmp_pts.end() );
changed_items.insert( itemData.linked_item );
// We have to directly add the pins here because the link may not exist on the schematic
// anymore and so won't be picked up by GetScreen()->Items().Overlapping() below.
if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( itemData.linked_item ) )
{
std::vector<SCH_PIN*> pins = symbol->GetPins();
changed_items.insert( pins.begin(), pins.end() );
}
for( SCH_SHEET_PATH& path : paths )
item_paths.insert( std::make_pair( path, itemData.linked_item ) );
};
// Get all changed connectable items and determine all changed screens
for( unsigned ii = 0; ii < aLastChangeList->GetCount(); ++ii )
{
switch( aLastChangeList->GetPickedItemStatus( ii ) )
{
// Only care about changed, new, and deleted items, the other
// cases are not connectivity-related
case UNDO_REDO::CHANGED:
case UNDO_REDO::NEWITEM:
case UNDO_REDO::DELETED:
break;
default:
continue;
}
SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aLastChangeList->GetPickedItem( ii ) );
if( item )
{
SCH_SCREEN* screen = static_cast<SCH_SCREEN*>( aLastChangeList->GetScreenForItem( ii ) );
changed_screens.insert( screen );
if( item->Type() == SCH_RULE_AREA_T )
{
SCH_RULE_AREA* ruleArea = static_cast<SCH_RULE_AREA*>( item );
// Clear item and directive associations for this rule area
ruleArea->ResetDirectivesAndItems( aSchView );
changed_rule_areas.insert( { ruleArea, screen } );
}
else if( item->IsConnectable() )
{
SCH_ITEM* linked_item = dynamic_cast<SCH_ITEM*>( aLastChangeList->GetPickedItemLink( ii ) );
changed_connectable_items.push_back( { item, linked_item, screen } );
}
}
}
// Update rule areas in changed screens to propagate any directive connectivity changes
std::vector<std::pair<SCH_RULE_AREA*, SCH_SCREEN*>> forceUpdateRuleAreas =
SCH_RULE_AREA::UpdateRuleAreasInScreens( changed_screens, aSchView );
std::for_each( forceUpdateRuleAreas.begin(), forceUpdateRuleAreas.end(),
[&]( std::pair<SCH_RULE_AREA*, SCH_SCREEN*>& updatedRuleArea )
{
changed_rule_areas.insert( updatedRuleArea );
} );
// If a SCH_RULE_AREA was changed, we need to add all past and present contained items to
// update their connectivity
for( const std::pair<SCH_RULE_AREA*, SCH_SCREEN*>& changedRuleArea : changed_rule_areas )
{
for( SCH_ITEM* containedItem : changedRuleArea.first->GetPastAndPresentContainedItems() )
addItemToChangeSet( { containedItem, nullptr, changedRuleArea.second } );
}
// Add all changed items, and associated items, to the change set
for( CHANGED_ITEM& changed_item_data : changed_connectable_items )
{
addItemToChangeSet( changed_item_data );
// If a SCH_DIRECTIVE_LABEL was changed which is attached to a SCH_RULE_AREA, we need
// to add the contained items to the change set to force update of their connectivity
if( changed_item_data.item->Type() == SCH_DIRECTIVE_LABEL_T )
{
const std::vector<VECTOR2I> labelConnectionPoints =
changed_item_data.item->GetConnectionPoints();
auto candidateRuleAreas =
changed_item_data.screen->Items().Overlapping( SCH_RULE_AREA_T,
changed_item_data.item->GetBoundingBox() );
for( SCH_ITEM* candidateRuleArea : candidateRuleAreas )
{
SCH_RULE_AREA* ruleArea = static_cast<SCH_RULE_AREA*>( candidateRuleArea );
std::vector<SHAPE*> borderShapes = ruleArea->MakeEffectiveShapes( true );
if( ruleArea->GetPolyShape().CollideEdge( labelConnectionPoints[0], nullptr, 5 ) )
{
for( SCH_ITEM* containedItem : ruleArea->GetPastAndPresentContainedItems() )
addItemToChangeSet( { containedItem, nullptr, changed_item_data.screen } );
}
}
}
}
for( const VECTOR2I& pt: pts )
{
for( SCH_ITEM* item : GetCurrentScreen()->Items().Overlapping( pt ) )
{
// Leave this check in place. Overlapping items are not necessarily connectable.
if( !item->IsConnectable() )
continue;
if( item->Type() == SCH_LINE_T )
{
if( item->HitTest( pt ) )
changed_items.insert( item );
}
else if( item->Type() == SCH_SYMBOL_T && item->IsConnected( pt ) )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
std::vector<SCH_PIN*> pins = symbol->GetPins();
changed_items.insert( pins.begin(), pins.end() );
}
else if( item->Type() == SCH_SHEET_T )
{
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
wxCHECK2( sheet, continue );
std::vector<SCH_SHEET_PIN*> sheetPins = sheet->GetPins();
changed_items.insert( sheetPins.begin(), sheetPins.end() );
}
else
{
if( item->IsConnected( pt ) )
changed_items.insert( item );
}
}
}
std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> all_items =
ConnectionGraph()->ExtractAffectedItems( changed_items );
all_items.insert( item_paths.begin(), item_paths.end() );
CONNECTION_GRAPH new_graph( this );
new_graph.SetLastCodes( ConnectionGraph() );
std::shared_ptr<NET_SETTINGS> netSettings = Prj().GetProjectFile().NetSettings();
std::set<wxString> affectedNets;
for( auto&[ path, item ] : all_items )
{
wxCHECK2( item, continue );
item->SetConnectivityDirty();
SCH_CONNECTION* conn = item->Connection();
if( conn )
affectedNets.insert( conn->Name() );
}
// Reset resolved netclass cache for this connection
for( const wxString& netName : affectedNets )
netSettings->ClearCacheForNet( netName );
new_graph.Recalculate( list, false, aChangedItemHandler );
ConnectionGraph()->Merge( new_graph );
}
if( !localCommit.Empty() )
localCommit.Push( _( "Schematic Cleanup" ) );
}

View File

@ -38,12 +38,20 @@ class SCH_SCREEN;
class SCH_SHEET;
class SCH_SHEET_LIST;
class SCH_GLOBALLABEL;
class PROGRESS_REPORTER;
class TOOL_MANAGER;
class PICKED_ITEMS_LIST;
namespace KIFONT
{
class OUTLINE_FONT;
}
namespace KIGFX
{
class SCH_VIEW;
}
class SCHEMATIC;
@ -60,6 +68,13 @@ public:
virtual void OnSchSheetChanged( SCHEMATIC& aSch ) {}
};
enum SCH_CLEANUP_FLAGS
{
NO_CLEANUP,
LOCAL_CLEANUP,
GLOBAL_CLEANUP
};
/**
* Holds all the data relating to one schematic.
*
@ -397,6 +412,16 @@ public:
*/
void CleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen = nullptr );
/**
* Generate the connection data for the entire schematic hierarchy.
*/
void RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FLAGS aCleanupFlags,
TOOL_MANAGER* aToolManager,
const std::function<void( SCH_GLOBALLABEL* )>& aIntersheetRefItemCallback,
KIGFX::SCH_VIEW* aSchView = nullptr,
std::function<void( SCH_ITEM* )>* aChangedItemHandler = nullptr,
PICKED_ITEMS_LIST* aLastChangeList = nullptr );
/**
* True if a SCHEMATIC exists, false if not
*/