ADDED: ERC/DRC exclusion comments.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16020
This commit is contained in:
Jeff Young 2024-01-29 15:59:28 +00:00
parent c8d2a9340b
commit d7e4a8cebd
17 changed files with 379 additions and 133 deletions

View File

@ -27,15 +27,20 @@
WX_TEXT_ENTRY_DIALOG::WX_TEXT_ENTRY_DIALOG( wxWindow* aParent, WX_TEXT_ENTRY_DIALOG::WX_TEXT_ENTRY_DIALOG( wxWindow* aParent,
const wxString& aFieldLabel, const wxString& aFieldLabel,
const wxString& aCaption, const wxString& aCaption,
const wxString& aDefaultValue ) : const wxString& aDefaultValue,
bool aExtraWidth ) :
WX_TEXT_ENTRY_DIALOG_BASE( aParent, wxID_ANY, aCaption, wxDefaultPosition, wxDefaultSize ) WX_TEXT_ENTRY_DIALOG_BASE( aParent, wxID_ANY, aCaption, wxDefaultPosition, wxDefaultSize )
{ {
m_label->SetLabel( aFieldLabel ); m_label->SetLabel( aFieldLabel );
m_textCtrl->SetValue( aDefaultValue ); m_textCtrl->SetValue( aDefaultValue );
m_textCtrl->SetMinSize( FromDIP( aExtraWidth ? wxSize( 700, -1 ) : wxSize( 300, -1 ) ) );
SetupStandardButtons(); SetupStandardButtons();
SetInitialFocus( m_textCtrl ); SetInitialFocus( m_textCtrl );
this->Layout();
m_mainSizer->Fit( this );
} }

View File

