58 m_commit( aFrame->GetToolManager() ),
85 const wxString previous = net->GetNetChain();
88 if( !previous.IsEmpty() &&
next.IsEmpty() && aReporter && !aDryRun )
92 _(
"Net chain assignment '%s' on net '%s' cleared by netlist "
94 previous, net->GetNetname() ),
100 net->SetNetChain(
next );
102 if( previous !=
next )
104 for(
int i = 0; i < 2; ++i )
105 net->ClearTerminalPad( i );
165 bestPosition.
x = pageSize.
x / 2;
166 bestPosition.
y = pageSize.
y / 2;
183 if( aFootprintId.
empty() )
185 msg.Printf(
_(
"Cannot add %s (no footprint assigned)." ),
194 if( footprint ==
nullptr )
196 msg.Printf(
_(
"Cannot add %s (footprint '%s' not found)." ),
205 m_board->GetComponentClassManager().GetNoneComponentClass() );
209 msg.Printf(
_(
"Add %s (footprint '%s')." ),
220 bool showRatsnest =
true;
223 showRatsnest =
m_settings->m_Display.m_ShowGlobalRatsnest;
225 pad->SetLocalRatsnestVisible( showRatsnest );
228 pad->SetNetCode( 0 );
243 msg.Printf(
_(
"Added %s (footprint '%s')." ),
256 wxString curClassName, newClassName;
260 curClassName = curClass->
GetName();
270 newClass =
m_board->GetComponentClassManager().GetEffectiveStaticComponentClass(
272 newClassName = newClass->
GetName();
275 if( curClassName == newClassName )
284 copy->SetParentGroup(
nullptr );
291 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
293 msg.Printf(
_(
"Change %s component class to '%s'." ),
297 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
299 msg.Printf(
_(
"Remove %s component class (currently '%s')." ),
305 msg.Printf(
_(
"Change %s component class from '%s' to '%s'." ),
313 wxASSERT_MSG( newClass !=
nullptr,
"Component class should not be nullptr" );
317 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
319 msg.Printf(
_(
"Changed %s component class to '%s'." ),
323 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
325 msg.Printf(
_(
"Removed %s component class (was '%s')." ),
331 msg.Printf(
_(
"Changed %s component class from '%s' to '%s'." ),
354 msg.Printf(
_(
"Cannot update %s (no footprint assigned)." ),
363 if( newFootprint ==
nullptr )
365 msg.Printf(
_(
"Cannot update %s (footprint '%s' not found)." ),
377 msg.Printf(
_(
"Cannot change %s footprint from '%s' to '%s' (footprint is locked)."),
388 msg.Printf(
_(
"Change %s footprint from '%s' to '%s'."),
402 msg.Printf(
_(
"Could not change %s footprint from '%s' to '%s' (footprint is locked)."),
416 m_board->ExchangeFootprint( aFootprint, newFootprint,
m_commit,
true );
418 msg.Printf(
_(
"Changed %s footprint from '%s' to '%s'."),
443 firstAssociatedVariant = &
test;
452 if( !
m_commit.GetStatus( aFootprint ) )
455 copy->SetParentGroup(
nullptr );
458 bool changed =
false;
465 msg.Printf(
_(
"Change %s reference designator to %s." ),
471 msg.Printf(
_(
"Changed %s reference designator to %s." ),
483 wxString netlistValue = aNetlistComponent->
GetValue();
485 if( firstAssociatedVariant !=
nullptr
491 if( aFootprint->
GetValue() != netlistValue )
495 msg.Printf(
_(
"Change %s value from %s to %s." ),
502 msg.Printf(
_(
"Changed %s value from %s to %s." ),
508 aFootprint->
SetValue( netlistValue );
517 if( !aNetlistComponent->
GetKIIDs().empty() )
518 new_path.push_back( aNetlistComponent->
GetKIIDs().front() );
520 if( aFootprint->
GetPath() != new_path )
524 msg.Printf(
_(
"Update %s symbol association from %s to %s." ),
531 msg.Printf(
_(
"Updated %s symbol association from %s to %s." ),
537 aFootprint->
SetPath( new_path );
543 nlohmann::ordered_map<wxString, wxString> fpFieldsAsMap;
548 if( field->IsReference() || field->IsValue() || field->IsComponentClass() )
553 fpFieldsAsMap[field->GetName()] = field->GetText();
557 nlohmann::ordered_map<wxString, wxString> compFields = aNetlistComponent->
GetFields();
563 compFields.erase( wxT(
"Component Class" ) );
565 if( firstAssociatedVariant !=
nullptr )
567 for(
const auto& [
name, value] : firstAssociatedVariant->
m_fields )
568 compFields[
name] = value;
574 bool remove_only =
true;
576 for(
const auto& [
name, value] : compFields )
578 if( fpFieldsAsMap.count(
name ) == 0 || fpFieldsAsMap[
name] != value )
586 for(
const auto& [
name, value] : fpFieldsAsMap )
588 if( compFields.count(
name ) == 0 )
601 msg.Printf(
_(
"Update %s fields." ), aFootprint->
GetReference() );
608 if( field->IsMandatory() )
611 if( compFields.count( field->GetName() ) == 0 )
615 msg.Printf(
_(
"Remove %s footprint fields not in symbol." ), aFootprint->
GetReference() );
627 msg.Printf(
_(
"Updated %s fields." ), aFootprint->
GetReference() );
633 for(
auto& [
name, value] : compFields )
642 aFootprint->
Add( newField );
663 std::vector<PCB_FIELD*> fieldList;
664 aFootprint->
GetFields( fieldList,
false );
668 if( field->IsMandatory() )
671 if( compFields.count( field->GetName() ) == 0 )
676 msg.Printf(
_(
"Removed %s footprint fields not in symbol." ), aFootprint->
GetReference() );
680 aFootprint->
Remove( field );
683 m_frame->GetCanvas()->GetView()->Remove( field );
698 if( !humanSheetPath.empty() )
699 sheetname = humanSheetPath;
700 else if( aNetlistComponent->
GetProperties().count( wxT(
"Sheetname" ) ) > 0 )
701 sheetname = aNetlistComponent->
GetProperties().at( wxT(
"Sheetname" ) );
703 if( aNetlistComponent->
GetProperties().count( wxT(
"Sheetfile" ) ) > 0 )
704 sheetfile = aNetlistComponent->
GetProperties().at( wxT(
"Sheetfile" ) );
706 if( aNetlistComponent->
GetProperties().count( wxT(
"ki_fp_filters" ) ) > 0 )
707 fpFilters = aNetlistComponent->
GetProperties().at( wxT(
"ki_fp_filters" ) );
713 msg.Printf(
_(
"Update %s sheetname to '%s'." ),
720 msg.Printf(
_(
"Updated %s sheetname to '%s'." ),
732 msg.Printf(
_(
"Update %s sheetfile to '%s'." ),
739 msg.Printf(
_(
"Updated %s sheetfile to '%s'." ),
751 msg.Printf(
_(
"Update %s footprint filters to '%s'." ),
758 msg.Printf(
_(
"Updated %s footprint filters to '%s'." ),
766 bool netlistExcludeFromBOM = aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_bom" ) ) > 0;
775 if( netlistExcludeFromBOM )
776 msg.Printf(
_(
"Add %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
778 msg.Printf(
_(
"Remove %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
784 if( netlistExcludeFromBOM )
787 msg.Printf(
_(
"Added %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
792 msg.Printf(
_(
"Removed %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
802 bool netlistDNP = aNetlistComponent->
GetProperties().count( wxT(
"dnp" ) ) > 0;
804 if( firstAssociatedVariant !=
nullptr && firstAssociatedVariant->
m_hasDnp )
805 netlistDNP = firstAssociatedVariant->
m_dnp;
812 msg.Printf(
_(
"Add %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
814 msg.Printf(
_(
"Remove %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
823 msg.Printf(
_(
"Added %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
828 msg.Printf(
_(
"Removed %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
838 bool netlistExcludeFromPosFiles = aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_pos_files" ) ) > 0;
848 if( netlistExcludeFromPosFiles )
850 msg.Printf(
_(
"Add %s 'exclude from position files' fabrication attribute." ),
855 msg.Printf(
_(
"Remove %s 'exclude from position files' fabrication attribute." ),
863 if( netlistExcludeFromPosFiles )
866 msg.Printf(
_(
"Added %s 'exclude from position files' fabrication attribute." ),
872 msg.Printf(
_(
"Removed %s 'exclude from position files' fabrication attribute." ),
895 msg.Printf(
_(
"Added %s 'duplicate pad numbers are jumpers' attribute." ),
900 msg.Printf(
_(
"Removed %s 'duplicate pad numbers are jumpers' attribute." ),
908 msg.Printf(
_(
"Add %s 'duplicate pad numbers are jumpers' attribute." ),
913 msg.Printf(
_(
"Remove %s 'duplicate pad numbers are jumpers' attribute." ),
927 msg.Printf(
_(
"Updated %s jumper pad groups" ), aFootprint->
GetReference() );
931 msg.Printf(
_(
"Update %s jumper pad groups" ), aFootprint->
GetReference() );
937 if( changed &&
copy )
957 if( !
m_commit.GetStatus( aPcbFootprint ) )
960 copy->SetParentGroup(
nullptr );
963 bool changed =
false;
972 KIID existingGroupKIID = existingGroup ? existingGroup->
m_Uuid : 0;
975 auto it = std::find_if(
m_board->Groups().begin(),
m_board->Groups().end(),
977 return group->m_Uuid == newGroupKIID;
981 if( it !=
m_board->Groups().end() )
985 if( newGroupKIID == existingGroupKIID )
989 if( existingGroupKIID != 0 )
993 msg.Printf(
_(
"Remove %s from group '%s'." ),
999 msg.Printf(
_(
"Removed %s from group '%s'." ),
1007 if( existingGroup->
GetItems().size() < 2 )
1018 if( newGroupKIID != 0 )
1022 msg.Printf(
_(
"Add %s to group '%s'." ),
1028 msg.Printf(
_(
"Added %s to group '%s'." ),
1034 if( newGroup ==
nullptr )
1037 newGroup->
SetUuid( newGroupKIID );
1051 newGroup->
AddItem( aPcbFootprint );
1057 if( changed &&
copy )
1077 copy->SetParentGroup(
nullptr );
1080 bool changed =
false;
1083 std::deque<PAD*> pads = aFootprint->
Pads();
1084 std::set<wxString> padNetnames;
1086 std::sort( pads.begin(), pads.end(),
1089 return a->m_Uuid < b->m_Uuid;
1096 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1097 wxT(
"Processing pad %s of component %s" ),
1101 wxString pinFunction;
1106 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1107 wxT(
" Found valid net: %s" ),
1114 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1115 wxT(
" No net found for pad %s" ),
1121 if(
pad->GetPinFunction() != pinFunction )
1124 pad->SetPinFunction( pinFunction );
1127 if(
pad->GetPinType() != pinType )
1130 pad->SetPinType( pinType );
1139 if( !net.
IsValid() || !
pad->IsOnCopperLayer() )
1141 if( !
pad->GetNetname().IsEmpty() )
1145 msg.Printf(
_(
"Disconnect %s pin %s." ),
1151 msg.Printf(
_(
"Disconnected %s pin %s." ),
1158 else if(
pad->IsOnCopperLayer() && !
pad->GetNumber().IsEmpty() )
1161 msg.Printf(
_(
"No net found for component %s pad %s (no pin %s in symbol)." ),
1176 if(
pad->GetNetname().IsEmpty() )
1177 pad->SetPinFunction( wxEmptyString );
1189 if(
pad->IsNoConnectPad() )
1191 netName = wxString::Format( wxS(
"%s" ), net.
GetNetName() );
1193 for(
int jj = 1; !padNetnames.insert( netName ).second
1197 netName = wxString::Format( wxS(
"%s_%d" ), net.
GetNetName(), jj );
1206 if(
pad->GetNetname() != netName )
1209 if( netinfo ==
nullptr )
1216 if( netinfo ==
nullptr )
1228 msg.Printf(
_(
"Add net %s." ),
1233 if( !
pad->GetNetname().IsEmpty() )
1239 msg.Printf(
_(
"Reconnect %s pin %s from %s to %s."),
1247 msg.Printf(
_(
"Reconnected %s pin %s from %s to %s."),
1258 msg.Printf(
_(
"Connect %s pin %s to %s."),
1265 msg.Printf(
_(
"Connected %s pin %s to %s."),
1277 pad->SetNet( netinfo );
1287 if( changed &&
copy )
1299 std::vector<FOOTPRINT::FP_UNIT_INFO> newUnits;
1302 newUnits.push_back( { u.m_unitName, u.m_pins } );
1304 const std::vector<FOOTPRINT::FP_UNIT_INFO>& curUnits = aFootprint->
GetUnitInfo();
1306 auto unitsEqual = [](
const std::vector<FOOTPRINT::FP_UNIT_INFO>& a,
1307 const std::vector<FOOTPRINT::FP_UNIT_INFO>& b )
1309 if( a.size() != b.size() )
1312 for(
size_t i = 0; i < a.size(); ++i )
1314 if( a[i].m_unitName != b[i].m_unitName )
1317 if( a[i].m_pins != b[i].m_pins )
1324 if( unitsEqual( curUnits, newUnits ) )
1331 msg.Printf(
_(
"Update %s unit metadata." ), aFootprint->
GetReference() );
1339 if( !
m_commit.GetStatus( aFootprint ) )
1342 copy->SetParentGroup(
nullptr );
1347 msg.Printf(
_(
"Updated %s unit metadata." ), aFootprint->
GetReference() );
1362 return aBoardFpid == aSchematicFpid;
1367 const std::vector<FOOTPRINT*>& aFootprints,
1368 const LIB_ID& aBaseFpid )
1373 if( aBaseFpid.
empty() )
1385 std::vector<VARIANT_INFO> variantInfo;
1386 variantInfo.reserve( variants.size() );
1388 for(
const auto& [variantName, variant] : variants )
1390 LIB_ID variantFPID = aBaseFpid;
1392 auto fieldIt = variant.m_fields.find( footprintFieldName );
1394 if( fieldIt != variant.m_fields.end() && !fieldIt->second.IsEmpty() )
1398 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
1400 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
1409 variantFPID = parsedId;
1413 variantInfo.push_back( { variantName, &variant, variantFPID } );
1416 for(
FOOTPRINT* footprint : aFootprints )
1426 copy->SetParentGroup(
nullptr );
1429 bool changed =
false;
1431 auto printAttributeMessage =
1432 [&](
bool add,
const wxString& attrName,
const wxString& variantName )
1436 if( aFootprints.size() > 1 )
1438 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s (footprint %s)." )
1439 :
_(
"Remove %s '%s' attribute from variant %s (footprint %s)." ),
1440 footprint->GetReference(),
1443 footprint->GetFPIDAsString() );
1447 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s." )
1448 :
_(
"Remove %s '%s' attribute from variant %s." ),
1449 footprint->GetReference(),
1456 if( aFootprints.size() > 1 )
1458 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s (footprint %s)." )
1459 :
_(
"Removed %s '%s' attribute from variant %s (footprint %s)." ),
1460 footprint->GetReference(),
1463 footprint->GetFPIDAsString() );
1467 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s." )
1468 :
_(
"Removed %s '%s' attribute from variant %s." ),
1469 footprint->GetReference(),
1476 std::set<wxString> excessVariants;
1478 for(
const auto& [variantName,
_] : footprint->GetVariants() )
1479 excessVariants.insert( variantName );
1481 for(
const VARIANT_INFO&
info : variantInfo )
1494 if( !isAssociatedFootprint )
1497 excessVariants.erase(
info.name );
1498 bool targetDnp = variant.
m_hasDnp ? variant.
m_dnp : footprint->IsDNP();
1499 bool currentDnp = currentVariant ? currentVariant->
GetDNP() : footprint->IsDNP();
1501 if( currentDnp != targetDnp )
1503 printAttributeMessage( targetDnp,
_(
"Do not place" ),
info.name );
1508 fpVariant->SetDNP( targetDnp );
1516 : footprint->IsExcludedFromBOM();
1518 : footprint->IsExcludedFromBOM();
1520 if( currentExcludedFromBOM != targetExcludedFromBOM )
1522 printAttributeMessage( targetExcludedFromBOM,
_(
"exclude from BOM" ),
info.name );
1527 fpVariant->SetExcludedFromBOM( targetExcludedFromBOM );
1535 : footprint->IsExcludedFromPosFiles();
1537 : footprint->IsExcludedFromPosFiles();
1539 if( currentExcludedFromPosFiles != targetExcludedFromPosFiles )
1541 printAttributeMessage( targetExcludedFromPosFiles,
_(
"exclude from position files" ),
info.name );
1546 fpVariant->SetExcludedFromPosFiles( targetExcludedFromPosFiles );
1553 for(
const auto& [fieldName, fieldValue] : variant.
m_fields )
1555 if( fieldName.CmpNoCase( footprintFieldName ) == 0 )
1558 bool hasCurrentValue = currentVariant && currentVariant->
HasFieldValue( fieldName );
1559 wxString currentValue = hasCurrentValue ? currentVariant->
GetFieldValue( fieldName ) : wxString();
1561 if( currentValue != fieldValue )
1565 if( aFootprints.size() > 1 )
1567 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s (footprint %s)." ),
1568 footprint->GetReference(),
1572 footprint->GetFPIDAsString() );
1576 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s." ),
1577 footprint->GetReference(),
1585 if( aFootprints.size() > 1 )
1587 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s (footprint %s)." ),
1588 footprint->GetReference(),
1592 footprint->GetFPIDAsString() );
1596 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s." ),
1597 footprint->GetReference(),
1604 fpVariant->SetFieldValue( fieldName, fieldValue );
1613 for(
const wxString& excess : excessVariants )
1617 msg.Printf(
_(
"Remove variant %s:%s no longer associated with footprint %s." ),
1618 footprint->GetReference(),
1620 footprint->GetFPIDAsString() );
1624 msg.Printf(
_(
"Removed variant %s:%s no longer associated with footprint %s." ),
1625 footprint->GetReference(),
1627 footprint->GetFPIDAsString() );
1629 footprint->DeleteVariant( excess );
1638 bool isBaseFootprint =
fpidsEquivalent( footprint->GetFPID(), aBaseFpid );
1640 if( !isBaseFootprint && !footprint->IsDNP() )
1642 msg.Printf(
m_isDryRun ?
_(
"Add %s 'Do not place' fabrication attribute." )
1643 :
_(
"Added %s 'Do not place' fabrication attribute." ),
1644 footprint->GetReference() );
1649 footprint->SetDNP(
true );
1666 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1677 std::set<wxString> netlistNetnames;
1679 for(
int ii = 0; ii < (int) aNetlist.
GetCount(); ii++ )
1683 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1695 if( netlistNetnames.count(
via->GetNetname() ) == 0 )
1697 wxString updatedNetname = wxEmptyString;
1706 if( !updatedNetname.IsEmpty() )
1710 wxString originalNetname =
via->GetNetname();
1712 msg.Printf(
_(
"Reconnect via from %s to %s." ),
1727 wxString originalNetname =
via->GetNetname();
1730 via->SetNet( netinfo );
1732 msg.Printf(
_(
"Reconnected via from %s to %s." ),
1742 msg.Printf(
_(
"Via connected to unknown net (%s)." ),
1754 auto isInNetlist = [&](
const wxString& aNetName ) ->
bool
1756 if( netlistNetnames.count( aNetName ) )
1761 for(
const wxString& netName : netlistNetnames )
1763 if( aNetName.StartsWith( netName ) )
1773 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1776 if( !isInNetlist( zone->GetNetname() ) )
1781 wxString updatedNetname = wxEmptyString;
1794 if( updatedNetname.IsEmpty() &&
m_oldToNewNets.count( zone->GetNetname() ) )
1799 if( !updatedNetname.IsEmpty() )
1803 wxString originalNetname = zone->GetNetname();
1805 if( !zone->GetZoneName().IsEmpty() )
1807 msg.Printf(
_(
"Reconnect copper zone '%s' from %s to %s." ),
1808 zone->GetZoneName(),
1814 msg.Printf(
_(
"Reconnect copper zone from %s to %s." ),
1830 wxString originalNetname = zone->GetNetname();
1833 zone->SetNet( netinfo );
1835 if( !zone->GetZoneName().IsEmpty() )
1837 msg.Printf(
_(
"Reconnected copper zone '%s' from %s to %s." ),
1844 msg.Printf(
_(
"Reconnected copper zone from %s to %s." ),
1855 if( !zone->GetZoneName().IsEmpty() )
1857 msg.Printf(
_(
"Copper zone '%s' has no pads connected." ),
1862 wxString layerNames = zone->LayerMaskDescribe();
1867 if(
m_settings->m_Display.m_DisplayInvertXAxis )
1870 if(
m_settings->m_Display.m_DisplayInvertYAxis )
1874 msg.Printf(
_(
"Copper zone on %s at (%s, %s) has no pads connected to net \"%s\"." ),
1884 zone->GetNetname() );
1908 if( netlistGroup ==
nullptr )
1911 if( netlistGroup->
name != pcbGroup->GetName() )
1915 msg.Printf(
_(
"Change group name from '%s' to '%s'." ),
1921 msg.Printf(
_(
"Changed group name from '%s' to '%s'." ),
1925 pcbGroup->SetName( netlistGroup->
name );
1931 if( netlistGroup->
libId != pcbGroup->GetDesignBlockLibId() )
1935 msg.Printf(
_(
"Change group library link from '%s' to '%s'." ),
1936 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1941 msg.Printf(
_(
"Changed group library link from '%s' to '%s'." ),
1942 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1945 pcbGroup->SetDesignBlockLibId( netlistGroup->
libId );
1957 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
1965 for(
int i = 0; i < (int) aNetlist.
GetCount(); i++ )
1968 FOOTPRINT* footprint = aFootprintMap[component];
1974 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1978 if( padNumber.IsEmpty() )
1981 msg.Printf(
_(
"Symbol %s has pins with no number. These pins can not be matched "
1991 msg.Printf(
_(
"%s pad %s not found in %s." ),
2007 FOOTPRINT* lastPreexistingFootprint =
nullptr;
2010 std::unordered_set<wxString> sheetPaths;
2011 std::unordered_set<FOOTPRINT*> usedFootprints;
2017 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
2019 if( !
m_board->Footprints().empty() )
2020 lastPreexistingFootprint =
m_board->Footprints().back();
2030 net->SetIsCurrent( net->GetNetCode() == 0 );
2032 m_board->GetComponentClassManager().InitNetlistUpdate();
2036 for(
unsigned ii = 0; ii < aNetlist.
GetCount(); ii++ )
2040 for(
unsigned jj = 0; jj <
comp->GetNetCount(); jj++ )
2047 for(
unsigned i = 0; i < aNetlist.
GetCount(); i++ )
2051 if( component->
GetProperties().count( wxT(
"exclude_from_board" ) ) )
2054 msg.Printf(
_(
"Processing symbol '%s:%s'." ),
2060 const bool hasBaseFpid = !baseFpid.
empty();
2064 msg.Printf(
_(
"Warning: %s footprint '%s' is missing a library name. "
2065 "Use the full 'Library:Footprint' format to avoid repeated update "
2073 std::vector<FOOTPRINT*> matchingFootprints;
2084 base.push_back( uuid );
2086 if( footprint->GetPath() == base )
2095 match = footprint->GetReference().CmpNoCase( component->
GetReference() ) == 0;
2099 matchingFootprints.push_back( footprint );
2101 if( footprint == lastPreexistingFootprint )
2108 std::vector<LIB_ID> expectedFpids;
2109 std::unordered_set<wxString> expectedFpidKeys;
2111 auto addExpectedFpid =
2112 [&](
const LIB_ID& aFpid )
2117 wxString key = aFpid.Format();
2119 if( expectedFpidKeys.insert( key ).second )
2120 expectedFpids.push_back( aFpid );
2123 addExpectedFpid( baseFpid );
2127 for(
const auto& [variantName, variant] : component->
GetVariants() )
2129 auto fieldIt = variant.m_fields.find( footprintFieldName );
2131 if( fieldIt == variant.m_fields.end() || fieldIt->second.IsEmpty() )
2136 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
2138 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
2147 addExpectedFpid( parsedId );
2150 auto isExpectedFpid =
2151 [&](
const LIB_ID& aFpid ) ->
bool
2156 if( expectedFpidKeys.count( aFpid.Format() ) > 0 )
2168 auto takeMatchingFootprint =
2171 for(
FOOTPRINT* footprint : matchingFootprints )
2173 if( usedFootprints.count( footprint ) )
2183 std::vector<FOOTPRINT*> componentFootprints;
2184 componentFootprints.reserve( expectedFpids.size() );
2188 baseFootprint = takeMatchingFootprint( baseFpid );
2189 else if( !matchingFootprints.empty() )
2190 baseFootprint = matchingFootprints.front();
2196 for(
FOOTPRINT* footprint : matchingFootprints )
2198 if( usedFootprints.count( footprint ) )
2201 if( isExpectedFpid( footprint->GetFPID() ) )
2204 replaceCandidate = footprint;
2208 if( replaceCandidate )
2213 baseFootprint = replaced;
2215 baseFootprint = replaceCandidate;
2219 if( !baseFootprint && ( hasBaseFpid || expectedFpids.empty() ) )
2224 componentFootprints.push_back( baseFootprint );
2225 usedFootprints.insert( baseFootprint );
2226 footprintMap[ component ] = baseFootprint;
2229 for(
const LIB_ID& fpid : expectedFpids )
2237 FOOTPRINT* footprint = takeMatchingFootprint( fpid );
2244 componentFootprints.push_back( footprint );
2245 usedFootprints.insert( footprint );
2249 for(
FOOTPRINT* footprint : componentFootprints )
2260 sheetPaths.insert( footprint->GetSheetname() );
2263 if( !componentFootprints.empty() )
2275 bool matched =
false;
2281 bool isStaleVariantFootprint =
false;
2283 if( usedFootprints.count( footprint ) )
2294 if( component && component->
GetProperties().count( wxT(
"exclude_from_board" ) ) == 0 )
2302 isStaleVariantFootprint =
true;
2313 if( isStaleVariantFootprint )
2316 if( doDelete && !matched && footprint->IsLocked() && !
m_overrideLocks )
2320 msg.Printf(
_(
"Cannot remove unused footprint %s (footprint is locked)." ),
2321 footprint->GetReference() );
2325 msg.Printf(
_(
"Could not remove unused footprint %s (footprint is locked)." ),
2326 footprint->GetReference() );
2334 if( doDelete && !matched )
2338 msg.Printf(
_(
"Remove unused footprint %s." ),
2339 footprint->GetReference() );
2344 msg.Printf(
_(
"Removed unused footprint %s." ),
2345 footprint->GetReference() );
2355 for(
PAD*
pad : footprint->Pads() )
2358 pad->GetNet()->SetIsCurrent(
true );
2366 m_board->GetComponentClassManager().FinishNetlistUpdate();
2367 m_board->SynchronizeComponentClasses( sheetPaths );
2374 if( !net->IsCurrent() )
2376 msg.Printf(
_(
"Removed unused net %s." ),
2385 const std::vector<wxString>& netlistVariants = aNetlist.
GetVariantNames();
2387 if( !netlistVariants.empty() || !
m_board->GetVariantNames().empty() )
2391 auto findBoardVariantName =
2392 [&](
const wxString& aVariantName ) -> wxString
2394 for(
const wxString&
name :
m_board->GetVariantNames() )
2396 if(
name.CmpNoCase( aVariantName ) == 0 )
2400 return wxEmptyString;
2403 std::vector<wxString> updatedVariantNames;
2404 updatedVariantNames.reserve( netlistVariants.size() );
2406 for(
const wxString& variantName : netlistVariants )
2408 wxString actualName = findBoardVariantName( variantName );
2410 if( actualName.IsEmpty() )
2412 m_board->AddVariant( variantName );
2413 actualName = findBoardVariantName( variantName );
2415 if( !actualName.IsEmpty() )
2417 msg.Printf(
_(
"Added variant '%s'." ), actualName );
2422 if( actualName.IsEmpty() )
2427 wxString oldDescription =
m_board->GetVariantDescription( actualName );
2429 if( newDescription != oldDescription )
2431 m_board->SetVariantDescription( actualName, newDescription );
2432 msg.Printf(
_(
"Updated description for variant '%s'." ), actualName );
2436 updatedVariantNames.push_back( actualName );
2439 std::vector<wxString> variantsToRemove;
2441 for(
const wxString& existingName :
m_board->GetVariantNames() )
2445 for(
const wxString& variantName : netlistVariants )
2447 if( existingName.CmpNoCase( variantName ) == 0 )
2455 variantsToRemove.push_back( existingName );
2458 for(
const wxString& variantName : variantsToRemove )
2460 m_board->DeleteVariant( variantName );
2461 msg.Printf(
_(
"Removed variant '%s'." ), variantName );
2465 if( !updatedVariantNames.empty() )
2466 m_board->SetVariantNames( updatedVariantNames );
2485 if( !colorStr.IsEmpty() )
2499 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
2503 netSettings->ClearNetChainClasses();
2504 netSettings->ClearChainPatternAssignments();
2507 netSettings->SetNetChainClass(
chain, className );
2515 const wxString& chainName = net->GetNetChain();
2517 if( chainName.IsEmpty() )
2520 auto it = chainClasses.find( chainName );
2522 if( it == chainClasses.end() || it->second.IsEmpty() )
2525 if( netSettings->HasNetclass( it->second ) )
2526 netSettings->SetChainPatternAssignment( net->GetNetname(), it->second );
2531 m_board->SynchronizeNetsAndNetClasses(
true );
2535 m_board->SynchronizeNetsAndNetClasses(
true );
2540 PAD* pads[2] = {
nullptr,
nullptr };
2542 for(
size_t i = 0; i < sig.second.size() && i < 2; ++i )
2544 const wxString& ref = sig.second[i].first;
2545 const wxString&
pin = sig.second[i].second;
2551 PAD* candidate =
nullptr;
2552 PAD* best =
nullptr;
2553 int bestDist = std::numeric_limits<int>::max();
2562 if( !best || dist < bestDist || ( dist == bestDist && candidate->
m_Uuid < best->
m_Uuid ) )
2572 for(
int i = 0; i < 2; ++i )
2579 if( !termNet || termNet->
GetNetChain() != sig.first )
2584 if( net != termNet && net->
GetNetChain() == sig.first
2585 && net->GetTerminalPad( i ) )
2587 net->ClearTerminalPad( i );
2603 for(
const std::pair<const wxString, NETINFO_ITEM*>& addedNet :
m_addedNets )
2604 delete addedNet.second;
constexpr EDA_IU_SCALE pcbIUScale
wxString GetNetname() const
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
void SetUuid(const KIID &aUuid)
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
std::map< PAD *, wxString > m_padNets
PCBNEW_SETTINGS * m_settings
bool m_deleteUnusedFootprints
void cacheNetname(PAD *aPad, const wxString &aNetname)
bool UpdateNetlist(NETLIST &aNetlist)
Update the board's components according to the new netlist.
wxString getNetname(PAD *aPad)
wxString getPinFunction(PAD *aPad)
std::vector< FOOTPRINT * > m_addedFootprints
bool updateFootprintParameters(FOOTPRINT *aFootprint, COMPONENT *aNetlistComponent)
std::map< wxString, wxString > m_oldToNewNets
static void ApplyChainAssignments(BOARD *aBoard, const NETLIST &aNetlist, REPORTER *aReporter, bool aDryRun)
Apply the netlist's chain assignments to every NETINFO_ITEM on the board.
bool updateFootprintGroup(FOOTPRINT *aPcbFootprint, COMPONENT *aNetlistComponent)
static bool fpidsEquivalent(const LIB_ID &aBoardFpid, const LIB_ID &aSchematicFpid)
Compare a board footprint ID against a schematic-derived footprint ID, ignoring the library nickname ...
std::map< wxString, NETINFO_ITEM * > m_addedNets
std::vector< PCB_GROUP * > m_addedGroups
bool testConnectivity(NETLIST &aNetlist, std::map< COMPONENT *, FOOTPRINT * > &aFootprintMap)
bool updateCopperZoneNets(NETLIST &aNetlist)
void cachePinFunction(PAD *aPad, const wxString &aPinFunction)
bool updateGroups(NETLIST &aNetlist)
BOARD_NETLIST_UPDATER(PCB_EDIT_FRAME *aFrame, BOARD *aBoard)
Construct an updater for interactive use from the board editor.
bool updateComponentClass(FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
bool updateComponentPadConnections(FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
VECTOR2I estimateFootprintInsertionPosition()
std::map< PAD *, wxString > m_padPinFunctions
void applyComponentVariants(COMPONENT *aComponent, const std::vector< FOOTPRINT * > &aFootprints, const LIB_ID &aBaseFpid)
std::map< ZONE *, std::vector< PAD * > > m_zoneConnectionsCache
FOOTPRINT * replaceFootprint(NETLIST &aNetlist, FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
void cacheCopperZoneConnections()
bool updateComponentUnits(FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
FOOTPRINT * addNewFootprint(COMPONENT *aComponent)
std::set< wxString > m_schematicNetNames
Information pertinent to a Pcbnew printed circuit board.
const NETINFO_LIST & GetNetInfo() const
constexpr size_type GetWidth() const
constexpr Vec Centre() const
constexpr size_type GetHeight() const
constexpr coord_type GetLeft() const
constexpr coord_type GetRight() const
constexpr coord_type GetTop() const
constexpr coord_type GetBottom() const
static wxString GetFullClassNameForConstituents(const std::unordered_set< wxString > &classNames)
Gets the full effective class name for the given set of constituent classes.
A lightweight representation of a component class.
const wxString & GetName() const
Fetches the full name of this component class.
Used to store the component pin name to net name (and pin function) associations stored in a netlist.
const wxString & GetNetName() const
const wxString & GetPinFunction() const
const wxString & GetPinName() const
const wxString & GetPinType() const
Store all of the related component information found in a netlist.
const std::vector< UNIT_INFO > & GetUnitInfo() const
const wxString & GetHumanReadablePath() const
const COMPONENT_NET & GetNet(unsigned aIndex) const
const KIID_PATH & GetPath() const
const wxString & GetReference() const
const wxString & GetValue() const
const nlohmann::ordered_map< wxString, wxString > & GetFields() const
const std::map< wxString, wxString > & GetProperties() const
const CASE_INSENSITIVE_MAP< COMPONENT_VARIANT > & GetVariants() const
NETLIST_GROUP * GetGroup() const
const std::vector< KIID > & GetKIIDs() const
bool GetDuplicatePadNumbersAreJumpers() const
const LIB_ID & GetFPID() const
unsigned GetNetCount() const
std::unordered_set< wxString > & GetComponentClassNames()
std::vector< std::set< wxString > > & JumperPadGroups()
std::unordered_set< EDA_ITEM * > & GetItems()
void RemoveItem(EDA_ITEM *aItem)
Remove item from group.
void AddItem(EDA_ITEM *aItem)
Add item to group.
void SetName(const wxString &aName)
virtual EDA_GROUP * GetParentGroup() const
virtual void SetParent(EDA_ITEM *aParent)
virtual void SetVisible(bool aVisible)
virtual void SetText(const wxString &aText)
A color representation with 4 components: red, green, blue, alpha.
bool SetFromHexString(const wxString &aColorString)
wxString AsString() const
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
wxString GetUniStringLibId() const
const UTF8 & GetLibItemName() const
Handle the data for a net.
const wxString & GetNetChain() const
void SetTerminal(int aIndex, PAD *aPad)
Set the terminal-pad pointer and the persisted UUID at aIndex from a single pad, keeping the two view...
void SetIsCurrent(bool isCurrent)
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
const std::map< wxString, std::vector< std::pair< wxString, wxString > > > & GetNetChainTerminalPins() const
const std::vector< wxString > & GetVariantNames() const
unsigned GetCount() const
COMPONENT * GetComponentByPath(const KIID_PATH &aPath)
Return a COMPONENT by aPath.
COMPONENT * GetComponentByReference(const wxString &aReference)
Return a COMPONENT by aReference.
const std::map< wxString, wxString > & GetNetChainNetClasses() const
const std::map< wxString, wxString > & GetSignalChainClasses() const
NETLIST_GROUP * GetGroupByUuid(const KIID &aUuid)
Return a NETLIST_GROUP by aUuid.
const std::map< wxString, wxString > & GetNetChainColors() const
COMPONENT * GetComponent(unsigned aIndex)
Return the COMPONENT at aIndex.
wxString GetNetChainFor(const wxString &aNet) const
wxString GetVariantDescription(const wxString &aVariantName) const
A singleton reporter that reports to nowhere.
const wxString & GetPinFunction() const
VECTOR2I GetPosition() const override
The main frame for Pcbnew.
void SetName(const wxString &aName)
A set of BOARD_ITEMs (i.e., without duplicates).
EDA_ITEM * AsEdaItem() override
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
virtual void SetPosition(const VECTOR2I &aPos) override
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Handle a list of polygons defining a copper zone.
KICOMMON_API wxString MessageTextFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A helper to convert the double length aValue to a string in inches, millimeters, or unscaled units.
Class to handle a set of BOARD_ITEMs.
FOOTPRINT * LoadFootprintFromProject(BOARD *aBoard, const LIB_ID &aFootprintId, bool aKeepUuid)
Load a footprint from the project library table and apply board default settings.
T * GetAppSettings(const char *aFilename)
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
wxString UnescapeString(const wxString &aSource)
bool m_excludedFromPosFiles
bool m_hasExcludedFromBOM
bool m_hasExcludedFromPosFiles
nlohmann::ordered_map< wxString, wxString > m_fields
@ USER
The field ID hasn't been set yet; field is invalid.
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
wxString GetCanonicalFieldName(FIELD_T aFieldType)
VECTOR3I expected(15, 30, 45)
const SHAPE_LINE_CHAIN chain
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
VECTOR2< int32_t > VECTOR2I