ADDED: field options for Update PCB from Schematic

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21021

(cherry picked from commit 4a21da6b27a7f7692751e0d583f5643f87d3638c)
This commit is contained in:
Jeff Young 2025-05-31 10:53:14 +01:00
parent ee62366607
commit cab050609d
9 changed files with 800 additions and 514 deletions

View File

@ -420,7 +420,8 @@ public:
enum COMPARE_FLAGS : int
{
DRC = 0x01
DRC = 0x01,
INSTANCE_TO_INSTANCE = 0x02
};
struct ptr_cmp

View File

@ -121,6 +121,8 @@ void DIALOG_UPDATE_PCB::PerformUpdate( bool aDryRun )
updater.SetDeleteUnusedFootprints( m_cbDeleteExtraFootprints->GetValue());
updater.SetReplaceFootprints( m_cbUpdateFootprints->GetValue() );
updater.SetOverrideLocks( m_cbOverrideLocks->GetValue() );
updater.SetUpdateFields( m_cbUpdateFields->GetValue() );
updater.SetRemoveExtraFields( m_cbRemoveExtraFields->GetValue() );
updater.UpdateNetlist( *m_netlist );
m_messagePanel->Flush( true );

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -21,30 +21,55 @@ 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.") );
sbSizer1->Add( m_cbDeleteExtraFootprints, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
bUpperSizer->Add( sbOptions, 1, wxEXPAND|wxALL, 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_cbOverrideLocks = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Delete/replace footprints even if locked"), wxDefaultPosition, wxDefaultSize, 0 );
sbSizer1->Add( m_cbOverrideLocks, 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( sbSizer1, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
bUpperSizer->Add( sbFootprints, 0, wxEXPAND|wxALL, 5 );
bUpperSizer->Add( 0, 5, 0, wxEXPAND, 5 );
wxStaticBoxSizer* sbFields;
sbFields = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Update Fields") ), wxVERTICAL );
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 );
@ -75,8 +100,8 @@ 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_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 );
}
@ -85,8 +110,8 @@ 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_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 );

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -36,9 +36,11 @@ class DIALOG_UPDATE_PCB_BASE : public DIALOG_SHIM
protected:
wxCheckBox* m_cbRelinkFootprints;
wxCheckBox* m_cbDeleteExtraFootprints;
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;

View File

@ -597,18 +597,20 @@ bool FOOTPRINT::FootprintNeedsUpdate( const FOOTPRINT* aLibFP, int aCompareFlags
// due to rounding and shape modifications
std::unique_ptr<FOOTPRINT> temp( static_cast<FOOTPRINT*>( 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();
@ -652,6 +654,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.
//
@ -661,20 +666,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." ) );
}
@ -682,21 +687,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." ) );
}
}
@ -709,9 +714,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.
//

View File

@ -59,6 +59,8 @@ BOARD_NETLIST_UPDATER::BOARD_NETLIST_UPDATER( PCB_EDIT_FRAME* aFrame, BOARD* aBo
m_replaceFootprints = true;
m_lookupByTimestamp = false;
m_overrideLocks = false;
m_updateFields = false;
m_removeExtraFields = false;
m_warningCount = 0;
m_errorCount = 0;
@ -501,8 +503,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() )
@ -512,69 +517,78 @@ 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 );
changed = true;
// Add or change field value
for( auto& [name, value] : compFields )
if( m_updateFields )
{
if( aPcbFootprint->HasFieldByName( name ) )
msg.Printf( _( "Updated %s fields." ), aPcbFootprint->GetReference() );
m_reporter->Report( msg, RPT_SEVERITY_ACTION );
changed = true;
// Add or change field value
for( auto& [name, value] : compFields )
{
aPcbFootprint->GetFieldByName( name )->SetText( value );
}
else
{
int idx = aPcbFootprint->GetNextFieldId();
PCB_FIELD* newField = aPcbFootprint->AddField( PCB_FIELD( aPcbFootprint, idx ) );
if( aPcbFootprint->HasFieldByName( name ) )
{
aPcbFootprint->GetFieldByName( name )->SetText( value );
}
else
{
int idx = aPcbFootprint->GetNextFieldId();
PCB_FIELD* newField = aPcbFootprint->AddField( PCB_FIELD( aPcbFootprint, idx ) );
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 fields that aren't present in the symbol
bool warned = false;
for( PCB_FIELD* field : aPcbFootprint->GetFields() )
if( m_removeExtraFields )
{
if( field->IsMandatory() )
continue;
bool warned = false;
if( compFields.count( field->GetName() ) == 0 )
for( PCB_FIELD* field : aPcbFootprint->GetFields() )
{
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->RemoveField( field->GetCanonicalName() );
if( m_frame )
m_frame->GetCanvas()->GetView()->Remove( field );
}
aPcbFootprint->RemoveField( field->GetCanonicalName() );
if( m_frame )
m_frame->GetCanvas()->GetView()->Remove( field );
}
}
}
@ -736,7 +750,7 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint,
if( changed && copy )
m_commit.Modified( aPcbFootprint, copy );
else if( copy )
else
delete copy;
return true;

View File

@ -91,6 +91,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<FOOTPRINT*> GetAddedFootprints() const { return m_addedFootprints; }
private:
@ -136,6 +140,8 @@ private:
bool m_replaceFootprints;
bool m_lookupByTimestamp;
bool m_overrideLocks;
bool m_updateFields;
bool m_removeExtraFields;
int m_warningCount;
int m_errorCount;

View File

@ -2416,6 +2416,8 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew,
newPad->SetNetCode( NETINFO_LIST::UNCONNECTED );
}
std::set<PCB_TEXT*> handledTextItems;
for( BOARD_ITEM* oldItem : aExisting->GraphicalItems() )
{
PCB_TEXT* oldTextItem = dynamic_cast<PCB_TEXT*>( oldItem );
@ -2430,6 +2432,7 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew,
if( newTextItem )
{
handledTextItems.insert( newTextItem );
processTextItem( *oldTextItem, *newTextItem, resetTextContent, resetTextLayers,
resetTextEffects, aUpdated );
}
@ -2439,7 +2442,28 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew,
}
else
{
aNew->Add( static_cast<BOARD_ITEM*>( oldTextItem->Clone() ) );
newTextItem = static_cast<PCB_TEXT*>( 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<PCB_TEXT*>( newItem );
if( newTextItem )
{
// Dimensions have PCB_TEXT base but are not treated like texts in the updater
if( dynamic_cast<PCB_DIMENSION_BASE*>( newTextItem ) )
continue;
if( !handledTextItems.contains( newTextItem ) )
{
*aUpdated = true;
break;
}
}
}
@ -2455,6 +2479,8 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew,
aExisting->GetValue() == aExisting->GetFPID().GetLibItemName().wx_str(),
resetTextLayers, resetTextEffects, aUpdated );
std::set<PCB_FIELD*> handledFields;
// Copy fields in accordance with the reset* flags
for( PCB_FIELD* oldField : aExisting->GetFields() )
{
@ -2466,6 +2492,7 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew,
if( newField )
{
handledFields.insert( newField );
processTextItem( *oldField, *newField, resetTextContent, resetTextLayers,
resetTextEffects, aUpdated );
}
@ -2476,8 +2503,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;
}
}
@ -2532,6 +2573,13 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew,
aNew->SetFilters( aExisting->GetFilters() );
aNew->SetComponentClass( 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 );