@ -84,12 +84,12 @@ wxString RC_ITEM::getSeverityString( SEVERITY aSeverity )
switch( aSeverity ) switch( aSeverity )
{ {
case RPT_SEVERITY_ERROR: severity = wxS( "error" ); break; case RPT_SEVERITY_ERROR: severity = wxS( "error" ); break;
case RPT_SEVERITY_WARNING: severity = wxS( "warning" ); break; case RPT_SEVERITY_WARNING: severity = wxS( "warning" ); break;
case RPT_SEVERITY_ACTION: severity = wxS( "action" ); break; case RPT_SEVERITY_ACTION: severity = wxS( "action" ); break;
case RPT_SEVERITY_INFO: severity = wxS( "info" ); break; case RPT_SEVERITY_INFO: severity = wxS( "info" ); break;
case RPT_SEVERITY_EXCLUSION: severity = wxS( "exclusion" ); break; case RPT_SEVERITY_EXCLUSION: severity = wxS( "exclusion" ); break;
case RPT_SEVERITY_DEBUG: severity = wxS( "debug" ); break; case RPT_SEVERITY_DEBUG: severity = wxS( "debug" ); break;
default:; default:;
}; };
@ -123,41 +123,48 @@ wxString RC_ITEM::ShowReport( UNITS_PROVIDER* aUnitsProvider, SEVERITY aSeverity
// 2) try not to re-order or change syntax // 2) try not to re-order or change syntax
// 3) report settings key (which should be more stable) in addition to message // 3) report settings key (which should be more stable) in addition to message
wxString msg;
if( mainItem && auxItem ) if( mainItem && auxItem )
{ {
return wxString::Format( wxT( "[%s]: %s\n %s; %s\n %s: %s\n %s: %s\n" ), msg.Printf( wxT( "[%s]: %s\n %s; %s\n %s: %s\n %s: %s\n" ),
GetSettingsKey(), GetSettingsKey(),
GetErrorMessage(), GetErrorMessage(),
GetViolatingRuleDesc(), GetViolatingRuleDesc(),
severity, severity,
showCoord( aUnitsProvider, mainItem->GetPosition()), showCoord( aUnitsProvider, mainItem->GetPosition()),
mainItem->GetItemDescription( aUnitsProvider ), mainItem->GetItemDescription( aUnitsProvider ),
showCoord( aUnitsProvider, auxItem->GetPosition()), showCoord( aUnitsProvider, auxItem->GetPosition()),
auxItem->GetItemDescription( aUnitsProvider ) ); auxItem->GetItemDescription( aUnitsProvider ) );
} }
else if( mainItem ) else if( mainItem )
{ {
return wxString::Format( wxT( "[%s]: %s\n %s; %s\n %s: %s\n" ), msg.Printf( wxT( "[%s]: %s\n %s; %s\n %s: %s\n" ),
GetSettingsKey(), GetSettingsKey(),
GetErrorMessage(), GetErrorMessage(),
GetViolatingRuleDesc(), GetViolatingRuleDesc(),
severity, severity,
showCoord( aUnitsProvider, mainItem->GetPosition()), showCoord( aUnitsProvider, mainItem->GetPosition()),
mainItem->GetItemDescription( aUnitsProvider ) ); mainItem->GetItemDescription( aUnitsProvider ) );
} }
else else
{ {
return wxString::Format( wxT( "[%s]: %s\n %s; %s\n" ), msg.Printf( wxT( "[%s]: %s\n %s; %s\n" ),
GetSettingsKey(), GetSettingsKey(),
GetErrorMessage(), GetErrorMessage(),
GetViolatingRuleDesc(), GetViolatingRuleDesc(),
severity ); severity );
} }
if( m_parent && m_parent->IsExcluded() && !m_parent->GetComment().IsEmpty() )
msg += wxString::Format( wxS( " %s\n" ), m_parent->GetComment() );
return msg;
} }
void RC_ITEM::GetJsonViolation( RC_JSON::VIOLATION& aViolation, UNITS_PROVIDER* aUnitsProvider, void RC_ITEM::GetJsonViolation( RC_JSON::VIOLATION& aViolation, UNITS_PROVIDER* aUnitsProvider,
SEVERITY aSeverity, SEVERITY aSeverity,
const std::map<KIID, EDA_ITEM*>& aItemMap ) const const std::map<KIID, EDA_ITEM*>& aItemMap ) const
{ {
wxString severity = getSeverityString( aSeverity ); wxString severity = getSeverityString( aSeverity );
@ -221,6 +228,7 @@ KIID RC_TREE_MODEL::ToUUID( wxDataViewItem aItem )
switch( node->m_Type ) switch( node->m_Type )
{ {
case RC_TREE_NODE::MARKER: case RC_TREE_NODE::MARKER:
case RC_TREE_NODE::COMMENT:
// rc_item->GetParent() can be null, if the parent is not existing // rc_item->GetParent() can be null, if the parent is not existing
// when a RC item has no corresponding ERC/DRC marker // when a RC item has no corresponding ERC/DRC marker
if( rc_item->GetParent() ) if( rc_item->GetParent() )
@ -310,6 +318,12 @@ void RC_TREE_MODEL::rebuildModel( std::shared_ptr<RC_ITEMS_PROVIDER> aProvider,
if( rcItem->GetAuxItem3ID() != niluuid ) if( rcItem->GetAuxItem3ID() != niluuid )
n->m_Children.push_back( new RC_TREE_NODE( n, rcItem, RC_TREE_NODE::AUX_ITEM3 ) ); n->m_Children.push_back( new RC_TREE_NODE( n, rcItem, RC_TREE_NODE::AUX_ITEM3 ) );
if( MARKER_BASE* marker = rcItem->GetParent() )
{
if( marker->IsExcluded() && !marker->GetComment().IsEmpty() )
n->m_Children.push_back( new RC_TREE_NODE( n, rcItem, RC_TREE_NODE::COMMENT ) );
}
} }
// Must be called after a significant change of items to force the // Must be called after a significant change of items to force the
@ -444,6 +458,12 @@ void RC_TREE_MODEL::GetValue( wxVariant& aVariant,
case RC_TREE_NODE::AUX_ITEM3: case RC_TREE_NODE::AUX_ITEM3:
item = m_editFrame->GetItem( rcItem->GetAuxItem3ID() ); item = m_editFrame->GetItem( rcItem->GetAuxItem3ID() );
break; break;
case RC_TREE_NODE::COMMENT:
if( marker )
msg = marker->GetComment();
break;
} }
if( item ) if( item )
@ -494,19 +514,51 @@ bool RC_TREE_MODEL::GetAttr( wxDataViewItem const& aItem,
} }
void RC_TREE_MODEL::ValueChanged( const RC_TREE_NODE* aNode ) void RC_TREE_MODEL::ValueChanged( RC_TREE_NODE* aNode )
{ {
if( aNode->m_Type == RC_TREE_NODE::MAIN_ITEM || aNode->m_Type == RC_TREE_NODE::AUX_ITEM ) if( aNode->m_Type != RC_TREE_NODE::MARKER )
{ {
ValueChanged( aNode->m_Parent ); ValueChanged( aNode->m_Parent );
return;
} }
if( aNode->m_Type == RC_TREE_NODE::MARKER ) wxDataViewItem markerItem = ToItem( aNode );
{
wxDataViewModel::ValueChanged( ToItem( aNode ), 0 );
for( const RC_TREE_NODE* child : aNode->m_Children ) wxDataViewModel::ValueChanged( markerItem, 0 );
wxDataViewModel::ValueChanged( ToItem( child ), 0 );
for( const RC_TREE_NODE* child : aNode->m_Children )
wxDataViewModel::ValueChanged( ToItem( child ), 0 );
// Comment items can come and go depening on exclusion state and comment content.
//
const std::shared_ptr<RC_ITEM> rcItem = aNode->m_RcItem;
MARKER_BASE* marker = rcItem ? rcItem->GetParent() : nullptr;
if( marker )
{
bool needsCommentNode = marker->IsExcluded() && !marker->GetComment().IsEmpty();
RC_TREE_NODE* commentNode = aNode->m_Children.back();
if( commentNode && commentNode->m_Type != RC_TREE_NODE::COMMENT )
commentNode = nullptr;
if( needsCommentNode && !commentNode )
{
commentNode = new RC_TREE_NODE( aNode, rcItem, RC_TREE_NODE::COMMENT );
wxDataViewItemArray newItems;
newItems.push_back( ToItem( commentNode ) );
aNode->m_Children.push_back( commentNode );
ItemsAdded( markerItem, newItems );
}
else if( commentNode && !needsCommentNode )
{
wxDataViewItemArray deletedItems;
deletedItems.push_back( ToItem( commentNode ) );
aNode->m_Children.erase( aNode->m_Children.end() - 1 );
ItemsDeleted( markerItem, deletedItems );
}
} }
} }

View File

@ -43,6 +43,7 @@
#include <confirm.h> #include <confirm.h>
#include <common.h> #include <common.h>
#include <widgets/wx_html_report_box.h> #include <widgets/wx_html_report_box.h>
#include <dialogs/dialog_text_entry.h>
#include <wx/ffile.h> #include <wx/ffile.h>
#include <wx/filedlg.h> #include <wx/filedlg.h>
#include <wx/hyperlink.h> #include <wx/hyperlink.h>
@ -599,14 +600,34 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
default: listName = _( "appropriate" ); break; default: listName = _( "appropriate" ); break;
} }
enum MENU_IDS
{
ID_EDIT_EXCLUSION_COMMENT = 4467,
ID_REMOVE_EXCLUSION,
ID_REMOVE_EXCLUSION_ALL,
ID_ADD_EXCLUSION,
ID_ADD_EXCLUSION_ALL,
ID_EDIT_PIN_CONFLICT_MAP,
ID_EDIT_CONNECTION_GRID,
ID_SET_SEVERITY_TO_ERROR,
ID_SET_SEVERITY_TO_WARNING,
ID_SET_SEVERITY_TO_IGNORE,
ID_EDIT_SEVERITIES,
};
if( rcItem->GetParent()->IsExcluded() ) if( rcItem->GetParent()->IsExcluded() )
{ {
menu.Append( 1, _( "Remove exclusion for this violation" ), menu.Append( ID_EDIT_EXCLUSION_COMMENT,
_( "Edit exclusion comment..." ) );
menu.Append( ID_REMOVE_EXCLUSION,
_( "Remove exclusion for this violation" ),
wxString::Format( _( "It will be placed back in the %s list" ), listName ) ); wxString::Format( _( "It will be placed back in the %s list" ), listName ) );
} }
else else
{ {
menu.Append( 2, _( "Exclude this violation" ), menu.Append( ID_ADD_EXCLUSION,
_( "Exclude this violation..." ),
wxString::Format( _( "It will be excluded from the %s list" ), listName ) ); wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
} }
@ -619,18 +640,21 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
} }
else if( settings.GetSeverity( rcItem->GetErrorCode() ) == RPT_SEVERITY_WARNING ) else if( settings.GetSeverity( rcItem->GetErrorCode() ) == RPT_SEVERITY_WARNING )
{ {
menu.Append( 4, wxString::Format( _( "Change severity to Error for all '%s' violations" ), menu.Append( ID_SET_SEVERITY_TO_ERROR,
rcItem->GetErrorText() ), wxString::Format( _( "Change severity to Error for all '%s' violations" ),
rcItem->GetErrorText() ),
_( "Violation severities can also be edited in the Schematic Setup... dialog" ) ); _( "Violation severities can also be edited in the Schematic Setup... dialog" ) );
} }
else else
{ {
menu.Append( 5, wxString::Format( _( "Change severity to Warning for all '%s' violations" ), menu.Append( ID_SET_SEVERITY_TO_WARNING,
rcItem->GetErrorText() ), wxString::Format( _( "Change severity to Warning for all '%s' violations" ),
rcItem->GetErrorText() ),
_( "Violation severities can also be edited in the Schematic Setup... dialog" ) ); _( "Violation severities can also be edited in the Schematic Setup... dialog" ) );
} }
menu.Append( 6, wxString::Format( _( "Ignore all '%s' violations" ), rcItem->GetErrorText() ), menu.Append( ID_SET_SEVERITY_TO_IGNORE,
wxString::Format( _( "Ignore all '%s' violations" ), rcItem->GetErrorText() ),
_( "Violations will not be checked or reported" ) ); _( "Violations will not be checked or reported" ) );
menu.AppendSeparator(); menu.AppendSeparator();
@ -638,17 +662,21 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_WARNING if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_WARNING
|| rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR ) || rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
{ {
menu.Append( 7, _( "Edit pin-to-pin conflict map..." ) ); menu.Append( ID_EDIT_PIN_CONFLICT_MAP,
_( "Edit pin-to-pin conflict map..." ),
_( "Open the Schematic Setup... dialog" ) );
} }
else else
{ {
menu.Append( 8, _( "Edit violation severities..." ), menu.Append( ID_EDIT_SEVERITIES,
_( "Edit violation severities..." ),
_( "Open the Schematic Setup... dialog" ) ); _( "Open the Schematic Setup... dialog" ) );
} }
if( rcItem->GetErrorCode() == ERCE_ENDPOINT_OFF_GRID ) if( rcItem->GetErrorCode() == ERCE_ENDPOINT_OFF_GRID )
{ {
menu.Append( 9, _( "Edit connection grid spacing..." ), menu.Append( ID_EDIT_CONNECTION_GRID,
_( "Edit connection grid spacing..." ),
_( "Open the Schematic Setup... dialog" ) ); _( "Open the Schematic Setup... dialog" ) );
} }
@ -656,11 +684,26 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
switch( GetPopupMenuSelectionFromUser( menu ) ) switch( GetPopupMenuSelectionFromUser( menu ) )
{ {
case 1: case ID_EDIT_EXCLUSION_COMMENT:
{ if( SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ) )
SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ); {
WX_TEXT_ENTRY_DIALOG dlg( this, _( "Optional comment:" ), _( "Exclusion Comment" ),
marker->GetComment(), true );
if( marker ) if( dlg.ShowModal() == wxID_CANCEL )
break;
marker->SetExcluded( true, dlg.GetValue() );
// Update view
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
modified = true;
}
break;
case ID_REMOVE_EXCLUSION:
if( SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ) )
{ {
marker->SetExcluded( false ); marker->SetExcluded( false );
m_parent->GetCanvas()->GetView()->Update( marker ); m_parent->GetCanvas()->GetView()->Update( marker );
@ -669,16 +712,20 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node ); static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
modified = true; modified = true;
} }
}
break; break;
case 2: case ID_ADD_EXCLUSION:
{ if( SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ) )
SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() );
if( marker )
{ {
marker->SetExcluded( true ); WX_TEXT_ENTRY_DIALOG dlg( this, _( "Optional comment:" ), _( "Exclusion Comment" ),
wxEmptyString, true );
if( dlg.ShowModal() == wxID_CANCEL )
break;
marker->SetExcluded( true, dlg.GetValue() );
m_parent->GetCanvas()->GetView()->Update( marker ); m_parent->GetCanvas()->GetView()->Update( marker );
// Update view // Update view
@ -689,10 +736,10 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
modified = true; modified = true;
} }
}
break; break;
case 4: case ID_SET_SEVERITY_TO_ERROR:
settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_ERROR ); settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_ERROR );
for( SCH_ITEM* item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) ) for( SCH_ITEM* item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
@ -708,7 +755,7 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
modified = true; modified = true;
break; break;
case 5: case ID_SET_SEVERITY_TO_WARNING:
settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_WARNING ); settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_WARNING );
for( SCH_ITEM* item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) ) for( SCH_ITEM* item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
@ -724,7 +771,7 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
modified = true; modified = true;
break; break;
case 6: case ID_SET_SEVERITY_TO_IGNORE:
{ {
settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_IGNORE ); settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_IGNORE );
@ -740,15 +787,15 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
} }
break; break;
case 7: case ID_EDIT_PIN_CONFLICT_MAP:
m_parent->ShowSchematicSetupDialog( _( "Pin Conflicts Map" ) ); m_parent->ShowSchematicSetupDialog( _( "Pin Conflicts Map" ) );
break; break;
case 8: case ID_EDIT_SEVERITIES:
m_parent->ShowSchematicSetupDialog( _( "Violation Severity" ) ); m_parent->ShowSchematicSetupDialog( _( "Violation Severity" ) );
break; break;
case 9: case ID_EDIT_CONNECTION_GRID:
m_parent->ShowSchematicSetupDialog( _( "Formatting" ) ); m_parent->ShowSchematicSetupDialog( _( "Formatting" ) );
break; break;
} }

