More safety around ratsnest state.

Fixes https://gitlab.com/kicad/code/kicad/issues/13011
This commit is contained in:
Jeff Young 2022-11-30 12:18:58 +00:00
parent 9fa8b9e49f
commit 19eab62516
14 changed files with 51 additions and 42 deletions

View File

@ -397,6 +397,8 @@ protected:
virtual void unitsChangeRefresh() override;
void rebuildConnectivity();
protected:
BOARD* m_pcb;
PCB_DISPLAY_OPTIONS m_displayOptions;

View File

@ -175,6 +175,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
if( Empty() )
return;
std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity();
// Note:
// frame == nullptr happens in QA tests
// in this case m_isBoardEditor and m_isFootprintEditor are set to false
@ -448,8 +450,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
if( !( aCommitFlags & SKIP_CONNECTIVITY ) )
{
std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity();
if( ent.m_copy )
connectivity->MarkItemNetAsDirty( static_cast<BOARD_ITEM*>( ent.m_copy ) );
@ -504,24 +504,28 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
{
size_t num_changes = m_changes.size();
if( !( aCommitFlags & SKIP_CONNECTIVITY ) )
if( aCommitFlags & SKIP_CONNECTIVITY )
{
connectivity->ClearRatsnest();
connectivity->ClearLocalRatsnest();
}
else
{
std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity();
if( m_resolveNetConflicts )
connectivity->PropagateNets( this, PROPAGATE_MODE::RESOLVE_CONFLICTS );
connectivity->RecalculateRatsnest( this );
board->UpdateRatsnestExclusions();
connectivity->ClearLocalRatsnest();
if( frame )
frame->GetCanvas()->RedrawRatsnest();
}
if( frame )
if( solderMaskDirty )
{
if( solderMaskDirty )
if( frame )
frame->HideSolderMask();
frame->GetCanvas()->RedrawRatsnest();
}
// Log undo items for any connectivity changes

View File

@ -63,7 +63,10 @@ CONNECTIVITY_DATA::CONNECTIVITY_DATA( const std::vector<BOARD_ITEM*>& aItems, bo
CONNECTIVITY_DATA::~CONNECTIVITY_DATA()
{
Clear();
for( RN_NET* net : m_nets )
delete net;
m_nets.clear();
}
@ -494,12 +497,10 @@ unsigned int CONNECTIVITY_DATA::GetUnconnectedCount( bool aVisibleOnly ) const
}
void CONNECTIVITY_DATA::Clear()
void CONNECTIVITY_DATA::ClearRatsnest()
{
for( RN_NET* net : m_nets )
delete net;
m_nets.clear();
net->Clear();
}

View File

@ -154,7 +154,7 @@ public:
* Function Clear()
* Erases the connectivity database.
*/
void Clear();
void ClearRatsnest();
/**
* Function GetNetCount()

View File

@ -83,7 +83,7 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
}
// Rebuild (from scratch, ignoring dirty flags) just in case. This really needs to be reliable.
connectivity->Clear();
connectivity->ClearRatsnest();
connectivity->Build( board, m_drcEngine->GetProgressReporter() );
connectivity->FindIsolatedCopperIslands( islandsList, true );

View File

@ -104,8 +104,7 @@ void PCB_EDIT_FRAME::Edit_Zone_Params( ZONE* aZone )
commit.Stage( pickedList );
commit.Push( _( "Modify zone properties" ), SKIP_CONNECTIVITY );
GetBoard()->BuildConnectivity();
GetToolManager()->PostEvent( EVENTS::ConnectivityChangedEvent );
rebuildConnectivity();
pickedList.ClearItemsList(); // s_ItemsListPicker is no longer owner of picked items
}

View File

@ -987,8 +987,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
if( filler.Fill( toFill ) )
commit.Push( _( "Convert Zone(s)" ), SKIP_CONNECTIVITY );
GetBoard()->BuildConnectivity( &progressReporter );
GetToolManager()->PostEvent( EVENTS::ConnectivityChangedEvent );
rebuildConnectivity();
}
// from EDA_APPL which was first loaded BOARD only:

View File

@ -1006,6 +1006,14 @@ void PCB_BASE_FRAME::OnModify()
}
void PCB_BASE_FRAME::rebuildConnectivity()
{
GetBoard()->BuildConnectivity();
GetToolManager()->PostEvent( EVENTS::ConnectivityChangedEvent );
GetCanvas()->RedrawRatsnest();
}
PCB_DRAW_PANEL_GAL* PCB_BASE_FRAME::GetCanvas() const
{
return static_cast<PCB_DRAW_PANEL_GAL*>( EDA_DRAW_FRAME::GetCanvas() );

View File

@ -980,7 +980,7 @@ void PCB_EDIT_FRAME::ResolveDRCExclusions()
commit.Add( marker );
}
commit.Push( wxEmptyString, SKIP_UNDO | SKIP_SET_DIRTY | SKIP_CONNECTIVITY );
commit.Push( wxEmptyString, SKIP_UNDO | SKIP_SET_DIRTY );
for( PCB_MARKER* marker : GetBoard()->Markers() )
{

View File

@ -64,11 +64,6 @@ class RN_NET
public:
RN_NET();
/**
* Mark ratsnest for given net as 'dirty', i.e. requiring recomputation.
*/
void MarkDirty() { m_dirty = true; }
/**
* Return state of the 'dirty' flag, indicating that ratsnest for a given net is invalid
* and requires an update.

View File

@ -81,7 +81,7 @@ bool PCB_EDIT_FRAME::ImportSpecctraSession( const wxString& fullFileName )
return false;
}
GetBoard()->GetConnectivity()->Clear();
GetBoard()->GetConnectivity()->ClearRatsnest();
GetBoard()->BuildConnectivity();
OnModify();

View File

@ -97,9 +97,7 @@ void ZONE_FILLER_TOOL::CheckAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aRep
commit.Revert();
}
board()->BuildConnectivity();
m_toolMgr->PostEvent( EVENTS::ConnectivityChangedEvent );
rebuildConnectivity();
refresh();
m_fillInProgress = false;
@ -174,14 +172,12 @@ void ZONE_FILLER_TOOL::FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aRepo
commit.Revert();
}
board()->BuildConnectivity( reporter.get() );
m_toolMgr->PostEvent( EVENTS::ConnectivityChangedEvent );
rebuildConnectivity();
refresh();
if( filler.IsDebug() )
frame->UpdateUserInterface();
refresh();
m_fillInProgress = false;
// wxWidgets has keyboard focus issues after the progress reporter. Re-setting the focus
@ -259,8 +255,8 @@ int ZONE_FILLER_TOOL::ZoneFillDirty( const TOOL_EVENT& aEvent )
else
commit.Revert();
board()->BuildConnectivity( reporter.get() );
m_toolMgr->PostEvent( EVENTS::ConnectivityChangedEvent );
rebuildConnectivity();
refresh();
if( GetRunningMicroSecs() - startTime > 1000000 )
{
@ -286,8 +282,6 @@ int ZONE_FILLER_TOOL::ZoneFillDirty( const TOOL_EVENT& aEvent )
if( filler.IsDebug() )
frame->UpdateUserInterface();
refresh();
m_fillInProgress = false;
// wxWidgets has keyboard focus issues after the progress reporter. Re-setting the focus
@ -340,9 +334,7 @@ int ZONE_FILLER_TOOL::ZoneFill( const TOOL_EVENT& aEvent )
commit.Revert();
}
board()->BuildConnectivity( reporter.get() );
m_toolMgr->PostEvent( EVENTS::ConnectivityChangedEvent );
rebuildConnectivity();
refresh();
m_fillInProgress = false;
@ -399,6 +391,14 @@ int ZONE_FILLER_TOOL::ZoneUnfillAll( const TOOL_EVENT& aEvent )
}
void ZONE_FILLER_TOOL::rebuildConnectivity()
{
board()->BuildConnectivity();
m_toolMgr->PostEvent( EVENTS::ConnectivityChangedEvent );
canvas()->RedrawRatsnest();
}
void ZONE_FILLER_TOOL::refresh()
{
canvas()->GetView()->UpdateAllItemsConditionally( KIGFX::REPAINT,

View File

@ -70,6 +70,7 @@ private:
///< Refocus on an idle event (used after the Progress Reporter messes up the focus).
void singleShotRefocus( wxIdleEvent& );
void rebuildConnectivity();
void refresh();
///< Set up handlers for various events.

View File

@ -97,7 +97,7 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
// Rebuild (from scratch, ignoring dirty flags) just in case. This really needs to be reliable.
connectivity->Clear();
connectivity->ClearRatsnest();
connectivity->Build( m_board, m_progressReporter );
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();