From 4a21da6b27a7f7692751e0d583f5643f87d3638c Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sat, 31 May 2025 10:53:14 +0100 Subject: [PATCH] ADDED: field options for Update PCB from Schematic Fixes https://gitlab.com/kicad/code/kicad/-/issues/21021 --- include/board_item.h | 3 +- pcbnew/dialogs/dialog_update_pcb.cpp | 2 + pcbnew/dialogs/dialog_update_pcb_base.cpp | 63 ++-- pcbnew/dialogs/dialog_update_pcb_base.fbp | 280 ++++++++++++++---- pcbnew/dialogs/dialog_update_pcb_base.h | 8 +- .../drc/drc_test_provider_library_parity.cpp | 36 +-- .../netlist_reader/board_netlist_updater.cpp | 112 ++++--- pcbnew/netlist_reader/board_netlist_updater.h | 6 + pcbnew/pcb_edit_frame.cpp | 52 +++- 9 files changed, 421 insertions(+), 141 deletions(-) diff --git a/include/board_item.h b/include/board_item.h index 375eb625bf..0e8217f049 100644 --- a/include/board_item.h +++ b/include/board_item.h @@ -431,7 +431,8 @@ public: enum COMPARE_FLAGS : int { - DRC = 0x01 + DRC = 0x01, + INSTANCE_TO_INSTANCE = 0x02 }; struct ptr_cmp diff --git a/pcbnew/dialogs/dialog_update_pcb.cpp b/pcbnew/dialogs/dialog_update_pcb.cpp index 4332afaf11..bfc0071fc8 100644 --- a/pcbnew/dialogs/dialog_update_pcb.cpp +++ b/pcbnew/dialogs/dialog_update_pcb.cpp @@ -124,6 +124,8 @@ void DIALOG_UPDATE_PCB::PerformUpdate( bool aDryRun ) updater.SetReplaceFootprints( m_cbUpdateFootprints->GetValue() ); updater.SetTransferGroups( m_cbTransferGroups->GetValue() ); updater.SetOverrideLocks( m_cbOverrideLocks->GetValue() ); + updater.SetUpdateFields( m_cbUpdateFields->GetValue() ); + updater.SetRemoveExtraFields( m_cbRemoveExtraFields->GetValue() ); updater.UpdateNetlist( *m_netlist ); m_messagePanel->Flush( true ); diff --git a/pcbnew/dialogs/dialog_update_pcb_base.cpp b/pcbnew/dialogs/dialog_update_pcb_base.cpp index e402ea3c11..84bc86c2c0 100644 --- a/pcbnew/dialogs/dialog_update_pcb_base.cpp +++ b/pcbnew/dialogs/dialog_update_pcb_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf-dirty) +// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -21,33 +21,58 @@ DIALOG_UPDATE_PCB_BASE::DIALOG_UPDATE_PCB_BASE( wxWindow* parent, wxWindowID id, wxBoxSizer* bUpperSizer; bUpperSizer = new wxBoxSizer( wxVERTICAL ); - wxStaticBoxSizer* sbSizer1; - sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Options") ), wxVERTICAL ); + wxStaticBoxSizer* sbOptions; + sbOptions = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Options") ), wxVERTICAL ); - m_cbRelinkFootprints = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Re-link footprints to schematic symbols based on their reference designators"), wxDefaultPosition, wxDefaultSize, 0 ); + m_cbRelinkFootprints = new wxCheckBox( sbOptions->GetStaticBox(), wxID_ANY, _("Re-link footprints to schematic symbols based on their reference designators"), wxDefaultPosition, wxDefaultSize, 0 ); m_cbRelinkFootprints->SetToolTip( _("Normally footprints are linked to their symbols via their Unique IDs. Select this option only if you want to reset the footprint linkages based on their reference designators.") ); - sbSizer1->Add( m_cbRelinkFootprints, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + sbOptions->Add( m_cbRelinkFootprints, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - m_cbDeleteExtraFootprints = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Delete footprints with no symbols"), wxDefaultPosition, wxDefaultSize, 0 ); - m_cbDeleteExtraFootprints->SetToolTip( _("Remove from the board unlocked footprints which are not linked to a schematic symbol.") ); + m_cbTransferGroups = new wxCheckBox( sbOptions->GetStaticBox(), wxID_ANY, _("Group footprints based on symbol group"), wxDefaultPosition, wxDefaultSize, 0 ); + sbOptions->Add( m_cbTransferGroups, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 ); + + + bUpperSizer->Add( sbOptions, 1, wxEXPAND|wxALL, 5 ); - sbSizer1->Add( m_cbDeleteExtraFootprints, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - m_cbUpdateFootprints = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Replace footprints with those specified in the schematic"), wxDefaultPosition, wxDefaultSize, 0 ); + bUpperSizer->Add( 0, 5, 0, wxEXPAND, 5 ); + + wxStaticBoxSizer* sbFootprints; + sbFootprints = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Update Footprints") ), wxVERTICAL ); + + m_cbUpdateFootprints = new wxCheckBox( sbFootprints->GetStaticBox(), wxID_ANY, _("Replace footprints with those specified by symbols"), wxDefaultPosition, wxDefaultSize, 0 ); m_cbUpdateFootprints->SetValue(true); m_cbUpdateFootprints->SetToolTip( _("Normally footprints on the board should be changed to match footprint assignment changes made in the schematic. Uncheck this only if you don't want to change existing footprints on the board.") ); - sbSizer1->Add( m_cbUpdateFootprints, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + sbFootprints->Add( m_cbUpdateFootprints, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_cbDeleteExtraFootprints = new wxCheckBox( sbFootprints->GetStaticBox(), wxID_ANY, _("Delete footprints with no symbols"), wxDefaultPosition, wxDefaultSize, 0 ); + m_cbDeleteExtraFootprints->SetToolTip( _("Remove from the board unlocked footprints which are not linked to a schematic symbol.") ); + + sbFootprints->Add( m_cbDeleteExtraFootprints, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_cbOverrideLocks = new wxCheckBox( sbFootprints->GetStaticBox(), wxID_ANY, _("Override locks"), wxDefaultPosition, wxDefaultSize, 0 ); + sbFootprints->Add( m_cbOverrideLocks, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 ); + + + bUpperSizer->Add( sbFootprints, 0, wxEXPAND|wxALL, 5 ); - m_cbTransferGroups = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Group footprints based on symbol group"), wxDefaultPosition, wxDefaultSize, 0 ); - sbSizer1->Add( m_cbTransferGroups, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 ); - m_cbOverrideLocks = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Delete/replace footprints even if locked"), wxDefaultPosition, wxDefaultSize, 0 ); - sbSizer1->Add( m_cbOverrideLocks, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 ); + bUpperSizer->Add( 0, 5, 0, wxEXPAND, 5 ); + wxStaticBoxSizer* sbFields; + sbFields = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Update Fields") ), wxVERTICAL ); - bUpperSizer->Add( sbSizer1, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + m_cbUpdateFields = new wxCheckBox( sbFields->GetStaticBox(), wxID_ANY, _("Update footprint fields from symbols"), wxDefaultPosition, wxDefaultSize, 0 ); + m_cbUpdateFields->SetValue(true); + sbFields->Add( m_cbUpdateFields, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_cbRemoveExtraFields = new wxCheckBox( sbFields->GetStaticBox(), wxID_ANY, _("Remove footprint fields not found in symbols"), wxDefaultPosition, wxDefaultSize, 0 ); + sbFields->Add( m_cbRemoveExtraFields, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + + bUpperSizer->Add( sbFields, 0, wxEXPAND|wxALL, 5 ); bMainSizer->Add( bUpperSizer, 0, wxALL|wxEXPAND, 5 ); @@ -78,9 +103,9 @@ DIALOG_UPDATE_PCB_BASE::DIALOG_UPDATE_PCB_BASE( wxWindow* parent, wxWindowID id, // Connect Events m_cbRelinkFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); - m_cbDeleteExtraFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); - m_cbUpdateFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); m_cbTransferGroups->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); + m_cbUpdateFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); + m_cbDeleteExtraFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); m_cbOverrideLocks->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnUpdateClick ), NULL, this ); } @@ -89,9 +114,9 @@ DIALOG_UPDATE_PCB_BASE::~DIALOG_UPDATE_PCB_BASE() { // Disconnect Events m_cbRelinkFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); - m_cbDeleteExtraFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); - m_cbUpdateFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); m_cbTransferGroups->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); + m_cbUpdateFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); + m_cbDeleteExtraFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); m_cbOverrideLocks->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this ); m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnUpdateClick ), NULL, this ); diff --git a/pcbnew/dialogs/dialog_update_pcb_base.fbp b/pcbnew/dialogs/dialog_update_pcb_base.fbp index cf4a09fc8b..b3350bd56e 100644 --- a/pcbnew/dialogs/dialog_update_pcb_base.fbp +++ b/pcbnew/dialogs/dialog_update_pcb_base.fbp @@ -1,34 +1,36 @@ - + - C++ - 1 - source_name - 0 - 0 + + 1 + connect + none + + + 0 + 1 res UTF-8 - connect dialog_update_pcb_base 1000 - none - - 1 + 1 + UI dialog_update_pcb_base - . - + 0 + source_name + 1 + 0 + source_name + + + 1 1 - 1 - 1 - 1 - UI - 0 - 1 0 + 0 0 wxAUI_MGR_DEFAULT @@ -73,13 +75,13 @@ none 5 - wxEXPAND|wxTOP|wxRIGHT|wxLEFT + wxEXPAND|wxALL 1 wxID_ANY Options - sbSizer1 + sbOptions wxVERTICAL 1 none @@ -92,10 +94,10 @@ 1 1 1 - + 0 - - + 0 + 0 @@ -151,17 +153,17 @@ 5 - wxBOTTOM|wxRIGHT|wxLEFT + wxBOTTOM|wxLEFT|wxRIGHT 0 1 1 1 1 - + 0 - - + 0 + 0 @@ -183,7 +185,7 @@ 0 0 wxID_ANY - Delete footprints with no symbols + Group footprints based on symbol group 0 @@ -191,7 +193,7 @@ 0 1 - m_cbDeleteExtraFootprints + m_cbTransferGroups 1 @@ -202,9 +204,9 @@ 1 - ; forward_declare + ; ; forward_declare 0 - Remove from the board unlocked footprints which are not linked to a schematic symbol. + wxFILTER_NONE wxDefaultValidator @@ -215,6 +217,30 @@ OnOptionChanged + + + + 5 + wxEXPAND + 0 + + 5 + protected + 0 + + + + 5 + wxEXPAND|wxALL + 0 + + wxID_ANY + Update Footprints + + sbFootprints + wxVERTICAL + 1 + none 5 wxBOTTOM|wxRIGHT|wxLEFT @@ -224,10 +250,10 @@ 1 1 1 - + 0 - - + 0 + 0 @@ -249,7 +275,7 @@ 0 0 wxID_ANY - Replace footprints with those specified in the schematic + Replace footprints with those specified by symbols 0 @@ -283,17 +309,17 @@ 5 - wxBOTTOM|wxLEFT|wxRIGHT + wxBOTTOM|wxRIGHT|wxLEFT 0 1 1 1 1 - + 0 - - + 0 + 0 @@ -315,7 +341,7 @@ 0 0 wxID_ANY - Group footprints based on symbol group + Delete footprints with no symbols 0 @@ -323,7 +349,7 @@ 0 1 - m_cbTransferGroups + m_cbDeleteExtraFootprints 1 @@ -334,9 +360,9 @@ 1 - ; ; forward_declare + ; forward_declare 0 - + Remove from the board unlocked footprints which are not linked to a schematic symbol. wxFILTER_NONE wxDefaultValidator @@ -356,10 +382,10 @@ 1 1 1 - + 0 - - + 0 + 0 @@ -381,7 +407,7 @@ 0 0 wxID_ANY - Delete/replace footprints even if locked + Override locks 0 @@ -415,6 +441,160 @@ + + 5 + wxEXPAND + 0 + + 5 + protected + 0 + + + + 5 + wxEXPAND|wxALL + 0 + + wxID_ANY + Update Fields + + sbFields + wxVERTICAL + 1 + none + + 5 + wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Update footprint fields from symbols + + 0 + + + 0 + + 1 + m_cbUpdateFields + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Remove footprint fields not found in symbols + + 0 + + + 0 + + 1 + m_cbRemoveExtraFields + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + @@ -435,10 +615,10 @@ 1 1 1 - + 0 - - + 0 + 0 diff --git a/pcbnew/dialogs/dialog_update_pcb_base.h b/pcbnew/dialogs/dialog_update_pcb_base.h index 390cfbbcf9..8d1085ef0e 100644 --- a/pcbnew/dialogs/dialog_update_pcb_base.h +++ b/pcbnew/dialogs/dialog_update_pcb_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf-dirty) +// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -36,10 +36,12 @@ class DIALOG_UPDATE_PCB_BASE : public DIALOG_SHIM protected: wxCheckBox* m_cbRelinkFootprints; - wxCheckBox* m_cbDeleteExtraFootprints; - wxCheckBox* m_cbUpdateFootprints; wxCheckBox* m_cbTransferGroups; + wxCheckBox* m_cbUpdateFootprints; + wxCheckBox* m_cbDeleteExtraFootprints; wxCheckBox* m_cbOverrideLocks; + wxCheckBox* m_cbUpdateFields; + wxCheckBox* m_cbRemoveExtraFields; WX_HTML_REPORT_PANEL* m_messagePanel; wxStdDialogButtonSizer* m_sdbSizer1; wxButton* m_sdbSizer1OK; diff --git a/pcbnew/drc/drc_test_provider_library_parity.cpp b/pcbnew/drc/drc_test_provider_library_parity.cpp index 28ba693465..a5e4055b72 100644 --- a/pcbnew/drc/drc_test_provider_library_parity.cpp +++ b/pcbnew/drc/drc_test_provider_library_parity.cpp @@ -597,18 +597,20 @@ bool FOOTPRINT::FootprintNeedsUpdate( const FOOTPRINT* aLibFP, int aCompareFlags // due to rounding and shape modifications std::unique_ptr temp( static_cast( aLibFP->Clone() ) ); - temp->SetParentGroup( nullptr ); temp->SetParent( GetBoard() ); // Needed to know the copper layer count; - if( IsFlipped() != temp->IsFlipped() ) - temp->Flip( { 0, 0 }, FLIP_DIRECTION::TOP_BOTTOM ); + if( !( aCompareFlags & COMPARE_FLAGS::INSTANCE_TO_INSTANCE ) ) + { + if( IsFlipped() != temp->IsFlipped() ) + temp->Flip( { 0, 0 }, FLIP_DIRECTION::TOP_BOTTOM ); - if( GetOrientation() != temp->GetOrientation() ) - temp->SetOrientation( GetOrientation() ); + if( GetOrientation() != temp->GetOrientation() ) + temp->SetOrientation( GetOrientation() ); - if( GetPosition() != temp->GetPosition() ) - temp->SetPosition( GetPosition() ); + if( GetPosition() != temp->GetPosition() ) + temp->SetPosition( GetPosition() ); + } for( BOARD_ITEM* item : temp->GraphicalItems() ) item->NormalizeForCompare(); @@ -648,6 +650,9 @@ bool FOOTPRINT::FootprintNeedsUpdate( const FOOTPRINT* aLibFP, int aCompareFlags _( "Do not populate" ) ) ); } +#define REPORT( msg ) { if( aReporter ) aReporter->Report( msg ); } +#define CHECKPOINT { if( diff && !aReporter ) return diff; } + // Clearance and zone connection overrides are as likely to be set at the board level as in // the library. // @@ -657,20 +662,20 @@ bool FOOTPRINT::FootprintNeedsUpdate( const FOOTPRINT* aLibFP, int aCompareFlags // On the other hand, if we report them then boards that override at the board level are // going to be VERY noisy. // - // For now we report them if there's a reporter, but we DON'T generate DRC errors on them. - if( aReporter ) + // For report them as different, but we DON'T generate DRC errors on them. + if( !( aCompareFlags & COMPARE_FLAGS::DRC ) ) { if( GetLocalClearance().has_value() && GetLocalClearance() != aLibFP->GetLocalClearance() ) { diff = true; - aReporter->Report( _( "Pad clearance overridden." ) ); + REPORT( _( "Pad clearance overridden." ) ); } if( GetLocalSolderMaskMargin().has_value() && GetLocalSolderMaskMargin() != aLibFP->GetLocalSolderMaskMargin() ) { diff = true; - aReporter->Report( _( "Solder mask expansion overridden." ) ); + REPORT( _( "Solder mask expansion overridden." ) ); } @@ -678,21 +683,21 @@ bool FOOTPRINT::FootprintNeedsUpdate( const FOOTPRINT* aLibFP, int aCompareFlags && GetLocalSolderPasteMargin() != aLibFP->GetLocalSolderPasteMargin() ) { diff = true; - aReporter->Report( _( "Solder paste absolute clearance overridden." ) ); + REPORT( _( "Solder paste absolute clearance overridden." ) ); } if( GetLocalSolderPasteMarginRatio() && GetLocalSolderPasteMarginRatio() != aLibFP->GetLocalSolderPasteMarginRatio() ) { diff = true; - aReporter->Report( _( "Solder paste relative clearance overridden." ) ); + REPORT( _( "Solder paste relative clearance overridden." ) ); } if( GetLocalZoneConnection() != ZONE_CONNECTION::INHERITED && GetLocalZoneConnection() != aLibFP->GetLocalZoneConnection() ) { diff = true; - aReporter->Report( _( "Zone connection overridden." ) ); + REPORT( _( "Zone connection overridden." ) ); } } @@ -705,9 +710,6 @@ bool FOOTPRINT::FootprintNeedsUpdate( const FOOTPRINT* aLibFP, int aCompareFlags _( "Net tie pad groups differ." ) ); } -#define REPORT( msg ) { if( aReporter ) aReporter->Report( msg ); } -#define CHECKPOINT { if( diff && !aReporter ) return diff; } - // Text items are really problematic. We don't want to test the reference, but after that // it gets messy. // diff --git a/pcbnew/netlist_reader/board_netlist_updater.cpp b/pcbnew/netlist_reader/board_netlist_updater.cpp index 9ffef81f15..5f4a6e3277 100644 --- a/pcbnew/netlist_reader/board_netlist_updater.cpp +++ b/pcbnew/netlist_reader/board_netlist_updater.cpp @@ -62,6 +62,8 @@ BOARD_NETLIST_UPDATER::BOARD_NETLIST_UPDATER( PCB_EDIT_FRAME* aFrame, BOARD* aBo m_lookupByTimestamp = false; m_transferGroups = false; m_overrideLocks = false; + m_updateFields = false; + m_removeExtraFields = false; m_warningCount = 0; m_errorCount = 0; @@ -505,8 +507,11 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint, { if( m_isDryRun ) { - msg.Printf( _( "Update %s fields." ), aPcbFootprint->GetReference() ); - m_reporter->Report( msg, RPT_SEVERITY_ACTION ); + if( m_updateFields ) + { + msg.Printf( _( "Update %s fields." ), aPcbFootprint->GetReference() ); + m_reporter->Report( msg, RPT_SEVERITY_ACTION ); + } // Remove fields that aren't present in the symbol for( PCB_FIELD* field : aPcbFootprint->GetFields() ) @@ -516,74 +521,83 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint, if( compFields.count( field->GetName() ) == 0 ) { - msg.Printf( _( "Remove %s footprint fields not in symbol." ), - aPcbFootprint->GetReference() ); - m_reporter->Report( msg, RPT_SEVERITY_ACTION ); + if( m_removeExtraFields ) + { + msg.Printf( _( "Remove %s footprint fields not in symbol." ), + aPcbFootprint->GetReference() ); + m_reporter->Report( msg, RPT_SEVERITY_ACTION ); + } + break; } } } else { - msg.Printf( _( "Updated %s fields." ), aPcbFootprint->GetReference() ); - m_reporter->Report( msg, RPT_SEVERITY_ACTION ); + if( m_updateFields ) + { + msg.Printf( _( "Updated %s fields." ), aPcbFootprint->GetReference() ); + m_reporter->Report( msg, RPT_SEVERITY_ACTION ); - changed = true; + changed = true; - // Add or change field value - for( auto& [name, value] : compFields ) - { - if( aPcbFootprint->HasField( name ) ) - { - aPcbFootprint->GetField( name )->SetText( value ); - } - else + // Add or change field value + for( auto& [name, value] : compFields ) { - PCB_FIELD* newField = new PCB_FIELD( aPcbFootprint, FIELD_T::USER ); - aPcbFootprint->Add( newField ); + if( aPcbFootprint->HasField( name ) ) + { + aPcbFootprint->GetField( name )->SetText( value ); + } + else + { + PCB_FIELD* newField = new PCB_FIELD( aPcbFootprint, FIELD_T::USER ); + aPcbFootprint->Add( newField ); - newField->SetName( name ); - newField->SetText( value ); - newField->SetVisible( false ); - newField->SetLayer( aPcbFootprint->GetLayer() == F_Cu ? F_Fab : B_Fab ); + newField->SetName( name ); + newField->SetText( value ); + newField->SetVisible( false ); + newField->SetLayer( aPcbFootprint->GetLayer() == F_Cu ? F_Fab : B_Fab ); - // Give the relative position (0,0) in footprint - newField->SetPosition( aPcbFootprint->GetPosition() ); - // Give the footprint orientation - newField->Rotate( aPcbFootprint->GetPosition(), aPcbFootprint->GetOrientation() ); + // Give the relative position (0,0) in footprint + newField->SetPosition( aPcbFootprint->GetPosition() ); + // Give the footprint orientation + newField->Rotate( aPcbFootprint->GetPosition(), aPcbFootprint->GetOrientation() ); - if( m_frame ) - newField->StyleFromSettings( m_frame->GetDesignSettings() ); + if( m_frame ) + newField->StyleFromSettings( m_frame->GetDesignSettings() ); + } } } - // Remove and delete fields that aren't present in the symbol - bool warned = false; - - std::vector fieldList; - aPcbFootprint->GetFields( fieldList, false ); - - for( PCB_FIELD* field : fieldList ) + if( m_removeExtraFields ) { - if( field->IsMandatory() ) - continue; + bool warned = false; - if( compFields.count( field->GetName() ) == 0 ) + std::vector fieldList; + aPcbFootprint->GetFields( fieldList, false ); + + for( PCB_FIELD* field : fieldList ) { - if( !warned ) + if( field->IsMandatory() ) + continue; + + if( compFields.count( field->GetName() ) == 0 ) { - warned = true; - msg.Printf( _( "Removed %s footprint fields not in symbol." ), - aPcbFootprint->GetReference() ); - m_reporter->Report( msg, RPT_SEVERITY_ACTION ); - } + if( !warned ) + { + warned = true; + msg.Printf( _( "Removed %s footprint fields not in symbol." ), + aPcbFootprint->GetReference() ); + m_reporter->Report( msg, RPT_SEVERITY_ACTION ); + } - aPcbFootprint->Remove( field ); + aPcbFootprint->Remove( field ); - if( m_frame ) - m_frame->GetCanvas()->GetView()->Remove( field ); + if( m_frame ) + m_frame->GetCanvas()->GetView()->Remove( field ); - delete field; + delete field; + } } } } @@ -799,7 +813,7 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint, if( changed && copy ) m_commit.Modified( aPcbFootprint, copy ); - else if( copy ) + else delete copy; return true; diff --git a/pcbnew/netlist_reader/board_netlist_updater.h b/pcbnew/netlist_reader/board_netlist_updater.h index 7306ba39ba..fe68507b02 100644 --- a/pcbnew/netlist_reader/board_netlist_updater.h +++ b/pcbnew/netlist_reader/board_netlist_updater.h @@ -93,6 +93,10 @@ public: void SetLookupByTimestamp( bool aEnabled ) { m_lookupByTimestamp = aEnabled; } + void SetUpdateFields( bool aEnabled ) { m_updateFields = aEnabled; } + + void SetRemoveExtraFields( bool aEnabled ) { m_removeExtraFields = aEnabled; } + std::vector GetAddedFootprints() const { return m_addedFootprints; } private: @@ -143,6 +147,8 @@ private: bool m_transferGroups; // copy component group associations from schematic to PCB bool m_lookupByTimestamp; bool m_overrideLocks; + bool m_updateFields; + bool m_removeExtraFields; int m_warningCount; int m_errorCount; diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp index b939b9250e..1e37ed40e0 100644 --- a/pcbnew/pcb_edit_frame.cpp +++ b/pcbnew/pcb_edit_frame.cpp @@ -2371,6 +2371,8 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew, newPad->SetNetCode( NETINFO_LIST::UNCONNECTED ); } + std::set handledTextItems; + for( BOARD_ITEM* oldItem : aExisting->GraphicalItems() ) { PCB_TEXT* oldTextItem = dynamic_cast( oldItem ); @@ -2385,6 +2387,7 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew, if( newTextItem ) { + handledTextItems.insert( newTextItem ); processTextItem( *oldTextItem, *newTextItem, resetTextContent, resetTextLayers, resetTextEffects, aUpdated ); } @@ -2394,7 +2397,28 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew, } else { - aNew->Add( static_cast( oldTextItem->Clone() ) ); + newTextItem = static_cast( oldTextItem->Clone() ); + handledTextItems.insert( newTextItem ); + aNew->Add( newTextItem ); + } + } + } + + // Check for any newly-added text items and set the update flag as appropriate + for( BOARD_ITEM* newItem : aNew->GraphicalItems() ) + { + PCB_TEXT* newTextItem = dynamic_cast( newItem ); + + if( newTextItem ) + { + // Dimensions have PCB_TEXT base but are not treated like texts in the updater + if( dynamic_cast( newTextItem ) ) + continue; + + if( !handledTextItems.contains( newTextItem ) ) + { + *aUpdated = true; + break; } } } @@ -2410,6 +2434,8 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew, aExisting->GetValue() == aExisting->GetFPID().GetLibItemName().wx_str(), resetTextLayers, resetTextEffects, aUpdated ); + std::set handledFields; + // Copy fields in accordance with the reset* flags for( PCB_FIELD* oldField : aExisting->GetFields() ) { @@ -2421,6 +2447,7 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew, if( newField ) { + handledFields.insert( newField ); processTextItem( *oldField, *newField, resetTextContent, resetTextLayers, resetTextEffects, aUpdated ); } @@ -2431,8 +2458,22 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew, else { newField = new PCB_FIELD( *oldField ); + handledFields.insert( newField ); aNew->Add( newField ); - processTextItem( *oldField, *newField, true, true, true, aUpdated ); + } + } + + // Check for any newly-added fields and set the update flag as appropriate + for( PCB_FIELD* newField : aNew->GetFields() ) + { + // Reference and value are already handled + if( newField->IsReference() || newField->IsValue() ) + continue; + + if( !handledFields.contains( newField ) ) + { + *aUpdated = true; + break; } } @@ -2505,6 +2546,13 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew, aNew->SetFilters( aExisting->GetFilters() ); aNew->SetStaticComponentClass( aExisting->GetComponentClass() ); + if( !aUpdated ) + { + // Check pad shapes, graphics, zones, etc. for changes + if( aNew->FootprintNeedsUpdate( aExisting, BOARD_ITEM::COMPARE_FLAGS::INSTANCE_TO_INSTANCE ) ) + *aUpdated = true; + } + aCommit.Remove( aExisting ); aCommit.Add( aNew );