58 m_commit( aFrame->GetToolManager() ),
85 const wxString previous = net->GetNetChain();
88 if( !previous.IsEmpty() &&
next.IsEmpty() && aReporter && !aDryRun )
92 _(
"Net chain assignment '%s' on net '%s' cleared by netlist "
94 previous, net->GetNetname() ),
100 net->SetNetChain(
next );
102 if( previous !=
next )
104 for(
int i = 0; i < 2; ++i )
105 net->ClearTerminalPad( i );
119 netSettings->ClearNetChainClasses();
120 netSettings->ClearNetChainNetClasses();
123 netSettings->SetNetChainClass(
chain, className );
126 netSettings->SetNetChainNetClass(
chain, netclass );
188 bestPosition.
x = pageSize.
x / 2;
189 bestPosition.
y = pageSize.
y / 2;
206 if( aFootprintId.
empty() )
208 msg.Printf(
_(
"Cannot add %s (no footprint assigned)." ),
217 if( footprint ==
nullptr )
219 msg.Printf(
_(
"Cannot add %s (footprint '%s' not found)." ),
228 m_board->GetComponentClassManager().GetNoneComponentClass() );
232 msg.Printf(
_(
"Add %s (footprint '%s')." ),
243 bool showRatsnest =
true;
246 showRatsnest =
m_settings->m_Display.m_ShowGlobalRatsnest;
248 pad->SetLocalRatsnestVisible( showRatsnest );
251 pad->SetNetCode( 0 );
266 msg.Printf(
_(
"Added %s (footprint '%s')." ),
279 wxString curClassName, newClassName;
283 curClassName = curClass->
GetName();
293 newClass =
m_board->GetComponentClassManager().GetEffectiveStaticComponentClass(
295 newClassName = newClass->
GetName();
298 if( curClassName == newClassName )
307 copy->SetParentGroup(
nullptr );
314 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
316 msg.Printf(
_(
"Change %s component class to '%s'." ),
320 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
322 msg.Printf(
_(
"Remove %s component class (currently '%s')." ),
328 msg.Printf(
_(
"Change %s component class from '%s' to '%s'." ),
336 wxASSERT_MSG( newClass !=
nullptr,
"Component class should not be nullptr" );
340 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
342 msg.Printf(
_(
"Changed %s component class to '%s'." ),
346 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
348 msg.Printf(
_(
"Removed %s component class (was '%s')." ),
354 msg.Printf(
_(
"Changed %s component class from '%s' to '%s'." ),
377 msg.Printf(
_(
"Cannot update %s (no footprint assigned)." ),
386 if( newFootprint ==
nullptr )
388 msg.Printf(
_(
"Cannot update %s (footprint '%s' not found)." ),
400 msg.Printf(
_(
"Cannot change %s footprint from '%s' to '%s' (footprint is locked)."),
411 msg.Printf(
_(
"Change %s footprint from '%s' to '%s'."),
425 msg.Printf(
_(
"Could not change %s footprint from '%s' to '%s' (footprint is locked)."),
439 m_board->ExchangeFootprint( aFootprint, newFootprint,
m_commit,
true );
441 msg.Printf(
_(
"Changed %s footprint from '%s' to '%s'."),
467 firstAssociatedVariant = &
test;
476 if( !
m_commit.GetStatus( aFootprint ) )
479 copy->SetParentGroup(
nullptr );
482 bool changed =
false;
489 msg.Printf(
_(
"Change %s reference designator to %s." ),
495 msg.Printf(
_(
"Changed %s reference designator to %s." ),
507 wxString netlistValue = aNetlistComponent->
GetValue();
509 if( firstAssociatedVariant !=
nullptr
515 if( aFootprint->
GetValue() != netlistValue )
519 msg.Printf(
_(
"Change %s value from %s to %s." ),
526 msg.Printf(
_(
"Changed %s value from %s to %s." ),
532 aFootprint->
SetValue( netlistValue );
541 if( !aNetlistComponent->
GetKIIDs().empty() )
542 new_path.push_back( aNetlistComponent->
GetKIIDs().front() );
544 if( aFootprint->
GetPath() != new_path )
548 msg.Printf(
_(
"Update %s symbol association from %s to %s." ),
555 msg.Printf(
_(
"Updated %s symbol association from %s to %s." ),
561 aFootprint->
SetPath( new_path );
567 nlohmann::ordered_map<wxString, wxString> fpFieldsAsMap;
572 if( field->IsReference() || field->IsValue() || field->IsComponentClass() )
577 fpFieldsAsMap[field->GetName()] = field->GetText();
581 nlohmann::ordered_map<wxString, wxString> compFields = aNetlistComponent->
GetFields();
587 compFields.erase( wxT(
"Component Class" ) );
589 if( firstAssociatedVariant !=
nullptr )
591 for(
const auto& [
name, value] : firstAssociatedVariant->
m_fields )
592 compFields[
name] = value;
598 bool remove_only =
true;
600 for(
const auto& [
name, value] : compFields )
602 if( fpFieldsAsMap.count(
name ) == 0 || fpFieldsAsMap[
name] != value )
610 for(
const auto& [
name, value] : fpFieldsAsMap )
612 if( compFields.count(
name ) == 0 )
625 msg.Printf(
_(
"Update %s fields." ), aFootprint->
GetReference() );
632 if( field->IsMandatory() )
635 if( compFields.count( field->GetName() ) == 0 )
639 msg.Printf(
_(
"Remove %s footprint fields not in symbol." ), aFootprint->
GetReference() );
651 msg.Printf(
_(
"Updated %s fields." ), aFootprint->
GetReference() );
657 for(
auto& [
name, value] : compFields )
666 aFootprint->
Add( newField );
687 std::vector<PCB_FIELD*> fieldList;
688 aFootprint->
GetFields( fieldList,
false );
692 if( field->IsMandatory() )
695 if( compFields.count( field->GetName() ) == 0 )
700 msg.Printf(
_(
"Removed %s footprint fields not in symbol." ), aFootprint->
GetReference() );
704 aFootprint->
Remove( field );
707 m_frame->GetCanvas()->GetView()->Remove( field );
722 if( !humanSheetPath.empty() )
723 sheetname = humanSheetPath;
724 else if( aNetlistComponent->
GetProperties().count( wxT(
"Sheetname" ) ) > 0 )
725 sheetname = aNetlistComponent->
GetProperties().at( wxT(
"Sheetname" ) );
727 if( aNetlistComponent->
GetProperties().count( wxT(
"Sheetfile" ) ) > 0 )
728 sheetfile = aNetlistComponent->
GetProperties().at( wxT(
"Sheetfile" ) );
730 if( aNetlistComponent->
GetProperties().count( wxT(
"ki_fp_filters" ) ) > 0 )
731 fpFilters = aNetlistComponent->
GetProperties().at( wxT(
"ki_fp_filters" ) );
737 msg.Printf(
_(
"Update %s sheetname to '%s'." ),
744 msg.Printf(
_(
"Updated %s sheetname to '%s'." ),
756 msg.Printf(
_(
"Update %s sheetfile to '%s'." ),
763 msg.Printf(
_(
"Updated %s sheetfile to '%s'." ),
775 msg.Printf(
_(
"Update %s footprint filters to '%s'." ),
782 msg.Printf(
_(
"Updated %s footprint filters to '%s'." ),
790 bool netlistExcludeFromBOM = aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_bom" ) ) > 0;
799 if( netlistExcludeFromBOM )
800 msg.Printf(
_(
"Add %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
802 msg.Printf(
_(
"Remove %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
808 if( netlistExcludeFromBOM )
811 msg.Printf(
_(
"Added %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
816 msg.Printf(
_(
"Removed %s 'exclude from BOM' fabrication attribute." ), aFootprint->
GetReference() );
826 bool netlistExcludeFromSim = aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_sim" ) ) > 0;
836 if( netlistExcludeFromSim )
837 msg.Printf(
_(
"Add %s 'exclude from simulation' attribute." ), aFootprint->
GetReference() );
839 msg.Printf(
_(
"Remove %s 'exclude from simulation' attribute." ), aFootprint->
GetReference() );
845 if( netlistExcludeFromSim )
848 msg.Printf(
_(
"Added %s 'exclude from simulation' attribute." ), aFootprint->
GetReference() );
853 msg.Printf(
_(
"Removed %s 'exclude from simulation' attribute." ), aFootprint->
GetReference() );
863 bool netlistDNP = aNetlistComponent->
GetProperties().count( wxT(
"dnp" ) ) > 0;
865 if( firstAssociatedVariant !=
nullptr && firstAssociatedVariant->
m_hasDnp )
866 netlistDNP = firstAssociatedVariant->
m_dnp;
873 msg.Printf(
_(
"Add %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
875 msg.Printf(
_(
"Remove %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
884 msg.Printf(
_(
"Added %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
889 msg.Printf(
_(
"Removed %s 'Do not place' fabrication attribute." ), aFootprint->
GetReference() );
899 bool netlistExcludeFromPosFiles = aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_pos_files" ) ) > 0;
909 if( netlistExcludeFromPosFiles )
911 msg.Printf(
_(
"Add %s 'exclude from position files' fabrication attribute." ),
916 msg.Printf(
_(
"Remove %s 'exclude from position files' fabrication attribute." ),
924 if( netlistExcludeFromPosFiles )
927 msg.Printf(
_(
"Added %s 'exclude from position files' fabrication attribute." ),
933 msg.Printf(
_(
"Removed %s 'exclude from position files' fabrication attribute." ),
956 msg.Printf(
_(
"Added %s 'duplicate pad numbers are jumpers' attribute." ),
961 msg.Printf(
_(
"Removed %s 'duplicate pad numbers are jumpers' attribute." ),
969 msg.Printf(
_(
"Add %s 'duplicate pad numbers are jumpers' attribute." ),
974 msg.Printf(
_(
"Remove %s 'duplicate pad numbers are jumpers' attribute." ),
988 msg.Printf(
_(
"Updated %s jumper pad groups" ), aFootprint->
GetReference() );
992 msg.Printf(
_(
"Update %s jumper pad groups" ), aFootprint->
GetReference() );
998 if( changed &&
copy )
1018 if( !
m_commit.GetStatus( aPcbFootprint ) )
1021 copy->SetParentGroup(
nullptr );
1024 bool changed =
false;
1033 KIID existingGroupKIID = existingGroup ? existingGroup->
m_Uuid : 0;
1036 auto it = std::find_if(
m_board->Groups().begin(),
m_board->Groups().end(),
1038 return group->m_Uuid == newGroupKIID;
1042 if( it !=
m_board->Groups().end() )
1046 if( newGroupKIID == existingGroupKIID )
1050 if( existingGroupKIID != 0 )
1054 msg.Printf(
_(
"Remove %s from group '%s'." ),
1060 msg.Printf(
_(
"Removed %s from group '%s'." ),
1068 if( existingGroup->
GetItems().size() < 2 )
1079 if( newGroupKIID != 0 )
1083 msg.Printf(
_(
"Add %s to group '%s'." ),
1089 msg.Printf(
_(
"Added %s to group '%s'." ),
1095 if( newGroup ==
nullptr )
1098 newGroup->
SetUuid( newGroupKIID );
1112 newGroup->
AddItem( aPcbFootprint );
1118 if( changed &&
copy )
1138 copy->SetParentGroup(
nullptr );
1141 bool changed =
false;
1144 std::deque<PAD*> pads = aFootprint->
Pads();
1145 std::set<wxString> padNetnames;
1147 std::sort( pads.begin(), pads.end(),
1150 return a->m_Uuid < b->m_Uuid;
1157 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1158 wxT(
"Processing pad %s of component %s" ),
1162 wxString pinFunction;
1167 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1168 wxT(
" Found valid net: %s" ),
1175 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1176 wxT(
" No net found for pad %s" ),
1182 if(
pad->GetPinFunction() != pinFunction )
1185 pad->SetPinFunction( pinFunction );
1188 if(
pad->GetPinType() != pinType )
1191 pad->SetPinType( pinType );
1200 if( !net.
IsValid() || !
pad->IsOnCopperLayer() )
1202 if( !
pad->GetNetname().IsEmpty() )
1206 msg.Printf(
_(
"Disconnect %s pin %s." ),
1212 msg.Printf(
_(
"Disconnected %s pin %s." ),
1219 else if(
pad->IsOnCopperLayer() && !
pad->GetNumber().IsEmpty() )
1222 msg.Printf(
_(
"No net found for component %s pad %s (no pin %s in symbol)." ),
1237 if(
pad->GetNetname().IsEmpty() )
1238 pad->SetPinFunction( wxEmptyString );
1250 if(
pad->IsNoConnectPad() )
1252 netName = wxString::Format( wxS(
"%s" ), net.
GetNetName() );
1254 for(
int jj = 1; !padNetnames.insert( netName ).second
1258 netName = wxString::Format( wxS(
"%s_%d" ), net.
GetNetName(), jj );
1267 if(
pad->GetNetname() != netName )
1270 if( netinfo ==
nullptr )
1277 if( netinfo ==
nullptr )
1289 msg.Printf(
_(
"Add net %s." ),
1294 if( !
pad->GetNetname().IsEmpty() )
1300 msg.Printf(
_(
"Reconnect %s pin %s from %s to %s."),
1308 msg.Printf(
_(
"Reconnected %s pin %s from %s to %s."),
1319 msg.Printf(
_(
"Connect %s pin %s to %s."),
1326 msg.Printf(
_(
"Connected %s pin %s to %s."),
1338 pad->SetNet( netinfo );
1348 if( changed &&
copy )
1360 std::vector<FOOTPRINT::FP_UNIT_INFO> newUnits;
1363 newUnits.push_back( { u.m_unitName, u.m_pins } );
1365 const std::vector<FOOTPRINT::FP_UNIT_INFO>& curUnits = aFootprint->
GetUnitInfo();
1367 auto unitsEqual = [](
const std::vector<FOOTPRINT::FP_UNIT_INFO>& a,
1368 const std::vector<FOOTPRINT::FP_UNIT_INFO>& b )
1370 if( a.size() != b.size() )
1373 for(
size_t i = 0; i < a.size(); ++i )
1375 if( a[i].m_unitName != b[i].m_unitName )
1378 if( a[i].m_pins != b[i].m_pins )
1385 if( unitsEqual( curUnits, newUnits ) )
1392 msg.Printf(
_(
"Update %s unit metadata." ), aFootprint->
GetReference() );
1400 if( !
m_commit.GetStatus( aFootprint ) )
1403 copy->SetParentGroup(
nullptr );
1408 msg.Printf(
_(
"Updated %s unit metadata." ), aFootprint->
GetReference() );
1423 return aBoardFpid == aSchematicFpid;
1428 const std::vector<FOOTPRINT*>& aFootprints,
1429 const LIB_ID& aBaseFpid )
1434 if( aBaseFpid.
empty() )
1446 std::vector<VARIANT_INFO> variantInfo;
1447 variantInfo.reserve( variants.size() );
1449 for(
const auto& [variantName, variant] : variants )
1451 LIB_ID variantFPID = aBaseFpid;
1453 auto fieldIt = variant.m_fields.find( footprintFieldName );
1455 if( fieldIt != variant.m_fields.end() && !fieldIt->second.IsEmpty() )
1459 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
1461 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
1470 variantFPID = parsedId;
1474 variantInfo.push_back( { variantName, &variant, variantFPID } );
1477 for(
FOOTPRINT* footprint : aFootprints )
1487 copy->SetParentGroup(
nullptr );
1490 bool changed =
false;
1492 auto printAttributeMessage =
1493 [&](
bool add,
const wxString& attrName,
const wxString& variantName )
1497 if( aFootprints.size() > 1 )
1499 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s (footprint %s)." )
1500 :
_(
"Remove %s '%s' attribute from variant %s (footprint %s)." ),
1501 footprint->GetReference(),
1504 footprint->GetFPIDAsString() );
1508 msg.Printf( add ?
_(
"Add %s '%s' attribute to variant %s." )
1509 :
_(
"Remove %s '%s' attribute from variant %s." ),
1510 footprint->GetReference(),
1517 if( aFootprints.size() > 1 )
1519 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s (footprint %s)." )
1520 :
_(
"Removed %s '%s' attribute from variant %s (footprint %s)." ),
1521 footprint->GetReference(),
1524 footprint->GetFPIDAsString() );
1528 msg.Printf( add ?
_(
"Added %s '%s' attribute to variant %s." )
1529 :
_(
"Removed %s '%s' attribute from variant %s." ),
1530 footprint->GetReference(),
1537 bool isBaseFootprint =
fpidsEquivalent( footprint->GetFPID(), aBaseFpid );
1542 const bool baseFootprintDnp = footprint->IsDNP();
1543 bool effectiveFootprintDnp = baseFootprintDnp;
1550 if( !isBaseFootprint && !effectiveFootprintDnp )
1552 msg.Printf(
m_isDryRun ?
_(
"Add %s 'Do not place' fabrication attribute." )
1553 :
_(
"Added %s 'Do not place' fabrication attribute." ),
1554 footprint->GetReference() );
1559 footprint->SetDNP(
true );
1563 effectiveFootprintDnp =
true;
1567 std::set<wxString> excessVariants;
1569 for(
const auto& [variantName,
_] : footprint->GetVariants() )
1570 excessVariants.insert( variantName );
1572 for(
const VARIANT_INFO&
info : variantInfo )
1586 if( !isAssociatedFootprint )
1588 if( aFootprints.size() > 1 )
1590 excessVariants.erase(
info.name );
1591 bool currentDnp = currentVariant ? currentVariant->
GetDNP() : effectiveFootprintDnp;
1595 printAttributeMessage(
true,
_(
"Do not place" ),
info.name );
1600 fpVariant->SetDNP(
true );
1611 excessVariants.erase(
info.name );
1612 bool targetDnp = variant.
m_hasDnp ? variant.
m_dnp : baseFootprintDnp;
1613 bool currentDnp = currentVariant ? currentVariant->
GetDNP() : effectiveFootprintDnp;
1615 if( currentDnp != targetDnp )
1617 printAttributeMessage( targetDnp,
_(
"Do not place" ),
info.name );
1622 fpVariant->SetDNP( targetDnp );
1630 : footprint->IsExcludedFromBOM();
1632 : footprint->IsExcludedFromBOM();
1634 if( currentExcludedFromBOM != targetExcludedFromBOM )
1636 printAttributeMessage( targetExcludedFromBOM,
_(
"exclude from BOM" ),
info.name );
1641 fpVariant->SetExcludedFromBOM( targetExcludedFromBOM );
1649 : footprint->IsExcludedFromSim();
1651 : footprint->IsExcludedFromSim();
1653 if( currentExcludedFromSim != targetExcludedFromSim )
1655 printAttributeMessage( targetExcludedFromSim,
_(
"exclude from simulation" ),
info.name );
1660 fpVariant->SetExcludedFromSim( targetExcludedFromSim );
1668 : footprint->IsExcludedFromPosFiles();
1670 : footprint->IsExcludedFromPosFiles();
1672 if( currentExcludedFromPosFiles != targetExcludedFromPosFiles )
1674 printAttributeMessage( targetExcludedFromPosFiles,
_(
"exclude from position files" ),
info.name );
1679 fpVariant->SetExcludedFromPosFiles( targetExcludedFromPosFiles );
1686 for(
const auto& [fieldName, fieldValue] : variant.
m_fields )
1688 if( fieldName.CmpNoCase( footprintFieldName ) == 0 )
1691 bool hasCurrentValue = currentVariant && currentVariant->
HasFieldValue( fieldName );
1692 wxString currentValue = hasCurrentValue ? currentVariant->
GetFieldValue( fieldName ) : wxString();
1694 if( currentValue != fieldValue )
1698 if( aFootprints.size() > 1 )
1700 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s (footprint %s)." ),
1701 footprint->GetReference(),
1705 footprint->GetFPIDAsString() );
1709 msg.Printf(
_(
"Change %s field '%s' to '%s' on variant %s." ),
1710 footprint->GetReference(),
1718 if( aFootprints.size() > 1 )
1720 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s (footprint %s)." ),
1721 footprint->GetReference(),
1725 footprint->GetFPIDAsString() );
1729 msg.Printf(
_(
"Changed %s field '%s' to '%s' on variant %s." ),
1730 footprint->GetReference(),
1737 fpVariant->SetFieldValue( fieldName, fieldValue );
1746 for(
const wxString& excess : excessVariants )
1750 msg.Printf(
_(
"Remove variant %s:%s no longer associated with footprint %s." ),
1751 footprint->GetReference(),
1753 footprint->GetFPIDAsString() );
1757 msg.Printf(
_(
"Removed variant %s:%s no longer associated with footprint %s." ),
1758 footprint->GetReference(),
1760 footprint->GetFPIDAsString() );
1762 footprint->DeleteVariant( excess );
1781 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1792 std::set<wxString> netlistNetnames;
1794 for(
int ii = 0; ii < (int) aNetlist.
GetCount(); ii++ )
1798 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1810 if( netlistNetnames.count(
via->GetNetname() ) == 0 )
1812 wxString updatedNetname = wxEmptyString;
1821 if( !updatedNetname.IsEmpty() )
1825 wxString originalNetname =
via->GetNetname();
1827 msg.Printf(
_(
"Reconnect via from %s to %s." ),
1842 wxString originalNetname =
via->GetNetname();
1845 via->SetNet( netinfo );
1847 msg.Printf(
_(
"Reconnected via from %s to %s." ),
1857 msg.Printf(
_(
"Via connected to unknown net (%s)." ),
1869 auto isInNetlist = [&](
const wxString& aNetName ) ->
bool
1871 if( netlistNetnames.count( aNetName ) )
1876 for(
const wxString& netName : netlistNetnames )
1878 if( aNetName.StartsWith( netName ) )
1888 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1891 if( !isInNetlist( zone->GetNetname() ) )
1896 wxString updatedNetname = wxEmptyString;
1909 if( updatedNetname.IsEmpty() &&
m_oldToNewNets.count( zone->GetNetname() ) )
1914 if( !updatedNetname.IsEmpty() )
1918 wxString originalNetname = zone->GetNetname();
1920 if( !zone->GetZoneName().IsEmpty() )
1922 msg.Printf(
_(
"Reconnect copper zone '%s' from %s to %s." ),
1923 zone->GetZoneName(),
1929 msg.Printf(
_(
"Reconnect copper zone from %s to %s." ),
1945 wxString originalNetname = zone->GetNetname();
1948 zone->SetNet( netinfo );
1950 if( !zone->GetZoneName().IsEmpty() )
1952 msg.Printf(
_(
"Reconnected copper zone '%s' from %s to %s." ),
1959 msg.Printf(
_(
"Reconnected copper zone from %s to %s." ),
1970 if( !zone->GetZoneName().IsEmpty() )
1972 msg.Printf(
_(
"Copper zone '%s' has no pads connected." ),
1977 wxString layerNames = zone->LayerMaskDescribe();
1982 if(
m_settings->m_Display.m_DisplayInvertXAxis )
1985 if(
m_settings->m_Display.m_DisplayInvertYAxis )
1989 msg.Printf(
_(
"Copper zone on %s at (%s, %s) has no pads connected to net \"%s\"." ),
1999 zone->GetNetname() );
2023 if( netlistGroup ==
nullptr )
2026 if( netlistGroup->
name != pcbGroup->GetName() )
2030 msg.Printf(
_(
"Change group name from '%s' to '%s'." ),
2036 msg.Printf(
_(
"Changed group name from '%s' to '%s'." ),
2040 pcbGroup->SetName( netlistGroup->
name );
2046 if( netlistGroup->
libId != pcbGroup->GetDesignBlockLibId() )
2050 msg.Printf(
_(
"Change group library link from '%s' to '%s'." ),
2051 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
2056 msg.Printf(
_(
"Changed group library link from '%s' to '%s'." ),
2057 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
2060 pcbGroup->SetDesignBlockLibId( netlistGroup->
libId );
2070 if( member.empty() )
2073 KIID memberGroupUuid =
2080 if( candidate->m_Uuid == memberGroupUuid )
2082 childGroup = candidate;
2087 if( !childGroup || childGroup == pcbGroup || childGroup->
GetParentGroup() == pcbGroup )
2094 msg.Printf(
_(
"Add group '%s' to group '%s'." ),
EscapeHTML( childGroup->
GetName() ),
2099 msg.Printf(
_(
"Added group '%s' to group '%s'." ),
EscapeHTML( childGroup->
GetName() ),
2103 pcbGroup->AddItem( childGroup );
2115 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
2123 for(
int i = 0; i < (int) aNetlist.
GetCount(); i++ )
2126 FOOTPRINT* footprint = aFootprintMap[component];
2132 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
2136 if( padNumber.IsEmpty() )
2139 msg.Printf(
_(
"Symbol %s has pins with no number. These pins can not be matched "
2149 msg.Printf(
_(
"%s pad %s not found in %s." ),
2165 FOOTPRINT* lastPreexistingFootprint =
nullptr;
2168 std::unordered_set<wxString> sheetPaths;
2169 std::unordered_set<FOOTPRINT*> usedFootprints;
2175 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
2177 if( !
m_board->Footprints().empty() )
2178 lastPreexistingFootprint =
m_board->Footprints().back();
2188 net->SetIsCurrent( net->GetNetCode() == 0 );
2190 m_board->GetComponentClassManager().InitNetlistUpdate();
2194 for(
unsigned ii = 0; ii < aNetlist.
GetCount(); ii++ )
2198 for(
unsigned jj = 0; jj <
comp->GetNetCount(); jj++ )
2205 for(
unsigned i = 0; i < aNetlist.
GetCount(); i++ )
2209 if( component->
GetProperties().count( wxT(
"exclude_from_board" ) ) )
2212 msg.Printf(
_(
"Processing symbol '%s:%s'." ),
2218 const bool hasBaseFpid = !baseFpid.
empty();
2222 msg.Printf(
_(
"Warning: %s footprint '%s' is missing a library name. "
2223 "Use the full 'Library:Footprint' format to avoid repeated update "
2231 std::vector<FOOTPRINT*> matchingFootprints;
2242 base.push_back( uuid );
2244 if( footprint->GetPath() == base )
2253 match = footprint->GetReference().CmpNoCase( component->
GetReference() ) == 0;
2257 matchingFootprints.push_back( footprint );
2259 if( footprint == lastPreexistingFootprint )
2266 std::vector<LIB_ID> expectedFpids;
2267 std::unordered_set<wxString> expectedFpidKeys;
2269 auto addExpectedFpid =
2270 [&](
const LIB_ID& aFpid )
2275 wxString key = aFpid.Format();
2277 if( expectedFpidKeys.insert( key ).second )
2278 expectedFpids.push_back( aFpid );
2281 addExpectedFpid( baseFpid );
2285 for(
const auto& [variantName, variant] : component->
GetVariants() )
2287 auto fieldIt = variant.m_fields.find( footprintFieldName );
2289 if( fieldIt == variant.m_fields.end() || fieldIt->second.IsEmpty() )
2294 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
2296 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
2305 addExpectedFpid( parsedId );
2308 auto isExpectedFpid =
2309 [&](
const LIB_ID& aFpid ) ->
bool
2314 if( expectedFpidKeys.count( aFpid.Format() ) > 0 )
2326 auto takeMatchingFootprint =
2329 for(
FOOTPRINT* footprint : matchingFootprints )
2331 if( usedFootprints.count( footprint ) )
2341 std::vector<FOOTPRINT*> componentFootprints;
2342 componentFootprints.reserve( expectedFpids.size() );
2346 baseFootprint = takeMatchingFootprint( baseFpid );
2347 else if( !matchingFootprints.empty() )
2348 baseFootprint = matchingFootprints.front();
2354 for(
FOOTPRINT* footprint : matchingFootprints )
2356 if( usedFootprints.count( footprint ) )
2359 if( isExpectedFpid( footprint->GetFPID() ) )
2362 replaceCandidate = footprint;
2366 if( replaceCandidate )
2371 baseFootprint = replaced;
2373 baseFootprint = replaceCandidate;
2379 for(
FOOTPRINT* footprint : matchingFootprints )
2381 if( usedFootprints.count( footprint ) )
2384 if( isExpectedFpid( footprint->GetFPID() ) )
2387 baseFootprint = footprint;
2392 if( !baseFootprint && ( hasBaseFpid || expectedFpids.empty() ) )
2397 componentFootprints.push_back( baseFootprint );
2398 usedFootprints.insert( baseFootprint );
2399 footprintMap[ component ] = baseFootprint;
2402 for(
const LIB_ID& fpid : expectedFpids )
2410 FOOTPRINT* footprint = takeMatchingFootprint( fpid );
2417 componentFootprints.push_back( footprint );
2418 usedFootprints.insert( footprint );
2422 for(
FOOTPRINT* footprint : componentFootprints )
2433 sheetPaths.insert( footprint->GetSheetname() );
2436 if( !componentFootprints.empty() )
2448 bool matched =
false;
2454 bool isStaleVariantFootprint =
false;
2456 if( usedFootprints.count( footprint ) )
2467 if( component && component->
GetProperties().count( wxT(
"exclude_from_board" ) ) == 0 )
2475 isStaleVariantFootprint =
true;
2486 if( isStaleVariantFootprint )
2489 if( doDelete && !matched && footprint->IsLocked() && !
m_overrideLocks )
2493 msg.Printf(
_(
"Cannot remove unused footprint %s (footprint is locked)." ),
2494 footprint->GetReference() );
2498 msg.Printf(
_(
"Could not remove unused footprint %s (footprint is locked)." ),
2499 footprint->GetReference() );
2507 if( doDelete && !matched )
2511 msg.Printf(
_(
"Remove unused footprint %s." ),
2512 footprint->GetReference() );
2517 msg.Printf(
_(
"Removed unused footprint %s." ),
2518 footprint->GetReference() );
2528 for(
PAD*
pad : footprint->Pads() )
2531 pad->GetNet()->SetIsCurrent(
true );
2539 m_board->GetComponentClassManager().FinishNetlistUpdate();
2540 m_board->SynchronizeComponentClasses( sheetPaths );
2547 if( !net->IsCurrent() )
2549 msg.Printf(
_(
"Removed unused net %s." ),
2558 const std::vector<wxString>& netlistVariants = aNetlist.
GetVariantNames();
2560 if( !netlistVariants.empty() || !
m_board->GetVariantNames().empty() )
2564 auto findBoardVariantName =
2565 [&](
const wxString& aVariantName ) -> wxString
2567 for(
const wxString&
name :
m_board->GetVariantNames() )
2569 if(
name.CmpNoCase( aVariantName ) == 0 )
2573 return wxEmptyString;
2576 std::vector<wxString> updatedVariantNames;
2577 updatedVariantNames.reserve( netlistVariants.size() );
2579 for(
const wxString& variantName : netlistVariants )
2581 wxString actualName = findBoardVariantName( variantName );
2583 if( actualName.IsEmpty() )
2585 m_board->AddVariant( variantName );
2586 actualName = findBoardVariantName( variantName );
2588 if( !actualName.IsEmpty() )
2590 msg.Printf(
_(
"Added variant '%s'." ), actualName );
2595 if( actualName.IsEmpty() )
2600 wxString oldDescription =
m_board->GetVariantDescription( actualName );
2602 if( newDescription != oldDescription )
2604 m_board->SetVariantDescription( actualName, newDescription );
2605 msg.Printf(
_(
"Updated description for variant '%s'." ), actualName );
2609 updatedVariantNames.push_back( actualName );
2612 std::vector<wxString> variantsToRemove;
2614 for(
const wxString& existingName :
m_board->GetVariantNames() )
2618 for(
const wxString& variantName : netlistVariants )
2620 if( existingName.CmpNoCase( variantName ) == 0 )
2628 variantsToRemove.push_back( existingName );
2631 for(
const wxString& variantName : variantsToRemove )
2633 m_board->DeleteVariant( variantName );
2634 msg.Printf(
_(
"Removed variant '%s'." ), variantName );
2638 if( !updatedVariantNames.empty() )
2639 m_board->SetVariantNames( updatedVariantNames );
2658 if( !colorStr.IsEmpty() )
2671 m_board->SynchronizeNetsAndNetClasses(
true );
2675 PAD* pads[2] = {
nullptr,
nullptr };
2677 for(
size_t i = 0; i < sig.second.size() && i < 2; ++i )
2679 const wxString& ref = sig.second[i].first;
2680 const wxString&
pin = sig.second[i].second;
2686 PAD* candidate =
nullptr;
2687 PAD* best =
nullptr;
2688 int bestDist = std::numeric_limits<int>::max();
2697 if( !best || dist < bestDist || ( dist == bestDist && candidate->
m_Uuid < best->
m_Uuid ) )
2707 for(
int i = 0; i < 2; ++i )
2714 if( !termNet || termNet->
GetNetChain() != sig.first )
2719 if( net != termNet && net->
GetNetChain() == sig.first
2720 && net->GetTerminalPad( i ) )
2722 net->ClearTerminalPad( i );
2738 for(
const std::pair<const wxString, NETINFO_ITEM*>& addedNet :
m_addedNets )
2739 delete addedNet.second;
constexpr EDA_IU_SCALE pcbIUScale
wxString GetNetname() const
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
std::shared_ptr< NET_SETTINGS > m_NetSettings
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
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() 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
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 &settings, 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)
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