88 const wxString previous = net->GetNetChain();
91 if( !previous.IsEmpty() &&
next.IsEmpty() && aReporter && !aDryRun )
95 _(
"Net chain assignment '%s' on net '%s' cleared by netlist "
97 previous, net->GetNetname() ),
103 net->SetNetChain(
next );
105 if( previous !=
next )
107 for(
int i = 0; i < 2; ++i )
108 net->ClearTerminalPad( i );
168 bestPosition.
x = pageSize.
x / 2;
169 bestPosition.
y = pageSize.
y / 2;
186 if( aFootprintId.
empty() )
188 msg.Printf(
_(
"Cannot add %s (no footprint assigned)." ),
197 if( footprint ==
nullptr )
199 msg.Printf(
_(
"Cannot add %s (footprint '%s' not found)." ),
208 m_board->GetComponentClassManager().GetNoneComponentClass() );
212 msg.Printf(
_(
"Add %s (footprint '%s')." ),
224 pad->SetLocalRatsnestVisible(
m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest );
227 pad->SetNetCode( 0 );
242 msg.Printf(
_(
"Added %s (footprint '%s')." ),
255 wxString curClassName, newClassName;
259 curClassName = curClass->
GetName();
269 newClass =
m_board->GetComponentClassManager().GetEffectiveStaticComponentClass(
271 newClassName = newClass->
GetName();
274 if( curClassName == newClassName )
283 copy->SetParentGroup(
nullptr );
290 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
292 msg.Printf(
_(
"Change %s component class to '%s'." ),
296 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
298 msg.Printf(
_(
"Remove %s component class (currently '%s')." ),
304 msg.Printf(
_(
"Change %s component class from '%s' to '%s'." ),
312 wxASSERT_MSG( newClass !=
nullptr,
"Component class should not be nullptr" );
316 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
318 msg.Printf(
_(
"Changed %s component class to '%s'." ),
322 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
324 msg.Printf(
_(
"Removed %s component class (was '%s')." ),
330 msg.Printf(
_(
"Changed %s component class from '%s' to '%s'." ),
353 msg.Printf(
_(
"Cannot update %s (no footprint assigned)." ),
362 if( newFootprint ==
nullptr )
364 msg.Printf(
_(
"Cannot update %s (footprint '%s' not found)." ),
376 msg.Printf(
_(
"Cannot change %s footprint from '%s' to '%s' (footprint is locked)."),
387 msg.Printf(
_(
"Change %s footprint from '%s' to '%s'."),
401 msg.Printf(
_(
"Could not change %s footprint from '%s' to '%s' (footprint is locked)."),
415 m_frame->ExchangeFootprint( aFootprint, newFootprint,
m_commit,
true );
417 msg.Printf(
_(
"Changed %s footprint from '%s' to '%s'."),
442 firstAssociatedVariant = &
test;
451 if( !
m_commit.GetStatus( aFootprint ) )
454 copy->SetParentGroup(
nullptr );
457 bool changed =
false;
464 msg.Printf(
_(
"Change %s reference designator to %s." ),
470 msg.Printf(
_(
"Changed %s reference designator to %s." ),
482 wxString netlistValue = aNetlistComponent->
GetValue();
484 if( firstAssociatedVariant !=
nullptr
490 if( aFootprint->
GetValue() != netlistValue )
494 msg.Printf(
_(
"Change %s value from %s to %s." ),
501 msg.Printf(
_(
"Changed %s value from %s to %s." ),
507 aFootprint->
SetValue( netlistValue );
516 if( !aNetlistComponent->
GetKIIDs().empty() )
517 new_path.push_back( aNetlistComponent->
GetKIIDs().front() );
519 if( aFootprint->
GetPath() != new_path )
523 msg.Printf(
_(
"Update %s symbol association from %s to %s." ),
530 msg.Printf(
_(
"Updated %s symbol association from %s to %s." ),
536 aFootprint->
SetPath( new_path );
542 nlohmann::ordered_map<wxString, wxString> fpFieldsAsMap;
547 if( field->IsReference() || field->IsValue() || field->IsComponentClass() )
552 fpFieldsAsMap[field->GetName()] = field->GetText();
556 nlohmann::ordered_map<wxString, wxString> compFields = aNetlistComponent->
GetFields();
562 compFields.erase( wxT(
"Component Class" ) );
564 if( firstAssociatedVariant !=
nullptr )
566 for(
const auto& [
name, value] : firstAssociatedVariant->
m_fields )
567 compFields[
name] = value;
573 bool remove_only =
true;
575 for(
const auto& [
name, value] : compFields )
577 if( fpFieldsAsMap.count(
name ) == 0 || fpFieldsAsMap[
name] != value )
585 for(
const auto& [
name, value] : fpFieldsAsMap )
587 if( compFields.count(
name ) == 0 )
600 msg.Printf(
_(
"Update %s fields." ), aFootprint->
GetReference() );
607 if( field->IsMandatory() )
610 if( compFields.count( field->GetName() ) == 0 )
614 msg.Printf(
_(
"Remove %s footprint fields not in symbol." ), aFootprint->
GetReference() );
626 msg.Printf(
_(
"Updated %s fields." ), aFootprint->
GetReference() );
632 for(
auto& [
name, value] : compFields )
641 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;
847 if( netlistExcludeFromPosFiles )
849 msg.Printf(
_(
"Add %s 'exclude from position files' fabrication attribute." ),
854 msg.Printf(
_(
"Remove %s 'exclude from position files' fabrication attribute." ),
862 if( netlistExcludeFromPosFiles )
865 msg.Printf(
_(
"Added %s 'exclude from position files' fabrication attribute." ),
871 msg.Printf(
_(
"Removed %s 'exclude from position files' fabrication attribute." ),
894 msg.Printf(
_(
"Added %s 'duplicate pad numbers are jumpers' attribute." ),
899 msg.Printf(
_(
"Removed %s 'duplicate pad numbers are jumpers' attribute." ),
907 msg.Printf(
_(
"Add %s 'duplicate pad numbers are jumpers' attribute." ),
912 msg.Printf(
_(
"Remove %s 'duplicate pad numbers are jumpers' attribute." ),
926 msg.Printf(
_(
"Updated %s jumper pad groups" ), aFootprint->
GetReference() );
930 msg.Printf(
_(
"Update %s jumper pad groups" ), aFootprint->
GetReference() );
936 if( changed &&
copy )
956 if( !
m_commit.GetStatus( aPcbFootprint ) )
959 copy->SetParentGroup(
nullptr );
962 bool changed =
false;
971 KIID existingGroupKIID = existingGroup ? existingGroup->
m_Uuid : 0;
974 auto it = std::find_if(
m_board->Groups().begin(),
m_board->Groups().end(),
976 return group->m_Uuid == newGroupKIID;
980 if( it !=
m_board->Groups().end() )
984 if( newGroupKIID == existingGroupKIID )
988 if( existingGroupKIID != 0 )
992 msg.Printf(
_(
"Remove %s from group '%s'." ),
998 msg.Printf(
_(
"Removed %s from group '%s'." ),
1006 if( existingGroup->
GetItems().size() < 2 )
1017 if( newGroupKIID != 0 )
1021 msg.Printf(
_(
"Add %s to group '%s'." ),
1027 msg.Printf(
_(
"Added %s to group '%s'." ),
1033 if( newGroup ==
nullptr )
1036 newGroup->
SetUuid( newGroupKIID );
1049 newGroup->
AddItem( aPcbFootprint );
1055 if( changed &&
copy )
1075 copy->SetParentGroup(
nullptr );
1078 bool changed =
false;
1081 std::deque<PAD*> pads = aFootprint->
Pads();
1082 std::set<wxString> padNetnames;
1084 std::sort( pads.begin(), pads.end(),
1087 return a->m_Uuid < b->m_Uuid;
1094 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1095 wxT(
"Processing pad %s of component %s" ),
1099 wxString pinFunction;
1104 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1105 wxT(
" Found valid net: %s" ),
1112 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1113 wxT(
" No net found for pad %s" ),
1119 if(
pad->GetPinFunction() != pinFunction )
1122 pad->SetPinFunction( pinFunction );
1125 if(
pad->GetPinType() != pinType )
1128 pad->SetPinType( pinType );
1137 if( !net.
IsValid() || !
pad->IsOnCopperLayer() )
1139 if( !
pad->GetNetname().IsEmpty() )
1143 msg.Printf(
_(
"Disconnect %s pin %s." ),
1149 msg.Printf(
_(
"Disconnected %s pin %s." ),
1156 else if(
pad->IsOnCopperLayer() && !
pad->GetNumber().IsEmpty() )
1159 msg.Printf(
_(
"No net found for component %s pad %s (no pin %s in symbol)." ),
1174 if(
pad->GetNetname().IsEmpty() )
1175 pad->SetPinFunction( wxEmptyString );
1187 if(
pad->IsNoConnectPad() )
1189 netName = wxString::Format( wxS(
"%s" ), net.
GetNetName() );
1191 for(
int jj = 1; !padNetnames.insert( netName ).second
1195 netName = wxString::Format( wxS(
"%s_%d" ), net.
GetNetName(), jj );
1204 if(
pad->GetNetname() != netName )
1207 if( netinfo ==
nullptr )
1214 if( netinfo ==
nullptr )
1226 msg.Printf(
_(
"Add net %s." ),
1231 if( !
pad->GetNetname().IsEmpty() )
1237 msg.Printf(
_(
"Reconnect %s pin %s from %s to %s."),
1245 msg.Printf(
_(
"Reconnected %s pin %s from %s to %s."),
1256 msg.Printf(
_(
"Connect %s pin %s to %s."),
1263 msg.Printf(
_(
"Connected %s pin %s to %s."),
1275 pad->SetNet( netinfo );
1285 if( changed &&
copy )
1297 std::vector<FOOTPRINT::FP_UNIT_INFO> newUnits;
1300 newUnits.push_back( { u.m_unitName, u.m_pins } );
1302 const std::vector<FOOTPRINT::FP_UNIT_INFO>& curUnits = aFootprint->
GetUnitInfo();
1304 auto unitsEqual = [](
const std::vector<FOOTPRINT::FP_UNIT_INFO>& a,
1305 const std::vector<FOOTPRINT::FP_UNIT_INFO>& b )
1307 if( a.size() != b.size() )
1310 for(
size_t i = 0; i < a.size(); ++i )
1312 if( a[i].m_unitName != b[i].m_unitName )
1315 if( a[i].m_pins != b[i].m_pins )
1322 if( unitsEqual( curUnits, newUnits ) )
1329 msg.Printf(
_(
"Update %s unit metadata." ), aFootprint->
GetReference() );
1337 if( !
m_commit.GetStatus( aFootprint ) )
1340 copy->SetParentGroup(
nullptr );
1345 msg.Printf(
_(
"Updated %s unit metadata." ), aFootprint->
GetReference() );
1356 const std::vector<FOOTPRINT*>& aFootprints,
1357 const LIB_ID& aBaseFpid )
1362 if( aBaseFpid.
empty() )
1374 std::vector<VARIANT_INFO> variantInfo;
1375 variantInfo.reserve( variants.size() );
1377 for(
const auto& [variantName, variant] : variants )
1379 LIB_ID variantFPID = aBaseFpid;
1381 auto fieldIt = variant.m_fields.find( footprintFieldName );
1383 if( fieldIt != variant.m_fields.end() && !fieldIt->second.IsEmpty() )
1387 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
1389 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
1398 variantFPID = parsedId;
1402 variantInfo.push_back( { variantName, &variant, variantFPID } );
1405 for(
FOOTPRINT* footprint : aFootprints )
1415 copy->SetParentGroup(
nullptr );
1418 bool changed =
false;
1420 auto printAttributeMessage =
1421 [&](
bool add,
const wxString& attrName,
const wxString& variantName )
1425 if( aFootprints.size() > 1 )
1427 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s (footprint %s)." )
1428 :
_(
"Remove %s '%s' attribute from variant %s (footprint %s)." ),
1429 footprint->GetReference(),
1432 footprint->GetFPIDAsString() );
1436 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s." )
1437 :
_(
"Remove %s '%s' attribute from variant %s." ),
1438 footprint->GetReference(),
1445 if( aFootprints.size() > 1 )
1447 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s (footprint %s)." )
1448 :
_(
"Removed %s '%s' attribute from variant %s (footprint %s)." ),
1449 footprint->GetReference(),
1452 footprint->GetFPIDAsString() );
1456 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s." )
1457 :
_(
"Removed %s '%s' attribute from variant %s." ),
1458 footprint->GetReference(),
1465 std::set<wxString> excessVariants;
1467 for(
const auto& [variantName,
_] : footprint->GetVariants() )
1468 excessVariants.insert( variantName );
1470 for(
const VARIANT_INFO&
info : variantInfo )
1478 bool isAssociatedFootprint = ( footprint->GetFPID() ==
info.variantFPID );
1483 if( !isAssociatedFootprint )
1486 excessVariants.erase(
info.name );
1487 bool targetDnp = variant.
m_hasDnp ? variant.
m_dnp : footprint->IsDNP();
1488 bool currentDnp = currentVariant ? currentVariant->
GetDNP() : footprint->IsDNP();
1490 if( currentDnp != targetDnp )
1492 printAttributeMessage( targetDnp,
_(
"Do not place" ),
info.name );
1497 fpVariant->SetDNP( targetDnp );
1505 : footprint->IsExcludedFromBOM();
1507 : footprint->IsExcludedFromBOM();
1509 if( currentExcludedFromBOM != targetExcludedFromBOM )
1511 printAttributeMessage( targetExcludedFromBOM,
_(
"exclude from BOM" ),
info.name );
1516 fpVariant->SetExcludedFromBOM( targetExcludedFromBOM );
1524 : footprint->IsExcludedFromPosFiles();
1526 : footprint->IsExcludedFromPosFiles();
1528 if( currentExcludedFromPosFiles != targetExcludedFromPosFiles )
1530 printAttributeMessage( targetExcludedFromPosFiles,
_(
"exclude from position files" ),
info.name );
1535 fpVariant->SetExcludedFromPosFiles( targetExcludedFromPosFiles );
1542 for(
const auto& [fieldName, fieldValue] : variant.
m_fields )
1544 if( fieldName.CmpNoCase( footprintFieldName ) == 0 )
1547 bool hasCurrentValue = currentVariant && currentVariant->
HasFieldValue( fieldName );
1548 wxString currentValue = hasCurrentValue ? currentVariant->
GetFieldValue( fieldName ) : wxString();
1550 if( currentValue != fieldValue )
1554 if( aFootprints.size() > 1 )
1556 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s (footprint %s)." ),
1557 footprint->GetReference(),
1561 footprint->GetFPIDAsString() );
1565 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s." ),
1566 footprint->GetReference(),
1574 if( aFootprints.size() > 1 )
1576 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s (footprint %s)." ),
1577 footprint->GetReference(),
1581 footprint->GetFPIDAsString() );
1585 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s." ),
1586 footprint->GetReference(),
1593 fpVariant->SetFieldValue( fieldName, fieldValue );
1602 for(
const wxString& excess : excessVariants )
1606 msg.Printf(
_(
"Remove variant %s:%s no longer associated with footprint %s." ),
1607 footprint->GetReference(),
1609 footprint->GetFPIDAsString() );
1613 msg.Printf(
_(
"Removed variant %s:%s no longer associated with footprint %s." ),
1614 footprint->GetReference(),
1616 footprint->GetFPIDAsString() );
1618 footprint->DeleteVariant( excess );
1627 bool isBaseFootprint = ( footprint->GetFPID() == aBaseFpid );
1629 if( !isBaseFootprint && !footprint->IsDNP() )
1631 msg.Printf(
m_isDryRun ?
_(
"Add %s 'Do not place' fabrication attribute." )
1632 :
_(
"Added %s 'Do not place' fabrication attribute." ),
1633 footprint->GetReference() );
1638 footprint->SetDNP(
true );
1655 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1666 std::set<wxString> netlistNetnames;
1668 for(
int ii = 0; ii < (int) aNetlist.
GetCount(); ii++ )
1672 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1684 if( netlistNetnames.count(
via->GetNetname() ) == 0 )
1686 wxString updatedNetname = wxEmptyString;
1695 if( !updatedNetname.IsEmpty() )
1699 wxString originalNetname =
via->GetNetname();
1701 msg.Printf(
_(
"Reconnect via from %s to %s." ),
1716 wxString originalNetname =
via->GetNetname();
1719 via->SetNet( netinfo );
1721 msg.Printf(
_(
"Reconnected via from %s to %s." ),
1731 msg.Printf(
_(
"Via connected to unknown net (%s)." ),
1743 auto isInNetlist = [&](
const wxString& aNetName ) ->
bool
1745 if( netlistNetnames.count( aNetName ) )
1750 for(
const wxString& netName : netlistNetnames )
1752 if( aNetName.StartsWith( netName ) )
1762 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1765 if( !isInNetlist( zone->GetNetname() ) )
1770 wxString updatedNetname = wxEmptyString;
1783 if( updatedNetname.IsEmpty() &&
m_oldToNewNets.count( zone->GetNetname() ) )
1788 if( !updatedNetname.IsEmpty() )
1792 wxString originalNetname = zone->GetNetname();
1794 if( !zone->GetZoneName().IsEmpty() )
1796 msg.Printf(
_(
"Reconnect copper zone '%s' from %s to %s." ),
1797 zone->GetZoneName(),
1803 msg.Printf(
_(
"Reconnect copper zone from %s to %s." ),
1819 wxString originalNetname = zone->GetNetname();
1822 zone->SetNet( netinfo );
1824 if( !zone->GetZoneName().IsEmpty() )
1826 msg.Printf(
_(
"Reconnected copper zone '%s' from %s to %s." ),
1833 msg.Printf(
_(
"Reconnected copper zone from %s to %s." ),
1844 if( !zone->GetZoneName().IsEmpty() )
1846 msg.Printf(
_(
"Copper zone '%s' has no pads connected." ),
1851 wxString layerNames = zone->LayerMaskDescribe();
1856 if(
m_frame->GetPcbNewSettings()->m_Display.m_DisplayInvertXAxis )
1859 if(
m_frame->GetPcbNewSettings()->m_Display.m_DisplayInvertYAxis )
1863 msg.Printf(
_(
"Copper zone on %s at (%s, %s) has no pads connected to net \"%s\"." ),
1869 zone->GetNetname() );
1893 if( netlistGroup ==
nullptr )
1896 if( netlistGroup->
name != pcbGroup->GetName() )
1900 msg.Printf(
_(
"Change group name from '%s' to '%s'." ),
1906 msg.Printf(
_(
"Changed group name from '%s' to '%s'." ),
1910 pcbGroup->SetName( netlistGroup->
name );
1916 if( netlistGroup->
libId != pcbGroup->GetDesignBlockLibId() )
1920 msg.Printf(
_(
"Change group library link from '%s' to '%s'." ),
1921 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1926 msg.Printf(
_(
"Changed group library link from '%s' to '%s'." ),
1927 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1930 pcbGroup->SetDesignBlockLibId( netlistGroup->
libId );
1942 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
1950 for(
int i = 0; i < (int) aNetlist.
GetCount(); i++ )
1953 FOOTPRINT* footprint = aFootprintMap[component];
1959 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1963 if( padNumber.IsEmpty() )
1966 msg.Printf(
_(
"Symbol %s has pins with no number. These pins can not be matched "
1976 msg.Printf(
_(
"%s pad %s not found in %s." ),
1992 FOOTPRINT* lastPreexistingFootprint =
nullptr;
1995 std::unordered_set<wxString> sheetPaths;
1996 std::unordered_set<FOOTPRINT*> usedFootprints;
2002 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
2004 if( !
m_board->Footprints().empty() )
2005 lastPreexistingFootprint =
m_board->Footprints().back();
2015 net->SetIsCurrent( net->GetNetCode() == 0 );
2017 m_board->GetComponentClassManager().InitNetlistUpdate();
2021 for(
unsigned ii = 0; ii < aNetlist.
GetCount(); ii++ )
2025 for(
unsigned jj = 0; jj <
comp->GetNetCount(); jj++ )
2032 for(
unsigned i = 0; i < aNetlist.
GetCount(); i++ )
2036 if( component->
GetProperties().count( wxT(
"exclude_from_board" ) ) )
2039 msg.Printf(
_(
"Processing symbol '%s:%s'." ),
2045 const bool hasBaseFpid = !baseFpid.
empty();
2049 msg.Printf(
_(
"Warning: %s footprint '%s' is missing a library name. "
2050 "Use the full 'Library:Footprint' format to avoid repeated update "
2058 std::vector<FOOTPRINT*> matchingFootprints;
2069 base.push_back( uuid );
2071 if( footprint->GetPath() == base )
2080 match = footprint->GetReference().CmpNoCase( component->
GetReference() ) == 0;
2084 matchingFootprints.push_back( footprint );
2086 if( footprint == lastPreexistingFootprint )
2093 std::vector<LIB_ID> expectedFpids;
2094 std::unordered_set<wxString> expectedFpidKeys;
2096 auto addExpectedFpid =
2097 [&](
const LIB_ID& aFpid )
2102 wxString key = aFpid.Format();
2104 if( expectedFpidKeys.insert( key ).second )
2105 expectedFpids.push_back( aFpid );
2108 addExpectedFpid( baseFpid );
2112 for(
const auto& [variantName, variant] : component->
GetVariants() )
2114 auto fieldIt = variant.m_fields.find( footprintFieldName );
2116 if( fieldIt == variant.m_fields.end() || fieldIt->second.IsEmpty() )
2121 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
2123 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
2132 addExpectedFpid( parsedId );
2140 [&](
const LIB_ID& aBoardFpid,
const LIB_ID& aExpectedFpid ) ->
bool
2142 if( aExpectedFpid.IsLegacy() )
2143 return aBoardFpid.
GetLibItemName() == aExpectedFpid.GetLibItemName();
2145 return aBoardFpid == aExpectedFpid;
2148 auto isExpectedFpid =
2149 [&](
const LIB_ID& aFpid ) ->
bool
2154 if( expectedFpidKeys.count( aFpid.Format() ) > 0 )
2159 if( fpidMatches( aFpid,
expected ) )
2166 auto takeMatchingFootprint =
2169 for(
FOOTPRINT* footprint : matchingFootprints )
2171 if( usedFootprints.count( footprint ) )
2174 if( fpidMatches( footprint->GetFPID(), aFpid ) )
2181 std::vector<FOOTPRINT*> componentFootprints;
2182 componentFootprints.reserve( expectedFpids.size() );
2186 baseFootprint = takeMatchingFootprint( baseFpid );
2187 else if( !matchingFootprints.empty() )
2188 baseFootprint = matchingFootprints.front();
2194 for(
FOOTPRINT* footprint : matchingFootprints )
2196 if( usedFootprints.count( footprint ) )
2199 if( isExpectedFpid( footprint->GetFPID() ) )
2202 replaceCandidate = footprint;
2206 if( replaceCandidate )
2211 baseFootprint = replaced;
2213 baseFootprint = replaceCandidate;
2217 if( !baseFootprint && ( hasBaseFpid || expectedFpids.empty() ) )
2222 componentFootprints.push_back( baseFootprint );
2223 usedFootprints.insert( baseFootprint );
2224 footprintMap[ component ] = baseFootprint;
2227 for(
const LIB_ID& fpid : expectedFpids )
2229 if( fpid == baseFpid )
2232 FOOTPRINT* footprint = takeMatchingFootprint( fpid );
2239 componentFootprints.push_back( footprint );
2240 usedFootprints.insert( footprint );
2244 for(
FOOTPRINT* footprint : componentFootprints )
2255 sheetPaths.insert( footprint->GetSheetname() );
2258 if( !componentFootprints.empty() )
2270 bool matched =
false;
2276 bool isStaleVariantFootprint =
false;
2278 if( usedFootprints.count( footprint ) )
2289 if( component && component->
GetProperties().count( wxT(
"exclude_from_board" ) ) == 0 )
2297 isStaleVariantFootprint =
true;
2308 if( isStaleVariantFootprint )
2311 if( doDelete && !matched && footprint->IsLocked() && !
m_overrideLocks )
2315 msg.Printf(
_(
"Cannot remove unused footprint %s (footprint is locked)." ),
2316 footprint->GetReference() );
2320 msg.Printf(
_(
"Could not remove unused footprint %s (footprint is locked)." ),
2321 footprint->GetReference() );
2329 if( doDelete && !matched )
2333 msg.Printf(
_(
"Remove unused footprint %s." ),
2334 footprint->GetReference() );
2339 msg.Printf(
_(
"Removed unused footprint %s." ),
2340 footprint->GetReference() );
2350 for(
PAD*
pad : footprint->Pads() )
2353 pad->GetNet()->SetIsCurrent(
true );
2361 m_board->GetComponentClassManager().FinishNetlistUpdate();
2362 m_board->SynchronizeComponentClasses( sheetPaths );
2369 if( !net->IsCurrent() )
2371 msg.Printf(
_(
"Removed unused net %s." ),
2380 const std::vector<wxString>& netlistVariants = aNetlist.
GetVariantNames();
2382 if( !netlistVariants.empty() || !
m_board->GetVariantNames().empty() )
2386 auto findBoardVariantName =
2387 [&](
const wxString& aVariantName ) -> wxString
2389 for(
const wxString&
name :
m_board->GetVariantNames() )
2391 if(
name.CmpNoCase( aVariantName ) == 0 )
2395 return wxEmptyString;
2398 std::vector<wxString> updatedVariantNames;
2399 updatedVariantNames.reserve( netlistVariants.size() );
2401 for(
const wxString& variantName : netlistVariants )
2403 wxString actualName = findBoardVariantName( variantName );
2405 if( actualName.IsEmpty() )
2407 m_board->AddVariant( variantName );
2408 actualName = findBoardVariantName( variantName );
2410 if( !actualName.IsEmpty() )
2412 msg.Printf(
_(
"Added variant '%s'." ), actualName );
2417 if( actualName.IsEmpty() )
2422 wxString oldDescription =
m_board->GetVariantDescription( actualName );
2424 if( newDescription != oldDescription )
2426 m_board->SetVariantDescription( actualName, newDescription );
2427 msg.Printf(
_(
"Updated description for variant '%s'." ), actualName );
2431 updatedVariantNames.push_back( actualName );
2434 std::vector<wxString> variantsToRemove;
2436 for(
const wxString& existingName :
m_board->GetVariantNames() )
2440 for(
const wxString& variantName : netlistVariants )
2442 if( existingName.CmpNoCase( variantName ) == 0 )
2450 variantsToRemove.push_back( existingName );
2453 for(
const wxString& variantName : variantsToRemove )
2455 m_board->DeleteVariant( variantName );
2456 msg.Printf(
_(
"Removed variant '%s'." ), variantName );
2460 if( !updatedVariantNames.empty() )
2461 m_board->SetVariantNames( updatedVariantNames );
2480 if( !colorStr.IsEmpty() )
2494 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
2498 netSettings->ClearNetChainClasses();
2499 netSettings->ClearChainPatternAssignments();
2502 netSettings->SetNetChainClass(
chain, className );
2510 const wxString& chainName = net->GetNetChain();
2512 if( chainName.IsEmpty() )
2515 auto it = chainClasses.find( chainName );
2517 if( it == chainClasses.end() || it->second.IsEmpty() )
2520 if( netSettings->HasNetclass( it->second ) )
2521 netSettings->SetChainPatternAssignment( net->GetNetname(), it->second );
2526 m_board->SynchronizeNetsAndNetClasses(
true );
2530 m_board->SynchronizeNetsAndNetClasses(
true );
2535 PAD* pads[2] = {
nullptr,
nullptr };
2537 for(
size_t i = 0; i < sig.second.size() && i < 2; ++i )
2539 const wxString& ref = sig.second[i].first;
2540 const wxString&
pin = sig.second[i].second;
2546 PAD* candidate =
nullptr;
2547 PAD* best =
nullptr;
2548 int bestDist = std::numeric_limits<int>::max();
2557 if( !best || dist < bestDist || ( dist == bestDist && candidate->
m_Uuid < best->
m_Uuid ) )
2567 for(
int i = 0; i < 2; ++i )
2574 if( !termNet || termNet->
GetNetChain() != sig.first )
2579 if( net != termNet && net->
GetNetChain() == sig.first
2580 && net->GetTerminalPad( i ) )
2582 net->ClearTerminalPad( i );
2598 for(
const std::pair<const wxString, NETINFO_ITEM*>& addedNet :
m_addedNets )
2599 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
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)
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.
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
static REPORTER & GetInstance()
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.
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