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)."),
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 const_cast<KIID&
>( newGroup->
m_Uuid ) = 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; jj++ )
1159 netName = wxString::Format( wxS(
"%s_%d" ), net.
GetNetName(), jj );
1168 if(
pad->GetNetname() != netName )
1171 if( netinfo ==
nullptr )
1178 if( netinfo ==
nullptr )
1190 msg.Printf(
_(
"Add net %s." ),
1195 if( !
pad->GetNetname().IsEmpty() )
1201 msg.Printf(
_(
"Reconnect %s pin %s from %s to %s."),
1209 msg.Printf(
_(
"Reconnected %s pin %s from %s to %s."),
1220 msg.Printf(
_(
"Connect %s pin %s to %s."),
1227 msg.Printf(
_(
"Connected %s pin %s to %s."),
1239 pad->SetNet( netinfo );
1249 if( changed &&
copy )
1261 std::vector<FOOTPRINT::FP_UNIT_INFO> newUnits;
1264 newUnits.push_back( { u.m_unitName, u.m_pins } );
1266 const std::vector<FOOTPRINT::FP_UNIT_INFO>& curUnits = aFootprint->
GetUnitInfo();
1268 auto unitsEqual = [](
const std::vector<FOOTPRINT::FP_UNIT_INFO>& a,
1269 const std::vector<FOOTPRINT::FP_UNIT_INFO>& b )
1271 if( a.size() != b.size() )
1274 for(
size_t i = 0; i < a.size(); ++i )
1276 if( a[i].m_unitName != b[i].m_unitName )
1279 if( a[i].m_pins != b[i].m_pins )
1286 if( unitsEqual( curUnits, newUnits ) )
1293 msg.Printf(
_(
"Update %s unit metadata." ), aFootprint->
GetReference() );
1301 if( !
m_commit.GetStatus( aFootprint ) )
1304 copy->SetParentGroup(
nullptr );
1309 msg.Printf(
_(
"Updated %s unit metadata." ), aFootprint->
GetReference() );
1320 const std::vector<FOOTPRINT*>& aFootprints,
1321 const LIB_ID& aBaseFpid )
1326 if( variants.empty() )
1329 if( aBaseFpid.
empty() )
1341 std::vector<VARIANT_INFO> variantInfo;
1342 variantInfo.reserve( variants.size() );
1344 for(
const auto& [variantName, variant] : variants )
1346 LIB_ID variantFPID = aBaseFpid;
1348 auto fieldIt = variant.m_fields.find( footprintFieldName );
1350 if( fieldIt != variant.m_fields.end() && !fieldIt->second.IsEmpty() )
1354 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
1356 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
1365 variantFPID = parsedId;
1369 variantInfo.push_back( { variantName, &variant, variantFPID } );
1372 for(
FOOTPRINT* footprint : aFootprints )
1382 copy->SetParentGroup(
nullptr );
1385 bool changed =
false;
1387 auto printAttributeMessage =
1388 [&](
bool add,
const wxString& attrName,
const wxString& variantName )
1392 if( aFootprints.size() > 1 )
1394 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s (footprint %s)." )
1395 :
_(
"Remove %s '%s' attribute from variant %s (footprint %s)." ),
1396 footprint->GetReference(),
1399 footprint->GetFPIDAsString() );
1403 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s." )
1404 :
_(
"Remove %s '%s' attribute from variant %s." ),
1405 footprint->GetReference(),
1412 if( aFootprints.size() > 1 )
1414 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s (footprint %s)." )
1415 :
_(
"Removed %s '%s' attribute from variant %s (footprint %s)." ),
1416 footprint->GetReference(),
1419 footprint->GetFPIDAsString() );
1423 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s." )
1424 :
_(
"Removed %s '%s' attribute from variant %s." ),
1425 footprint->GetReference(),
1432 std::set<wxString> excessVariants;
1434 for(
const auto& [variantName,
_] : footprint->GetVariants() )
1435 excessVariants.insert( variantName );
1437 for(
const VARIANT_INFO&
info : variantInfo )
1445 bool isAssociatedFootprint = ( footprint->GetFPID() ==
info.variantFPID );
1450 if( !isAssociatedFootprint )
1453 excessVariants.erase(
info.name );
1454 bool targetDnp = variant.
m_hasDnp ? variant.
m_dnp : footprint->IsDNP();
1455 bool currentDnp = currentVariant ? currentVariant->
GetDNP() : footprint->IsDNP();
1457 if( currentDnp != targetDnp )
1459 printAttributeMessage( targetDnp,
_(
"Do not place" ),
info.name );
1464 fpVariant->SetDNP( targetDnp );
1472 : footprint->IsExcludedFromBOM();
1474 : footprint->IsExcludedFromBOM();
1476 if( currentExcludedFromBOM != targetExcludedFromBOM )
1478 printAttributeMessage( targetExcludedFromBOM,
_(
"exclude from BOM" ),
info.name );
1483 fpVariant->SetExcludedFromBOM( targetExcludedFromBOM );
1491 : footprint->IsExcludedFromPosFiles();
1493 : footprint->IsExcludedFromPosFiles();
1495 if( currentExcludedFromPosFiles != targetExcludedFromPosFiles )
1497 printAttributeMessage( targetExcludedFromPosFiles,
_(
"exclude from position files" ),
info.name );
1502 fpVariant->SetExcludedFromPosFiles( targetExcludedFromPosFiles );
1509 for(
const auto& [fieldName, fieldValue] : variant.
m_fields )
1511 if( fieldName.CmpNoCase( footprintFieldName ) == 0 )
1514 bool hasCurrentValue = currentVariant && currentVariant->
HasFieldValue( fieldName );
1515 wxString currentValue = hasCurrentValue ? currentVariant->
GetFieldValue( fieldName ) : wxString();
1517 if( currentValue != fieldValue )
1521 if( aFootprints.size() > 1 )
1523 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s (footprint %s)." ),
1524 footprint->GetReference(),
1528 footprint->GetFPIDAsString() );
1532 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s." ),
1533 footprint->GetReference(),
1541 if( aFootprints.size() > 1 )
1543 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s (footprint %s)." ),
1544 footprint->GetReference(),
1548 footprint->GetFPIDAsString() );
1552 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s." ),
1553 footprint->GetReference(),
1560 fpVariant->SetFieldValue( fieldName, fieldValue );
1569 for(
const wxString& excess : excessVariants )
1573 msg.Printf(
_(
"Remove variant %s:%s no longer associated with footprint %s." ),
1574 footprint->GetReference(),
1576 footprint->GetFPIDAsString() );
1580 msg.Printf(
_(
"Removed variant %s:%s no longer associated with footprint %s." ),
1581 footprint->GetReference(),
1583 footprint->GetFPIDAsString() );
1585 footprint->DeleteVariant( excess );
1594 bool isBaseFootprint = ( footprint->GetFPID() == aBaseFpid );
1596 if( !isBaseFootprint && !footprint->IsDNP() )
1598 msg.Printf(
m_isDryRun ?
_(
"Add %s 'Do not place' fabrication attribute." )
1599 :
_(
"Added %s 'Do not place' fabrication attribute." ),
1600 footprint->GetReference() );
1605 footprint->SetDNP(
true );
1622 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1633 std::set<wxString> netlistNetnames;
1635 for(
int ii = 0; ii < (int) aNetlist.
GetCount(); ii++ )
1639 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1651 if( netlistNetnames.count(
via->GetNetname() ) == 0 )
1653 wxString updatedNetname = wxEmptyString;
1662 if( !updatedNetname.IsEmpty() )
1666 wxString originalNetname =
via->GetNetname();
1668 msg.Printf(
_(
"Reconnect via from %s to %s." ),
1683 wxString originalNetname =
via->GetNetname();
1686 via->SetNet( netinfo );
1688 msg.Printf(
_(
"Reconnected via from %s to %s." ),
1698 msg.Printf(
_(
"Via connected to unknown net (%s)." ),
1710 auto isInNetlist = [&](
const wxString& aNetName ) ->
bool
1712 if( netlistNetnames.count( aNetName ) )
1717 for(
const wxString& netName : netlistNetnames )
1719 if( aNetName.StartsWith( netName ) )
1729 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1732 if( !isInNetlist( zone->GetNetname() ) )
1737 wxString updatedNetname = wxEmptyString;
1750 if( updatedNetname.IsEmpty() &&
m_oldToNewNets.count( zone->GetNetname() ) )
1755 if( !updatedNetname.IsEmpty() )
1759 wxString originalNetname = zone->GetNetname();
1761 if( !zone->GetZoneName().IsEmpty() )
1763 msg.Printf(
_(
"Reconnect copper zone '%s' from %s to %s." ),
1764 zone->GetZoneName(),
1770 msg.Printf(
_(
"Reconnect copper zone from %s to %s." ),
1786 wxString originalNetname = zone->GetNetname();
1789 zone->SetNet( netinfo );
1791 if( !zone->GetZoneName().IsEmpty() )
1793 msg.Printf(
_(
"Reconnected copper zone '%s' from %s to %s." ),
1800 msg.Printf(
_(
"Reconnected copper zone from %s to %s." ),
1811 if( !zone->GetZoneName().IsEmpty() )
1813 msg.Printf(
_(
"Copper zone '%s' has no pads connected." ),
1818 wxString layerNames = zone->LayerMaskDescribe();
1823 if(
m_frame->GetPcbNewSettings()->m_Display.m_DisplayInvertXAxis )
1826 if(
m_frame->GetPcbNewSettings()->m_Display.m_DisplayInvertYAxis )
1830 msg.Printf(
_(
"Copper zone on %s at (%s, %s) has no pads connected to net \"%s\"." ),
1836 zone->GetNetname() );
1860 if( netlistGroup ==
nullptr )
1863 if( netlistGroup->
name != pcbGroup->GetName() )
1867 msg.Printf(
_(
"Change group name from '%s' to '%s'." ),
1873 msg.Printf(
_(
"Changed group name from '%s' to '%s'." ),
1877 pcbGroup->SetName( netlistGroup->
name );
1883 if( netlistGroup->
libId != pcbGroup->GetDesignBlockLibId() )
1887 msg.Printf(
_(
"Change group library link from '%s' to '%s'." ),
1888 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1893 msg.Printf(
_(
"Changed group library link from '%s' to '%s'." ),
1894 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1897 pcbGroup->SetDesignBlockLibId( netlistGroup->
libId );
1909 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
1917 for(
int i = 0; i < (int) aNetlist.
GetCount(); i++ )
1920 FOOTPRINT* footprint = aFootprintMap[component];
1926 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1930 if( padNumber.IsEmpty() )
1933 msg.Printf(
_(
"Symbol %s has pins with no number. These pins can not be matched "
1943 msg.Printf(
_(
"%s pad %s not found in %s." ),
1959 FOOTPRINT* lastPreexistingFootprint =
nullptr;
1962 std::unordered_set<wxString> sheetPaths;
1963 std::unordered_set<FOOTPRINT*> usedFootprints;
1969 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
1971 if( !
m_board->Footprints().empty() )
1972 lastPreexistingFootprint =
m_board->Footprints().back();
1982 net->SetIsCurrent( net->GetNetCode() == 0 );
1984 m_board->GetComponentClassManager().InitNetlistUpdate();
1990 for(
unsigned i = 0; i < aNetlist.
GetCount(); i++ )
1994 if( component->
GetProperties().count( wxT(
"exclude_from_board" ) ) )
1997 msg.Printf(
_(
"Processing symbol '%s:%s'." ),
2003 const bool hasBaseFpid = !baseFpid.
empty();
2007 msg.Printf(
_(
"Warning: %s footprint '%s' is missing a library name. "
2008 "Use the full 'Library:Footprint' format to avoid repeated update "
2016 std::vector<FOOTPRINT*> matchingFootprints;
2027 base.push_back( uuid );
2029 if( footprint->GetPath() == base )
2038 match = footprint->GetReference().CmpNoCase( component->
GetReference() ) == 0;
2042 matchingFootprints.push_back( footprint );
2044 if( footprint == lastPreexistingFootprint )
2051 std::vector<LIB_ID> expectedFpids;
2052 std::unordered_set<wxString> expectedFpidKeys;
2054 auto addExpectedFpid =
2055 [&](
const LIB_ID& aFpid )
2060 wxString key = aFpid.Format();
2062 if( expectedFpidKeys.insert( key ).second )
2063 expectedFpids.push_back( aFpid );
2066 addExpectedFpid( baseFpid );
2070 for(
const auto& [variantName, variant] : component->
GetVariants() )
2072 auto fieldIt = variant.m_fields.find( footprintFieldName );
2074 if( fieldIt == variant.m_fields.end() || fieldIt->second.IsEmpty() )
2079 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
2081 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
2090 addExpectedFpid( parsedId );
2098 [&](
const LIB_ID& aBoardFpid,
const LIB_ID& aExpectedFpid ) ->
bool
2100 if( aExpectedFpid.IsLegacy() )
2101 return aBoardFpid.
GetLibItemName() == aExpectedFpid.GetLibItemName();
2103 return aBoardFpid == aExpectedFpid;
2106 auto isExpectedFpid =
2107 [&](
const LIB_ID& aFpid ) ->
bool
2112 if( expectedFpidKeys.count( aFpid.Format() ) > 0 )
2117 if( fpidMatches( aFpid,
expected ) )
2124 auto takeMatchingFootprint =
2127 for(
FOOTPRINT* footprint : matchingFootprints )
2129 if( usedFootprints.count( footprint ) )
2132 if( fpidMatches( footprint->GetFPID(), aFpid ) )
2139 std::vector<FOOTPRINT*> componentFootprints;
2140 componentFootprints.reserve( expectedFpids.size() );
2144 baseFootprint = takeMatchingFootprint( baseFpid );
2145 else if( !matchingFootprints.empty() )
2146 baseFootprint = matchingFootprints.front();
2152 for(
FOOTPRINT* footprint : matchingFootprints )
2154 if( usedFootprints.count( footprint ) )
2157 if( isExpectedFpid( footprint->GetFPID() ) )
2160 replaceCandidate = footprint;
2164 if( replaceCandidate )
2169 baseFootprint = replaced;
2171 baseFootprint = replaceCandidate;
2175 if( !baseFootprint && hasBaseFpid )
2180 componentFootprints.push_back( baseFootprint );
2181 usedFootprints.insert( baseFootprint );
2182 footprintMap[ component ] = baseFootprint;
2185 for(
const LIB_ID& fpid : expectedFpids )
2187 if( fpid == baseFpid )
2190 FOOTPRINT* footprint = takeMatchingFootprint( fpid );
2197 componentFootprints.push_back( footprint );
2198 usedFootprints.insert( footprint );
2202 for(
FOOTPRINT* footprint : componentFootprints )
2213 sheetPaths.insert( footprint->GetSheetname() );
2216 if( !componentFootprints.empty() )
2228 bool matched =
false;
2234 bool isStaleVariantFootprint =
false;
2236 if( usedFootprints.count( footprint ) )
2247 if( component && component->
GetProperties().count( wxT(
"exclude_from_board" ) ) == 0 )
2255 isStaleVariantFootprint =
true;
2266 if( isStaleVariantFootprint )
2269 if( doDelete && !matched && footprint->IsLocked() && !
m_overrideLocks )
2273 msg.Printf(
_(
"Cannot remove unused footprint %s (footprint is locked)." ),
2274 footprint->GetReference() );
2278 msg.Printf(
_(
"Could not remove unused footprint %s (footprint is locked)." ),
2279 footprint->GetReference() );
2287 if( doDelete && !matched )
2291 msg.Printf(
_(
"Remove unused footprint %s." ),
2292 footprint->GetReference() );
2297 msg.Printf(
_(
"Removed unused footprint %s." ),
2298 footprint->GetReference() );
2308 for(
PAD*
pad : footprint->Pads() )
2311 pad->GetNet()->SetIsCurrent(
true );
2319 m_board->GetComponentClassManager().FinishNetlistUpdate();
2320 m_board->SynchronizeComponentClasses( sheetPaths );
2327 if( !net->IsCurrent() )
2329 msg.Printf(
_(
"Removed unused net %s." ),
2338 const std::vector<wxString>& netlistVariants = aNetlist.
GetVariantNames();
2340 if( !netlistVariants.empty() || !
m_board->GetVariantNames().empty() )
2344 auto findBoardVariantName =
2345 [&](
const wxString& aVariantName ) -> wxString
2347 for(
const wxString&
name :
m_board->GetVariantNames() )
2349 if(
name.CmpNoCase( aVariantName ) == 0 )
2353 return wxEmptyString;
2356 std::vector<wxString> updatedVariantNames;
2357 updatedVariantNames.reserve( netlistVariants.size() );
2359 for(
const wxString& variantName : netlistVariants )
2361 wxString actualName = findBoardVariantName( variantName );
2363 if( actualName.IsEmpty() )
2365 m_board->AddVariant( variantName );
2366 actualName = findBoardVariantName( variantName );
2368 if( !actualName.IsEmpty() )
2370 msg.Printf(
_(
"Added variant '%s'." ), actualName );
2375 if( actualName.IsEmpty() )
2380 wxString oldDescription =
m_board->GetVariantDescription( actualName );
2382 if( newDescription != oldDescription )
2384 m_board->SetVariantDescription( actualName, newDescription );
2385 msg.Printf(
_(
"Updated description for variant '%s'." ), actualName );
2389 updatedVariantNames.push_back( actualName );
2392 std::vector<wxString> variantsToRemove;
2394 for(
const wxString& existingName :
m_board->GetVariantNames() )
2398 for(
const wxString& variantName : netlistVariants )
2400 if( existingName.CmpNoCase( variantName ) == 0 )
2408 variantsToRemove.push_back( existingName );
2411 for(
const wxString& variantName : variantsToRemove )
2413 m_board->DeleteVariant( variantName );
2414 msg.Printf(
_(
"Removed variant '%s'." ), variantName );
2418 if( !updatedVariantNames.empty() )
2419 m_board->SetVariantNames( updatedVariantNames );
2429 m_board->SynchronizeNetsAndNetClasses(
true );
2440 for(
const std::pair<const wxString, NETINFO_ITEM*>& addedNet :
m_addedNets )
2441 delete addedNet.second;
constexpr EDA_IU_SCALE pcbIUScale
wxString GetNetname() const
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)
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