From 0598ca0f904f20628a5ced703f4147d122d85256 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sun, 17 Mar 2024 16:28:46 +0000 Subject: [PATCH] Keep BOARD_DESIGN_SETTINGS DRC marker exclusions up-to-date. Fixes https://gitlab.com/kicad/code/kicad/-/issues/17429 --- pcbnew/board.cpp | 61 ++++++++++++------- pcbnew/dialogs/dialog_drc.cpp | 24 ++++++++ pcbnew/pcbnew_jobs_handler.cpp | 6 +- .../scripting/pcbnew_scripting_helpers.cpp | 5 +- 4 files changed, 66 insertions(+), 30 deletions(-) diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index 0ab6c0f360..c08c9c5db2 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -326,17 +326,45 @@ void BOARD::UpdateRatsnestExclusions() } +void BOARD::RecordDRCExclusions() +{ + m_designSettings->m_DrcExclusions.clear(); + m_designSettings->m_DrcExclusionComments.clear(); + + for( PCB_MARKER* marker : m_markers ) + { + if( marker->IsExcluded() ) + { + wxString serialized = marker->Serialize(); + m_designSettings->m_DrcExclusions.insert( serialized ); + m_designSettings->m_DrcExclusionComments[ serialized ] = marker->GetComment(); + } + } +} + + std::vector BOARD::ResolveDRCExclusions( bool aCreateMarkers ) { + std::set exclusions = m_designSettings->m_DrcExclusions; + std::map comments = m_designSettings->m_DrcExclusionComments; + + m_designSettings->m_DrcExclusions.clear(); + m_designSettings->m_DrcExclusionComments.clear(); + for( PCB_MARKER* marker : GetBoard()->Markers() ) { wxString serialized = marker->Serialize(); - std::set::iterator it = m_designSettings->m_DrcExclusions.find( serialized ); + std::set::iterator it = exclusions.find( serialized ); - if( it != m_designSettings->m_DrcExclusions.end() ) + if( it != exclusions.end() ) { - marker->SetExcluded( true, m_designSettings->m_DrcExclusionComments[serialized] ); - m_designSettings->m_DrcExclusions.erase( it ); + marker->SetExcluded( true, comments[ serialized ] ); + + // Exclusion still valid; store back to BOARD_DESIGN_SETTINGS + m_designSettings->m_DrcExclusions.insert( serialized ); + m_designSettings->m_DrcExclusionComments[ serialized ] = comments[ serialized ]; + + exclusions.erase( it ); } } @@ -344,7 +372,7 @@ std::vector BOARD::ResolveDRCExclusions( bool aCreateMarkers ) if( aCreateMarkers ) { - for( const wxString& serialized : m_designSettings->m_DrcExclusions ) + for( const wxString& serialized : exclusions ) { PCB_MARKER* marker = PCB_MARKER::Deserialize( serialized ); @@ -364,14 +392,16 @@ std::vector BOARD::ResolveDRCExclusions( bool aCreateMarkers ) if( marker ) { - marker->SetExcluded( true, m_designSettings->m_DrcExclusionComments[serialized] ); + marker->SetExcluded( true, comments[ serialized ] ); newMarkers.push_back( marker ); + + // Exclusion still valid; store back to BOARD_DESIGN_SETTINGS + m_designSettings->m_DrcExclusions.insert( serialized ); + m_designSettings->m_DrcExclusionComments[ serialized ] = comments[ serialized ]; } } } - m_designSettings->m_DrcExclusions.clear(); - return newMarkers; } @@ -2750,18 +2780,3 @@ bool BOARD::operator==( const BOARD_ITEM& aItem ) const } -void BOARD::RecordDRCExclusions() -{ - m_designSettings->m_DrcExclusions.clear(); - m_designSettings->m_DrcExclusionComments.clear(); - - for( PCB_MARKER* marker : m_markers ) - { - if( marker->IsExcluded() ) - { - wxString serialized = marker->Serialize(); - m_designSettings->m_DrcExclusions.insert( serialized ); - m_designSettings->m_DrcExclusionComments[ serialized ] = marker->GetComment(); - } - } -} \ No newline at end of file diff --git a/pcbnew/dialogs/dialog_drc.cpp b/pcbnew/dialogs/dialog_drc.cpp index 5355764f3e..2293e2d933 100644 --- a/pcbnew/dialogs/dialog_drc.cpp +++ b/pcbnew/dialogs/dialog_drc.cpp @@ -697,6 +697,10 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) marker->SetExcluded( true, dlg.GetValue() ); + wxString serialized = marker->Serialize(); + m_frame->GetDesignSettings().m_DrcExclusions.insert( serialized ); + m_frame->GetDesignSettings().m_DrcExclusionComments[ serialized ] = dlg.GetValue(); + // Update view static_cast( aEvent.GetModel() )->ValueChanged( node ); modified = true; @@ -709,6 +713,10 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) { marker->SetExcluded( false ); + wxString serialized = marker->Serialize(); + m_frame->GetDesignSettings().m_DrcExclusions.erase( serialized ); + m_frame->GetDesignSettings().m_DrcExclusionComments.erase( serialized ); + if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS ) { m_frame->GetBoard()->UpdateRatsnestExclusions(); @@ -737,6 +745,10 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) marker->SetExcluded( true, dlg.GetValue() ); + wxString serialized = marker->Serialize(); + m_frame->GetDesignSettings().m_DrcExclusions.insert( serialized ); + m_frame->GetDesignSettings().m_DrcExclusionComments[ serialized ] = dlg.GetValue(); + if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS ) { m_frame->GetBoard()->UpdateRatsnestExclusions(); @@ -764,7 +776,13 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) DRC_ITEM* candidateDrcItem = static_cast( marker->GetRCItem().get() ); if( candidateDrcItem->GetViolatingRule() == drcItem->GetViolatingRule() ) + { marker->SetExcluded( false ); + + wxString serialized = marker->Serialize(); + m_frame->GetDesignSettings().m_DrcExclusions.erase( serialized ); + m_frame->GetDesignSettings().m_DrcExclusionComments.erase( serialized ); + } } // Rebuild model and view @@ -778,7 +796,12 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) DRC_ITEM* candidateDrcItem = static_cast( marker->GetRCItem().get() ); if( candidateDrcItem->GetViolatingRule() == drcItem->GetViolatingRule() ) + { marker->SetExcluded( true ); + + wxString serialized = marker->Serialize(); + m_frame->GetDesignSettings().m_DrcExclusions.insert( serialized ); + } } // Rebuild model and view @@ -1043,6 +1066,7 @@ void DIALOG_DRC::ExcludeMarker() if( marker && marker->GetSeverity() != RPT_SEVERITY_EXCLUSION ) { marker->SetExcluded( true ); + m_frame->GetDesignSettings().m_DrcExclusions.insert( marker->Serialize() ); m_frame->GetCanvas()->GetView()->Update( marker ); // Update view diff --git a/pcbnew/pcbnew_jobs_handler.cpp b/pcbnew/pcbnew_jobs_handler.cpp index 9b3a4d92f8..609677bb54 100644 --- a/pcbnew/pcbnew_jobs_handler.cpp +++ b/pcbnew/pcbnew_jobs_handler.cpp @@ -1266,10 +1266,8 @@ int PCBNEW_JOBS_HANDLER::JobExportDrc( JOB* aJob ) commit.Push( _( "DRC" ), SKIP_UNDO | SKIP_SET_DIRTY ); - // now "resolve" the drc exclusions again because its the only way to set exclusion status on - // a marker - for( PCB_MARKER* marker : brd->ResolveDRCExclusions( false ) ) - brd->Add( marker ); + // Update the exclusion status on any excluded markers that still exist. + brd->ResolveDRCExclusions( false ); std::shared_ptr markersProvider = std::make_shared( brd, MARKER_BASE::MARKER_DRC, MARKER_BASE::MARKER_DRAWING_SHEET ); diff --git a/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp b/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp index 918ea0eb31..aea45f7e01 100644 --- a/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp +++ b/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp @@ -605,9 +605,8 @@ bool WriteDRCReport( BOARD* aBoard, const wxString& aFileName, EDA_UNITS aUnits, engine->RunTests( aUnits, aReportAllTrackErrors, false ); engine->ClearViolationHandler(); - // now "resolve" the drc exclusions again because its the only way to set exclusion status on a marker - for( PCB_MARKER* marker : aBoard->ResolveDRCExclusions( false ) ) - aBoard->Add( marker ); + // Update the exclusion status on any excluded markers that still exist. + aBoard->ResolveDRCExclusions( false ); // TODO: Unify this with DIALOG_DRC::writeReport