View File

@ -376,6 +376,12 @@ void ERC_TREE_MODEL::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
msg = getItemDesc( schEditFrame->GetItem( ercItem->GetAuxItem3ID() ), msg = getItemDesc( schEditFrame->GetItem( ercItem->GetAuxItem3ID() ),
schEditFrame->GetCurrentSheet() ); schEditFrame->GetCurrentSheet() );
break; break;
case RC_TREE_NODE::COMMENT:
if( marker )
msg = marker->GetComment();
break;
} }
msg.Replace( wxS( "\n" ), wxS( " " ) ); msg.Replace( wxS( "\n" ), wxS( " " ) );

View File

@ -148,7 +148,7 @@ bool ERC_REPORT::WriteJsonReport( const wxString& aFullFileName )
switch( severity ) switch( severity )
{ {
case RPT_SEVERITY_ERROR: err_count++; break; case RPT_SEVERITY_ERROR: err_count++; break;
case RPT_SEVERITY_WARNING: warn_count++; break; case RPT_SEVERITY_WARNING: warn_count++; break;
default: break; default: break;
} }

View File

@ -149,8 +149,8 @@ ERC_SETTINGS::ERC_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
{ {
nlohmann::json js = nlohmann::json::array(); nlohmann::json js = nlohmann::json::array();
for( const auto& entry : m_ErcExclusions ) for( const wxString& entry : m_ErcExclusions )
js.push_back( entry ); js.push_back( { entry, m_ErcExclusionComments[ entry ] } );
return js; return js;
}, },
@ -163,10 +163,16 @@ ERC_SETTINGS::ERC_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
for( const nlohmann::json& entry : aObj ) for( const nlohmann::json& entry : aObj )
{ {
if( entry.empty() ) if( entry.is_array() )
continue; {
wxString serialized = entry[0].get<wxString>();
m_ErcExclusions.insert( entry.get<wxString>() ); m_ErcExclusions.insert( serialized );
m_ErcExclusionComments[ serialized ] = entry[1].get<wxString>();
}
else if( entry.is_string() )
{
m_ErcExclusions.insert( entry.get<wxString>() );
}
} }
}, },
{} ) ); {} ) );

