134 bestPosition.
x = pageSize.
x / 2;
135 bestPosition.
y = pageSize.
y / 2;
152 if( aFootprintId.
empty() )
154 msg.Printf(
_(
"Cannot add %s (no footprint assigned)." ),
163 if( footprint ==
nullptr )
165 msg.Printf(
_(
"Cannot add %s (footprint '%s' not found)." ),
174 m_board->GetComponentClassManager().GetNoneComponentClass() );
178 msg.Printf(
_(
"Add %s (footprint '%s')." ),
190 pad->SetLocalRatsnestVisible(
m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest );
193 pad->SetNetCode( 0 );
208 msg.Printf(
_(
"Added %s (footprint '%s')." ),
221 wxString curClassName, newClassName;
225 curClassName = curClass->
GetName();
235 newClass =
m_board->GetComponentClassManager().GetEffectiveStaticComponentClass(
237 newClassName = newClass->
GetName();
240 if( curClassName == newClassName )
249 copy->SetParentGroup(
nullptr );
256 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
258 msg.Printf(
_(
"Change %s component class to '%s'." ),
262 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
264 msg.Printf(
_(
"Remove %s component class (currently '%s')." ),
270 msg.Printf(
_(
"Change %s component class from '%s' to '%s'." ),
278 wxASSERT_MSG( newClass !=
nullptr,
"Component class should not be nullptr" );
282 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
284 msg.Printf(
_(
"Changed %s component class to '%s'." ),
288 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
290 msg.Printf(
_(
"Removed %s component class (was '%s')." ),
296 msg.Printf(
_(
"Changed %s component class from '%s' to '%s'." ),
319 msg.Printf(
_(
"Cannot update %s (no footprint assigned)." ),
328 if( newFootprint ==
nullptr )
330 msg.Printf(
_(
"Cannot update %s (footprint '%s' not found)." ),
342 msg.Printf(
_(
"Cannot change %s footprint from '%s' to '%s' (footprint is locked)."),
353 msg.Printf(
_(
"Change %s footprint from '%s' to '%s'."),
367 msg.Printf(
_(
"Could not change %s footprint from '%s' to '%s' (footprint is locked)."),
381 m_frame->ExchangeFootprint( aFootprint, newFootprint,
m_commit,
true );
383 msg.Printf(
_(
"Changed %s footprint from '%s' to '%s'."),
408 firstAssociatedVariant = &
test;
417 if( !
m_commit.GetStatus( aFootprint ) )
420 copy->SetParentGroup(
nullptr );
423 bool changed =
false;
430 msg.Printf(
_(
"Change %s reference designator to %s." ),
436 msg.Printf(
_(
"Changed %s reference designator to %s." ),
448 wxString netlistValue = aNetlistComponent->
GetValue();
450 if( firstAssociatedVariant !=
nullptr
456 if( aFootprint->
GetValue() != netlistValue )
460 msg.Printf(
_(
"Change %s value from %s to %s." ),
467 msg.Printf(
_(
"Changed %s value from %s to %s." ),
473 aFootprint->
SetValue( netlistValue );
482 if( !aNetlistComponent->
GetKIIDs().empty() )
483 new_path.push_back( aNetlistComponent->
GetKIIDs().front() );
485 if( aFootprint->
GetPath() != new_path )
489 msg.Printf(
_(
"Update %s symbol association from %s to %s." ),
496 msg.Printf(
_(
"Updated %s symbol association from %s to %s." ),
502 aFootprint->
SetPath( new_path );
508 nlohmann::ordered_map<wxString, wxString> fpFieldsAsMap;
513 if( field->IsReference() || field->IsValue() || field->IsComponentClass() )
518 fpFieldsAsMap[field->GetName()] = field->GetText();
522 nlohmann::ordered_map<wxString, wxString> compFields = aNetlistComponent->
GetFields();
528 compFields.erase( wxT(
"Component Class" ) );
530 if( firstAssociatedVariant !=
nullptr )
532 for(
const auto& [
name, value] : firstAssociatedVariant->
m_fields )
533 compFields[
name] = value;
539 bool remove_only =
true;
541 for(
const auto& [
name, value] : compFields )
543 if( fpFieldsAsMap.count(
name ) == 0 || fpFieldsAsMap[
name] != value )
551 for(
const auto& [
name, value] : fpFieldsAsMap )
553 if( compFields.count(
name ) == 0 )
566 msg.Printf(
_(
"Update %s fields." ), aFootprint->
GetReference() );
573 if( field->IsMandatory() )
576 if( compFields.count( field->GetName() ) == 0 )
580 msg.Printf(
_(
"Remove %s footprint fields not in symbol." ), aFootprint->
GetReference() );
592 msg.Printf(
_(
"Updated %s fields." ), aFootprint->
GetReference() );
598 for(
auto& [
name, value] : compFields )
607 aFootprint->
Add( newField );
629 std::vector<PCB_FIELD*> fieldList;
630 aFootprint->
GetFields( fieldList,
false );
634 if( field->IsMandatory() )
637 if( compFields.count( field->GetName() ) == 0 )
642 msg.Printf(
_(
"Removed %s footprint fields not in symbol." ), aFootprint->
GetReference() );
646 aFootprint->
Remove( field );
649 m_frame->GetCanvas()->GetView()->Remove( field );
664 if( !humanSheetPath.empty() )
665 sheetname = humanSheetPath;
666 else if( aNetlistComponent->
GetProperties().count( wxT(
"Sheetname" ) ) > 0 )
667 sheetname = aNetlistComponent->
GetProperties().at( wxT(
"Sheetname" ) );
669 if( aNetlistComponent->
GetProperties().count( wxT(
"Sheetfile" ) ) > 0 )
670 sheetfile = aNetlistComponent->
GetProperties().at( wxT(
"Sheetfile" ) );
672 if( aNetlistComponent->
GetProperties().count( wxT(
"ki_fp_filters" ) ) > 0 )
673 fpFilters = aNetlistComponent->
GetProperties().at( wxT(
"ki_fp_filters" ) );
679 msg.Printf(
_(
"Update %s sheetname to '%s'." ),
686 msg.Printf(
_(
"Updated %s sheetname to '%s'." ),
698 msg.Printf(
_(
"Update %s sheetfile to '%s'." ),
705 msg.Printf(
_(
"Updated %s sheetfile to '%s'." ),
717 msg.Printf(
_(
"Update %s footprint filters to '%s'." ),
724 msg.Printf(
_(
"Updated %s footprint filters to '%s'." ),
732 bool netlistExcludeFromBOM = aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_bom" ) ) > 0;
741 if( netlistExcludeFromBOM )
742 msg.Printf(
_(
"Add %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
744 msg.Printf(
_(
"Remove %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
750 if( netlistExcludeFromBOM )
753 msg.Printf(
_(
"Added %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
758 msg.Printf(
_(
"Removed %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
768 bool netlistDNP = aNetlistComponent->
GetProperties().count( wxT(
"dnp" ) ) > 0;
770 if( firstAssociatedVariant !=
nullptr && firstAssociatedVariant->
m_hasDnp )
771 netlistDNP = firstAssociatedVariant->
m_dnp;
778 msg.Printf(
_(
"Add %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
780 msg.Printf(
_(
"Remove %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
789 msg.Printf(
_(
"Added %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
794 msg.Printf(
_(
"Removed %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
804 bool netlistExcludeFromPosFiles = aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_pos_files" ) ) > 0;
813 if( netlistExcludeFromPosFiles )
815 msg.Printf(
_(
"Add %s 'exclude from position files' fabrication attribute." ),
820 msg.Printf(
_(
"Remove %s 'exclude from position files' fabrication attribute." ),
828 if( netlistExcludeFromPosFiles )
831 msg.Printf(
_(
"Added %s 'exclude from position files' fabrication attribute." ),
837 msg.Printf(
_(
"Removed %s 'exclude from position files' fabrication attribute." ),
860 msg.Printf(
_(
"Added %s 'duplicate pad numbers are jumpers' attribute." ),
865 msg.Printf(
_(
"Removed %s 'duplicate pad numbers are jumpers' attribute." ),
873 msg.Printf(
_(
"Add %s 'duplicate pad numbers are jumpers' attribute." ),
878 msg.Printf(
_(
"Remove %s 'duplicate pad numbers are jumpers' attribute." ),
892 msg.Printf(
_(
"Updated %s jumper pad groups" ), aFootprint->
GetReference() );
896 msg.Printf(
_(
"Update %s jumper pad groups" ), aFootprint->
GetReference() );
902 if( changed &&
copy )
922 if( !
m_commit.GetStatus( aPcbFootprint ) )
925 copy->SetParentGroup(
nullptr );
928 bool changed =
false;
937 KIID existingGroupKIID = existingGroup ? existingGroup->
m_Uuid : 0;
940 auto it = std::find_if(
m_board->Groups().begin(),
m_board->Groups().end(),
942 return group->m_Uuid == newGroupKIID;
946 if( it !=
m_board->Groups().end() )
950 if( newGroupKIID == existingGroupKIID )
954 if( existingGroupKIID != 0 )
958 msg.Printf(
_(
"Remove %s from group '%s'." ),
964 msg.Printf(
_(
"Removed %s from group '%s'." ),
972 if( existingGroup->
GetItems().size() < 2 )
983 if( newGroupKIID != 0 )
987 msg.Printf(
_(
"Add %s to group '%s'." ),
993 msg.Printf(
_(
"Added %s to group '%s'." ),
999 if( newGroup ==
nullptr )
1002 newGroup->
SetUuid( newGroupKIID );
1015 newGroup->
AddItem( aPcbFootprint );
1021 if( changed &&
copy )
1041 copy->SetParentGroup(
nullptr );
1044 bool changed =
false;
1047 std::deque<PAD*> pads = aFootprint->
Pads();
1048 std::set<wxString> padNetnames;
1050 std::sort( pads.begin(), pads.end(),
1053 return a->m_Uuid < b->m_Uuid;
1060 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1061 wxT(
"Processing pad %s of component %s" ),
1065 wxString pinFunction;
1070 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1071 wxT(
" Found valid net: %s" ),
1078 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1079 wxT(
" No net found for pad %s" ),
1085 if(
pad->GetPinFunction() != pinFunction )
1088 pad->SetPinFunction( pinFunction );
1091 if(
pad->GetPinType() != pinType )
1094 pad->SetPinType( pinType );
1103 if( !net.
IsValid() || !
pad->IsOnCopperLayer() )
1105 if( !
pad->GetNetname().IsEmpty() )
1109 msg.Printf(
_(
"Disconnect %s pin %s." ),
1115 msg.Printf(
_(
"Disconnected %s pin %s." ),
1122 else if(
pad->IsOnCopperLayer() && !
pad->GetNumber().IsEmpty() )
1125 msg.Printf(
_(
"No net found for component %s pad %s (no pin %s in symbol)." ),
1140 if(
pad->GetNetname().IsEmpty() )
1141 pad->SetPinFunction( wxEmptyString );
1153 if(
pad->IsNoConnectPad() )
1155 netName = wxString::Format( wxS(
"%s" ), net.
GetNetName() );
1157 for(
int jj = 1; !padNetnames.insert( netName ).second
1161 netName = wxString::Format( wxS(
"%s_%d" ), net.
GetNetName(), jj );
1170 if(
pad->GetNetname() != netName )
1173 if( netinfo ==
nullptr )
1180 if( netinfo ==
nullptr )
1192 msg.Printf(
_(
"Add net %s." ),
1197 if( !
pad->GetNetname().IsEmpty() )
1203 msg.Printf(
_(
"Reconnect %s pin %s from %s to %s."),
1211 msg.Printf(
_(
"Reconnected %s pin %s from %s to %s."),
1222 msg.Printf(
_(
"Connect %s pin %s to %s."),
1229 msg.Printf(
_(
"Connected %s pin %s to %s."),
1241 pad->SetNet( netinfo );
1251 if( changed &&
copy )
1263 std::vector<FOOTPRINT::FP_UNIT_INFO> newUnits;
1266 newUnits.push_back( { u.m_unitName, u.m_pins } );
1268 const std::vector<FOOTPRINT::FP_UNIT_INFO>& curUnits = aFootprint->
GetUnitInfo();
1270 auto unitsEqual = [](
const std::vector<FOOTPRINT::FP_UNIT_INFO>& a,
1271 const std::vector<FOOTPRINT::FP_UNIT_INFO>& b )
1273 if( a.size() != b.size() )
1276 for(
size_t i = 0; i < a.size(); ++i )
1278 if( a[i].m_unitName != b[i].m_unitName )
1281 if( a[i].m_pins != b[i].m_pins )
1288 if( unitsEqual( curUnits, newUnits ) )
1295 msg.Printf(
_(
"Update %s unit metadata." ), aFootprint->
GetReference() );
1303 if( !
m_commit.GetStatus( aFootprint ) )
1306 copy->SetParentGroup(
nullptr );
1311 msg.Printf(
_(
"Updated %s unit metadata." ), aFootprint->
GetReference() );
1322 const std::vector<FOOTPRINT*>& aFootprints,
1323 const LIB_ID& aBaseFpid )
1328 if( aBaseFpid.
empty() )
1340 std::vector<VARIANT_INFO> variantInfo;
1341 variantInfo.reserve( variants.size() );
1343 for(
const auto& [variantName, variant] : variants )
1345 LIB_ID variantFPID = aBaseFpid;
1347 auto fieldIt = variant.m_fields.find( footprintFieldName );
1349 if( fieldIt != variant.m_fields.end() && !fieldIt->second.IsEmpty() )
1353 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
1355 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
1364 variantFPID = parsedId;
1368 variantInfo.push_back( { variantName, &variant, variantFPID } );
1371 for(
FOOTPRINT* footprint : aFootprints )
1381 copy->SetParentGroup(
nullptr );
1384 bool changed =
false;
1386 auto printAttributeMessage =
1387 [&](
bool add,
const wxString& attrName,
const wxString& variantName )
1391 if( aFootprints.size() > 1 )
1393 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s (footprint %s)." )
1394 :
_(
"Remove %s '%s' attribute from variant %s (footprint %s)." ),
1395 footprint->GetReference(),
1398 footprint->GetFPIDAsString() );
1402 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s." )
1403 :
_(
"Remove %s '%s' attribute from variant %s." ),
1404 footprint->GetReference(),
1411 if( aFootprints.size() > 1 )
1413 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s (footprint %s)." )
1414 :
_(
"Removed %s '%s' attribute from variant %s (footprint %s)." ),
1415 footprint->GetReference(),
1418 footprint->GetFPIDAsString() );
1422 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s." )
1423 :
_(
"Removed %s '%s' attribute from variant %s." ),
1424 footprint->GetReference(),
1431 std::set<wxString> excessVariants;
1433 for(
const auto& [variantName,
_] : footprint->GetVariants() )
1434 excessVariants.insert( variantName );
1436 for(
const VARIANT_INFO&
info : variantInfo )
1444 bool isAssociatedFootprint = ( footprint->GetFPID() ==
info.variantFPID );
1449 if( !isAssociatedFootprint )
1452 excessVariants.erase(
info.name );
1453 bool targetDnp = variant.
m_hasDnp ? variant.
m_dnp : footprint->IsDNP();
1454 bool currentDnp = currentVariant ? currentVariant->
GetDNP() : footprint->IsDNP();
1456 if( currentDnp != targetDnp )
1458 printAttributeMessage( targetDnp,
_(
"Do not place" ),
info.name );
1463 fpVariant->SetDNP( targetDnp );
1471 : footprint->IsExcludedFromBOM();
1473 : footprint->IsExcludedFromBOM();
1475 if( currentExcludedFromBOM != targetExcludedFromBOM )
1477 printAttributeMessage( targetExcludedFromBOM,
_(
"exclude from BOM" ),
info.name );
1482 fpVariant->SetExcludedFromBOM( targetExcludedFromBOM );
1490 : footprint->IsExcludedFromPosFiles();
1492 : footprint->IsExcludedFromPosFiles();
1494 if( currentExcludedFromPosFiles != targetExcludedFromPosFiles )
1496 printAttributeMessage( targetExcludedFromPosFiles,
_(
"exclude from position files" ),
info.name );
1501 fpVariant->SetExcludedFromPosFiles( targetExcludedFromPosFiles );
1508 for(
const auto& [fieldName, fieldValue] : variant.
m_fields )
1510 if( fieldName.CmpNoCase( footprintFieldName ) == 0 )
1513 bool hasCurrentValue = currentVariant && currentVariant->
HasFieldValue( fieldName );
1514 wxString currentValue = hasCurrentValue ? currentVariant->
GetFieldValue( fieldName ) : wxString();
1516 if( currentValue != fieldValue )
1520 if( aFootprints.size() > 1 )
1522 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s (footprint %s)." ),
1523 footprint->GetReference(),
1527 footprint->GetFPIDAsString() );
1531 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s." ),
1532 footprint->GetReference(),
1540 if( aFootprints.size() > 1 )
1542 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s (footprint %s)." ),
1543 footprint->GetReference(),
1547 footprint->GetFPIDAsString() );
1551 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s." ),
1552 footprint->GetReference(),
1559 fpVariant->SetFieldValue( fieldName, fieldValue );
1568 for(
const wxString& excess : excessVariants )
1572 msg.Printf(
_(
"Remove variant %s:%s no longer associated with footprint %s." ),
1573 footprint->GetReference(),
1575 footprint->GetFPIDAsString() );
1579 msg.Printf(
_(
"Removed variant %s:%s no longer associated with footprint %s." ),
1580 footprint->GetReference(),
1582 footprint->GetFPIDAsString() );
1584 footprint->DeleteVariant( excess );
1593 bool isBaseFootprint = ( footprint->GetFPID() == aBaseFpid );
1595 if( !isBaseFootprint && !footprint->IsDNP() )
1597 msg.Printf(
m_isDryRun ?
_(
"Add %s 'Do not place' fabrication attribute." )
1598 :
_(
"Added %s 'Do not place' fabrication attribute." ),
1599 footprint->GetReference() );
1604 footprint->SetDNP(
true );
1621 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1632 std::set<wxString> netlistNetnames;
1634 for(
int ii = 0; ii < (int) aNetlist.
GetCount(); ii++ )
1638 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1650 if( netlistNetnames.count(
via->GetNetname() ) == 0 )
1652 wxString updatedNetname = wxEmptyString;
1661 if( !updatedNetname.IsEmpty() )
1665 wxString originalNetname =
via->GetNetname();
1667 msg.Printf(
_(
"Reconnect via from %s to %s." ),
1682 wxString originalNetname =
via->GetNetname();
1685 via->SetNet( netinfo );
1687 msg.Printf(
_(
"Reconnected via from %s to %s." ),
1697 msg.Printf(
_(
"Via connected to unknown net (%s)." ),
1709 auto isInNetlist = [&](
const wxString& aNetName ) ->
bool
1711 if( netlistNetnames.count( aNetName ) )
1716 for(
const wxString& netName : netlistNetnames )
1718 if( aNetName.StartsWith( netName ) )
1728 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1731 if( !isInNetlist( zone->GetNetname() ) )
1736 wxString updatedNetname = wxEmptyString;
1749 if( updatedNetname.IsEmpty() &&
m_oldToNewNets.count( zone->GetNetname() ) )
1754 if( !updatedNetname.IsEmpty() )
1758 wxString originalNetname = zone->GetNetname();
1760 if( !zone->GetZoneName().IsEmpty() )
1762 msg.Printf(
_(
"Reconnect copper zone '%s' from %s to %s." ),
1763 zone->GetZoneName(),
1769 msg.Printf(
_(
"Reconnect copper zone from %s to %s." ),
1785 wxString originalNetname = zone->GetNetname();
1788 zone->SetNet( netinfo );
1790 if( !zone->GetZoneName().IsEmpty() )
1792 msg.Printf(
_(
"Reconnected copper zone '%s' from %s to %s." ),
1799 msg.Printf(
_(
"Reconnected copper zone from %s to %s." ),
1810 if( !zone->GetZoneName().IsEmpty() )
1812 msg.Printf(
_(
"Copper zone '%s' has no pads connected." ),
1817 wxString layerNames = zone->LayerMaskDescribe();
1822 if(
m_frame->GetPcbNewSettings()->m_Display.m_DisplayInvertXAxis )
1825 if(
m_frame->GetPcbNewSettings()->m_Display.m_DisplayInvertYAxis )
1829 msg.Printf(
_(
"Copper zone on %s at (%s, %s) has no pads connected to net \"%s\"." ),
1835 zone->GetNetname() );
1859 if( netlistGroup ==
nullptr )
1862 if( netlistGroup->
name != pcbGroup->GetName() )
1866 msg.Printf(
_(
"Change group name from '%s' to '%s'." ),
1872 msg.Printf(
_(
"Changed group name from '%s' to '%s'." ),
1876 pcbGroup->SetName( netlistGroup->
name );
1882 if( netlistGroup->
libId != pcbGroup->GetDesignBlockLibId() )
1886 msg.Printf(
_(
"Change group library link from '%s' to '%s'." ),
1887 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1892 msg.Printf(
_(
"Changed group library link from '%s' to '%s'." ),
1893 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1896 pcbGroup->SetDesignBlockLibId( netlistGroup->
libId );
1908 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
1916 for(
int i = 0; i < (int) aNetlist.
GetCount(); i++ )
1919 FOOTPRINT* footprint = aFootprintMap[component];
1925 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1929 if( padNumber.IsEmpty() )
1932 msg.Printf(
_(
"Symbol %s has pins with no number. These pins can not be matched "
1942 msg.Printf(
_(
"%s pad %s not found in %s." ),
1958 FOOTPRINT* lastPreexistingFootprint =
nullptr;
1961 std::unordered_set<wxString> sheetPaths;
1962 std::unordered_set<FOOTPRINT*> usedFootprints;
1968 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
1970 if( !
m_board->Footprints().empty() )
1971 lastPreexistingFootprint =
m_board->Footprints().back();
1981 net->SetIsCurrent( net->GetNetCode() == 0 );
1983 m_board->GetComponentClassManager().InitNetlistUpdate();
1987 for(
unsigned ii = 0; ii < aNetlist.
GetCount(); ii++ )
1991 for(
unsigned jj = 0; jj <
comp->GetNetCount(); jj++ )
1998 for(
unsigned i = 0; i < aNetlist.
GetCount(); i++ )
2002 if( component->
GetProperties().count( wxT(
"exclude_from_board" ) ) )
2005 msg.Printf(
_(
"Processing symbol '%s:%s'." ),
2011 const bool hasBaseFpid = !baseFpid.
empty();
2015 msg.Printf(
_(
"Warning: %s footprint '%s' is missing a library name. "
2016 "Use the full 'Library:Footprint' format to avoid repeated update "
2024 std::vector<FOOTPRINT*> matchingFootprints;
2035 base.push_back( uuid );
2037 if( footprint->GetPath() == base )
2046 match = footprint->GetReference().CmpNoCase( component->
GetReference() ) == 0;
2050 matchingFootprints.push_back( footprint );
2052 if( footprint == lastPreexistingFootprint )
2059 std::vector<LIB_ID> expectedFpids;
2060 std::unordered_set<wxString> expectedFpidKeys;
2062 auto addExpectedFpid =
2063 [&](
const LIB_ID& aFpid )
2068 wxString key = aFpid.Format();
2070 if( expectedFpidKeys.insert( key ).second )
2071 expectedFpids.push_back( aFpid );
2074 addExpectedFpid( baseFpid );
2078 for(
const auto& [variantName, variant] : component->
GetVariants() )
2080 auto fieldIt = variant.m_fields.find( footprintFieldName );
2082 if( fieldIt == variant.m_fields.end() || fieldIt->second.IsEmpty() )
2087 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
2089 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
2098 addExpectedFpid( parsedId );
2106 [&](
const LIB_ID& aBoardFpid,
const LIB_ID& aExpectedFpid ) ->
bool
2108 if( aExpectedFpid.IsLegacy() )
2109 return aBoardFpid.
GetLibItemName() == aExpectedFpid.GetLibItemName();
2111 return aBoardFpid == aExpectedFpid;
2114 auto isExpectedFpid =
2115 [&](
const LIB_ID& aFpid ) ->
bool
2120 if( expectedFpidKeys.count( aFpid.Format() ) > 0 )
2125 if( fpidMatches( aFpid,
expected ) )
2132 auto takeMatchingFootprint =
2135 for(
FOOTPRINT* footprint : matchingFootprints )
2137 if( usedFootprints.count( footprint ) )
2140 if( fpidMatches( footprint->GetFPID(), aFpid ) )
2147 std::vector<FOOTPRINT*> componentFootprints;
2148 componentFootprints.reserve( expectedFpids.size() );
2152 baseFootprint = takeMatchingFootprint( baseFpid );
2153 else if( !matchingFootprints.empty() )
2154 baseFootprint = matchingFootprints.front();
2160 for(
FOOTPRINT* footprint : matchingFootprints )
2162 if( usedFootprints.count( footprint ) )
2165 if( isExpectedFpid( footprint->GetFPID() ) )
2168 replaceCandidate = footprint;
2172 if( replaceCandidate )
2177 baseFootprint = replaced;
2179 baseFootprint = replaceCandidate;
2183 if( !baseFootprint && ( hasBaseFpid || expectedFpids.empty() ) )
2188 componentFootprints.push_back( baseFootprint );
2189 usedFootprints.insert( baseFootprint );
2190 footprintMap[ component ] = baseFootprint;
2193 for(
const LIB_ID& fpid : expectedFpids )
2195 if( fpid == baseFpid )
2198 FOOTPRINT* footprint = takeMatchingFootprint( fpid );
2205 componentFootprints.push_back( footprint );
2206 usedFootprints.insert( footprint );
2210 for(
FOOTPRINT* footprint : componentFootprints )
2221 sheetPaths.insert( footprint->GetSheetname() );
2224 if( !componentFootprints.empty() )
2236 bool matched =
false;
2242 bool isStaleVariantFootprint =
false;
2244 if( usedFootprints.count( footprint ) )
2255 if( component && component->
GetProperties().count( wxT(
"exclude_from_board" ) ) == 0 )
2263 isStaleVariantFootprint =
true;
2274 if( isStaleVariantFootprint )
2277 if( doDelete && !matched && footprint->IsLocked() && !
m_overrideLocks )
2281 msg.Printf(
_(
"Cannot remove unused footprint %s (footprint is locked)." ),
2282 footprint->GetReference() );
2286 msg.Printf(
_(
"Could not remove unused footprint %s (footprint is locked)." ),
2287 footprint->GetReference() );
2295 if( doDelete && !matched )
2299 msg.Printf(
_(
"Remove unused footprint %s." ),
2300 footprint->GetReference() );
2305 msg.Printf(
_(
"Removed unused footprint %s." ),
2306 footprint->GetReference() );
2316 for(
PAD*
pad : footprint->Pads() )
2319 pad->GetNet()->SetIsCurrent(
true );
2327 m_board->GetComponentClassManager().FinishNetlistUpdate();
2328 m_board->SynchronizeComponentClasses( sheetPaths );
2335 if( !net->IsCurrent() )
2337 msg.Printf(
_(
"Removed unused net %s." ),
2346 const std::vector<wxString>& netlistVariants = aNetlist.
GetVariantNames();
2348 if( !netlistVariants.empty() || !
m_board->GetVariantNames().empty() )
2352 auto findBoardVariantName =
2353 [&](
const wxString& aVariantName ) -> wxString
2355 for(
const wxString&
name :
m_board->GetVariantNames() )
2357 if(
name.CmpNoCase( aVariantName ) == 0 )
2361 return wxEmptyString;
2364 std::vector<wxString> updatedVariantNames;
2365 updatedVariantNames.reserve( netlistVariants.size() );
2367 for(
const wxString& variantName : netlistVariants )
2369 wxString actualName = findBoardVariantName( variantName );
2371 if( actualName.IsEmpty() )
2373 m_board->AddVariant( variantName );
2374 actualName = findBoardVariantName( variantName );
2376 if( !actualName.IsEmpty() )
2378 msg.Printf(
_(
"Added variant '%s'." ), actualName );
2383 if( actualName.IsEmpty() )
2388 wxString oldDescription =
m_board->GetVariantDescription( actualName );
2390 if( newDescription != oldDescription )
2392 m_board->SetVariantDescription( actualName, newDescription );
2393 msg.Printf(
_(
"Updated description for variant '%s'." ), actualName );
2397 updatedVariantNames.push_back( actualName );
2400 std::vector<wxString> variantsToRemove;
2402 for(
const wxString& existingName :
m_board->GetVariantNames() )
2406 for(
const wxString& variantName : netlistVariants )
2408 if( existingName.CmpNoCase( variantName ) == 0 )
2416 variantsToRemove.push_back( existingName );
2419 for(
const wxString& variantName : variantsToRemove )
2421 m_board->DeleteVariant( variantName );
2422 msg.Printf(
_(
"Removed variant '%s'." ), variantName );
2426 if( !updatedVariantNames.empty() )
2427 m_board->SetVariantNames( updatedVariantNames );
2437 m_board->SynchronizeNetsAndNetClasses(
true );
2448 for(
const std::pair<const wxString, NETINFO_ITEM*>& addedNet :
m_addedNets )
2449 delete addedNet.second;
constexpr EDA_IU_SCALE pcbIUScale
wxString GetNetname() const
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
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
bool updateFootprintGroup(FOOTPRINT *aPcbFootprint, COMPONENT *aNetlistComponent)
std::map< wxString, NETINFO_ITEM * > m_addedNets
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)
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.
constexpr size_type GetWidth() const
constexpr Vec Centre() const
constexpr size_type GetHeight() 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)
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.
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::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.
NETLIST_GROUP * GetGroupByUuid(const KIID &aUuid)
Return a NETLIST_GROUP by aUuid.
COMPONENT * GetComponent(unsigned aIndex)
Return the COMPONENT at aIndex.
wxString GetVariantDescription(const wxString &aVariantName) const
static REPORTER & GetInstance()
const wxString & GetPinFunction() const
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.
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.
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)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
VECTOR2< int32_t > VECTOR2I