From 833ec402a05da8afc52aea6d83f982a13a238ad9 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sun, 28 Jan 2024 19:49:43 +0000 Subject: [PATCH] Generalize DRCItem inspections. Fixes https://gitlab.com/kicad/code/kicad/-/issues/10539 --- include/tool/action_menu.h | 3 ++ include/widgets/wx_menubar.h | 18 +++++++ pcbnew/dialogs/dialog_drc.cpp | 53 ++++---------------- pcbnew/tools/board_inspection_tool.cpp | 69 ++++++++++++++++++++++++++ pcbnew/tools/board_inspection_tool.h | 1 + 5 files changed, 100 insertions(+), 44 deletions(-) diff --git a/include/tool/action_menu.h b/include/tool/action_menu.h index 95221eb796..2f8def0e1a 100644 --- a/include/tool/action_menu.h +++ b/include/tool/action_menu.h @@ -64,6 +64,9 @@ public: */ void SetTitle( const wxString& aTitle ) override; + // Yes, it hides a non-virtual method in the parent class. + wxString GetTitle() const { return m_title; } + /** * Decide whether a title for a pop up menu should be displayed. */ diff --git a/include/widgets/wx_menubar.h b/include/widgets/wx_menubar.h index 61a6e80872..0b09d17472 100644 --- a/include/widgets/wx_menubar.h +++ b/include/widgets/wx_menubar.h @@ -26,6 +26,7 @@ #include #include +#include /** @@ -53,6 +54,23 @@ public: // Don't use the passed in accelerator table, create a new empty one wxMenuBar::SetAcceleratorTable( wxAcceleratorTable() ); } + + wxString GetMenuLabelText( size_t aPos ) const override + { + if( ACTION_MENU* actionMenu = dynamic_cast( GetMenu( aPos ) ) ) + { + wxString title = actionMenu->GetTitle(); + + // Clear accelerator key markings + title.Replace( wxS( " & " ), wxS( " {amp} " ) ); + title.Replace( wxS( "&" ), wxEmptyString ); + title.Replace( wxS( "{amp}" ), wxS( "&" ) ); + + return title; + } + + return wxMenuBar::GetMenuLabelText( aPos ); + } }; #endif // COMMON_WIDGETS_WX_BUSY_INDICATOR__H diff --git a/pcbnew/dialogs/dialog_drc.cpp b/pcbnew/dialogs/dialog_drc.cpp index 60caff82f5..0fddfe81b5 100644 --- a/pcbnew/dialogs/dialog_drc.cpp +++ b/pcbnew/dialogs/dialog_drc.cpp @@ -567,7 +567,9 @@ void DIALOG_DRC::OnDRCItemDClick( wxDataViewEvent& aEvent ) void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) { - RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() ); + TOOL_MANAGER* toolMgr = m_frame->GetToolManager(); + BOARD_INSPECTION_TOOL* inspectionTool = toolMgr->GetTool(); + RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() ); if( !node ) return; @@ -611,30 +613,10 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) } } - if( rcItem->GetErrorCode() == DRCE_CLEARANCE - || rcItem->GetErrorCode() == DRCE_EDGE_CLEARANCE - || rcItem->GetErrorCode() == DRCE_HOLE_CLEARANCE - || rcItem->GetErrorCode() == DRCE_DRILLED_HOLES_TOO_CLOSE ) - { - menu.Append( 3, _( "Run Inspect > Clearance Resolution" ) ); - } - else if( rcItem->GetErrorCode() == DRCE_TEXT_HEIGHT - || rcItem->GetErrorCode() == DRCE_TEXT_THICKNESS - || rcItem->GetErrorCode() == DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG - || rcItem->GetErrorCode() == DRCE_TRACK_WIDTH - || rcItem->GetErrorCode() == DRCE_VIA_DIAMETER - || rcItem->GetErrorCode() == DRCE_ANNULAR_WIDTH - || rcItem->GetErrorCode() == DRCE_DRILL_OUT_OF_RANGE - || rcItem->GetErrorCode() == DRCE_MICROVIA_DRILL_OUT_OF_RANGE - || rcItem->GetErrorCode() == DRCE_CONNECTION_WIDTH - || rcItem->GetErrorCode() == DRCE_ASSERTION_FAILURE ) - { - menu.Append( 3, _( "Run Inspect > Constraints Resolution" ) ); - } - else if( rcItem->GetErrorCode() == DRCE_LIB_FOOTPRINT_MISMATCH ) - { - menu.Append( 3, _( "Run Inspect > Compare Footprint with Library" ) ); - } + wxString inspectDRCErrorMenuText = inspectionTool->InspectDRCErrorMenuText( rcItem ); + + if( !inspectDRCErrorMenuText.IsEmpty() ) + menu.Append( 3, inspectDRCErrorMenuText ); menu.AppendSeparator(); @@ -667,10 +649,7 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) switch( GetPopupMenuSelectionFromUser( menu ) ) { case 1: - { - PCB_MARKER* marker = dynamic_cast( rcItem->GetParent() ); - - if( marker ) + if( PCB_MARKER* marker = dynamic_cast( rcItem->GetParent() ) ) { marker->SetExcluded( false ); @@ -690,13 +669,9 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) } break; - } case 2: - { - PCB_MARKER* marker = dynamic_cast( rcItem->GetParent() ); - - if( marker ) + if( PCB_MARKER* marker = dynamic_cast( rcItem->GetParent() ) ) { marker->SetExcluded( true ); @@ -720,10 +695,8 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) } break; - } case 11: - { for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() ) { DRC_ITEM* candidateDrcItem = static_cast( marker->GetRCItem().get() ); @@ -736,10 +709,8 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) static_cast( aEvent.GetModel() )->Update( m_markersProvider, m_severities ); modified = true; break; - } case 21: - { for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() ) { DRC_ITEM* candidateDrcItem = static_cast( marker->GetRCItem().get() ); @@ -752,16 +723,10 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) static_cast( aEvent.GetModel() )->Update( m_markersProvider, m_severities ); modified = true; break; - } case 3: - { - TOOL_MANAGER* toolMgr = m_frame->GetToolManager(); - BOARD_INSPECTION_TOOL* inspectionTool = toolMgr->GetTool(); - inspectionTool->InspectDRCError( node->m_RcItem ); break; - } case 4: bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_ERROR; diff --git a/pcbnew/tools/board_inspection_tool.cpp b/pcbnew/tools/board_inspection_tool.cpp index 7651ca97c4..6f7b9293c1 100644 --- a/pcbnew/tools/board_inspection_tool.cpp +++ b/pcbnew/tools/board_inspection_tool.cpp @@ -269,6 +269,69 @@ wxString reportMax( PCB_BASE_FRAME* aFrame, DRC_CONSTRAINT& aConstraint ) } +wxString BOARD_INSPECTION_TOOL::InspectDRCErrorMenuText( const std::shared_ptr& aDRCItem ) +{ + auto menuDescription = + [&]( const TOOL_ACTION& aAction ) + { + wxString menuItemLabel = aAction.GetMenuLabel(); + wxMenuBar* menuBar = m_frame->GetMenuBar(); + + for( size_t ii = 0; ii < menuBar->GetMenuCount(); ++ii ) + { + for( wxMenuItem* menuItem : menuBar->GetMenu( ii )->GetMenuItems() ) + { + if( menuItem->GetItemLabelText() == menuItemLabel ) + { + wxString menuTitleLabel = menuBar->GetMenuLabelText( ii ); + + menuTitleLabel.Replace( wxS( "&" ), wxS( "&&" ) ); + menuItemLabel.Replace( wxS( "&" ), wxS( "&&" ) ); + + return wxString::Format( _( "Run %s > %s" ), + menuTitleLabel, + menuItemLabel ); + } + } + } + + return wxString::Format( _( "Run %s" ), aAction.GetFriendlyName() ); + }; + + if( aDRCItem->GetErrorCode() == DRCE_CLEARANCE + || aDRCItem->GetErrorCode() == DRCE_EDGE_CLEARANCE + || aDRCItem->GetErrorCode() == DRCE_HOLE_CLEARANCE + || aDRCItem->GetErrorCode() == DRCE_DRILLED_HOLES_TOO_CLOSE ) + { + return menuDescription( PCB_ACTIONS::inspectClearance ); + } + else if( aDRCItem->GetErrorCode() == DRCE_TEXT_HEIGHT + || aDRCItem->GetErrorCode() == DRCE_TEXT_THICKNESS + || aDRCItem->GetErrorCode() == DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG + || aDRCItem->GetErrorCode() == DRCE_TRACK_WIDTH + || aDRCItem->GetErrorCode() == DRCE_VIA_DIAMETER + || aDRCItem->GetErrorCode() == DRCE_ANNULAR_WIDTH + || aDRCItem->GetErrorCode() == DRCE_DRILL_OUT_OF_RANGE + || aDRCItem->GetErrorCode() == DRCE_MICROVIA_DRILL_OUT_OF_RANGE + || aDRCItem->GetErrorCode() == DRCE_CONNECTION_WIDTH + || aDRCItem->GetErrorCode() == DRCE_ASSERTION_FAILURE ) + { + return menuDescription( PCB_ACTIONS::inspectConstraints ); + } + else if( aDRCItem->GetErrorCode() == DRCE_LIB_FOOTPRINT_MISMATCH ) + { + return menuDescription( PCB_ACTIONS::diffFootprint ); + } + else if( aDRCItem->GetErrorCode() == DRCE_DANGLING_TRACK + || aDRCItem->GetErrorCode() == DRCE_DANGLING_VIA ) + { + return menuDescription( PCB_ACTIONS::cleanupTracksAndVias ); + } + + return wxEmptyString; +} + + void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr& aDRCItem ) { BOARD_ITEM* a = m_frame->GetBoard()->GetItem( aDRCItem->GetMainItemID() ); @@ -286,6 +349,12 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr& aDR return; } + else if( aDRCItem->GetErrorCode() == DRCE_DANGLING_TRACK + || aDRCItem->GetErrorCode() == DRCE_DANGLING_VIA ) + { + m_toolMgr->RunAction( PCB_ACTIONS::cleanupTracksAndVias ); + return; + } DIALOG_BOOK_REPORTER* dialog = m_frame->GetInspectDrcErrorDialog(); wxCHECK( dialog, /* void */ ); diff --git a/pcbnew/tools/board_inspection_tool.h b/pcbnew/tools/board_inspection_tool.h index 34673cb170..ce5f38f6b1 100644 --- a/pcbnew/tools/board_inspection_tool.h +++ b/pcbnew/tools/board_inspection_tool.h @@ -82,6 +82,7 @@ public: ///< Show the ratsnest for a given net. int ShowNetInRatsnest( const TOOL_EVENT& aEvent ); + wxString InspectDRCErrorMenuText( const std::shared_ptr& aDRCItem ); void InspectDRCError( const std::shared_ptr& aDRCItem ); ///< Show the clearance resolution for two selected items.