89 const wxString previous = net->GetNetChain();
92 if( !previous.IsEmpty() &&
next.IsEmpty() && aReporter && !aDryRun )
96 _(
"Net chain assignment '%s' on net '%s' cleared by netlist "
98 previous, net->GetNetname() ),
104 net->SetNetChain(
next );
106 if( previous !=
next )
108 for(
int i = 0; i < 2; ++i )
109 net->ClearTerminalPad( i );
169 bestPosition.
x = pageSize.
x / 2;
170 bestPosition.
y = pageSize.
y / 2;
187 if( aFootprintId.
empty() )
189 msg.Printf(
_(
"Cannot add %s (no footprint assigned)." ),
198 if( footprint ==
nullptr )
200 msg.Printf(
_(
"Cannot add %s (footprint '%s' not found)." ),
209 m_board->GetComponentClassManager().GetNoneComponentClass() );
213 msg.Printf(
_(
"Add %s (footprint '%s')." ),
225 pad->SetLocalRatsnestVisible(
m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest );
228 pad->SetNetCode( 0 );
243 msg.Printf(
_(
"Added %s (footprint '%s')." ),
256 wxString curClassName, newClassName;
260 curClassName = curClass->
GetName();
270 newClass =
m_board->GetComponentClassManager().GetEffectiveStaticComponentClass(
272 newClassName = newClass->
GetName();
275 if( curClassName == newClassName )
284 copy->SetParentGroup(
nullptr );
291 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
293 msg.Printf(
_(
"Change %s component class to '%s'." ),
297 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
299 msg.Printf(
_(
"Remove %s component class (currently '%s')." ),
305 msg.Printf(
_(
"Change %s component class from '%s' to '%s'." ),
313 wxASSERT_MSG( newClass !=
nullptr,
"Component class should not be nullptr" );
317 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
319 msg.Printf(
_(
"Changed %s component class to '%s'." ),
323 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
325 msg.Printf(
_(
"Removed %s component class (was '%s')." ),
331 msg.Printf(
_(
"Changed %s component class from '%s' to '%s'." ),
354 msg.Printf(
_(
"Cannot update %s (no footprint assigned)." ),
363 if( newFootprint ==
nullptr )
365 msg.Printf(
_(
"Cannot update %s (footprint '%s' not found)." ),
377 msg.Printf(
_(
"Cannot change %s footprint from '%s' to '%s' (footprint is locked)."),
388 msg.Printf(
_(
"Change %s footprint from '%s' to '%s'."),
402 msg.Printf(
_(
"Could not change %s footprint from '%s' to '%s' (footprint is locked)."),
416 m_frame->ExchangeFootprint( aFootprint, newFootprint,
m_commit,
true );
418 msg.Printf(
_(
"Changed %s footprint from '%s' to '%s'."),
443 firstAssociatedVariant = &
test;
452 if( !
m_commit.GetStatus( aFootprint ) )
455 copy->SetParentGroup(
nullptr );
458 bool changed =
false;
465 msg.Printf(
_(
"Change %s reference designator to %s." ),
471 msg.Printf(
_(
"Changed %s reference designator to %s." ),
483 wxString netlistValue = aNetlistComponent->
GetValue();
485 if( firstAssociatedVariant !=
nullptr
491 if( aFootprint->
GetValue() != netlistValue )
495 msg.Printf(
_(
"Change %s value from %s to %s." ),
502 msg.Printf(
_(
"Changed %s value from %s to %s." ),
508 aFootprint->
SetValue( netlistValue );
517 if( !aNetlistComponent->
GetKIIDs().empty() )
518 new_path.push_back( aNetlistComponent->
GetKIIDs().front() );
520 if( aFootprint->
GetPath() != new_path )
524 msg.Printf(
_(
"Update %s symbol association from %s to %s." ),
531 msg.Printf(
_(
"Updated %s symbol association from %s to %s." ),
537 aFootprint->
SetPath( new_path );
543 nlohmann::ordered_map<wxString, wxString> fpFieldsAsMap;
548 if( field->IsReference() || field->IsValue() || field->IsComponentClass() )
553 fpFieldsAsMap[field->GetName()] = field->GetText();
557 nlohmann::ordered_map<wxString, wxString> compFields = aNetlistComponent->
GetFields();
563 compFields.erase( wxT(
"Component Class" ) );
565 if( firstAssociatedVariant !=
nullptr )
567 for(
const auto& [
name, value] : firstAssociatedVariant->
m_fields )
568 compFields[
name] = value;
574 bool remove_only =
true;
576 for(
const auto& [
name, value] : compFields )
578 if( fpFieldsAsMap.count(
name ) == 0 || fpFieldsAsMap[
name] != value )
586 for(
const auto& [
name, value] : fpFieldsAsMap )
588 if( compFields.count(
name ) == 0 )
601 msg.Printf(
_(
"Update %s fields." ), aFootprint->
GetReference() );
608 if( field->IsMandatory() )
611 if( compFields.count( field->GetName() ) == 0 )
615 msg.Printf(
_(
"Remove %s footprint fields not in symbol." ), aFootprint->
GetReference() );
627 msg.Printf(
_(
"Updated %s fields." ), aFootprint->
GetReference() );
633 for(
auto& [
name, value] : compFields )
642 aFootprint->
Add( newField );
664 std::vector<PCB_FIELD*> fieldList;
665 aFootprint->
GetFields( fieldList,
false );
669 if( field->IsMandatory() )
672 if( compFields.count( field->GetName() ) == 0 )
677 msg.Printf(
_(
"Removed %s footprint fields not in symbol." ), aFootprint->
GetReference() );
681 aFootprint->
Remove( field );
684 m_frame->GetCanvas()->GetView()->Remove( field );
699 if( !humanSheetPath.empty() )
700 sheetname = humanSheetPath;
701 else if( aNetlistComponent->
GetProperties().count( wxT(
"Sheetname" ) ) > 0 )
702 sheetname = aNetlistComponent->
GetProperties().at( wxT(
"Sheetname" ) );
704 if( aNetlistComponent->
GetProperties().count( wxT(
"Sheetfile" ) ) > 0 )
705 sheetfile = aNetlistComponent->
GetProperties().at( wxT(
"Sheetfile" ) );
707 if( aNetlistComponent->
GetProperties().count( wxT(
"ki_fp_filters" ) ) > 0 )
708 fpFilters = aNetlistComponent->
GetProperties().at( wxT(
"ki_fp_filters" ) );
714 msg.Printf(
_(
"Update %s sheetname to '%s'." ),
721 msg.Printf(
_(
"Updated %s sheetname to '%s'." ),
733 msg.Printf(
_(
"Update %s sheetfile to '%s'." ),
740 msg.Printf(
_(
"Updated %s sheetfile to '%s'." ),
752 msg.Printf(
_(
"Update %s footprint filters to '%s'." ),
759 msg.Printf(
_(
"Updated %s footprint filters to '%s'." ),
767 bool netlistExcludeFromBOM = aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_bom" ) ) > 0;
776 if( netlistExcludeFromBOM )
777 msg.Printf(
_(
"Add %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
779 msg.Printf(
_(
"Remove %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
785 if( netlistExcludeFromBOM )
788 msg.Printf(
_(
"Added %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
793 msg.Printf(
_(
"Removed %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
803 bool netlistDNP = aNetlistComponent->
GetProperties().count( wxT(
"dnp" ) ) > 0;
805 if( firstAssociatedVariant !=
nullptr && firstAssociatedVariant->
m_hasDnp )
806 netlistDNP = firstAssociatedVariant->
m_dnp;
813 msg.Printf(
_(
"Add %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
815 msg.Printf(
_(
"Remove %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
824 msg.Printf(
_(
"Added %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
829 msg.Printf(
_(
"Removed %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
839 bool netlistExcludeFromPosFiles = aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_pos_files" ) ) > 0;
849 if( netlistExcludeFromPosFiles )
851 msg.Printf(
_(
"Add %s 'exclude from position files' fabrication attribute." ),
856 msg.Printf(
_(
"Remove %s 'exclude from position files' fabrication attribute." ),
864 if( netlistExcludeFromPosFiles )
867 msg.Printf(
_(
"Added %s 'exclude from position files' fabrication attribute." ),
873 msg.Printf(
_(
"Removed %s 'exclude from position files' fabrication attribute." ),
896 msg.Printf(
_(
"Added %s 'duplicate pad numbers are jumpers' attribute." ),
901 msg.Printf(
_(
"Removed %s 'duplicate pad numbers are jumpers' attribute." ),
909 msg.Printf(
_(
"Add %s 'duplicate pad numbers are jumpers' attribute." ),
914 msg.Printf(
_(
"Remove %s 'duplicate pad numbers are jumpers' attribute." ),
928 msg.Printf(
_(
"Updated %s jumper pad groups" ), aFootprint->
GetReference() );
932 msg.Printf(
_(
"Update %s jumper pad groups" ), aFootprint->
GetReference() );
938 if( changed &&
copy )
958 if( !
m_commit.GetStatus( aPcbFootprint ) )
961 copy->SetParentGroup(
nullptr );
964 bool changed =
false;
973 KIID existingGroupKIID = existingGroup ? existingGroup->
m_Uuid : 0;
976 auto it = std::find_if(
m_board->Groups().begin(),
m_board->Groups().end(),
978 return group->m_Uuid == newGroupKIID;
982 if( it !=
m_board->Groups().end() )
986 if( newGroupKIID == existingGroupKIID )
990 if( existingGroupKIID != 0 )
994 msg.Printf(
_(
"Remove %s from group '%s'." ),
1000 msg.Printf(
_(
"Removed %s from group '%s'." ),
1008 if( existingGroup->
GetItems().size() < 2 )
1019 if( newGroupKIID != 0 )
1023 msg.Printf(
_(
"Add %s to group '%s'." ),
1029 msg.Printf(
_(
"Added %s to group '%s'." ),
1035 if( newGroup ==
nullptr )
1038 newGroup->
SetUuid( newGroupKIID );
1052 newGroup->
AddItem( aPcbFootprint );
1058 if( changed &&
copy )
1078 copy->SetParentGroup(
nullptr );
1081 bool changed =
false;
1084 std::deque<PAD*> pads = aFootprint->
Pads();
1085 std::set<wxString> padNetnames;
1087 std::sort( pads.begin(), pads.end(),
1090 return a->m_Uuid < b->m_Uuid;
1097 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1098 wxT(
"Processing pad %s of component %s" ),
1102 wxString pinFunction;
1107 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1108 wxT(
" Found valid net: %s" ),
1115 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1116 wxT(
" No net found for pad %s" ),
1122 if(
pad->GetPinFunction() != pinFunction )
1125 pad->SetPinFunction( pinFunction );
1128 if(
pad->GetPinType() != pinType )
1131 pad->SetPinType( pinType );
1140 if( !net.
IsValid() || !
pad->IsOnCopperLayer() )
1142 if( !
pad->GetNetname().IsEmpty() )
1146 msg.Printf(
_(
"Disconnect %s pin %s." ),
1152 msg.Printf(
_(
"Disconnected %s pin %s." ),
1159 else if(
pad->IsOnCopperLayer() && !
pad->GetNumber().IsEmpty() )
1162 msg.Printf(
_(
"No net found for component %s pad %s (no pin %s in symbol)." ),
1177 if(
pad->GetNetname().IsEmpty() )
1178 pad->SetPinFunction( wxEmptyString );
1190 if(
pad->IsNoConnectPad() )
1192 netName = wxString::Format( wxS(
"%s" ), net.
GetNetName() );
1194 for(
int jj = 1; !padNetnames.insert( netName ).second
1198 netName = wxString::Format( wxS(
"%s_%d" ), net.
GetNetName(), jj );
1207 if(
pad->GetNetname() != netName )
1210 if( netinfo ==
nullptr )
1217 if( netinfo ==
nullptr )
1229 msg.Printf(
_(
"Add net %s." ),
1234 if( !
pad->GetNetname().IsEmpty() )
1240 msg.Printf(
_(
"Reconnect %s pin %s from %s to %s."),
1248 msg.Printf(
_(
"Reconnected %s pin %s from %s to %s."),
1259 msg.Printf(
_(
"Connect %s pin %s to %s."),
1266 msg.Printf(
_(
"Connected %s pin %s to %s."),
1278 pad->SetNet( netinfo );
1288 if( changed &&
copy )
1300 std::vector<FOOTPRINT::FP_UNIT_INFO> newUnits;
1303 newUnits.push_back( { u.m_unitName, u.m_pins } );
1305 const std::vector<FOOTPRINT::FP_UNIT_INFO>& curUnits = aFootprint->
GetUnitInfo();
1307 auto unitsEqual = [](
const std::vector<FOOTPRINT::FP_UNIT_INFO>& a,
1308 const std::vector<FOOTPRINT::FP_UNIT_INFO>& b )
1310 if( a.size() != b.size() )
1313 for(
size_t i = 0; i < a.size(); ++i )
1315 if( a[i].m_unitName != b[i].m_unitName )
1318 if( a[i].m_pins != b[i].m_pins )
1325 if( unitsEqual( curUnits, newUnits ) )
1332 msg.Printf(
_(
"Update %s unit metadata." ), aFootprint->
GetReference() );
1340 if( !
m_commit.GetStatus( aFootprint ) )
1343 copy->SetParentGroup(
nullptr );
1348 msg.Printf(
_(
"Updated %s unit metadata." ), aFootprint->
GetReference() );
1359 const std::vector<FOOTPRINT*>& aFootprints,
1360 const LIB_ID& aBaseFpid )
1365 if( aBaseFpid.
empty() )
1377 std::vector<VARIANT_INFO> variantInfo;
1378 variantInfo.reserve( variants.size() );
1380 for(
const auto& [variantName, variant] : variants )
1382 LIB_ID variantFPID = aBaseFpid;
1384 auto fieldIt = variant.m_fields.find( footprintFieldName );
1386 if( fieldIt != variant.m_fields.end() && !fieldIt->second.IsEmpty() )
1390 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
1392 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
1401 variantFPID = parsedId;
1405 variantInfo.push_back( { variantName, &variant, variantFPID } );
1408 for(
FOOTPRINT* footprint : aFootprints )
1418 copy->SetParentGroup(
nullptr );
1421 bool changed =
false;
1423 auto printAttributeMessage =
1424 [&](
bool add,
const wxString& attrName,
const wxString& variantName )
1428 if( aFootprints.size() > 1 )
1430 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s (footprint %s)." )
1431 :
_(
"Remove %s '%s' attribute from variant %s (footprint %s)." ),
1432 footprint->GetReference(),
1435 footprint->GetFPIDAsString() );
1439 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s." )
1440 :
_(
"Remove %s '%s' attribute from variant %s." ),
1441 footprint->GetReference(),
1448 if( aFootprints.size() > 1 )
1450 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s (footprint %s)." )
1451 :
_(
"Removed %s '%s' attribute from variant %s (footprint %s)." ),
1452 footprint->GetReference(),
1455 footprint->GetFPIDAsString() );
1459 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s." )
1460 :
_(
"Removed %s '%s' attribute from variant %s." ),
1461 footprint->GetReference(),
1468 std::set<wxString> excessVariants;
1470 for(
const auto& [variantName,
_] : footprint->GetVariants() )
1471 excessVariants.insert( variantName );
1473 for(
const VARIANT_INFO&
info : variantInfo )
1481 bool isAssociatedFootprint = ( footprint->GetFPID() ==
info.variantFPID );
1486 if( !isAssociatedFootprint )
1489 excessVariants.erase(
info.name );
1490 bool targetDnp = variant.
m_hasDnp ? variant.
m_dnp : footprint->IsDNP();
1491 bool currentDnp = currentVariant ? currentVariant->
GetDNP() : footprint->IsDNP();
1493 if( currentDnp != targetDnp )
1495 printAttributeMessage( targetDnp,
_(
"Do not place" ),
info.name );
1500 fpVariant->SetDNP( targetDnp );
1508 : footprint->IsExcludedFromBOM();
1510 : footprint->IsExcludedFromBOM();
1512 if( currentExcludedFromBOM != targetExcludedFromBOM )
1514 printAttributeMessage( targetExcludedFromBOM,
_(
"exclude from BOM" ),
info.name );
1519 fpVariant->SetExcludedFromBOM( targetExcludedFromBOM );
1527 : footprint->IsExcludedFromPosFiles();
1529 : footprint->IsExcludedFromPosFiles();
1531 if( currentExcludedFromPosFiles != targetExcludedFromPosFiles )
1533 printAttributeMessage( targetExcludedFromPosFiles,
_(
"exclude from position files" ),
info.name );
1538 fpVariant->SetExcludedFromPosFiles( targetExcludedFromPosFiles );
1545 for(
const auto& [fieldName, fieldValue] : variant.
m_fields )
1547 if( fieldName.CmpNoCase( footprintFieldName ) == 0 )
1550 bool hasCurrentValue = currentVariant && currentVariant->
HasFieldValue( fieldName );
1551 wxString currentValue = hasCurrentValue ? currentVariant->
GetFieldValue( fieldName ) : wxString();
1553 if( currentValue != fieldValue )
1557 if( aFootprints.size() > 1 )
1559 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s (footprint %s)." ),
1560 footprint->GetReference(),
1564 footprint->GetFPIDAsString() );
1568 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s." ),
1569 footprint->GetReference(),
1577 if( aFootprints.size() > 1 )
1579 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s (footprint %s)." ),
1580 footprint->GetReference(),
1584 footprint->GetFPIDAsString() );
1588 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s." ),
1589 footprint->GetReference(),
1596 fpVariant->SetFieldValue( fieldName, fieldValue );
1605 for(
const wxString& excess : excessVariants )
1609 msg.Printf(
_(
"Remove variant %s:%s no longer associated with footprint %s." ),
1610 footprint->GetReference(),
1612 footprint->GetFPIDAsString() );
1616 msg.Printf(
_(
"Removed variant %s:%s no longer associated with footprint %s." ),
1617 footprint->GetReference(),
1619 footprint->GetFPIDAsString() );
1621 footprint->DeleteVariant( excess );
1630 bool isBaseFootprint = ( footprint->GetFPID() == aBaseFpid );
1632 if( !isBaseFootprint && !footprint->IsDNP() )
1634 msg.Printf(
m_isDryRun ?
_(
"Add %s 'Do not place' fabrication attribute." )
1635 :
_(
"Added %s 'Do not place' fabrication attribute." ),
1636 footprint->GetReference() );
1641 footprint->SetDNP(
true );
1658 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1669 std::set<wxString> netlistNetnames;
1671 for(
int ii = 0; ii < (int) aNetlist.
GetCount(); ii++ )
1675 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1687 if( netlistNetnames.count(
via->GetNetname() ) == 0 )
1689 wxString updatedNetname = wxEmptyString;
1698 if( !updatedNetname.IsEmpty() )
1702 wxString originalNetname =
via->GetNetname();
1704 msg.Printf(
_(
"Reconnect via from %s to %s." ),
1719 wxString originalNetname =
via->GetNetname();
1722 via->SetNet( netinfo );
1724 msg.Printf(
_(
"Reconnected via from %s to %s." ),
1734 msg.Printf(
_(
"Via connected to unknown net (%s)." ),
1746 auto isInNetlist = [&](
const wxString& aNetName ) ->
bool
1748 if( netlistNetnames.count( aNetName ) )
1753 for(
const wxString& netName : netlistNetnames )
1755 if( aNetName.StartsWith( netName ) )
1765 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1768 if( !isInNetlist( zone->GetNetname() ) )
1773 wxString updatedNetname = wxEmptyString;
1786 if( updatedNetname.IsEmpty() &&
m_oldToNewNets.count( zone->GetNetname() ) )
1791 if( !updatedNetname.IsEmpty() )
1795 wxString originalNetname = zone->GetNetname();
1797 if( !zone->GetZoneName().IsEmpty() )
1799 msg.Printf(
_(
"Reconnect copper zone '%s' from %s to %s." ),
1800 zone->GetZoneName(),
1806 msg.Printf(
_(
"Reconnect copper zone from %s to %s." ),
1822 wxString originalNetname = zone->GetNetname();
1825 zone->SetNet( netinfo );
1827 if( !zone->GetZoneName().IsEmpty() )
1829 msg.Printf(
_(
"Reconnected copper zone '%s' from %s to %s." ),
1836 msg.Printf(
_(
"Reconnected copper zone from %s to %s." ),
1847 if( !zone->GetZoneName().IsEmpty() )
1849 msg.Printf(
_(
"Copper zone '%s' has no pads connected." ),
1854 wxString layerNames = zone->LayerMaskDescribe();
1859 if(
m_frame->GetPcbNewSettings()->m_Display.m_DisplayInvertXAxis )
1862 if(
m_frame->GetPcbNewSettings()->m_Display.m_DisplayInvertYAxis )
1866 msg.Printf(
_(
"Copper zone on %s at (%s, %s) has no pads connected to net \"%s\"." ),
1872 zone->GetNetname() );
1896 if( netlistGroup ==
nullptr )
1899 if( netlistGroup->
name != pcbGroup->GetName() )
1903 msg.Printf(
_(
"Change group name from '%s' to '%s'." ),
1909 msg.Printf(
_(
"Changed group name from '%s' to '%s'." ),
1913 pcbGroup->SetName( netlistGroup->
name );
1919 if( netlistGroup->
libId != pcbGroup->GetDesignBlockLibId() )
1923 msg.Printf(
_(
"Change group library link from '%s' to '%s'." ),
1924 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1929 msg.Printf(
_(
"Changed group library link from '%s' to '%s'." ),
1930 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1933 pcbGroup->SetDesignBlockLibId( netlistGroup->
libId );
1945 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
1953 for(
int i = 0; i < (int) aNetlist.
GetCount(); i++ )
1956 FOOTPRINT* footprint = aFootprintMap[component];
1962 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1966 if( padNumber.IsEmpty() )
1969 msg.Printf(
_(
"Symbol %s has pins with no number. These pins can not be matched "
1979 msg.Printf(
_(
"%s pad %s not found in %s." ),
1995 FOOTPRINT* lastPreexistingFootprint =
nullptr;
1998 std::unordered_set<wxString> sheetPaths;
1999 std::unordered_set<FOOTPRINT*> usedFootprints;
2005 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
2007 if( !
m_board->Footprints().empty() )
2008 lastPreexistingFootprint =
m_board->Footprints().back();
2018 net->SetIsCurrent( net->GetNetCode() == 0 );
2020 m_board->GetComponentClassManager().InitNetlistUpdate();
2024 for(
unsigned ii = 0; ii < aNetlist.
GetCount(); ii++ )
2028 for(
unsigned jj = 0; jj <
comp->GetNetCount(); jj++ )
2035 for(
unsigned i = 0; i < aNetlist.
GetCount(); i++ )
2039 if( component->
GetProperties().count( wxT(
"exclude_from_board" ) ) )
2042 msg.Printf(
_(
"Processing symbol '%s:%s'." ),
2048 const bool hasBaseFpid = !baseFpid.
empty();
2052 msg.Printf(
_(
"Warning: %s footprint '%s' is missing a library name. "
2053 "Use the full 'Library:Footprint' format to avoid repeated update "
2061 std::vector<FOOTPRINT*> matchingFootprints;
2072 base.push_back( uuid );
2074 if( footprint->GetPath() == base )
2083 match = footprint->GetReference().CmpNoCase( component->
GetReference() ) == 0;
2087 matchingFootprints.push_back( footprint );
2089 if( footprint == lastPreexistingFootprint )
2096 std::vector<LIB_ID> expectedFpids;
2097 std::unordered_set<wxString> expectedFpidKeys;
2099 auto addExpectedFpid =
2100 [&](
const LIB_ID& aFpid )
2105 wxString key = aFpid.Format();
2107 if( expectedFpidKeys.insert( key ).second )
2108 expectedFpids.push_back( aFpid );
2111 addExpectedFpid( baseFpid );
2115 for(
const auto& [variantName, variant] : component->
GetVariants() )
2117 auto fieldIt = variant.m_fields.find( footprintFieldName );
2119 if( fieldIt == variant.m_fields.end() || fieldIt->second.IsEmpty() )
2124 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
2126 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
2135 addExpectedFpid( parsedId );
2143 [&](
const LIB_ID& aBoardFpid,
const LIB_ID& aExpectedFpid ) ->
bool
2145 if( aExpectedFpid.IsLegacy() )
2146 return aBoardFpid.
GetLibItemName() == aExpectedFpid.GetLibItemName();
2148 return aBoardFpid == aExpectedFpid;
2151 auto isExpectedFpid =
2152 [&](
const LIB_ID& aFpid ) ->
bool
2157 if( expectedFpidKeys.count( aFpid.Format() ) > 0 )
2162 if( fpidMatches( aFpid,
expected ) )
2169 auto takeMatchingFootprint =
2172 for(
FOOTPRINT* footprint : matchingFootprints )
2174 if( usedFootprints.count( footprint ) )
2177 if( fpidMatches( footprint->GetFPID(), aFpid ) )
2184 std::vector<FOOTPRINT*> componentFootprints;
2185 componentFootprints.reserve( expectedFpids.size() );
2189 baseFootprint = takeMatchingFootprint( baseFpid );
2190 else if( !matchingFootprints.empty() )
2191 baseFootprint = matchingFootprints.front();
2197 for(
FOOTPRINT* footprint : matchingFootprints )
2199 if( usedFootprints.count( footprint ) )
2202 if( isExpectedFpid( footprint->GetFPID() ) )
2205 replaceCandidate = footprint;
2209 if( replaceCandidate )
2214 baseFootprint = replaced;
2216 baseFootprint = replaceCandidate;
2220 if( !baseFootprint && ( hasBaseFpid || expectedFpids.empty() ) )
2225 componentFootprints.push_back( baseFootprint );
2226 usedFootprints.insert( baseFootprint );
2227 footprintMap[ component ] = baseFootprint;
2230 for(
const LIB_ID& fpid : expectedFpids )
2232 if( fpid == baseFpid )
2235 FOOTPRINT* footprint = takeMatchingFootprint( fpid );
2242 componentFootprints.push_back( footprint );
2243 usedFootprints.insert( footprint );
2247 for(
FOOTPRINT* footprint : componentFootprints )
2258 sheetPaths.insert( footprint->GetSheetname() );
2261 if( !componentFootprints.empty() )
2273 bool matched =
false;
2279 bool isStaleVariantFootprint =
false;
2281 if( usedFootprints.count( footprint ) )
2292 if( component && component->
GetProperties().count( wxT(
"exclude_from_board" ) ) == 0 )
2300 isStaleVariantFootprint =
true;
2311 if( isStaleVariantFootprint )
2314 if( doDelete && !matched && footprint->IsLocked() && !
m_overrideLocks )
2318 msg.Printf(
_(
"Cannot remove unused footprint %s (footprint is locked)." ),
2319 footprint->GetReference() );
2323 msg.Printf(
_(
"Could not remove unused footprint %s (footprint is locked)." ),
2324 footprint->GetReference() );
2332 if( doDelete && !matched )
2336 msg.Printf(
_(
"Remove unused footprint %s." ),
2337 footprint->GetReference() );
2342 msg.Printf(
_(
"Removed unused footprint %s." ),
2343 footprint->GetReference() );
2353 for(
PAD*
pad : footprint->Pads() )
2356 pad->GetNet()->SetIsCurrent(
true );
2364 m_board->GetComponentClassManager().FinishNetlistUpdate();
2365 m_board->SynchronizeComponentClasses( sheetPaths );
2372 if( !net->IsCurrent() )
2374 msg.Printf(
_(
"Removed unused net %s." ),
2383 const std::vector<wxString>& netlistVariants = aNetlist.
GetVariantNames();
2385 if( !netlistVariants.empty() || !
m_board->GetVariantNames().empty() )
2389 auto findBoardVariantName =
2390 [&](
const wxString& aVariantName ) -> wxString
2392 for(
const wxString&
name :
m_board->GetVariantNames() )
2394 if(
name.CmpNoCase( aVariantName ) == 0 )
2398 return wxEmptyString;
2401 std::vector<wxString> updatedVariantNames;
2402 updatedVariantNames.reserve( netlistVariants.size() );
2404 for(
const wxString& variantName : netlistVariants )
2406 wxString actualName = findBoardVariantName( variantName );
2408 if( actualName.IsEmpty() )
2410 m_board->AddVariant( variantName );
2411 actualName = findBoardVariantName( variantName );
2413 if( !actualName.IsEmpty() )
2415 msg.Printf(
_(
"Added variant '%s'." ), actualName );
2420 if( actualName.IsEmpty() )
2425 wxString oldDescription =
m_board->GetVariantDescription( actualName );
2427 if( newDescription != oldDescription )
2429 m_board->SetVariantDescription( actualName, newDescription );
2430 msg.Printf(
_(
"Updated description for variant '%s'." ), actualName );
2434 updatedVariantNames.push_back( actualName );
2437 std::vector<wxString> variantsToRemove;
2439 for(
const wxString& existingName :
m_board->GetVariantNames() )
2443 for(
const wxString& variantName : netlistVariants )
2445 if( existingName.CmpNoCase( variantName ) == 0 )
2453 variantsToRemove.push_back( existingName );
2456 for(
const wxString& variantName : variantsToRemove )
2458 m_board->DeleteVariant( variantName );
2459 msg.Printf(
_(
"Removed variant '%s'." ), variantName );
2463 if( !updatedVariantNames.empty() )
2464 m_board->SetVariantNames( updatedVariantNames );
2483 if( !colorStr.IsEmpty() )
2497 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
2501 netSettings->ClearNetChainClasses();
2502 netSettings->ClearChainPatternAssignments();
2505 netSettings->SetNetChainClass(
chain, className );
2513 const wxString& chainName = net->GetNetChain();
2515 if( chainName.IsEmpty() )
2518 auto it = chainClasses.find( chainName );
2520 if( it == chainClasses.end() || it->second.IsEmpty() )
2523 if( netSettings->HasNetclass( it->second ) )
2524 netSettings->SetChainPatternAssignment( net->GetNetname(), it->second );
2529 m_board->SynchronizeNetsAndNetClasses(
true );
2533 m_board->SynchronizeNetsAndNetClasses(
true );
2538 PAD* pads[2] = {
nullptr,
nullptr };
2540 for(
size_t i = 0; i < sig.second.size() && i < 2; ++i )
2542 const wxString& ref = sig.second[i].first;
2543 const wxString&
pin = sig.second[i].second;
2549 PAD* candidate =
nullptr;
2550 PAD* best =
nullptr;
2551 int bestDist = std::numeric_limits<int>::max();
2560 if( !best || dist < bestDist || ( dist == bestDist && candidate->
m_Uuid < best->
m_Uuid ) )
2570 for(
int i = 0; i < 2; ++i )
2577 if( !termNet || termNet->
GetNetChain() != sig.first )
2582 if( net != termNet && net->
GetNetChain() == sig.first
2583 && net->GetTerminalPad( i ) )
2585 net->ClearTerminalPad( i );
2601 for(
const std::pair<const wxString, NETINFO_ITEM*>& addedNet :
m_addedNets )
2602 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
std::vector< PCB_GROUP * > m_addedGroups
bool testConnectivity(NETLIST &aNetlist, std::map< COMPONENT *, FOOTPRINT * > &aFootprintMap)
bool updateCopperZoneNets(NETLIST &aNetlist)
void cachePinFunction(PAD *aPad, const wxString &aPinFunction)
bool updateGroups(NETLIST &aNetlist)
BOARD_NETLIST_UPDATER(PCB_EDIT_FRAME *aFrame, BOARD *aBoard)
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 m_applyDesignBlockLayouts
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