diff --git a/pcbnew/clean.cpp b/pcbnew/clean.cpp index 50af04968c..76e66dbc9a 100644 --- a/pcbnew/clean.cpp +++ b/pcbnew/clean.cpp @@ -37,16 +37,15 @@ #include #include #include -#include +#include + +#include // Helper class used to clean tracks and vias class TRACKS_CLEANER: CONNECTIONS { -private: - BOARD *m_Brd; - public: - TRACKS_CLEANER( BOARD * aPcb ); + TRACKS_CLEANER( BOARD* aPcb, BOARD_COMMIT& aCommit ); /** * the cleanup function. @@ -119,6 +118,10 @@ private: ENDPOINT_T aEndPoint ); bool testTrackEndpointDangling( TRACK* aTrack, ENDPOINT_T aEndPoint ); + + BOARD* m_brd; + BOARD_COMMIT& m_commit; + std::set m_removed; }; @@ -135,7 +138,8 @@ void PCB_EDIT_FRAME::Clean_Pcb() Compile_Ratsnest( NULL, false ); wxBusyCursor( dummy ); - TRACKS_CLEANER cleaner( GetBoard() ); + BOARD_COMMIT commit( this ); + TRACKS_CLEANER cleaner( GetBoard(), commit ); bool modified = cleaner.CleanupBoard( dlg.m_deleteShortCircuits, dlg.m_cleanVias, dlg.m_mergeSegments, dlg.m_deleteUnconnectedSegm ); @@ -143,17 +147,11 @@ void PCB_EDIT_FRAME::Clean_Pcb() if( modified ) { // Clear undo and redo lists to avoid inconsistencies between lists - GetScreen()->ClearUndoRedoList(); SetCurItem( NULL ); + commit.Push( _( "Board cleanup" ) ); Compile_Ratsnest( NULL, true ); - OnModify(); } - // There is a chance that some of tracks have changed their nets, - // so rebuild ratsnest from scratch - if( IsGalCanvasActive() ) - GetBoard()->GetRatsnest()->ProcessBoard(); - m_canvas->Refresh( true ); } @@ -213,13 +211,16 @@ bool TRACKS_CLEANER::CleanupBoard( bool aRemoveMisConnected, } } + for( auto track : m_removed ) + m_commit.Remove( track ); + return modified; } -TRACKS_CLEANER::TRACKS_CLEANER( BOARD * aPcb ): CONNECTIONS( aPcb ) -{ - m_Brd = aPcb; +TRACKS_CLEANER::TRACKS_CLEANER( BOARD* aPcb, BOARD_COMMIT& aCommit ) + : CONNECTIONS( aPcb ), m_brd( aPcb ), m_commit( aCommit ) +{ // Be sure pad list is up to date BuildPadsList(); } @@ -227,10 +228,10 @@ TRACKS_CLEANER::TRACKS_CLEANER( BOARD * aPcb ): CONNECTIONS( aPcb ) void TRACKS_CLEANER::buildTrackConnectionInfo() { - BuildTracksCandidatesList( m_Brd->m_Track, NULL); + BuildTracksCandidatesList( m_brd->m_Track, NULL ); // clear flags and variables used in cleanup - for( TRACK *track = m_Brd->m_Track; track != NULL; track = track->Next() ) + for( TRACK* track = m_brd->m_Track; track != NULL; track = track->Next() ) { track->start = NULL; track->end = NULL; @@ -271,7 +272,7 @@ bool TRACKS_CLEANER::removeBadTrackSegments() // Rebuild physical connections. // the list of physical connected items to a given item is in // m_PadsConnected and m_TracksConnected members of each item - BuildTracksCandidatesList( m_Brd->m_Track ); + BuildTracksCandidatesList( m_brd->m_Track ); // build connections between track segments and pads. SearchTracksConnectedToPads(); @@ -279,7 +280,7 @@ bool TRACKS_CLEANER::removeBadTrackSegments() TRACK* segment; // build connections between track ends - for( segment = m_Brd->m_Track; segment; segment = segment->Next() ) + for( segment = m_brd->m_Track; segment; segment = segment->Next() ) { SearchConnectedTracks( segment ); GetConnectedTracks( segment ); @@ -287,7 +288,7 @@ bool TRACKS_CLEANER::removeBadTrackSegments() bool isModified = false; - for( segment = m_Brd->m_Track; segment; segment = segment->Next() ) + for( segment = m_brd->m_Track; segment; segment = segment->Next() ) { segment->SetState( FLAG0, false ); @@ -308,28 +309,27 @@ bool TRACKS_CLEANER::removeBadTrackSegments() // Remove tracks having a flagged segment TRACK* next; - for( segment = m_Brd->m_Track; segment; segment = next ) + + for( segment = m_brd->m_Track; segment; segment = next ) { next = segment->Next(); if( segment->GetState( FLAG0 ) ) // Segment is flagged to be removed { isModified = true; - segment->ViewRelease(); - m_Brd->Remove( segment ); - delete segment; // TODO: See if it can be put in undo list + m_removed.insert( segment ); } } if( isModified ) { // some pointers are invalid. Clear the m_TracksConnected list, // to avoid any issue - for( segment = m_Brd->m_Track; segment; segment = segment->Next() ) + for( segment = m_brd->m_Track; segment; segment = segment->Next() ) { segment->m_TracksConnected.clear(); } - m_Brd->m_Status_Pcb = 0; + m_brd->m_Status_Pcb = 0; } return isModified; @@ -341,19 +341,13 @@ bool TRACKS_CLEANER::remove_duplicates_of_via( const VIA *aVia ) bool modified = false; // Search and delete others vias at same location - VIA* next_via; for( VIA* alt_via = GetFirstVia( aVia->Next() ); alt_via != NULL; - alt_via = next_via ) + alt_via = GetFirstVia( alt_via->Next() ) ) { - next_via = GetFirstVia( alt_via->Next() ); - - if( (alt_via->GetViaType() == VIA_THROUGH) && - (alt_via->GetStart() == aVia->GetStart()) ) + if( ( alt_via->GetViaType() == VIA_THROUGH ) && + ( alt_via->GetStart() == aVia->GetStart() ) ) { - // delete via - m_Brd->GetRatsnest()->Remove( alt_via ); - alt_via->ViewRelease(); - alt_via->DeleteStructure(); + m_removed.insert( alt_via ); modified = true; } } @@ -365,7 +359,7 @@ bool TRACKS_CLEANER::clean_vias() { bool modified = false; - for( VIA* via = GetFirstVia( m_Brd->m_Track ); via != NULL; + for( VIA* via = GetFirstVia( m_brd->m_Track ); via != NULL; via = GetFirstVia( via->Next() ) ) { // Correct via m_End defects (if any), should never happen @@ -392,9 +386,7 @@ bool TRACKS_CLEANER::clean_vias() if( ( pad->GetLayerSet() & all_cu ) == all_cu ) { // redundant: delete the via - m_Brd->GetRatsnest()->Remove( via ); - via->ViewRelease(); - via->DeleteStructure(); + m_removed.insert( via ); modified = true; break; } @@ -422,7 +414,7 @@ const ZONE_CONTAINER* TRACKS_CLEANER::zoneForTrackEndpoint( const TRACK* aTrack, bottom_layer = top_layer; } - return m_Brd->HitTestForAnyFilledArea( aTrack->GetEndPoint( aEndPoint ), + return m_brd->HitTestForAnyFilledArea( aTrack->GetEndPoint( aEndPoint ), top_layer, bottom_layer, aTrack->GetNetCode() ); } @@ -455,7 +447,7 @@ bool TRACKS_CLEANER::testTrackEndpointDangling( TRACK* aTrack, ENDPOINT_T aEndPo // search for another segment following the via aTrack->SetState( BUSY, true ); - other = via->GetTrack( m_Brd->m_Track, NULL, aEndPoint, true, false ); + other = via->GetTrack( m_brd->m_Track, NULL, aEndPoint, true, false ); // There is a via on the start but it goes nowhere if( !other && !zoneForTrackEndpoint( via, aEndPoint ) ) @@ -475,7 +467,7 @@ bool TRACKS_CLEANER::testTrackEndpointDangling( TRACK* aTrack, ENDPOINT_T aEndPo */ bool TRACKS_CLEANER::deleteDanglingTracks() { - if( m_Brd->m_Track == NULL ) + if( m_brd->m_Track == NULL ) return false; bool modified = false; @@ -484,12 +476,9 @@ bool TRACKS_CLEANER::deleteDanglingTracks() do // Iterate when at least one track is deleted { item_erased = false; - TRACK* next_track; - for( TRACK *track = m_Brd->m_Track; track != NULL; track = next_track ) + for( TRACK* track = m_brd->m_Track; track != NULL; track = track->Next() ) { - next_track = track->Next(); - bool flag_erase = false; // Start without a good reason to erase it /* if a track endpoint is not connected to a pad, test if @@ -509,14 +498,9 @@ bool TRACKS_CLEANER::deleteDanglingTracks() if( flag_erase ) { - // remove segment from board - m_Brd->GetRatsnest()->Remove( track ); - track->ViewRelease(); - track->DeleteStructure(); - /* keep iterating, because a track connected to the deleted track * now perhaps is not connected and should be deleted */ - item_erased = true; + tie( std::ignore, flag_erase ) = m_removed.insert( track ); modified = true; } } @@ -529,19 +513,14 @@ bool TRACKS_CLEANER::deleteDanglingTracks() // Delete null length track segments bool TRACKS_CLEANER::delete_null_segments() { - TRACK *nextsegment; bool modified = false; // Delete null segments - for( TRACK *segment = m_Brd->m_Track; segment; segment = nextsegment ) + for( TRACK* segment = m_brd->m_Track; segment; segment = segment->Next() ) { - nextsegment = segment->Next(); - if( segment->IsNull() ) // Length segment = 0; delete it { - m_Brd->GetRatsnest()->Remove( segment ); - segment->ViewRelease(); - segment->DeleteStructure(); + m_removed.insert( segment ); modified = true; } } @@ -554,11 +533,8 @@ bool TRACKS_CLEANER::remove_duplicates_of_track( const TRACK *aTrack ) { bool modified = false; - TRACK *nextsegment; - for( TRACK *other = aTrack->Next(); other; other = nextsegment ) + for( TRACK *other = aTrack->Next(); other; other = other->Next() ) { - nextsegment = other->Next(); - // New netcode, break out (can't be there any other) if( aTrack->GetNetCode() != other->GetNetCode() ) break; @@ -573,9 +549,7 @@ bool TRACKS_CLEANER::remove_duplicates_of_track( const TRACK *aTrack ) ( ( aTrack->GetStart() == other->GetEnd() ) && ( aTrack->GetEnd() == other->GetStart() ) ) ) { - m_Brd->GetRatsnest()->Remove( other ); - other->ViewRelease(); - other->DeleteStructure(); + m_removed.insert( other ); modified = true; } } @@ -608,7 +582,7 @@ bool TRACKS_CLEANER::merge_collinear_of_track( TRACK* aSegment ) { // There can be only one segment connected other->SetState( BUSY, true ); - TRACK *yet_another = aSegment->GetTrack( m_Brd->m_Track, NULL, + TRACK* yet_another = aSegment->GetTrack( m_brd->m_Track, NULL, endpoint, true, false ); other->SetState( BUSY, false ); @@ -621,9 +595,7 @@ bool TRACKS_CLEANER::merge_collinear_of_track( TRACK* aSegment ) // Merge succesful, the other one has to go away if( segDelete ) { - m_Brd->GetRatsnest()->Remove( segDelete ); - segDelete->ViewRelease(); - segDelete->DeleteStructure(); + m_removed.insert( segDelete ); merged_this = true; } } @@ -646,13 +618,13 @@ bool TRACKS_CLEANER::clean_segments() // Delete redundant segments, i.e. segments having the same end points and layers // (can happens when blocks are copied on themselve) - for( TRACK *segment = m_Brd->m_Track; segment; segment = segment->Next() ) + for( TRACK* segment = m_brd->m_Track; segment; segment = segment->Next() ) modified |= remove_duplicates_of_track( segment ); // merge collinear segments: TRACK* nextsegment; - for( TRACK *segment = m_Brd->m_Track; segment; segment = nextsegment ) + for( TRACK* segment = m_brd->m_Track; segment; segment = nextsegment ) { nextsegment = segment->Next(); @@ -801,24 +773,17 @@ bool PCB_EDIT_FRAME::RemoveMisConnectedTracks() { // Old model has to be refreshed, GAL normally does not keep updating it Compile_Ratsnest( NULL, false ); + BOARD_COMMIT commit( this ); - TRACKS_CLEANER cleaner( GetBoard() ); - + TRACKS_CLEANER cleaner( GetBoard(), commit ); bool isModified = cleaner.CleanupBoard( true, false, false, false ); if( isModified ) { // Clear undo and redo lists to avoid inconsistencies between lists - GetScreen()->ClearUndoRedoList(); SetCurItem( NULL ); - - // There is a chance that some of tracks have changed, - // so rebuild ratsnest from scratch - if( IsGalCanvasActive() ) - GetBoard()->GetRatsnest()->ProcessBoard(); - + commit.Push( _( "Board cleanup" ) ); Compile_Ratsnest( NULL, true ); - OnModify(); } m_canvas->Refresh( true );