Back Annotation: add support for DNP and Exclude from BOM attributes

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/14584
This commit is contained in:
Mike Williams 2023-05-01 08:53:36 -04:00
parent c31fb435e6
commit 39cc686dc4
9 changed files with 181 additions and 10 deletions

View File

@ -31,7 +31,7 @@
// Saved dialog settings
DIALOG_UPDATE_FROM_PCB::DIALOG_UPDATE_FROM_PCB_SAVED_STATE
DIALOG_UPDATE_FROM_PCB::s_savedDialogState{ false, true, true, true, false };
DIALOG_UPDATE_FROM_PCB::s_savedDialogState{ false, true, true, true, false, true };
DIALOG_UPDATE_FROM_PCB::DIALOG_UPDATE_FROM_PCB( SCH_EDIT_FRAME* aParent )
@ -61,6 +61,7 @@ DIALOG_UPDATE_FROM_PCB::DIALOG_UPDATE_FROM_PCB( SCH_EDIT_FRAME* aParent )
m_cbUpdateFootprints->SetValue( s_savedDialogState.UpdateFootprints );
m_cbUpdateValues->SetValue( s_savedDialogState.UpdateValues );
m_cbUpdateNetNames->SetValue( s_savedDialogState.UpdateNetNames );
m_cbUpdateAttributes->SetValue( s_savedDialogState.UpdateAttributes );
SetupStandardButtons( { { wxID_OK, _( "Update Schematic" ) },
{ wxID_CANCEL, _( "Close" ) } } );
@ -80,6 +81,7 @@ void DIALOG_UPDATE_FROM_PCB::updateData()
m_cbUpdateValues->GetValue(),
m_cbUpdateReferences->GetValue(),
m_cbUpdateNetNames->GetValue(),
m_cbUpdateAttributes->GetValue(),
true );
std::string netlist;
@ -131,6 +133,8 @@ void DIALOG_UPDATE_FROM_PCB::OnOptionChanged( wxCommandEvent& event )
s_savedDialogState.UpdateValues = m_cbUpdateValues->GetValue();
else if( event.GetEventObject() == m_cbUpdateNetNames )
s_savedDialogState.UpdateNetNames = m_cbUpdateNetNames->GetValue();
else if( event.GetEventObject() == m_cbUpdateAttributes )
s_savedDialogState.UpdateAttributes = m_cbUpdateAttributes->GetValue();
}
@ -145,6 +149,7 @@ void DIALOG_UPDATE_FROM_PCB::OnUpdateClick( wxCommandEvent& event )
m_cbUpdateValues->GetValue(),
m_cbUpdateReferences->GetValue(),
m_cbUpdateNetNames->GetValue(),
m_cbUpdateAttributes->GetValue(),
false );
if( backAnno.FetchNetlistFromPCB( netlist ) && backAnno.BackAnnotateSymbols( netlist ) )

View File

@ -55,6 +55,7 @@ private:
bool UpdateFootprints;
bool UpdateValues;
bool UpdateNetNames;
bool UpdateAttributes;
};
static DIALOG_UPDATE_FROM_PCB_SAVED_STATE s_savedDialogState;

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -69,6 +69,9 @@ DIALOG_UPDATE_FROM_PCB_BASE::DIALOG_UPDATE_FROM_PCB_BASE( wxWindow* parent, wxWi
m_cbUpdateNetNames = new wxCheckBox( sbSizer2->GetStaticBox(), wxID_ANY, _("Net names"), wxDefaultPosition, wxDefaultSize, 0 );
fgSizer2->Add( m_cbUpdateNetNames, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_cbUpdateAttributes = new wxCheckBox( sbSizer2->GetStaticBox(), wxID_ANY, _("Attributes"), wxDefaultPosition, wxDefaultSize, 0 );
fgSizer2->Add( m_cbUpdateAttributes, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 );
sbSizer2->Add( fgSizer2, 1, wxEXPAND, 5 );
@ -108,6 +111,7 @@ DIALOG_UPDATE_FROM_PCB_BASE::DIALOG_UPDATE_FROM_PCB_BASE( wxWindow* parent, wxWi
m_cbUpdateFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateValues->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateNetNames->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateAttributes->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnUpdateClick ), NULL, this );
}
@ -119,6 +123,7 @@ DIALOG_UPDATE_FROM_PCB_BASE::~DIALOG_UPDATE_FROM_PCB_BASE()
m_cbUpdateFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateValues->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateNetNames->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateAttributes->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnUpdateClick ), NULL, this );
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="15" />
<FileVersion major="1" minor="16" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
@ -14,6 +14,7 @@
<property name="file">dialog_update_from_pcb_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">dialog_update_from_pcb_base</property>
@ -25,6 +26,7 @@
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">1</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="1">
@ -50,6 +52,7 @@
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">Update Schematic from PCB</property>
<property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
@ -452,6 +455,71 @@
<event name="OnCheckBox">OnOptionChanged</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxLEFT|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Attributes</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_cbUpdateAttributes</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">OnOptionChanged</event>
</object>
</object>
</object>
</object>
</object>

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -40,12 +40,13 @@ class DIALOG_UPDATE_FROM_PCB_BASE : public DIALOG_SHIM
wxCheckBox* m_cbUpdateFootprints;
wxCheckBox* m_cbUpdateValues;
wxCheckBox* m_cbUpdateNetNames;
wxCheckBox* m_cbUpdateAttributes;
WX_HTML_REPORT_PANEL* m_messagePanel;
wxStdDialogButtonSizer* m_sdbSizer;
wxButton* m_sdbSizerOK;
wxButton* m_sdbSizerCancel;
// Virtual event handlers, overide them in your derived class
// Virtual event handlers, override them in your derived class
virtual void OnOptionChanged( wxCommandEvent& event ) { event.Skip(); }
virtual void OnUpdateClick( wxCommandEvent& event ) { event.Skip(); }
@ -53,6 +54,7 @@ class DIALOG_UPDATE_FROM_PCB_BASE : public DIALOG_SHIM
public:
DIALOG_UPDATE_FROM_PCB_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Update Schematic from PCB"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_UPDATE_FROM_PCB_BASE();
};