View File

@ -172,8 +172,9 @@ public:
public: public:
std::map<int, SEVERITY> m_ERCSeverities; std::map<int, SEVERITY> m_ERCSeverities;
std::set<wxString> m_ErcExclusions; std::set<wxString> m_ErcExclusions; // Serialized excluded ERC markers
std::map<wxString, wxString> m_ErcExclusionComments; // Map from serialization to comment
PIN_ERROR m_PinMap[ELECTRICAL_PINTYPES_TOTAL][ELECTRICAL_PINTYPES_TOTAL]; PIN_ERROR m_PinMap[ELECTRICAL_PINTYPES_TOTAL][ELECTRICAL_PINTYPES_TOTAL];

View File

@ -27,6 +27,7 @@
#include <widgets/msgpanel.h> #include <widgets/msgpanel.h>
#include <bitmaps.h> #include <bitmaps.h>
#include <base_units.h> #include <base_units.h>
#include <eda_draw_frame.h>
#include <erc_settings.h> #include <erc_settings.h>
#include <sch_marker.h> #include <sch_marker.h>
#include <schematic.h> #include <schematic.h>
@ -272,7 +273,52 @@ const BOX2I SCH_MARKER::GetBoundingBox() const
void SCH_MARKER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) void SCH_MARKER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
{ {
aList.emplace_back( _( "Electrical Rule Check Error" ), m_rcItem->GetErrorMessage() ); aList.emplace_back( _( "Type" ), _( "Marker" ) );
aList.emplace_back( _( "Violation" ), m_rcItem->GetErrorMessage() );
switch( GetSeverity() )
{
case RPT_SEVERITY_IGNORE:
aList.emplace_back( _( "Severity" ), _( "Ignore" ) );
break;
case RPT_SEVERITY_WARNING:
aList.emplace_back( _( "Severity" ), _( "Warning" ) );
break;
case RPT_SEVERITY_ERROR:
aList.emplace_back( _( "Severity" ), _( "Error" ) );
break;
default:
break;
}
if( GetMarkerType() == MARKER_DRAWING_SHEET )
{
aList.emplace_back( _( "Drawing Sheet" ), wxEmptyString );
}
else
{
wxString mainText;
wxString auxText;
EDA_ITEM* mainItem = nullptr;
EDA_ITEM* auxItem = nullptr;
if( m_rcItem->GetMainItemID() != niluuid )
mainItem = aFrame->GetItem( m_rcItem->GetMainItemID() );
if( m_rcItem->GetAuxItemID() != niluuid )
auxItem = aFrame->GetItem( m_rcItem->GetAuxItemID() );
if( mainItem )
mainText = mainItem->GetItemDescription( aFrame );
if( auxItem )
auxText = auxItem->GetItemDescription( aFrame );
aList.emplace_back( mainText, auxText );
}
if( IsExcluded() )
aList.emplace_back( _( "Excluded" ), m_comment );
} }

