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'." ),
951 if( existingGroup->
GetItems().size() < 2 )
962 if( newGroupKIID != 0 )
966 msg.Printf(
_(
"Add %s to group '%s'." ),
972 msg.Printf(
_(
"Added %s to group '%s'." ),
978 if( newGroup ==
nullptr )
981 const_cast<KIID&
>( newGroup->
m_Uuid ) = newGroupKIID;
994 newGroup->
AddItem( aPcbFootprint );
1000 if( changed &&
copy )
1020 copy->SetParentGroup(
nullptr );
1023 bool changed =
false;
1026 std::deque<PAD*> pads = aFootprint->
Pads();
1027 std::set<wxString> padNetnames;
1029 std::sort( pads.begin(), pads.end(),
1032 return a->m_Uuid < b->m_Uuid;
1039 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1040 wxT(
"Processing pad %s of component %s" ),
1044 wxString pinFunction;
1049 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1050 wxT(
" Found valid net: %s" ),
1057 wxLogTrace( wxT(
"NETLIST_UPDATE" ),
1058 wxT(
" No net found for pad %s" ),
1064 if(
pad->GetPinFunction() != pinFunction )
1067 pad->SetPinFunction( pinFunction );
1070 if(
pad->GetPinType() != pinType )
1073 pad->SetPinType( pinType );
1082 if( !net.
IsValid() || !
pad->IsOnCopperLayer() )
1084 if( !
pad->GetNetname().IsEmpty() )
1088 msg.Printf(
_(
"Disconnect %s pin %s." ),
1094 msg.Printf(
_(
"Disconnected %s pin %s." ),
1101 else if(
pad->IsOnCopperLayer() && !
pad->GetNumber().IsEmpty() )
1104 msg.Printf(
_(
"No net found for component %s pad %s (no pin %s in symbol)." ),
1119 if(
pad->GetNetname().IsEmpty() )
1120 pad->SetPinFunction( wxEmptyString );
1132 if(
pad->IsNoConnectPad() )
1134 netName = wxString::Format( wxS(
"%s" ), net.
GetNetName() );
1136 for(
int jj = 1; !padNetnames.insert( netName ).second; jj++ )
1138 netName = wxString::Format( wxS(
"%s_%d" ), net.
GetNetName(), jj );
1147 if(
pad->GetNetname() != netName )
1150 if( netinfo ==
nullptr )
1157 if( netinfo ==
nullptr )
1169 msg.Printf(
_(
"Add net %s." ),
1174 if( !
pad->GetNetname().IsEmpty() )
1180 msg.Printf(
_(
"Reconnect %s pin %s from %s to %s."),
1188 msg.Printf(
_(
"Reconnected %s pin %s from %s to %s."),
1199 msg.Printf(
_(
"Connect %s pin %s to %s."),
1206 msg.Printf(
_(
"Connected %s pin %s to %s."),
1218 pad->SetNet( netinfo );
1228 if( changed &&
copy )
1240 std::vector<FOOTPRINT::FP_UNIT_INFO> newUnits;
1243 newUnits.push_back( { u.m_unitName, u.m_pins } );
1245 const std::vector<FOOTPRINT::FP_UNIT_INFO>& curUnits = aFootprint->
GetUnitInfo();
1247 auto unitsEqual = [](
const std::vector<FOOTPRINT::FP_UNIT_INFO>& a,
1248 const std::vector<FOOTPRINT::FP_UNIT_INFO>& b )
1250 if( a.size() != b.size() )
1253 for(
size_t i = 0; i < a.size(); ++i )
1255 if( a[i].m_unitName != b[i].m_unitName )
1258 if( a[i].m_pins != b[i].m_pins )
1265 if( unitsEqual( curUnits, newUnits ) )
1272 msg.Printf(
_(
"Update %s unit metadata." ), aFootprint->
GetReference() );
1280 if( !
m_commit.GetStatus( aFootprint ) )
1283 copy->SetParentGroup(
nullptr );
1288 msg.Printf(
_(
"Updated %s unit metadata." ), aFootprint->
GetReference() );
1299 const std::vector<FOOTPRINT*>& aFootprints,
1300 const LIB_ID& aBaseFpid )
1304 if( variants.empty() )
1307 if( aBaseFpid.
empty() )
1319 std::vector<VARIANT_INFO> variantInfo;
1320 variantInfo.reserve( variants.size() );
1322 for(
const auto& [variantName, variant] : variants )
1324 LIB_ID activeFpid = aBaseFpid;
1326 auto fieldIt = variant.m_fields.find( footprintFieldName );
1328 if( fieldIt != variant.m_fields.end() && !fieldIt->second.IsEmpty() )
1332 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
1335 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
1344 activeFpid = parsedId;
1348 variantInfo.push_back( { variantName, &variant, activeFpid } );
1351 for(
FOOTPRINT* footprint : aFootprints )
1361 copy->SetParentGroup(
nullptr );
1364 bool changed =
false;
1366 for(
const VARIANT_INFO&
info : variantInfo )
1374 bool isActiveFootprint = ( footprint->GetFPID() ==
info.activeFpid );
1380 if( !isActiveFootprint )
1386 targetDnp = variant.
m_hasDnp ? variant.
m_dnp : footprint->IsDNP();
1389 bool currentDnp = currentVariant ? currentVariant->
GetDNP() : footprint->IsDNP();
1391 if( currentDnp != targetDnp )
1397 msg.Printf( targetDnp ?
_(
"Add %s:%s 'Do not place' variant attribute." )
1398 :
_(
"Remove %s:%s 'Do not place' variant attribute." ),
1399 footprint->GetReference(),
info.name );
1403 msg.Printf( targetDnp ?
_(
"Added %s:%s 'Do not place' variant attribute." )
1404 :
_(
"Removed %s:%s 'Do not place' variant attribute." ),
1405 footprint->GetReference(),
info.name );
1410 fpVariant->
SetDNP( targetDnp );
1419 : footprint->IsExcludedFromBOM();
1421 : footprint->IsExcludedFromBOM();
1423 if( currentExcludedFromBOM != targetExcludedFromBOM )
1429 msg.Printf( targetExcludedFromBOM
1430 ?
_(
"Add %s:%s 'exclude from BOM' variant attribute." )
1431 :
_(
"Remove %s:%s 'exclude from BOM' variant attribute." ),
1432 footprint->GetReference(),
info.name );
1436 msg.Printf( targetExcludedFromBOM
1437 ?
_(
"Added %s:%s 'exclude from BOM' variant attribute." )
1438 :
_(
"Removed %s:%s 'exclude from BOM' variant attribute." ),
1439 footprint->GetReference(),
info.name );
1453 : footprint->IsExcludedFromPosFiles();
1454 bool currentExcludedFromPosFiles = currentVariant
1456 : footprint->IsExcludedFromPosFiles();
1458 if( currentExcludedFromPosFiles != targetExcludedFromPosFiles )
1464 msg.Printf( targetExcludedFromPosFiles
1465 ?
_(
"Add %s:%s 'exclude from position files' variant attribute." )
1466 :
_(
"Remove %s:%s 'exclude from position files' variant attribute." ),
1467 footprint->GetReference(),
info.name );
1471 msg.Printf( targetExcludedFromPosFiles
1472 ?
_(
"Added %s:%s 'exclude from position files' variant attribute." )
1473 :
_(
"Removed %s:%s 'exclude from position files' variant attribute." ),
1474 footprint->GetReference(),
info.name );
1486 for(
const auto& [fieldName, fieldValue] : variant.
m_fields )
1488 if( fieldName.CmpNoCase( footprintFieldName ) == 0 )
1491 bool hasCurrentValue = currentVariant && currentVariant->
HasFieldValue( fieldName );
1492 wxString currentValue = hasCurrentValue ? currentVariant->
GetFieldValue( fieldName )
1495 if( currentValue != fieldValue )
1501 msg.Printf(
_(
"Change %s:%s field '%s' to '%s'." ),
1502 footprint->GetReference(),
info.name, fieldName, fieldValue );
1506 msg.Printf(
_(
"Changed %s:%s field '%s' to '%s'." ),
1507 footprint->GetReference(),
info.name, fieldName, fieldValue );
1523 bool isBaseFootprint = ( footprint->GetFPID() == aBaseFpid );
1525 if( !isBaseFootprint && !footprint->IsDNP() )
1528 msg.Printf(
m_isDryRun ?
_(
"Add %s 'Do not place' fabrication attribute." )
1529 :
_(
"Added %s 'Do not place' fabrication attribute." ),
1530 footprint->GetReference() );
1535 footprint->SetDNP(
true );
1552 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1563 std::set<wxString> netlistNetnames;
1565 for(
int ii = 0; ii < (int) aNetlist.
GetCount(); ii++ )
1569 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1581 if( netlistNetnames.count(
via->GetNetname() ) == 0 )
1583 wxString updatedNetname = wxEmptyString;
1592 if( !updatedNetname.IsEmpty() )
1596 wxString originalNetname =
via->GetNetname();
1598 msg.Printf(
_(
"Reconnect via from %s to %s." ),
1613 wxString originalNetname =
via->GetNetname();
1616 via->SetNet( netinfo );
1618 msg.Printf(
_(
"Reconnected via from %s to %s." ),
1628 msg.Printf(
_(
"Via connected to unknown net (%s)." ),
1640 auto isInNetlist = [&](
const wxString& aNetName ) ->
bool
1642 if( netlistNetnames.count( aNetName ) )
1647 for(
const wxString& netName : netlistNetnames )
1649 if( aNetName.StartsWith( netName ) )
1659 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1662 if( !isInNetlist( zone->GetNetname() ) )
1667 wxString updatedNetname = wxEmptyString;
1680 if( updatedNetname.IsEmpty() &&
m_oldToNewNets.count( zone->GetNetname() ) )
1685 if( !updatedNetname.IsEmpty() )
1689 wxString originalNetname = zone->GetNetname();
1691 if( !zone->GetZoneName().IsEmpty() )
1693 msg.Printf(
_(
"Reconnect copper zone '%s' from %s to %s." ),
1694 zone->GetZoneName(),
1700 msg.Printf(
_(
"Reconnect copper zone from %s to %s." ),
1716 wxString originalNetname = zone->GetNetname();
1719 zone->SetNet( netinfo );
1721 if( !zone->GetZoneName().IsEmpty() )
1723 msg.Printf(
_(
"Reconnected copper zone '%s' from %s to %s." ),
1730 msg.Printf(
_(
"Reconnected copper zone from %s to %s." ),
1741 if( !zone->GetZoneName().IsEmpty() )
1743 msg.Printf(
_(
"Copper zone '%s' has no pads connected." ),
1748 wxString layerNames = zone->LayerMaskDescribe();
1753 if(
m_frame->GetPcbNewSettings()->m_Display.m_DisplayInvertXAxis )
1756 if(
m_frame->GetPcbNewSettings()->m_Display.m_DisplayInvertYAxis )
1760 msg.Printf(
_(
"Copper zone on %s at (%s, %s) has no pads connected to net \"%s\"." ),
1766 zone->GetNetname() );
1790 if( netlistGroup ==
nullptr )
1793 if( netlistGroup->
name != pcbGroup->GetName() )
1797 msg.Printf(
_(
"Change group name from '%s' to '%s'." ),
1803 msg.Printf(
_(
"Changed group name from '%s' to '%s'." ),
1807 pcbGroup->SetName( netlistGroup->
name );
1813 if( netlistGroup->
libId != pcbGroup->GetDesignBlockLibId() )
1817 msg.Printf(
_(
"Change group library link from '%s' to '%s'." ),
1818 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1823 msg.Printf(
_(
"Changed group library link from '%s' to '%s'." ),
1824 EscapeHTML( pcbGroup->GetDesignBlockLibId().GetUniStringLibId() ),
1827 pcbGroup->SetDesignBlockLibId( netlistGroup->
libId );
1839 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
1847 for(
int i = 0; i < (int) aNetlist.
GetCount(); i++ )
1850 FOOTPRINT* footprint = aFootprintMap[component];
1856 for(
unsigned jj = 0; jj < component->
GetNetCount(); jj++ )
1860 if( padNumber.IsEmpty() )
1863 msg.Printf(
_(
"Symbol %s has pins with no number. These pins can not be matched "
1873 msg.Printf(
_(
"%s pad %s not found in %s." ),
1889 FOOTPRINT* lastPreexistingFootprint =
nullptr;
1892 std::unordered_set<wxString> sheetPaths;
1893 std::unordered_set<FOOTPRINT*> usedFootprints;
1899 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
1901 if( !
m_board->Footprints().empty() )
1902 lastPreexistingFootprint =
m_board->Footprints().back();
1912 net->SetIsCurrent( net->GetNetCode() == 0 );
1914 m_board->GetComponentClassManager().InitNetlistUpdate();
1920 for(
unsigned i = 0; i < aNetlist.
GetCount(); i++ )
1924 if( component->
GetProperties().count( wxT(
"exclude_from_board" ) ) )
1927 msg.Printf(
_(
"Processing symbol '%s:%s'." ),
1933 const bool hasBaseFpid = !baseFpid.
empty();
1937 msg.Printf(
_(
"Warning: %s footprint '%s' is missing a library name. "
1938 "Use the full 'Library:Footprint' format to avoid repeated update "
1946 std::vector<FOOTPRINT*> matchingFootprints;
1957 base.push_back( uuid );
1959 if( footprint->GetPath() == base )
1968 match = footprint->GetReference().CmpNoCase( component->
GetReference() ) == 0;
1972 matchingFootprints.push_back( footprint );
1974 if( footprint == lastPreexistingFootprint )
1981 std::vector<LIB_ID> expectedFpids;
1982 std::unordered_set<wxString> expectedFpidKeys;
1984 auto addExpectedFpid =
1985 [&](
const LIB_ID& aFpid )
1990 wxString key = aFpid.Format();
1992 if( expectedFpidKeys.insert( key ).second )
1993 expectedFpids.push_back( aFpid );
1996 addExpectedFpid( baseFpid );
2000 for(
const auto& [variantName, variant] : component->
GetVariants() )
2002 auto fieldIt = variant.m_fields.find( footprintFieldName );
2004 if( fieldIt == variant.m_fields.end() || fieldIt->second.IsEmpty() )
2009 if( parsedId.
Parse( fieldIt->second,
true ) >= 0 )
2011 msg.Printf(
_(
"Invalid footprint ID '%s' for variant '%s' on %s." ),
2020 addExpectedFpid( parsedId );
2028 [&](
const LIB_ID& aBoardFpid,
const LIB_ID& aExpectedFpid ) ->
bool
2030 if( aExpectedFpid.IsLegacy() )
2031 return aBoardFpid.
GetLibItemName() == aExpectedFpid.GetLibItemName();
2033 return aBoardFpid == aExpectedFpid;
2036 auto isExpectedFpid =
2037 [&](
const LIB_ID& aFpid ) ->
bool
2042 if( expectedFpidKeys.count( aFpid.Format() ) > 0 )
2047 if( fpidMatches( aFpid,
expected ) )
2054 auto takeMatchingFootprint =
2057 for(
FOOTPRINT* footprint : matchingFootprints )
2059 if( usedFootprints.count( footprint ) )
2062 if( fpidMatches( footprint->GetFPID(), aFpid ) )
2069 std::vector<FOOTPRINT*> componentFootprints;
2070 componentFootprints.reserve( expectedFpids.size() );
2074 baseFootprint = takeMatchingFootprint( baseFpid );
2075 else if( !matchingFootprints.empty() )
2076 baseFootprint = matchingFootprints.front();
2082 for(
FOOTPRINT* footprint : matchingFootprints )
2084 if( usedFootprints.count( footprint ) )
2087 if( isExpectedFpid( footprint->GetFPID() ) )
2090 replaceCandidate = footprint;
2094 if( replaceCandidate )
2099 baseFootprint = replaced;
2101 baseFootprint = replaceCandidate;
2105 if( !baseFootprint && hasBaseFpid )
2110 componentFootprints.push_back( baseFootprint );
2111 usedFootprints.insert( baseFootprint );
2112 footprintMap[ component ] = baseFootprint;
2115 for(
const LIB_ID& fpid : expectedFpids )
2117 if( fpid == baseFpid )
2120 FOOTPRINT* footprint = takeMatchingFootprint( fpid );
2127 componentFootprints.push_back( footprint );
2128 usedFootprints.insert( footprint );
2132 for(
FOOTPRINT* footprint : componentFootprints )
2143 sheetPaths.insert( footprint->GetSheetname() );
2146 if( !componentFootprints.empty() )
2158 bool matched =
false;
2164 bool isStaleVariantFootprint =
false;
2166 if( usedFootprints.count( footprint ) )
2177 if( component && component->
GetProperties().count( wxT(
"exclude_from_board" ) ) == 0 )
2185 isStaleVariantFootprint =
true;
2196 if( isStaleVariantFootprint )
2199 if( doDelete && !matched && footprint->IsLocked() && !
m_overrideLocks )
2203 msg.Printf(
_(
"Cannot remove unused footprint %s (footprint is locked)." ),
2204 footprint->GetReference() );
2208 msg.Printf(
_(
"Could not remove unused footprint %s (footprint is locked)." ),
2209 footprint->GetReference() );
2217 if( doDelete && !matched )
2221 msg.Printf(
_(
"Remove unused footprint %s." ),
2222 footprint->GetReference() );
2227 msg.Printf(
_(
"Removed unused footprint %s." ),
2228 footprint->GetReference() );
2238 for(
PAD*
pad : footprint->Pads() )
2241 pad->GetNet()->SetIsCurrent(
true );
2249 m_board->GetComponentClassManager().FinishNetlistUpdate();
2250 m_board->SynchronizeComponentClasses( sheetPaths );
2257 if( !net->IsCurrent() )
2259 msg.Printf(
_(
"Removed unused net %s." ),
2268 const std::vector<wxString>& netlistVariants = aNetlist.
GetVariantNames();
2270 if( !netlistVariants.empty() || !
m_board->GetVariantNames().empty() )
2274 auto findBoardVariantName =
2275 [&](
const wxString& aVariantName ) -> wxString
2277 for(
const wxString&
name :
m_board->GetVariantNames() )
2279 if(
name.CmpNoCase( aVariantName ) == 0 )
2283 return wxEmptyString;
2286 std::vector<wxString> updatedVariantNames;
2287 updatedVariantNames.reserve( netlistVariants.size() );
2289 for(
const wxString& variantName : netlistVariants )
2291 wxString actualName = findBoardVariantName( variantName );
2293 if( actualName.IsEmpty() )
2295 m_board->AddVariant( variantName );
2296 actualName = findBoardVariantName( variantName );
2298 if( !actualName.IsEmpty() )
2300 msg.Printf(
_(
"Added variant '%s'." ), actualName );
2305 if( actualName.IsEmpty() )
2310 wxString oldDescription =
m_board->GetVariantDescription( actualName );
2312 if( newDescription != oldDescription )
2314 m_board->SetVariantDescription( actualName, newDescription );
2315 msg.Printf(
_(
"Updated description for variant '%s'." ), actualName );
2319 updatedVariantNames.push_back( actualName );
2322 std::vector<wxString> variantsToRemove;
2324 for(
const wxString& existingName :
m_board->GetVariantNames() )
2328 for(
const wxString& variantName : netlistVariants )
2330 if( existingName.CmpNoCase( variantName ) == 0 )
2338 variantsToRemove.push_back( existingName );
2341 for(
const wxString& variantName : variantsToRemove )
2343 m_board->DeleteVariant( variantName );
2344 msg.Printf(
_(
"Removed variant '%s'." ), variantName );
2348 if( !updatedVariantNames.empty() )
2349 m_board->SetVariantNames( updatedVariantNames );
2359 m_board->SynchronizeNetsAndNetClasses(
true );
2370 for(
const std::pair<const wxString, NETINFO_ITEM*>& addedNet :
m_addedNets )
2371 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()
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)
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