View File

@ -42,13 +42,15 @@
BACK_ANNOTATE::BACK_ANNOTATE( SCH_EDIT_FRAME* aFrame, REPORTER& aReporter, bool aRelinkFootprints,
bool aProcessFootprints, bool aProcessValues,
bool aProcessReferences, bool aProcessNetNames, bool aDryRun ) :
bool aProcessReferences, bool aProcessNetNames,
bool aProcessAttributes, bool aDryRun ) :
m_reporter( aReporter ),
m_matchByReference( aRelinkFootprints ),
m_processFootprints( aProcessFootprints ),
m_processValues( aProcessValues ),
m_processReferences( aProcessReferences ),
m_processNetNames( aProcessNetNames ),
m_processAttributes( aProcessAttributes ),
m_dryRun( aDryRun ),
m_frame( aFrame ),
m_changesCount( 0 ),
@ -68,7 +70,7 @@ bool BACK_ANNOTATE::BackAnnotateSymbols( const std::string& aNetlist )
m_appendUndo = false;
if( !m_matchByReference && !m_processValues && !m_processFootprints && !m_processReferences
&& !m_processNetNames )
&& !m_processNetNames && !m_processAttributes )
{
m_reporter.ReportTail( _( "Select at least one property to back annotate." ),
RPT_SEVERITY_ERROR );
@ -148,6 +150,7 @@ void BACK_ANNOTATE::getPcbModulesFromString( const std::string& aPayload )
for( const std::pair<const std::string, PTREE>& item : tree )
{
wxString path, value, footprint;
bool dnp = false, exBOM = false;
std::map<wxString, wxString> pinNetMap;
wxASSERT( item.first == "ref" );
wxString ref = getStr( item.second );
@ -169,6 +172,28 @@ void BACK_ANNOTATE::getPcbModulesFromString( const std::string& aPayload )
footprint = getStr( item.second.get_child( "fpid" ) );
value = getStr( item.second.get_child( "value" ) );
// Get DNP and Exclude from BOM out of the properties if they exist
for( const auto& child : item.second )
{
if( child.first != "property" )
continue;
auto property = child.second;
auto name = property.get_child_optional( "name" );
if( !name )
continue;
if( name.get().front().first == "dnp" )
{
dnp = true;
}
else if( name.get().front().first == "exclude_from_bom" )
{
exBOM = true;
}
}
boost::optional<const PTREE&> nets = item.second.get_child_optional( "nets" );
if( nets )
@ -201,7 +226,8 @@ void BACK_ANNOTATE::getPcbModulesFromString( const std::string& aPayload )
else
{
// Add footprint to the map
auto data = std::make_shared<PCB_FP_DATA>( ref, footprint, value, pinNetMap );
auto data =
std::make_shared<PCB_FP_DATA>( ref, footprint, value, dnp, exBOM, pinNetMap );
m_pcbFootprints.insert( nearestItem, std::make_pair( path, data ) );
}
}
@ -321,8 +347,15 @@ void BACK_ANNOTATE::applyChangelist()
SCH_SCREEN* screen = ref.GetSheetPath().LastScreen();
wxString oldFootprint = ref.GetFootprint();
wxString oldValue = ref.GetValue();
bool oldDNP = ref.GetSymbol()->GetDNP();
bool oldExBOM = !ref.GetSymbol()->GetIncludeInBom();
bool skip = ( ref.GetSymbol()->GetFlags() & SKIP_STRUCT ) > 0;
auto boolString = []( bool b ) -> wxString
{
return b ? _( "true" ) : _( "false" );
};
if( m_processReferences && ref.GetRef() != fpData.m_ref && !skip )
{
++m_changesCount;
@ -376,6 +409,39 @@ void BACK_ANNOTATE::applyChangelist()
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
}
if( m_processAttributes && oldDNP != fpData.m_DNP && !skip )
{
++m_changesCount;
msg.Printf( _( "Change %s 'Do not populate' from '%s' to '%s'." ), ref.GetRef(),
boolString( oldDNP ), boolString( fpData.m_DNP ) );
if( !m_dryRun )
{
m_frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, m_appendUndo );
m_appendUndo = true;
symbol->SetDNP( fpData.m_DNP );
}
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
}
if( m_processAttributes && oldExBOM != fpData.m_excludeFromBOM && !skip )
{
++m_changesCount;
msg.Printf( _( "Change %s 'Exclude from bill of materials' from '%s' to '%s'." ),
ref.GetRef(), boolString( oldExBOM ),
boolString( fpData.m_excludeFromBOM ) );
if( !m_dryRun )
{
m_frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, m_appendUndo );
m_appendUndo = true;
symbol->SetIncludeInBom( !fpData.m_excludeFromBOM );
}
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
}
if( m_processNetNames )
{
for( const std::pair<const wxString, wxString>& entry : fpData.m_pinMap )

View File

@ -61,16 +61,21 @@ public:
struct PCB_FP_DATA
{
PCB_FP_DATA( const wxString& aRef, const wxString& aFootprint, const wxString& aValue,
bool aDNP, bool aExcludeFromBOM,
const std::map<wxString, wxString> aPinMap ) :
m_ref( aRef ),
m_footprint( aFootprint ),
m_value( aValue ),
m_DNP( aDNP ),
m_excludeFromBOM( aExcludeFromBOM ),
m_pinMap( aPinMap )
{};
{}
wxString m_ref;
wxString m_footprint;
wxString m_value;
bool m_DNP;
bool m_excludeFromBOM;
std::map<wxString, wxString> m_pinMap;
};
@ -81,7 +86,7 @@ public:
BACK_ANNOTATE( SCH_EDIT_FRAME* aFrame, REPORTER& aReporter, bool aRelinkFootprints,
bool aProcessFootprints, bool aProcessValues, bool aProcessReferences,
bool aProcessNetNames, bool aDryRun );
bool aProcessNetNames, bool aProcessAttributes, bool aDryRun );
~BACK_ANNOTATE();
/**
@ -137,6 +142,7 @@ private:
bool m_processValues;
bool m_processReferences;
bool m_processNetNames;
bool m_processAttributes;
bool m_dryRun;
PCB_FOOTPRINTS_MAP m_pcbFootprints;

View File

@ -563,6 +563,17 @@ void PCB_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
}
}
// Add DNP and Exclude from BOM properties
std::map<wxString, wxString> properties;
if( footprint->GetAttributes() & FP_DNP )
properties.emplace( "dnp", "" );
if( footprint->GetAttributes() & FP_EXCLUDE_FROM_BOM )
properties.emplace( "exclude_from_bom", "" );
component->SetProperties( properties );
netlist.AddComponent( component );
}

View File

@ -93,6 +93,13 @@ void COMPONENT::Format( OUTPUTFORMATTER* aOut, int aNestLevel, int aCtl )
path += '/' + m_kiids.front().AsString();
aOut->Print( nl+1, "(timestamp %s)\n", aOut->Quotew( path ).c_str() );
// Add DNP and Exclude from BOM properties if we have them
if( m_properties.count( "dnp" ) )
aOut->Print( nl + 1, "(property (name \"dnp\"))\n" );
if( m_properties.count( "exclude_from_bom" ) )
aOut->Print( nl + 1, "(property (name \"exclude_from_bom\"))\n" );
}
if( !( aCtl & CTL_OMIT_FILTERS ) && m_footprintFilters.GetCount() )