View File

@ -349,7 +349,7 @@ std::vector<SCH_MARKER*> SCHEMATIC::ResolveERCExclusions()
if( it != settings.m_ErcExclusions.end() ) if( it != settings.m_ErcExclusions.end() )
{ {
marker->SetExcluded( true ); marker->SetExcluded( true, settings.m_ErcExclusionComments[serialized] );
settings.m_ErcExclusions.erase( it ); settings.m_ErcExclusions.erase( it );
} }
} }
@ -363,7 +363,7 @@ std::vector<SCH_MARKER*> SCHEMATIC::ResolveERCExclusions()
if( marker ) if( marker )
{ {
marker->SetExcluded( true ); marker->SetExcluded( true, settings.m_ErcExclusionComments[serialized] );
newMarkers.push_back( marker ); newMarkers.push_back( marker );
} }
} }
@ -818,6 +818,7 @@ void SCHEMATIC::RecordERCExclusions()
ERC_SETTINGS& ercSettings = ErcSettings(); ERC_SETTINGS& ercSettings = ErcSettings();
ercSettings.m_ErcExclusions.clear(); ercSettings.m_ErcExclusions.clear();
ercSettings.m_ErcExclusionComments.clear();
for( unsigned i = 0; i < sheetList.size(); i++ ) for( unsigned i = 0; i < sheetList.size(); i++ )
{ {
@ -826,7 +827,11 @@ void SCHEMATIC::RecordERCExclusions()
SCH_MARKER* marker = static_cast<SCH_MARKER*>( item ); SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
if( marker->IsExcluded() ) if( marker->IsExcluded() )
ercSettings.m_ErcExclusions.insert( marker->Serialize() ); {
wxString serialized = marker->Serialize();
ercSettings.m_ErcExclusions.insert( serialized );
ercSettings.m_ErcExclusionComments[ serialized ] = marker->GetComment();
}
} }
} }
} }

View File

@ -695,9 +695,10 @@ public:
int m_MinSilkTextHeight; // Min text height for silkscreen layers int m_MinSilkTextHeight; // Min text height for silkscreen layers
int m_MinSilkTextThickness; // Min text thickness for silkscreen layers int m_MinSilkTextThickness; // Min text thickness for silkscreen layers
std::shared_ptr<DRC_ENGINE> m_DRCEngine; std::shared_ptr<DRC_ENGINE> m_DRCEngine;
std::map<int, SEVERITY> m_DRCSeverities; // Map from DRCErrorCode to SEVERITY std::map<int, SEVERITY> m_DRCSeverities; // Map from DRCErrorCode to SEVERITY
std::set<wxString> m_DrcExclusions; std::set<wxString> m_DrcExclusions; // Serialized excluded DRC markers
std::map<wxString, wxString> m_DrcExclusionComments; // Map from serialization to comment
// When smoothing the zone's outline there's the question of external fillets (that is, those // When smoothing the zone's outline there's the question of external fillets (that is, those
// applied to concave corners). While it seems safer to never have copper extend outside the // applied to concave corners). While it seems safer to never have copper extend outside the

View File

