59 m_commit( aFrame->GetToolManager() ),
86 const wxString previous = net->GetNetChain();
89 if( !previous.IsEmpty() &&
next.IsEmpty() && aReporter && !aDryRun )
93 _(
"Net chain assignment '%s' on net '%s' cleared by netlist "
95 previous, net->GetNetname() ),
101 net->SetNetChain(
next );
103 if( previous !=
next )
105 for(
int i = 0; i < 2; ++i )
106 net->ClearTerminalPad( i );
120 netSettings->ClearNetChainClasses();
121 netSettings->ClearNetChainNetClasses();
124 netSettings->SetNetChainClass(
chain, className );
127 netSettings->SetNetChainNetClass(
chain, netclass );
189 bestPosition.
x = pageSize.
x / 2;
190 bestPosition.
y = pageSize.
y / 2;
207 if( aFootprintId.
empty() )
209 msg.Printf(
_(
"Cannot add %s (no footprint assigned)." ),
218 if( footprint ==
nullptr )
220 msg.Printf(
_(
"Cannot add %s (footprint '%s' not found)." ),
229 m_board->GetComponentClassManager().GetNoneComponentClass() );
233 msg.Printf(
_(
"Add %s (footprint '%s')." ),
244 bool showRatsnest =
true;
247 showRatsnest =
m_settings->m_Display.m_ShowGlobalRatsnest;
249 pad->SetLocalRatsnestVisible( showRatsnest );
252 pad->SetNetCode( 0 );
268 msg.Printf(
_(
"Added %s (footprint '%s')." ),
281 wxString curClassName, newClassName;
285 curClassName = curClass->
GetName();
295 newClass =
m_board->GetComponentClassManager().GetEffectiveStaticComponentClass(
297 newClassName = newClass->
GetName();
300 if( curClassName == newClassName )
309 copy->SetParentGroup(
nullptr );
316 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
318 msg.Printf(
_(
"Change %s component class to '%s'." ),
322 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
324 msg.Printf(
_(
"Remove %s component class (currently '%s')." ),
330 msg.Printf(
_(
"Change %s component class from '%s' to '%s'." ),
338 wxASSERT_MSG( newClass !=
nullptr,
"Component class should not be nullptr" );
342 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
344 msg.Printf(
_(
"Changed %s component class to '%s'." ),
348 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
350 msg.Printf(
_(
"Removed %s component class (was '%s')." ),
356 msg.Printf(
_(
"Changed %s component class from '%s' to '%s'." ),
379 msg.Printf(
_(
"Cannot update %s (no footprint assigned)." ),
388 if( newFootprint ==
nullptr )
390 msg.Printf(
_(
"Cannot update %s (footprint '%s' not found)." ),
402 msg.Printf(
_(
"Cannot change %s footprint from '%s' to '%s' (footprint is locked)."),
413 msg.Printf(
_(
"Change %s footprint from '%s' to '%s'."),
427 msg.Printf(
_(
"Could not change %s footprint from '%s' to '%s' (footprint is locked)."),
442 m_frame->GetPcbNewSettings()->m_FlipDirection,
true );
444 msg.Printf(
_(
"Changed %s footprint from '%s' to '%s'."),
470 firstAssociatedVariant = &
test;
479 if( !
m_commit.GetStatus( aFootprint ) )
482 copy->SetParentGroup(
nullptr );
485 bool changed =
false;
492 msg.Printf(
_(
"Change %s reference designator to %s." ),
498 msg.Printf(
_(
"Changed %s reference designator to %s." ),
512 if( firstAssociatedVariant !=
nullptr
522 msg.Printf(
_(
"Change %s value from %s to %s." ),
529 msg.Printf(
_(
"Changed %s value from %s to %s." ),
544 if( !aNetlistComponent->
GetKIIDs().empty() )
545 new_path.push_back( aNetlistComponent->
GetKIIDs().front() );
547 if( aFootprint->
GetPath() != new_path )
551 msg.Printf(
_(
"Update %s symbol association from %s to %s." ),
558 msg.Printf(
_(
"Updated %s symbol association from %s to %s." ),
564 aFootprint->
SetPath( new_path );
570 nlohmann::ordered_map<wxString, wxString> fpFieldsAsMap;
575 if( field->IsReference() || field->IsValue() || field->IsComponentClass() )
580 fpFieldsAsMap[field->GetName()] = field->GetText();
583 nlohmann::ordered_map<wxString, wxString> compFields = aNetlistComponent->
GetFields();
585 if( firstAssociatedVariant !=
nullptr )
587 for(
const auto& [
name, value] : firstAssociatedVariant->
m_fields )
588 compFields[
name] = value;
597 compFields.erase( wxT(
"Component Class" ) );
602 bool remove_only =
true;
604 for(
const auto& [
name, value] : compFields )
606 if( fpFieldsAsMap.count(
name ) == 0 || fpFieldsAsMap[
name] != value )
614 for(
const auto& [
name, value] : fpFieldsAsMap )
616 if( compFields.count(
name ) == 0 )
629 msg.Printf(
_(
"Update %s fields." ), aFootprint->
GetReference() );
636 if( field->IsMandatory() )
639 if( compFields.count( field->GetName() ) == 0 )
643 msg.Printf(
_(
"Remove %s footprint fields not in symbol." ), aFootprint->
GetReference() );
655 msg.Printf(
_(
"Updated %s fields." ), aFootprint->
GetReference() );
661 for(
auto& [
name, value] : compFields )
670 aFootprint->
Add( newField );
691 std::vector<PCB_FIELD*> fieldList;
692 aFootprint->
GetFields( fieldList,
false );
696 if( field->IsMandatory() )
699 if( compFields.count( field->GetName() ) == 0 )
704 msg.Printf(
_(
"Removed %s footprint fields not in symbol." ), aFootprint->
GetReference() );
708 aFootprint->
Remove( field );
711 m_frame->GetCanvas()->GetView()->Remove( field );
726 if( !humanSheetPath.empty() )
727 sheetname = humanSheetPath;
728 else if( aNetlistComponent->
GetProperties().count( wxT(
"Sheetname" ) ) > 0 )
729 sheetname = aNetlistComponent->
GetProperties().at( wxT(
"Sheetname" ) );
731 if( aNetlistComponent->
GetProperties().count( wxT(
"Sheetfile" ) ) > 0 )
732 sheetfile = aNetlistComponent->
GetProperties().at( wxT(
"Sheetfile" ) );
734 if( aNetlistComponent->
GetProperties().count( wxT(
"ki_fp_filters" ) ) > 0 )
735 fpFilters = aNetlistComponent->
GetProperties().at( wxT(
"ki_fp_filters" ) );
741 msg.Printf(
_(
"Update %s sheetname to '%s'." ),
747 msg.Printf(
_(
"Updated %s sheetname to '%s'." ),
762 msg.Printf(
_(
"Update %s sheetfile to '%s'." ),
768 msg.Printf(
_(
"Updated %s sheetfile to '%s'." ),
783 msg.Printf(
_(
"Update %s footprint filters to '%s'." ),
789 msg.Printf(
_(
"Updated %s footprint filters to '%s'." ),
800 bool netlistExcludeFromBOM = aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_bom" ) ) > 0;
809 if( netlistExcludeFromBOM )
810 msg.Printf(
_(
"Add %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
812 msg.Printf(
_(
"Remove %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
818 if( netlistExcludeFromBOM )
821 msg.Printf(
_(
"Added %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
826 msg.Printf(
_(
"Removed %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
836 bool netlistExcludeFromSim = aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_sim" ) ) > 0;
846 if( netlistExcludeFromSim )
847 msg.Printf(
_(
"Add %s 'exclude from simulation' attribute." ), aFootprint->
GetReference() );
849 msg.Printf(
_(
"Remove %s 'exclude from simulation' attribute." ), aFootprint->
GetReference() );
855 if( netlistExcludeFromSim )
858 msg.Printf(
_(
"Added %s 'exclude from simulation' attribute." ), aFootprint->
GetReference() );
863 msg.Printf(
_(
"Removed %s 'exclude from simulation' attribute." ), aFootprint->
GetReference() );
873 bool netlistDNP = aNetlistComponent->
GetProperties().count( wxT(
"dnp" ) ) > 0;
875 if( firstAssociatedVariant !=
nullptr && firstAssociatedVariant->
m_hasDnp )
876 netlistDNP = firstAssociatedVariant->
m_dnp;
883 msg.Printf(
_(
"Add %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
885 msg.Printf(
_(
"Remove %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
894 msg.Printf(
_(
"Added %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
899 msg.Printf(
_(
"Removed %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
909 bool netlistExcludeFromPosFiles = aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_pos_files" ) ) > 0;
919 if( netlistExcludeFromPosFiles )
921 msg.Printf(
_(
"Add %s 'exclude from position files' fabrication attribute." ),
926 msg.Printf(
_(
"Remove %s 'exclude from position files' fabrication attribute." ),
934 if( netlistExcludeFromPosFiles )
937 msg.Printf(
_(
"Added %s 'exclude from position files' fabrication attribute." ),
943 msg.Printf(
_(
"Removed %s 'exclude from position files' fabrication attribute." ),
966 msg.Printf(
_(
"Added %s 'duplicate pad numbers are jumpers' attribute." ),
971 msg.Printf(
_(
"Removed %s 'duplicate pad numbers are jumpers' attribute." ),
979 msg.Printf(
_(
"Add %s 'duplicate pad numbers are jumpers' attribute." ),
984 msg.Printf(
_(
"Remove %s 'duplicate pad numbers are jumpers' attribute." ),
998 msg.Printf(
_(
"Updated %s jumper pad groups" ), aFootprint->
GetReference() );
1002 msg.Printf(
_(
"Update %s jumper pad groups" ), aFootprint->
GetReference() );
1008 if( changed &&
copy )
1024 KIID existingGroupKIID = existingGroup ? existingGroup->
m_Uuid : 0;
1027 if( newGroupKIID == existingGroupKIID )
1038 copy->SetParentGroup(
nullptr );
1041 bool changed =
false;
1048 auto it = std::find_if(
m_board->Groups().begin(),
m_board->Groups().end(),
1050 return group->m_Uuid == newGroupKIID;
1054 if( it !=
m_board->Groups().end() )
1058 if( existingGroupKIID != 0 )
1062 msg.Printf(
_(
"Remove %s from group '%s'." ),
1068 msg.Printf(
_(
"Removed %s from group '%s'." ),
1076 if( existingGroup->
GetItems().size() < 2 )
1087 if( newGroupKIID != 0 )
1091 msg.Printf(
_(
"Add %s to group '%s'." ),
1097 msg.Printf(
_(
"Added %s to group '%s'." ),
1103 if( newGroup ==
nullptr )
1106 newGroup->
SetUuid( newGroupKIID );
1120 newGroup->
AddItem( aPcbFootprint );
1126 if( changed &&
copy )
1145 copy->SetParentGroup(
nullptr );
1148 bool changed =
false;
1151 std::deque<PAD*> pads = aFootprint->
Pads();
1152 std::set<wxString> padNetnames;
1154 std::sort( pads.begin(), pads.end(),
1157 return a->m_Uuid < b->m_Uuid;
1164 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1165 wxT(
"Processing pad %s of component %s" ),
1169 wxString pinFunction;
1174 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1175 wxT(
" Found valid net: %s" ),
1182 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1183 wxT(
" No net found for pad %s" ),
1189 if(
pad->GetPinFunction() != pinFunction )
1192 pad->SetPinFunction( pinFunction );
1195 if(
pad->GetPinType() != pinType )
1198 pad->SetPinType( pinType );
1207 if( !net.
IsValid() || !
pad->IsOnCopperLayer() )
1209 if( !
pad->GetNetname().IsEmpty() )
1213 msg.Printf(
_(
"Disconnect %s pin %s." ),
1219 msg.Printf(
_(
"Disconnected %s pin %s." ),
1226 else if(
pad->IsOnCopperLayer() && !
pad->GetNumber().IsEmpty() )
1229 msg.Printf(
_(
"No net found for component %s pad %s (no pin %s in symbol)." ),
1247 if(
pad->GetNetname().IsEmpty() && !
pad->GetPinFunction().IsEmpty() )
1250 pad->SetPinFunction( wxEmptyString );
1262 if(
pad->IsNoConnectPad() )
1264 netName = wxString::Format( wxS(
"%s" ), net.
GetNetName() );
1266 for(
int jj = 1; !padNetnames.insert( netName ).second
1270 netName = wxString::Format( wxS(
"%s_%d" ), net.
GetNetName(), jj );
1279 if(
pad->GetNetname() != netName )
1282 if( netinfo ==
nullptr )
1289 if( netinfo ==
nullptr )
1301 msg.Printf(
_(
"Add net %s." ),
1306 if( !
pad->GetNetname().IsEmpty() )
1312 msg.Printf(
_(
"Reconnect %s pin %s from %s to %s."),
1320 msg.Printf(
_(
"Reconnected %s pin %s from %s to %s."),
1331 msg.Printf(
_(
"Connect %s pin %s to %s."),
1338 msg.Printf(
_(
"Connected %s pin %s to %s."),
1350 pad->SetNet( netinfo );
1360 if( changed &&
copy )
1372 std::vector<FOOTPRINT::FP_UNIT_INFO> newUnits;
1375 newUnits.push_back( { u.m_unitName, u.m_pins } );
1377 const std::vector<FOOTPRINT::FP_UNIT_INFO>& curUnits = aFootprint->
GetUnitInfo();
1379 if( std::ranges::equal( curUnits, newUnits,
1380 [](
const auto& a,
const auto& b )
1382 return a.m_unitName == b.m_unitName && a.m_pins == b.m_pins;
1390 msg.Printf(
_(
"Update %s unit metadata." ), aFootprint->
GetReference() );
1398 if( !
m_commit.GetStatus( aFootprint ) )
1401 copy->SetParentGroup(
nullptr );
1406 msg.Printf(
_(
"Updated %s unit metadata." ), aFootprint->
GetReference() );
1421 return aBoardFpid == aSchematicFpid;
1426 const std::vector<FOOTPRINT*>& aFootprints,
1427 const LIB_ID& aBaseFpid )
1432 if( aBaseFpid.
empty() )
1444 std::vector<VARIANT_INFO> variantInfo;
1445 variantInfo.reserve( variants.size() );
1447 for(
const auto& [variantName, variant] : variants )
1449 LIB_ID variantFPID = aBaseFpid;
1451 auto fieldIt = variant.m_fields.find( FOOTPRINT_FIELD_NAME );
1453 if( fieldIt != variant.m_fields.end() && !fieldIt->second.IsEmpty() )
1457 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
1459 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
1468 variantFPID = parsedId;
1472 variantInfo.push_back( { variantName, &variant, variantFPID } );
1475 for(
FOOTPRINT* footprint : aFootprints )
1485 copy->SetParentGroup(
nullptr );
1488 bool changed =
false;
1490 auto printAttributeMessage =
1491 [&](
bool add,
const wxString& attrName,
const wxString& variantName )
1495 if( aFootprints.size() > 1 )
1497 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s (footprint %s)." )
1498 :
_(
"Remove %s '%s' attribute from variant %s (footprint %s)." ),
1499 footprint->GetReference(),
1502 footprint->GetFPIDAsString() );
1506 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s." )
1507 :
_(
"Remove %s '%s' attribute from variant %s." ),
1508 footprint->GetReference(),
1515 if( aFootprints.size() > 1 )
1517 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s (footprint %s)." )
1518 :
_(
"Removed %s '%s' attribute from variant %s (footprint %s)." ),
1519 footprint->GetReference(),
1522 footprint->GetFPIDAsString() );
1526 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s." )
1527 :
_(
"Removed %s '%s' attribute from variant %s." ),
1528 footprint->GetReference(),
1535 bool isBaseFootprint =
fpidsEquivalent( footprint->GetFPID(), aBaseFpid );
1540 const bool baseFootprintDnp = footprint->IsDNP();
1541 bool effectiveFootprintDnp = baseFootprintDnp;
1548 if( !isBaseFootprint && !effectiveFootprintDnp )
1550 msg.Printf(
m_isDryRun ?
_(
"Add %s 'Do not place' fabrication attribute." )
1551 :
_(
"Added %s 'Do not place' fabrication attribute." ),
1552 footprint->GetReference() );
1557 footprint->SetDNP(
true );
1561 effectiveFootprintDnp =
true;
1565 std::set<wxString> excessVariants;
1567 for(
const auto& [variantName,
_] : footprint->GetVariants() )
1568 excessVariants.insert( variantName );
1570 for(
const VARIANT_INFO&
info : variantInfo )
1582 if( !isAssociatedFootprint && aFootprints.size() <= 1 )
1585 excessVariants.erase(
info.name );
1586 bool targetDnp = variant.
m_hasDnp ? variant.
m_dnp : baseFootprintDnp;
1587 bool currentDnp = currentVariant ? currentVariant->
GetDNP() : effectiveFootprintDnp;
1593 if( !isAssociatedFootprint )
1596 if( currentDnp != targetDnp )
1598 printAttributeMessage( targetDnp,
_(
"Do not place" ),
info.name );
1603 fpVariant->SetDNP( targetDnp );
1611 : footprint->IsExcludedFromBOM();
1613 : footprint->IsExcludedFromBOM();
1615 if( currentExcludedFromBOM != targetExcludedFromBOM )
1617 printAttributeMessage( targetExcludedFromBOM,
_(
"exclude from BOM" ),
info.name );
1622 fpVariant->SetExcludedFromBOM( targetExcludedFromBOM );
1630 : footprint->IsExcludedFromSim();
1632 : footprint->IsExcludedFromSim();
1634 if( currentExcludedFromSim != targetExcludedFromSim )
1636 printAttributeMessage( targetExcludedFromSim,
_(
"exclude from simulation" ),
info.name );
1641 fpVariant->SetExcludedFromSim( targetExcludedFromSim );
1649 : footprint->IsExcludedFromPosFiles();
1651 : footprint->IsExcludedFromPosFiles();
1653 if( currentExcludedFromPosFiles != targetExcludedFromPosFiles )
1655 printAttributeMessage( targetExcludedFromPosFiles,
_(
"exclude from position files" ),
info.name );
1660 fpVariant->SetExcludedFromPosFiles( targetExcludedFromPosFiles );
1669 std::map<wxString, wxString> fpFieldsAsMap;
1671 for(
PCB_FIELD* field : footprint->GetFields() )
1672 fpFieldsAsMap[field->GetName()] = field->GetText();
1674 for(
const auto& [fieldName, fieldValue] : variant.
m_fields )
1676 if( fieldName.CmpNoCase( FOOTPRINT_FIELD_NAME ) == 0 )
1679 wxString currentValue;
1681 if( currentVariant && currentVariant->
HasFieldValue( fieldName ) )
1684 currentValue = fpFieldsAsMap[fieldName];
1686 fpFieldsAsMap.erase( fieldName );
1688 if( currentValue != fieldValue )
1692 if( aFootprints.size() > 1 )
1694 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s (footprint %s)." ),
1695 footprint->GetReference(),
1699 footprint->GetFPIDAsString() );
1703 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s." ),
1704 footprint->GetReference(),
1712 if( aFootprints.size() > 1 )
1714 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s (footprint %s)." ),
1715 footprint->GetReference(),
1719 footprint->GetFPIDAsString() );
1723 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s." ),
1724 footprint->GetReference(),
1731 fpVariant->SetFieldValue( fieldName, fieldValue );
1741 for(
const auto& [fieldName, fieldValue] : fpFieldsAsMap )
1743 if( fieldName.CmpNoCase( FOOTPRINT_FIELD_NAME ) == 0 )
1746 if( currentVariant && currentVariant->
HasFieldValue( fieldName ) )
1750 if( aFootprints.size() > 1 )
1752 msg.Printf(
_(
"Remove %s field '%s' override on variant %s (footprint %s)." ),
1753 footprint->GetReference(),
1756 footprint->GetFPIDAsString() );
1760 msg.Printf(
_(
"Remove %s field '%s' override on variant %s." ),
1761 footprint->GetReference(),
1768 if( aFootprints.size() > 1 )
1770 msg.Printf(
_(
"Removed %s field '%s' override on variant %s (footprint %s)." ),
1771 footprint->GetReference(),
1774 footprint->GetFPIDAsString() );
1778 msg.Printf(
_(
"Removed %s field '%s' override on variant %s." ),
1779 footprint->GetReference(),
1791 for(
const wxString& excess : excessVariants )
1795 msg.Printf(
_(
"Remove variant %s:%s no longer associated with footprint %s." ),
1796 footprint->GetReference(),
1798 footprint->GetFPIDAsString() );
1802 msg.Printf(
_(
"Removed variant %s:%s no longer associated with footprint %s." ),
1803 footprint->GetReference(),
1805 footprint->GetFPIDAsString() );
1807 footprint->DeleteVariant( excess );
1826 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1837 std::set<wxString> netlistNetnames;
1839 for(
int ii = 0; ii < (int) aNetlist.
GetCount(); ii++ )
1843 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1855 if( netlistNetnames.count(
via->GetNetname() ) == 0 )
1857 wxString updatedNetname = wxEmptyString;
1866 if( !updatedNetname.IsEmpty() )
1870 wxString originalNetname =
via->GetNetname();
1872 msg.Printf(
_(
"Reconnect via from %s to %s." ),
1887 wxString originalNetname =
via->GetNetname();
1890 via->SetNet( netinfo );
1892 msg.Printf(
_(
"Reconnected via from %s to %s." ),
1902 msg.Printf(
_(
"Via connected to unknown net (%s)." ),
1914 auto isInNetlist = [&](
const wxString& aNetName ) ->
bool
1916 if( netlistNetnames.count( aNetName ) )
1921 for(
const wxString& netName : netlistNetnames )
1923 if( aNetName.StartsWith( netName ) )
1933 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1936 if( !isInNetlist( zone->GetNetname() ) )
1941 wxString updatedNetname = wxEmptyString;
1954 if( updatedNetname.IsEmpty() &&
m_oldToNewNets.count( zone->GetNetname() ) )
1959 if( !updatedNetname.IsEmpty() )
1963 wxString originalNetname = zone->GetNetname();
1965 if( !zone->GetZoneName().IsEmpty() )
1967 msg.Printf(
_(
"Reconnect copper zone '%s' from %s to %s." ),
1968 zone->GetZoneName(),
1974 msg.Printf(
_(
"Reconnect copper zone from %s to %s." ),
1990 wxString originalNetname = zone->GetNetname();
1993 zone->SetNet( netinfo );
1995 if( !zone->GetZoneName().IsEmpty() )
1997 msg.Printf(
_(
"Reconnected copper zone '%s' from %s to %s." ),
2004 msg.Printf(
_(
"Reconnected copper zone from %s to %s." ),
2015 if( !zone->GetZoneName().IsEmpty() )
2017 msg.Printf(
_(
"Copper zone '%s' has no pads connected." ),
2022 wxString layerNames = zone->LayerMaskDescribe();
2027 if(
m_settings->m_Display.m_DisplayInvertXAxis )
2030 if(
m_settings->m_Display.m_DisplayInvertYAxis )
2034 msg.Printf(
_(
"Copper zone on %s at (%s, %s) has no pads connected to net \"%s\"." ),
2044 zone->GetNetname() );
2068 if( netlistGroup ==
nullptr )
2071 if( netlistGroup->
name != pcbGroup->GetName() )
2075 msg.Printf(
_(
"Change group name from '%s' to '%s'." ),
2081 msg.Printf(
_(
"Changed group name from '%s' to '%s'." ),
2085 pcbGroup->SetName( netlistGroup->
name );
2091 if( netlistGroup->
libId != pcbGroup->GetDesignBlockLibId() )
2095 msg.Printf(
_(
"Change group library link from '%s' to '%s'." ),
2096 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
2101 msg.Printf(
_(
"Changed group library link from '%s' to '%s'." ),
2102 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
2105 pcbGroup->SetDesignBlockLibId( netlistGroup->
libId );
2115 if( member.empty() )
2118 KIID memberGroupUuid =
2125 if( candidate->m_Uuid == memberGroupUuid )
2127 childGroup = candidate;
2132 if( !childGroup || childGroup == pcbGroup || childGroup->
GetParentGroup() == pcbGroup )
2139 msg.Printf(
_(
"Add group '%s' to group '%s'." ),
EscapeHTML( childGroup->
GetName() ),
2144 msg.Printf(
_(
"Added group '%s' to group '%s'." ),
EscapeHTML( childGroup->
GetName() ),
2148 pcbGroup->AddItem( childGroup );
2160 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
2168 for(
int i = 0; i < (int) aNetlist.
GetCount(); i++ )
2171 FOOTPRINT* footprint = aFootprintMap[component];
2177 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
2181 if( padNumber.IsEmpty() )
2184 msg.Printf(
_(
"Symbol %s has pins with no number. These pins can not be matched "
2194 msg.Printf(
_(
"%s pad %s not found in %s." ),
2210 FOOTPRINT* lastPreexistingFootprint =
nullptr;
2213 std::unordered_set<wxString> sheetPaths;
2214 std::unordered_set<FOOTPRINT*> usedFootprints;
2220 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
2222 if( !
m_board->Footprints().empty() )
2223 lastPreexistingFootprint =
m_board->Footprints().back();
2233 net->SetIsCurrent( net->GetNetCode() == 0 );
2235 m_board->GetComponentClassManager().InitNetlistUpdate();
2239 for(
unsigned ii = 0; ii < aNetlist.
GetCount(); ii++ )
2243 for(
unsigned jj = 0; jj <
comp->GetNetCount(); jj++ )
2250 for(
unsigned i = 0; i < aNetlist.
GetCount(); i++ )
2254 if( component->
GetProperties().count( wxT(
"exclude_from_board" ) ) )
2257 msg.Printf(
_(
"Processing symbol '%s:%s'." ),
2263 const bool hasBaseFpid = !baseFpid.
empty();
2267 msg.Printf(
_(
"Warning: %s footprint '%s' is missing a library name. "
2268 "Use the full 'Library:Footprint' format to avoid repeated update "
2276 std::vector<FOOTPRINT*> matchingFootprints;
2287 base.push_back( uuid );
2289 if( footprint->GetPath() == base )
2298 match = footprint->GetReference().CmpNoCase( component->
GetReference() ) == 0;
2303 if( footprint->IsBoardOnly() )
2305 msg.Printf(
_(
"Found a footprint matching %s, but the footprint's 'Not in schematic' "
2306 "flag indicates there should be no matching symbol." ),
2313 matchingFootprints.push_back( footprint );
2317 if( footprint == lastPreexistingFootprint )
2324 std::vector<LIB_ID> expectedFpids;
2325 std::unordered_set<wxString> expectedFpidKeys;
2327 auto addExpectedFpid =
2328 [&](
const LIB_ID& aFpid )
2333 wxString key = aFpid.Format();
2335 if( expectedFpidKeys.insert( key ).second )
2336 expectedFpids.push_back( aFpid );
2339 addExpectedFpid( baseFpid );
2343 for(
const auto& [variantName, variant] : component->
GetVariants() )
2345 auto fieldIt = variant.m_fields.find( footprintFieldName );
2347 if( fieldIt == variant.m_fields.end() || fieldIt->second.IsEmpty() )
2352 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
2354 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
2363 addExpectedFpid( parsedId );
2366 auto isExpectedFpid =
2367 [&](
const LIB_ID& aFpid ) ->
bool
2372 if( expectedFpidKeys.count( aFpid.Format() ) > 0 )
2384 auto takeMatchingFootprint =
2387 for(
FOOTPRINT* footprint : matchingFootprints )
2389 if( usedFootprints.count( footprint ) )
2399 std::vector<FOOTPRINT*> componentFootprints;
2400 componentFootprints.reserve( expectedFpids.size() );
2404 baseFootprint = takeMatchingFootprint( baseFpid );
2405 else if( !matchingFootprints.empty() )
2406 baseFootprint = matchingFootprints.front();
2412 for(
FOOTPRINT* footprint : matchingFootprints )
2414 if( usedFootprints.count( footprint ) )
2417 if( isExpectedFpid( footprint->GetFPID() ) )
2420 replaceCandidate = footprint;
2424 if( replaceCandidate )
2429 baseFootprint = replaced;
2431 baseFootprint = replaceCandidate;
2437 for(
FOOTPRINT* footprint : matchingFootprints )
2439 if( usedFootprints.count( footprint ) )
2442 if( isExpectedFpid( footprint->GetFPID() ) )
2445 baseFootprint = footprint;
2450 if( !baseFootprint && ( hasBaseFpid || expectedFpids.empty() ) )
2455 componentFootprints.push_back( baseFootprint );
2456 usedFootprints.insert( baseFootprint );
2457 footprintMap[ component ] = baseFootprint;
2460 for(
const LIB_ID& fpid : expectedFpids )
2468 FOOTPRINT* footprint = takeMatchingFootprint( fpid );
2475 componentFootprints.push_back( footprint );
2476 usedFootprints.insert( footprint );
2480 for(
FOOTPRINT* footprint : componentFootprints )
2491 sheetPaths.insert( footprint->GetSheetname() );
2494 if( !componentFootprints.empty() )
2506 bool matched =
false;
2512 bool isStaleVariantFootprint =
false;
2514 if( usedFootprints.count( footprint ) )
2525 if( component && component->
GetProperties().count( wxT(
"exclude_from_board" ) ) == 0 )
2533 isStaleVariantFootprint =
true;
2544 if( isStaleVariantFootprint )
2547 if( doDelete && !matched && footprint->IsLocked() && !
m_overrideLocks )
2551 msg.Printf(
_(
"Cannot remove unused footprint %s (footprint is locked)." ),
2552 footprint->GetReference() );
2556 msg.Printf(
_(
"Could not remove unused footprint %s (footprint is locked)." ),
2557 footprint->GetReference() );
2565 if( doDelete && !matched )
2569 msg.Printf(
_(
"Remove unused footprint %s." ),
2570 footprint->GetReference() );
2575 msg.Printf(
_(
"Removed unused footprint %s." ),
2576 footprint->GetReference() );
2586 for(
PAD*
pad : footprint->Pads() )
2589 pad->GetNet()->SetIsCurrent(
true );
2596 m_board->ClearNetChainColors();
2599 m_board->GetComponentClassManager().FinishNetlistUpdate();
2600 m_board->SynchronizeComponentClasses( sheetPaths );
2607 if( !net->IsCurrent() )
2609 msg.Printf(
_(
"Removed unused net %s." ),
EscapeHTML( net->GetNetname() ) );
2617 const std::vector<wxString>& netlistVariants = aNetlist.
GetVariantNames();
2619 if( !netlistVariants.empty() || !
m_board->GetVariantNames().empty() )
2623 auto findBoardVariantName =
2624 [&](
const wxString& aVariantName ) -> wxString
2626 for(
const wxString&
name :
m_board->GetVariantNames() )
2628 if(
name.CmpNoCase( aVariantName ) == 0 )
2632 return wxEmptyString;
2635 std::vector<wxString> updatedVariantNames;
2636 updatedVariantNames.reserve( netlistVariants.size() );
2638 for(
const wxString& variantName : netlistVariants )
2640 wxString actualName = findBoardVariantName( variantName );
2642 if( actualName.IsEmpty() )
2644 m_board->AddVariant( variantName );
2645 actualName = findBoardVariantName( variantName );
2647 if( !actualName.IsEmpty() )
2649 msg.Printf(
_(
"Added variant '%s'." ), actualName );
2654 if( actualName.IsEmpty() )
2659 wxString oldDescription =
m_board->GetVariantDescription( actualName );
2661 if( newDescription != oldDescription )
2663 m_board->SetVariantDescription( actualName, newDescription );
2664 msg.Printf(
_(
"Updated description for variant '%s'." ), actualName );
2668 updatedVariantNames.push_back( actualName );
2671 std::vector<wxString> variantsToRemove;
2673 for(
const wxString& existingName :
m_board->GetVariantNames() )
2677 for(
const wxString& variantName : netlistVariants )
2679 if( existingName.CmpNoCase( variantName ) == 0 )
2687 variantsToRemove.push_back( existingName );
2690 for(
const wxString& variantName : variantsToRemove )
2692 m_board->DeleteVariant( variantName );
2693 msg.Printf(
_(
"Removed variant '%s'." ), variantName );
2697 if( !updatedVariantNames.empty() )
2698 m_board->SetVariantNames( updatedVariantNames );
2717 if( !colorStr.IsEmpty() )
2730 m_board->SynchronizeNetsAndNetClasses(
true );
2734 PAD* pads[2] = {
nullptr,
nullptr };
2736 for(
size_t i = 0; i < terminalPins.size() && i < 2; ++i )
2738 const wxString& ref = terminalPins[i].first;
2739 const wxString&
pin = terminalPins[i].second;
2745 PAD* candidate =
nullptr;
2746 PAD* best =
nullptr;
2747 int bestDist = std::numeric_limits<int>::max();
2756 if( !best || dist < bestDist || ( dist == bestDist && candidate->
m_Uuid < best->
m_Uuid ) )
2766 for(
int i = 0; i < 2; ++i )
2778 if( net != termNet && net->
GetNetChain() ==
chain && net->GetTerminalPad( i ) )
2779 net->ClearTerminalPad( i );
2794 for(
const std::pair<const wxString, NETINFO_ITEM*>& addedNet :
m_addedNets )
2795 delete addedNet.second;
constexpr EDA_IU_SCALE pcbIUScale
wxString GetNetname() const
NETINFO_ITEM * GetNet() const
Return NETINFO_ITEM object for a given item.
std::shared_ptr< NET_SETTINGS > m_NetSettings
void SetUuid(const KIID &aUuid)
bool IsLocked() const override
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
std::map< PAD *, wxString > m_padNets
PCBNEW_SETTINGS * m_settings
bool m_deleteUnusedFootprints
void cacheNetname(PAD *aPad, const wxString &aNetname)
bool UpdateNetlist(NETLIST &aNetlist)
Update the board's components according to the new netlist.
wxString getNetname(PAD *aPad)
wxString getPinFunction(PAD *aPad)
std::vector< FOOTPRINT * > m_addedFootprints
bool updateFootprintParameters(FOOTPRINT *aFootprint, COMPONENT *aNetlistComponent)
std::map< wxString, wxString > m_oldToNewNets
static void ApplyChainAssignments(BOARD *aBoard, const NETLIST &aNetlist, REPORTER *aReporter, bool aDryRun)
Apply the netlist's chain assignments to every NETINFO_ITEM on the board.
static void ApplyChainNetclasses(BOARD *aBoard, const NETLIST &aNetlist)
Mirror the netlist's chain-to-class and chain-to-netclass maps into the project's NET_SETTINGS.
bool updateFootprintGroup(FOOTPRINT *aPcbFootprint, COMPONENT *aNetlistComponent)
static bool fpidsEquivalent(const LIB_ID &aBoardFpid, const LIB_ID &aSchematicFpid)
Compare a board footprint ID against a schematic-derived footprint ID, ignoring the library nickname ...
std::map< wxString, NETINFO_ITEM * > m_addedNets
std::vector< PCB_GROUP * > m_addedGroups
bool testConnectivity(NETLIST &aNetlist, std::map< COMPONENT *, FOOTPRINT * > &aFootprintMap)
bool updateCopperZoneNets(NETLIST &aNetlist)
void cachePinFunction(PAD *aPad, const wxString &aPinFunction)
bool updateGroups(NETLIST &aNetlist)
BOARD_NETLIST_UPDATER(PCB_EDIT_FRAME *aFrame, BOARD *aBoard)
Construct an updater for interactive use from the board editor.
bool updateComponentClass(FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
bool updateComponentPadConnections(FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
VECTOR2I estimateFootprintInsertionPosition()
std::map< PAD *, wxString > m_padPinFunctions
void applyComponentVariants(COMPONENT *aComponent, const std::vector< FOOTPRINT * > &aFootprints, const LIB_ID &aBaseFpid)
std::map< ZONE *, std::vector< PAD * > > m_zoneConnectionsCache
FOOTPRINT * replaceFootprint(NETLIST &aNetlist, FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
void cacheCopperZoneConnections()
bool updateComponentUnits(FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
FOOTPRINT * addNewFootprint(COMPONENT *aComponent)
std::set< wxString > m_schematicNetNames
Information pertinent to a Pcbnew printed circuit board.
const NETINFO_LIST & GetNetInfo() const
BOARD_DESIGN_SETTINGS & GetDesignSettings()
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()
JUMPER_GROUP_SET & 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
static KIID FromName(const std::string &aName)
Return a KIID derived from a name, the same name always gives the same KIID.
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
wxString GetUniStringLibId() const
const UTF8 & GetLibItemName() const
Handle the data for a net.
const wxString & GetNetChain() const
void SetTerminal(int aIndex, PAD *aPad)
Set the terminal-pad pointer and the persisted UUID at aIndex from a single pad, keeping the two view...
void SetIsCurrent(bool isCurrent)
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
const std::map< wxString, std::vector< std::pair< wxString, wxString > > > & GetNetChainTerminalPins() const
const std::vector< wxString > & GetVariantNames() const
unsigned GetCount() const
COMPONENT * GetComponentByPath(const KIID_PATH &aPath)
Return a COMPONENT by aPath.
COMPONENT * GetComponentByReference(const wxString &aReference)
Return a COMPONENT by aReference.
const std::map< wxString, wxString > & GetNetChainNetClasses() const
const std::map< wxString, wxString > & GetSignalChainClasses() const
NETLIST_GROUP * GetGroupByUuid(const KIID &aUuid)
Return a NETLIST_GROUP by aUuid.
const std::map< wxString, wxString > & GetNetChainColors() const
COMPONENT * GetComponent(unsigned aIndex)
Return the COMPONENT at aIndex.
wxString GetNetChainFor(const wxString &aNet) const
wxString GetVariantDescription(const wxString &aVariantName) const
A singleton reporter that reports to nowhere.
const wxString & GetPinFunction() const
VECTOR2I GetPosition() const override
The main frame for Pcbnew.
void SetName(const wxString &aName)
A set of BOARD_ITEMs (i.e., without duplicates).
EDA_ITEM * AsEdaItem() override
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &aSettings, bool aCheckSide) override
void SetPosition(const VECTOR2I &aPos) override
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Handle a list of polygons defining a copper zone.
KICOMMON_API wxString MessageTextFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A helper to convert the double length aValue to a string in inches, millimeters, or unscaled units.
Class to handle a set of BOARD_ITEMs.
FOOTPRINT * LoadFootprintFromProject(BOARD *aBoard, const LIB_ID &aFootprintId, bool aKeepUuid)
Load a footprint from the project library table and apply board default settings.
T * GetAppSettings(const char *aFilename)
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
wxString UnescapeString(const wxString &aSource)
bool m_excludedFromPosFiles
bool m_hasExcludedFromBOM
bool m_hasExcludedFromSim
bool m_hasExcludedFromPosFiles
nlohmann::ordered_map< wxString, wxString > m_fields
std::vector< KIID > members
wxString GetDefaultFieldName(FIELD_T aFieldId, TRANSLATION aTranslation)
Return a default symbol field name for a mandatory field type.
@ 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".
VECTOR3I expected(15, 30, 45)
static std::string netlistValue(const SEXPR::SEXPR &aNode, const std::string &aHead)
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