134 bestPosition.
x = pageSize.
x / 2;
135 bestPosition.
y = pageSize.
y / 2;
152 if( aFootprintId.
empty() )
154 msg.Printf(
_(
"Cannot add %s (no footprint assigned)." ),
163 if( footprint ==
nullptr )
165 msg.Printf(
_(
"Cannot add %s (footprint '%s' not found)." ),
174 m_board->GetComponentClassManager().GetNoneComponentClass() );
178 msg.Printf(
_(
"Add %s (footprint '%s')." ),
190 pad->SetLocalRatsnestVisible(
m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest );
193 pad->SetNetCode( 0 );
208 msg.Printf(
_(
"Added %s (footprint '%s')." ),
221 wxString curClassName, newClassName;
225 curClassName = curClass->
GetName();
235 newClass =
m_board->GetComponentClassManager().GetEffectiveStaticComponentClass(
237 newClassName = newClass->
GetName();
240 if( curClassName == newClassName )
249 copy->SetParentGroup(
nullptr );
256 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
258 msg.Printf(
_(
"Change %s component class to '%s'." ),
262 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
264 msg.Printf(
_(
"Remove %s component class (currently '%s')." ),
270 msg.Printf(
_(
"Change %s component class from '%s' to '%s'." ),
278 wxASSERT_MSG( newClass !=
nullptr,
"Component class should not be nullptr" );
282 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
284 msg.Printf(
_(
"Changed %s component class to '%s'." ),
288 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
290 msg.Printf(
_(
"Removed %s component class (was '%s')." ),
296 msg.Printf(
_(
"Changed %s component class from '%s' to '%s'." ),
319 msg.Printf(
_(
"Cannot update %s (no footprint assigned)." ),
328 if( newFootprint ==
nullptr )
330 msg.Printf(
_(
"Cannot update %s (footprint '%s' not found)." ),
342 msg.Printf(
_(
"Cannot change %s footprint from '%s' to '%s' (footprint is locked)."),
353 msg.Printf(
_(
"Change %s footprint from '%s' to '%s'."),
367 msg.Printf(
_(
"Could not change %s footprint from '%s' to '%s' (footprint is locked)."),
383 msg.Printf(
_(
"Changed %s footprint from '%s' to '%s'."),
403 if( !
m_commit.GetStatus( aPcbFootprint ) )
406 copy->SetParentGroup(
nullptr );
409 bool changed =
false;
416 msg.Printf(
_(
"Change %s reference designator to %s." ),
422 msg.Printf(
_(
"Changed %s reference designator to %s." ),
438 msg.Printf(
_(
"Change %s value from %s to %s." ),
445 msg.Printf(
_(
"Changed %s value from %s to %s." ),
460 if( !aNetlistComponent->
GetKIIDs().empty() )
461 new_path.push_back( aNetlistComponent->
GetKIIDs().front() );
463 if( aPcbFootprint->
GetPath() != new_path )
467 msg.Printf(
_(
"Update %s symbol association from %s to %s." ),
474 msg.Printf(
_(
"Updated %s symbol association from %s to %s." ),
480 aPcbFootprint->
SetPath( new_path );
486 nlohmann::ordered_map<wxString, wxString> fpFieldsAsMap;
491 if( field->IsReference() || field->IsValue() || field->IsComponentClass() )
496 fpFieldsAsMap[field->GetName()] = field->GetText();
500 nlohmann::ordered_map<wxString, wxString> compFields = aNetlistComponent->
GetFields();
506 compFields.erase( wxT(
"Component Class" ) );
512 bool remove_only =
true;
514 for(
const auto& [
name, value] : compFields )
516 if( fpFieldsAsMap.count(
name ) == 0 || fpFieldsAsMap[
name] != value )
524 for(
const auto& [
name, value] : fpFieldsAsMap )
526 if( compFields.count(
name ) == 0 )
539 msg.Printf(
_(
"Update %s fields." ), aPcbFootprint->
GetReference() );
546 if( field->IsMandatory() )
549 if( compFields.count( field->GetName() ) == 0 )
553 msg.Printf(
_(
"Remove %s footprint fields not in symbol." ),
566 msg.Printf(
_(
"Updated %s fields." ), aPcbFootprint->
GetReference() );
572 for(
auto& [
name, value] : compFields )
581 aPcbFootprint->
Add( newField );
603 std::vector<PCB_FIELD*> fieldList;
604 aPcbFootprint->
GetFields( fieldList,
false );
608 if( field->IsMandatory() )
611 if( compFields.count( field->GetName() ) == 0 )
616 msg.Printf(
_(
"Removed %s footprint fields not in symbol." ),
621 aPcbFootprint->
Remove( field );
624 m_frame->GetCanvas()->GetView()->Remove( field );
639 if( !humanSheetPath.empty() )
640 sheetname = humanSheetPath;
641 else if( aNetlistComponent->
GetProperties().count( wxT(
"Sheetname" ) ) > 0 )
642 sheetname = aNetlistComponent->
GetProperties().at( wxT(
"Sheetname" ) );
644 if( aNetlistComponent->
GetProperties().count( wxT(
"Sheetfile" ) ) > 0 )
645 sheetfile = aNetlistComponent->
GetProperties().at( wxT(
"Sheetfile" ) );
647 if( aNetlistComponent->
GetProperties().count( wxT(
"ki_fp_filters" ) ) > 0 )
648 fpFilters = aNetlistComponent->
GetProperties().at( wxT(
"ki_fp_filters" ) );
654 msg.Printf(
_(
"Update %s sheetname to '%s'." ),
661 msg.Printf(
_(
"Updated %s sheetname to '%s'." ),
673 msg.Printf(
_(
"Update %s sheetfile to '%s'." ),
680 msg.Printf(
_(
"Updated %s sheetfile to '%s'." ),
688 if( fpFilters != aPcbFootprint->
GetFilters() )
692 msg.Printf(
_(
"Update %s footprint filters to '%s'." ),
699 msg.Printf(
_(
"Updated %s footprint filters to '%s'." ),
707 if( ( aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_bom" ) ) > 0 )
712 if( aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_bom" ) ) )
714 msg.Printf(
_(
"Add %s 'exclude from BOM' fabrication attribute." ),
719 msg.Printf(
_(
"Remove %s 'exclude from BOM' fabrication attribute." ),
727 if( aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_bom" ) ) )
730 msg.Printf(
_(
"Added %s 'exclude from BOM' fabrication attribute." ),
736 msg.Printf(
_(
"Removed %s 'exclude from BOM' fabrication attribute." ),
747 if( ( aNetlistComponent->
GetProperties().count( wxT(
"dnp" ) ) > 0 )
752 if( aNetlistComponent->
GetProperties().count( wxT(
"dnp" ) ) )
754 msg.Printf(
_(
"Add %s 'Do not place' fabrication attribute." ),
759 msg.Printf(
_(
"Remove %s 'Do not place' fabrication attribute." ),
767 if( aNetlistComponent->
GetProperties().count( wxT(
"dnp" ) ) )
770 msg.Printf(
_(
"Added %s 'Do not place' fabrication attribute." ),
776 msg.Printf(
_(
"Removed %s 'Do not place' fabrication attribute." ),
787 if( ( aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_pos_files" ) ) > 0 )
792 if( aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_pos_files" ) ) )
794 msg.Printf(
_(
"Add %s 'exclude from position files' fabrication attribute." ),
799 msg.Printf(
_(
"Remove %s 'exclude from position files' fabrication attribute." ),
807 if( aNetlistComponent->
GetProperties().count( wxT(
"exclude_from_pos_files" ) ) )
810 msg.Printf(
_(
"Added %s 'exclude from position files' fabrication attribute." ),
816 msg.Printf(
_(
"Removed %s 'exclude from position files' fabrication attribute." ),
839 msg.Printf(
_(
"Added %s 'duplicate pad numbers are jumpers' attribute." ),
844 msg.Printf(
_(
"Removed %s 'duplicate pad numbers are jumpers' attribute." ),
852 msg.Printf(
_(
"Add %s 'duplicate pad numbers are jumpers' attribute." ),
857 msg.Printf(
_(
"Remove %s 'duplicate pad numbers are jumpers' attribute." ),
871 msg.Printf(
_(
"Updated %s jumper pad groups" ), aPcbFootprint->
GetReference() );
875 msg.Printf(
_(
"Update %s jumper pad groups" ), aPcbFootprint->
GetReference() );
881 if( changed &&
copy )
901 if( !
m_commit.GetStatus( aPcbFootprint ) )
904 copy->SetParentGroup(
nullptr );
907 bool changed =
false;
916 KIID existingGroupKIID = existingGroup ? existingGroup->
m_Uuid : 0;
919 auto it = std::find_if(
m_board->Groups().begin(),
m_board->Groups().end(),
921 return group->m_Uuid == newGroupKIID;
925 if( it !=
m_board->Groups().end() )
929 if( newGroupKIID == existingGroupKIID )
933 if( existingGroupKIID != 0 )
937 msg.Printf(
_(
"Remove %s from group '%s'." ),
943 msg.Printf(
_(
"Removed %s from group '%s'." ),
956 if( newGroupKIID != 0 )
960 msg.Printf(
_(
"Add %s to group '%s'." ),
966 msg.Printf(
_(
"Added %s to group '%s'." ),
972 if( newGroup ==
nullptr )
975 const_cast<KIID&
>( newGroup->
m_Uuid ) = newGroupKIID;
988 newGroup->
AddItem( aPcbFootprint );
994 if( changed &&
copy )
1014 copy->SetParentGroup(
nullptr );
1017 bool changed =
false;
1020 std::deque<PAD*> pads = aFootprint->
Pads();
1021 std::set<wxString> padNetnames;
1023 std::sort( pads.begin(), pads.end(),
1026 return a->m_Uuid < b->m_Uuid;
1033 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1034 wxT(
"Processing pad %s of component %s" ),
1038 wxString pinFunction;
1043 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1044 wxT(
" Found valid net: %s" ),
1051 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1052 wxT(
" No net found for pad %s" ),
1058 if(
pad->GetPinFunction() != pinFunction )
1061 pad->SetPinFunction( pinFunction );
1064 if(
pad->GetPinType() != pinType )
1067 pad->SetPinType( pinType );
1076 if( !net.
IsValid() || !
pad->IsOnCopperLayer() )
1078 if( !
pad->GetNetname().IsEmpty() )
1082 msg.Printf(
_(
"Disconnect %s pin %s." ),
1088 msg.Printf(
_(
"Disconnected %s pin %s." ),
1095 else if(
pad->IsOnCopperLayer() && !
pad->GetNumber().IsEmpty() )
1098 msg.Printf(
_(
"No net found for component %s pad %s (no pin %s in symbol)." ),
1113 if(
pad->GetNetname().IsEmpty() )
1114 pad->SetPinFunction( wxEmptyString );
1126 if(
pad->IsNoConnectPad() )
1128 netName = wxString::Format( wxS(
"%s" ), net.
GetNetName() );
1130 for(
int jj = 1; !padNetnames.insert( netName ).second; jj++ )
1132 netName = wxString::Format( wxS(
"%s_%d" ), net.
GetNetName(), jj );
1141 if(
pad->GetNetname() != netName )
1144 if( netinfo ==
nullptr )
1151 if( netinfo ==
nullptr )
1163 msg.Printf(
_(
"Add net %s." ),
1168 if( !
pad->GetNetname().IsEmpty() )
1174 msg.Printf(
_(
"Reconnect %s pin %s from %s to %s."),
1182 msg.Printf(
_(
"Reconnected %s pin %s from %s to %s."),
1193 msg.Printf(
_(
"Connect %s pin %s to %s."),
1200 msg.Printf(
_(
"Connected %s pin %s to %s."),
1212 pad->SetNet( netinfo );
1222 if( changed &&
copy )
1234 std::vector<FOOTPRINT::FP_UNIT_INFO> newUnits;
1237 newUnits.push_back( { u.m_unitName, u.m_pins } );
1239 const std::vector<FOOTPRINT::FP_UNIT_INFO>& curUnits = aFootprint->
GetUnitInfo();
1241 auto unitsEqual = [](
const std::vector<FOOTPRINT::FP_UNIT_INFO>& a,
1242 const std::vector<FOOTPRINT::FP_UNIT_INFO>& b )
1244 if( a.size() != b.size() )
1247 for(
size_t i = 0; i < a.size(); ++i )
1249 if( a[i].m_unitName != b[i].m_unitName )
1252 if( a[i].m_pins != b[i].m_pins )
1259 if( unitsEqual( curUnits, newUnits ) )
1266 msg.Printf(
_(
"Update %s unit metadata." ), aFootprint->
GetReference() );
1274 if( !
m_commit.GetStatus( aFootprint ) )
1277 copy->SetParentGroup(
nullptr );
1282 msg.Printf(
_(
"Updated %s unit metadata." ), aFootprint->
GetReference() );
1293 const std::vector<FOOTPRINT*>& aFootprints,
1294 const LIB_ID& aBaseFpid )
1298 if( variants.empty() )
1301 if( aBaseFpid.
empty() )
1313 std::vector<VARIANT_INFO> variantInfo;
1314 variantInfo.reserve( variants.size() );
1316 for(
const auto& [variantName, variant] : variants )
1318 LIB_ID activeFpid = aBaseFpid;
1320 auto fieldIt = variant.m_fields.find( footprintFieldName );
1322 if( fieldIt != variant.m_fields.end() && !fieldIt->second.IsEmpty() )
1326 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
1329 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
1338 activeFpid = parsedId;
1342 variantInfo.push_back( { variantName, &variant, activeFpid } );
1345 for(
FOOTPRINT* footprint : aFootprints )
1355 copy->SetParentGroup(
nullptr );
1358 bool changed =
false;
1360 for(
const VARIANT_INFO&
info : variantInfo )
1368 bool isActiveFootprint = ( footprint->GetFPID() ==
info.activeFpid );
1374 if( !isActiveFootprint )
1380 targetDnp = variant.
m_hasDnp ? variant.
m_dnp : footprint->IsDNP();
1383 bool currentDnp = currentVariant ? currentVariant->
GetDNP() : footprint->IsDNP();
1385 if( currentDnp != targetDnp )
1391 msg.Printf( targetDnp ?
_(
"Add %s:%s 'Do not place' variant attribute." )
1392 :
_(
"Remove %s:%s 'Do not place' variant attribute." ),
1393 footprint->GetReference(),
info.name );
1397 msg.Printf( targetDnp ?
_(
"Added %s:%s 'Do not place' variant attribute." )
1398 :
_(
"Removed %s:%s 'Do not place' variant attribute." ),
1399 footprint->GetReference(),
info.name );
1404 fpVariant->
SetDNP( targetDnp );
1413 : footprint->IsExcludedFromBOM();
1415 : footprint->IsExcludedFromBOM();
1417 if( currentExcludedFromBOM != targetExcludedFromBOM )
1423 msg.Printf( targetExcludedFromBOM
1424 ?
_(
"Add %s:%s 'exclude from BOM' variant attribute." )
1425 :
_(
"Remove %s:%s 'exclude from BOM' variant attribute." ),
1426 footprint->GetReference(),
info.name );
1430 msg.Printf( targetExcludedFromBOM
1431 ?
_(
"Added %s:%s 'exclude from BOM' variant attribute." )
1432 :
_(
"Removed %s:%s 'exclude from BOM' variant attribute." ),
1433 footprint->GetReference(),
info.name );
1447 : footprint->IsExcludedFromPosFiles();
1448 bool currentExcludedFromPosFiles = currentVariant
1450 : footprint->IsExcludedFromPosFiles();
1452 if( currentExcludedFromPosFiles != targetExcludedFromPosFiles )
1458 msg.Printf( targetExcludedFromPosFiles
1459 ?
_(
"Add %s:%s 'exclude from position files' variant attribute." )
1460 :
_(
"Remove %s:%s 'exclude from position files' variant attribute." ),
1461 footprint->GetReference(),
info.name );
1465 msg.Printf( targetExcludedFromPosFiles
1466 ?
_(
"Added %s:%s 'exclude from position files' variant attribute." )
1467 :
_(
"Removed %s:%s 'exclude from position files' variant attribute." ),
1468 footprint->GetReference(),
info.name );
1480 for(
const auto& [fieldName, fieldValue] : variant.
m_fields )
1482 if( fieldName.CmpNoCase( footprintFieldName ) == 0 )
1485 bool hasCurrentValue = currentVariant && currentVariant->
HasFieldValue( fieldName );
1486 wxString currentValue = hasCurrentValue ? currentVariant->
GetFieldValue( fieldName )
1489 if( currentValue != fieldValue )
1495 msg.Printf(
_(
"Change %s:%s field '%s' to '%s'." ),
1496 footprint->GetReference(),
info.name, fieldName, fieldValue );
1500 msg.Printf(
_(
"Changed %s:%s field '%s' to '%s'." ),
1501 footprint->GetReference(),
info.name, fieldName, fieldValue );
1517 bool isBaseFootprint = ( footprint->GetFPID() == aBaseFpid );
1519 if( !isBaseFootprint && !footprint->IsDNP() )
1522 msg.Printf(
m_isDryRun ?
_(
"Add %s 'Do not place' fabrication attribute." )
1523 :
_(
"Added %s 'Do not place' fabrication attribute." ),
1524 footprint->GetReference() );
1529 footprint->SetDNP(
true );
1546 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1557 std::set<wxString> netlistNetnames;
1559 for(
int ii = 0; ii < (int) aNetlist.
GetCount(); ii++ )
1563 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1575 if( netlistNetnames.count(
via->GetNetname() ) == 0 )
1577 wxString updatedNetname = wxEmptyString;
1586 if( !updatedNetname.IsEmpty() )
1590 wxString originalNetname =
via->GetNetname();
1592 msg.Printf(
_(
"Reconnect via from %s to %s." ),
1607 wxString originalNetname =
via->GetNetname();
1610 via->SetNet( netinfo );
1612 msg.Printf(
_(
"Reconnected via from %s to %s." ),
1622 msg.Printf(
_(
"Via connected to unknown net (%s)." ),
1634 auto isInNetlist = [&](
const wxString& aNetName ) ->
bool
1636 if( netlistNetnames.count( aNetName ) )
1641 for(
const wxString& netName : netlistNetnames )
1643 if( aNetName.StartsWith( netName ) )
1653 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1656 if( !isInNetlist( zone->GetNetname() ) )
1661 wxString updatedNetname = wxEmptyString;
1674 if( updatedNetname.IsEmpty() &&
m_oldToNewNets.count( zone->GetNetname() ) )
1679 if( !updatedNetname.IsEmpty() )
1683 wxString originalNetname = zone->GetNetname();
1685 if( !zone->GetZoneName().IsEmpty() )
1687 msg.Printf(
_(
"Reconnect copper zone '%s' from %s to %s." ),
1688 zone->GetZoneName(),
1694 msg.Printf(
_(
"Reconnect copper zone from %s to %s." ),
1710 wxString originalNetname = zone->GetNetname();
1713 zone->SetNet( netinfo );
1715 if( !zone->GetZoneName().IsEmpty() )
1717 msg.Printf(
_(
"Reconnected copper zone '%s' from %s to %s." ),
1724 msg.Printf(
_(
"Reconnected copper zone from %s to %s." ),
1735 if( !zone->GetZoneName().IsEmpty() )
1737 msg.Printf(
_(
"Copper zone '%s' has no pads connected." ),
1742 wxString layerNames = zone->LayerMaskDescribe();
1747 if(
m_frame->GetPcbNewSettings()->m_Display.m_DisplayInvertXAxis )
1750 if(
m_frame->GetPcbNewSettings()->m_Display.m_DisplayInvertYAxis )
1754 msg.Printf(
_(
"Copper zone on %s at (%s, %s) has no pads connected to net \"%s\"." ),
1760 zone->GetNetname() );
1784 if( netlistGroup ==
nullptr )
1787 if( netlistGroup->
name != pcbGroup->GetName() )
1791 msg.Printf(
_(
"Change group name from '%s' to '%s'." ),
1797 msg.Printf(
_(
"Changed group name from '%s' to '%s'." ),
1801 pcbGroup->SetName( netlistGroup->
name );
1807 if( netlistGroup->
libId != pcbGroup->GetDesignBlockLibId() )
1811 msg.Printf(
_(
"Change group library link from '%s' to '%s'." ),
1812 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1817 msg.Printf(
_(
"Changed group library link from '%s' to '%s'." ),
1818 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1821 pcbGroup->SetDesignBlockLibId( netlistGroup->
libId );
1833 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
1841 for(
int i = 0; i < (int) aNetlist.
GetCount(); i++ )
1844 FOOTPRINT* footprint = aFootprintMap[component];
1850 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1854 if( padNumber.IsEmpty() )
1857 msg.Printf(
_(
"Symbol %s has pins with no number. These pins can not be matched "
1867 msg.Printf(
_(
"%s pad %s not found in %s." ),
1883 FOOTPRINT* lastPreexistingFootprint =
nullptr;
1886 std::unordered_set<wxString> sheetPaths;
1887 std::unordered_set<FOOTPRINT*> usedFootprints;
1893 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
1895 if( !
m_board->Footprints().empty() )
1896 lastPreexistingFootprint =
m_board->Footprints().back();
1906 net->SetIsCurrent( net->GetNetCode() == 0 );
1908 m_board->GetComponentClassManager().InitNetlistUpdate();
1914 for(
unsigned i = 0; i < aNetlist.
GetCount(); i++ )
1918 if( component->
GetProperties().count( wxT(
"exclude_from_board" ) ) )
1921 msg.Printf(
_(
"Processing symbol '%s:%s'." ),
1927 const bool hasBaseFpid = !baseFpid.
empty();
1931 msg.Printf(
_(
"Warning: %s footprint '%s' is missing a library name. "
1932 "Use the full 'Library:Footprint' format to avoid repeated update "
1940 std::vector<FOOTPRINT*> matchingFootprints;
1951 base.push_back( uuid );
1953 if( footprint->GetPath() == base )
1962 match = footprint->GetReference().CmpNoCase( component->
GetReference() ) == 0;
1966 matchingFootprints.push_back( footprint );
1968 if( footprint == lastPreexistingFootprint )
1975 std::vector<LIB_ID> expectedFpids;
1976 std::unordered_set<wxString> expectedFpidKeys;
1978 auto addExpectedFpid =
1979 [&](
const LIB_ID& aFpid )
1984 wxString key = aFpid.Format();
1986 if( expectedFpidKeys.insert( key ).second )
1987 expectedFpids.push_back( aFpid );
1990 addExpectedFpid( baseFpid );
1994 for(
const auto& [variantName, variant] : component->
GetVariants() )
1996 auto fieldIt = variant.m_fields.find( footprintFieldName );
1998 if( fieldIt == variant.m_fields.end() || fieldIt->second.IsEmpty() )
2003 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
2005 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
2014 addExpectedFpid( parsedId );
2022 [&](
const LIB_ID& aBoardFpid,
const LIB_ID& aExpectedFpid ) ->
bool
2024 if( aExpectedFpid.IsLegacy() )
2025 return aBoardFpid.
GetLibItemName() == aExpectedFpid.GetLibItemName();
2027 return aBoardFpid == aExpectedFpid;
2030 auto isExpectedFpid =
2031 [&](
const LIB_ID& aFpid ) ->
bool
2036 if( expectedFpidKeys.count( aFpid.Format() ) > 0 )
2041 if( fpidMatches( aFpid,
expected ) )
2048 auto takeMatchingFootprint =
2051 for(
FOOTPRINT* footprint : matchingFootprints )
2053 if( usedFootprints.count( footprint ) )
2056 if( fpidMatches( footprint->GetFPID(), aFpid ) )
2063 std::vector<FOOTPRINT*> componentFootprints;
2064 componentFootprints.reserve( expectedFpids.size() );
2068 baseFootprint = takeMatchingFootprint( baseFpid );
2069 else if( !matchingFootprints.empty() )
2070 baseFootprint = matchingFootprints.front();
2076 for(
FOOTPRINT* footprint : matchingFootprints )
2078 if( usedFootprints.count( footprint ) )
2081 if( isExpectedFpid( footprint->GetFPID() ) )
2084 replaceCandidate = footprint;
2088 if( replaceCandidate )
2093 baseFootprint = replaced;
2095 baseFootprint = replaceCandidate;
2099 if( !baseFootprint && hasBaseFpid )
2104 componentFootprints.push_back( baseFootprint );
2105 usedFootprints.insert( baseFootprint );
2106 footprintMap[ component ] = baseFootprint;
2109 for(
const LIB_ID& fpid : expectedFpids )
2111 if( fpid == baseFpid )
2114 FOOTPRINT* footprint = takeMatchingFootprint( fpid );
2121 componentFootprints.push_back( footprint );
2122 usedFootprints.insert( footprint );
2126 for(
FOOTPRINT* footprint : componentFootprints )
2137 sheetPaths.insert( footprint->GetSheetname() );
2140 if( !componentFootprints.empty() )
2152 bool matched =
false;
2158 bool isStaleVariantFootprint =
false;
2160 if( usedFootprints.count( footprint ) )
2171 if( component && component->
GetProperties().count( wxT(
"exclude_from_board" ) ) == 0 )
2179 isStaleVariantFootprint =
true;
2190 if( isStaleVariantFootprint )
2193 if( doDelete && !matched && footprint->IsLocked() && !
m_overrideLocks )
2197 msg.Printf(
_(
"Cannot remove unused footprint %s (footprint is locked)." ),
2198 footprint->GetReference() );
2202 msg.Printf(
_(
"Could not remove unused footprint %s (footprint is locked)." ),
2203 footprint->GetReference() );
2211 if( doDelete && !matched )
2215 msg.Printf(
_(
"Remove unused footprint %s." ),
2216 footprint->GetReference() );
2221 msg.Printf(
_(
"Removed unused footprint %s." ),
2222 footprint->GetReference() );
2232 for(
PAD*
pad : footprint->Pads() )
2235 pad->GetNet()->SetIsCurrent(
true );
2243 m_board->GetComponentClassManager().FinishNetlistUpdate();
2244 m_board->SynchronizeComponentClasses( sheetPaths );
2251 if( !net->IsCurrent() )
2253 msg.Printf(
_(
"Removed unused net %s." ),
2262 const std::vector<wxString>& netlistVariants = aNetlist.
GetVariantNames();
2264 if( !netlistVariants.empty() || !
m_board->GetVariantNames().empty() )
2268 auto findBoardVariantName =
2269 [&](
const wxString& aVariantName ) -> wxString
2271 for(
const wxString&
name :
m_board->GetVariantNames() )
2273 if(
name.CmpNoCase( aVariantName ) == 0 )
2277 return wxEmptyString;
2280 std::vector<wxString> updatedVariantNames;
2281 updatedVariantNames.reserve( netlistVariants.size() );
2283 for(
const wxString& variantName : netlistVariants )
2285 wxString actualName = findBoardVariantName( variantName );
2287 if( actualName.IsEmpty() )
2289 m_board->AddVariant( variantName );
2290 actualName = findBoardVariantName( variantName );
2292 if( !actualName.IsEmpty() )
2294 msg.Printf(
_(
"Added variant '%s'." ), actualName );
2299 if( actualName.IsEmpty() )
2304 wxString oldDescription =
m_board->GetVariantDescription( actualName );
2306 if( newDescription != oldDescription )
2308 m_board->SetVariantDescription( actualName, newDescription );
2309 msg.Printf(
_(
"Updated description for variant '%s'." ), actualName );
2313 updatedVariantNames.push_back( actualName );
2316 std::vector<wxString> variantsToRemove;
2318 for(
const wxString& existingName :
m_board->GetVariantNames() )
2322 for(
const wxString& variantName : netlistVariants )
2324 if( existingName.CmpNoCase( variantName ) == 0 )
2332 variantsToRemove.push_back( existingName );
2335 for(
const wxString& variantName : variantsToRemove )
2337 m_board->DeleteVariant( variantName );
2338 msg.Printf(
_(
"Removed variant '%s'." ), variantName );
2342 if( !updatedVariantNames.empty() )
2343 m_board->SetVariantNames( updatedVariantNames );
2353 m_board->SynchronizeNetsAndNetClasses(
true );
2364 for(
const std::pair<const wxString, NETINFO_ITEM*>& addedNet :
m_addedNets )
2365 delete addedNet.second;
constexpr EDA_IU_SCALE pcbIUScale
wxString GetNetname() const
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
std::map< PAD *, wxString > m_padNets
bool m_deleteUnusedFootprints
void cacheNetname(PAD *aPad, const wxString &aNetname)
bool UpdateNetlist(NETLIST &aNetlist)
Update the board's components according to the new netlist.
wxString getNetname(PAD *aPad)
wxString getPinFunction(PAD *aPad)
std::vector< FOOTPRINT * > m_addedFootprints
std::map< wxString, wxString > m_oldToNewNets
bool updateFootprintGroup(FOOTPRINT *aPcbFootprint, COMPONENT *aNetlistComponent)
bool updateFootprintParameters(FOOTPRINT *aPcbFootprint, COMPONENT *aNetlistComponent)
std::map< wxString, NETINFO_ITEM * > m_addedNets
bool testConnectivity(NETLIST &aNetlist, std::map< COMPONENT *, FOOTPRINT * > &aFootprintMap)
bool updateCopperZoneNets(NETLIST &aNetlist)
void cachePinFunction(PAD *aPad, const wxString &aPinFunction)
bool updateGroups(NETLIST &aNetlist)
BOARD_NETLIST_UPDATER(PCB_EDIT_FRAME *aFrame, BOARD *aBoard)
bool updateComponentClass(FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
bool updateComponentPadConnections(FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
VECTOR2I estimateFootprintInsertionPosition()
std::map< PAD *, wxString > m_padPinFunctions
void applyComponentVariants(COMPONENT *aComponent, const std::vector< FOOTPRINT * > &aFootprints, const LIB_ID &aBaseFpid)
std::map< ZONE *, std::vector< PAD * > > m_zoneConnectionsCache
FOOTPRINT * replaceFootprint(NETLIST &aNetlist, FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
void cacheCopperZoneConnections()
bool updateComponentUnits(FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
FOOTPRINT * addNewFootprint(COMPONENT *aComponent)
Information pertinent to a Pcbnew printed circuit board.
constexpr size_type GetWidth() const
constexpr Vec Centre() const
constexpr size_type GetHeight() const
constexpr coord_type GetBottom() const
static wxString GetFullClassNameForConstituents(const std::unordered_set< wxString > &classNames)
Gets the full effective class name for the given set of constituent classes.
A lightweight representation of a component class.
const wxString & GetName() const
Fetches the full name of this component class.
Used to store the component pin name to net name (and pin function) associations stored in a netlist.
const wxString & GetNetName() const
const wxString & GetPinFunction() const
const wxString & GetPinName() const
const wxString & GetPinType() const
Store all of the related component information found in a netlist.
const std::vector< UNIT_INFO > & GetUnitInfo() const
const wxString & GetHumanReadablePath() const
const COMPONENT_NET & GetNet(unsigned aIndex) const
const KIID_PATH & GetPath() const
const wxString & GetReference() const
const wxString & GetValue() const
const nlohmann::ordered_map< wxString, wxString > & GetFields() const
const std::map< wxString, wxString > & GetProperties() const
const CASE_INSENSITIVE_MAP< COMPONENT_VARIANT > & GetVariants() const
NETLIST_GROUP * GetGroup() const
const std::vector< KIID > & GetKIIDs() const
bool GetDuplicatePadNumbersAreJumpers() const
const LIB_ID & GetFPID() const
unsigned GetNetCount() const
std::unordered_set< wxString > & GetComponentClassNames()
std::vector< std::set< wxString > > & JumperPadGroups()
void RemoveItem(EDA_ITEM *aItem)
Remove item from group.
void AddItem(EDA_ITEM *aItem)
Add item to group.
void SetName(const wxString &aName)
virtual EDA_GROUP * GetParentGroup() const
virtual void SetParent(EDA_ITEM *aParent)
virtual void SetVisible(bool aVisible)
virtual void SetText(const wxString &aText)
wxString AsString() const
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
wxString GetUniStringLibId() const
const UTF8 & GetLibItemName() const
Handle the data for a net.
void SetIsCurrent(bool isCurrent)
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
const std::vector< wxString > & GetVariantNames() const
unsigned GetCount() const
COMPONENT * GetComponentByPath(const KIID_PATH &aPath)
Return a COMPONENT by aPath.
COMPONENT * GetComponentByReference(const wxString &aReference)
Return a COMPONENT by aReference.
NETLIST_GROUP * GetGroupByUuid(const KIID &aUuid)
Return a NETLIST_GROUP by aUuid.
COMPONENT * GetComponent(unsigned aIndex)
Return the COMPONENT at aIndex.
wxString GetVariantDescription(const wxString &aVariantName) const
static REPORTER & GetInstance()
const wxString & GetPinFunction() const
The main frame for Pcbnew.
void SetName(const wxString &aName)
A set of BOARD_ITEMs (i.e., without duplicates).
EDA_ITEM * AsEdaItem() override
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
virtual void SetPosition(const VECTOR2I &aPos) override
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Handle a list of polygons defining a copper zone.
KICOMMON_API wxString MessageTextFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A helper to convert the double length aValue to a string in inches, millimeters, or unscaled units.
Class to handle a set of BOARD_ITEMs.
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
wxString UnescapeString(const wxString &aSource)
bool m_excludedFromPosFiles
bool m_hasExcludedFromBOM
bool m_hasExcludedFromPosFiles
nlohmann::ordered_map< wxString, wxString > m_fields
@ USER
The field ID hasn't been set yet; field is invalid.
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
wxString GetCanonicalFieldName(FIELD_T aFieldType)
VECTOR3I expected(15, 30, 45)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
VECTOR2< int32_t > VECTOR2I