@ -40,7 +40,7 @@ class WX_TEXT_ENTRY_DIALOG : public WX_TEXT_ENTRY_DIALOG_BASE
{ {
public: public:
WX_TEXT_ENTRY_DIALOG( wxWindow* aParent, const wxString& aLabel, const wxString& aCaption, WX_TEXT_ENTRY_DIALOG( wxWindow* aParent, const wxString& aLabel, const wxString& aCaption,
const wxString& aDefaultValue = wxEmptyString ); const wxString& aDefaultValue = wxEmptyString, bool aExtraWidth = false );
WX_TEXT_ENTRY_DIALOG( wxWindow* aParent, const wxString& aLabel, const wxString& aCaption, WX_TEXT_ENTRY_DIALOG( wxWindow* aParent, const wxString& aLabel, const wxString& aCaption,

View File

@ -96,7 +96,13 @@ public:
enum MARKER_T GetMarkerType() const { return m_markerType; } enum MARKER_T GetMarkerType() const { return m_markerType; }
bool IsExcluded() const { return m_excluded; } bool IsExcluded() const { return m_excluded; }
void SetExcluded( bool aExcluded ) { m_excluded = aExcluded; } void SetExcluded( bool aExcluded, const wxString& aComment = wxEmptyString )
{
m_excluded = aExcluded;
m_comment = aComment;
}
wxString GetComment() const { return m_comment; }
virtual SEVERITY GetSeverity() const { return RPT_SEVERITY_UNDEFINED; } virtual SEVERITY GetSeverity() const { return RPT_SEVERITY_UNDEFINED; }
@ -131,6 +137,7 @@ public:
protected: protected:
MARKER_T m_markerType; // The type of marker (useful to filter markers) MARKER_T m_markerType; // The type of marker (useful to filter markers)
bool m_excluded; // User has excluded this specific error bool m_excluded; // User has excluded this specific error
wxString m_comment; // User-supplied comment (generally for exclusions)
std::shared_ptr<RC_ITEM> m_rcItem; std::shared_ptr<RC_ITEM> m_rcItem;
int m_scalingFactor; // Scaling factor to convert corners coordinates int m_scalingFactor; // Scaling factor to convert corners coordinates

View File

@ -195,7 +195,15 @@ protected:
class RC_TREE_NODE class RC_TREE_NODE
{ {
public: public:
enum NODE_TYPE { MARKER, MAIN_ITEM, AUX_ITEM, AUX_ITEM2, AUX_ITEM3 }; enum NODE_TYPE
{
MARKER,
MAIN_ITEM,
AUX_ITEM,
AUX_ITEM2,
AUX_ITEM3,
COMMENT
};
RC_TREE_NODE( RC_TREE_NODE* aParent, const std::shared_ptr<RC_ITEM>& aRcItem, NODE_TYPE aType ) : RC_TREE_NODE( RC_TREE_NODE* aParent, const std::shared_ptr<RC_ITEM>& aRcItem, NODE_TYPE aType ) :
m_Type( aType ), m_Type( aType ),
@ -280,7 +288,7 @@ public:
bool GetAttr( wxDataViewItem const& aItem, unsigned int aCol, bool GetAttr( wxDataViewItem const& aItem, unsigned int aCol,
wxDataViewItemAttr& aAttr ) const override; wxDataViewItemAttr& aAttr ) const override;
void ValueChanged( const RC_TREE_NODE* aNode ); void ValueChanged( RC_TREE_NODE* aNode );
void DeleteCurrentItem( bool aDeep ); void DeleteCurrentItem( bool aDeep );

View File

@ -328,7 +328,7 @@ std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions( bool aCreateMarkers )
if( it != m_designSettings->m_DrcExclusions.end() ) if( it != m_designSettings->m_DrcExclusions.end() )
{ {
marker->SetExcluded( true ); marker->SetExcluded( true, m_designSettings->m_DrcExclusionComments[serialized] );
m_designSettings->m_DrcExclusions.erase( it ); m_designSettings->m_DrcExclusions.erase( it );
} }
} }
@ -357,7 +357,7 @@ std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions( bool aCreateMarkers )
if( marker ) if( marker )
{ {
marker->SetExcluded( true ); marker->SetExcluded( true, m_designSettings->m_DrcExclusionComments[serialized] );
newMarkers.push_back( marker ); newMarkers.push_back( marker );
} }
} }
@ -2738,10 +2738,15 @@ bool BOARD::operator==( const BOARD_ITEM& aItem ) const
void BOARD::RecordDRCExclusions() void BOARD::RecordDRCExclusions()
{ {
m_designSettings->m_DrcExclusions.clear(); m_designSettings->m_DrcExclusions.clear();
m_designSettings->m_DrcExclusionComments.clear();
for( PCB_MARKER* marker : m_markers ) for( PCB_MARKER* marker : m_markers )
{ {
if( marker->IsExcluded() ) if( marker->IsExcluded() )
m_designSettings->m_DrcExclusions.insert( marker->Serialize() ); {
wxString serialized = marker->Serialize();
m_designSettings->m_DrcExclusions.insert( serialized );
m_designSettings->m_DrcExclusionComments[ serialized ] = marker->GetComment();
}
} }
} }

View File

@ -336,8 +336,8 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
{ {
nlohmann::json js = nlohmann::json::array(); nlohmann::json js = nlohmann::json::array();
for( const auto& entry : m_DrcExclusions ) for( const wxString& entry : m_DrcExclusions )
js.push_back( entry ); js.push_back( { entry, m_DrcExclusionComments[ entry ] } );
return js; return js;
}, },
@ -350,10 +350,16 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
for( const nlohmann::json& entry : aObj ) for( const nlohmann::json& entry : aObj )
{ {
if( entry.empty() ) if( entry.is_array() )
continue; {
wxString serialized = entry[0].get<wxString>();
m_DrcExclusions.insert( entry.get<wxString>() ); m_DrcExclusions.insert( serialized );
m_DrcExclusionComments[ serialized ] = entry[1].get<wxString>();
}
else if( entry.is_string() )
{
m_DrcExclusions.insert( entry.get<wxString>() );
}
} }
}, },
{} ) ); {} ) );
@ -938,6 +944,7 @@ void BOARD_DESIGN_SETTINGS::initFromOther( const BOARD_DESIGN_SETTINGS& aOther )
m_MinSilkTextThickness = aOther.m_MinSilkTextThickness; m_MinSilkTextThickness = aOther.m_MinSilkTextThickness;
m_DRCSeverities = aOther.m_DRCSeverities; m_DRCSeverities = aOther.m_DRCSeverities;
m_DrcExclusions = aOther.m_DrcExclusions; m_DrcExclusions = aOther.m_DrcExclusions;
m_DrcExclusionComments = aOther.m_DrcExclusionComments;
m_ZoneKeepExternalFillets = aOther.m_ZoneKeepExternalFillets; m_ZoneKeepExternalFillets = aOther.m_ZoneKeepExternalFillets;
m_MaxError = aOther.m_MaxError; m_MaxError = aOther.m_MaxError;
m_SolderMaskExpansion = aOther.m_SolderMaskExpansion; m_SolderMaskExpansion = aOther.m_SolderMaskExpansion;
@ -1025,6 +1032,7 @@ bool BOARD_DESIGN_SETTINGS::operator==( const BOARD_DESIGN_SETTINGS& aOther ) co
if( m_MinSilkTextThickness != aOther.m_MinSilkTextThickness ) return false; if( m_MinSilkTextThickness != aOther.m_MinSilkTextThickness ) return false;
if( m_DRCSeverities != aOther.m_DRCSeverities ) return false; if( m_DRCSeverities != aOther.m_DRCSeverities ) return false;
if( m_DrcExclusions != aOther.m_DrcExclusions ) return false; if( m_DrcExclusions != aOther.m_DrcExclusions ) return false;
if( m_DrcExclusionComments != aOther.m_DrcExclusionComments ) return false;
if( m_ZoneKeepExternalFillets != aOther.m_ZoneKeepExternalFillets ) return false; if( m_ZoneKeepExternalFillets != aOther.m_ZoneKeepExternalFillets ) return false;
if( m_MaxError != aOther.m_MaxError ) return false; if( m_MaxError != aOther.m_MaxError ) return false;
if( m_SolderMaskExpansion != aOther.m_SolderMaskExpansion ) return false; if( m_SolderMaskExpansion != aOther.m_SolderMaskExpansion ) return false;

View File

@ -47,6 +47,7 @@
#include <widgets/progress_reporter_base.h> #include <widgets/progress_reporter_base.h>
#include <widgets/wx_html_report_box.h> #include <widgets/wx_html_report_box.h>
#include <dialogs/panel_setup_rules_base.h> #include <dialogs/panel_setup_rules_base.h>
#include <dialogs/dialog_text_entry.h>
#include <tools/drc_tool.h> #include <tools/drc_tool.h>
#include <tools/zone_filler_tool.h> #include <tools/zone_filler_tool.h>
#include <tools/board_inspection_tool.h> #include <tools/board_inspection_tool.h>
@ -579,7 +580,6 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
std::shared_ptr<CONNECTIVITY_DATA> conn = m_currentBoard->GetConnectivity(); std::shared_ptr<CONNECTIVITY_DATA> conn = m_currentBoard->GetConnectivity();
wxString listName; wxString listName;
wxMenu menu; wxMenu menu;
wxString msg;
switch( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] ) switch( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] )
{ {
@ -588,67 +588,107 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
default: listName = _( "appropriate" ); break; default: listName = _( "appropriate" ); break;
} }
enum MENU_IDS
{
ID_EDIT_EXCLUSION_COMMENT = 4467,
ID_REMOVE_EXCLUSION,
ID_REMOVE_EXCLUSION_ALL,
ID_ADD_EXCLUSION,
ID_ADD_EXCLUSION_ALL,
ID_INSPECT_VIOLATION,
ID_SET_SEVERITY_TO_ERROR,
ID_SET_SEVERITY_TO_WARNING,
ID_SET_SEVERITY_TO_IGNORE,
ID_EDIT_SEVERITIES
};
if( rcItem->GetParent()->IsExcluded() ) if( rcItem->GetParent()->IsExcluded() )
{ {
menu.Append( 1, _( "Remove exclusion for this violation" ), menu.Append( ID_EDIT_EXCLUSION_COMMENT,
_( "Edit exclusion comment..." ) );
menu.Append( ID_REMOVE_EXCLUSION,
_( "Remove exclusion for this violation" ),
wxString::Format( _( "It will be placed back in the %s list" ), listName ) ); wxString::Format( _( "It will be placed back in the %s list" ), listName ) );
if( drcItem->GetViolatingRule() && !drcItem->GetViolatingRule()->m_Implicit ) if( drcItem->GetViolatingRule() && !drcItem->GetViolatingRule()->m_Implicit )
{ {
msg.Printf( _( "Remove all exclusions for violations of rule '%s'" ), menu.Append( ID_REMOVE_EXCLUSION_ALL,
drcItem->GetViolatingRule()->m_Name ); wxString::Format( _( "Remove all exclusions for violations of rule '%s'" ),
menu.Append( 11, msg ); drcItem->GetViolatingRule()->m_Name ),
wxString::Format( _( "They will be placed back in the %s list" ), listName ) );
} }
} }
else else
{ {
menu.Append( 2, _( "Exclude this violation" ), menu.Append( ID_ADD_EXCLUSION,
_( "Exclude this violation..." ),
wxString::Format( _( "It will be excluded from the %s list" ), listName ) ); wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
if( drcItem->GetViolatingRule() && !drcItem->GetViolatingRule()->m_Implicit ) if( drcItem->GetViolatingRule() && !drcItem->GetViolatingRule()->m_Implicit )
{ {
msg.Printf( _( "Exclude all violations of rule '%s'" ), menu.Append( ID_ADD_EXCLUSION_ALL,
drcItem->GetViolatingRule()->m_Name ); wxString::Format( _( "Exclude all violations of rule '%s'..." ),
menu.Append( 21, msg ); drcItem->GetViolatingRule()->m_Name ),
wxString::Format( _( "They will be excluded from the %s list" ), listName ) );
} }
} }
wxString inspectDRCErrorMenuText = inspectionTool->InspectDRCErrorMenuText( rcItem ); wxString inspectDRCErrorMenuText = inspectionTool->InspectDRCErrorMenuText( rcItem );
if( !inspectDRCErrorMenuText.IsEmpty() ) if( !inspectDRCErrorMenuText.IsEmpty() )
menu.Append( 3, inspectDRCErrorMenuText ); menu.Append( ID_INSPECT_VIOLATION, inspectDRCErrorMenuText );
menu.AppendSeparator(); menu.AppendSeparator();
if( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] == RPT_SEVERITY_WARNING ) if( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] == RPT_SEVERITY_WARNING )
{ {
msg.Printf( _( "Change severity to Error for all '%s' violations" ), menu.Append( ID_SET_SEVERITY_TO_ERROR,
rcItem->GetErrorText(), wxString::Format( _( "Change severity to Error for all '%s' violations" ),
_( "Violation severities can also be edited in the Board Setup... dialog" ) ); rcItem->GetErrorText() ),
menu.Append( 4, msg ); _( "Violation severities can also be edited in the Board Setup... dialog" ) );
} }
else else
{ {
msg.Printf( _( "Change severity to Warning for all '%s' violations" ), menu.Append( ID_SET_SEVERITY_TO_WARNING,
rcItem->GetErrorText(), wxString::Format( _( "Change severity to Warning for all '%s' violations" ),
_( "Violation severities can also be edited in the Board Setup... dialog" ) ); rcItem->GetErrorText() ),
menu.Append( 5, msg ); _( "Violation severities can also be edited in the Board Setup... dialog" ) );
} }
msg.Printf( _( "Ignore all '%s' violations" ), menu.Append( ID_SET_SEVERITY_TO_IGNORE,
rcItem->GetErrorText(), wxString::Format( _( "Ignore all '%s' violations" ), rcItem->GetErrorText() ),
_( "Violations will not be checked or reported" ) ); _( "Violations will not be checked or reported" ) );
menu.Append( 6, msg );
menu.AppendSeparator(); menu.AppendSeparator();
menu.Append( 7, _( "Edit violation severities..." ), _( "Open the Board Setup... dialog" ) ); menu.Append( ID_EDIT_SEVERITIES,
_( "Edit violation severities..." ),
_( "Open the Board Setup... dialog" ) );
bool modified = false; bool modified = false;
switch( GetPopupMenuSelectionFromUser( menu ) ) switch( GetPopupMenuSelectionFromUser( menu ) )
{ {
case 1: case ID_EDIT_EXCLUSION_COMMENT:
if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() ) )
{
WX_TEXT_ENTRY_DIALOG dlg( this, _( "Optional comment:" ), _( "Exclusion Comment" ),
marker->GetComment(), true );
if( dlg.ShowModal() == wxID_CANCEL )
break;
marker->SetExcluded( true, dlg.GetValue() );
// Update view
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
modified = true;
}
break;
case ID_REMOVE_EXCLUSION:
if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( rcItem->GetParent() ) ) if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( rcItem->GetParent() ) )
{ {
marker->SetExcluded( false ); marker->SetExcluded( false );
@ -670,10 +710,16 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
break; break;
case 2: case ID_ADD_EXCLUSION:
if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( rcItem->GetParent() ) ) if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( rcItem->GetParent() ) )
{ {
marker->SetExcluded( true ); WX_TEXT_ENTRY_DIALOG dlg( this, _( "Optional comment:" ), _( "Exclusion Comment" ),
wxEmptyString, true );
if( dlg.ShowModal() == wxID_CANCEL )
break;
marker->SetExcluded( true, dlg.GetValue() );
if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS ) if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
{ {
@ -696,7 +742,7 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
break; break;
case 11: case ID_REMOVE_EXCLUSION_ALL:
for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() ) for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
{ {
DRC_ITEM* candidateDrcItem = static_cast<DRC_ITEM*>( marker->GetRCItem().get() ); DRC_ITEM* candidateDrcItem = static_cast<DRC_ITEM*>( marker->GetRCItem().get() );
@ -710,7 +756,7 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
modified = true; modified = true;
break; break;
case 21: case ID_ADD_EXCLUSION_ALL:
for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() ) for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
{ {
DRC_ITEM* candidateDrcItem = static_cast<DRC_ITEM*>( marker->GetRCItem().get() ); DRC_ITEM* candidateDrcItem = static_cast<DRC_ITEM*>( marker->GetRCItem().get() );
@ -724,11 +770,11 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
modified = true; modified = true;
break; break;
case 3: case ID_INSPECT_VIOLATION:
inspectionTool->InspectDRCError( node->m_RcItem ); inspectionTool->InspectDRCError( node->m_RcItem );
break; break;
case 4: case ID_SET_SEVERITY_TO_ERROR:
bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_ERROR; bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_ERROR;
for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() ) for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
@ -742,7 +788,7 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
modified = true; modified = true;
break; break;
case 5: case ID_SET_SEVERITY_TO_WARNING:
bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_WARNING; bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_WARNING;
for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() ) for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
@ -756,7 +802,7 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
modified = true; modified = true;
break; break;
case 6: case ID_SET_SEVERITY_TO_IGNORE:
{ {
bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_IGNORE; bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_IGNORE;
@ -787,7 +833,7 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
break; break;
} }
case 7: case ID_EDIT_SEVERITIES:
m_frame->ShowBoardSetupDialog( _( "Violation Severity" ) ); m_frame->ShowBoardSetupDialog( _( "Violation Severity" ) );
break; break;
} }
@ -930,10 +976,10 @@ void DIALOG_DRC::PrevMarker()
{ {
switch( m_Notebook->GetSelection() ) switch( m_Notebook->GetSelection() )
{ {
case 0: m_markersTreeModel->PrevMarker(); break; case 0: m_markersTreeModel->PrevMarker(); break;
case 1: m_unconnectedTreeModel->PrevMarker(); break; case 1: m_unconnectedTreeModel->PrevMarker(); break;
case 2: m_fpWarningsTreeModel->PrevMarker(); break; case 2: m_fpWarningsTreeModel->PrevMarker(); break;
case 3: break; case 3: break;
} }
} }
} }
@ -945,10 +991,10 @@ void DIALOG_DRC::NextMarker()
{ {
switch( m_Notebook->GetSelection() ) switch( m_Notebook->GetSelection() )
{ {
case 0: m_markersTreeModel->NextMarker(); break; case 0: m_markersTreeModel->NextMarker(); break;
case 1: m_unconnectedTreeModel->NextMarker(); break; case 1: m_unconnectedTreeModel->NextMarker(); break;
case 2: m_fpWarningsTreeModel->NextMarker(); break; case 2: m_fpWarningsTreeModel->NextMarker(); break;
case 3: break; case 3: break;
} }
} }
} }

View File

@ -234,6 +234,9 @@ void PCB_MARKER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_
aList.emplace_back( mainText, auxText ); aList.emplace_back( mainText, auxText );
} }
if( IsExcluded() )
aList.emplace_back( _( "Excluded" ), m_comment );
} }