From 7ce00e511b4460e28bb200764a99a7748324fb92 Mon Sep 17 00:00:00 2001 From: James J <13408010-JamesJCode@users.noreply.gitlab.com> Date: Fri, 26 Jul 2024 20:49:29 +0000 Subject: [PATCH] Multi-netclass support --- common/api/api_handler_common.cpp | 2 +- common/bitmap_info.cpp | 2 + common/dialogs/dialog_assign_netclass.cpp | 23 +- common/dialogs/panel_setup_netclasses.cpp | 347 ++-- .../dialogs/panel_setup_netclasses_base.cpp | 18 +- .../dialogs/panel_setup_netclasses_base.fbp | 172 +- common/dialogs/panel_setup_netclasses_base.h | 4 + common/netclass.cpp | 157 +- common/project/net_settings.cpp | 751 +++++++- common/widgets/wx_grid.cpp | 102 +- eeschema/connection_graph.cpp | 264 +-- eeschema/connection_graph.h | 6 +- eeschema/eeschema_config.cpp | 2 +- eeschema/erc/erc.cpp | 77 +- eeschema/erc/erc.h | 6 - eeschema/erc/erc_item.cpp | 12 - eeschema/erc/erc_item.h | 2 - eeschema/erc/erc_settings.h | 2 - eeschema/fields_grid_table.cpp | 4 +- eeschema/sch_edit_frame.cpp | 17 + eeschema/sch_file_versions.h | 3 +- eeschema/sch_io/altium/sch_io_altium.cpp | 4 +- eeschema/sch_item.cpp | 2 +- eeschema/sch_label.cpp | 2 +- include/bitmaps/bitmaps_list.h | 1 + include/dialogs/panel_setup_netclasses.h | 4 + include/netclass.h | 193 +- include/project/net_settings.h | 161 +- include/units_provider.h | 53 + include/widgets/grid_icon_text_helpers.h | 24 + include/widgets/wx_grid.h | 27 +- pcbnew/board.cpp | 18 +- pcbnew/board_connected_item.cpp | 8 +- pcbnew/board_connected_item.h | 5 + pcbnew/board_design_settings.cpp | 26 +- pcbnew/connectivity/connectivity_data.cpp | 21 +- pcbnew/connectivity/connectivity_data.h | 18 +- .../dialogs/dialog_global_edit_teardrops.cpp | 14 +- .../dialog_global_edit_tracks_and_vias.cpp | 14 +- pcbnew/dialogs/panel_setup_rules.cpp | 2 +- pcbnew/dialogs/panel_setup_rules_help.md | 5 + pcbnew/dialogs/panel_setup_rules_help_md.h | 5 + pcbnew/drc/drc_engine.cpp | 150 +- pcbnew/exporters/gerber_jobfile_writer.cpp | 8 +- pcbnew/footprint.cpp | 2 +- pcbnew/footprint_edit_frame.cpp | 2 +- pcbnew/footprint_viewer_frame.cpp | 2 +- pcbnew/footprint_wizard_frame.cpp | 2 +- pcbnew/netinfo_item.cpp | 6 +- .../netlist_reader/board_netlist_updater.cpp | 2 + pcbnew/netlist_reader/netlist.cpp | 15 + pcbnew/pcb_io/altium/altium_pcb.cpp | 11 +- .../cadstar/cadstar_pcb_archive_loader.cpp | 28 +- pcbnew/pcb_io/eagle/pcb_io_eagle.cpp | 14 +- .../pcb_io/easyeda/pcb_io_easyeda_plugin.cpp | 2 +- .../kicad_legacy/pcb_io_kicad_legacy.cpp | 13 +- .../kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp | 17 +- pcbnew/pcb_painter.cpp | 6 +- pcbnew/pcb_painter.h | 2 - pcbnew/pcbexpr_evaluator.cpp | 6 +- pcbnew/pcbexpr_functions.cpp | 45 +- pcbnew/pcbnew_config.cpp | 21 +- .../scripting/pcbnew_scripting_helpers.cpp | 2 +- pcbnew/python/swig/board.i | 4 +- pcbnew/python/swig/board_design_settings.i | 4 +- pcbnew/ratsnest/ratsnest_view_item.cpp | 34 +- pcbnew/ratsnest/ratsnest_view_item.h | 1 + pcbnew/router/pns_kicad_iface.cpp | 19 +- pcbnew/router/router_tool.cpp | 2 +- .../specctra_export.cpp | 18 +- .../specctra_import.cpp | 2 +- pcbnew/tools/board_editor_control.cpp | 12 +- pcbnew/tools/pcb_control.cpp | 2 +- pcbnew/widgets/appearance_controls.cpp | 54 +- ...RuleAreaNetclassConflictOnWire_1.kicad_sch | 376 ---- ...RuleAreaNetclassConflictOnWire_2.kicad_sch | 365 ---- qa/data/eeschema/RuleAreaNoOverlap.kicad_sch | 45 - .../RuleAreaOneNetclassDirective.kicad_sch | 327 ---- qa/data/eeschema/RuleAreaOneOverlap.kicad_sch | 43 - .../RuleAreaOneOverlapTwice.kicad_sch | 75 - .../RuleAreaThreeNetclassDirectives.kicad_sch | 373 ---- .../RuleAreaTwoNetclassDirectives.kicad_sch | 350 ---- .../eeschema/RuleAreaTwoOverlaps.kicad_sch | 58 - .../multinetclasses/multinetclasses.kicad_pro | 482 +++++ .../multinetclasses/multinetclasses.kicad_sch | 1628 +++++++++++++++++ qa/data/pcbnew/multinetclasses_drc.kicad_dru | 19 + qa/data/pcbnew/multinetclasses_drc.kicad_pcb | 1014 ++++++++++ qa/data/pcbnew/multinetclasses_drc.kicad_pro | 626 +++++++ qa/schematic_utils/eeschema_test_utils.cpp | 8 + qa/tests/eeschema/CMakeLists.txt | 1 - qa/tests/eeschema/erc/test_erc_rule_areas.cpp | 142 -- qa/tests/eeschema/test_sch_netclass.cpp | 34 + qa/tests/pcbnew/CMakeLists.txt | 1 + .../pcbnew/drc/test_drc_multi_netclasses.cpp | 110 ++ resources/bitmaps_png/CMakeLists.txt | 1 + resources/bitmaps_png/png/stroke_none.png | Bin 0 -> 268 bytes .../bitmaps_png/png/stroke_none_dark.png | Bin 0 -> 268 bytes .../bitmaps_png/sources/dark/stroke_none.svg | 68 + .../bitmaps_png/sources/light/stroke_none.svg | 68 + 99 files changed, 6298 insertions(+), 3004 deletions(-) delete mode 100644 qa/data/eeschema/RuleAreaNetclassConflictOnWire_1.kicad_sch delete mode 100644 qa/data/eeschema/RuleAreaNetclassConflictOnWire_2.kicad_sch delete mode 100644 qa/data/eeschema/RuleAreaNoOverlap.kicad_sch delete mode 100644 qa/data/eeschema/RuleAreaOneNetclassDirective.kicad_sch delete mode 100644 qa/data/eeschema/RuleAreaOneOverlap.kicad_sch delete mode 100644 qa/data/eeschema/RuleAreaOneOverlapTwice.kicad_sch delete mode 100644 qa/data/eeschema/RuleAreaThreeNetclassDirectives.kicad_sch delete mode 100644 qa/data/eeschema/RuleAreaTwoNetclassDirectives.kicad_sch delete mode 100644 qa/data/eeschema/RuleAreaTwoOverlaps.kicad_sch create mode 100644 qa/data/eeschema/netlists/multinetclasses/multinetclasses.kicad_pro create mode 100644 qa/data/eeschema/netlists/multinetclasses/multinetclasses.kicad_sch create mode 100644 qa/data/pcbnew/multinetclasses_drc.kicad_dru create mode 100644 qa/data/pcbnew/multinetclasses_drc.kicad_pcb create mode 100644 qa/data/pcbnew/multinetclasses_drc.kicad_pro delete mode 100644 qa/tests/eeschema/erc/test_erc_rule_areas.cpp create mode 100644 qa/tests/pcbnew/drc/test_drc_multi_netclasses.cpp create mode 100644 resources/bitmaps_png/png/stroke_none.png create mode 100644 resources/bitmaps_png/png/stroke_none_dark.png create mode 100644 resources/bitmaps_png/sources/dark/stroke_none.svg create mode 100644 resources/bitmaps_png/sources/light/stroke_none.svg diff --git a/common/api/api_handler_common.cpp b/common/api/api_handler_common.cpp index b0e961e744..75abab1a2b 100644 --- a/common/api/api_handler_common.cpp +++ b/common/api/api_handler_common.cpp @@ -67,7 +67,7 @@ HANDLER_RESULT API_HANDLER_COMMON::handleGetNetClasses( GetN std::shared_ptr& netSettings = Pgm().GetSettingsManager().Prj().GetProjectFile().m_NetSettings; - for( const auto& [name, netClass] : netSettings->m_NetClasses ) + for( const auto& [name, netClass] : netSettings->GetNetclasses() ) { reply.add_net_classes()->set_name( name.ToStdString() ); } diff --git a/common/bitmap_info.cpp b/common/bitmap_info.cpp index 8a9e0ed371..6f0ebbab78 100644 --- a/common/bitmap_info.cpp +++ b/common/bitmap_info.cpp @@ -4711,6 +4711,7 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::stroke_dashdotdot].emplace_back( BITMAPS::stroke_dashdotdot, wxT( "stroke_dashdotdot.png" ), -1, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::stroke_dot].emplace_back( BITMAPS::stroke_dot, wxT( "stroke_dot.png" ), -1, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::stroke_solid].emplace_back( BITMAPS::stroke_solid, wxT( "stroke_solid.png" ), -1, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::stroke_none].emplace_back( BITMAPS::stroke_none, wxT( "stroke_none.png" ), -1, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::twistedpair].emplace_back( BITMAPS::twistedpair, wxT( "twistedpair.png" ), -1, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::viacalc].emplace_back( BITMAPS::viacalc, wxT( "viacalc.png" ), -1, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::att_bridge].emplace_back( BITMAPS::att_bridge, wxT( "att_bridge_dark.png" ), -1, wxT( "dark" ) ); @@ -4745,6 +4746,7 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::stroke_dashdotdot].emplace_back( BITMAPS::stroke_dashdotdot, wxT( "stroke_dashdotdot_dark.png" ), -1, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::stroke_dot].emplace_back( BITMAPS::stroke_dot, wxT( "stroke_dot_dark.png" ), -1, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::stroke_solid].emplace_back( BITMAPS::stroke_solid, wxT( "stroke_solid_dark.png" ), -1, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::stroke_none].emplace_back( BITMAPS::stroke_none, wxT( "stroke_none_dark.png" ), -1, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::twistedpair].emplace_back( BITMAPS::twistedpair, wxT( "twistedpair_dark.png" ), -1, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::viacalc].emplace_back( BITMAPS::viacalc, wxT( "viacalc_dark.png" ), -1, wxT( "dark" ) ); diff --git a/common/dialogs/dialog_assign_netclass.cpp b/common/dialogs/dialog_assign_netclass.cpp index aa1791df0c..1d7e189c68 100644 --- a/common/dialogs/dialog_assign_netclass.cpp +++ b/common/dialogs/dialog_assign_netclass.cpp @@ -41,7 +41,7 @@ DIALOG_ASSIGN_NETCLASS::DIALOG_ASSIGN_NETCLASS( EDA_BASE_FRAME* aParent, const w m_netclassCtrl->Append( NETCLASS::Default ); - for( const auto& [ name, netclass ] : netSettings->m_NetClasses ) + for( const auto& [name, netclass] : netSettings->GetNetclasses() ) m_netclassCtrl->Append( name ); if( m_netclassCtrl->GetCount() > 1 ) @@ -69,25 +69,8 @@ bool DIALOG_ASSIGN_NETCLASS::TransferDataFromWindow() if( m_patternCtrl->GetValue().IsEmpty() ) return true; - // TODO: Rework when we support multiple netclass assignments - // Replace existing assignment if we have one - for( auto& assignment : netSettings->m_NetClassPatternAssignments ) - { - if( assignment.first->GetPattern() == m_patternCtrl->GetValue() ) - { - assignment.second = m_netclassCtrl->GetStringSelection(); - return true; - } - } - - // No assignment, add a new one - netSettings->m_NetClassPatternAssignments.push_back( - { - std::make_unique( m_patternCtrl->GetValue(), CTX_NETCLASS ), - m_netclassCtrl->GetStringSelection() - } ); - - netSettings->m_NetClassPatternAssignmentCache.clear(); + netSettings->SetNetclassPatternAssignment( m_patternCtrl->GetValue(), + m_netclassCtrl->GetStringSelection() ); return true; } diff --git a/common/dialogs/panel_setup_netclasses.cpp b/common/dialogs/panel_setup_netclasses.cpp index 575aacde71..41485a4d3f 100644 --- a/common/dialogs/panel_setup_netclasses.cpp +++ b/common/dialogs/panel_setup_netclasses.cpp @@ -24,6 +24,7 @@ */ #include +#include #include #include @@ -91,6 +92,8 @@ PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( wxWindow* aParentWindow, EDA_DRA g_lineStyleIcons.clear(); g_lineStyleNames.clear(); + g_lineStyleIcons.push_back( BITMAPS::stroke_none ); + g_lineStyleNames.push_back( _( "" ) ); g_lineStyleIcons.push_back( BITMAPS::stroke_solid ); g_lineStyleNames.push_back( _( "Solid" ) ); g_lineStyleIcons.push_back( BITMAPS::stroke_dash ); @@ -216,6 +219,9 @@ PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( wxWindow* aParentWindow, EDA_DRA m_addAssignmentButton->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) ); m_removeAssignmentButton->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) ); + m_moveUpButton->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) ); + m_moveDownButton->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) ); + // wxFormBuilder doesn't include this event... m_netclassGrid->Connect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( PANEL_SETUP_NETCLASSES::OnNetclassGridCellChanging ), @@ -242,7 +248,7 @@ PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( wxWindow* aParentWindow, EDA_DRA wxWindow* dialog = wxGetTopLevelParent( this ); wxWindow* topLevelFocus = wxGetTopLevelParent( wxWindow::FindFocus() ); - if( topLevelFocus == dialog && m_lastLoaded != m_netSettings->m_NetClasses ) + if( topLevelFocus == dialog && m_lastLoaded != m_netSettings->GetNetclasses() ) checkReload(); } } ); @@ -275,86 +281,94 @@ PANEL_SETUP_NETCLASSES::~PANEL_SETUP_NETCLASSES() void PANEL_SETUP_NETCLASSES::loadNetclasses() { - KIGFX::PCB_RENDER_SETTINGS* rs = nullptr; - - if( !m_isEEschema ) - { - rs = static_cast( - m_frame->GetCanvas()->GetView()->GetPainter()->GetSettings() ); - } - - int row = 0; - auto netclassToGridRow = - [&]( int aRow, const std::shared_ptr& nc, bool isDefault ) + [&]( int aRow, const NETCLASS* nc ) { m_netclassGrid->SetCellValue( aRow, GRID_NAME, nc->GetName() ); - m_netclassGrid->SetUnitValue( aRow, GRID_WIREWIDTH, nc->GetWireWidth() ); - m_netclassGrid->SetUnitValue( aRow, GRID_BUSWIDTH, nc->GetBusWidth() ); + m_netclassGrid->SetOptionalUnitValue( aRow, GRID_WIREWIDTH, + nc->GetWireWidthOpt() ); + m_netclassGrid->SetOptionalUnitValue( aRow, GRID_BUSWIDTH, + nc->GetBusWidthOpt() ); wxString colorAsString = nc->GetSchematicColor().ToCSSString(); m_netclassGrid->SetCellValue( aRow, GRID_SCHEMATIC_COLOR, colorAsString ); - int lineStyleIdx = std::max( 0, nc->GetLineStyle() ); - - if( lineStyleIdx >= (int) g_lineStyleNames.size() ) - lineStyleIdx = 0; - - m_netclassGrid->SetCellValue( aRow, GRID_LINESTYLE, g_lineStyleNames[lineStyleIdx] ); - m_netclassGrid->SetUnitValue( aRow, GRID_CLEARANCE, nc->GetClearance() ); - m_netclassGrid->SetUnitValue( aRow, GRID_TRACKSIZE, nc->GetTrackWidth() ); - m_netclassGrid->SetUnitValue( aRow, GRID_VIASIZE, nc->GetViaDiameter() ); - m_netclassGrid->SetUnitValue( aRow, GRID_VIADRILL, nc->GetViaDrill() ); - m_netclassGrid->SetUnitValue( aRow, GRID_uVIASIZE, nc->GetuViaDiameter() ); - m_netclassGrid->SetUnitValue( aRow, GRID_uVIADRILL, nc->GetuViaDrill() ); - m_netclassGrid->SetUnitValue( aRow, GRID_DIFF_PAIR_WIDTH, nc->GetDiffPairWidth() ); - m_netclassGrid->SetUnitValue( aRow, GRID_DIFF_PAIR_GAP, nc->GetDiffPairGap() ); - - colorAsString = KIGFX::COLOR4D( 0.0, 0.0, 0.0, 0.0 ).ToCSSString(); - - if( m_isEEschema ) - colorAsString = nc->GetPcbColor().ToCSSString(); - - if( rs ) + if( nc->HasLineStyle() ) { - std::map& netclassColors = rs->GetNetclassColorMap(); + int lineStyleIdx = std::max( 0, nc->GetLineStyle() ); - if( netclassColors.find( nc->GetName() ) != netclassColors.end() ) - colorAsString = netclassColors[nc->GetName()].ToCSSString(); + if( lineStyleIdx >= (int) g_lineStyleNames.size() + 1 ) + lineStyleIdx = 0; + + m_netclassGrid->SetCellValue( aRow, GRID_LINESTYLE, + g_lineStyleNames[lineStyleIdx + 1] ); + } + else + { + m_netclassGrid->SetCellValue( + aRow, GRID_LINESTYLE, + g_lineStyleNames[0] ); // line style in list } - if( isDefault ) - { - colorAsString = KIGFX::COLOR4D( 0.0, 0.0, 0.0, 0.0 ).ToCSSString(); - m_netclassGrid->SetReadOnly( aRow, GRID_PCB_COLOR ); - } + m_netclassGrid->SetOptionalUnitValue( aRow, GRID_CLEARANCE, nc->GetClearanceOpt() ); + m_netclassGrid->SetOptionalUnitValue( aRow, GRID_TRACKSIZE, nc->GetTrackWidthOpt() ); + m_netclassGrid->SetOptionalUnitValue( aRow, GRID_VIASIZE, nc->GetViaDiameterOpt() ); + m_netclassGrid->SetOptionalUnitValue( aRow, GRID_VIADRILL, nc->GetViaDrillOpt() ); + m_netclassGrid->SetOptionalUnitValue( aRow, GRID_uVIASIZE, nc->GetuViaDiameterOpt() ); + m_netclassGrid->SetOptionalUnitValue( aRow, GRID_uVIADRILL, nc->GetuViaDrillOpt() ); + m_netclassGrid->SetOptionalUnitValue( aRow, GRID_DIFF_PAIR_WIDTH, nc->GetDiffPairWidthOpt() ); + m_netclassGrid->SetOptionalUnitValue( aRow, GRID_DIFF_PAIR_GAP, nc->GetDiffPairGapOpt() ); + colorAsString = nc->GetPcbColor().ToCSSString(); m_netclassGrid->SetCellValue( aRow, GRID_PCB_COLOR, colorAsString ); + + if( nc->IsDefault() ) + { + m_netclassGrid->SetReadOnly( aRow, GRID_PCB_COLOR ); + m_netclassGrid->SetReadOnly( aRow, GRID_SCHEMATIC_COLOR ); + } + + setNetclassRowNullableEditors( aRow, nc->IsDefault() ); }; + // Get the netclasses sorted by priority + std::vector netclasses; + netclasses.reserve( m_netSettings->GetNetclasses().size() ); + + for( const auto& [name, netclass] : m_netSettings->GetNetclasses() ) + netclasses.push_back( netclass.get() ); + + std::sort( netclasses.begin(), netclasses.end(), + []( const NETCLASS* nc1, const NETCLASS* nc2 ) + { + return nc1->GetPriority() < nc2->GetPriority(); + } ); + + // Enter user-defined netclasses m_netclassGrid->ClearRows(); + m_netclassGrid->AppendRows( static_cast( netclasses.size() ) ); - // enter the Default NETCLASS. + int row = 0; + + for( const NETCLASS* nc : netclasses ) + netclassToGridRow( row++, nc ); + + // Enter the Default netclass. m_netclassGrid->AppendRows( 1 ); - netclassToGridRow( row++, m_netSettings->m_DefaultNetClass, true ); + netclassToGridRow( row, m_netSettings->GetDefaultNetclass().get() ); - // make the Default NETCLASS name read-only + // Make the Default netclass name read-only wxGridCellAttr* cellAttr = m_netclassGrid->GetOrCreateCellAttr( 0, GRID_NAME ); cellAttr->SetReadOnly(); cellAttr->DecRef(); - // enter other netclasses - m_netclassGrid->AppendRows( (int) m_netSettings->m_NetClasses.size() ); - - for( const auto& [ name, netclass ] : m_netSettings->m_NetClasses ) - netclassToGridRow( row++, netclass, false ); - m_assignmentGrid->ClearRows(); - m_assignmentGrid->AppendRows( m_netSettings->m_NetClassPatternAssignments.size() ); + m_assignmentGrid->AppendRows( m_netSettings->GetNetclassPatternAssignments().size() ); + row = 0; - for( const auto& [ matcher, netclassName ] : m_netSettings->m_NetClassPatternAssignments ) + for( const auto& [matcher, netclassName] : m_netSettings->GetNetclassPatternAssignments() ) { m_assignmentGrid->SetCellValue( row, 0, matcher->GetPattern() ); m_assignmentGrid->SetCellValue( row, 1, netclassName ); @@ -363,6 +377,37 @@ void PANEL_SETUP_NETCLASSES::loadNetclasses() } +void PANEL_SETUP_NETCLASSES::setNetclassRowNullableEditors( int aRowId, bool aIsDefault ) +{ + // Set nullable editors + auto setCellEditor = [this, aRowId, aIsDefault]( int aCol ) + { + GRID_CELL_MARK_AS_NULLABLE* cellEditor; + + if( aIsDefault ) + cellEditor = new GRID_CELL_MARK_AS_NULLABLE( false ); + else + cellEditor = new GRID_CELL_MARK_AS_NULLABLE( true ); + + wxGridCellAttr* attr = m_netclassGrid->GetOrCreateCellAttr( aRowId, aCol ); + attr->SetEditor( cellEditor ); + attr->DecRef(); + }; + + setCellEditor( GRID_WIREWIDTH ); + setCellEditor( GRID_BUSWIDTH ); + setCellEditor( GRID_CLEARANCE ); + setCellEditor( GRID_TRACKSIZE ); + setCellEditor( GRID_VIASIZE ); + setCellEditor( GRID_VIADRILL ); + setCellEditor( GRID_VIADRILL ); + setCellEditor( GRID_uVIASIZE ); + setCellEditor( GRID_uVIADRILL ); + setCellEditor( GRID_DIFF_PAIR_WIDTH ); + setCellEditor( GRID_DIFF_PAIR_GAP ); +} + + void PANEL_SETUP_NETCLASSES::checkReload() { // MUST update the ticker before calling IsOK (or we'll end up re-entering through the idle @@ -372,7 +417,7 @@ void PANEL_SETUP_NETCLASSES::checkReload() if( IsOK( m_parent, _( "The netclasses have been changed outside the Setup dialog.\n" "Do you wish to reload them?" ) ) ) { - m_lastLoaded = m_netSettings->m_NetClasses; + m_lastLoaded = m_netSettings->GetNetclasses(); loadNetclasses(); } } @@ -400,7 +445,7 @@ void PANEL_SETUP_NETCLASSES::onUnitsChanged( wxCommandEvent& aEvent ) bool PANEL_SETUP_NETCLASSES::TransferDataToWindow() { - m_lastLoaded = m_netSettings->m_NetClasses; + m_lastLoaded = m_netSettings->GetNetclasses(); m_lastCheckedTicker = m_frame->Prj().GetNetclassesTicker(); loadNetclasses(); @@ -435,80 +480,79 @@ bool PANEL_SETUP_NETCLASSES::TransferDataFromWindow() if( !Validate() ) return false; - int row = 0; - auto gridRowToNetclass = - [&]( int aRow, const std::shared_ptr& nc, bool isDefault ) + [&]( int aRow, const std::shared_ptr& nc ) { + if( nc->IsDefault() ) + nc->SetPriority( std::numeric_limits::max() ); + else + nc->SetPriority( aRow ); + nc->SetName( m_netclassGrid->GetCellValue( aRow, GRID_NAME ) ); - nc->SetWireWidth( m_netclassGrid->GetUnitValue( aRow, GRID_WIREWIDTH ) ); - nc->SetBusWidth( m_netclassGrid->GetUnitValue( aRow, GRID_BUSWIDTH ) ); - - wxString color = m_netclassGrid->GetCellValue( aRow, GRID_SCHEMATIC_COLOR ); - nc->SetSchematicColor( wxColour( color ) ); + nc->SetWireWidth( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_WIREWIDTH ) ); + nc->SetBusWidth( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_BUSWIDTH ) ); wxString lineStyle = m_netclassGrid->GetCellValue( aRow, GRID_LINESTYLE ); - nc->SetLineStyle( g_lineStyleNames.Index( lineStyle ) ); - wxASSERT_MSG( nc->GetLineStyle() >= 0, "Line style name not found." ); + int lineIdx = g_lineStyleNames.Index( lineStyle ); - nc->SetClearance( m_netclassGrid->GetUnitValue( aRow, GRID_CLEARANCE ) ); - nc->SetTrackWidth( m_netclassGrid->GetUnitValue( aRow, GRID_TRACKSIZE ) ); - nc->SetViaDiameter( m_netclassGrid->GetUnitValue( aRow, GRID_VIASIZE ) ); - nc->SetViaDrill( m_netclassGrid->GetUnitValue( aRow, GRID_VIADRILL ) ); - nc->SetuViaDiameter( m_netclassGrid->GetUnitValue( aRow, GRID_uVIASIZE ) ); - nc->SetuViaDrill( m_netclassGrid->GetUnitValue( aRow, GRID_uVIADRILL ) ); - nc->SetDiffPairWidth( m_netclassGrid->GetUnitValue( aRow, GRID_DIFF_PAIR_WIDTH ) ); - nc->SetDiffPairGap( m_netclassGrid->GetUnitValue( aRow, GRID_DIFF_PAIR_GAP ) ); + if( lineIdx == 0 ) + nc->SetLineStyle( std::optional() ); + else + nc->SetLineStyle( lineIdx - 1 ); - if( !isDefault ) + wxASSERT_MSG( lineIdx >= 0, "Line style name not found." ); + + nc->SetClearance( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_CLEARANCE ) ); + nc->SetTrackWidth( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_TRACKSIZE ) ); + nc->SetViaDiameter( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_VIASIZE ) ); + nc->SetViaDrill( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_VIADRILL ) ); + nc->SetuViaDiameter( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_uVIASIZE ) ); + nc->SetuViaDrill( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_uVIADRILL ) ); + nc->SetDiffPairWidth( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_DIFF_PAIR_WIDTH ) ); + nc->SetDiffPairGap( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_DIFF_PAIR_GAP ) ); + + if( !nc->IsDefault() ) { - color = m_netclassGrid->GetCellValue( aRow, GRID_PCB_COLOR ); + wxString color = m_netclassGrid->GetCellValue( aRow, GRID_PCB_COLOR ); KIGFX::COLOR4D newPcbColor( color ); if( newPcbColor != KIGFX::COLOR4D::UNSPECIFIED ) nc->SetPcbColor( newPcbColor ); + + color = m_netclassGrid->GetCellValue( aRow, GRID_SCHEMATIC_COLOR ); + KIGFX::COLOR4D newSchematicColor( color ); - if( !m_isEEschema ) - { - KIGFX::PCB_RENDER_SETTINGS* rs = static_cast( - m_frame->GetCanvas()->GetView()->GetPainter()->GetSettings() ); - std::map& netclassColors = rs->GetNetclassColorMap(); - - if( newPcbColor != COLOR4D::UNSPECIFIED ) - netclassColors[nc->GetName()] = newPcbColor; - else - netclassColors.erase( nc->GetName() ); - } + if( newSchematicColor != KIGFX::COLOR4D::UNSPECIFIED ) + nc->SetSchematicColor( newSchematicColor ); } }; - m_netSettings->m_NetClasses.clear(); + m_netSettings->ClearNetclasses(); // Copy the default NetClass: - gridRowToNetclass( row++, m_netSettings->m_DefaultNetClass, true ); + gridRowToNetclass( m_netclassGrid->GetNumberRows() - 1, m_netSettings->GetDefaultNetclass() ); // Copy other NetClasses: - for( row = 1; row < m_netclassGrid->GetNumberRows(); ++row ) + for( int row = 0; row < m_netclassGrid->GetNumberRows() - 1; ++row ) { - auto nc = std::make_shared( m_netclassGrid->GetCellValue( row, GRID_NAME ) ); - gridRowToNetclass( row, nc, false ); - m_netSettings->m_NetClasses[ nc->GetName() ] = nc; + auto nc = + std::make_shared( m_netclassGrid->GetCellValue( row, GRID_NAME ), false ); + gridRowToNetclass( row, nc ); + m_netSettings->SetNetclass( nc->GetName(), nc ); } - m_netSettings->m_NetClassPatternAssignments.clear(); + m_netSettings->ClearNetclassPatternAssignments(); + m_netSettings->ClearAllCaches(); - for( row = 0; row < m_assignmentGrid->GetNumberRows(); ++row ) + for( int row = 0; row < m_assignmentGrid->GetNumberRows(); ++row ) { wxString pattern = m_assignmentGrid->GetCellValue( row, 0 ); wxString netclass = m_assignmentGrid->GetCellValue( row, 1 ); - m_netSettings->m_NetClassPatternAssignments.push_back( - { std::make_unique( pattern, CTX_NETCLASS ), netclass } ); + m_netSettings->SetNetclassPatternAssignment( pattern, netclass ); } - m_netSettings->m_NetClassPatternAssignmentCache.clear(); - return true; } @@ -627,15 +671,19 @@ void PANEL_SETUP_NETCLASSES::OnAddNetclassClick( wxCommandEvent& event ) if( !m_netclassGrid->CommitPendingChanges() ) return; - int row = m_netclassGrid->GetNumberRows(); - m_netclassGrid->AppendRows(); + m_netclassGrid->InsertRows(); - // Copy values of the default class: - for( int col = 1; col < m_netclassGrid->GetNumberCols(); col++ ) - m_netclassGrid->SetCellValue( row, col, m_netclassGrid->GetCellValue( 0, col ) ); + // Set defaults where required + wxString colorAsString = KIGFX::COLOR4D::UNSPECIFIED.ToCSSString(); + m_netclassGrid->SetCellValue( 0, GRID_PCB_COLOR, colorAsString ); + m_netclassGrid->SetCellValue( 0, GRID_SCHEMATIC_COLOR, colorAsString ); + m_netclassGrid->SetCellValue( 0, GRID_LINESTYLE, g_lineStyleNames[0] ); - m_netclassGrid->MakeCellVisible( row, 0 ); - m_netclassGrid->SetGridCursor( row, 0 ); + // Set the row nullable editors + setNetclassRowNullableEditors( 0, false ); + + m_netclassGrid->MakeCellVisible( 0, 0 ); + m_netclassGrid->SetGridCursor( 0, 0 ); m_netclassGrid->EnableCellEditControl( true ); m_netclassGrid->ShowCellEditControl(); @@ -655,7 +703,7 @@ void PANEL_SETUP_NETCLASSES::OnRemoveNetclassClick( wxCommandEvent& event ) { return; } - else if( curRow == 0 ) + else if( curRow == m_netclassGrid->GetNumberRows() - 1 ) { wxWindow* topLevelParent = wxGetTopLevelParent( this ); @@ -720,7 +768,7 @@ void PANEL_SETUP_NETCLASSES::OnAddAssignmentClick( wxCommandEvent& event ) int row = m_assignmentGrid->GetNumberRows(); m_assignmentGrid->AppendRows(); - m_assignmentGrid->SetCellValue( row, 1, m_netSettings->m_DefaultNetClass->GetName() ); + m_assignmentGrid->SetCellValue( row, 1, m_netSettings->GetDefaultNetclass()->GetName() ); m_assignmentGrid->MakeCellVisible( row, 0 ); m_assignmentGrid->SetGridCursor( row, 0 ); @@ -752,7 +800,8 @@ void PANEL_SETUP_NETCLASSES::OnRemoveAssignmentClick( wxCommandEvent& event ) void PANEL_SETUP_NETCLASSES::OnImportColorsClick( wxCommandEvent& event ) { - std::map>& netclasses = m_netSettings->m_NetClasses; + const std::map>& netclasses = + m_netSettings->GetNetclasses(); for( int row = 1; row < m_netclassGrid->GetNumberRows(); ++row ) { @@ -760,7 +809,7 @@ void PANEL_SETUP_NETCLASSES::OnImportColorsClick( wxCommandEvent& event ) if( netclasses.find( netclassName ) != netclasses.end() ) { - const KIGFX::COLOR4D ncColor = netclasses[netclassName]->GetSchematicColor(); + const KIGFX::COLOR4D ncColor = netclasses.at( netclassName )->GetSchematicColor(); m_netclassGrid->SetCellValue( row, GRID_PCB_COLOR, ncColor.ToCSSString() ); } } @@ -882,3 +931,81 @@ void PANEL_SETUP_NETCLASSES::ImportSettingsFrom( const std::shared_ptrCommitPendingChanges() ) + return; + + // Work out which rows are selected + std::vector selectedRows; + + for( int i = 0; i < m_netclassGrid->GetNumberRows(); ++i ) + { + if( m_netclassGrid->IsInSelection( i, 0 ) ) + selectedRows.push_back( i ); + } + + // Only move one row at a time + if( selectedRows.size() != 1 ) + return; + + // Can't move the first netclass, nor move the Default netclass + if( selectedRows[0] == 0 || selectedRows[0] == ( m_netclassGrid->GetNumberRows() - 1 ) ) + return; + + int newRowId = selectedRows[0] - 1; + m_netclassGrid->InsertRows( newRowId ); + + for( int col = 0; col < m_netclassGrid->GetNumberCols(); col++ ) + m_netclassGrid->SetCellValue( newRowId, col, + m_netclassGrid->GetCellValue( newRowId + 2, col ) ); + + // Set the row nullable editors + setNetclassRowNullableEditors( newRowId, false ); + + m_netclassGrid->DeleteRows( newRowId + 2, 1 ); + m_netclassGrid->MakeCellVisible( newRowId, 0 ); + m_netclassGrid->SetGridCursor( newRowId, 0 ); + + m_netclassesDirty = true; +} + + +void PANEL_SETUP_NETCLASSES::OnMoveNetclassDownClick( wxCommandEvent& event ) +{ + if( !m_netclassGrid->CommitPendingChanges() ) + return; + + // Work out which rows are selected + std::vector selectedRows; + + for( int i = 0; i < m_netclassGrid->GetNumberRows(); ++i ) + { + if( m_netclassGrid->IsInSelection( i, 0 ) ) + selectedRows.push_back( i ); + } + + // Only move one row at a time + if( selectedRows.size() != 1 ) + return; + + // Can't move the last row down, nor move the Default netclass + if( selectedRows[0] == ( m_netclassGrid->GetNumberRows() - 2 ) + || selectedRows[0] == ( m_netclassGrid->GetNumberRows() - 1 ) ) + return; + + int newRowId = selectedRows[0] + 2; + m_netclassGrid->InsertRows( newRowId ); + + for( int col = 0; col < m_netclassGrid->GetNumberCols(); col++ ) + { + m_netclassGrid->SetCellValue( newRowId, col, + m_netclassGrid->GetCellValue( newRowId - 2, col ) ); + } + + m_netclassGrid->DeleteRows( newRowId - 2, 1 ); + m_netclassGrid->MakeCellVisible( newRowId - 1, 0 ); + m_netclassGrid->SetGridCursor( newRowId - 1, 0 ); + + m_netclassesDirty = true; +} diff --git a/common/dialogs/panel_setup_netclasses_base.cpp b/common/dialogs/panel_setup_netclasses_base.cpp index 39227d1af2..064bd7fa0f 100644 --- a/common/dialogs/panel_setup_netclasses_base.cpp +++ b/common/dialogs/panel_setup_netclasses_base.cpp @@ -87,7 +87,19 @@ PANEL_SETUP_NETCLASSES_BASE::PANEL_SETUP_NETCLASSES_BASE( wxWindow* parent, wxWi buttonBoxSizer->Add( 20, 0, 0, wxEXPAND, 5 ); m_removeButton = new STD_BITMAP_BUTTON( m_netclassesPane, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - buttonBoxSizer->Add( m_removeButton, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + buttonBoxSizer->Add( m_removeButton, 0, wxBOTTOM|wxLEFT, 5 ); + + + buttonBoxSizer->Add( 20, 0, 0, wxEXPAND, 5 ); + + m_moveUpButton = new STD_BITMAP_BUTTON( m_netclassesPane, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); + buttonBoxSizer->Add( m_moveUpButton, 0, wxBOTTOM|wxLEFT, 5 ); + + + buttonBoxSizer->Add( 20, 0, 0, wxEXPAND, 5 ); + + m_moveDownButton = new STD_BITMAP_BUTTON( m_netclassesPane, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); + buttonBoxSizer->Add( m_moveDownButton, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 ); buttonBoxSizer->Add( 60, 0, 1, wxEXPAND, 5 ); @@ -197,6 +209,8 @@ PANEL_SETUP_NETCLASSES_BASE::PANEL_SETUP_NETCLASSES_BASE( wxWindow* parent, wxWi m_netclassGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnSizeNetclassGrid ), NULL, this ); m_addButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnAddNetclassClick ), NULL, this ); m_removeButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnRemoveNetclassClick ), NULL, this ); + m_moveUpButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnMoveNetclassUpClick ), NULL, this ); + m_moveDownButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnMoveNetclassDownClick ), NULL, this ); m_importColorsButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnImportColorsClick ), NULL, this ); m_membershipPane->Connect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_NETCLASSES_BASE::onmembershipPanelSize ), NULL, this ); m_assignmentGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnSizeAssignmentGrid ), NULL, this ); @@ -212,6 +226,8 @@ PANEL_SETUP_NETCLASSES_BASE::~PANEL_SETUP_NETCLASSES_BASE() m_netclassGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnSizeNetclassGrid ), NULL, this ); m_addButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnAddNetclassClick ), NULL, this ); m_removeButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnRemoveNetclassClick ), NULL, this ); + m_moveUpButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnMoveNetclassUpClick ), NULL, this ); + m_moveDownButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnMoveNetclassDownClick ), NULL, this ); m_importColorsButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnImportColorsClick ), NULL, this ); m_membershipPane->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_NETCLASSES_BASE::onmembershipPanelSize ), NULL, this ); m_assignmentGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnSizeAssignmentGrid ), NULL, this ); diff --git a/common/dialogs/panel_setup_netclasses_base.fbp b/common/dialogs/panel_setup_netclasses_base.fbp index 23a95a3dbd..5788ab61f7 100644 --- a/common/dialogs/panel_setup_netclasses_base.fbp +++ b/common/dialogs/panel_setup_netclasses_base.fbp @@ -446,7 +446,7 @@ 5 - wxBOTTOM|wxRIGHT|wxLEFT + wxBOTTOM|wxLEFT 0 1 @@ -519,6 +519,176 @@ OnRemoveNetclassClick + + 5 + wxEXPAND + 0 + + 0 + protected + 20 + + + + 5 + wxBOTTOM|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Delete Net Class + + 0 + + 0 + + + 0 + -1,-1 + 1 + m_moveUpButton + 1 + + + protected + 1 + + + + Resizable + 1 + -1,-1 + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnMoveNetclassUpClick + + + + 5 + wxEXPAND + 0 + + 0 + protected + 20 + + + + 5 + wxBOTTOM|wxLEFT|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Delete Net Class + + 0 + + 0 + + + 0 + -1,-1 + 1 + m_moveDownButton + 1 + + + protected + 1 + + + + Resizable + 1 + -1,-1 + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnMoveNetclassDownClick + + 5 wxEXPAND diff --git a/common/dialogs/panel_setup_netclasses_base.h b/common/dialogs/panel_setup_netclasses_base.h index e963579ee8..ef75e6fe72 100644 --- a/common/dialogs/panel_setup_netclasses_base.h +++ b/common/dialogs/panel_setup_netclasses_base.h @@ -48,6 +48,8 @@ class PANEL_SETUP_NETCLASSES_BASE : public wxPanel WX_GRID* m_netclassGrid; STD_BITMAP_BUTTON* m_addButton; STD_BITMAP_BUTTON* m_removeButton; + STD_BITMAP_BUTTON* m_moveUpButton; + STD_BITMAP_BUTTON* m_moveDownButton; wxStaticText* m_colorDefaultHelpText; wxButton* m_importColorsButton; WX_PANEL* m_membershipPane; @@ -62,6 +64,8 @@ class PANEL_SETUP_NETCLASSES_BASE : public wxPanel virtual void OnSizeNetclassGrid( wxSizeEvent& event ) { event.Skip(); } virtual void OnAddNetclassClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnRemoveNetclassClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnMoveNetclassUpClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnMoveNetclassDownClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnImportColorsClick( wxCommandEvent& event ) { event.Skip(); } virtual void onmembershipPanelSize( wxSizeEvent& event ) { event.Skip(); } virtual void OnSizeAssignmentGrid( wxSizeEvent& event ) { event.Skip(); } diff --git a/common/netclass.cpp b/common/netclass.cpp index c9cd5b9a84..0c15ee47a3 100644 --- a/common/netclass.cpp +++ b/common/netclass.cpp @@ -23,6 +23,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#include #include #include #include @@ -44,35 +45,151 @@ const int DEFAULT_DIFF_PAIR_VIAGAP = pcbIUScale.mmToIU( 0.25 ); const int DEFAULT_WIRE_WIDTH = schIUScale.MilsToIU( 6 ); const int DEFAULT_BUS_WIDTH = schIUScale.MilsToIU( 12 ); -const int DEFAULT_LINE_STYLE = 0; // solid +const int DEFAULT_LINE_STYLE = 0; // solid -NETCLASS::NETCLASS( const wxString& aName ) : - m_Name( aName ), - m_PcbColor( KIGFX::COLOR4D::UNSPECIFIED ) +NETCLASS::NETCLASS( const wxString& aName, bool aInitWithDefaults ) : m_isDefault( false ) { - // Default settings - SetClearance( DEFAULT_CLEARANCE ); - SetViaDrill( DEFAULT_VIA_DRILL ); - SetuViaDrill( DEFAULT_UVIA_DRILL ); - // These defaults will be overwritten by SetParams, - // from the board design parameters, later - SetTrackWidth( DEFAULT_TRACK_WIDTH ); - SetViaDiameter( DEFAULT_VIA_DIAMETER ); - SetuViaDiameter( DEFAULT_UVIA_DIAMETER ); - SetDiffPairWidth( DEFAULT_DIFF_PAIR_WIDTH ); - SetDiffPairGap( DEFAULT_DIFF_PAIR_GAP ); - SetDiffPairViaGap( DEFAULT_DIFF_PAIR_VIAGAP ); + m_constituents.push_back( this ); - SetWireWidth( DEFAULT_WIRE_WIDTH ); - SetBusWidth( DEFAULT_BUS_WIDTH ); + SetName( aName ); + SetPriority( -1 ); + + // Colors are a special optional case - always set, but UNSPECIFIED used in place of optional + SetPcbColor( COLOR4D::UNSPECIFIED ); SetSchematicColor( COLOR4D::UNSPECIFIED ); - SetLineStyle( DEFAULT_LINE_STYLE ); + + if( aInitWithDefaults ) + { + SetClearance( DEFAULT_CLEARANCE ); + SetViaDrill( DEFAULT_VIA_DRILL ); + SetuViaDrill( DEFAULT_UVIA_DRILL ); + SetTrackWidth( DEFAULT_TRACK_WIDTH ); + SetViaDiameter( DEFAULT_VIA_DIAMETER ); + SetuViaDiameter( DEFAULT_UVIA_DIAMETER ); + SetDiffPairWidth( DEFAULT_DIFF_PAIR_WIDTH ); + SetDiffPairGap( DEFAULT_DIFF_PAIR_GAP ); + SetDiffPairViaGap( DEFAULT_DIFF_PAIR_VIAGAP ); + + SetWireWidth( DEFAULT_WIRE_WIDTH ); + SetBusWidth( DEFAULT_BUS_WIDTH ); + SetLineStyle( DEFAULT_LINE_STYLE ); + } + + ResetParents(); } -NETCLASS::~NETCLASS() +void NETCLASS::ResetParents() { + SetClearanceParent( this ); + SetTrackWidthParent( this ); + SetViaDiameterParent( this ); + SetViaDrillParent( this ); + SetuViaDiameterParent( this ); + SetuViaDrillParent( this ); + SetDiffPairWidthParent( this ); + SetDiffPairGapParent( this ); + SetDiffPairViaGapParent( this ); + SetPcbColorParent( this ); + SetWireWidthParent( this ); + SetBusWidthParent( this ); + SetSchematicColorParent( this ); + SetLineStyleParent( this ); } +void NETCLASS::ResetParameters() +{ + SetPcbColor( COLOR4D::UNSPECIFIED ); + SetSchematicColor( COLOR4D::UNSPECIFIED ); + SetClearance( std::optional() ); + SetViaDrill( std::optional() ); + SetuViaDrill( std::optional() ); + SetTrackWidth( std::optional() ); + SetViaDiameter( std::optional() ); + SetuViaDiameter( std::optional() ); + SetDiffPairWidth( std::optional() ); + SetDiffPairGap( std::optional() ); + SetDiffPairViaGap( std::optional() ); + SetWireWidth( std::optional() ); + SetBusWidth( std::optional() ); + SetLineStyle( std::optional() ); + + ResetParents(); +} + + +bool NETCLASS::operator==( const NETCLASS& other ) const +{ + return m_constituents == other.m_constituents; +} + + +const std::vector& NETCLASS::GetConstituentNetclasses() const +{ + return m_constituents; +} + + +void NETCLASS::SetConstituentNetclasses( std::vector&& constituents ) +{ + m_constituents = std::move( constituents ); +} + + +bool NETCLASS::ContainsNetclassWithName( const wxString& netclass ) const +{ + return std::any_of( m_constituents.begin(), m_constituents.end(), + [&netclass]( const NETCLASS* nc ) + { + return nc->GetName() == netclass; + } ); +} + + +const wxString NETCLASS::GetName() const +{ + if( m_constituents.size() == 1 ) + return m_Name; + + wxASSERT( m_constituents.size() >= 2 ); + + wxString name; + + if( m_constituents.size() == 2 ) + { + name.Printf( _( "%s and %s" ), m_constituents[0]->GetName(), m_constituents[1]->GetName() ); + } + else if( m_constituents.size() == 3 ) + { + name.Printf( _( "%s, %s and %s" ), m_constituents[0]->GetName(), + m_constituents[1]->GetName(), m_constituents[2]->GetName() ); + } + else if( m_constituents.size() > 3 ) + { + name.Printf( _( "%s, %s and %d more" ), m_constituents[0]->GetName(), + m_constituents[1]->GetName(), static_cast( m_constituents.size() - 2 ) ); + } + + return name; +} + + +const wxString NETCLASS::GetVariableSubstitutionName() const +{ + if( m_constituents.size() == 1 ) + return m_Name; + + wxASSERT( m_constituents.size() >= 2 ); + + wxString name = m_constituents[0]->GetName(); + + for( std::size_t i = 1; i < m_constituents.size(); ++i ) + { + name += ","; + name += m_constituents[i]->GetName(); + } + + return name; +} diff --git a/common/project/net_settings.cpp b/common/project/net_settings.cpp index 343745140f..a91def2634 100644 --- a/common/project/net_settings.cpp +++ b/common/project/net_settings.cpp @@ -19,6 +19,9 @@ * with this program. If not, see . */ +#include +#include + #include #include @@ -31,7 +34,8 @@ // const int netSettingsSchemaVersion = 0; // const int netSettingsSchemaVersion = 1; // new overbar syntax // const int netSettingsSchemaVersion = 2; // exclude buses from netclass members -const int netSettingsSchemaVersion = 3; // netclass assignment patterns +// const int netSettingsSchemaVersion = 3; // netclass assignment patterns +const int netSettingsSchemaVersion = 4; // netclass ordering static std::optional getInPcbUnits( const nlohmann::json& aObj, const std::string& aKey, @@ -44,7 +48,8 @@ static std::optional getInPcbUnits( const nlohmann::json& aObj, const std:: }; -static int getInSchUnits( const nlohmann::json& aObj, const std::string& aKey, int aDefault ) +static std::optional getInSchUnits( const nlohmann::json& aObj, const std::string& aKey, + std::optional aDefault = std::optional() ) { if( aObj.contains( aKey ) && aObj[aKey].is_number() ) return schIUScale.MilsToIU( aObj[aKey].get() ); @@ -56,22 +61,18 @@ static int getInSchUnits( const nlohmann::json& aObj, const std::string& aKey, i NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : NESTED_SETTINGS( "net_settings", netSettingsSchemaVersion, aParent, aPath, false ) { - m_DefaultNetClass = std::make_shared( NETCLASS::Default ); - m_DefaultNetClass->SetDescription( _( "This is the default net class." ) ); + m_defaultNetClass = std::make_shared( NETCLASS::Default, true ); + m_defaultNetClass->SetDescription( _( "This is the default net class." ) ); auto saveNetclass = []( nlohmann::json& json_array, const std::shared_ptr& nc ) { // Note: we're in common/, but we do happen to know which of these // fields are used in which units system. - nlohmann::json nc_json = { - { "name", nc->GetName().ToUTF8() }, - { "wire_width", schIUScale.IUToMils( nc->GetWireWidth() ) }, - { "bus_width", schIUScale.IUToMils( nc->GetBusWidth() ) }, - { "line_style", nc->GetLineStyle() }, - { "schematic_color", nc->GetSchematicColor() }, - { "pcb_color", nc->GetPcbColor() } - }; + nlohmann::json nc_json = { { "name", nc->GetName().ToUTF8() }, + { "priority", nc->GetPriority() }, + { "schematic_color", nc->GetSchematicColor( true ) }, + { "pcb_color", nc->GetPcbColor( true ) } }; auto saveInPcbUnits = []( nlohmann::json& json, const std::string& aKey, int aValue ) @@ -79,6 +80,16 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : json.push_back( { aKey, pcbIUScale.IUTomm( aValue ) } ); }; + if( nc->HasWireWidth() ) + nc_json.push_back( + { "wire_width", schIUScale.IUToMils( nc->GetWireWidth() ) } ); + + if( nc->HasBusWidth() ) + nc_json.push_back( { "bus_width", schIUScale.IUToMils( nc->GetBusWidth() ) } ); + + if( nc->HasLineStyle() ) + nc_json.push_back( { "line_style", nc->GetLineStyle() } ); + if( nc->HasClearance() ) saveInPcbUnits( nc_json, "clearance", nc->GetClearance() ); @@ -114,7 +125,10 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : { wxString name = entry["name"]; - std::shared_ptr nc = std::make_shared( name ); + std::shared_ptr nc = std::make_shared( name, false ); + + int priority = entry["priority"]; + nc->SetPriority( priority ); if( auto value = getInPcbUnits( entry, "clearance" ) ) nc->SetClearance( *value ); @@ -143,8 +157,11 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : if( auto value = getInPcbUnits( entry, "diff_pair_via_gap" ) ) nc->SetDiffPairViaGap( *value ); - nc->SetWireWidth( getInSchUnits( entry, "wire_width", nc->GetWireWidth() ) ); - nc->SetBusWidth( getInSchUnits( entry, "bus_width", nc->GetBusWidth() ) ); + if( auto value = getInSchUnits( entry, "wire_width" ) ) + nc->SetWireWidth( *value ); + + if( auto value = getInSchUnits( entry, "bus_width" ) ) + nc->SetBusWidth( *value ); if( entry.contains( "line_style" ) && entry["line_style"].is_number() ) nc->SetLineStyle( entry["line_style"].get() ); @@ -166,10 +183,10 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : { nlohmann::json ret = nlohmann::json::array(); - if( m_DefaultNetClass ) - saveNetclass( ret, m_DefaultNetClass ); + if( m_defaultNetClass ) + saveNetclass( ret, m_defaultNetClass ); - for( const auto& [ name, netclass ] : m_NetClasses ) + for( const auto& [name, netclass] : m_netClasses ) saveNetclass( ret, netclass ); return ret; @@ -179,7 +196,7 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : if( !aJson.is_array() ) return; - m_NetClasses.clear(); + m_netClasses.clear(); for( const nlohmann::json& entry : aJson ) { @@ -188,10 +205,10 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : std::shared_ptr nc = readNetClass( entry ); - if( nc->GetName() == NETCLASS::Default ) - m_DefaultNetClass = nc; + if( nc->IsDefault() ) + m_defaultNetClass = nc; else - m_NetClasses[ nc->GetName() ] = nc; + m_netClasses[nc->GetName()] = nc; } }, {} ) ); @@ -201,7 +218,7 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : { nlohmann::json ret = {}; - for( const auto& [ netname, color ] : m_NetColorAssignments ) + for( const auto& [netname, color] : m_netColorAssignments ) { std::string key( netname.ToUTF8() ); ret[ std::move( key ) ] = color; @@ -214,12 +231,12 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : if( !aJson.is_object() ) return; - m_NetColorAssignments.clear(); + m_netColorAssignments.clear(); for( const auto& pair : aJson.items() ) { wxString key( pair.key().c_str(), wxConvUTF8 ); - m_NetColorAssignments[ std::move( key ) ] = pair.value().get(); + m_netColorAssignments[std::move( key )] = pair.value().get(); } }, {} ) ); @@ -229,10 +246,18 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : { nlohmann::json ret = {}; - for( const auto& [ netname, netclassName ] : m_NetClassLabelAssignments ) + for( const auto& [netname, netclassNames] : m_netClassLabelAssignments ) { + nlohmann::json netclassesJson = nlohmann::json::array(); + + for( const auto& netclass : netclassNames ) + { + std::string netclassStr( netclass.ToUTF8() ); + netclassesJson.push_back( std::move( netclassStr ) ); + } + std::string key( netname.ToUTF8() ); - ret[ std::move( key ) ] = netclassName; + ret[std::move( key )] = netclassesJson; } return ret; @@ -242,12 +267,14 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : if( !aJson.is_object() ) return; - m_NetClassLabelAssignments.clear(); + m_netClassLabelAssignments.clear(); for( const auto& pair : aJson.items() ) { wxString key( pair.key().c_str(), wxConvUTF8 ); - m_NetClassLabelAssignments[ std::move( key ) ] = pair.value().get(); + + for( const auto& netclassName : pair.value() ) + m_netClassLabelAssignments[key].insert( netclassName.get() ); } }, {} ) ); @@ -257,7 +284,7 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : { nlohmann::json ret = nlohmann::json::array(); - for( const auto& [ matcher, netclassName ] : m_NetClassPatternAssignments ) + for( const auto& [matcher, netclassName] : m_netClassPatternAssignments ) { nlohmann::json pattern_json = { { "pattern", matcher->GetPattern().ToUTF8() }, @@ -274,7 +301,7 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : if( !aJson.is_array() ) return; - m_NetClassPatternAssignments.clear(); + m_netClassPatternAssignments.clear(); for( const nlohmann::json& entry : aJson ) { @@ -287,11 +314,9 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : wxString pattern = entry["pattern"].get(); wxString netclass = entry["netclass"].get(); - m_NetClassPatternAssignments.push_back( - { - std::make_unique( pattern, CTX_NETCLASS ), - netclass - } ); + m_netClassPatternAssignments.push_back( + { std::make_unique( pattern, CTX_NETCLASS ), + netclass } ); } } }, @@ -300,6 +325,7 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : registerMigration( 0, 1, std::bind( &NET_SETTINGS::migrateSchema0to1, this ) ); registerMigration( 1, 2, std::bind( &NET_SETTINGS::migrateSchema1to2, this ) ); registerMigration( 2, 3, std::bind( &NET_SETTINGS::migrateSchema2to3, this ) ); + registerMigration( 3, 4, std::bind( &NET_SETTINGS::migrateSchema3to4, this ) ); } @@ -316,23 +342,23 @@ NET_SETTINGS::~NET_SETTINGS() bool NET_SETTINGS::operator==( const NET_SETTINGS& aOther ) const { - if( !std::equal( std::begin( m_NetClasses ), std::end( m_NetClasses ), - std::begin( aOther.m_NetClasses ) ) ) + if( !std::equal( std::begin( m_netClasses ), std::end( m_netClasses ), + std::begin( aOther.m_netClasses ) ) ) return false; - if( !std::equal( std::begin( m_NetClassPatternAssignments ), - std::end( m_NetClassPatternAssignments ), - std::begin( aOther.m_NetClassPatternAssignments ) ) ) + if( !std::equal( std::begin( m_netClassPatternAssignments ), + std::end( m_netClassPatternAssignments ), + std::begin( aOther.m_netClassPatternAssignments ) ) ) return false; - if( !std::equal( std::begin( m_NetClassLabelAssignments ), - std::end( m_NetClassLabelAssignments ), - std::begin( aOther.m_NetClassLabelAssignments ) ) ) + if( !std::equal( std::begin( m_netClassLabelAssignments ), + std::end( m_netClassLabelAssignments ), + std::begin( aOther.m_netClassLabelAssignments ) ) ) return false; - if( !std::equal( std::begin( m_NetColorAssignments ), std::end( m_NetColorAssignments ), - std::begin( aOther.m_NetColorAssignments ) ) ) + if( !std::equal( std::begin( m_netColorAssignments ), std::end( m_netColorAssignments ), + std::begin( aOther.m_netColorAssignments ) ) ) return false; return true; @@ -400,53 +426,616 @@ bool NET_SETTINGS::migrateSchema2to3() } -std::shared_ptr NET_SETTINGS::GetEffectiveNetClass( const wxString& aNetName ) const +bool NET_SETTINGS::migrateSchema3to4() { - auto getNetclass = - [&]( const wxString& netclass ) - { - auto ii = m_NetClasses.find( netclass ); - - if( ii == m_NetClasses.end() ) - return m_DefaultNetClass; - else - return ii->second; - }; - - // is forced to be part of the Default netclass. - if( aNetName.IsEmpty() ) - return m_DefaultNetClass; - - auto it = m_NetClassLabelAssignments.find( aNetName ); - - if( it != m_NetClassLabelAssignments.end() ) - return getNetclass( it->second ); - - auto it2 = m_NetClassPatternAssignmentCache.find( aNetName ); - - if( it2 != m_NetClassPatternAssignmentCache.end() ) - return getNetclass( it2->second ); - - for( const auto& [ matcher, netclassName ] : m_NetClassPatternAssignments ) + // Add priority field to netclasses + if( m_internals->contains( "classes" ) && m_internals->At( "classes" ).is_array() ) { - if( matcher->StartsWith( aNetName ) ) + int priority = 0; + + for( auto& netClass : m_internals->At( "classes" ).items() ) { - m_NetClassPatternAssignmentCache[ aNetName ] = netclassName; - return getNetclass( netclassName ); + if( netClass.value()["name"].get() == NETCLASS::Default ) + netClass.value()["priority"] = std::numeric_limits::max(); + else + netClass.value()["priority"] = priority++; } } - m_NetClassPatternAssignmentCache[ aNetName ] = wxEmptyString; - return m_DefaultNetClass; + // Move netclass assignments to a list + if( m_internals->contains( "netclass_assignments" ) + && m_internals->At( "netclass_assignments" ).is_object() ) + { + nlohmann::json migrated = {}; + + for( const auto& pair : m_internals->At( "netclass_assignments" ).items() ) + { + nlohmann::json netclassesJson = nlohmann::json::array(); + + if( pair.value().get() != wxEmptyString ) + netclassesJson.push_back( pair.value() ); + + migrated[pair.key()] = netclassesJson; + } + + m_internals->SetFromString( "netclass_assignments", migrated ); + } + + return true; +} + + +void NET_SETTINGS::SetDefaultNetclass( std::shared_ptr netclass ) +{ + m_defaultNetClass = netclass; +} + + +std::shared_ptr NET_SETTINGS::GetDefaultNetclass() +{ + return m_defaultNetClass; +} + + +bool NET_SETTINGS::HasNetclass( const wxString& netclassName ) const +{ + return m_netClasses.find( netclassName ) != m_netClasses.end(); +} + + +void NET_SETTINGS::SetNetclass( const wxString& netclassName, std::shared_ptr& netclass ) +{ + m_netClasses[netclassName] = netclass; +} + + +void NET_SETTINGS::SetNetclasses( const std::map>& netclasses ) +{ + m_netClasses = netclasses; +} + + +const std::map>& NET_SETTINGS::GetNetclasses() const +{ + return m_netClasses; +} + + +const std::map>& NET_SETTINGS::GetCompositeNetclasses() const +{ + return m_compositeNetClasses; +} + + +void NET_SETTINGS::ClearNetclasses() +{ + m_netClasses.clear(); + m_impicitNetClasses.clear(); +} + + +const std::map>& NET_SETTINGS::GetNetclassLabelAssignments() const +{ + return m_netClassLabelAssignments; +} + + +void NET_SETTINGS::ClearNetclassLabelAssignments() +{ + m_netClassLabelAssignments.clear(); +} + + +void NET_SETTINGS::ClearNetclassLabelAssignment( const wxString& netName ) +{ + m_netClassLabelAssignments.erase( netName ); +} + + +void NET_SETTINGS::SetNetclassLabelAssignment( const wxString& netName, + const std::set& netclasses ) +{ + m_netClassLabelAssignments[netName] = netclasses; +} + + +void NET_SETTINGS::AppendNetclassLabelAssignment( const wxString& netName, + const std::set& netclasses ) +{ + m_netClassLabelAssignments[netName].insert( netclasses.begin(), netclasses.end() ); +} + + +bool NET_SETTINGS::HasNetclassLabelAssignment( const wxString& netName ) const +{ + return m_netClassLabelAssignments.find( netName ) != m_netClassLabelAssignments.end(); +} + + +void NET_SETTINGS::SetNetclassPatternAssignment( const wxString& pattern, const wxString& netclass ) +{ + // Replace existing assignment if we have one + for( auto& assignment : m_netClassPatternAssignments ) + { + if( assignment.first->GetPattern() == pattern ) + { + assignment.second = netclass; + ClearAllCaches(); + return; + } + } + + // No assignment, add a new one + m_netClassPatternAssignments.push_back( + { std::make_unique( pattern, CTX_NETCLASS ), netclass } ); + + ClearAllCaches(); +} + + +void NET_SETTINGS::SetNetclassPatternAssignments( + std::vector, wxString>>&& netclassPatterns ) +{ + m_netClassPatternAssignments = std::move( netclassPatterns ); + ClearAllCaches(); +} + + +std::vector, wxString>>& +NET_SETTINGS::GetNetclassPatternAssignments() +{ + return m_netClassPatternAssignments; +} + + +void NET_SETTINGS::ClearNetclassPatternAssignments() +{ + m_netClassPatternAssignments.clear(); +} + + +void NET_SETTINGS::ClearCacheForNet( const wxString& netName ) +{ + if( m_effectiveNetclassCache.count( netName ) ) + { + wxString compositeNetclassName = + m_effectiveNetclassCache[netName]->GetVariableSubstitutionName(); + m_compositeNetClasses.erase( compositeNetclassName ); + m_effectiveNetclassCache.erase( netName ); + } +} + + +void NET_SETTINGS::ClearAllCaches() +{ + m_effectiveNetclassCache.clear(); + m_compositeNetClasses.clear(); +} + + +void NET_SETTINGS::SetNetColorAssignment( const wxString& netName, const KIGFX::COLOR4D& color ) +{ + m_netColorAssignments[netName] = color; +} + + +const std::map& NET_SETTINGS::GetNetColorAssignments() const +{ + return m_netColorAssignments; +} + + +void NET_SETTINGS::ClearNetColorAssignments() +{ + m_netColorAssignments.clear(); +} + + +bool NET_SETTINGS::HasEffectiveNetClass( const wxString& aNetName ) const +{ + return m_effectiveNetclassCache.count( aNetName ) > 0; +} + + +std::shared_ptr NET_SETTINGS::GetCachedEffectiveNetClass( const wxString& aNetName ) const +{ + return m_effectiveNetclassCache.at( aNetName ); +} + + +std::shared_ptr NET_SETTINGS::GetEffectiveNetClass( const wxString& aNetName ) +{ + // Lambda to fetch an explicit netclass. Returns a nullptr if not found + auto getExplicitNetclass = [this]( const wxString& netclass ) -> std::shared_ptr + { + if( netclass == NETCLASS::Default ) + return m_defaultNetClass; + + auto ii = m_netClasses.find( netclass ); + + if( ii == m_netClasses.end() ) + return {}; + else + return ii->second; + }; + + // Lambda to fetch or create an implicit netclass (defined with a label, but not configured) + // These are needed as while they do not provide any netclass parameters, they do now appear in + // DRC matching strings as an assigned netclass. + auto getOrAddImplicitNetcless = [this]( const wxString& netclass ) -> std::shared_ptr + { + auto ii = m_impicitNetClasses.find( netclass ); + + if( ii == m_impicitNetClasses.end() ) + { + std::shared_ptr nc = std::make_shared( netclass, false ); + nc->SetPriority( std::numeric_limits().max() - 1 ); // Priority > default netclass + m_impicitNetClasses[netclass] = nc; + return nc; + } + else + { + return ii->second; + } + }; + + // is forced to be part of the default netclass. + if( aNetName.IsEmpty() ) + return m_defaultNetClass; + + // First check if we have a cached resolved netclass + auto cacheItr = m_effectiveNetclassCache.find( aNetName ); + + if( cacheItr != m_effectiveNetclassCache.end() ) + return cacheItr->second; + + // No cache found - build a vector of all netclasses assigned to or matching this net + std::vector> resolvedNetclasses; + + // First find explicit netclass assignments + auto it = m_netClassLabelAssignments.find( aNetName ); + + if( it != m_netClassLabelAssignments.end() && it->second.size() > 0 ) + { + for( const wxString& netclassName : it->second ) + { + std::shared_ptr netclass = getExplicitNetclass( netclassName ); + + if( netclass ) + { + resolvedNetclasses.push_back( std::move( netclass ) ); + } + else + { + resolvedNetclasses.push_back( + getOrAddImplicitNetcless( netclassName ) ); + } + } + } + + // Now find any pattern-matched netclass assignments + for( const auto& [matcher, netclassName] : m_netClassPatternAssignments ) + { + if( matcher->StartsWith( aNetName ) ) + { + std::shared_ptr netclass = getExplicitNetclass( netclassName ); + + if( netclass ) + { + resolvedNetclasses.push_back( std::move( netclass ) ); + } + else + { + resolvedNetclasses.push_back( getOrAddImplicitNetcless( netclassName ) ); + } + } + } + + // Handle zero resolved netclasses + if( resolvedNetclasses.size() == 0 ) + { + m_effectiveNetclassCache[aNetName] = m_defaultNetClass; + + return m_defaultNetClass; + } + + // Make and cache the effective netclass. Note that makeEffectiveNetclass will add the default + // netclass to resolvedNetclasses if it is needed to complete the netclass paramters set. It + // will also sort resolvedNetclasses by priority order. + std::vector netclassPtrs; + + for( std::shared_ptr& nc : resolvedNetclasses ) + netclassPtrs.push_back( nc.get() ); + + wxString name; + name.Printf( "Effective for net: %s", aNetName ); + std::shared_ptr effectiveNetclass = std::make_shared( name, false ); + makeEffectiveNetclass( effectiveNetclass, netclassPtrs ); + + if( netclassPtrs.size() == 1 ) + { + // No defaults were added - just return the primary netclass + m_effectiveNetclassCache[aNetName] = resolvedNetclasses[0]; + return resolvedNetclasses[0]; + } + else + { + effectiveNetclass->SetConstituentNetclasses( std::move( netclassPtrs ) ); + + m_compositeNetClasses[effectiveNetclass->GetVariableSubstitutionName()] = effectiveNetclass; + m_effectiveNetclassCache[aNetName] = effectiveNetclass; + + return effectiveNetclass; + } +} + + +void NET_SETTINGS::RecomputeEffectiveNetclasses() +{ + for( auto& [ncName, nc] : m_compositeNetClasses ) + { + // Note this needs to be a copy in case we now need to add the default netclass + std::vector constituents = nc->GetConstituentNetclasses(); + + wxASSERT( constituents.size() > 0 ); + + // If the last netclass is Default, remove it (it will be re-added if still needed) + if( ( *constituents.rbegin() )->GetName() == NETCLASS::Default ) + { + constituents.pop_back(); + } + + // Remake the netclass from original constituents + nc->ResetParameters(); + makeEffectiveNetclass( nc, constituents ); + nc->SetConstituentNetclasses( std::move( constituents ) ); + } +} + + +void NET_SETTINGS::makeEffectiveNetclass( std::shared_ptr& effectiveNetclass, + std::vector& constituentNetclasses ) const +{ + // Sort the resolved netclasses by priority (highest first), with same-priority netclasses + // ordered alphabetically + std::sort( constituentNetclasses.begin(), constituentNetclasses.end(), + []( NETCLASS* nc1, NETCLASS* nc2 ) + { + int p1 = nc1->GetPriority(); + int p2 = nc2->GetPriority(); + + if( p1 < p2 ) + return true; + + if (p1 == p2) + return nc1->GetName().Cmp( nc2->GetName() ) < 0; + + return false; + } ); + + // Iterate from lowest priority netclass and fill effective netclass parameters + for( auto itr = constituentNetclasses.rbegin(); itr != constituentNetclasses.rend(); ++itr ) + { + NETCLASS* nc = *itr; + + if( nc->HasClearance() ) + { + effectiveNetclass->SetClearance( nc->GetClearance() ); + effectiveNetclass->SetClearanceParent( nc ); + } + + if( nc->HasTrackWidth() ) + { + effectiveNetclass->SetTrackWidth( nc->GetTrackWidth() ); + effectiveNetclass->SetTrackWidthParent( nc ); + } + + if( nc->HasViaDiameter() ) + { + effectiveNetclass->SetViaDiameter( nc->GetViaDiameter() ); + effectiveNetclass->SetViaDiameterParent( nc ); + } + + if( nc->HasViaDrill() ) + { + effectiveNetclass->SetViaDrill( nc->GetViaDrill() ); + effectiveNetclass->SetViaDrillParent( nc ); + } + + if( nc->HasuViaDiameter() ) + { + effectiveNetclass->SetuViaDiameter( nc->GetuViaDiameter() ); + effectiveNetclass->SetuViaDiameterParent( nc ); + } + + if( nc->HasuViaDrill() ) + { + effectiveNetclass->SetuViaDrill( nc->GetuViaDrill() ); + effectiveNetclass->SetuViaDrillParent( nc ); + } + + if( nc->HasDiffPairWidth() ) + { + effectiveNetclass->SetDiffPairWidth( nc->GetDiffPairWidth() ); + effectiveNetclass->SetDiffPairWidthParent( nc ); + } + + if( nc->HasDiffPairGap() ) + { + effectiveNetclass->SetDiffPairGap( nc->GetDiffPairGap() ); + effectiveNetclass->SetDiffPairGapParent( nc ); + } + + if( nc->HasDiffPairViaGap() ) + { + effectiveNetclass->SetDiffPairViaGap( nc->GetDiffPairViaGap() ); + effectiveNetclass->SetDiffPairViaGapParent( nc ); + } + + if( nc->HasWireWidth() ) + { + effectiveNetclass->SetWireWidth( nc->GetWireWidth() ); + effectiveNetclass->SetWireWidthParent( nc ); + } + + if( nc->HasBusWidth() ) + { + effectiveNetclass->SetBusWidth( nc->GetBusWidth() ); + effectiveNetclass->SetBusWidthParent( nc ); + } + + if( nc->HasLineStyle() ) + { + effectiveNetclass->SetLineStyle( nc->GetLineStyle() ); + effectiveNetclass->SetLineStyleParent( nc ); + } + + COLOR4D pcbColor = nc->GetPcbColor(); + + if( pcbColor != COLOR4D::UNSPECIFIED ) + { + effectiveNetclass->SetPcbColor( pcbColor ); + effectiveNetclass->SetPcbColorParent( nc ); + } + + COLOR4D schColor = nc->GetSchematicColor(); + + if( schColor != COLOR4D::UNSPECIFIED ) + { + effectiveNetclass->SetSchematicColor( schColor ); + effectiveNetclass->SetSchematicColorParent( nc ); + } + } + + // Fill in any required defaults + if( addMissingDefaults( effectiveNetclass.get() ) ) + constituentNetclasses.push_back( m_defaultNetClass.get() ); +} + + +bool NET_SETTINGS::addMissingDefaults( NETCLASS* nc ) const +{ + bool addedDefault = false; + + if( !nc->HasClearance() ) + { + addedDefault = true; + nc->SetClearance( m_defaultNetClass->GetClearance() ); + nc->SetClearanceParent( m_defaultNetClass.get() ); + } + + if( !nc->HasTrackWidth() ) + { + addedDefault = true; + nc->SetTrackWidth( m_defaultNetClass->GetTrackWidth() ); + nc->SetTrackWidthParent( m_defaultNetClass.get() ); + } + + if( !nc->HasViaDiameter() ) + { + addedDefault = true; + nc->SetViaDiameter( m_defaultNetClass->GetViaDiameter() ); + nc->SetViaDiameterParent( m_defaultNetClass.get() ); + } + + if( !nc->HasViaDrill() ) + { + addedDefault = true; + nc->SetViaDrill( m_defaultNetClass->GetViaDrill() ); + nc->SetViaDrillParent( m_defaultNetClass.get() ); + } + + if( !nc->HasuViaDiameter() ) + { + addedDefault = true; + nc->SetuViaDiameter( m_defaultNetClass->GetuViaDiameter() ); + nc->SetuViaDiameterParent( m_defaultNetClass.get() ); + } + + if( !nc->HasuViaDrill() ) + { + addedDefault = true; + nc->SetuViaDrill( m_defaultNetClass->GetuViaDrill() ); + nc->SetuViaDrillParent( m_defaultNetClass.get() ); + } + + if( !nc->HasDiffPairWidth() ) + { + addedDefault = true; + nc->SetDiffPairWidth( m_defaultNetClass->GetDiffPairWidth() ); + nc->SetDiffPairWidthParent( m_defaultNetClass.get() ); + } + + if( !nc->HasDiffPairGap() ) + { + addedDefault = true; + nc->SetDiffPairGap( m_defaultNetClass->GetDiffPairGap() ); + nc->SetDiffPairGapParent( m_defaultNetClass.get() ); + } + + // Currently this is only on the default netclass, and not editable in the setup panel + // if( !nc->HasDiffPairViaGap() ) + // { + // addedDefault = true; + // nc->SetDiffPairViaGap( m_defaultNetClass->GetDiffPairViaGap() ); + // nc->SetDiffPairViaGapParent( m_defaultNetClass.get() ); + // } + + if( !nc->HasWireWidth() ) + { + addedDefault = true; + nc->SetWireWidth( m_defaultNetClass->GetWireWidth() ); + nc->SetWireWidthParent( m_defaultNetClass.get() ); + } + + if( !nc->HasBusWidth() ) + { + addedDefault = true; + nc->SetBusWidth( m_defaultNetClass->GetBusWidth() ); + nc->SetBusWidthParent( m_defaultNetClass.get() ); + } + + if( !nc->HasLineStyle() ) + { + addedDefault = true; + nc->SetLineStyle( m_defaultNetClass->GetLineStyle() ); + nc->SetLineStyleParent( m_defaultNetClass.get() ); + } + + COLOR4D pcbColor = nc->GetPcbColor(); + + if( pcbColor == COLOR4D::UNSPECIFIED ) + { + if( m_defaultNetClass->GetPcbColor() != COLOR4D::UNSPECIFIED ) + { + addedDefault = true; + nc->SetPcbColor( m_defaultNetClass->GetPcbColor() ); + nc->SetPcbColorParent( m_defaultNetClass.get() ); + } + } + + COLOR4D schColor = nc->GetSchematicColor(); + + if( schColor == COLOR4D::UNSPECIFIED ) + { + if( m_defaultNetClass->GetSchematicColor() != COLOR4D::UNSPECIFIED ) + { + addedDefault = true; + nc->SetSchematicColor( m_defaultNetClass->GetSchematicColor() ); + nc->SetSchematicColorParent( m_defaultNetClass.get() ); + } + } + + return addedDefault; } std::shared_ptr NET_SETTINGS::GetNetClassByName( const wxString& aNetClassName ) const { - auto ii = m_NetClasses.find( aNetClassName ); + auto ii = m_netClasses.find( aNetClassName ); - if( ii == m_NetClasses.end() ) - return m_DefaultNetClass; + if( ii == m_netClasses.end() ) + return m_defaultNetClass; else return ii->second; } diff --git a/common/widgets/wx_grid.cpp b/common/widgets/wx_grid.cpp index 88dbee458e..887f56eacf 100644 --- a/common/widgets/wx_grid.cpp +++ b/common/widgets/wx_grid.cpp @@ -28,12 +28,14 @@ #include // Needed for textentry.h on MSW #include +#include #include #include #include #include #include #include +#include #include #include @@ -374,23 +376,63 @@ void WX_GRID::onCellEditorHidden( wxGridEvent& aEvent ) int row = aEvent.GetRow(); int col = aEvent.GetCol(); + // Determine if this cell is marked as holding nullable values + bool isNullable = false; + wxGridCellEditor* cellEditor = GetCellEditor( row, col ); + + if( cellEditor ) + { + GRID_CELL_MARK_AS_NULLABLE* nullableCell = + dynamic_cast( cellEditor ); + + if( nullableCell ) + isNullable = nullableCell->IsNullable(); + + cellEditor->DecRef(); + } + CallAfter( - [this, row, col, unitsProvider]() - { - wxString stringValue = GetCellValue( row, col ); + [this, row, col, isNullable, unitsProvider]() + { + wxString stringValue = GetCellValue( row, col ); + bool processedOk = true; - if( m_eval->Process( stringValue ) ) - { - int val = unitsProvider->ValueFromString( m_eval->Result() ); - wxString evalValue = unitsProvider->StringFromValue( val, true ); + if( stringValue != UNITS_PROVIDER::NullUiString ) + processedOk = m_eval->Process( stringValue ); - if( stringValue != evalValue ) - { - SetCellValue( row, col, evalValue ); - m_evalBeforeAfter[ { row, col } ] = { stringValue, evalValue }; - } - } - } ); + if( processedOk ) + { + wxString evalValue; + + if( isNullable ) + { + std::optional val; + + if( stringValue == UNITS_PROVIDER::NullUiString ) + { + val = unitsProvider->OptionalValueFromString( + UNITS_PROVIDER::NullUiString ); + } + else + { + val = unitsProvider->OptionalValueFromString( m_eval->Result() ); + } + + evalValue = unitsProvider->StringFromOptionalValue( val, true ); + } + else + { + int val = unitsProvider->ValueFromString( m_eval->Result() ); + evalValue = unitsProvider->StringFromValue( val, true ); + } + + if( stringValue != evalValue ) + { + SetCellValue( row, col, evalValue ); + m_evalBeforeAfter[{ row, col }] = { stringValue, evalValue }; + } + } + } ); } aEvent.Skip(); @@ -670,6 +712,27 @@ int WX_GRID::GetUnitValue( int aRow, int aCol ) } +std::optional WX_GRID::GetOptionalUnitValue( int aRow, int aCol ) +{ + UNITS_PROVIDER* unitsProvider = m_unitsProviders[aCol]; + + if( !unitsProvider ) + unitsProvider = m_unitsProviders.begin()->second; + + wxString stringValue = GetCellValue( aRow, aCol ); + + if( alg::contains( m_autoEvalCols, aCol ) ) + { + m_eval->SetDefaultUnits( unitsProvider->GetUserUnits() ); + + if( stringValue != UNITS_PROVIDER::NullUiString && m_eval->Process( stringValue ) ) + stringValue = m_eval->Result(); + } + + return unitsProvider->OptionalValueFromString( stringValue ); +} + + void WX_GRID::SetUnitValue( int aRow, int aCol, int aValue ) { UNITS_PROVIDER* unitsProvider = m_unitsProviders[ aCol ]; @@ -681,6 +744,17 @@ void WX_GRID::SetUnitValue( int aRow, int aCol, int aValue ) } +void WX_GRID::SetOptionalUnitValue( int aRow, int aCol, std::optional aValue ) +{ + UNITS_PROVIDER* unitsProvider = m_unitsProviders[aCol]; + + if( !unitsProvider ) + unitsProvider = m_unitsProviders.begin()->second; + + SetCellValue( aRow, aCol, unitsProvider->StringFromOptionalValue( aValue, true ) ); +} + + void WX_GRID::onGridColMove( wxGridEvent& aEvent ) { // wxWidgets won't move an open editor, so better just to close it diff --git a/eeschema/connection_graph.cpp b/eeschema/connection_graph.cpp index d23c612e45..9f910eaeb6 100644 --- a/eeschema/connection_graph.cpp +++ b/eeschema/connection_graph.cpp @@ -432,7 +432,7 @@ const wxString& CONNECTION_SUBGRAPH::GetNameForDriver( SCH_ITEM* aItem ) const const std::vector> -CONNECTION_SUBGRAPH::GetNetclassesForDriver( SCH_ITEM* aItem, bool returnAll ) const +CONNECTION_SUBGRAPH::GetNetclassesForDriver( SCH_ITEM* aItem ) const { std::vector> foundNetclasses; @@ -446,16 +446,8 @@ CONNECTION_SUBGRAPH::GetNetclassesForDriver( SCH_ITEM* aItem, bool returnAll ) c if( ruleNetclasses.size() > 0 ) { - if( returnAll ) - { - foundNetclasses.insert( foundNetclasses.end(), ruleNetclasses.begin(), - ruleNetclasses.end() ); - } - else - { - foundNetclasses.push_back( ruleNetclasses[0] ); - return foundNetclasses; - } + foundNetclasses.insert( foundNetclasses.end(), ruleNetclasses.begin(), + ruleNetclasses.end() ); } } @@ -473,12 +465,15 @@ CONNECTION_SUBGRAPH::GetNetclassesForDriver( SCH_ITEM* aItem, bool returnAll ) c if( netclass != wxEmptyString ) foundNetclasses.push_back( { netclass, aItem } ); - - return returnAll; } } + } ); - return true; + std::sort( + foundNetclasses.begin(), foundNetclasses.end(), + []( const std::pair& i1, const std::pair& i2 ) + { + return i1.first < i2.first; } ); return foundNetclasses; @@ -2368,16 +2363,11 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function* a } std::shared_ptr& netSettings = m_schematic->Prj().GetProjectFile().m_NetSettings; - std::map oldAssignments = netSettings->m_NetClassLabelAssignments; + std::map> oldAssignments = + netSettings->GetNetclassLabelAssignments(); std::set affectedNetclassNetAssignments; - netSettings->m_NetClassLabelAssignments.clear(); - - // Used to track where netclasses are assigned to a net from a bus netclass - // definition. Without this tracking, depending on the order of testing for - // netclasses, an already-assigned netclass on a bus member can be deleted - // if an explicitly labelled member net does not have a netclass assigned. - std::unordered_set netclassAssignedFromBus; + netSettings->ClearNetclassLabelAssignments(); auto dirtySubgraphs = [&]( const std::vector& subgraphs ) @@ -2393,132 +2383,117 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function* a }; auto checkNetclassDrivers = - [&]( const std::vector& subgraphs ) + [&]( const wxString& netName, const std::vector& subgraphs ) + { + wxCHECK_RET( !subgraphs.empty(), wxS( "Invalid empty subgraph" ) ); + + const CONNECTION_SUBGRAPH* driverSubgraph = nullptr; + std::set netclasses; + + // Collect all netclasses on all subgraphs for this net + for( const CONNECTION_SUBGRAPH* subgraph : subgraphs ) + { + for( SCH_ITEM* item : subgraph->m_items ) { - const CONNECTION_SUBGRAPH* driverSubgraph = nullptr; - wxString netclass; + std::vector> netclassesWithProviders = + subgraph->GetNetclassesForDriver( item ); - wxCHECK_RET( !subgraphs.empty(), wxS( "Invalid empty subgraph" ) ); + for( std::pair& ncPair : netclassesWithProviders ) + netclasses.insert( std::move( ncPair.first ) ); + } + } - for( const CONNECTION_SUBGRAPH* subgraph : subgraphs ) + // Append the netclasses to any included bus members + for( const CONNECTION_SUBGRAPH* subgraph : subgraphs ) + { + if( subgraph->m_driver_connection->IsBus() ) + { + auto processBusMember = [&, this]( const SCH_CONNECTION* member ) { - for( SCH_ITEM* item : subgraph->m_items ) + if( !netclasses.empty() ) { - const std::vector> netclassesWithProviders = - subgraph->GetNetclassesForDriver( item, false ); - - if( netclassesWithProviders.size() > 0 ) - { - netclass = netclassesWithProviders[0].first; - break; - } + netSettings->AppendNetclassLabelAssignment( member->Name(), netclasses ); } - if( !netclass.IsEmpty() ) + auto ii = m_net_name_to_subgraphs_map.find( member->Name() ); + + if( oldAssignments.count( member->Name() ) ) { - driverSubgraph = subgraph; - break; - } - } - - if( !driverSubgraph ) - driverSubgraph = subgraphs.front(); - - const wxString netname = driverSubgraph->GetNetName(); - - // Handle netclass assignments on buses - if( driverSubgraph->m_driver_connection->IsBus() ) - { - auto processBusMember = [&, this]( const SCH_CONNECTION* member ) - { - if( !netclass.IsEmpty() ) - { - netSettings->m_NetClassLabelAssignments[member->Name()] = netclass; - netclassAssignedFromBus.insert( member->Name() ); - } - - auto ii = m_net_name_to_subgraphs_map.find( member->Name() ); - - if( oldAssignments.count( member->Name() ) ) - { - if( oldAssignments[member->Name()] != netclass ) - { - affectedNetclassNetAssignments.insert( member->Name() ); - - if( ii != m_net_name_to_subgraphs_map.end() ) - dirtySubgraphs( ii->second ); - } - } - else if( !netclass.IsEmpty() ) + if( oldAssignments[member->Name()] != netclasses ) { affectedNetclassNetAssignments.insert( member->Name() ); if( ii != m_net_name_to_subgraphs_map.end() ) dirtySubgraphs( ii->second ); } - }; - - for( const std::shared_ptr& member : - driverSubgraph->m_driver_connection->Members() ) - { - // Check if this member itself is a bus (which can be the case - // for vector buses as members of a bus, see - // https://gitlab.com/kicad/code/kicad/-/issues/16545 - if( member->IsBus() ) - { - for( const std::shared_ptr& nestedMember : - member->Members() ) - { - processBusMember( nestedMember.get() ); - } - } - else - { - processBusMember( member.get() ); - } } - } + else if( !netclasses.empty() ) + { + affectedNetclassNetAssignments.insert( member->Name() ); - // Handle netclass assignments on nets / overarching bus definitions. - // Note: currently a netclass definition on a bus will override any - // on a net. This will be resolved with multiple netclasses. - if( !netclassAssignedFromBus.count( netname ) ) + if( ii != m_net_name_to_subgraphs_map.end() ) + dirtySubgraphs( ii->second ); + } + }; + + for( const std::shared_ptr& member : + subgraph->m_driver_connection->Members() ) { - if( !netclass.IsEmpty() ) + // Check if this member itself is a bus (which can be the case + // for vector buses as members of a bus, see + // https://gitlab.com/kicad/code/kicad/-/issues/16545 + if( member->IsBus() ) { - netSettings->m_NetClassLabelAssignments[netname] = netclass; - } - - if( oldAssignments.count( netname ) ) - { - if( oldAssignments[netname] != netclass ) + for( const std::shared_ptr& nestedMember : + member->Members() ) { - affectedNetclassNetAssignments.insert( netname ); - dirtySubgraphs( subgraphs ); + processBusMember( nestedMember.get() ); } } - else if( !netclass.IsEmpty() ) + else { - affectedNetclassNetAssignments.insert( netname ); - dirtySubgraphs( subgraphs ); + processBusMember( member.get() ); } } - }; + } + } + // Assign the netclasses to the root netname + if( !netclasses.empty() ) + { + netSettings->AppendNetclassLabelAssignment( netName, netclasses ); + } + + if( oldAssignments.count( netName ) ) + { + if( oldAssignments[netName] != netclasses ) + { + affectedNetclassNetAssignments.insert( netName ); + dirtySubgraphs( subgraphs ); + } + } + else if( !netclasses.empty() ) + { + affectedNetclassNetAssignments.insert( netName ); + dirtySubgraphs( subgraphs ); + } + }; + + // Check for netclass assignments for( const auto& [ netname, subgraphs ] : m_net_name_to_subgraphs_map ) - checkNetclassDrivers( subgraphs ); + checkNetclassDrivers( netname, subgraphs ); if( !aUnconditional ) { - for( auto& [ netname, netclass ] : oldAssignments ) + for( auto& [netname, netclasses] : oldAssignments ) { - if( netSettings->m_NetClassLabelAssignments.count( netname ) + if( netSettings->GetNetclassLabelAssignments().count( netname ) || affectedNetclassNetAssignments.count( netname ) ) { continue; } - netSettings->m_NetClassLabelAssignments[ netname ] = netclass; + netSettings->SetNetclassLabelAssignment( netname, netclasses ); } } } @@ -3250,15 +3225,6 @@ int CONNECTION_GRAPH::RunERC() error_count += ercCheckHierSheets(); } - if( settings.IsTestEnabled( ERCE_NETCLASS_CONFLICT ) ) - { - for( const auto& [ netname, subgraphs ] : m_net_name_to_subgraphs_map ) - { - if( !ercCheckNetclassConflicts( subgraphs ) ) - error_count++; - } - } - if( settings.IsTestEnabled( ERCE_SINGLE_GLOBAL_LABEL ) ) { error_count += ercCheckSingleGlobalLabel(); @@ -3313,60 +3279,6 @@ bool CONNECTION_GRAPH::ercCheckMultipleDrivers( const CONNECTION_SUBGRAPH* aSubg } -bool CONNECTION_GRAPH::ercCheckNetclassConflicts( const std::vector& subgraphs ) -{ - wxString firstNetclass; - SCH_ITEM* firstNetclassDriver = nullptr; - const SCH_SHEET_PATH* firstNetclassDriverSheet = nullptr; - bool conflictFound = false; - - for( const CONNECTION_SUBGRAPH* subgraph : subgraphs ) - { - for( SCH_ITEM* item : subgraph->m_items ) - { - const std::vector> netclassesWithProvider = - subgraph->GetNetclassesForDriver( item, true ); - - if( netclassesWithProvider.size() == 0 ) - continue; - - auto checkNetclass = [&]( const std::pair& netclass ) - { - if( netclass.first != firstNetclass ) - { - if( !firstNetclassDriver ) - { - firstNetclass = netclass.first; - firstNetclassDriver = netclass.second; - firstNetclassDriverSheet = &subgraph->GetSheet(); - } - else - { - conflictFound = true; - - std::shared_ptr ercItem = - ERC_ITEM::Create( ERCE_NETCLASS_CONFLICT ); - ercItem->SetItems( firstNetclassDriver, netclass.second ); - ercItem->SetSheetSpecificPath( subgraph->GetSheet() ); - ercItem->SetItemsSheetPaths( *firstNetclassDriverSheet, - subgraph->GetSheet() ); - - SCH_MARKER* marker = - new SCH_MARKER( ercItem, netclass.second->GetPosition() ); - subgraph->m_sheet.LastScreen()->Append( marker ); - } - } - }; - - for( const std::pair& netclass : netclassesWithProvider ) - checkNetclass( netclass ); - } - } - - return conflictFound; -} - - bool CONNECTION_GRAPH::ercCheckBusToNetConflicts( const CONNECTION_SUBGRAPH* aSubgraph ) { const SCH_SHEET_PATH& sheet = aSubgraph->m_sheet; diff --git a/eeschema/connection_graph.h b/eeschema/connection_graph.h index fb115d9f1d..a6ade147be 100644 --- a/eeschema/connection_graph.h +++ b/eeschema/connection_graph.h @@ -126,10 +126,8 @@ public: /// Return the resolved netclasses for the item, and the source item providing the netclass /// @param aItem the item to query for netclass assignments - /// @param returnAll If true, return all assigned netclasses (for ERC). If false, stop on first - /// netclass (for connectivity). const std::vector> - GetNetclassesForDriver( SCH_ITEM* aItem, bool returnAll ) const; + GetNetclassesForDriver( SCH_ITEM* aItem ) const; /// Combine another subgraph on the same sheet into this one. void Absorb( CONNECTION_SUBGRAPH* aOther ); @@ -642,8 +640,6 @@ private: */ bool ercCheckMultipleDrivers( const CONNECTION_SUBGRAPH* aSubgraph ); - bool ercCheckNetclassConflicts( const std::vector& subgraphs ); - /** * Check one subgraph for conflicting connections between net and bus labels. * diff --git a/eeschema/eeschema_config.cpp b/eeschema/eeschema_config.cpp index 6e399fc868..d7ac921fd1 100644 --- a/eeschema/eeschema_config.cpp +++ b/eeschema/eeschema_config.cpp @@ -162,7 +162,7 @@ int SCH_EDIT_FRAME::GetSchematicJunctionSize() const std::shared_ptr& netSettings = Prj().GetProjectFile().NetSettings(); int sizeChoice = Schematic().Settings().m_JunctionSizeChoice; - int dotSize = netSettings->m_DefaultNetClass->GetWireWidth() * sizeMultipliers[ sizeChoice ]; + int dotSize = netSettings->GetDefaultNetclass()->GetWireWidth() * sizeMultipliers[sizeChoice]; return std::max( dotSize, 1 ); } diff --git a/eeschema/erc/erc.cpp b/eeschema/erc/erc.cpp index 3bcae421f6..3add0b9d10 100644 --- a/eeschema/erc/erc.cpp +++ b/eeschema/erc/erc.cpp @@ -652,7 +652,7 @@ int ERC_TESTER::TestMissingNetclasses() { int err_count = 0; std::shared_ptr& settings = m_schematic->Prj().GetProjectFile().NetSettings(); - wxString defaultNetclass = settings->m_DefaultNetClass->GetName(); + wxString defaultNetclass = settings->GetDefaultNetclass()->GetName(); auto logError = [&]( const SCH_SHEET_PATH& sheet, SCH_ITEM* item, const wxString& netclass ) @@ -685,7 +685,7 @@ int ERC_TESTER::TestMissingNetclasses() wxString netclass = field->GetShownText( &sheet, false ); if( !netclass.IsSameAs( defaultNetclass ) - && settings->m_NetClasses.count( netclass ) == 0 ) + && !settings->HasNetclass( netclass ) ) { logError( sheet, item, netclass ); } @@ -1558,71 +1558,6 @@ int ERC_TESTER::TestSimModelIssues() } -int ERC_TESTER::RunRuleAreaERC() -{ - int numErrors = 0; - - if( !m_settings.IsTestEnabled( ERCE_OVERLAPPING_RULE_AREAS ) ) - return 0; - - std::map> allScreenRuleAreas; - - for( SCH_SCREEN* screen = m_screens.GetFirst(); screen; screen = m_screens.GetNext() ) - { - for( SCH_ITEM* item : screen->Items().OfType( SCH_RULE_AREA_T ) ) - { - allScreenRuleAreas[screen].push_back( static_cast( item ) ); - } - } - - if( m_settings.IsTestEnabled( ERCE_OVERLAPPING_RULE_AREAS ) ) - numErrors += TestRuleAreaOverlappingRuleAreasERC( allScreenRuleAreas ); - - return numErrors; -} - - -int ERC_TESTER::TestRuleAreaOverlappingRuleAreasERC( - std::map>& allScreenRuleAreas ) -{ - int numErrors = 0; - - for( auto screenRuleAreas : allScreenRuleAreas ) - { - std::vector& ruleAreas = screenRuleAreas.second; - - for( std::size_t i = 0; i < ruleAreas.size(); ++i ) - { - SHAPE_POLY_SET& polyFirst = ruleAreas[i]->GetPolyShape(); - - for( std::size_t j = i + 1; j < ruleAreas.size(); ++j ) - { - SHAPE_POLY_SET polySecond = ruleAreas[j]->GetPolyShape(); - - if( polyFirst.Collide( &polySecond ) ) - { - numErrors++; - - SCH_SCREEN* screen = screenRuleAreas.first; - SCH_SHEET_PATH firstSheet = screen->GetClientSheetPaths()[0]; - - std::shared_ptr ercItem = - ERC_ITEM::Create( ERCE_OVERLAPPING_RULE_AREAS ); - ercItem->SetItems( ruleAreas[i], ruleAreas[j] ); - ercItem->SetSheetSpecificPath( firstSheet ); - ercItem->SetItemsSheetPaths( firstSheet, firstSheet ); - - SCH_MARKER* marker = new SCH_MARKER( ercItem, ruleAreas[i]->GetPosition() ); - screen->Append( marker ); - } - } - } - } - - return numErrors; -} - - void ERC_TESTER::RunTests( DS_PROXY_VIEW_ITEM* aDrawingSheet, SCH_EDIT_FRAME* aEditFrame, KIFACE* aCvPcb, PROJECT* aProject, PROGRESS_REPORTER* aProgressReporter ) { @@ -1661,14 +1596,6 @@ void ERC_TESTER::RunTests( DS_PROXY_VIEW_ITEM* aDrawingSheet, SCH_EDIT_FRAME* aE m_schematic->ConnectionGraph()->RunERC(); - if( aProgressReporter ) - aProgressReporter->AdvancePhase( _( "Checking rule areas..." ) ); - - if( m_settings.IsTestEnabled( ERCE_OVERLAPPING_RULE_AREAS ) ) - { - RunRuleAreaERC(); - } - if( aProgressReporter ) aProgressReporter->AdvancePhase( _( "Checking units..." ) ); diff --git a/eeschema/erc/erc.h b/eeschema/erc/erc.h index 556d55bbe5..18c9733a60 100644 --- a/eeschema/erc/erc.h +++ b/eeschema/erc/erc.h @@ -173,12 +173,6 @@ public: */ int RunRuleAreaERC(); - /** - * Runs ERC to check for overlapping rule areas - */ - int TestRuleAreaOverlappingRuleAreasERC( std::map>& allScreenRuleAreas ); - void RunTests( DS_PROXY_VIEW_ITEM* aDrawingSheet, SCH_EDIT_FRAME* aEditFrame, KIFACE* aCvPcb, PROJECT* aProject, PROGRESS_REPORTER* aProgressReporter ); diff --git a/eeschema/erc/erc_item.cpp b/eeschema/erc/erc_item.cpp index db51338559..faeaec2995 100644 --- a/eeschema/erc/erc_item.cpp +++ b/eeschema/erc/erc_item.cpp @@ -148,14 +148,6 @@ ERC_ITEM ERC_ITEM::multipleNetNames( ERCE_DRIVER_CONFLICT, _( "More than one name given to this bus or net" ), wxT( "multiple_net_names" ) ); -ERC_ITEM ERC_ITEM::netclassConflict( ERCE_NETCLASS_CONFLICT, - _( "Conflicting netclass assignments" ), - wxT( "conflicting_netclasses" ) ); - -ERC_ITEM ERC_ITEM::overlappingRuleAreas( ERCE_OVERLAPPING_RULE_AREAS, - _( "Overlapping rule areas" ), - wxT( "overlapping_rule_areas" ) ); - ERC_ITEM ERC_ITEM::netNotBusMember( ERCE_BUS_ENTRY_CONFLICT, _( "Net is graphically connected to a bus but not a bus member" ), wxT( "net_not_bus_member" ) ); @@ -268,7 +260,6 @@ std::vector> ERC_ITEM::allItemTypes( ERC_ITEM::busToBusConflict, ERC_ITEM::busToNetConflict, ERC_ITEM::netNotBusMember, - ERC_ITEM::netclassConflict, ERC_ITEM::heading_misc, ERC_ITEM::unannotated, @@ -288,7 +279,6 @@ std::vector> ERC_ITEM::allItemTypes( ERC_ITEM::missingInputPin, ERC_ITEM::missingBidiPin, ERC_ITEM::missingPowerInputPin, - ERC_ITEM::overlappingRuleAreas, // ERC_ITEM types with no user-editable severities // NOTE: this MUST be the last grouping in the list! @@ -332,8 +322,6 @@ std::shared_ptr ERC_ITEM::Create( int aErrorCode ) case ERCE_BUS_ENTRY_CONFLICT: return std::make_shared( netNotBusMember ); case ERCE_BUS_TO_BUS_CONFLICT: return std::make_shared( busToBusConflict ); case ERCE_BUS_TO_NET_CONFLICT: return std::make_shared( busToNetConflict ); - case ERCE_NETCLASS_CONFLICT: return std::make_shared( netclassConflict ); - case ERCE_OVERLAPPING_RULE_AREAS: return std::make_shared( overlappingRuleAreas ); case ERCE_GLOBLABEL: return std::make_shared( globalLabelDangling ); case ERCE_UNRESOLVED_VARIABLE: return std::make_shared( unresolvedVariable ); case ERCE_UNDEFINED_NETCLASS: return std::make_shared( undefinedNetclass ); diff --git a/eeschema/erc/erc_item.h b/eeschema/erc/erc_item.h index f6ccbd4a2a..97d4e9aa78 100644 --- a/eeschema/erc/erc_item.h +++ b/eeschema/erc/erc_item.h @@ -223,8 +223,6 @@ private: static ERC_ITEM differentUnitNet; static ERC_ITEM busDefinitionConflict; static ERC_ITEM multipleNetNames; - static ERC_ITEM netclassConflict; - static ERC_ITEM overlappingRuleAreas; static ERC_ITEM netNotBusMember; static ERC_ITEM busToBusConflict; static ERC_ITEM busToNetConflict; diff --git a/eeschema/erc/erc_settings.h b/eeschema/erc/erc_settings.h index 82d81fdd19..1ebcc850d2 100644 --- a/eeschema/erc/erc_settings.h +++ b/eeschema/erc/erc_settings.h @@ -69,8 +69,6 @@ enum ERCE_T ///< one net. ERCE_BUS_TO_NET_CONFLICT, ///< A bus wire is graphically connected to a net port/pin ///< (or vice versa). - ERCE_NETCLASS_CONFLICT, ///< Multiple labels assign different netclasses to same net. - ERCE_OVERLAPPING_RULE_AREAS, ///< Rule areas are overlapping ERCE_GLOBLABEL, ///< A global label is unique. ERCE_UNRESOLVED_VARIABLE, ///< A text variable could not be resolved. ERCE_UNDEFINED_NETCLASS, ///< A netclass was referenced but not defined. diff --git a/eeschema/fields_grid_table.cpp b/eeschema/fields_grid_table.cpp index 679a2e1ceb..55a919a695 100644 --- a/eeschema/fields_grid_table.cpp +++ b/eeschema/fields_grid_table.cpp @@ -310,9 +310,9 @@ void FIELDS_GRID_TABLE::initGrid( WX_GRID* aGrid ) PROJECT_FILE& projectFile = editFrame->Prj().GetProjectFile(); const std::shared_ptr& settings = projectFile.NetSettings(); - existingNetclasses.push_back( settings->m_DefaultNetClass->GetName() ); + existingNetclasses.push_back( settings->GetDefaultNetclass()->GetName() ); - for( const auto& [ name, netclass ] : settings->m_NetClasses ) + for( const auto& [name, netclass] : settings->GetNetclasses() ) existingNetclasses.push_back( name ); // We don't need to re-cache the embedded fonts when looking at symbols in the schematic editor diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp index 17cf5f7993..fc98fdbb90 100644 --- a/eeschema/sch_edit_frame.cpp +++ b/eeschema/sch_edit_frame.cpp @@ -1771,6 +1771,9 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FL if( !ADVANCED_CFG::GetCfg().m_IncrementalConnectivity || aCleanupFlags == GLOBAL_CLEANUP || m_undoList.m_CommandsList.empty()|| Schematic().ConnectionGraph()->IsMinor() ) { + // Clear all resolved netclass caches in case labels have changed + Prj().GetProjectFile().NetSettings()->ClearAllCaches(); + // Update all rule areas so we can cascade implied connectivity changes std::unordered_set all_screens; @@ -1975,12 +1978,26 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FL new_graph.SetLastCodes( Schematic().ConnectionGraph() ); + std::shared_ptr netSettings = Prj().GetProjectFile().NetSettings(); + + std::set affectedNets; + for( auto&[ path, item ] : all_items ) { wxCHECK2( item, continue ); item->SetConnectivityDirty(); + SCH_CONNECTION* conn = item->Connection(); + + if( conn ) + { + affectedNets.insert( conn->Name() ); + } } + // Reset resolved netclass cache for this connection + for( const wxString& netName : affectedNets ) + netSettings->ClearCacheForNet( netName ); + new_graph.Recalculate( list, false, &changeHandler ); Schematic().ConnectionGraph()->Merge( new_graph ); } diff --git a/eeschema/sch_file_versions.h b/eeschema/sch_file_versions.h index d55bc39d98..e9f7778323 100644 --- a/eeschema/sch_file_versions.h +++ b/eeschema/sch_file_versions.h @@ -107,4 +107,5 @@ //#define SEXPR_SCHEMATIC_FILE_VERSION 20240101 // Tables. //#define SEXPR_SCHEMATIC_FILE_VERSION 20240417 // Rule areas //#define SEXPR_SCHEMATIC_FILE_VERSION 20240602 // Sheet attributes -#define SEXPR_SCHEMATIC_FILE_VERSION 20240620 // Embedded Files +//#define SEXPR_SCHEMATIC_FILE_VERSION 20240620 // Embedded Files +#define SEXPR_SCHEMATIC_FILE_VERSION 20240716 // Multiple netclass assignments diff --git a/eeschema/sch_io/altium/sch_io_altium.cpp b/eeschema/sch_io/altium/sch_io_altium.cpp index 19b01a4215..8a70de80f7 100644 --- a/eeschema/sch_io/altium/sch_io_altium.cpp +++ b/eeschema/sch_io/altium/sch_io_altium.cpp @@ -502,10 +502,10 @@ SCH_SHEET* SCH_IO_ALTIUM::LoadSchematicFile( const wxString& aFileName, SCHEMATI std::shared_ptr& netSettings = m_schematic->Prj().GetProjectFile().NetSettings(); if( minWireWidth < std::numeric_limits::max() ) - netSettings->m_DefaultNetClass->SetWireWidth( minWireWidth ); + netSettings->GetDefaultNetclass()->SetWireWidth( minWireWidth ); if( minBusWidth < std::numeric_limits::max() ) - netSettings->m_DefaultNetClass->SetBusWidth( minBusWidth ); + netSettings->GetDefaultNetclass()->SetBusWidth( minBusWidth ); return m_rootSheet; } diff --git a/eeschema/sch_item.cpp b/eeschema/sch_item.cpp index fc214f384e..6210e3eeae 100644 --- a/eeschema/sch_item.cpp +++ b/eeschema/sch_item.cpp @@ -261,7 +261,7 @@ std::shared_ptr SCH_ITEM::GetEffectiveNetClass( const SCH_SHEET_PATH* if( connection ) return netSettings->GetEffectiveNetClass( connection->Name() ); else - return netSettings->m_DefaultNetClass; + return netSettings->GetDefaultNetclass(); } return nullNetclass; diff --git a/eeschema/sch_label.cpp b/eeschema/sch_label.cpp index b8bf89c7ee..6bf6973619 100644 --- a/eeschema/sch_label.cpp +++ b/eeschema/sch_label.cpp @@ -807,7 +807,7 @@ bool SCH_LABEL_BASE::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* toke *token = wxEmptyString; if( connection ) - *token = GetEffectiveNetClass()->GetName(); + *token = GetEffectiveNetClass()->GetVariableSubstitutionName(); return true; } diff --git a/include/bitmaps/bitmaps_list.h b/include/bitmaps/bitmaps_list.h index a4f3fcbc4e..70c2928a76 100644 --- a/include/bitmaps/bitmaps_list.h +++ b/include/bitmaps/bitmaps_list.h @@ -577,6 +577,7 @@ enum class BITMAPS : unsigned int stroke_dashdotdot, stroke_dot, stroke_solid, + stroke_none, subtract_polygons, swap, swap_layer, diff --git a/include/dialogs/panel_setup_netclasses.h b/include/dialogs/panel_setup_netclasses.h index 4c39563465..a95d8469e7 100644 --- a/include/dialogs/panel_setup_netclasses.h +++ b/include/dialogs/panel_setup_netclasses.h @@ -51,6 +51,8 @@ public: private: void OnAddNetclassClick( wxCommandEvent& event ) override; void OnRemoveNetclassClick( wxCommandEvent& event ) override; + void OnMoveNetclassUpClick( wxCommandEvent& event ) override; + void OnMoveNetclassDownClick( wxCommandEvent& event ) override; void OnImportColorsClick( wxCommandEvent& event ) override; void OnSizeNetclassGrid( wxSizeEvent& event ) override; void OnSizeAssignmentGrid( wxSizeEvent& event ) override; @@ -72,6 +74,8 @@ private: void loadNetclasses(); void checkReload(); + void setNetclassRowNullableEditors( int aRowId, bool aIsDefault ); + private: EDA_DRAW_FRAME* m_frame; bool m_isEEschema; diff --git a/include/netclass.h b/include/netclass.h index 9fea1c4d80..114accd259 100644 --- a/include/netclass.h +++ b/include/netclass.h @@ -26,17 +26,17 @@ #ifndef CLASS_NETCLASS_H #define CLASS_NETCLASS_H -#include -#include #include + +#include +#include #include +#include using KIGFX::COLOR4D; - DECL_SET_FOR_SWIG( STRINGSET, wxString ) - /** * A collection of nets and the parameters used to route or test these nets. */ @@ -49,100 +49,229 @@ public: * Create a NETCLASS instance with \a aName. * The units on the optional parameters are Internal Units (1 nm) * @param aName is the name of this new netclass. + * @param aInitWithDefaults if true, initalise the netclass with default values */ - NETCLASS( const wxString& aName ); + NETCLASS( const wxString& aName, bool aInitWithDefaults = true ); - ~NETCLASS(); + ~NETCLASS(){}; + + bool operator==( const NETCLASS& other ) const; wxString GetClass() const { return wxT( "NETCLASS" ); } - const wxString GetName() const { return m_Name; } - void SetName( const wxString& aName ) { m_Name = aName; } + /// @brief Resets all parent fields to point to this netclass + void ResetParents(); + + /// @brief Resets all parameters (except Name and Description) + void ResetParameters(); + + /// @brief Gets the netclasses which make up this netclass + // For a root netcless, this is the netclass this pointer, for aggregate netclasses is contains + // all constituent netclasses, in order of priority. + const std::vector& GetConstituentNetclasses() const; + + /// @brief Sets the netclasses which make up this netclass + void SetConstituentNetclasses( std::vector&& constituents ); + + /// @brief Gets the name of this (maybe aggregate) netclass in a format for label variable + /// substitutions + const wxString GetVariableSubstitutionName() const; + + /// @brief Determines if the given netclass name is a constituent of this (maybe aggregate) + /// netclass + bool ContainsNetclassWithName( const wxString& netclass ) const; + + /// @ brief Determines if this is marked as the default netclass + const bool IsDefault() const { return m_isDefault; } + + /// @brief Gets the consolidated name of this netclass (which may be an aggregate) + const wxString GetName() const; + void SetName( const wxString& aName ) + { + m_Name = aName; + + if( aName == Default ) + m_isDefault = true; + } const wxString& GetDescription() const { return m_Description; } void SetDescription( const wxString& aDesc ) { m_Description = aDesc; } bool HasClearance() const { return (bool) m_Clearance; } int GetClearance() const { return m_Clearance.value_or(-1); } + std::optional GetClearanceOpt() const { return m_Clearance; } void SetClearance( int aClearance ) { m_Clearance = aClearance; } + void SetClearance( std::optional aClearance ) { m_Clearance = aClearance; } + void SetClearanceParent( NETCLASS* parent) { m_clearanceParent = parent; } + NETCLASS* GetClearanceParent() const { return m_clearanceParent; } bool HasTrackWidth() const { return (bool) m_TrackWidth; } int GetTrackWidth() const { return m_TrackWidth.value_or( -1 ); } + std::optional GetTrackWidthOpt() const { return m_TrackWidth; } void SetTrackWidth( int aWidth ) { m_TrackWidth = aWidth; } + void SetTrackWidth( std::optional aWidth ) { m_TrackWidth = aWidth; } + void SetTrackWidthParent( NETCLASS* parent) { m_trackWidthParent = parent; } + NETCLASS* GetTrackWidthParent() const { return m_trackWidthParent; } bool HasViaDiameter() const { return (bool) m_ViaDia; } int GetViaDiameter() const { return m_ViaDia.value_or( -1 ); } + std::optional GetViaDiameterOpt() const { return m_ViaDia; } void SetViaDiameter( int aDia ) { m_ViaDia = aDia; } + void SetViaDiameter( std::optional aDia ) { m_ViaDia = aDia; } + void SetViaDiameterParent( NETCLASS* parent) { m_viaDiameterParent = parent; } + NETCLASS* GetViaDiameterParent() const { return m_viaDiameterParent; } int HasViaDrill() const { return (bool) m_ViaDrill; } int GetViaDrill() const { return m_ViaDrill.value_or( -1 ); } + std::optional GetViaDrillOpt() const { return m_ViaDrill; } void SetViaDrill( int aSize ) { m_ViaDrill = aSize; } + void SetViaDrill( std::optional aSize ) { m_ViaDrill = aSize; } + void SetViaDrillParent( NETCLASS* parent) { m_viaDrillParent = parent; } + NETCLASS* GetViaDrillParent() const { return m_viaDrillParent; } bool HasuViaDiameter() const { return (bool) m_uViaDia; } int GetuViaDiameter() const { return m_uViaDia.value_or( -1 ); } + std::optional GetuViaDiameterOpt() const { return m_uViaDia; } void SetuViaDiameter( int aSize ) { m_uViaDia = aSize; } + void SetuViaDiameter( std::optional aSize ) { m_uViaDia = aSize; } + void SetuViaDiameterParent( NETCLASS* parent) { m_uViaDiaParent = parent; } + NETCLASS* GetuViaDiameterParent() const { return m_uViaDiaParent; } bool HasuViaDrill() const { return (bool) m_uViaDrill; } int GetuViaDrill() const { return m_uViaDrill.value_or( -1 ); } + std::optional GetuViaDrillOpt() const { return m_uViaDrill; } void SetuViaDrill( int aSize ) { m_uViaDrill = aSize; } + void SetuViaDrill( std::optional aSize ) { m_uViaDrill = aSize; } + void SetuViaDrillParent( NETCLASS* parent) { m_uViaDrillParent = parent; } + NETCLASS* GetuViaDrillParent() const { return m_uViaDrillParent; } bool HasDiffPairWidth() const { return (bool) m_diffPairWidth; } int GetDiffPairWidth() const { return m_diffPairWidth.value_or( -1 ); } + std::optional GetDiffPairWidthOpt() const { return m_diffPairWidth; } void SetDiffPairWidth( int aSize ) { m_diffPairWidth = aSize; } + void SetDiffPairWidth( std::optional aSize ) { m_diffPairWidth = aSize; } + void SetDiffPairWidthParent( NETCLASS* parent) { m_diffPairWidthParent = parent; } + NETCLASS* GetDiffPairWidthParent() const { return m_diffPairWidthParent; } bool HasDiffPairGap() const { return (bool) m_diffPairGap; } int GetDiffPairGap() const { return m_diffPairGap.value_or( -1 ); } + std::optional GetDiffPairGapOpt() const { return m_diffPairGap; } void SetDiffPairGap( int aSize ) { m_diffPairGap = aSize; } + void SetDiffPairGap( std::optional aSize ) { m_diffPairGap = aSize; } + void SetDiffPairGapParent( NETCLASS* parent) { m_diffPairGapParent = parent; } + NETCLASS* GetDiffPairGapParent() const { return m_diffPairGapParent; } bool HasDiffPairViaGap() const { return (bool) m_diffPairViaGap; } int GetDiffPairViaGap() const { return m_diffPairViaGap.value_or( -1 ); } + std::optional GetDiffPairViaGapOpt() const { return m_diffPairViaGap; } void SetDiffPairViaGap( int aSize ) { m_diffPairViaGap = aSize; } + void SetDiffPairViaGap( std::optional aSize ) { m_diffPairViaGap = aSize; } + void SetDiffPairViaGapParent( NETCLASS* parent) { m_diffPairViaGapParent = parent; } + NETCLASS* GetDiffPairViaGapParent() const { return m_diffPairViaGapParent; } - COLOR4D GetPcbColor() const { return m_PcbColor; } - void SetPcbColor( const COLOR4D& aColor ) { m_PcbColor = aColor; } + bool HasPcbColor() const { return m_isDefault ? false : m_pcbColor != COLOR4D::UNSPECIFIED; } + COLOR4D GetPcbColor( bool aIsForSave = false ) const + { + // If we are saving netclases, return the underlying color (which may be set from an old + // schematic with a default color set - this allows us to roll back the no-default-colors + // changes later if required) + if( aIsForSave || !m_isDefault ) + return m_pcbColor; - int GetWireWidth() const { return m_wireWidth; } + return COLOR4D::UNSPECIFIED; + } + void SetPcbColor( const COLOR4D& aColor ) { m_pcbColor = aColor; } + void SetPcbColorParent( NETCLASS* parent) { m_pcbColorParent = parent; } + NETCLASS* GetPcbColorParent() const { return m_pcbColorParent; } + + bool HasWireWidth() const { return (bool) m_wireWidth; } + int GetWireWidth() const { return m_wireWidth.value_or( -1 ); } + std::optional GetWireWidthOpt() const { return m_wireWidth; } void SetWireWidth( int aWidth ) { m_wireWidth = aWidth; } + void SetWireWidth( std::optional aWidth ) { m_wireWidth = aWidth; } + void SetWireWidthParent( NETCLASS* parent) { m_wireWidthParent = parent; } + NETCLASS* GetWireWidthParent() const { return m_wireWidthParent; } - int GetBusWidth() const { return m_busWidth; } + bool HasBusWidth() const { return (bool) m_busWidth; } + int GetBusWidth() const { return m_busWidth.value_or( -1 ); } + std::optional GetBusWidthOpt() const { return m_busWidth; } void SetBusWidth( int aWidth ) { m_busWidth = aWidth; } + void SetBusWidth( std::optional aWidth ) { m_busWidth = aWidth; } + void SetBusWidthParent( NETCLASS* parent) { m_busWidthParent = parent; } + NETCLASS* GetBusWidthParent() const { return m_busWidthParent; } - COLOR4D GetSchematicColor() const { return m_schematicColor; } + COLOR4D GetSchematicColor( bool aIsForSave = false ) const + { + // If we are saving netclases, return the underlying color (which may be set from an old + // schematic with a default color set - this allows us to roll back the no-default-colors + // changes later if required) + if( aIsForSave || !m_isDefault ) + return m_schematicColor; + + return COLOR4D::UNSPECIFIED; + } void SetSchematicColor( COLOR4D aColor ) { m_schematicColor = aColor; } + void SetSchematicColorParent( NETCLASS* parent) { m_schematicColorParent = parent; } + NETCLASS* GetSchematicColorParent() const { return m_schematicColorParent; } - int GetLineStyle() const { return m_lineStyle; } + bool HasLineStyle() const { return (bool) m_lineStyle; } + int GetLineStyle() const { return m_lineStyle.value_or( 0 ); } + std::optional GetLineStyleOpt() const { return m_lineStyle; } void SetLineStyle( int aStyle ) { m_lineStyle = aStyle; } + void SetLineStyle( std::optional aStyle ) { m_lineStyle = aStyle; } + void SetLineStyleParent( NETCLASS* parent) { m_lineStyleParent = parent; } + NETCLASS* GetLineStyleParent() const { return m_lineStyleParent; } + + void SetPriority( int aPriority ) { m_Priority = aPriority; } + int GetPriority() const { return m_Priority; } protected: - wxString m_Name; ///< Name of the net class - wxString m_Description; ///< what this NETCLASS is for. + bool m_isDefault; ///< Mark if this instance is the default netclass + std::vector m_constituents; ///< NETCLASSes contributing to an aggregate + wxString m_Name; ///< Name of the net class + int m_Priority; ///< The priority for multiple netclass resolution + wxString m_Description; ///< what this NETCLASS is for. - std::optional m_Clearance; ///< clearance when routing + std::optional m_Clearance; ///< clearance when routing - std::optional m_TrackWidth; ///< track width used to route NETs in this NETCLASS - std::optional m_ViaDia; ///< via diameter - std::optional m_ViaDrill; ///< via drill hole diameter + std::optional m_TrackWidth; ///< track width used to route nets + std::optional m_ViaDia; ///< via diameter + std::optional m_ViaDrill; ///< via drill hole diameter - std::optional m_uViaDia; ///< microvia diameter - std::optional m_uViaDrill; ///< microvia drill hole diameter + std::optional m_uViaDia; ///< microvia diameter + std::optional m_uViaDrill; ///< microvia drill hole diameter - std::optional m_diffPairWidth; - std::optional m_diffPairGap; - std::optional m_diffPairViaGap; + std::optional m_diffPairWidth; + std::optional m_diffPairGap; + std::optional m_diffPairViaGap; - int m_wireWidth; - int m_busWidth; - COLOR4D m_schematicColor; - int m_lineStyle; + std::optional m_wireWidth; + std::optional m_busWidth; + COLOR4D m_schematicColor; + std::optional m_lineStyle; - COLOR4D m_PcbColor; ///< Optional color override for this netclass (PCB context) + COLOR4D m_pcbColor; ///< Optional PCB color override for this netclass + + // The NETCLASS providing each parameter + NETCLASS* m_clearanceParent; + NETCLASS* m_trackWidthParent; + NETCLASS* m_viaDiameterParent; + NETCLASS* m_viaDrillParent; + NETCLASS* m_uViaDiaParent; + NETCLASS* m_uViaDrillParent; + NETCLASS* m_diffPairWidthParent; + NETCLASS* m_diffPairGapParent; + NETCLASS* m_diffPairViaGapParent; + NETCLASS* m_pcbColorParent; + NETCLASS* m_wireWidthParent; + NETCLASS* m_busWidthParent; + NETCLASS* m_schematicColorParent; + NETCLASS* m_lineStyleParent; }; - - #endif // CLASS_NETCLASS_H diff --git a/include/project/net_settings.h b/include/project/net_settings.h index e0f6542a02..5e012a44fc 100644 --- a/include/project/net_settings.h +++ b/include/project/net_settings.h @@ -22,6 +22,11 @@ #ifndef KICAD_NET_SETTINGS_H #define KICAD_NET_SETTINGS_H +#include +#include +#include +#include + #include #include #include @@ -41,26 +46,97 @@ public: bool operator!=( const NET_SETTINGS& aOther ) const { return !operator==( aOther ); } -public: - std::map> m_NetClasses; - std::shared_ptr m_DefaultNetClass; + /// @brief Sets the default netclass for the project + void SetDefaultNetclass( std::shared_ptr netclass ); - std::vector, wxString>> - m_NetClassPatternAssignments; - mutable std::map m_NetClassPatternAssignmentCache; + /// @brief Gets the default netclass for the project + std::shared_ptr GetDefaultNetclass(); - std::map m_NetClassLabelAssignments; + /// @brief Determines if the given netclass exists + bool HasNetclass( const wxString& netclassName ) const; - /** - * A map of fully-qualified net names to colors used in the board context. - * Since these color overrides are for the board, buses are not included here. - * Only nets that the user has assigned custom colors to will be in this list. - * Nets that no longer exist will be deleted during a netlist read in Pcbnew. - */ - std::map m_NetColorAssignments; + /// @brief Sets the given netclass + void SetNetclass( const wxString& netclassName, std::shared_ptr& netclass ); -public: - std::shared_ptr GetEffectiveNetClass( const wxString& aNetName ) const; + /// @brief Sets all netclass + void SetNetclasses( const std::map>& netclasses ); + + /// @brief Gets all netclasses + const std::map>& GetNetclasses() const; + + /// @brief Gets all composite (multiple assignment / missing defaults) netclasses + // Note the full connectivity or board net synchronisation must be run before calling + // this, otherwise resolved netclasses may be missing + const std::map>& GetCompositeNetclasses() const; + + /// @brief Clears all netclasses + void ClearNetclasses(); + + /// @brief Gets all current net name to netclasses assignments + const std::map>& GetNetclassLabelAssignments() const; + + /// @brief Clears all net name to netclasses assignments + void ClearNetclassLabelAssignments(); + + /// @brief Clears a specific net name to netclass assignment + void ClearNetclassLabelAssignment( const wxString& netName ); + + /// @brief Sets a net name to netclasses assignment + void SetNetclassLabelAssignment( const wxString& netName, + const std::set& netclasses ); + + /// @brief Apppends to a net name to netclasses assignment + void AppendNetclassLabelAssignment( const wxString& netName, + const std::set& netclasses ); + + /// @brief Determines if a given net name has netclasses assigned + bool HasNetclassLabelAssignment( const wxString& netName ) const; + + /// @brief Sets a netclass pattern assignment + void SetNetclassPatternAssignment( const wxString& pattern, const wxString& netclass ); + + /// @brief Sets all netclass pattern assignments + void SetNetclassPatternAssignments( + std::vector, wxString>>&& + netclassPatterns ); + + /// @brief Gets the netclass pattern assignments + std::vector, wxString>>& + GetNetclassPatternAssignments(); + + /// @brief Clears all netclass pattern assignments + void ClearNetclassPatternAssignments(); + + /// @brief Clears effective netclass cache for the given net + void ClearCacheForNet( const wxString& netName ); + + // @brief Clears the effective netclass cache for all nets + void ClearAllCaches(); + + /// @brief Sets a net to color assignment + void SetNetColorAssignment( const wxString& netName, const KIGFX::COLOR4D& color ); + + /// @brief Gets all net name to color assignments + const std::map& GetNetColorAssignments() const; + + /// @brief Clears all net name to color assignments + void ClearNetColorAssignments(); + + /// @brief Determines if an effective netclass for the given net name has been cached + bool HasEffectiveNetClass( const wxString& aNetName ) const; + + /// @brief Returns an already cached effective netclass for the given net name + /// @return The netclass, or default netclass if not found + std::shared_ptr GetCachedEffectiveNetClass( const wxString& aNetName ) const; + + /// @brief Fetches the effective (may be aggregate) netclass for the given net name + // If the effective netclass has not been computed, it will be created and cached. + std::shared_ptr GetEffectiveNetClass( const wxString& aNetName ); + + /// @brief Recomputes the internal values of all aggregate effective netclasses + // Called when a value of a user-defined netclass changes, but the whole netclass list is not + // being recomputed. + void RecomputeEffectiveNetclasses(); /** * Get a NETCLASS object from a given Netclass name string @@ -98,6 +174,59 @@ private: bool migrateSchema0to1(); bool migrateSchema1to2(); bool migrateSchema2to3(); + bool migrateSchema3to4(); + + /** + * @brief Creates an effective aggregate netclass from the given constituent netclasses + * + * Takes the aggregate parameters from the constituent netclasses in priority order. If any + * parameters are missing from the overall union, then they are filled from the default + * netclass. Note that the netclasses vector will have the default netclass added if it is used + * to provide missing defaults. The netclasses vector will be sorted by priority 1st and then + * name alphabetically + */ + void makeEffectiveNetclass( std::shared_ptr& effectiveNetclass, + std::vector& netclasses ) const; + + /// @brief Adds any missing fields to the given netclass from the default netclass + /// @returns true if any fields were added from the default netclass + bool addMissingDefaults( NETCLASS* nc ) const; + + /// @brief The default netclass + std::shared_ptr m_defaultNetClass; + + /// @brief Map of netclass names to netclass definitions + std::map> m_netClasses; + + /// @brief Map of net names to resolved netclasses + std::map> m_netClassLabelAssignments; + + /// @brief List of net class pattern assignments + std::vector, wxString>> + m_netClassPatternAssignments; + + /// @brief Map of netclass names to netclass definitions for + // composite (multiple netclass assignment / missing defaults) netclasses + std::map> m_compositeNetClasses; + + /// @brief Map of netclass names to netclass definitions for implicit netclasses + /// + /// Implicit netclasses are those which are in a netclass label, but which do not have a + /// netclass definition in the netclass setup panel. They contribute as a constituent + /// netclass to enable DRC rules and name resolution, but do not contribute parameters + // to the effective netclasses which contain them. + std::map> m_impicitNetClasses; + + /// @brief Cache of nets to pattern-matched netclasses + std::map> m_effectiveNetclassCache; + + /** + * A map of fully-qualified net names to colors used in the board context. + * Since these color overrides are for the board, buses are not included here. + * Only nets that the user has assigned custom colors to will be in this list. + * Nets that no longer exist will be deleted during a netlist read in Pcbnew. + */ + std::map m_netColorAssignments; // TODO: Add diff pairs, bus information, etc. }; diff --git a/include/units_provider.h b/include/units_provider.h index dce97632bc..ab340b0a83 100644 --- a/include/units_provider.h +++ b/include/units_provider.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include class UNITS_PROVIDER @@ -85,6 +87,30 @@ public: aAddUnitLabel, aType ); } + /** + * Converts an optional \a aValue in internal units into a united string. + * + * For readability, trailing 0s are removed if the mantissa has 3 or more digits. + * This function should be used to display values in dialogs because a value entered in mm + * (for instance 2.0 mm) could need up to 8 digits mantissa if displayed in inch to avoid + * truncation or rounding made just by the printf function. + * + * @param aValue = optional value in internal units + * @param aAddUnitLabel = true to add symbol unit to the string value + * @param aType is the type of this value, and controls the way the value is converted + * to a string, and the suitable unit + * @return A wxString object containing value and optionally the symbol unit (like 2.000 mm) + */ + wxString StringFromOptionalValue( std::optional aValue, bool aAddUnitLabel = false, + EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE ) const + { + if( !aValue ) + return NullUiString; + else + return EDA_UNIT_UTILS::UI::StringFromValue( GetIuScale(), GetUserUnits(), + aValue.value(), aAddUnitLabel, aType ); + } + wxString StringFromValue( const EDA_ANGLE& aValue, bool aAddUnitLabel = false ) const { return EDA_UNIT_UTILS::UI::StringFromValue( unityScale, EDA_UNITS::DEGREES, @@ -135,6 +161,30 @@ public: return KiROUND( value ); } + /** + * Converts \a aTextValue in \a aUnits to internal units used by the frame. Allows the return + * of an empty optional if the string represents a null value (currently empty string) + * @warning This utilizes the current locale and will break if decimal formats differ + * @param aType is the type of this value, and controls the way the string is converted + * to a value + * + * @param aTextValue A reference to a wxString object containing the string to convert. + * @return internal units value + */ + std::optional + OptionalValueFromString( const wxString& aTextValue, + EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE ) const + { + // Handle null (empty) values + if( aTextValue == NullUiString ) + return {}; + + double value = EDA_UNIT_UTILS::UI::DoubleValueFromString( GetIuScale(), GetUserUnits(), + aTextValue, aType ); + + return KiROUND( value ); + } + EDA_ANGLE AngleValueFromString( const wxString& aTextValue ) const { double angle = EDA_UNIT_UTILS::UI::DoubleValueFromString( GetIuScale(), EDA_UNITS::DEGREES, @@ -143,6 +193,9 @@ public: return EDA_ANGLE( angle, DEGREES_T ); } + /// @brief The string that is used in the UI to represent a null value + static inline const wxString NullUiString = ""; + private: const EDA_IU_SCALE& m_iuScale; EDA_UNITS m_userUnits; diff --git a/include/widgets/grid_icon_text_helpers.h b/include/widgets/grid_icon_text_helpers.h index 120df0f141..7f68f21f83 100644 --- a/include/widgets/grid_icon_text_helpers.h +++ b/include/widgets/grid_icon_text_helpers.h @@ -121,5 +121,29 @@ protected: }; +//---- Grid helpers: custom wxGridCellTextEditor ------------------------------------------ +// +// Note: This is used to mark WX_GRID cell as nullable +class GRID_CELL_MARK_AS_NULLABLE : public wxGridCellTextEditor +{ +public: + GRID_CELL_MARK_AS_NULLABLE() : m_isNullable( true ) {} + GRID_CELL_MARK_AS_NULLABLE( bool aIsNullable ) : m_isNullable( aIsNullable ) {} + + wxGridCellEditor* Clone() const override + { + return new GRID_CELL_MARK_AS_NULLABLE( m_isNullable ); + } + + void Reset() override {} + + bool IsNullable() { return m_isNullable; } + +protected: + bool m_isNullable; + + wxDECLARE_NO_COPY_CLASS( GRID_CELL_MARK_AS_NULLABLE ); +}; + #endif // GRID_ICON_TEXT_HELPERS_H diff --git a/include/widgets/wx_grid.h b/include/widgets/wx_grid.h index d225d565b0..9e027653be 100644 --- a/include/widgets/wx_grid.h +++ b/include/widgets/wx_grid.h @@ -24,15 +24,17 @@ #ifndef KICAD_WX_GRID_H #define KICAD_WX_GRID_H -#include -#include -#include #include +#include +#include +#include + #include #include #include -#include + #include +#include class wxTextEntryBase; @@ -123,15 +125,32 @@ public: /** * Apply standard KiCad unit and eval services to a numeric cell. + * @param aRow the cell row index to fetch + * @param aCol the cell column index to fetch + * @param aIsOptional if true, indicates to the unit provider the value is optional * @return the value held by the cell in internal units */ int GetUnitValue( int aRow, int aCol ); + + /** + * Apply standard KiCad unit and eval services to a numeric cell. + * @param aRow the cell row index to fetch + * @param aCol the cell column index to fetch + * @return the value held by the cell in internal units + */ + std::optional GetOptionalUnitValue( int aRow, int aCol ); + /** * Set a unitized cell's value. */ void SetUnitValue( int aRow, int aCol, int aValue ); + /** + * Set a unitized cell's optional value + */ + void SetOptionalUnitValue( int aRow, int aCol, std::optional aValue ); + /** * Calculates the specified column based on the actual size of the text * on screen. Will return the maximum value of all calculated widths. diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index dfce43ba7d..6e8d9a6912 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -126,8 +126,9 @@ BOARD::BOARD() : BOARD_DESIGN_SETTINGS& bds = GetDesignSettings(); // Initialize default netclass. - bds.m_NetSettings->m_DefaultNetClass = std::make_shared( NETCLASS::Default ); - bds.m_NetSettings->m_DefaultNetClass->SetDescription( _( "This is the default net class." ) ); + bds.m_NetSettings->SetDefaultNetclass( std::make_shared( NETCLASS::Default ) ); + bds.m_NetSettings->GetDefaultNetclass()->SetDescription( + _( "This is the default net class." ) ); bds.UseCustomTrackViaSize( false ); @@ -219,11 +220,10 @@ void BOARD::SetProject( PROJECT* aProject, bool aReferenceOnly ) std::shared_ptr legacySettings = GetDesignSettings().m_NetSettings; std::shared_ptr& projectSettings = project.NetSettings(); - projectSettings->m_DefaultNetClass = legacySettings->m_DefaultNetClass; - projectSettings->m_NetClasses = legacySettings->m_NetClasses; - projectSettings->m_NetClassPatternAssignments = - std::move( legacySettings->m_NetClassPatternAssignments ); - projectSettings->m_NetClassPatternAssignmentCache.clear(); + projectSettings->SetDefaultNetclass( legacySettings->GetDefaultNetclass() ); + projectSettings->SetNetclasses( legacySettings->GetNetclasses() ); + projectSettings->SetNetclassPatternAssignments( + std::move( legacySettings->GetNetclassPatternAssignments() ) ); } // Now update the DesignSettings' netclass pointer to point into the project. @@ -2037,7 +2037,9 @@ void BOARD::SynchronizeNetsAndNetClasses( bool aResetTrackAndViaSizes ) return; BOARD_DESIGN_SETTINGS& bds = GetDesignSettings(); - std::shared_ptr& defaultNetClass = bds.m_NetSettings->m_DefaultNetClass; + const std::shared_ptr& defaultNetClass = bds.m_NetSettings->GetDefaultNetclass(); + + bds.m_NetSettings->ClearAllCaches(); for( NETINFO_ITEM* net : m_NetInfo ) net->SetNetClass( bds.m_NetSettings->GetEffectiveNetClass( net->GetNetname() ) ); diff --git a/pcbnew/board_connected_item.cpp b/pcbnew/board_connected_item.cpp index c21d3f09ea..b0f641a5d5 100644 --- a/pcbnew/board_connected_item.cpp +++ b/pcbnew/board_connected_item.cpp @@ -101,7 +101,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetEffectiveNetClass() const if( m_netinfo && m_netinfo->GetNetClass() ) return m_netinfo->GetNetClass(); else - return GetBoard()->GetDesignSettings().m_NetSettings->m_DefaultNetClass.get(); + return GetBoard()->GetDesignSettings().m_NetSettings->GetDefaultNetclass().get(); } @@ -111,6 +111,12 @@ wxString BOARD_CONNECTED_ITEM::GetNetClassName() const } +wxString BOARD_CONNECTED_ITEM::GetNetClassVariableSubstitutionName() const +{ + return GetEffectiveNetClass()->GetVariableSubstitutionName(); +} + + wxString BOARD_CONNECTED_ITEM::GetNetname() const { return m_netinfo ? m_netinfo->GetNetname() : wxString(); diff --git a/pcbnew/board_connected_item.h b/pcbnew/board_connected_item.h index 8150cc9a29..59bf1a1b6d 100644 --- a/pcbnew/board_connected_item.h +++ b/pcbnew/board_connected_item.h @@ -185,6 +185,11 @@ public: */ wxString GetNetClassName() const; + /* + * Returns the name of the effective netclass for variable substitutions + */ + wxString GetNetClassVariableSubstitutionName() const; + void SetLocalRatsnestVisible( bool aVisible ) { m_localRatsnestVisible = aVisible; } bool GetLocalRatsnestVisible() const { return m_localRatsnestVisible; } diff --git a/pcbnew/board_design_settings.cpp b/pcbnew/board_design_settings.cpp index 43bd3e70ea..cdb848cc4a 100644 --- a/pcbnew/board_design_settings.cpp +++ b/pcbnew/board_design_settings.cpp @@ -1274,9 +1274,9 @@ int BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue() const int BOARD_DESIGN_SETTINGS::GetSmallestClearanceValue() const { - int clearance = m_NetSettings->m_DefaultNetClass->GetClearance(); + int clearance = m_NetSettings->GetDefaultNetclass()->GetClearance(); - for( const auto& [ name, netclass ] : m_NetSettings->m_NetClasses ) + for( const auto& [name, netclass] : m_NetSettings->GetNetclasses() ) clearance = std::min( clearance, netclass->GetClearance() ); return clearance; @@ -1295,7 +1295,7 @@ int BOARD_DESIGN_SETTINGS::GetCurrentViaSize() const if( m_useCustomTrackVia ) return m_customViaSize.m_Diameter; else if( m_viaSizeIndex == 0 ) - return m_NetSettings->m_DefaultNetClass->GetViaDiameter(); + return m_NetSettings->GetDefaultNetclass()->GetViaDiameter(); else return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter; } @@ -1308,7 +1308,7 @@ int BOARD_DESIGN_SETTINGS::GetCurrentViaDrill() const if( m_useCustomTrackVia ) drill = m_customViaSize.m_Drill; else if( m_viaSizeIndex == 0 ) - drill = m_NetSettings->m_DefaultNetClass->GetViaDrill(); + drill = m_NetSettings->GetDefaultNetclass()->GetViaDrill(); else drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill; @@ -1328,7 +1328,7 @@ int BOARD_DESIGN_SETTINGS::GetCurrentTrackWidth() const if( m_useCustomTrackVia ) return m_customTrackWidth; else if( m_trackWidthIndex == 0 ) - return m_NetSettings->m_DefaultNetClass->GetTrackWidth(); + return m_NetSettings->GetDefaultNetclass()->GetTrackWidth(); else return m_TrackWidthList[ m_trackWidthIndex ]; } @@ -1354,10 +1354,10 @@ int BOARD_DESIGN_SETTINGS::GetCurrentDiffPairWidth() const } else if( m_diffPairIndex == 0 ) { - if( m_NetSettings->m_DefaultNetClass->HasDiffPairWidth() ) - return m_NetSettings->m_DefaultNetClass->GetDiffPairWidth(); + if( m_NetSettings->GetDefaultNetclass()->HasDiffPairWidth() ) + return m_NetSettings->GetDefaultNetclass()->GetDiffPairWidth(); else - return m_NetSettings->m_DefaultNetClass->GetTrackWidth(); + return m_NetSettings->GetDefaultNetclass()->GetTrackWidth(); } else { @@ -1374,10 +1374,10 @@ int BOARD_DESIGN_SETTINGS::GetCurrentDiffPairGap() const } else if( m_diffPairIndex == 0 ) { - if( m_NetSettings->m_DefaultNetClass->HasDiffPairGap() ) - return m_NetSettings->m_DefaultNetClass->GetDiffPairGap(); + if( m_NetSettings->GetDefaultNetclass()->HasDiffPairGap() ) + return m_NetSettings->GetDefaultNetclass()->GetDiffPairGap(); else - return m_NetSettings->m_DefaultNetClass->GetClearance(); + return m_NetSettings->GetDefaultNetclass()->GetClearance(); } else { @@ -1394,8 +1394,8 @@ int BOARD_DESIGN_SETTINGS::GetCurrentDiffPairViaGap() const } else if( m_diffPairIndex == 0 ) { - if( m_NetSettings->m_DefaultNetClass->HasDiffPairViaGap() ) - return m_NetSettings->m_DefaultNetClass->GetDiffPairViaGap(); + if( m_NetSettings->GetDefaultNetclass()->HasDiffPairViaGap() ) + return m_NetSettings->GetDefaultNetclass()->GetDiffPairViaGap(); else return GetCurrentDiffPairGap(); } diff --git a/pcbnew/connectivity/connectivity_data.cpp b/pcbnew/connectivity/connectivity_data.cpp index 9e35055787..0df5490e48 100644 --- a/pcbnew/connectivity/connectivity_data.cpp +++ b/pcbnew/connectivity/connectivity_data.cpp @@ -110,20 +110,12 @@ bool CONNECTIVITY_DATA::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter ) aReporter->KeepRefreshing( false ); } - std::shared_ptr& netSettings = aBoard->GetDesignSettings().m_NetSettings; - m_connAlgo.reset( new CN_CONNECTIVITY_ALGO( this ) ); m_connAlgo->Build( aBoard, aReporter ); - m_netclassMap.clear(); + m_netSettings = aBoard->GetDesignSettings().m_NetSettings; - for( NETINFO_ITEM* net : aBoard->GetNetInfo() ) - { - net->SetNetClass( netSettings->GetEffectiveNetClass( net->GetNetname() ) ); - - if( net->GetNetClass()->GetName() != NETCLASS::Default ) - m_netclassMap[ net->GetNetCode() ] = net->GetNetClass()->GetName(); - } + RefreshNetcodeMap( aBoard ); if( aReporter ) { @@ -143,6 +135,15 @@ bool CONNECTIVITY_DATA::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter ) } +void CONNECTIVITY_DATA::RefreshNetcodeMap( BOARD* aBoard ) +{ + m_netcodeMap.clear(); + + for( NETINFO_ITEM* net : aBoard->GetNetInfo() ) + m_netcodeMap[net->GetNetCode()] = net->GetNetname(); +} + + void CONNECTIVITY_DATA::Build( std::shared_ptr& aGlobalConnectivity, const std::vector& aLocalItems ) { diff --git a/pcbnew/connectivity/connectivity_data.h b/pcbnew/connectivity/connectivity_data.h index 8081d22256..0cfc9d4624 100644 --- a/pcbnew/connectivity/connectivity_data.h +++ b/pcbnew/connectivity/connectivity_data.h @@ -37,6 +37,7 @@ #include #include +#include #include class FROM_TO_CACHE; @@ -270,7 +271,13 @@ public: void SetProgressReporter( PROGRESS_REPORTER* aReporter ); - const std::map& GetNetclassMap() const { return m_netclassMap; } + const NET_SETTINGS* GetNetSettings() const { return m_netSettings.get(); } + + bool HasNetNameForNetCode( int nc ) const { return m_netcodeMap.count( nc ) > 0; } + const wxString& GetNetNameForNetCode( int nc ) const { return m_netcodeMap.at( nc ); } + + /// @brief Refresh the map of netcodes to net names + void RefreshNetcodeMap( BOARD* aBoard ); #ifndef SWIG const std::vector GetRatsnestForItems( const std::vector& aItems ); @@ -306,10 +313,13 @@ private: KISPINLOCK m_lock; - /// Map of netcode -> netclass the net is a member of; used for ratsnest painting - std::map m_netclassMap; - PROGRESS_REPORTER* m_progressReporter; + + /// @brief Used to get netclass data when drawing ratsnests + std::shared_ptr m_netSettings; + + /// @brief Used to map netcode to net name + std::map m_netcodeMap; }; #endif diff --git a/pcbnew/dialogs/dialog_global_edit_teardrops.cpp b/pcbnew/dialogs/dialog_global_edit_teardrops.cpp index 8a5747b2c8..94ce47ca7f 100644 --- a/pcbnew/dialogs/dialog_global_edit_teardrops.cpp +++ b/pcbnew/dialogs/dialog_global_edit_teardrops.cpp @@ -21,6 +21,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#include + #include #include #include @@ -215,9 +217,9 @@ void DIALOG_GLOBAL_EDIT_TEARDROPS::buildFilterLists() wxArrayString netclassNames; std::shared_ptr& settings = m_brd->GetDesignSettings().m_NetSettings; - netclassNames.push_back( settings->m_DefaultNetClass->GetName() ); + netclassNames.push_back( settings->GetDefaultNetclass()->GetName() ); - for( const auto& [ name, netclass ] : settings->m_NetClasses ) + for( const auto& [name, netclass] : settings->GetNetclasses() ) netclassNames.push_back( name ); m_netclassFilter->Set( netclassNames ); @@ -246,7 +248,8 @@ bool DIALOG_GLOBAL_EDIT_TEARDROPS::TransferDataToWindow() if( g_filterByNetclass && m_netclassFilter->SetStringSelection( g_netclassFilter ) ) m_netclassFilterOpt->SetValue( true ); else if( item ) - m_netclassFilter->SetStringSelection( item->GetNet()->GetNetClass()->GetName() ); + m_netclassFilter->SetStringSelection( + item->GetNet()->GetNetClass()->GetVariableSubstitutionName() ); if( g_filterByNet && m_brd->FindNet( g_netFilter ) != nullptr ) { @@ -387,7 +390,10 @@ void DIALOG_GLOBAL_EDIT_TEARDROPS::visitItem( BOARD_COMMIT* aCommit, BOARD_CONNE if( m_netclassFilterOpt->GetValue() && !m_netclassFilter->GetStringSelection().IsEmpty() ) { - if( aItem->GetEffectiveNetClass()->GetName() != m_netclassFilter->GetStringSelection() ) + wxString filterNetclass = m_netclassFilter->GetStringSelection(); + NETCLASS* netclass = aItem->GetEffectiveNetClass(); + + if( !netclass->ContainsNetclassWithName( filterNetclass ) ) return; } diff --git a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp index 611a4ae03e..fdeda7651c 100644 --- a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp +++ b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp @@ -22,6 +22,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#include + #include #include #include @@ -209,9 +211,9 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::buildFilterLists() wxArrayString netclassNames; std::shared_ptr& settings = m_brd->GetDesignSettings().m_NetSettings; - netclassNames.push_back( settings->m_DefaultNetClass->GetName() ); + netclassNames.push_back( settings->GetDefaultNetclass()->GetName() ); - for( const auto& [ name, netclass ] : settings->m_NetClasses ) + for( const auto& [name, netclass] : settings->GetNetclasses() ) netclassNames.push_back( name ); m_netclassFilter->Set( netclassNames ); @@ -238,7 +240,8 @@ bool DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::TransferDataToWindow() if( g_filterByNetclass && m_netclassFilter->SetStringSelection( g_netclassFilter ) ) m_netclassFilterOpt->SetValue( true ); else if( item ) - m_netclassFilter->SetStringSelection( item->GetNet()->GetNetClass()->GetName() ); + m_netclassFilter->SetStringSelection( + item->GetNet()->GetNetClass()->GetVariableSubstitutionName() ); if( g_filterByNet && m_brd->FindNet( g_netFilter ) != nullptr ) { @@ -382,7 +385,10 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::visitItem( PICKED_ITEMS_LIST* aUndoList if( m_netclassFilterOpt->GetValue() && !m_netclassFilter->GetStringSelection().IsEmpty() ) { - if( aItem->GetEffectiveNetClass()->GetName() != m_netclassFilter->GetStringSelection() ) + wxString filterNetclass = m_netclassFilter->GetStringSelection(); + NETCLASS* netclass = aItem->GetEffectiveNetClass(); + + if( !netclass->ContainsNetclassWithName( filterNetclass ) ) return; } diff --git a/pcbnew/dialogs/panel_setup_rules.cpp b/pcbnew/dialogs/panel_setup_rules.cpp index ce6e154769..a1fccabf66 100644 --- a/pcbnew/dialogs/panel_setup_rules.cpp +++ b/pcbnew/dialogs/panel_setup_rules.cpp @@ -508,7 +508,7 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent ) BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings(); std::shared_ptr& netSettings = bds.m_NetSettings; - for( const auto& [ name, netclass ] : netSettings->m_NetClasses ) + for( const auto& [name, netclass] : netSettings->GetNetclasses() ) tokens += wxT( "|" ) + name; } else if( m_netNameRegex.Matches( last ) ) diff --git a/pcbnew/dialogs/panel_setup_rules_help.md b/pcbnew/dialogs/panel_setup_rules_help.md index 7868f427cd..67bcfc4e95 100644 --- a/pcbnew/dialogs/panel_setup_rules_help.md +++ b/pcbnew/dialogs/panel_setup_rules_help.md @@ -179,6 +179,11 @@ the canonical name (ie: `F.Cu`). NB: this returns true if `A` is on the given layer, independently of whether or not the rule is being evaluated for that layer. For the latter use a `(layer "layer_name")` clause in the rule. +

+ + A.hasNetclass('') +True if `A` has had the given netclass assigned to it, either by an explicit netclass label +or through a pattern match assignment.

### More Examples diff --git a/pcbnew/dialogs/panel_setup_rules_help_md.h b/pcbnew/dialogs/panel_setup_rules_help_md.h index 18dec6c7dc..7383674ef8 100644 --- a/pcbnew/dialogs/panel_setup_rules_help_md.h +++ b/pcbnew/dialogs/panel_setup_rules_help_md.h @@ -182,6 +182,11 @@ _HKI( "### Top-level Clauses\n" "For the latter use a `(layer \"layer_name\")` clause in the rule.\n" "

\n" "\n" +" A.hasNetclass('')\n" +"True if `A` has had the given netclass assigned to it, either by an explicit netclass label \n" +"or through a pattern match assignment.\n" +"

\n" +"\n" "### More Examples\n" "\n" " (rule \"copper keepout\"\n" diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp index 9c7c85eb80..22e0d48196 100644 --- a/pcbnew/drc/drc_engine.cpp +++ b/pcbnew/drc/drc_engine.cpp @@ -229,48 +229,50 @@ void DRC_ENGINE::loadImplicitRules() auto makeNetclassRules = [&]( const std::shared_ptr& nc, bool isDefault ) { - wxString ncName = nc->GetName(); - wxString friendlyName; - wxString* shownName = &ncName; - wxString expr; + wxString ncName = nc->GetVariableSubstitutionName(); + wxString friendlyName = nc->GetName(); + wxString expr; - if( ncName.Replace( "'", "\\'" ) ) - { - friendlyName = nc->GetName(); - shownName = &friendlyName; - } + ncName.Replace( "'", "\\'" ); - if( nc->GetClearance() || nc->GetTrackWidth() ) + if( nc->HasClearance()) { std::shared_ptr netclassRule = std::make_shared(); - netclassRule->m_Name = wxString::Format( _( "netclass '%s'" ), *shownName ); + netclassRule->m_Name = wxString::Format( _( "netclass '%s'" ), + nc->GetClearanceParent()->GetName() ); netclassRule->m_Implicit = true; expr = wxString::Format( wxT( "A.NetClass == '%s'" ), ncName ); netclassRule->m_Condition = new DRC_RULE_CONDITION( expr ); netclassClearanceRules.push_back( netclassRule ); - if( nc->GetClearance() ) - { - DRC_CONSTRAINT constraint( CLEARANCE_CONSTRAINT ); - constraint.Value().SetMin( nc->GetClearance() ); - netclassRule->AddConstraint( constraint ); - } - - if( nc->GetTrackWidth() ) - { - DRC_CONSTRAINT constraint( TRACK_WIDTH_CONSTRAINT ); - constraint.Value().SetMin( bds.m_TrackMinWidth ); - constraint.Value().SetOpt( nc->GetTrackWidth() ); - netclassRule->AddConstraint( constraint ); - } + DRC_CONSTRAINT constraint( CLEARANCE_CONSTRAINT ); + constraint.Value().SetMin( nc->GetClearance() ); + netclassRule->AddConstraint( constraint ); } - if( nc->GetDiffPairWidth() ) + if( nc->HasTrackWidth() ) + { + std::shared_ptr netclassRule = std::make_shared(); + netclassRule->m_Name = wxString::Format( _( "netclass '%s'" ), + nc->GetTrackWidthParent()->GetName() ); + netclassRule->m_Implicit = true; + + expr = wxString::Format( wxT( "A.NetClass == '%s'" ), ncName ); + netclassRule->m_Condition = new DRC_RULE_CONDITION( expr ); + netclassClearanceRules.push_back( netclassRule ); + + DRC_CONSTRAINT constraint( TRACK_WIDTH_CONSTRAINT ); + constraint.Value().SetMin( bds.m_TrackMinWidth ); + constraint.Value().SetOpt( nc->GetTrackWidth() ); + netclassRule->AddConstraint( constraint ); + } + + if( nc->HasDiffPairWidth() ) { std::shared_ptr netclassRule = std::make_shared(); netclassRule->m_Name = wxString::Format( _( "netclass '%s' (diff pair)" ), - *shownName ); + nc->GetDiffPairWidthParent()->GetName() ); netclassRule->m_Implicit = true; expr = wxString::Format( wxT( "A.NetClass == '%s' && A.inDiffPair('*')" ), @@ -284,11 +286,11 @@ void DRC_ENGINE::loadImplicitRules() netclassRule->AddConstraint( constraint ); } - if( nc->GetDiffPairGap() ) + if( nc->HasDiffPairGap() ) { std::shared_ptr netclassRule = std::make_shared(); netclassRule->m_Name = wxString::Format( _( "netclass '%s' (diff pair)" ), - *shownName ); + nc->GetDiffPairGapParent()->GetName() ); netclassRule->m_Implicit = true; expr = wxString::Format( wxT( "A.NetClass == '%s'" ), ncName ); @@ -305,7 +307,7 @@ void DRC_ENGINE::loadImplicitRules() { netclassRule = std::make_shared(); netclassRule->m_Name = wxString::Format( _( "netclass '%s' (diff pair)" ), - *shownName ); + nc->GetDiffPairGapParent()->GetName() ); netclassRule->m_Implicit = true; expr = wxString::Format( wxT( "A.NetClass == '%s' && AB.isCoupledDiffPair()" ), @@ -319,10 +321,11 @@ void DRC_ENGINE::loadImplicitRules() } } - if( nc->GetViaDiameter() || nc->GetViaDrill() ) + if( nc->HasViaDiameter() ) { std::shared_ptr netclassRule = std::make_shared(); - netclassRule->m_Name = wxString::Format( _( "netclass '%s'" ), *shownName ); + netclassRule->m_Name = wxString::Format( _( "netclass '%s'" ), + nc->GetViaDiameterParent()->GetName() ); netclassRule->m_Implicit = true; expr = wxString::Format( wxT( "A.NetClass == '%s' && A.Via_Type != 'Micro'" ), @@ -330,28 +333,35 @@ void DRC_ENGINE::loadImplicitRules() netclassRule->m_Condition = new DRC_RULE_CONDITION( expr ); netclassItemSpecificRules.push_back( netclassRule ); - if( nc->GetViaDiameter() ) - { - DRC_CONSTRAINT constraint( VIA_DIAMETER_CONSTRAINT ); - constraint.Value().SetMin( bds.m_ViasMinSize ); - constraint.Value().SetOpt( nc->GetViaDiameter() ); - netclassRule->AddConstraint( constraint ); - } - - if( nc->GetViaDrill() ) - { - DRC_CONSTRAINT constraint( HOLE_SIZE_CONSTRAINT ); - constraint.Value().SetMin( bds.m_MinThroughDrill ); - constraint.Value().SetOpt( nc->GetViaDrill() ); - netclassRule->AddConstraint( constraint ); - } + DRC_CONSTRAINT constraint( VIA_DIAMETER_CONSTRAINT ); + constraint.Value().SetMin( bds.m_ViasMinSize ); + constraint.Value().SetOpt( nc->GetViaDiameter() ); + netclassRule->AddConstraint( constraint ); } - if( nc->GetuViaDiameter() || nc->GetuViaDrill() ) + if( nc->HasViaDrill() ) + { + std::shared_ptr netclassRule = std::make_shared(); + netclassRule->m_Name = wxString::Format( _( "netclass '%s'" ), + nc->GetViaDrillParent()->GetName() ); + netclassRule->m_Implicit = true; + + expr = wxString::Format( wxT( "A.NetClass == '%s' && A.Via_Type != 'Micro'" ), + ncName ); + netclassRule->m_Condition = new DRC_RULE_CONDITION( expr ); + netclassItemSpecificRules.push_back( netclassRule ); + + DRC_CONSTRAINT constraint( HOLE_SIZE_CONSTRAINT ); + constraint.Value().SetMin( bds.m_MinThroughDrill ); + constraint.Value().SetOpt( nc->GetViaDrill() ); + netclassRule->AddConstraint( constraint ); + } + + if( nc->HasuViaDiameter() ) { std::shared_ptr netclassRule = std::make_shared(); netclassRule->m_Name = wxString::Format( _( "netclass '%s' (uvia)" ), - *shownName ); + nc->GetuViaDiameterParent()->GetName() ); netclassRule->m_Implicit = true; expr = wxString::Format( wxT( "A.NetClass == '%s' && A.Via_Type == 'Micro'" ), @@ -359,28 +369,38 @@ void DRC_ENGINE::loadImplicitRules() netclassRule->m_Condition = new DRC_RULE_CONDITION( expr ); netclassItemSpecificRules.push_back( netclassRule ); - if( nc->GetuViaDiameter() ) - { - DRC_CONSTRAINT constraint( VIA_DIAMETER_CONSTRAINT ); - constraint.Value().SetMin( bds.m_MicroViasMinSize ); - constraint.Value().SetMin( nc->GetuViaDiameter() ); - netclassRule->AddConstraint( constraint ); - } + DRC_CONSTRAINT constraint( VIA_DIAMETER_CONSTRAINT ); + constraint.Value().SetMin( bds.m_MicroViasMinSize ); + constraint.Value().SetMin( nc->GetuViaDiameter() ); + netclassRule->AddConstraint( constraint ); + } - if( nc->GetuViaDrill() ) - { - DRC_CONSTRAINT constraint( HOLE_SIZE_CONSTRAINT ); - constraint.Value().SetMin( bds.m_MicroViasMinDrill ); - constraint.Value().SetOpt( nc->GetuViaDrill() ); - netclassRule->AddConstraint( constraint ); - } + if( nc->HasuViaDrill() ) + { + std::shared_ptr netclassRule = std::make_shared(); + netclassRule->m_Name = wxString::Format( _( "netclass '%s' (uvia)" ), + nc->GetuViaDrillParent()->GetName() ); + netclassRule->m_Implicit = true; + + expr = wxString::Format( wxT( "A.NetClass == '%s' && A.Via_Type == 'Micro'" ), + ncName ); + netclassRule->m_Condition = new DRC_RULE_CONDITION( expr ); + netclassItemSpecificRules.push_back( netclassRule ); + + DRC_CONSTRAINT constraint( HOLE_SIZE_CONSTRAINT ); + constraint.Value().SetMin( bds.m_MicroViasMinDrill ); + constraint.Value().SetOpt( nc->GetuViaDrill() ); + netclassRule->AddConstraint( constraint ); } }; m_board->SynchronizeNetsAndNetClasses( false ); - makeNetclassRules( bds.m_NetSettings->m_DefaultNetClass, true ); + makeNetclassRules( bds.m_NetSettings->GetDefaultNetclass(), true ); - for( const auto& [ name, netclass ] : bds.m_NetSettings->m_NetClasses ) + for( const auto& [name, netclass] : bds.m_NetSettings->GetNetclasses() ) + makeNetclassRules( netclass, false ); + + for( const auto& [name, netclass] : bds.m_NetSettings->GetCompositeNetclasses() ) makeNetclassRules( netclass, false ); // The netclass clearance rules have to be sorted by min clearance so the right one fires diff --git a/pcbnew/exporters/gerber_jobfile_writer.cpp b/pcbnew/exporters/gerber_jobfile_writer.cpp index 4b99e07179..0e7a4d02a6 100644 --- a/pcbnew/exporters/gerber_jobfile_writer.cpp +++ b/pcbnew/exporters/gerber_jobfile_writer.cpp @@ -456,11 +456,11 @@ void GERBER_JOBFILE_WRITER::addJSONDesignRules() // Job file support a few design rules: std::shared_ptr& netSettings = m_pcb->GetDesignSettings().m_NetSettings; - int minclearanceOuter = netSettings->m_DefaultNetClass->GetClearance(); + int minclearanceOuter = netSettings->GetDefaultNetclass()->GetClearance(); bool hasInnerLayers = m_pcb->GetCopperLayerCount() > 2; // Search a smaller clearance in other net classes, if any. - for( const auto& [ name, netclass ] : netSettings->m_NetClasses ) + for( const auto& [name, netclass] : netSettings->GetNetclasses() ) minclearanceOuter = std::min( minclearanceOuter, netclass->GetClearance() ); // job file knows different clearance types. @@ -470,8 +470,8 @@ void GERBER_JOBFILE_WRITER::addJSONDesignRules() // However, pads can have a specific clearance defined for a pad or a footprint, // and min clearance can be dependent on layers. // Search for a minimal pad clearance: - int minPadClearanceOuter = netSettings->m_DefaultNetClass->GetClearance(); - int minPadClearanceInner = netSettings->m_DefaultNetClass->GetClearance(); + int minPadClearanceOuter = netSettings->GetDefaultNetclass()->GetClearance(); + int minPadClearanceInner = netSettings->GetDefaultNetclass()->GetClearance(); for( FOOTPRINT* footprint : m_pcb->Footprints() ) { diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index 46d024ce94..0dec468fcc 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -950,7 +950,7 @@ bool FOOTPRINT::ResolveTextVar( wxString* token, int aDepth ) const else if( token->StartsWith( wxT( "NET_NAME" ) ) ) *token = pad->GetNetname(); else if( token->StartsWith( wxT( "NET_CLASS" ) ) ) - *token = pad->GetNetClassName(); + *token = pad->GetNetClassVariableSubstitutionName(); else *token = pad->GetPinFunction(); diff --git a/pcbnew/footprint_edit_frame.cpp b/pcbnew/footprint_edit_frame.cpp index 1ce6b5f0b6..0240e9892f 100644 --- a/pcbnew/footprint_edit_frame.cpp +++ b/pcbnew/footprint_edit_frame.cpp @@ -150,7 +150,7 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : // In Footprint Editor, the default net clearance is not known (it depends on the actual // board). So we do not show the default clearance, by setting it to 0. The footprint or // pad specific clearance will be shown. - GetBoard()->GetDesignSettings().m_NetSettings->m_DefaultNetClass->SetClearance( 0 ); + GetBoard()->GetDesignSettings().m_NetSettings->GetDefaultNetclass()->SetClearance( 0 ); // Don't show the default board solder mask expansion in the footprint editor. Only the // footprint or pad mask expansions settings should be shown. diff --git a/pcbnew/footprint_viewer_frame.cpp b/pcbnew/footprint_viewer_frame.cpp index e4d274d11e..aea8249350 100644 --- a/pcbnew/footprint_viewer_frame.cpp +++ b/pcbnew/footprint_viewer_frame.cpp @@ -193,7 +193,7 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent // In viewer, the default net clearance is not known (it depends on the actual board). // So we do not show the default clearance, by setting it to 0 // The footprint or pad specific clearance will be shown - GetBoard()->GetDesignSettings().m_NetSettings->m_DefaultNetClass->SetClearance( 0 ); + GetBoard()->GetDesignSettings().m_NetSettings->GetDefaultNetclass()->SetClearance( 0 ); // Don't show the default board solder mask clearance in the footprint viewer. Only the // footprint or pad clearance setting should be shown if it is not 0. diff --git a/pcbnew/footprint_wizard_frame.cpp b/pcbnew/footprint_wizard_frame.cpp index c67e201086..a82db94b32 100644 --- a/pcbnew/footprint_wizard_frame.cpp +++ b/pcbnew/footprint_wizard_frame.cpp @@ -131,7 +131,7 @@ FOOTPRINT_WIZARD_FRAME::FOOTPRINT_WIZARD_FRAME( KIWAY* aKiway, wxWindow* aParent // In viewer, the default net clearance is not known (it depends on the actual board). // So we do not show the default clearance, by setting it to 0 // The footprint or pad specific clearance will be shown - GetBoard()->GetDesignSettings().m_NetSettings->m_DefaultNetClass->SetClearance( 0 ); + GetBoard()->GetDesignSettings().m_NetSettings->GetDefaultNetclass()->SetClearance( 0 ); // Create the manager and dispatcher & route draw panel events to the dispatcher m_toolManager = new TOOL_MANAGER; diff --git a/pcbnew/netinfo_item.cpp b/pcbnew/netinfo_item.cpp index 4f2a7fb544..82e1024ec6 100644 --- a/pcbnew/netinfo_item.cpp +++ b/pcbnew/netinfo_item.cpp @@ -50,7 +50,7 @@ NETINFO_ITEM::NETINFO_ITEM( BOARD* aParent, const wxString& aNetName, int aNetCo m_parent = aParent; if( aParent ) - m_netClass = aParent->GetDesignSettings().m_NetSettings->m_DefaultNetClass; + m_netClass = aParent->GetDesignSettings().m_NetSettings->GetDefaultNetclass(); else m_netClass = std::make_shared( wxT( "" ) ); } @@ -65,7 +65,7 @@ NETINFO_ITEM::~NETINFO_ITEM() void NETINFO_ITEM::Clear() { wxCHECK( m_parent, /* void */ ); - m_netClass = m_parent->GetDesignSettings().m_NetSettings->m_DefaultNetClass; + m_netClass = m_parent->GetDesignSettings().m_NetSettings->GetDefaultNetclass(); } @@ -76,7 +76,7 @@ void NETINFO_ITEM::SetNetClass( const std::shared_ptr& aNetClass ) if( aNetClass ) m_netClass = aNetClass; else - m_netClass = m_parent->GetDesignSettings().m_NetSettings->m_DefaultNetClass; + m_netClass = m_parent->GetDesignSettings().m_NetSettings->GetDefaultNetclass(); } diff --git a/pcbnew/netlist_reader/board_netlist_updater.cpp b/pcbnew/netlist_reader/board_netlist_updater.cpp index b4aa21e796..5e783f659f 100644 --- a/pcbnew/netlist_reader/board_netlist_updater.cpp +++ b/pcbnew/netlist_reader/board_netlist_updater.cpp @@ -1324,7 +1324,9 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist ) // * it is useless because zones will be refilled after placing new footprints m_commit.Push( _( "Update Netlist" ), m_newFootprintsCount ? ZONE_FILL_OP : 0 ); + // Update net, netcode and netclass data after commiting the netlist m_board->SynchronizeNetsAndNetClasses( true ); + m_board->GetConnectivity()->RefreshNetcodeMap( m_board ); // Although m_commit will probably also set this, it's not guaranteed, and we need to make // sure any modification to netclasses gets persisted to project settings through a save. diff --git a/pcbnew/netlist_reader/netlist.cpp b/pcbnew/netlist_reader/netlist.cpp index be091e8272..0eab8c24ed 100644 --- a/pcbnew/netlist_reader/netlist.cpp +++ b/pcbnew/netlist_reader/netlist.cpp @@ -29,6 +29,7 @@ using namespace std::placeholders; #include #include +#include #include #include #include @@ -42,6 +43,7 @@ using namespace std::placeholders; #include #include "board_netlist_updater.h" #include +#include #include #include #include // LAST_PATH_TYPE @@ -88,6 +90,19 @@ void PCB_EDIT_FRAME::OnNetlistChanged( BOARD_NETLIST_UPDATER& aUpdater, bool* aR SetMsgPanel( board ); + // Re-sync nets, netclasses, and DRC rules to account for new aggregate netclass rules + board->SynchronizeNetsAndNetClasses( false ); + + DRC_TOOL* drcTool = m_toolManager->GetTool(); + + try + { + drcTool->GetDRCEngine()->InitEngine( GetDesignRulesPath() ); + } + catch( PARSE_ERROR& ) + { + } + // Update rendered track/via/pad net labels, and any text items that might reference a // netName or netClass int netNamesCfg = GetPcbNewSettings()->m_Display.m_NetNames; diff --git a/pcbnew/pcb_io/altium/altium_pcb.cpp b/pcbnew/pcb_io/altium/altium_pcb.cpp index 9bd6ee83c0..f93dc8b927 100644 --- a/pcbnew/pcb_io/altium/altium_pcb.cpp +++ b/pcbnew/pcb_io/altium/altium_pcb.cpp @@ -1222,14 +1222,11 @@ void ALTIUM_PCB::ParseClasses6Data( const ALTIUM_PCB_COMPOUND_FILE& aAltiumP for( const wxString& name : elem.names ) { - m_board->GetDesignSettings().m_NetSettings->m_NetClassPatternAssignments.push_back( - { - std::make_unique( name, CTX_NETCLASS ), - nc->GetName() - } ); + m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment( + name, nc->GetName() ); } - if( m_board->GetDesignSettings().m_NetSettings->m_NetClasses.count( nc->GetName() ) ) + if( m_board->GetDesignSettings().m_NetSettings->HasNetclass( nc->GetName() ) ) { // Name conflict, happens in some unknown circumstances // unique_ptr will delete nc on this code path @@ -1243,7 +1240,7 @@ void ALTIUM_PCB::ParseClasses6Data( const ALTIUM_PCB_COMPOUND_FILE& aAltiumP } else { - m_board->GetDesignSettings().m_NetSettings->m_NetClasses[ nc->GetName() ] = nc; + m_board->GetDesignSettings().m_NetSettings->SetNetclass( nc->GetName(), nc ); } } } diff --git a/pcbnew/pcb_io/cadstar/cadstar_pcb_archive_loader.cpp b/pcbnew/pcb_io/cadstar/cadstar_pcb_archive_loader.cpp index 85b433f9bd..4fabd09ec2 100644 --- a/pcbnew/pcb_io/cadstar/cadstar_pcb_archive_loader.cpp +++ b/pcbnew/pcb_io/cadstar/cadstar_pcb_archive_loader.cpp @@ -760,17 +760,16 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadDesignRules() // so set to minimum permitted in KiCad (2 mils) bds.m_HoleClearance = 0; // Testing suggests cadstar might not have a copper-to-hole clearance - auto applyNetClassRule = - [&]( wxString aID, std::shared_ptr& aNetClassPtr ) - { - int value = -1; - applyRule( aID, &value ); + auto applyNetClassRule = [&]( wxString aID, const std::shared_ptr& aNetClassPtr ) + { + int value = -1; + applyRule( aID, &value ); - if( value != -1 ) - aNetClassPtr->SetClearance( value ); - }; + if( value != -1 ) + aNetClassPtr->SetClearance( value ); + }; - applyNetClassRule( "T_T", bds.m_NetSettings->m_DefaultNetClass ); + applyNetClassRule( "T_T", bds.m_NetSettings->GetDefaultNetclass() ); wxLogWarning( _( "KiCad design rules are different from CADSTAR ones. Only the compatible " "design rules were imported. It is recommended that you review the design " @@ -4047,18 +4046,15 @@ NETINFO_ITEM* CADSTAR_PCB_ARCHIVE_LOADER::getKiCadNet( const NET_ID& aCadstarNet netClassName += wxT( " | Spacing class: " ) + sp.Name; } - netclass.reset( new NETCLASS( *netSettings->m_DefaultNetClass ) ); + netclass.reset( new NETCLASS( *netSettings->GetDefaultNetclass() ) ); netclass->SetName( netClassName ); - netSettings->m_NetClasses[ netClassName ] = netclass; + netSettings->SetNetclass( netClassName, netclass ); netclass->SetTrackWidth( getKiCadLength( rc.OptimalWidth ) ); m_netClassMap.insert( { key, netclass } ); } - m_board->GetDesignSettings().m_NetSettings->m_NetClassPatternAssignments.push_back( - { - std::make_unique( newName, CTX_NETCLASS ), - netclass->GetName() - } ); + m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment( + newName, netclass->GetName() ); netInfo->SetNetClass( netclass ); m_board->Add( netInfo, ADD_MODE::APPEND ); diff --git a/pcbnew/pcb_io/eagle/pcb_io_eagle.cpp b/pcbnew/pcb_io/eagle/pcb_io_eagle.cpp index e0acf4b9ea..cae77b0d4b 100644 --- a/pcbnew/pcb_io/eagle/pcb_io_eagle.cpp +++ b/pcbnew/pcb_io/eagle/pcb_io_eagle.cpp @@ -410,9 +410,9 @@ BOARD* PCB_IO_EAGLE::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe, std::shared_ptr& netSettings = bds.m_NetSettings; - finishNetclass( netSettings->m_DefaultNetClass ); + finishNetclass( netSettings->GetDefaultNetclass() ); - for( const auto& [ name, netclass ] : netSettings->m_NetClasses ) + for( const auto& [name, netclass] : netSettings->GetNetclasses() ) finishNetclass( netclass ); m_board->m_LegacyNetclassesLoaded = true; @@ -2603,12 +2603,12 @@ void PCB_IO_EAGLE::loadClasses( wxXmlNode* aClasses ) if( eClass.name.CmpNoCase( wxT( "default" ) ) == 0 ) { - netclass = bds.m_NetSettings->m_DefaultNetClass; + netclass = bds.m_NetSettings->GetDefaultNetclass(); } else { netclass.reset( new NETCLASS( eClass.name ) ); - bds.m_NetSettings->m_NetClasses[ eClass.name ] = netclass; + bds.m_NetSettings->SetNetclass( eClass.name, netclass ); } netclass->SetTrackWidth( INT_MAX ); @@ -2681,10 +2681,8 @@ void PCB_IO_EAGLE::loadSignals( wxXmlNode* aSignals ) if( netclassIt != m_classMap.end() ) { - m_board->GetDesignSettings().m_NetSettings->m_NetClassPatternAssignments.push_back( - { std::make_unique( netName, CTX_NETCLASS ), - netclassIt->second->GetName() } ); - + m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment( + netName, netclassIt->second->GetName() ); netInfo->SetNetClass( netclassIt->second ); netclass = netclassIt->second; } diff --git a/pcbnew/pcb_io/easyeda/pcb_io_easyeda_plugin.cpp b/pcbnew/pcb_io/easyeda/pcb_io_easyeda_plugin.cpp index fbd2167cd9..782963b8aa 100644 --- a/pcbnew/pcb_io/easyeda/pcb_io_easyeda_plugin.cpp +++ b/pcbnew/pcb_io/easyeda/pcb_io_easyeda_plugin.cpp @@ -200,7 +200,7 @@ BOARD* PCB_IO_EASYEDA::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe, m_board->SetLayerName( klayer, name ); BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); - std::shared_ptr defNetclass = bds.m_NetSettings->m_DefaultNetClass; + std::shared_ptr defNetclass = bds.m_NetSettings->GetDefaultNetclass(); if( pcbDoc.DRCRULE ) { diff --git a/pcbnew/pcb_io/kicad_legacy/pcb_io_kicad_legacy.cpp b/pcbnew/pcb_io/kicad_legacy/pcb_io_kicad_legacy.cpp index 7240e8f5f5..390c00bf00 100644 --- a/pcbnew/pcb_io/kicad_legacy/pcb_io_kicad_legacy.cpp +++ b/pcbnew/pcb_io/kicad_legacy/pcb_io_kicad_legacy.cpp @@ -908,7 +908,7 @@ void PCB_IO_KICAD_LEGACY::loadSETUP() { BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); ZONE_SETTINGS zoneSettings = bds.GetDefaultZoneSettings(); - std::shared_ptr defaultNetclass = bds.m_NetSettings->m_DefaultNetClass; + std::shared_ptr defaultNetclass = bds.m_NetSettings->GetDefaultNetclass(); char* line; char* saveptr; @@ -2313,11 +2313,8 @@ void PCB_IO_KICAD_LEGACY::loadNETCLASS() ReadDelimitedText( buf, line + SZ( "AddNet" ), sizeof(buf) ); netname = ConvertToNewOverbarNotation( From_UTF8( buf ) ); - m_board->GetDesignSettings().m_NetSettings->m_NetClassPatternAssignments.push_back( - { - std::make_unique( netname, CTX_NETCLASS ), - nc->GetName() - } ); + m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment( + netname, nc->GetName() ); } else if( TESTLINE( "Clearance" ) ) { @@ -2361,7 +2358,7 @@ void PCB_IO_KICAD_LEGACY::loadNETCLASS() } else if( TESTLINE( "$EndNCLASS" ) ) { - if( m_board->GetDesignSettings().m_NetSettings->m_NetClasses.count( nc->GetName() ) ) + if( m_board->GetDesignSettings().m_NetSettings->HasNetclass( nc->GetName() ) ) { // Must have been a name conflict, this is a bad board file. // User may have done a hand edit to the file. @@ -2373,7 +2370,7 @@ void PCB_IO_KICAD_LEGACY::loadNETCLASS() } else { - m_board->GetDesignSettings().m_NetSettings->m_NetClasses[ nc->GetName() ] = nc; + m_board->GetDesignSettings().m_NetSettings->SetNetclass( nc->GetName(), nc ); } return; // preferred exit diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp index de06b98af7..d1244cc4e9 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp @@ -2081,7 +2081,7 @@ void PCB_IO_KICAD_SEXPR_PARSER::parseSetup() wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as setup." ) ); BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); - std::shared_ptr& defaultNetClass = bds.m_NetSettings->m_DefaultNetClass; + const std::shared_ptr& defaultNetClass = bds.m_NetSettings->GetDefaultNetclass(); ZONE_SETTINGS& zoneSettings = bds.GetDefaultZoneSettings(); // Missing soldermask min width value means that the user has set the value to 0 and @@ -2682,11 +2682,8 @@ void PCB_IO_KICAD_SEXPR_PARSER::parseNETCLASS() if( m_requiredVersion < 20210606 ) netName = ConvertToNewOverbarNotation( FromUTF8() ); - m_board->GetDesignSettings().m_NetSettings->m_NetClassPatternAssignments.push_back( - { - std::make_unique( netName, CTX_NETCLASS ), - nc->GetName() - } ); + m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment( + netName, nc->GetName() ); break; } @@ -2701,7 +2698,7 @@ void PCB_IO_KICAD_SEXPR_PARSER::parseNETCLASS() std::shared_ptr& netSettings = m_board->GetDesignSettings().m_NetSettings; - if( netSettings->m_NetClasses.count( nc->GetName() ) ) + if( netSettings->HasNetclass( nc->GetName() ) ) { // Must have been a name conflict, this is a bad board file. // User may have done a hand edit to the file. @@ -2711,13 +2708,13 @@ void PCB_IO_KICAD_SEXPR_PARSER::parseNETCLASS() CurOffset() ); THROW_IO_ERROR( error ); } - else if( nc->GetName() == netSettings->m_DefaultNetClass->GetName() ) + else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() ) { - netSettings->m_DefaultNetClass = nc; + netSettings->SetDefaultNetclass( nc ); } else { - netSettings->m_NetClasses[ nc->GetName() ] = nc; + netSettings->SetNetclass( nc->GetName(), nc ); } } diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 6bd4a260a0..6f560d3504 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -308,10 +308,10 @@ COLOR4D PCB_RENDER_SETTINGS::GetColor( const BOARD_ITEM* aItem, int aLayer ) con if( netColor == COLOR4D::UNSPECIFIED ) { - auto jj = m_netclassColors.find( conItem->GetNetClassName() ); + const NETCLASS* nc = conItem->GetEffectiveNetClass(); - if( jj != m_netclassColors.end() ) - netColor = jj->second; + if( nc->HasPcbColor() ) + netColor = nc->GetPcbColor(); } if( netColor == COLOR4D::UNSPECIFIED ) diff --git a/pcbnew/pcb_painter.h b/pcbnew/pcb_painter.h index 018bc4bc3f..e8578346e7 100644 --- a/pcbnew/pcb_painter.h +++ b/pcbnew/pcb_painter.h @@ -126,8 +126,6 @@ public: NET_COLOR_MODE GetNetColorMode() const { return m_netColorMode; } void SetNetColorMode( NET_COLOR_MODE aMode ) { m_netColorMode = aMode; } - std::map& GetNetclassColorMap() { return m_netclassColors; } - std::map& GetNetColorMap() { return m_netColors; } std::set& GetHiddenNets() { return m_hiddenNets; } diff --git a/pcbnew/pcbexpr_evaluator.cpp b/pcbnew/pcbexpr_evaluator.cpp index 9cd7c79ff4..ea705e173e 100644 --- a/pcbnew/pcbexpr_evaluator.cpp +++ b/pcbnew/pcbexpr_evaluator.cpp @@ -138,14 +138,16 @@ public: const wxString& AsString() const override { - const_cast( this )->Set( m_item->GetEffectiveNetClass()->GetName() ); + const_cast( this )->Set( + m_item->GetEffectiveNetClass()->GetVariableSubstitutionName() ); return LIBEVAL::VALUE::AsString(); } bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override { if( const PCBEXPR_NETCLASS_VALUE* bValue = dynamic_cast( b ) ) - return m_item->GetEffectiveNetClass() == bValue->m_item->GetEffectiveNetClass(); + return *( m_item->GetEffectiveNetClass() ) + == *( bValue->m_item->GetEffectiveNetClass() ); else return LIBEVAL::VALUE::EqualTo( aCtx, b ); } diff --git a/pcbnew/pcbexpr_functions.cpp b/pcbnew/pcbexpr_functions.cpp index 87bccc220d..7ba17bfe98 100644 --- a/pcbnew/pcbexpr_functions.cpp +++ b/pcbnew/pcbexpr_functions.cpp @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - +#include #include #include #include @@ -1162,6 +1162,45 @@ static void getFieldFunc( LIBEVAL::CONTEXT* aCtx, void* self ) } +static void hasNetclassFunc( LIBEVAL::CONTEXT* aCtx, void* self ) +{ + LIBEVAL::VALUE* arg = aCtx->Pop(); + LIBEVAL::VALUE* result = aCtx->AllocValue(); + + result->Set( 0.0 ); + aCtx->Push( result ); + + if( !arg || arg->AsString().IsEmpty() ) + { + if( aCtx->HasErrorCallback() ) + aCtx->ReportError( _( "Missing netclass name argument to hasNetclass()" ) ); + + return; + } + + PCBEXPR_VAR_REF* vref = static_cast( self ); + BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr; + + if( !item ) + return; + + result->SetDeferredEval( + [item, arg]() -> double + { + if( !item->IsConnected() ) + return 0.0; + + BOARD_CONNECTED_ITEM* bcItem = static_cast( item ); + NETCLASS* netclass = bcItem->GetEffectiveNetClass(); + + if( netclass->ContainsNetclassWithName( arg->AsString() ) ) + return 1.0; + + return 0.0; + } ); +} + + PCBEXPR_BUILTIN_FUNCTIONS::PCBEXPR_BUILTIN_FUNCTIONS() { RegisterAllFunctions(); @@ -1200,6 +1239,6 @@ void PCBEXPR_BUILTIN_FUNCTIONS::RegisterAllFunctions() RegisterFunc( wxT( "inDiffPair('x')" ), inDiffPairFunc ); RegisterFunc( wxT( "getField('x')" ), getFieldFunc ); + + RegisterFunc( wxT( "hasNetclass('x')" ), hasNetclassFunc ); } - - diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp index 8507d7b937..b6f8941c22 100644 --- a/pcbnew/pcbnew_config.cpp +++ b/pcbnew/pcbnew_config.cpp @@ -95,7 +95,7 @@ bool PCB_EDIT_FRAME::LoadProjectSettings() std::map& netColors = renderSettings->GetNetColorMap(); netColors.clear(); - for( const auto& [ netname, color ] : netSettings->m_NetColorAssignments ) + for( const auto& [netname, color] : netSettings->GetNetColorAssignments() ) { if( color != COLOR4D::UNSPECIFIED ) { @@ -104,12 +104,6 @@ bool PCB_EDIT_FRAME::LoadProjectSettings() } } - std::map& netclassColors = renderSettings->GetNetclassColorMap(); - netclassColors.clear(); - - for( const auto& [ name, netclass ] : netSettings->m_NetClasses ) - netclassColors[ name ] = netclass->GetPcbColor(); - m_appearancePanel->SetUserLayerPresets( project.m_LayerPresets ); m_appearancePanel->SetUserViewports( project.m_Viewports ); @@ -174,21 +168,12 @@ void PCB_EDIT_FRAME::SaveProjectLocalSettings() KIGFX::RENDER_SETTINGS* rs = GetCanvas()->GetView()->GetPainter()->GetSettings(); KIGFX::PCB_RENDER_SETTINGS* renderSettings = static_cast( rs ); - netSettings->m_NetColorAssignments.clear(); + netSettings->ClearNetColorAssignments(); for( const auto& [ netcode, color ] : renderSettings->GetNetColorMap() ) { if( NETINFO_ITEM* net = nets.GetNetItem( netcode ) ) - netSettings->m_NetColorAssignments[ net->GetNetname() ] = color; - } - - std::map& netclassColors = renderSettings->GetNetclassColorMap(); - - // NOTE: this assumes netclasses will have already been updated, which I think is the case - for( const auto& [ name, netclass ] : netSettings->m_NetClasses ) - { - if( netclassColors.count( name ) ) - netclass->SetPcbColor( netclassColors.at( name ) ); + netSettings->SetNetColorAssignment( net->GetNetname(), color ); } /** diff --git a/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp b/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp index ed602cde75..904447a85f 100644 --- a/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp +++ b/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp @@ -246,7 +246,7 @@ BOARD* LoadBoard( wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, bool aSet brd->BuildConnectivity(); brd->BuildListOfNets(); - brd->SynchronizeNetsAndNetClasses( false ); + brd->SynchronizeNetsAndNetClasses( true ); brd->UpdateUserUnits( brd, nullptr ); } diff --git a/pcbnew/python/swig/board.i b/pcbnew/python/swig/board.i index b22bbcd83a..cbaf07389a 100644 --- a/pcbnew/python/swig/board.i +++ b/pcbnew/python/swig/board.i @@ -154,7 +154,7 @@ HANDLE_EXCEPTIONS(BOARD::TracksInNetBetweenPoints) return SaveBoard(filename,self) def GetNetClasses(self): - return self.GetDesignSettings().m_NetSettings.m_NetClasses + return self.GetDesignSettings().m_NetSettings.GetNetclasses() def GetCurrentNetClassName(self): return self.GetDesignSettings().GetCurrentNetClassName() @@ -194,7 +194,7 @@ HANDLE_EXCEPTIONS(BOARD::TracksInNetBetweenPoints) # Copy the NETCLASS_MAP so the one in the BOARD isn't modified # when we add the Default net class. netclassmap = {k:v for k,v in self.GetNetClasses().items()} - netclassmap['Default'] = self.GetDesignSettings().m_NetSettings.m_DefaultNetClass + netclassmap['Default'] = self.GetDesignSettings().m_NetSettings.GetDefaultNetclass() return netclassmap %} } diff --git a/pcbnew/python/swig/board_design_settings.i b/pcbnew/python/swig/board_design_settings.i index 8e1ea0edb7..3caccf70c6 100644 --- a/pcbnew/python/swig/board_design_settings.i +++ b/pcbnew/python/swig/board_design_settings.i @@ -1,7 +1,7 @@ %ignore BOARD_DESIGN_SETTINGS::m_Pad_Master; %ignore BOARD_DESIGN_SETTINGS::m_DRCEngine; -%ignore NET_SETTINGS::m_NetClassPatternAssignments; -%ignore NET_SETTINGS::m_NetClassLabelAssignments; +%ignore NET_SETTINGS::m_netClassPatternAssignments; +%ignore NET_SETTINGS::m_netClassLabelAssignments; %shared_ptr(NET_SETTINGS) %template(netclasses_map) std::map>; diff --git a/pcbnew/ratsnest/ratsnest_view_item.cpp b/pcbnew/ratsnest/ratsnest_view_item.cpp index 4113ca1c65..2a6e02f004 100644 --- a/pcbnew/ratsnest/ratsnest_view_item.cpp +++ b/pcbnew/ratsnest/ratsnest_view_item.cpp @@ -88,9 +88,7 @@ void RATSNEST_VIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const const bool colorByNet = rs->GetNetColorMode() != NET_COLOR_MODE::OFF; const bool dimStatic = m_data->GetLocalRatsnest().size() > 0 || highlightedNets.size() > 0; - std::map& netColors = rs->GetNetColorMap(); - std::map& ncColors = rs->GetNetclassColorMap(); - const std::map& ncMap = m_data->GetNetclassMap(); + std::map& netColors = rs->GetNetColorMap(); const bool onlyVisibleLayers = cfg->m_Display.m_RatsnestMode == RATSNEST_MODE::VISIBLE; LSET visibleLayers; @@ -127,10 +125,21 @@ void RATSNEST_VIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const if( hiddenNets.count( l.netCode ) ) continue; + const NETCLASS* nc = nullptr; + const NET_SETTINGS* netSettings = m_data->GetNetSettings(); + + if( m_data->HasNetNameForNetCode( l.netCode ) ) + { + const wxString& netName = m_data->GetNetNameForNetCode( l.netCode ); + + if( netSettings->HasEffectiveNetClass( netName ) ) + nc = netSettings->GetCachedEffectiveNetClass( netName ).get(); + } + if( colorByNet && netColors.count( l.netCode ) ) color = netColors.at( l.netCode ); - else if( colorByNet && ncMap.count( l.netCode ) && ncColors.count( ncMap.at( l.netCode ) ) ) - color = ncColors.at( ncMap.at( l.netCode ) ); + else if( colorByNet && nc && nc->HasPcbColor() ) + color = nc->GetPcbColor(); else color = defaultColor; @@ -173,10 +182,21 @@ void RATSNEST_VIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const if( !net || m_data->GetConnectivityAlgo()->IsNetDirty( i ) ) continue; + const NETCLASS* nc = nullptr; + const NET_SETTINGS* netSettings = m_data->GetNetSettings(); + + if( m_data->HasNetNameForNetCode( i ) ) + { + const wxString& netName = m_data->GetNetNameForNetCode( i ); + + if( netSettings->HasEffectiveNetClass( netName ) ) + nc = netSettings->GetCachedEffectiveNetClass( netName ).get(); + } + if( colorByNet && netColors.count( i ) ) color = netColors.at( i ); - else if( colorByNet && ncMap.count( i ) && ncColors.count( ncMap.at( i ) ) ) - color = ncColors.at( ncMap.at( i ) ); + else if( colorByNet && nc && nc->HasPcbColor() ) + color = nc->GetPcbColor(); else color = defaultColor; diff --git a/pcbnew/ratsnest/ratsnest_view_item.h b/pcbnew/ratsnest/ratsnest_view_item.h index 5f8dd4397a..62548a19ad 100644 --- a/pcbnew/ratsnest/ratsnest_view_item.h +++ b/pcbnew/ratsnest/ratsnest_view_item.h @@ -34,6 +34,7 @@ #include #include #include +#include class GAL; class CONNECTIVITY_DATA; diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 76960ec282..01e216e455 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -1737,17 +1737,26 @@ void PNS_KICAD_IFACE::DisplayRatline( const SHAPE_LINE_CHAIN& aRatline, PNS::NET std::shared_ptr connectivity = m_board->GetConnectivity(); std::set highlightedNets = rs->GetHighlightNetCodes(); std::map& netColors = rs->GetNetColorMap(); - std::map& ncColors = rs->GetNetclassColorMap(); - const std::map& ncMap = connectivity->GetNetclassMap(); int netCode = -1; if( NETINFO_ITEM* net = static_cast( aNet ) ) netCode = net->GetNetCode(); + const NETCLASS* nc = nullptr; + const NET_SETTINGS* netSettings = connectivity->GetNetSettings(); + + if( connectivity->HasNetNameForNetCode( netCode ) ) + { + const wxString& netName = connectivity->GetNetNameForNetCode( netCode ); + + if( netSettings->HasEffectiveNetClass( netName ) ) + nc = netSettings->GetCachedEffectiveNetClass( netName ).get(); + } + if( colorByNet && netColors.count( netCode ) ) color = netColors.at( netCode ); - else if( colorByNet && ncMap.count( netCode ) && ncColors.count( ncMap.at( netCode ) ) ) - color = ncColors.at( ncMap.at( netCode ) ); + else if( colorByNet && nc && nc->HasPcbColor() ) + color = nc->GetPcbColor(); else color = defaultColor; @@ -1969,7 +1978,7 @@ BOARD_CONNECTED_ITEM* PNS_KICAD_IFACE::createBoardItem( PNS::ITEM* aItem ) NETINFO_ITEM* newNetInfo = newBoardItem->GetNet(); newNetInfo->SetParent( m_board ); - newNetInfo->SetNetClass( m_board->GetDesignSettings().m_NetSettings->m_DefaultNetClass ); + newNetInfo->SetNetClass( m_board->GetDesignSettings().m_NetSettings->GetDefaultNetclass() ); } return newBoardItem; diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index 4b4573d3d4..97f7a61e11 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -2642,7 +2642,7 @@ void ROUTER_TOOL::UpdateMessagePanel() NETCLASS* netclassA = netA->GetNetClass(); NETCLASS* netclassB = netB->GetNetClass(); - if( netclassA == netclassB ) + if( *netclassA == *netclassB ) netclass = netclassA->GetName(); else netclass = netclassA->GetName() + wxT( ", " ) + netclassB->GetName(); diff --git a/pcbnew/specctra_import_export/specctra_export.cpp b/pcbnew/specctra_import_export/specctra_export.cpp index 373f9ceef1..16421ff1b7 100644 --- a/pcbnew/specctra_import_export/specctra_export.cpp +++ b/pcbnew/specctra_import_export/specctra_export.cpp @@ -1180,8 +1180,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) //------------------------------------------------------------- { char rule[80]; - int defaultTrackWidth = netSettings->m_DefaultNetClass->GetTrackWidth(); - int defaultClearance = netSettings->m_DefaultNetClass->GetClearance(); + int defaultTrackWidth = netSettings->GetDefaultNetclass()->GetTrackWidth(); + int defaultClearance = netSettings->GetDefaultNetclass()->GetClearance(); double clearance = scale( defaultClearance ); STRINGS& rules = m_pcb->m_structure->m_rules->m_rules; @@ -1571,9 +1571,9 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) // Add the via from the Default netclass first. The via container // in pcb->library preserves the sequence of addition. - PADSTACK* via = makeVia( netSettings->m_DefaultNetClass->GetViaDiameter(), - netSettings->m_DefaultNetClass->GetViaDrill(), - m_top_via_layer, m_bot_via_layer ); + PADSTACK* via = makeVia( netSettings->GetDefaultNetclass()->GetViaDiameter(), + netSettings->GetDefaultNetclass()->GetViaDrill(), m_top_via_layer, + m_bot_via_layer ); // we AppendVia() this first one, there is no way it can be a duplicate, // the pcb->library via container is empty at this point. After this, @@ -1585,7 +1585,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) // pcb->library->spareViaIndex = pcb->library->vias.size(); // output the non-Default netclass vias - for( const auto& [ name, netclass ] : netSettings->m_NetClasses ) + for( const auto& [name, netclass] : netSettings->GetNetclasses() ) { via = makeVia( netclass->GetViaDiameter(), netclass->GetViaDrill(), m_top_via_layer, m_bot_via_layer ); @@ -1717,9 +1717,9 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) //--------------------------------------------------------- - exportNETCLASS( netSettings->m_DefaultNetClass, aBoard ); + exportNETCLASS( netSettings->GetDefaultNetclass(), aBoard ); - for( const auto& [ name, netclass ] : netSettings->m_NetClasses ) + for( const auto& [name, netclass] : netSettings->GetNetclasses() ) exportNETCLASS( netclass, aBoard ); } @@ -1766,7 +1766,7 @@ void SPECCTRA_DB::exportNETCLASS( const std::shared_ptr& aNetClass, BO for( NETINFO_ITEM* net : aBoard->GetNetInfo() ) { - if( net->GetNetClass()->GetName() == clazz->m_class_id ) + if( net->GetNetClass()->GetVariableSubstitutionName() == clazz->m_class_id ) clazz->m_net_ids.push_back( TO_UTF8( net->GetNetname() ) ); } diff --git a/pcbnew/specctra_import_export/specctra_import.cpp b/pcbnew/specctra_import_export/specctra_import.cpp index cc10b251dc..225120dd61 100644 --- a/pcbnew/specctra_import_export/specctra_import.cpp +++ b/pcbnew/specctra_import_export/specctra_import.cpp @@ -523,7 +523,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) std::shared_ptr& netSettings = aBoard->GetDesignSettings().m_NetSettings; - int via_drill_default = netSettings->m_DefaultNetClass->GetViaDrill(); + int via_drill_default = netSettings->GetDefaultNetclass()->GetViaDrill(); for( unsigned v = 0; v < wire_via->m_vertexes.size(); ++v ) { diff --git a/pcbnew/tools/board_editor_control.cpp b/pcbnew/tools/board_editor_control.cpp index 7da38de694..c3f1844b80 100644 --- a/pcbnew/tools/board_editor_control.cpp +++ b/pcbnew/tools/board_editor_control.cpp @@ -734,7 +734,7 @@ int BOARD_EDITOR_CONTROL::TrackWidthInc( const TOOL_EVENT& aEvent ) for( int i = 0; i < (int) bds.m_TrackWidthList.size(); ++i ) { - int candidate = bds.m_NetSettings->m_DefaultNetClass->GetTrackWidth(); + int candidate = bds.m_NetSettings->GetDefaultNetclass()->GetTrackWidth(); if( i > 0 ) candidate = bds.m_TrackWidthList[ i ]; @@ -816,7 +816,7 @@ int BOARD_EDITOR_CONTROL::TrackWidthDec( const TOOL_EVENT& aEvent ) for( int i = (int) bds.m_TrackWidthList.size() - 1; i >= 0; --i ) { - int candidate = bds.m_NetSettings->m_DefaultNetClass->GetTrackWidth(); + int candidate = bds.m_NetSettings->GetDefaultNetclass()->GetTrackWidth(); if( i > 0 ) candidate = bds.m_TrackWidthList[ i ]; @@ -898,8 +898,8 @@ int BOARD_EDITOR_CONTROL::ViaSizeInc( const TOOL_EVENT& aEvent ) for( int i = 0; i < (int) bds.m_ViasDimensionsList.size(); ++i ) { - VIA_DIMENSION dims( bds.m_NetSettings->m_DefaultNetClass->GetViaDiameter(), - bds.m_NetSettings->m_DefaultNetClass->GetViaDrill() ); + VIA_DIMENSION dims( bds.m_NetSettings->GetDefaultNetclass()->GetViaDiameter(), + bds.m_NetSettings->GetDefaultNetclass()->GetViaDrill() ); if( i> 0 ) dims = bds.m_ViasDimensionsList[ i ]; @@ -953,8 +953,8 @@ int BOARD_EDITOR_CONTROL::ViaSizeDec( const TOOL_EVENT& aEvent ) for( int i = (int) bds.m_ViasDimensionsList.size() - 1; i >= 0; --i ) { - VIA_DIMENSION dims( bds.m_NetSettings->m_DefaultNetClass->GetViaDiameter(), - bds.m_NetSettings->m_DefaultNetClass->GetViaDrill() ); + VIA_DIMENSION dims( bds.m_NetSettings->GetDefaultNetclass()->GetViaDiameter(), + bds.m_NetSettings->GetDefaultNetclass()->GetViaDrill() ); if( i > 0 ) dims = bds.m_ViasDimensionsList[ i ]; diff --git a/pcbnew/tools/pcb_control.cpp b/pcbnew/tools/pcb_control.cpp index 593f5f8d57..bbcb7b9b1f 100644 --- a/pcbnew/tools/pcb_control.cpp +++ b/pcbnew/tools/pcb_control.cpp @@ -1352,7 +1352,7 @@ int PCB_CONTROL::AppendBoard( PCB_IO& pi, wxString& fileName ) WX_PROGRESS_REPORTER progressReporter( editFrame, _( "Loading PCB" ), 1 ); - editFrame->GetDesignSettings().m_NetSettings->m_NetClasses.clear(); + editFrame->GetDesignSettings().m_NetSettings->ClearNetclasses(); pi.SetProgressReporter( &progressReporter ); pi.LoadBoard( fileName, brd, &props, nullptr ); } diff --git a/pcbnew/widgets/appearance_controls.cpp b/pcbnew/widgets/appearance_controls.cpp index 401cc1acb9..4ac3b4b7de 100644 --- a/pcbnew/widgets/appearance_controls.cpp +++ b/pcbnew/widgets/appearance_controls.cpp @@ -2425,10 +2425,8 @@ void APPEARANCE_CONTROLS::rebuildNets() m_staticTextNets->SetLabel( _( "Nets" ) ); m_staticTextNetClasses->SetLabel( _( "Net Classes" ) ); - KIGFX::PCB_RENDER_SETTINGS* rs = static_cast( - m_frame->GetCanvas()->GetView()->GetPainter()->GetSettings() ); + std::shared_ptr& netSettings = board->GetDesignSettings().m_NetSettings; - std::map& netclassColors = rs->GetNetclassColorMap(); const std::set& hiddenClasses = m_frame->Prj().GetLocalSettings().m_HiddenNetclasses; m_netclassOuterSizer->Clear( true ); @@ -2445,8 +2443,10 @@ void APPEARANCE_CONTROLS::rebuildNets() setting->ctl_panel = new wxPanel( m_netclassScrolledWindow, aId ); wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL ); setting->ctl_panel->SetSizer( sizer ); - COLOR4D color = netclassColors.count( name ) ? netclassColors.at( name ) : - COLOR4D::UNSPECIFIED; + + COLOR4D color = netSettings->HasNetclass( name ) + ? netSettings->GetNetClassByName( name )->GetPcbColor() + : COLOR4D::UNSPECIFIED; setting->ctl_color = new COLOR_SWATCH( setting->ctl_panel, color, aId, bgColor, COLOR4D::UNSPECIFIED, SWATCH_SMALL ); @@ -2502,11 +2502,9 @@ void APPEARANCE_CONTROLS::rebuildNets() setting->ctl_text->Bind( wxEVT_RIGHT_DOWN, menuHandler ); }; - std::shared_ptr& netSettings = board->GetDesignSettings().m_NetSettings; - std::vector names; - for( const auto& [ name, netclass ] : netSettings->m_NetClasses ) + for( const auto& [name, netclass] : netSettings->GetNetclasses() ) names.emplace_back( name ); std::sort( names.begin(), names.end() ); @@ -2515,13 +2513,13 @@ void APPEARANCE_CONTROLS::rebuildNets() int idx = wxID_HIGHEST; - m_netclassIdMap[idx] = netSettings->m_DefaultNetClass->GetName(); - appendNetclass( idx++, netSettings->m_DefaultNetClass, true ); + m_netclassIdMap[idx] = netSettings->GetDefaultNetclass()->GetName(); + appendNetclass( idx++, netSettings->GetDefaultNetclass(), true ); for( const wxString& name : names ) { m_netclassIdMap[idx] = name; - appendNetclass( idx++, netSettings->m_NetClasses.at( name ) ); + appendNetclass( idx++, netSettings->GetNetclasses().at( name ) ); } int hotkey; @@ -3143,7 +3141,7 @@ void APPEARANCE_CONTROLS::showNetclass( const wxString& aClassName, bool aShow ) for( NETINFO_ITEM* net : m_frame->GetBoard()->GetNetInfo() ) { - if( net->GetNetClass()->GetName() == aClassName ) + if( net->GetNetClass()->ContainsNetclassWithName( aClassName ) ) { m_frame->GetToolManager()->RunAction( aShow ? PCB_ACTIONS::showNetInRatsnest : PCB_ACTIONS::hideNetInRatsnest, @@ -3177,12 +3175,10 @@ void APPEARANCE_CONTROLS::onNetclassColorChanged( wxCommandEvent& aEvent ) BOARD* board = m_frame->GetBoard(); std::shared_ptr& netSettings = board->GetDesignSettings().m_NetSettings; - netSettings->m_NetClasses[netclassName]->SetPcbColor( swatch->GetSwatchColor() ); + std::shared_ptr nc = netSettings->GetNetClassByName( netclassName ); - KIGFX::PCB_RENDER_SETTINGS* rs = static_cast( - m_frame->GetCanvas()->GetView()->GetPainter()->GetSettings() ); - std::map& netclassColors = rs->GetNetclassColorMap(); - netclassColors[netclassName] = swatch->GetSwatchColor(); + nc->SetPcbColor( swatch->GetSwatchColor() ); + netSettings->RecomputeEffectiveNetclasses(); m_frame->GetCanvas()->GetView()->UpdateAllLayersColor(); m_frame->GetCanvas()->RedrawRatsnest(); @@ -3267,7 +3263,7 @@ void APPEARANCE_CONTROLS::onNetclassContextMenu( wxCommandEvent& aEvent ) { for( NETINFO_ITEM* net : board->GetNetInfo() ) { - if( net->GetNetClass()->GetName() == netClassName ) + if( net->GetNetClass()->ContainsNetclassWithName( netClassName ) ) aFunction( net ); } }; @@ -3282,12 +3278,11 @@ void APPEARANCE_CONTROLS::onNetclassContextMenu( wxCommandEvent& aEvent ) COLOR4D color = setting->ctl_color->GetSwatchColor(); - std::map& netclassColors = rs->GetNetclassColorMap(); - if( color != COLOR4D::UNSPECIFIED ) - netclassColors[m_contextMenuNetclass] = color; - else - netclassColors.erase( m_contextMenuNetclass ); + { + netSettings->GetNetClassByName( m_contextMenuNetclass )->SetPcbColor( color ); + netSettings->RecomputeEffectiveNetclasses(); + } view->UpdateAllLayersColor(); } @@ -3301,8 +3296,9 @@ void APPEARANCE_CONTROLS::onNetclassContextMenu( wxCommandEvent& aEvent ) { setting->ctl_color->SetSwatchColor( COLOR4D( 0, 0, 0, 0 ), true ); - std::map& netclassColors = rs->GetNetclassColorMap(); - netclassColors.erase( m_contextMenuNetclass ); + netSettings->GetNetClassByName( m_contextMenuNetclass ) + ->SetPcbColor( COLOR4D::UNSPECIFIED ); + netSettings->RecomputeEffectiveNetclasses(); view->UpdateAllLayersColor(); } @@ -3320,8 +3316,8 @@ void APPEARANCE_CONTROLS::onNetclassContextMenu( wxCommandEvent& aEvent ) setting->ctl_color->SetSwatchColor( ncColor, true ); - std::map& netclassColors = rs->GetNetclassColorMap(); - netclassColors[m_contextMenuNetclass] = ncColor; + netSettings->GetNetClassByName( m_contextMenuNetclass )->SetPcbColor( ncColor ); + netSettings->RecomputeEffectiveNetclasses(); view->UpdateAllLayersColor(); } @@ -3384,7 +3380,7 @@ void APPEARANCE_CONTROLS::onNetclassContextMenu( wxCommandEvent& aEvent ) wxASSERT( m_netclassSettingsMap.count( NETCLASS::Default ) ); m_netclassSettingsMap.at( NETCLASS::Default )->ctl_visibility->SetValue( true ); - for( const auto& [ name, netclass ] : netSettings->m_NetClasses ) + for( const auto& [name, netclass] : netSettings->GetNetclasses() ) { showNetclass( name ); @@ -3402,7 +3398,7 @@ void APPEARANCE_CONTROLS::onNetclassContextMenu( wxCommandEvent& aEvent ) wxASSERT( m_netclassSettingsMap.count( NETCLASS::Default ) ); m_netclassSettingsMap.at( NETCLASS::Default )->ctl_visibility->SetValue( showDefault ); - for( const auto& [ name, netclass ] : netSettings->m_NetClasses ) + for( const auto& [name, netclass] : netSettings->GetNetclasses() ) { bool show = ( name == m_contextMenuNetclass ); diff --git a/qa/data/eeschema/RuleAreaNetclassConflictOnWire_1.kicad_sch b/qa/data/eeschema/RuleAreaNetclassConflictOnWire_1.kicad_sch deleted file mode 100644 index a0f2740c66..0000000000 --- a/qa/data/eeschema/RuleAreaNetclassConflictOnWire_1.kicad_sch +++ /dev/null @@ -1,376 +0,0 @@ -(kicad_sch - (version 20240417) - (generator "eeschema") - (generator_version "8.99") - (uuid "0726e9d1-eea3-424d-8780-ca27e04db582") - (paper "A4") - (lib_symbols - (symbol "Device:R" - (pin_numbers hide) - (pin_names - (offset 0) - ) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (property "Reference" "R" - (at 2.032 0 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 0 0 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at -1.778 0 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "ki_keywords" "R res resistor" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "ki_fp_filters" "R_*" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (symbol "R_0_1" - (rectangle - (start -1.016 -2.54) - (end 1.016 2.54) - (stroke - (width 0.254) - (type default) - ) - (fill - (type none) - ) - ) - ) - (symbol "R_1_1" - (pin passive line - (at 0 3.81 270) - (length 1.27) - (name "~" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (number "1" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - ) - (pin passive line - (at 0 -3.81 90) - (length 1.27) - (name "~" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (number "2" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - ) - ) - ) - ) - (no_connect - (at 121.92 97.79) - (uuid "4236af9f-a6bf-4cf1-9924-15f3612b7e4e") - ) - (no_connect - (at 83.82 73.66) - (uuid "5e7b627b-1c2e-465a-84ed-c5ec27af46ab") - ) - (wire - (pts - (xy 91.44 73.66) (xy 121.92 73.66) - ) - (stroke - (width 0) - (type default) - ) - (uuid "73c537ad-8abb-4a42-9ec1-e67712c81b34") - ) - (wire - (pts - (xy 121.92 90.17) (xy 121.92 73.66) - ) - (stroke - (width 0) - (type default) - ) - (uuid "f443e7c4-f627-4cda-b5a1-cbc238e17fb4") - ) - (rule_area - (polyline - (pts - (xy 93.98 67.31) (xy 99.06 67.31) (xy 99.06 80.01) (xy 96.52 82.55) (xy 95.25 81.28) (xy 95.25 77.47) - (xy 93.98 76.2) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid 40e86e61-b17e-4a50-a591-d1015a45e6e4) - ) - ) - (rule_area - (polyline - (pts - (xy 133.35 77.47) (xy 133.35 83.82) (xy 114.3 83.82) (xy 111.76 81.28) (xy 111.76 77.47) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid ea7226cb-9108-48d9-9ca3-95d32a5d4077) - ) - ) - (netclass_flag "" - (length 2.54) - (shape round) - (at 95.25 67.31 0) - (fields_autoplaced yes) - (effects - (font - (size 1.27 1.27) - ) - (justify left bottom) - ) - (uuid "71111a86-8188-4247-ad10-36f2f6d838f8") - (property "Netclass" "CLASS1" - (at 95.9485 64.77 0) - (effects - (font - (size 1.27 1.27) - (italic yes) - ) - (justify left) - ) - ) - ) - (netclass_flag "" - (length 2.54) - (shape round) - (at 133.35 80.01 270) - (fields_autoplaced yes) - (effects - (font - (size 1.27 1.27) - ) - (justify right bottom) - ) - (uuid "e8b709aa-42c8-45a8-8cd0-dd3110e4048f") - (property "Netclass" "CLASS2" - (at 135.89 79.3115 90) - (effects - (font - (size 1.27 1.27) - (italic yes) - ) - (justify left) - ) - ) - ) - (symbol - (lib_id "Device:R") - (at 121.92 93.98 180) - (unit 1) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (dnp no) - (fields_autoplaced yes) - (uuid "e294c19e-e287-4924-9e89-aea9a1a5c8e1") - (property "Reference" "R2" - (at 128.27 93.98 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 125.73 93.98 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at 123.698 93.98 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 121.92 93.98 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 121.92 93.98 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (pin "1" - (uuid "6e8901c6-d0c5-455a-a42b-f31a4c09e3db") - ) - (pin "2" - (uuid "fcf2f54f-8f15-40c7-882e-02cb8d2d987f") - ) - (instances - (project "RuleAreaNetclassConflictOnWire" - (path "/0726e9d1-eea3-424d-8780-ca27e04db582" - (reference "R2") - (unit 1) - ) - ) - ) - ) - (symbol - (lib_id "Device:R") - (at 87.63 73.66 270) - (unit 1) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (dnp no) - (fields_autoplaced yes) - (uuid "e33b52ff-7e35-442f-8c36-1e6677209b8c") - (property "Reference" "R1" - (at 87.63 67.31 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 87.63 69.85 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at 87.63 71.882 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 87.63 73.66 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 87.63 73.66 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (pin "1" - (uuid "c87ab3da-a973-4c8f-8e38-3156b231d8af") - ) - (pin "2" - (uuid "5d2f6407-4aee-4cc1-850a-883ae2f37307") - ) - (instances - (project "" - (path "/0726e9d1-eea3-424d-8780-ca27e04db582" - (reference "R1") - (unit 1) - ) - ) - ) - ) - (sheet_instances - (path "/" - (page "1") - ) - ) -) diff --git a/qa/data/eeschema/RuleAreaNetclassConflictOnWire_2.kicad_sch b/qa/data/eeschema/RuleAreaNetclassConflictOnWire_2.kicad_sch deleted file mode 100644 index 1aa17a9159..0000000000 --- a/qa/data/eeschema/RuleAreaNetclassConflictOnWire_2.kicad_sch +++ /dev/null @@ -1,365 +0,0 @@ -(kicad_sch - (version 20240417) - (generator "eeschema") - (generator_version "8.99") - (uuid "0726e9d1-eea3-424d-8780-ca27e04db582") - (paper "A4") - (lib_symbols - (symbol "Device:R" - (pin_numbers hide) - (pin_names - (offset 0) - ) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (property "Reference" "R" - (at 2.032 0 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 0 0 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at -1.778 0 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "ki_keywords" "R res resistor" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "ki_fp_filters" "R_*" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (symbol "R_0_1" - (rectangle - (start -1.016 -2.54) - (end 1.016 2.54) - (stroke - (width 0.254) - (type default) - ) - (fill - (type none) - ) - ) - ) - (symbol "R_1_1" - (pin passive line - (at 0 3.81 270) - (length 1.27) - (name "~" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (number "1" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - ) - (pin passive line - (at 0 -3.81 90) - (length 1.27) - (name "~" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (number "2" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - ) - ) - ) - ) - (no_connect - (at 127 73.66) - (uuid "4236af9f-a6bf-4cf1-9924-15f3612b7e4e") - ) - (no_connect - (at 83.82 73.66) - (uuid "5e7b627b-1c2e-465a-84ed-c5ec27af46ab") - ) - (wire - (pts - (xy 91.44 73.66) (xy 119.38 73.66) - ) - (stroke - (width 0) - (type default) - ) - (uuid "73c537ad-8abb-4a42-9ec1-e67712c81b34") - ) - (rule_area - (polyline - (pts - (xy 106.68 67.31) (xy 110.49 67.31) (xy 110.49 77.47) (xy 106.68 77.47) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid 03801fed-03b2-45ff-96c8-aae8ef0df963) - ) - ) - (rule_area - (polyline - (pts - (xy 93.98 67.31) (xy 97.79 67.31) (xy 97.79 80.01) (xy 93.98 80.01) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid 6fd89307-6035-4c4e-8858-d37921436305) - ) - ) - (netclass_flag "" - (length 2.54) - (shape round) - (at 95.25 67.31 0) - (fields_autoplaced yes) - (effects - (font - (size 1.27 1.27) - ) - (justify left bottom) - ) - (uuid "71111a86-8188-4247-ad10-36f2f6d838f8") - (property "Netclass" "CLASS1" - (at 95.9485 64.77 0) - (effects - (font - (size 1.27 1.27) - (italic yes) - ) - (justify left) - ) - ) - ) - (netclass_flag "" - (length 2.54) - (shape round) - (at 107.95 67.31 0) - (fields_autoplaced yes) - (effects - (font - (size 1.27 1.27) - ) - (justify left bottom) - ) - (uuid "e8b709aa-42c8-45a8-8cd0-dd3110e4048f") - (property "Netclass" "CLASS2" - (at 108.6485 64.77 0) - (effects - (font - (size 1.27 1.27) - (italic yes) - ) - (justify left) - ) - ) - ) - (symbol - (lib_id "Device:R") - (at 123.19 73.66 270) - (unit 1) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (dnp no) - (fields_autoplaced yes) - (uuid "e294c19e-e287-4924-9e89-aea9a1a5c8e1") - (property "Reference" "R2" - (at 123.19 67.31 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 123.19 69.85 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at 123.19 71.882 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 123.19 73.66 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 123.19 73.66 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (pin "1" - (uuid "6e8901c6-d0c5-455a-a42b-f31a4c09e3db") - ) - (pin "2" - (uuid "fcf2f54f-8f15-40c7-882e-02cb8d2d987f") - ) - (instances - (project "RuleAreaNetclassConflictOnWire" - (path "/0726e9d1-eea3-424d-8780-ca27e04db582" - (reference "R2") - (unit 1) - ) - ) - ) - ) - (symbol - (lib_id "Device:R") - (at 87.63 73.66 270) - (unit 1) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (dnp no) - (fields_autoplaced yes) - (uuid "e33b52ff-7e35-442f-8c36-1e6677209b8c") - (property "Reference" "R1" - (at 87.63 67.31 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 87.63 69.85 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at 87.63 71.882 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 87.63 73.66 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 87.63 73.66 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (pin "1" - (uuid "c87ab3da-a973-4c8f-8e38-3156b231d8af") - ) - (pin "2" - (uuid "5d2f6407-4aee-4cc1-850a-883ae2f37307") - ) - (instances - (project "" - (path "/0726e9d1-eea3-424d-8780-ca27e04db582" - (reference "R1") - (unit 1) - ) - ) - ) - ) - (sheet_instances - (path "/" - (page "1") - ) - ) -) diff --git a/qa/data/eeschema/RuleAreaNoOverlap.kicad_sch b/qa/data/eeschema/RuleAreaNoOverlap.kicad_sch deleted file mode 100644 index e5625a1336..0000000000 --- a/qa/data/eeschema/RuleAreaNoOverlap.kicad_sch +++ /dev/null @@ -1,45 +0,0 @@ -(kicad_sch - (version 20240417) - (generator "eeschema") - (generator_version "8.99") - (uuid "e77939c4-758d-4d0c-a6e5-dc441c8c54c9") - (paper "A4") - (lib_symbols) - (rule_area - (polyline - (pts - (xy 144.78 63.5) (xy 177.8 63.5) (xy 180.34 66.04) (xy 180.34 110.49) (xy 171.45 110.49) (xy 157.48 96.52) - (xy 148.59 105.41) (xy 148.59 107.95) (xy 133.35 92.71) (xy 133.35 85.09) (xy 139.7 78.74) (xy 139.7 68.58) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid 4f0aecc0-f3b3-4645-a47e-6a29fb5ff671) - ) - ) - (rule_area - (polyline - (pts - (xy 69.85 49.53) (xy 101.6 49.53) (xy 101.6 73.66) (xy 95.25 80.01) (xy 86.36 80.01) (xy 76.2 69.85) - (xy 76.2 66.04) (xy 78.74 63.5) (xy 69.85 54.61) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid 839de646-0221-4c81-b248-242a273d8ed3) - ) - ) - (sheet_instances - (path "/" - (page "1") - ) - ) -) diff --git a/qa/data/eeschema/RuleAreaOneNetclassDirective.kicad_sch b/qa/data/eeschema/RuleAreaOneNetclassDirective.kicad_sch deleted file mode 100644 index 74fb302963..0000000000 --- a/qa/data/eeschema/RuleAreaOneNetclassDirective.kicad_sch +++ /dev/null @@ -1,327 +0,0 @@ -(kicad_sch - (version 20240417) - (generator "eeschema") - (generator_version "8.99") - (uuid "8a90b8e2-28c2-4028-bcb6-cef3be983f1e") - (paper "A4") - (lib_symbols - (symbol "Device:R" - (pin_numbers hide) - (pin_names - (offset 0) - ) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (property "Reference" "R" - (at 2.032 0 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 0 0 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at -1.778 0 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "ki_keywords" "R res resistor" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "ki_fp_filters" "R_*" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (symbol "R_0_1" - (rectangle - (start -1.016 -2.54) - (end 1.016 2.54) - (stroke - (width 0.254) - (type default) - ) - (fill - (type none) - ) - ) - ) - (symbol "R_1_1" - (pin passive line - (at 0 3.81 270) - (length 1.27) - (name "~" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (number "1" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - ) - (pin passive line - (at 0 -3.81 90) - (length 1.27) - (name "~" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (number "2" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - ) - ) - ) - ) - (no_connect - (at 132.08 53.34) - (uuid "45692886-21e1-4796-b1b4-634d6c7163d5") - ) - (no_connect - (at 83.82 53.34) - (uuid "c283f30d-202c-4a0d-9d0a-ea95c5656841") - ) - (wire - (pts - (xy 91.44 53.34) (xy 124.46 53.34) - ) - (stroke - (width 0) - (type default) - ) - (uuid "6f61af9e-a21c-4ea8-aac1-554407fe006a") - ) - (rule_area - (polyline - (pts - (xy 99.06 44.45) (xy 105.41 44.45) (xy 105.41 60.96) (xy 99.06 60.96) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid 01d7705f-5c3d-4abe-b2c7-9e8f5b00caa8) - ) - ) - (netclass_flag "" - (length 2.54) - (shape round) - (at 101.6 44.45 0) - (fields_autoplaced yes) - (effects - (font - (size 1.27 1.27) - ) - (justify left bottom) - ) - (uuid "655ca652-695a-4f6a-93fa-4347d69a2f15") - (property "Netclass" "CLASS1" - (at 102.2985 41.91 0) - (effects - (font - (size 1.27 1.27) - (italic yes) - ) - (justify left) - ) - ) - ) - (symbol - (lib_id "Device:R") - (at 87.63 53.34 270) - (unit 1) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (dnp no) - (fields_autoplaced yes) - (uuid "57d8460e-6d78-4dc9-8734-201edb21294a") - (property "Reference" "R1" - (at 87.63 46.99 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 87.63 49.53 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at 87.63 51.562 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 87.63 53.34 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 87.63 53.34 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (pin "1" - (uuid "5d7b48cb-ccac-454c-b8ae-d8106594e160") - ) - (pin "2" - (uuid "e59c83d5-3e67-4d97-8414-98cf0d4cd0f7") - ) - (instances - (project "" - (path "/8a90b8e2-28c2-4028-bcb6-cef3be983f1e" - (reference "R1") - (unit 1) - ) - ) - ) - ) - (symbol - (lib_id "Device:R") - (at 128.27 53.34 270) - (unit 1) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (dnp no) - (fields_autoplaced yes) - (uuid "758cfdea-5424-4d58-a623-ef6afa897cdc") - (property "Reference" "R2" - (at 128.27 46.99 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 128.27 49.53 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at 128.27 51.562 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 128.27 53.34 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 128.27 53.34 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (pin "1" - (uuid "fc325f46-cf90-477d-b24e-842cfcdab056") - ) - (pin "2" - (uuid "d48f9df0-ba21-474c-878e-433fd5cecebf") - ) - (instances - (project "RuleAreaOneNetclassDirective" - (path "/8a90b8e2-28c2-4028-bcb6-cef3be983f1e" - (reference "R2") - (unit 1) - ) - ) - ) - ) - (sheet_instances - (path "/" - (page "1") - ) - ) -) diff --git a/qa/data/eeschema/RuleAreaOneOverlap.kicad_sch b/qa/data/eeschema/RuleAreaOneOverlap.kicad_sch deleted file mode 100644 index 9011dd7462..0000000000 --- a/qa/data/eeschema/RuleAreaOneOverlap.kicad_sch +++ /dev/null @@ -1,43 +0,0 @@ -(kicad_sch - (version 20240417) - (generator "eeschema") - (generator_version "8.99") - (uuid "e77939c4-758d-4d0c-a6e5-dc441c8c54c9") - (paper "A4") - (lib_symbols) - (rule_area - (polyline - (pts - (xy 81.28 64.77) (xy 107.95 64.77) (xy 107.95 97.79) (xy 106.68 99.06) (xy 100.33 99.06) (xy 81.28 80.01) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid 29482117-50fb-4bf0-9227-b57a2a024196) - ) - ) - (rule_area - (polyline - (pts - (xy 63.5 48.26) (xy 95.25 48.26) (xy 95.25 76.2) (xy 92.71 78.74) (xy 67.31 78.74) (xy 63.5 74.93) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid fb9e0dd5-7b94-4714-b095-086e21d4076e) - ) - ) - (sheet_instances - (path "/" - (page "1") - ) - ) -) diff --git a/qa/data/eeschema/RuleAreaOneOverlapTwice.kicad_sch b/qa/data/eeschema/RuleAreaOneOverlapTwice.kicad_sch deleted file mode 100644 index dc53e6fa9f..0000000000 --- a/qa/data/eeschema/RuleAreaOneOverlapTwice.kicad_sch +++ /dev/null @@ -1,75 +0,0 @@ -(kicad_sch - (version 20240417) - (generator "eeschema") - (generator_version "8.99") - (uuid "e77939c4-758d-4d0c-a6e5-dc441c8c54c9") - (paper "A4") - (lib_symbols) - (rule_area - (polyline - (pts - (xy 193.04 80.01) (xy 229.87 80.01) (xy 231.14 81.28) (xy 231.14 111.76) (xy 205.74 111.76) (xy 199.39 105.41) - (xy 199.39 102.87) (xy 193.04 96.52) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid 205fcd89-40f4-4d53-8543-c72a408467cf) - ) - ) - (rule_area - (polyline - (pts - (xy 215.9 100.33) (xy 215.9 135.89) (xy 250.19 135.89) (xy 255.27 130.81) (xy 255.27 109.22) (xy 246.38 100.33) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid 4953ad1a-332e-4324-a6e9-44125580b5ce) - ) - ) - (rule_area - (polyline - (pts - (xy 90.17 52.07) (xy 64.77 52.07) (xy 64.77 71.12) (xy 73.66 80.01) (xy 77.47 80.01) (xy 90.17 67.31) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid 9e60651e-f0c3-4ab3-88c0-5b67a7585ce9) - ) - ) - (rule_area - (polyline - (pts - (xy 80.01 66.04) (xy 107.95 66.04) (xy 110.49 68.58) (xy 110.49 100.33) (xy 85.09 100.33) (xy 74.93 90.17) - (xy 74.93 71.12) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid a2990ee5-6b66-496f-a7b1-0402651214fa) - ) - ) - (sheet_instances - (path "/" - (page "1") - ) - ) -) diff --git a/qa/data/eeschema/RuleAreaThreeNetclassDirectives.kicad_sch b/qa/data/eeschema/RuleAreaThreeNetclassDirectives.kicad_sch deleted file mode 100644 index b64e842aed..0000000000 --- a/qa/data/eeschema/RuleAreaThreeNetclassDirectives.kicad_sch +++ /dev/null @@ -1,373 +0,0 @@ -(kicad_sch - (version 20240417) - (generator "eeschema") - (generator_version "8.99") - (uuid "3faa707b-1d78-466d-bafe-1ee08b43bb08") - (paper "A4") - (lib_symbols - (symbol "Device:R" - (pin_numbers hide) - (pin_names - (offset 0) - ) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (property "Reference" "R" - (at 2.032 0 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 0 0 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at -1.778 0 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "ki_keywords" "R res resistor" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "ki_fp_filters" "R_*" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (symbol "R_0_1" - (rectangle - (start -1.016 -2.54) - (end 1.016 2.54) - (stroke - (width 0.254) - (type default) - ) - (fill - (type none) - ) - ) - ) - (symbol "R_1_1" - (pin passive line - (at 0 3.81 270) - (length 1.27) - (name "~" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (number "1" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - ) - (pin passive line - (at 0 -3.81 90) - (length 1.27) - (name "~" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (number "2" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - ) - ) - ) - ) - (no_connect - (at 88.9 74.93) - (uuid "5833ab2c-0b21-4284-bda0-ec7a7f3886e3") - ) - (no_connect - (at 137.16 74.93) - (uuid "6a8eab8a-8b70-48aa-8775-bd58e38e6544") - ) - (wire - (pts - (xy 96.52 74.93) (xy 129.54 74.93) - ) - (stroke - (width 0) - (type default) - ) - (uuid "3c913039-c0ff-4276-9bfd-95aa6d609814") - ) - (rule_area - (polyline - (pts - (xy 102.87 66.04) (xy 119.38 66.04) (xy 119.38 78.74) (xy 113.03 85.09) (xy 107.95 85.09) (xy 102.87 80.01) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid 732edf9e-56d8-43fc-b7ec-e3df2ffeb182) - ) - ) - (netclass_flag "" - (length 2.54) - (shape round) - (at 106.68 66.04 0) - (fields_autoplaced yes) - (effects - (font - (size 1.27 1.27) - ) - (justify left bottom) - ) - (uuid "0e535a38-1e87-423a-9462-046eeca2761f") - (property "Netclass" "CLASS1" - (at 107.3785 63.5 0) - (effects - (font - (size 1.27 1.27) - (italic yes) - ) - (justify left) - ) - ) - ) - (netclass_flag "" - (length 2.54) - (shape round) - (at 115.57 66.04 0) - (fields_autoplaced yes) - (effects - (font - (size 1.27 1.27) - ) - (justify left bottom) - ) - (uuid "3651b727-06a6-4517-b594-14249bcb01ff") - (property "Netclass" "CLASS2" - (at 116.2685 63.5 0) - (effects - (font - (size 1.27 1.27) - (italic yes) - ) - (justify left) - ) - ) - ) - (netclass_flag "" - (length 2.54) - (shape round) - (at 111.76 85.09 180) - (fields_autoplaced yes) - (effects - (font - (size 1.27 1.27) - ) - (justify right bottom) - ) - (uuid "39c91c96-4582-476e-aaa8-0403610211a4") - (property "Netclass" "CLASS3" - (at 112.4585 87.63 0) - (effects - (font - (size 1.27 1.27) - (italic yes) - ) - (justify left) - ) - ) - ) - (symbol - (lib_id "Device:R") - (at 133.35 74.93 270) - (unit 1) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (dnp no) - (fields_autoplaced yes) - (uuid "69906541-660f-49dd-b971-79ef911d51f2") - (property "Reference" "R2" - (at 133.35 68.58 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 133.35 71.12 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at 133.35 73.152 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 133.35 74.93 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 133.35 74.93 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (pin "1" - (uuid "5a4f2edd-e02e-4a2a-b273-2a79268c7b9b") - ) - (pin "2" - (uuid "92e081c4-e86d-400c-82e1-d46671606b34") - ) - (instances - (project "RuleAreaThreeNetclassDirectives" - (path "/3faa707b-1d78-466d-bafe-1ee08b43bb08" - (reference "R2") - (unit 1) - ) - ) - ) - ) - (symbol - (lib_id "Device:R") - (at 92.71 74.93 270) - (unit 1) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (dnp no) - (fields_autoplaced yes) - (uuid "6c332818-966e-43a5-87c5-6aea83712c35") - (property "Reference" "R1" - (at 92.71 68.58 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 92.71 71.12 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at 92.71 73.152 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 92.71 74.93 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 92.71 74.93 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (pin "1" - (uuid "50fab8cc-532c-479e-a764-1688c768c001") - ) - (pin "2" - (uuid "0f5fce2a-437e-4928-b1e0-0469819dd910") - ) - (instances - (project "RuleAreaThreeNetclassDirectives" - (path "/3faa707b-1d78-466d-bafe-1ee08b43bb08" - (reference "R1") - (unit 1) - ) - ) - ) - ) - (sheet_instances - (path "/" - (page "1") - ) - ) -) diff --git a/qa/data/eeschema/RuleAreaTwoNetclassDirectives.kicad_sch b/qa/data/eeschema/RuleAreaTwoNetclassDirectives.kicad_sch deleted file mode 100644 index 3c30f7825e..0000000000 --- a/qa/data/eeschema/RuleAreaTwoNetclassDirectives.kicad_sch +++ /dev/null @@ -1,350 +0,0 @@ -(kicad_sch - (version 20240417) - (generator "eeschema") - (generator_version "8.99") - (uuid "72af7883-b930-45a7-b8c1-7781d1afdd37") - (paper "A4") - (lib_symbols - (symbol "Device:R" - (pin_numbers hide) - (pin_names - (offset 0) - ) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (property "Reference" "R" - (at 2.032 0 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 0 0 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at -1.778 0 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "ki_keywords" "R res resistor" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "ki_fp_filters" "R_*" - (at 0 0 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (symbol "R_0_1" - (rectangle - (start -1.016 -2.54) - (end 1.016 2.54) - (stroke - (width 0.254) - (type default) - ) - (fill - (type none) - ) - ) - ) - (symbol "R_1_1" - (pin passive line - (at 0 3.81 270) - (length 1.27) - (name "~" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (number "1" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - ) - (pin passive line - (at 0 -3.81 90) - (length 1.27) - (name "~" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (number "2" - (effects - (font - (size 1.27 1.27) - ) - ) - ) - ) - ) - ) - ) - (no_connect - (at 106.68 71.12) - (uuid "2f717211-60fa-4046-b14f-c148c1bebb31") - ) - (no_connect - (at 154.94 71.12) - (uuid "e58e3d56-33f2-47c1-8169-9b603a68c30f") - ) - (wire - (pts - (xy 114.3 71.12) (xy 147.32 71.12) - ) - (stroke - (width 0) - (type default) - ) - (uuid "2d14d2f0-6ae7-41c8-8699-c57748f8f4ae") - ) - (rule_area - (polyline - (pts - (xy 121.92 62.23) (xy 137.16 62.23) (xy 137.16 73.66) (xy 135.89 74.93) (xy 123.19 74.93) (xy 121.92 73.66) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid 826526a6-b643-4832-8cb3-7693aac87471) - ) - ) - (netclass_flag "" - (length 2.54) - (shape round) - (at 133.35 62.23 0) - (fields_autoplaced yes) - (effects - (font - (size 1.27 1.27) - ) - (justify left bottom) - ) - (uuid "0318db31-1e4c-4d69-8534-0e5f3ee9c7eb") - (property "Netclass" "CLASS2" - (at 134.0485 59.69 0) - (effects - (font - (size 1.27 1.27) - (italic yes) - ) - (justify left) - ) - ) - ) - (netclass_flag "" - (length 2.54) - (shape round) - (at 124.46 62.23 0) - (fields_autoplaced yes) - (effects - (font - (size 1.27 1.27) - ) - (justify left bottom) - ) - (uuid "74dc4bc7-6913-49ba-a2f3-bcdc39c3019f") - (property "Netclass" "CLASS1" - (at 125.1585 59.69 0) - (effects - (font - (size 1.27 1.27) - (italic yes) - ) - (justify left) - ) - ) - ) - (symbol - (lib_id "Device:R") - (at 151.13 71.12 270) - (unit 1) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (dnp no) - (fields_autoplaced yes) - (uuid "4f5c367d-1c08-48f1-86dc-e95b0140a51b") - (property "Reference" "R2" - (at 151.13 64.77 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 151.13 67.31 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at 151.13 69.342 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 151.13 71.12 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 151.13 71.12 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (pin "1" - (uuid "dbe85168-ed53-4e8a-8c45-277d6c150cde") - ) - (pin "2" - (uuid "4c070690-f1aa-48d2-a083-8c7fe39df9c2") - ) - (instances - (project "RuleAreaTwoNetclassDirectives" - (path "/72af7883-b930-45a7-b8c1-7781d1afdd37" - (reference "R2") - (unit 1) - ) - ) - ) - ) - (symbol - (lib_id "Device:R") - (at 110.49 71.12 270) - (unit 1) - (exclude_from_sim no) - (in_bom yes) - (on_board yes) - (dnp no) - (fields_autoplaced yes) - (uuid "7848d115-602f-44c3-b980-c1e03934ea7e") - (property "Reference" "R1" - (at 110.49 64.77 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Value" "R" - (at 110.49 67.31 90) - (effects - (font - (size 1.27 1.27) - ) - ) - ) - (property "Footprint" "" - (at 110.49 69.342 90) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Datasheet" "~" - (at 110.49 71.12 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (property "Description" "Resistor" - (at 110.49 71.12 0) - (effects - (font - (size 1.27 1.27) - ) - (hide yes) - ) - ) - (pin "1" - (uuid "84a25105-1263-4adf-a0a5-a2bdf51e736e") - ) - (pin "2" - (uuid "4d2f1a67-27d6-4ef0-a95f-9a34d0373e7d") - ) - (instances - (project "RuleAreaTwoNetclassDirectives" - (path "/72af7883-b930-45a7-b8c1-7781d1afdd37" - (reference "R1") - (unit 1) - ) - ) - ) - ) - (sheet_instances - (path "/" - (page "1") - ) - ) -) diff --git a/qa/data/eeschema/RuleAreaTwoOverlaps.kicad_sch b/qa/data/eeschema/RuleAreaTwoOverlaps.kicad_sch deleted file mode 100644 index 11b789fe37..0000000000 --- a/qa/data/eeschema/RuleAreaTwoOverlaps.kicad_sch +++ /dev/null @@ -1,58 +0,0 @@ -(kicad_sch - (version 20240417) - (generator "eeschema") - (generator_version "8.99") - (uuid "e77939c4-758d-4d0c-a6e5-dc441c8c54c9") - (paper "A4") - (lib_symbols) - (rule_area - (polyline - (pts - (xy 105.41 66.04) (xy 105.41 95.25) (xy 124.46 95.25) (xy 133.35 86.36) (xy 133.35 83.82) (xy 115.57 66.04) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid b2e29650-5d7b-46fa-b3ac-2da8c988ba4f) - ) - ) - (rule_area - (polyline - (pts - (xy 85.09 76.2) (xy 114.3 76.2) (xy 114.3 107.95) (xy 92.71 107.95) (xy 85.09 100.33) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid c2d18c36-f42f-4d71-b979-aec0f5842e3b) - ) - ) - (rule_area - (polyline - (pts - (xy 68.58 60.96) (xy 96.52 60.96) (xy 97.79 62.23) (xy 97.79 88.9) (xy 76.2 88.9) (xy 68.58 81.28) - ) - (stroke - (width 0) - (type dash) - ) - (fill - (type none) - ) - (uuid d4219527-beea-4857-99ad-9080af58cbc4) - ) - ) - (sheet_instances - (path "/" - (page "1") - ) - ) -) diff --git a/qa/data/eeschema/netlists/multinetclasses/multinetclasses.kicad_pro b/qa/data/eeschema/netlists/multinetclasses/multinetclasses.kicad_pro new file mode 100644 index 0000000000..e71b367d72 --- /dev/null +++ b/qa/data/eeschema/netlists/multinetclasses/multinetclasses.kicad_pro @@ -0,0 +1,482 @@ +{ + "board": { + "3dviewports": [], + "design_settings": { + "defaults": {}, + "diff_pair_dimensions": [], + "drc_exclusions": [], + "rules": {}, + "track_widths": [], + "via_dimensions": [] + }, + "ipc2581": { + "dist": "", + "distpn": "", + "internal_id": "", + "mfg": "", + "mpn": "" + }, + "layer_presets": [], + "viewports": [] + }, + "boards": [], + "cvpcb": { + "equivalence_files": [] + }, + "erc": { + "erc_exclusions": [], + "meta": { + "version": 0 + }, + "pin_map": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 2 + ], + [ + 0, + 2, + 0, + 1, + 0, + 0, + 1, + 0, + 2, + 2, + 2, + 2 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 1, + 0, + 1, + 2 + ], + [ + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 2, + 1, + 1, + 2 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 2 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2 + ], + [ + 1, + 1, + 1, + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 2 + ], + [ + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 2 + ], + [ + 0, + 2, + 1, + 2, + 0, + 0, + 1, + 0, + 2, + 2, + 2, + 2 + ], + [ + 0, + 2, + 0, + 1, + 0, + 0, + 1, + 0, + 2, + 0, + 0, + 2 + ], + [ + 0, + 2, + 1, + 1, + 0, + 0, + 1, + 0, + 2, + 0, + 0, + 2 + ], + [ + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2 + ] + ], + "rule_severities": { + "bus_definition_conflict": "error", + "bus_entry_needed": "error", + "bus_to_bus_conflict": "error", + "bus_to_net_conflict": "error", + "conflicting_netclasses": "error", + "different_unit_footprint": "error", + "different_unit_net": "error", + "duplicate_reference": "error", + "duplicate_sheet_names": "error", + "endpoint_off_grid": "warning", + "extra_units": "error", + "footprint_link_issues": "warning", + "four_way_junction": "ignore", + "global_label_dangling": "warning", + "hier_label_mismatch": "error", + "label_multiple_wires": "warning", + "lib_symbol_issues": "warning", + "lib_symbol_mismatch": "warning", + "missing_bidi_pin": "warning", + "missing_input_pin": "warning", + "missing_power_pin": "error", + "missing_unit": "warning", + "multiple_net_names": "warning", + "net_not_bus_member": "warning", + "no_connect_connected": "warning", + "no_connect_dangling": "warning", + "overlapping_rule_areas": "error", + "pin_not_connected": "error", + "pin_not_driven": "error", + "pin_to_pin": "warning", + "power_pin_not_driven": "error", + "similar_label_and_power": "warning", + "similar_labels": "warning", + "similar_power": "warning", + "simulation_model_issue": "ignore", + "single_global_label": "ignore", + "unannotated": "error", + "unit_value_mismatch": "error", + "unresolved_variable": "error", + "wire_dangling": "error" + } + }, + "libraries": { + "pinned_footprint_libs": [], + "pinned_symbol_libs": [] + }, + "meta": { + "filename": "MultiNetclasses.kicad_pro", + "version": 1 + }, + "net_settings": { + "classes": [ + { + "bus_width": 12, + "clearance": 0.2, + "diff_pair_gap": 0.25, + "diff_pair_via_gap": 0.25, + "diff_pair_width": 0.2, + "line_style": 0, + "microvia_diameter": 0.3, + "microvia_drill": 0.1, + "name": "Default", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "priority": 2147483647, + "schematic_color": "rgba(0, 0, 0, 0.000)", + "track_width": 0.2, + "via_diameter": 0.6, + "via_drill": 0.3, + "wire_width": 6 + }, + { + "name": "CLASS1", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "priority": 2, + "schematic_color": "rgba(0, 0, 0, 0.000)" + }, + { + "name": "CLASS2", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "priority": 1, + "schematic_color": "rgba(0, 0, 0, 0.000)" + }, + { + "bus_width": 12, + "clearance": 0.1778, + "diff_pair_gap": 0.2286, + "diff_pair_width": 0.1778, + "line_style": 0, + "microvia_diameter": 0.2794, + "microvia_drill": 0.0762, + "name": "CLASS_COMPLETE", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "priority": 0, + "schematic_color": "rgba(0, 0, 0, 0.000)", + "track_width": 0.1778, + "via_diameter": 0.5842, + "via_drill": 0.2794, + "wire_width": 6 + } + ], + "meta": { + "version": 4 + }, + "net_colors": null, + "netclass_assignments": { + "/BUS.A0": [ + "CLASS1", + "CLASS3" + ], + "/BUS.A1": [ + "CLASS1" + ], + "/BUS.A2": [ + "CLASS1", + "CLASS4" + ], + "/BUS.SIGNAL": [ + "CLASS1", + "CLASS2" + ], + "/BUS{SIGNAL A[0..1]}": [ + "CLASS1" + ], + "/BUS{SIGNAL A[0..2]}": [ + "CLASS1" + ], + "/NET_1": [ + "CLASS2", + "CLASS3" + ], + "/NET_2": [ + "CLASS_COMPLETE" + ], + "/NET_3": [ + "CLASS3", + "CLASS4", + "CLASS_COMPLETE" + ], + "/NET_4": [ + "CLASS3", + "CLASS4", + "CLASS_COMPLETE" + ] + }, + "netclass_patterns": [] + }, + "pcbnew": { + "last_paths": { + "gencad": "", + "idf": "", + "netlist": "", + "plot": "", + "pos_files": "", + "specctra_dsn": "", + "step": "", + "svg": "", + "vrml": "" + }, + "page_layout_descr_file": "" + }, + "schematic": { + "annotate_start_num": 0, + "bom_export_filename": "${PROJECTNAME}.csv", + "bom_fmt_presets": [], + "bom_fmt_settings": { + "field_delimiter": ",", + "keep_line_breaks": false, + "keep_tabs": false, + "name": "CSV", + "ref_delimiter": ",", + "ref_range_delimiter": "", + "string_delimiter": "\"" + }, + "bom_presets": [], + "bom_settings": { + "exclude_dnp": false, + "fields_ordered": [ + { + "group_by": false, + "label": "Reference", + "name": "Reference", + "show": true + }, + { + "group_by": false, + "label": "Qty", + "name": "${QUANTITY}", + "show": true + }, + { + "group_by": true, + "label": "Value", + "name": "Value", + "show": true + }, + { + "group_by": true, + "label": "DNP", + "name": "${DNP}", + "show": true + }, + { + "group_by": true, + "label": "Exclude from BOM", + "name": "${EXCLUDE_FROM_BOM}", + "show": true + }, + { + "group_by": true, + "label": "Exclude from Board", + "name": "${EXCLUDE_FROM_BOARD}", + "show": true + }, + { + "group_by": true, + "label": "Footprint", + "name": "Footprint", + "show": true + }, + { + "group_by": false, + "label": "Datasheet", + "name": "Datasheet", + "show": true + } + ], + "filter_string": "", + "group_symbols": true, + "include_excluded_from_bom": true, + "name": "Default Editing", + "sort_asc": true, + "sort_field": "Reference" + }, + "connection_grid_size": 50.0, + "drawing": { + "dashed_lines_dash_length_ratio": 12.0, + "dashed_lines_gap_length_ratio": 3.0, + "default_line_thickness": 6.0, + "default_text_size": 50.0, + "field_names": [], + "intersheets_ref_own_page": false, + "intersheets_ref_prefix": "", + "intersheets_ref_short": false, + "intersheets_ref_show": false, + "intersheets_ref_suffix": "", + "junction_size_choice": 3, + "label_size_ratio": 0.375, + "operating_point_overlay_i_precision": 3, + "operating_point_overlay_i_range": "~A", + "operating_point_overlay_v_precision": 3, + "operating_point_overlay_v_range": "~V", + "overbar_offset_ratio": 1.23, + "pin_symbol_size": 25.0, + "text_offset_ratio": 0.15 + }, + "legacy_lib_dir": "", + "legacy_lib_list": [], + "meta": { + "version": 1 + }, + "net_format_name": "", + "page_layout_descr_file": "", + "plot_directory": "", + "space_save_all_events": true, + "spice_current_sheet_as_root": false, + "spice_external_command": "spice \"%I\"", + "spice_model_current_sheet_as_root": true, + "spice_save_all_currents": false, + "spice_save_all_dissipations": false, + "spice_save_all_voltages": false, + "subpart_first_id": 65, + "subpart_id_separator": 0 + }, + "sheets": [ + [ + "bc9d1c5e-a887-4e72-af9f-7d5405947d97", + "Root" + ] + ], + "text_variables": {} +} diff --git a/qa/data/eeschema/netlists/multinetclasses/multinetclasses.kicad_sch b/qa/data/eeschema/netlists/multinetclasses/multinetclasses.kicad_sch new file mode 100644 index 0000000000..9bbd53ad8e --- /dev/null +++ b/qa/data/eeschema/netlists/multinetclasses/multinetclasses.kicad_sch @@ -0,0 +1,1628 @@ +(kicad_sch + (version 20240716) + (generator "eeschema") + (generator_version "8.99") + (uuid "bc9d1c5e-a887-4e72-af9f-7d5405947d97") + (paper "A4") + (lib_symbols + (symbol "Device:R" + (pin_numbers hide) + (pin_names + (offset 0) + ) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (property "Reference" "R" + (at 2.032 0 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 0 0 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at -1.778 0 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 0 0 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 0 0 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "ki_keywords" "R res resistor" + (at 0 0 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "ki_fp_filters" "R_*" + (at 0 0 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (symbol "R_0_1" + (rectangle + (start -1.016 -2.54) + (end 1.016 2.54) + (stroke + (width 0.254) + (type default) + ) + (fill + (type none) + ) + ) + ) + (symbol "R_1_1" + (pin passive line + (at 0 3.81 270) + (length 1.27) + (name "~" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (number "1" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + ) + (pin passive line + (at 0 -3.81 90) + (length 1.27) + (name "~" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (number "2" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + ) + ) + (embedded_fonts no) + ) + ) + (text "Netclasses should resolve as:\n\n/BUS.SIGNAL -> CLASS2,CLASS1,Default\n/BUS.A0 -> CLASS1,CLASS3,Default\n/BUS.A1 -> CLASS1,Default\n/BUS.A2 -> CLASS1,CLASS4,Default\n/NET_1 -> CLASS2,CLASS3,Default\n/NET_2 -> CLASS_COMPLETE\n" + (exclude_from_sim no) + (at 183.896 50.038 0) + (effects + (font + (size 1.27 1.27) + ) + (justify left) + ) + (uuid "c6d819a3-1a62-4749-b687-13f4fe893435") + ) + (bus_entry + (at 86.36 48.26) + (size 2.54 2.54) + (stroke + (width 0) + (type default) + ) + (uuid "09d3d8cb-8b76-45e8-8e87-d37d5fb23f1f") + ) + (bus_entry + (at 86.36 30.48) + (size 2.54 2.54) + (stroke + (width 0) + (type default) + ) + (uuid "2a1afc8a-88cf-4107-88ac-6c4b94f9a25d") + ) + (bus_entry + (at 86.36 55.88) + (size 2.54 2.54) + (stroke + (width 0) + (type default) + ) + (uuid "a25a8457-a7e4-477a-9884-8819b4f69261") + ) + (bus_entry + (at 86.36 68.58) + (size 2.54 2.54) + (stroke + (width 0) + (type default) + ) + (uuid "b188a8eb-d246-4209-a15c-aef3446bcecb") + ) + (wire + (pts + (xy 88.9 50.8) (xy 88.9 53.34) + ) + (stroke + (width 0) + (type default) + ) + (uuid "06c878a9-4cbd-4313-b485-59764f9ecf9e") + ) + (wire + (pts + (xy 85.09 121.92) (xy 132.08 121.92) + ) + (stroke + (width 0) + (type default) + ) + (uuid "133078b4-49ed-4721-b112-db818adeb329") + ) + (wire + (pts + (xy 88.9 77.47) (xy 135.89 77.47) + ) + (stroke + (width 0) + (type default) + ) + (uuid "4441b3be-9ddf-4ab4-9c55-ac04cebd880d") + ) + (wire + (pts + (xy 85.09 139.7) (xy 132.08 139.7) + ) + (stroke + (width 0) + (type default) + ) + (uuid "47160e4c-50a1-41c1-9f26-94bda63350fa") + ) + (wire + (pts + (xy 88.9 41.91) (xy 135.89 41.91) + ) + (stroke + (width 0) + (type default) + ) + (uuid "6482e0ec-d80b-47d3-a3c7-590155d8bd6d") + ) + (bus + (pts + (xy 86.36 30.48) (xy 86.36 48.26) + ) + (stroke + (width 0) + (type default) + ) + (uuid "699d0bfe-515d-4a61-a920-3860c05218fe") + ) + (wire + (pts + (xy 88.9 66.04) (xy 135.89 66.04) + ) + (stroke + (width 0) + (type default) + ) + (uuid "6cb05da7-c0dd-4d53-8eff-094e63c03f22") + ) + (bus + (pts + (xy 86.36 24.13) (xy 86.36 30.48) + ) + (stroke + (width 0) + (type default) + ) + (uuid "77a1667e-0f75-4d8a-8f65-f10227c261ac") + ) + (bus + (pts + (xy 86.36 55.88) (xy 86.36 68.58) + ) + (stroke + (width 0) + (type default) + ) + (uuid "78461402-5239-42b9-ae8b-5e87a7d282e0") + ) + (wire + (pts + (xy 88.9 58.42) (xy 88.9 66.04) + ) + (stroke + (width 0) + (type default) + ) + (uuid "7b8e7bf0-a800-4c53-9323-ef1042260729") + ) + (wire + (pts + (xy 88.9 33.02) (xy 88.9 41.91) + ) + (stroke + (width 0) + (type default) + ) + (uuid "86775574-2c6b-45c4-b52e-a8fd9630f75b") + ) + (wire + (pts + (xy 88.9 53.34) (xy 135.89 53.34) + ) + (stroke + (width 0) + (type default) + ) + (uuid "9cc500eb-546f-4aee-9fe1-adf59ade5ac3") + ) + (bus + (pts + (xy 86.36 68.58) (xy 86.36 82.55) + ) + (stroke + (width 0) + (type default) + ) + (uuid "a8f52a20-9dd9-4323-8b14-c3a94849329e") + ) + (wire + (pts + (xy 85.09 163.83) (xy 132.08 163.83) + ) + (stroke + (width 0) + (type default) + ) + (uuid "c77cf431-47db-454e-a7f5-88b08bbc673b") + ) + (bus + (pts + (xy 86.36 48.26) (xy 86.36 55.88) + ) + (stroke + (width 0) + (type default) + ) + (uuid "ceea50ab-1873-4a4d-ae01-3d3dd92b14d6") + ) + (wire + (pts + (xy 85.09 107.95) (xy 132.08 107.95) + ) + (stroke + (width 0) + (type default) + ) + (uuid "e22d1e23-40ab-4c2e-8f21-07fd3bc6a5d4") + ) + (wire + (pts + (xy 88.9 71.12) (xy 88.9 77.47) + ) + (stroke + (width 0) + (type default) + ) + (uuid "fa97e3ae-a582-4153-9370-96eed751d7f6") + ) + (label "BUS.A1" + (at 121.92 66.04 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "0668f585-5e19-40f0-a821-bf3362514561") + ) + (label "BUS.SIGNAL" + (at 121.92 41.91 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "1e4c8a10-3be3-4c5b-beab-b9d6f33bf023") + ) + (label "BUS{SIGNAL A[0..2]}" + (at 86.36 24.13 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "505e1218-c259-44d9-a2bb-5fdd0b9bea53") + ) + (label "NET_4" + (at 88.9 163.83 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "59c445f1-3f25-40df-9f76-42f3a0d26321") + ) + (label "NET_1" + (at 88.9 107.95 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "6145ae74-b637-4a72-a5de-ad08388fb892") + ) + (label "NET_2" + (at 88.9 121.92 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "823a4f74-51bd-40f0-b6e4-de9b486cd251") + ) + (label "BUS.A0" + (at 121.92 53.34 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "c203e942-304a-4fe3-80f7-dcfd59b4cf0c") + ) + (label "BUS.A2" + (at 121.92 77.47 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "cc36e759-9291-4227-a034-f31cf9376c94") + ) + (label "NET_3" + (at 88.9 139.7 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "f1308710-8c5c-4584-a706-b3735972840b") + ) + (rule_area + (polyline + (pts + (xy 96.52 74.93) (xy 109.22 74.93) (xy 109.22 85.09) (xy 96.52 85.09) + ) + (stroke + (width 0) + (type dash) + ) + (fill + (type none) + ) + (uuid 040a28b5-2d48-433c-9cd4-ab93d3b46d38) + ) + ) + (rule_area + (polyline + (pts + (xy 96.52 134.62) (xy 106.68 134.62) (xy 106.68 144.78) (xy 96.52 144.78) + ) + (stroke + (width 0) + (type dash) + ) + (fill + (type none) + ) + (uuid 6ba20b94-0e46-4b8f-a023-c91a1d3b84ac) + ) + ) + (rule_area + (polyline + (pts + (xy 97.79 158.75) (xy 102.87 158.75) (xy 102.87 165.1) (xy 97.79 165.1) + ) + (stroke + (width 0) + (type dash) + ) + (fill + (type none) + ) + (uuid c6597973-2b5f-459c-ac9e-71a9364928a8) + ) + ) + (rule_area + (polyline + (pts + (xy 96.52 162.56) (xy 102.87 162.56) (xy 102.87 168.91) (xy 96.52 168.91) + ) + (stroke + (width 0) + (type dash) + ) + (fill + (type none) + ) + (uuid e848db3e-0d49-478e-af4c-5b39d67bd9d2) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 99.06 41.91 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "102f1d77-52c3-4835-948d-486fd427488b") + (property "Netclass" "CLASS2" + (at 99.7585 39.37 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 110.49 139.7 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "20fe2096-2c56-4c5a-be18-dd8ed4e8c24b") + (property "Netclass" "CLASS_COMPLETE" + (at 111.1885 137.16 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 110.49 163.83 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "22160d5c-1402-4993-8488-cd3b6af99118") + (property "Netclass" "CLASS_COMPLETE" + (at 111.1885 161.29 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 101.6 168.91 180) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify right bottom) + ) + (uuid "246e7e52-5508-4c7c-a6cb-a19bdc658f61") + (property "Netclass" "CLASS3" + (at 102.2985 171.45 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 97.79 53.34 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "267fbc3d-1cc5-44cc-8b0b-0a0bcf1a5231") + (property "Netclass" "CLASS3" + (at 98.4885 50.8 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 101.6 74.93 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "3f0ba5c8-6358-45d3-b5c7-713bb6a5348f") + (property "Netclass" "CLASS4" + (at 102.2985 72.39 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 102.87 107.95 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "4bf6d01b-dee7-467f-846d-cf469aea7978") + (property "Netclass" "CLASS2" + (at 103.5685 105.41 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 118.11 107.95 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "58ae08ae-b593-4ff6-a87c-8381a0141c98") + (property "Netclass" "CLASS3" + (at 118.8085 105.41 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 101.6 158.75 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "b3cce970-5671-4671-ad74-60327667aeb2") + (property "Netclass" "CLASS4" + (at 102.2985 156.21 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 101.6 134.62 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "d621a8cb-a64e-4a49-9e1a-e53c70125578") + (property "Netclass" "CLASS4" + (at 102.2985 132.08 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 110.49 121.92 0) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "ee6e16c3-4992-4509-af20-19bf69075886") + (property "Netclass" "CLASS_COMPLETE" + (at 111.1885 119.38 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 101.6 144.78 180) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify right bottom) + ) + (uuid "fa18d4f0-df63-4616-a8a9-4b9de0d5b15e") + (property "Netclass" "CLASS3" + (at 102.2985 147.32 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (netclass_flag "" + (length 2.54) + (shape round) + (at 86.36 40.64 90) + (fields_autoplaced yes) + (effects + (font + (size 1.27 1.27) + ) + (justify left bottom) + ) + (uuid "fd957ac5-ec16-49de-8074-14078956b7f0") + (property "Netclass" "CLASS1" + (at 83.82 39.9415 90) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (justify left) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 81.28 121.92 90) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "013297c8-cfd7-409f-b81d-c1d8f671a82f") + (property "Reference" "R7" + (at 81.28 115.57 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 81.28 118.11 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at 81.28 123.698 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 81.28 121.92 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 81.28 121.92 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "f891d7c2-13d0-495d-9577-32983715aeda") + ) + (pin "1" + (uuid "98d9c372-0032-41d3-9f7c-4cb8e6c7fdbb") + ) + (instances + (project "MultiNetclasses" + (path "/bc9d1c5e-a887-4e72-af9f-7d5405947d97" + (reference "R7") + (unit 1) + ) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 135.89 163.83 90) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "16ce1cd1-068c-44c7-bad3-3830596ae37d") + (property "Reference" "R12" + (at 135.89 157.48 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 135.89 160.02 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at 135.89 165.608 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 135.89 163.83 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 135.89 163.83 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "fb555104-eaba-4f66-9d02-1423fa23b904") + ) + (pin "1" + (uuid "e94d5933-c4b9-4269-a225-7451ad5233aa") + ) + (instances + (project "MultiNetclasses" + (path "/bc9d1c5e-a887-4e72-af9f-7d5405947d97" + (reference "R12") + (unit 1) + ) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 135.89 139.7 90) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "17b6ce67-6699-41d5-a096-6714796adaa3") + (property "Reference" "R10" + (at 135.89 133.35 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 135.89 135.89 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at 135.89 141.478 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 135.89 139.7 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 135.89 139.7 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "9f31f861-ffe4-4c44-88d6-e7f3cf6ba540") + ) + (pin "1" + (uuid "6627b24b-db2a-4b46-9b8b-bd8b97cc26cf") + ) + (instances + (project "MultiNetclasses" + (path "/bc9d1c5e-a887-4e72-af9f-7d5405947d97" + (reference "R10") + (unit 1) + ) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 135.89 107.95 90) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "1bad0c73-7972-4d84-814d-f9d67f2ba084") + (property "Reference" "R4" + (at 135.89 101.6 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 135.89 104.14 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at 135.89 109.728 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 135.89 107.95 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 135.89 107.95 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "c09ddcdb-0c17-461d-8337-b41c88d7a692") + ) + (pin "1" + (uuid "64656645-81df-4365-8ac8-d39a9faa5ec6") + ) + (instances + (project "NetclassERC1" + (path "/bc9d1c5e-a887-4e72-af9f-7d5405947d97" + (reference "R4") + (unit 1) + ) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 81.28 107.95 90) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "2b597e45-5af9-4ec4-9ed0-8151143d9e97") + (property "Reference" "R3" + (at 81.28 101.6 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 81.28 104.14 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at 81.28 109.728 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 81.28 107.95 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 81.28 107.95 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "0e7bf9ff-fc2f-468d-a728-00ecac0b0f93") + ) + (pin "1" + (uuid "0be24e0d-0a24-4977-a2c5-2be675852aee") + ) + (instances + (project "NetclassERC1" + (path "/bc9d1c5e-a887-4e72-af9f-7d5405947d97" + (reference "R3") + (unit 1) + ) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 139.7 53.34 90) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "692791d4-470e-4233-9e70-bfe645704f32") + (property "Reference" "R2" + (at 139.7 46.99 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 139.7 49.53 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at 139.7 55.118 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 139.7 53.34 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 139.7 53.34 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "aa7ed66c-102b-4afc-a9c2-3d2972a4c82d") + ) + (pin "1" + (uuid "79b18de2-3130-4ab1-afd4-1efd24f227ee") + ) + (instances + (project "NetclassERC1" + (path "/bc9d1c5e-a887-4e72-af9f-7d5405947d97" + (reference "R2") + (unit 1) + ) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 139.7 41.91 90) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "84ebbe6f-4f16-4b6e-882a-6dc4a67152da") + (property "Reference" "R1" + (at 139.7 35.56 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 139.7 38.1 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at 139.7 43.688 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 139.7 41.91 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 139.7 41.91 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "020b2909-d985-465c-acb5-e6ce89547311") + ) + (pin "1" + (uuid "0807e74f-65d5-435a-a5da-757b3cb3b00b") + ) + (instances + (project "" + (path "/bc9d1c5e-a887-4e72-af9f-7d5405947d97" + (reference "R1") + (unit 1) + ) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 81.28 139.7 90) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "8598689f-ce4f-414f-a720-b8fa4ecb6b41") + (property "Reference" "R9" + (at 81.28 133.35 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 81.28 135.89 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at 81.28 141.478 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 81.28 139.7 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 81.28 139.7 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "7c4c8b57-d447-472f-b751-c8f95c64ad61") + ) + (pin "1" + (uuid "fadd3114-9e7a-4c73-9cb4-83674a3ab498") + ) + (instances + (project "MultiNetclasses" + (path "/bc9d1c5e-a887-4e72-af9f-7d5405947d97" + (reference "R9") + (unit 1) + ) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 81.28 163.83 90) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "e238dcde-8495-47bf-bfca-aceb29a93079") + (property "Reference" "R11" + (at 81.28 157.48 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 81.28 160.02 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at 81.28 165.608 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 81.28 163.83 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 81.28 163.83 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "897fb258-a610-4cac-b815-8f0adf675695") + ) + (pin "1" + (uuid "c9476fbd-19d9-45b7-bbc3-ad702dd3be09") + ) + (instances + (project "MultiNetclasses" + (path "/bc9d1c5e-a887-4e72-af9f-7d5405947d97" + (reference "R11") + (unit 1) + ) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 139.7 66.04 90) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "e49cddf9-077d-4aa7-bdff-e73daae9738c") + (property "Reference" "R5" + (at 139.7 59.69 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 139.7 62.23 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at 139.7 67.818 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 139.7 66.04 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 139.7 66.04 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "0291109b-6553-4aaf-a789-c4834c8c1eec") + ) + (pin "1" + (uuid "e0b512fa-45c2-4f4b-8e35-b74061c9f865") + ) + (instances + (project "NetclassERC1" + (path "/bc9d1c5e-a887-4e72-af9f-7d5405947d97" + (reference "R5") + (unit 1) + ) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 135.89 121.92 90) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "f90a3215-ad26-41e7-bf2f-ac1d56dee10c") + (property "Reference" "R8" + (at 135.89 115.57 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 135.89 118.11 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at 135.89 123.698 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 135.89 121.92 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 135.89 121.92 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "33e38591-72f7-4a42-8d77-bcaae9850ed4") + ) + (pin "1" + (uuid "87a7a104-d839-4810-9426-486c1b3944e8") + ) + (instances + (project "MultiNetclasses" + (path "/bc9d1c5e-a887-4e72-af9f-7d5405947d97" + (reference "R8") + (unit 1) + ) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 139.7 77.47 90) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "fdcc8b6a-a00d-4f52-864b-51f063eb922e") + (property "Reference" "R6" + (at 139.7 71.12 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Value" "R" + (at 139.7 73.66 90) + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Footprint" "" + (at 139.7 79.248 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 139.7 77.47 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 139.7 77.47 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "95d4942b-c109-429e-a8bf-ad08adf1eef6") + ) + (pin "1" + (uuid "f8ce39e9-b5ce-4cee-b7e2-e79df2075903") + ) + (instances + (project "MultiNetclasses" + (path "/bc9d1c5e-a887-4e72-af9f-7d5405947d97" + (reference "R6") + (unit 1) + ) + ) + ) + ) + (sheet_instances + (path "/" + (page "1") + ) + ) + (embedded_fonts no) +) diff --git a/qa/data/pcbnew/multinetclasses_drc.kicad_dru b/qa/data/pcbnew/multinetclasses_drc.kicad_dru new file mode 100644 index 0000000000..f100a2e31a --- /dev/null +++ b/qa/data/pcbnew/multinetclasses_drc.kicad_dru @@ -0,0 +1,19 @@ +(version 1) + +(rule rule_1 + (constraint track_width (max 10mil)) + (condition "A.hasNetclass('CLASS2')") + (severity error) +) + +(rule rule_2 + (constraint track_width (max 30mil)) + (condition "A.NetClass == 'CLASS1,Default'") + (severity error) +) + +(rule rule_3 + (constraint track_width (max 5mil)) + (condition "A.NetClass == 'Default'") + (severity error) +) \ No newline at end of file diff --git a/qa/data/pcbnew/multinetclasses_drc.kicad_pcb b/qa/data/pcbnew/multinetclasses_drc.kicad_pcb new file mode 100644 index 0000000000..c21f66b30b --- /dev/null +++ b/qa/data/pcbnew/multinetclasses_drc.kicad_pcb @@ -0,0 +1,1014 @@ +(kicad_pcb + (version 20240706) + (generator "pcbnew") + (generator_version "8.99") + (general + (thickness 1.6) + (legacy_teardrops no) + ) + (paper "A4") + (layers + (0 "F.Cu" signal) + (31 "B.Cu" signal) + (32 "B.Adhes" user "B.Adhesive") + (33 "F.Adhes" user "F.Adhesive") + (34 "B.Paste" user) + (35 "F.Paste" user) + (36 "B.SilkS" user "B.Silkscreen") + (37 "F.SilkS" user "F.Silkscreen") + (38 "B.Mask" user) + (39 "F.Mask" user) + (40 "Dwgs.User" user "User.Drawings") + (41 "Cmts.User" user "User.Comments") + (42 "Eco1.User" user "User.Eco1") + (43 "Eco2.User" user "User.Eco2") + (44 "Edge.Cuts" user) + (45 "Margin" user) + (46 "B.CrtYd" user "B.Courtyard") + (47 "F.CrtYd" user "F.Courtyard") + (48 "B.Fab" user) + (49 "F.Fab" user) + (50 "User.1" auxiliary) + (51 "User.2" auxiliary) + (52 "User.3" auxiliary) + (53 "User.4" auxiliary) + (54 "User.5" auxiliary) + (55 "User.6" auxiliary) + (56 "User.7" auxiliary) + (57 "User.8" auxiliary) + (58 "User.9" auxiliary) + ) + (setup + (pad_to_mask_clearance 0) + (allow_soldermask_bridges_in_footprints no) + (tenting front back) + (pcbplotparams + (layerselection 0x00010fc_ffffffff) + (plot_on_all_layers_selection 0x0000000_00000000) + (disableapertmacros no) + (usegerberextensions no) + (usegerberattributes yes) + (usegerberadvancedattributes yes) + (creategerberjobfile yes) + (dashed_line_dash_ratio 12.000000) + (dashed_line_gap_ratio 3.000000) + (svgprecision 4) + (plotframeref no) + (mode 1) + (useauxorigin no) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15.000000) + (pdf_front_fp_property_popups yes) + (pdf_back_fp_property_popups yes) + (pdf_metadata yes) + (dxfpolygonmode yes) + (dxfimperialunits yes) + (dxfusepcbnewfont yes) + (psnegative no) + (psa4output no) + (plotreference yes) + (plotvalue yes) + (plotfptext yes) + (plotinvisibletext no) + (sketchpadsonfab no) + (plotpadnumbers no) + (subtractmaskfromsilk no) + (outputformat 1) + (mirror no) + (drillshape 1) + (scaleselection 1) + (outputdirectory "") + ) + ) + (net 0 "") + (net 1 "unconnected-(R1-Pad1)") + (net 2 "Net-(R1-Pad2)") + (net 3 "unconnected-(R2-Pad2)") + (net 4 "unconnected-(R3-Pad2)") + (net 5 "Net-(R3-Pad1)") + (net 6 "unconnected-(R4-Pad1)") + (footprint "Resistor_SMD:R_0805_2012Metric" + (layer "F.Cu") + (uuid "6fa361af-8de0-4529-9fe9-c068235509c5") + (at 91.9775 76.91) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: IPC-SM-782 page 72, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf), generated with kicad-footprint-generator") + (tags "resistor") + (property "Reference" "R4" + (at 0 -1.65 0) + (layer "F.SilkS") + (uuid "610738a0-97c0-49e0-9c6a-95439211bcc4") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "R" + (at 0 1.65 0) + (layer "F.Fab") + (uuid "99374578-08cb-40fd-8d5c-db48f866672d") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Footprint" "Resistor_SMD:R_0805_2012Metric" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "0cf17a80-ef83-46e5-9ac2-aa88f78cb5c0") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Datasheet" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "fb11be23-cdc7-4107-b393-9dc0a7b8e595") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Description" "Resistor" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "2008b080-5e7c-41b1-a76c-09c87d4ab48e") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property ki_fp_filters "R_*") + (path "/babb2dc9-71a2-419d-8b34-0fc314503d38") + (sheetname "Root") + (sheetfile "multinetclasses_drc.kicad_sch") + (attr smd) + (fp_line + (start -0.227064 -0.735) + (end 0.227064 -0.735) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "984d7d1d-929f-4992-93e7-884a9071e812") + ) + (fp_line + (start -0.227064 0.735) + (end 0.227064 0.735) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "4496bfdd-5050-4315-add4-ba8bbe046d8b") + ) + (fp_line + (start -1.68 -0.95) + (end 1.68 -0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "1b81308d-ed1e-4459-a9cc-d6ba53e0cd7a") + ) + (fp_line + (start -1.68 0.95) + (end -1.68 -0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "683c4413-d274-4d7d-ac6b-dee569effdd7") + ) + (fp_line + (start 1.68 -0.95) + (end 1.68 0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "ee584701-ccc2-4781-98a1-7ab7df64357b") + ) + (fp_line + (start 1.68 0.95) + (end -1.68 0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "a472a84d-475c-49e0-a274-143da489d304") + ) + (fp_line + (start -1 -0.625) + (end 1 -0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "1880eff6-37a5-49c4-9a17-317be9d3391f") + ) + (fp_line + (start -1 0.625) + (end -1 -0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "af83f1f4-5466-4483-90bd-dd1b4fc47f87") + ) + (fp_line + (start 1 -0.625) + (end 1 0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "62850874-5c00-41c0-8370-334390d0d705") + ) + (fp_line + (start 1 0.625) + (end -1 0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "392b2cb0-708a-4952-a1eb-3211578fabe3") + ) + (fp_text user "${REFERENCE}" + (at 0 0 0) + (layer "F.Fab") + (uuid "ba9d47d7-14ea-41ab-9390-21846853555e") + (effects + (font + (size 0.5 0.5) + (thickness 0.08) + ) + ) + ) + (pad "1" smd roundrect + (at -0.9125 0) + (size 1.025 1.4) + (layers "F.Cu" "F.Paste" "F.Mask") + (roundrect_rratio 0.243902) + (net 6 "unconnected-(R4-Pad1)") + (pintype "passive+no_connect") + (uuid "f375c5bd-a6be-4783-9916-e175b2dd101f") + ) + (pad "2" smd roundrect + (at 0.9125 0) + (size 1.025 1.4) + (layers "F.Cu" "F.Paste" "F.Mask") + (roundrect_rratio 0.243902) + (net 5 "Net-(R3-Pad1)") + (pintype "passive") + (uuid "c99d68e6-bede-4e15-96c7-55746cc9e356") + ) + (embedded_fonts no) + (model "${KICAD8_3DMODEL_DIR}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl" + (offset + (xyz 0 0 0) + ) + (scale + (xyz 1 1 1) + ) + (rotate + (xyz 0 0 0) + ) + ) + ) + (footprint "Resistor_SMD:R_0805_2012Metric" + (layer "F.Cu") + (uuid "95389f3c-85bb-4b8e-812a-9ae273546d13") + (at 92.0075 71.86) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: IPC-SM-782 page 72, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf), generated with kicad-footprint-generator") + (tags "resistor") + (property "Reference" "R1" + (at 0 -1.65 0) + (layer "F.SilkS") + (uuid "36818ec5-55fc-4300-9fbe-7444c7fa3a1a") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "R" + (at 0 1.65 0) + (layer "F.Fab") + (uuid "8ce321bd-517d-40bc-880e-7c5881f696c0") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Footprint" "Resistor_SMD:R_0805_2012Metric" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "5e2ef19a-f562-45bd-91f1-e9b6ea1291b8") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Datasheet" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "876a6906-01f2-41ee-b909-fec2f99fec8b") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Description" "Resistor" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "3d9ac356-edd7-4e34-9f86-3d2752f4d4be") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property ki_fp_filters "R_*") + (path "/241c6028-d179-47d5-838d-b34a506e651d") + (sheetname "Root") + (sheetfile "multinetclasses_drc.kicad_sch") + (attr smd) + (fp_line + (start -0.227064 -0.735) + (end 0.227064 -0.735) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "93cb5ea3-8197-4380-9668-d43eff29d705") + ) + (fp_line + (start -0.227064 0.735) + (end 0.227064 0.735) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "5d559823-b22b-4a88-9a01-415670eab6ef") + ) + (fp_line + (start -1.68 -0.95) + (end 1.68 -0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "a50e357b-3a22-4651-a703-e26c8f431263") + ) + (fp_line + (start -1.68 0.95) + (end -1.68 -0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "ee018e3e-0725-41b6-998c-9e7228b5a182") + ) + (fp_line + (start 1.68 -0.95) + (end 1.68 0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "a430c5cd-528f-4da6-923b-449fde3fc687") + ) + (fp_line + (start 1.68 0.95) + (end -1.68 0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "3d8213cb-ca37-46a2-89dd-f59d75e3c5c7") + ) + (fp_line + (start -1 -0.625) + (end 1 -0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "03a181d8-b8b3-426a-b9f0-860885c8a40c") + ) + (fp_line + (start -1 0.625) + (end -1 -0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "a85f8b40-586f-458c-a2eb-b5283d72bd28") + ) + (fp_line + (start 1 -0.625) + (end 1 0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "abdf5627-d274-4adb-a1b4-d9972e2ab7d2") + ) + (fp_line + (start 1 0.625) + (end -1 0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "9f92f716-301d-4f70-ba9a-fb48a2979e24") + ) + (fp_text user "${REFERENCE}" + (at 0 0 0) + (layer "F.Fab") + (uuid "b571f50a-95b9-48fa-b819-c8b5be465a4c") + (effects + (font + (size 0.5 0.5) + (thickness 0.08) + ) + ) + ) + (pad "1" smd roundrect + (at -0.9125 0) + (size 1.025 1.4) + (layers "F.Cu" "F.Paste" "F.Mask") + (roundrect_rratio 0.243902) + (net 1 "unconnected-(R1-Pad1)") + (pintype "passive+no_connect") + (uuid "7607eac6-dbc5-4832-8f45-933b8603723b") + ) + (pad "2" smd roundrect + (at 0.9125 0) + (size 1.025 1.4) + (layers "F.Cu" "F.Paste" "F.Mask") + (roundrect_rratio 0.243902) + (net 2 "Net-(R1-Pad2)") + (pintype "passive") + (uuid "a6788b5c-c345-4eaf-9dc2-392aecdd372c") + ) + (embedded_fonts no) + (model "${KICAD8_3DMODEL_DIR}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl" + (offset + (xyz 0 0 0) + ) + (scale + (xyz 1 1 1) + ) + (rotate + (xyz 0 0 0) + ) + ) + ) + (footprint "Resistor_SMD:R_0805_2012Metric" + (layer "F.Cu") + (uuid "ce8ef068-2665-4fa1-8424-68cc42f5e641") + (at 104.1675 76.88) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: IPC-SM-782 page 72, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf), generated with kicad-footprint-generator") + (tags "resistor") + (property "Reference" "R3" + (at 0 -1.65 0) + (layer "F.SilkS") + (uuid "698c5219-be1c-4bc9-a0ec-71bbc79802bc") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "R" + (at 0 1.65 0) + (layer "F.Fab") + (uuid "c46f98a6-fe30-4409-a41a-da2a395f6eca") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Footprint" "Resistor_SMD:R_0805_2012Metric" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "a59d7640-2cc7-4a4c-85aa-8d6565aad010") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Datasheet" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "5e5b01c9-7202-4a86-8857-8240b8f68269") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Description" "Resistor" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "948232f4-7787-428a-9005-9a969399e846") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property ki_fp_filters "R_*") + (path "/a309f89e-9361-426e-b855-d6363e6e3f57") + (sheetname "Root") + (sheetfile "multinetclasses_drc.kicad_sch") + (attr smd) + (fp_line + (start -0.227064 -0.735) + (end 0.227064 -0.735) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "4a18862c-b67e-4d88-91d9-1708c244d3d5") + ) + (fp_line + (start -0.227064 0.735) + (end 0.227064 0.735) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "e317efad-b1fa-42d9-86a3-c424e6895dee") + ) + (fp_line + (start -1.68 -0.95) + (end 1.68 -0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "9ff14a37-c74e-4aa4-b78c-09e54245be09") + ) + (fp_line + (start -1.68 0.95) + (end -1.68 -0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "e913d525-4a92-4181-b193-569d05e743a7") + ) + (fp_line + (start 1.68 -0.95) + (end 1.68 0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "60d56579-b798-4859-905b-7ef138d3c47e") + ) + (fp_line + (start 1.68 0.95) + (end -1.68 0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "4597d622-dee1-4415-8974-77a57daddf4b") + ) + (fp_line + (start -1 -0.625) + (end 1 -0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "c428686f-6628-4efc-97ff-a2b05f46a8b9") + ) + (fp_line + (start -1 0.625) + (end -1 -0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "4151196f-4d7f-44bb-8732-e71c2378aadf") + ) + (fp_line + (start 1 -0.625) + (end 1 0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "f1ab0a2a-10fd-4848-85a4-e83224aa446c") + ) + (fp_line + (start 1 0.625) + (end -1 0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "b1e79351-ea7b-4ebb-ac7b-fa38448f212d") + ) + (fp_text user "${REFERENCE}" + (at 0 0 0) + (layer "F.Fab") + (uuid "36e61941-2a81-4cc6-ab8d-359b46734bbe") + (effects + (font + (size 0.5 0.5) + (thickness 0.08) + ) + ) + ) + (pad "1" smd roundrect + (at -0.9125 0) + (size 1.025 1.4) + (layers "F.Cu" "F.Paste" "F.Mask") + (roundrect_rratio 0.243902) + (net 5 "Net-(R3-Pad1)") + (pintype "passive") + (uuid "67a43e38-7450-4c9e-a76f-e6e7de8dd2f9") + ) + (pad "2" smd roundrect + (at 0.9125 0) + (size 1.025 1.4) + (layers "F.Cu" "F.Paste" "F.Mask") + (roundrect_rratio 0.243902) + (net 4 "unconnected-(R3-Pad2)") + (pintype "passive+no_connect") + (uuid "39b77ab5-6107-402d-9ef7-3553e446aae7") + ) + (embedded_fonts no) + (model "${KICAD8_3DMODEL_DIR}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl" + (offset + (xyz 0 0 0) + ) + (scale + (xyz 1 1 1) + ) + (rotate + (xyz 0 0 0) + ) + ) + ) + (footprint "Resistor_SMD:R_0805_2012Metric" + (layer "F.Cu") + (uuid "f5072944-4754-4fee-a3e6-06f374de8f85") + (at 104.0175 71.88) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: IPC-SM-782 page 72, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf), generated with kicad-footprint-generator") + (tags "resistor") + (property "Reference" "R2" + (at 0 -1.65 0) + (layer "F.SilkS") + (uuid "3cdedb54-f5bc-4a12-9748-f79010435406") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "R" + (at 0 1.65 0) + (layer "F.Fab") + (uuid "6e26b12a-a0b7-4ea6-98c3-201f235d7842") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Footprint" "Resistor_SMD:R_0805_2012Metric" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "4d37a1a9-5d9b-4b30-bf5b-0bbd7dc78f55") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Datasheet" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "2581bf98-aa20-4687-9487-143d5c7b8a22") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Description" "Resistor" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "15b63204-b1f5-4a4a-93af-8d94e9f8a662") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property ki_fp_filters "R_*") + (path "/adf5c04f-1ad9-4f7e-94b8-ca2d71b65e15") + (sheetname "Root") + (sheetfile "multinetclasses_drc.kicad_sch") + (attr smd) + (fp_line + (start -0.227064 -0.735) + (end 0.227064 -0.735) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "cc9e1f15-31ef-4bb3-9cc6-ef0c7f70bab4") + ) + (fp_line + (start -0.227064 0.735) + (end 0.227064 0.735) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "eeac0688-1bc9-4569-9486-fe0c3eae5847") + ) + (fp_line + (start -1.68 -0.95) + (end 1.68 -0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "da50366a-126d-4131-bb34-0ec1f22ac0f1") + ) + (fp_line + (start -1.68 0.95) + (end -1.68 -0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "76c14f24-e496-4b02-be3a-00532856d43f") + ) + (fp_line + (start 1.68 -0.95) + (end 1.68 0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "f90aecee-ed44-4d4d-b12b-b70445cea176") + ) + (fp_line + (start 1.68 0.95) + (end -1.68 0.95) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "1f7f2687-181b-423b-8fad-567c293f2a14") + ) + (fp_line + (start -1 -0.625) + (end 1 -0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "af9a0f38-9e73-41ec-a72a-bca1771cc9a7") + ) + (fp_line + (start -1 0.625) + (end -1 -0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "796248de-540c-42b0-8e42-963cccff3d89") + ) + (fp_line + (start 1 -0.625) + (end 1 0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "04ebc41f-2794-4256-85d7-fa6153b3bfe8") + ) + (fp_line + (start 1 0.625) + (end -1 0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "2fc646e7-0889-431f-90dc-4d275782a00e") + ) + (fp_text user "${REFERENCE}" + (at 0 0 0) + (layer "F.Fab") + (uuid "b3c3ea54-3fee-4fb7-9e63-fcceb791a99d") + (effects + (font + (size 0.5 0.5) + (thickness 0.08) + ) + ) + ) + (pad "1" smd roundrect + (at -0.9125 0) + (size 1.025 1.4) + (layers "F.Cu" "F.Paste" "F.Mask") + (roundrect_rratio 0.243902) + (net 2 "Net-(R1-Pad2)") + (pintype "passive") + (uuid "c03217c8-3f4f-425e-8100-b854faa30110") + ) + (pad "2" smd roundrect + (at 0.9125 0) + (size 1.025 1.4) + (layers "F.Cu" "F.Paste" "F.Mask") + (roundrect_rratio 0.243902) + (net 3 "unconnected-(R2-Pad2)") + (pintype "passive+no_connect") + (uuid "165f3c83-32ed-4211-aac6-677b9dbf888f") + ) + (embedded_fonts no) + (model "${KICAD8_3DMODEL_DIR}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl" + (offset + (xyz 0 0 0) + ) + (scale + (xyz 1 1 1) + ) + (rotate + (xyz 0 0 0) + ) + ) + ) + (gr_line + (start 109.55 84.65) + (end 89.81 82.83) + (stroke + (width 0.05) + (type default) + ) + (layer "Edge.Cuts") + (uuid "397c7092-13a9-4a57-844a-69be981223bc") + ) + (gr_line + (start 88.99 67) + (end 109.11 67.32) + (stroke + (width 0.05) + (type default) + ) + (layer "Edge.Cuts") + (uuid "427d2051-6cd9-4e89-b83d-e5a6eb7ccdac") + ) + (gr_line + (start 109.11 67.32) + (end 109.55 84.65) + (stroke + (width 0.05) + (type default) + ) + (layer "Edge.Cuts") + (uuid "b648b916-1742-4c4f-98f1-58c816f6335d") + ) + (gr_line + (start 88.99 67) + (end 88.48 67.7) + (stroke + (width 0.05) + (type default) + ) + (layer "Edge.Cuts") + (uuid "d70808e7-2dc7-47a6-a1b1-4cd9c3b26ad4") + ) + (gr_line + (start 89.81 82.83) + (end 88.48 67.7) + (stroke + (width 0.05) + (type default) + ) + (layer "Edge.Cuts") + (uuid "e75d0c91-37b0-4521-97d2-39315da42921") + ) + (segment + (start 103.105 71.88) + (end 92.94 71.88) + (width 1.016) + (layer "F.Cu") + (net 2) + (uuid "2a7c931b-072e-4000-9dc5-1c4949cffe4f") + ) + (segment + (start 92.89 76.91) + (end 103.225 76.91) + (width 0.508) + (layer "F.Cu") + (net 5) + (uuid "995d2ce6-a1f6-4315-a31f-e3c626d0a199") + ) + (embedded_fonts no) +) diff --git a/qa/data/pcbnew/multinetclasses_drc.kicad_pro b/qa/data/pcbnew/multinetclasses_drc.kicad_pro new file mode 100644 index 0000000000..c1b3dd88b3 --- /dev/null +++ b/qa/data/pcbnew/multinetclasses_drc.kicad_pro @@ -0,0 +1,626 @@ +{ + "board": { + "3dviewports": [], + "design_settings": { + "defaults": { + "apply_defaults_to_fp_fields": false, + "apply_defaults_to_fp_shapes": false, + "apply_defaults_to_fp_text": false, + "board_outline_line_width": 0.05, + "copper_line_width": 0.2, + "copper_text_italic": false, + "copper_text_size_h": 1.5, + "copper_text_size_v": 1.5, + "copper_text_thickness": 0.3, + "copper_text_upright": false, + "courtyard_line_width": 0.05, + "dimension_precision": 4, + "dimension_units": 3, + "dimensions": { + "arrow_length": 1270000, + "extension_offset": 500000, + "keep_text_aligned": true, + "suppress_zeroes": false, + "text_position": 0, + "units_format": 1 + }, + "fab_line_width": 0.1, + "fab_text_italic": false, + "fab_text_size_h": 1.0, + "fab_text_size_v": 1.0, + "fab_text_thickness": 0.15, + "fab_text_upright": false, + "other_line_width": 0.1, + "other_text_italic": false, + "other_text_size_h": 1.0, + "other_text_size_v": 1.0, + "other_text_thickness": 0.15, + "other_text_upright": false, + "pads": { + "drill": 0.8, + "height": 1.27, + "width": 2.54 + }, + "silk_line_width": 0.1, + "silk_text_italic": false, + "silk_text_size_h": 1.0, + "silk_text_size_v": 1.0, + "silk_text_thickness": 0.1, + "silk_text_upright": false, + "zones": { + "min_clearance": 0.5 + } + }, + "diff_pair_dimensions": [], + "drc_exclusions": [], + "meta": { + "version": 2 + }, + "rule_severities": { + "annular_width": "error", + "clearance": "error", + "connection_width": "warning", + "copper_edge_clearance": "error", + "copper_sliver": "warning", + "courtyards_overlap": "error", + "diff_pair_gap_out_of_range": "error", + "diff_pair_uncoupled_length_too_long": "error", + "drill_out_of_range": "error", + "duplicate_footprints": "warning", + "extra_footprint": "warning", + "footprint": "error", + "footprint_symbol_mismatch": "warning", + "footprint_type_mismatch": "ignore", + "hole_clearance": "error", + "hole_to_hole": "warning", + "holes_co_located": "warning", + "invalid_outline": "error", + "isolated_copper": "warning", + "item_on_disabled_layer": "error", + "items_not_allowed": "error", + "length_out_of_range": "error", + "lib_footprint_issues": "warning", + "lib_footprint_mismatch": "warning", + "malformed_courtyard": "error", + "microvia_drill_out_of_range": "error", + "missing_courtyard": "ignore", + "missing_footprint": "warning", + "net_conflict": "warning", + "npth_inside_courtyard": "ignore", + "padstack": "warning", + "pth_inside_courtyard": "ignore", + "shorting_items": "error", + "silk_edge_clearance": "warning", + "silk_over_copper": "warning", + "silk_overlap": "warning", + "skew_out_of_range": "error", + "solder_mask_bridge": "error", + "starved_thermal": "error", + "text_height": "warning", + "text_thickness": "warning", + "through_hole_pad_without_hole": "error", + "too_many_vias": "error", + "track_dangling": "warning", + "track_width": "error", + "tracks_crossing": "error", + "unconnected_items": "error", + "unresolved_variable": "error", + "via_dangling": "warning", + "zones_intersect": "error" + }, + "rules": { + "max_error": 0.005, + "min_clearance": 0.0, + "min_connection": 0.0, + "min_copper_edge_clearance": 0.5, + "min_hole_clearance": 0.25, + "min_hole_to_hole": 0.25, + "min_microvia_diameter": 0.2, + "min_microvia_drill": 0.1, + "min_resolved_spokes": 2, + "min_silk_clearance": 0.0, + "min_text_height": 0.8, + "min_text_thickness": 0.08, + "min_through_hole_diameter": 0.3, + "min_track_width": 0.0, + "min_via_annular_width": 0.1, + "min_via_diameter": 0.5, + "solder_mask_to_copper_clearance": 0.0, + "use_height_for_length_calcs": true + }, + "teardrop_options": [ + { + "td_onpadsmd": true, + "td_onroundshapesonly": false, + "td_ontrackend": false, + "td_onviapad": true + } + ], + "teardrop_parameters": [ + { + "td_allow_use_two_tracks": true, + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_on_pad_in_zone": false, + "td_target_name": "td_round_shape", + "td_width_to_size_filter_ratio": 0.9 + }, + { + "td_allow_use_two_tracks": true, + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_on_pad_in_zone": false, + "td_target_name": "td_rect_shape", + "td_width_to_size_filter_ratio": 0.9 + }, + { + "td_allow_use_two_tracks": true, + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_on_pad_in_zone": false, + "td_target_name": "td_track_end", + "td_width_to_size_filter_ratio": 0.9 + } + ], + "track_widths": [], + "tuning_pattern_settings": { + "diff_pair_defaults": { + "corner_radius_percentage": 80, + "corner_style": 1, + "max_amplitude": 1.0, + "min_amplitude": 0.2, + "single_sided": false, + "spacing": 1.0 + }, + "diff_pair_skew_defaults": { + "corner_radius_percentage": 80, + "corner_style": 1, + "max_amplitude": 1.0, + "min_amplitude": 0.2, + "single_sided": false, + "spacing": 0.6 + }, + "single_track_defaults": { + "corner_radius_percentage": 80, + "corner_style": 1, + "max_amplitude": 1.0, + "min_amplitude": 0.2, + "single_sided": false, + "spacing": 0.6 + } + }, + "via_dimensions": [], + "zones_allow_external_fillets": false + }, + "ipc2581": { + "dist": "", + "distpn": "", + "internal_id": "", + "mfg": "", + "mpn": "" + }, + "layer_presets": [], + "viewports": [] + }, + "boards": [], + "cvpcb": { + "equivalence_files": [] + }, + "erc": { + "erc_exclusions": [], + "meta": { + "version": 0 + }, + "pin_map": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 2 + ], + [ + 0, + 2, + 0, + 1, + 0, + 0, + 1, + 0, + 2, + 2, + 2, + 2 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 1, + 0, + 1, + 2 + ], + [ + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 2, + 1, + 1, + 2 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 2 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2 + ], + [ + 1, + 1, + 1, + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 2 + ], + [ + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 2 + ], + [ + 0, + 2, + 1, + 2, + 0, + 0, + 1, + 0, + 2, + 2, + 2, + 2 + ], + [ + 0, + 2, + 0, + 1, + 0, + 0, + 1, + 0, + 2, + 0, + 0, + 2 + ], + [ + 0, + 2, + 1, + 1, + 0, + 0, + 1, + 0, + 2, + 0, + 0, + 2 + ], + [ + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2 + ] + ], + "rule_severities": { + "bus_definition_conflict": "error", + "bus_entry_needed": "error", + "bus_to_bus_conflict": "error", + "bus_to_net_conflict": "error", + "conflicting_netclasses": "error", + "different_unit_footprint": "error", + "different_unit_net": "error", + "duplicate_reference": "error", + "duplicate_sheet_names": "error", + "endpoint_off_grid": "warning", + "extra_units": "error", + "footprint_link_issues": "warning", + "four_way_junction": "ignore", + "global_label_dangling": "warning", + "hier_label_mismatch": "error", + "label_multiple_wires": "warning", + "lib_symbol_issues": "warning", + "lib_symbol_mismatch": "warning", + "missing_bidi_pin": "warning", + "missing_input_pin": "warning", + "missing_power_pin": "error", + "missing_unit": "warning", + "multiple_net_names": "warning", + "net_not_bus_member": "warning", + "no_connect_connected": "warning", + "no_connect_dangling": "warning", + "overlapping_rule_areas": "error", + "pin_not_connected": "error", + "pin_not_driven": "error", + "pin_to_pin": "warning", + "power_pin_not_driven": "error", + "similar_label_and_power": "warning", + "similar_labels": "warning", + "similar_power": "warning", + "simulation_model_issue": "ignore", + "single_global_label": "ignore", + "unannotated": "error", + "unit_value_mismatch": "error", + "unresolved_variable": "error", + "wire_dangling": "error" + } + }, + "libraries": { + "pinned_footprint_libs": [], + "pinned_symbol_libs": [] + }, + "meta": { + "filename": "multinetclasses_drc.kicad_pro", + "version": 1 + }, + "net_settings": { + "classes": [ + { + "bus_width": 12, + "clearance": 0.2, + "diff_pair_gap": 0.25, + "diff_pair_via_gap": 0.25, + "diff_pair_width": 0.2, + "line_style": 0, + "microvia_diameter": 0.3, + "microvia_drill": 0.1, + "name": "Default", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "priority": -1, + "schematic_color": "rgba(0, 0, 0, 0.000)", + "track_width": 0.2, + "via_diameter": 0.6, + "via_drill": 0.3, + "wire_width": 6 + } + ], + "meta": { + "version": 4 + }, + "net_colors": null, + "netclass_assignments": { + "Net-(R1-Pad2)": [ + "CLASS1" + ], + "Net-(R3-Pad1)": [ + "CLASS1", + "CLASS2" + ] + }, + "netclass_patterns": [] + }, + "pcbnew": { + "last_paths": { + "gencad": "", + "idf": "", + "netlist": "", + "plot": "", + "pos_files": "", + "specctra_dsn": "", + "step": "", + "svg": "", + "vrml": "" + }, + "page_layout_descr_file": "" + }, + "schematic": { + "annotate_start_num": 0, + "bom_export_filename": "${PROJECTNAME}.csv", + "bom_fmt_presets": [], + "bom_fmt_settings": { + "field_delimiter": ",", + "keep_line_breaks": false, + "keep_tabs": false, + "name": "CSV", + "ref_delimiter": ",", + "ref_range_delimiter": "", + "string_delimiter": "\"" + }, + "bom_presets": [], + "bom_settings": { + "exclude_dnp": false, + "fields_ordered": [ + { + "group_by": false, + "label": "Reference", + "name": "Reference", + "show": true + }, + { + "group_by": false, + "label": "Qty", + "name": "${QUANTITY}", + "show": true + }, + { + "group_by": true, + "label": "Value", + "name": "Value", + "show": true + }, + { + "group_by": true, + "label": "DNP", + "name": "${DNP}", + "show": true + }, + { + "group_by": true, + "label": "Exclude from BOM", + "name": "${EXCLUDE_FROM_BOM}", + "show": true + }, + { + "group_by": true, + "label": "Exclude from Board", + "name": "${EXCLUDE_FROM_BOARD}", + "show": true + }, + { + "group_by": true, + "label": "Footprint", + "name": "Footprint", + "show": true + }, + { + "group_by": false, + "label": "Datasheet", + "name": "Datasheet", + "show": true + }, + { + "group_by": false, + "label": "Description", + "name": "Description", + "show": false + }, + { + "group_by": false, + "label": "#", + "name": "${ITEM_NUMBER}", + "show": false + } + ], + "filter_string": "", + "group_symbols": true, + "include_excluded_from_bom": true, + "name": "", + "sort_asc": true, + "sort_field": "Reference" + }, + "connection_grid_size": 50.0, + "drawing": { + "dashed_lines_dash_length_ratio": 12.0, + "dashed_lines_gap_length_ratio": 3.0, + "default_line_thickness": 6.0, + "default_text_size": 50.0, + "field_names": [], + "intersheets_ref_own_page": false, + "intersheets_ref_prefix": "", + "intersheets_ref_short": false, + "intersheets_ref_show": false, + "intersheets_ref_suffix": "", + "junction_size_choice": 3, + "label_size_ratio": 0.375, + "operating_point_overlay_i_precision": 3, + "operating_point_overlay_i_range": "~A", + "operating_point_overlay_v_precision": 3, + "operating_point_overlay_v_range": "~V", + "overbar_offset_ratio": 1.23, + "pin_symbol_size": 25.0, + "text_offset_ratio": 0.15 + }, + "legacy_lib_dir": "", + "legacy_lib_list": [], + "meta": { + "version": 1 + }, + "net_format_name": "", + "page_layout_descr_file": "", + "plot_directory": "", + "space_save_all_events": true, + "spice_current_sheet_as_root": false, + "spice_external_command": "spice \"%I\"", + "spice_model_current_sheet_as_root": true, + "spice_save_all_currents": false, + "spice_save_all_dissipations": false, + "spice_save_all_voltages": false, + "subpart_first_id": 65, + "subpart_id_separator": 0 + }, + "sheets": [ + [ + "6360f841-f79b-45a0-9d89-6238b58cc46d", + "Root" + ] + ], + "text_variables": {} +} diff --git a/qa/schematic_utils/eeschema_test_utils.cpp b/qa/schematic_utils/eeschema_test_utils.cpp index 9d36b76255..a06f128677 100644 --- a/qa/schematic_utils/eeschema_test_utils.cpp +++ b/qa/schematic_utils/eeschema_test_utils.cpp @@ -32,6 +32,7 @@ #include #include #include +#include void KI_TEST::SCHEMATIC_TEST_FIXTURE::LoadSchematic( const wxString& aBaseName ) @@ -88,6 +89,13 @@ void KI_TEST::SCHEMATIC_TEST_FIXTURE::LoadSchematic( const wxString& aBaseName ) // NOTE: SchematicCleanUp is not called; QA schematics must already be clean or else // SchematicCleanUp must be freed from its UI dependencies. + std::unordered_set all_screens; + + for( const SCH_SHEET_PATH& path : sheets ) + all_screens.insert( path.LastScreen() ); + + SCH_RULE_AREA::UpdateRuleAreasInScreens( all_screens, nullptr ); + m_schematic.ConnectionGraph()->Recalculate( sheets, true ); } diff --git a/qa/tests/eeschema/CMakeLists.txt b/qa/tests/eeschema/CMakeLists.txt index 65acb2b60c..8c7c9cb35f 100644 --- a/qa/tests/eeschema/CMakeLists.txt +++ b/qa/tests/eeschema/CMakeLists.txt @@ -59,7 +59,6 @@ set( QA_EESCHEMA_SRCS erc/test_erc_no_connect.cpp erc/test_erc_hierarchical_schematics.cpp erc/test_erc_label_multiple_wires.cpp - erc/test_erc_rule_areas.cpp erc/test_erc_unconnected_wire_endpoints.cpp test_eagle_plugin.cpp diff --git a/qa/tests/eeschema/erc/test_erc_rule_areas.cpp b/qa/tests/eeschema/erc/test_erc_rule_areas.cpp deleted file mode 100644 index 7054b13735..0000000000 --- a/qa/tests/eeschema/erc/test_erc_rule_areas.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2024 KiCad Developers, see AUTHORS.TXT for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 3 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one at - * http://www.gnu.org/licenses/ - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - - -struct ERC_REGRESSION_TEST_FIXTURE -{ - ERC_REGRESSION_TEST_FIXTURE() : m_settingsManager( true /* headless */ ) {} - - SETTINGS_MANAGER m_settingsManager; - std::unique_ptr m_schematic; -}; - - -BOOST_FIXTURE_TEST_CASE( ERCRuleAreaNetClasseDirectives, ERC_REGRESSION_TEST_FIXTURE ) -{ - LOCALE_IO dummy; - - // Check for Errors when using rule area netclass directives - std::vector> tests = { { "RuleAreaOneNetclassDirective", 0 }, - { "RuleAreaTwoNetclassDirectives", 1 }, - { "RuleAreaThreeNetclassDirectives", 2 }, - { "RuleAreaNetclassConflictOnWire_1", 1 }, - { "RuleAreaNetclassConflictOnWire_2", 1 } }; - - for( const std::pair& test : tests ) - { - KI_TEST::LoadSchematic( m_settingsManager, test.first, m_schematic ); - - ERC_SETTINGS& settings = m_schematic->ErcSettings(); - SHEETLIST_ERC_ITEMS_PROVIDER errors( m_schematic.get() ); - - // Skip the "Modified symbol" warning - settings.m_ERCSeverities[ERCE_LIB_SYMBOL_ISSUES] = RPT_SEVERITY_IGNORE; - settings.m_ERCSeverities[ERCE_LIB_SYMBOL_MISMATCH] = RPT_SEVERITY_IGNORE; - - // Configure the rules under test - settings.m_ERCSeverities[ERCE_NETCLASS_CONFLICT] = RPT_SEVERITY_ERROR; - - std::unordered_set allScreens; - SCH_SCREENS screens( m_schematic->Root() ); - screens.BuildClientSheetPathList(); - - for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; - screen = screens.GetNext() ) - allScreens.insert( screen ); - - SCH_RULE_AREA::UpdateRuleAreasInScreens( allScreens, nullptr ); - - SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers(); - m_schematic->ConnectionGraph()->Recalculate( sheets, true ); - m_schematic->ConnectionGraph()->RunERC(); - - errors.SetSeverities( RPT_SEVERITY_ERROR | RPT_SEVERITY_WARNING ); - - ERC_REPORT reportWriter( m_schematic.get(), EDA_UNITS::MILLIMETRES ); - - BOOST_CHECK_MESSAGE( errors.GetCount() == test.second, - "Expected " << test.second << " errors in " << test.first.ToStdString() - << " but got " << errors.GetCount() << "\n" - << reportWriter.GetTextReport() ); - } -} - - -BOOST_FIXTURE_TEST_CASE( ERCRuleAreaOverlaps, ERC_REGRESSION_TEST_FIXTURE ) -{ - LOCALE_IO dummy; - - // Check for Errors when using rule area netclass directives - std::vector> tests = { { "RuleAreaNoOverlap", 0 }, - { "RuleAreaOneOverlap", 1 }, - { "RuleAreaOneOverlapTwice", 2 }, - { "RuleAreaTwoOverlaps", 2 } }; - - for( const std::pair& test : tests ) - { - KI_TEST::LoadSchematic( m_settingsManager, test.first, m_schematic ); - - ERC_SETTINGS& settings = m_schematic->ErcSettings(); - SHEETLIST_ERC_ITEMS_PROVIDER errors( m_schematic.get() ); - - // Skip the "Modified symbol" warning - settings.m_ERCSeverities[ERCE_LIB_SYMBOL_ISSUES] = RPT_SEVERITY_IGNORE; - settings.m_ERCSeverities[ERCE_LIB_SYMBOL_MISMATCH] = RPT_SEVERITY_IGNORE; - - // Configure the rules under test - settings.m_ERCSeverities[ERCE_OVERLAPPING_RULE_AREAS] = RPT_SEVERITY_ERROR; - - std::unordered_set allScreens; - SCH_SCREENS screens( m_schematic->Root() ); - screens.BuildClientSheetPathList(); - - for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() ) - allScreens.insert( screen ); - - SCH_RULE_AREA::UpdateRuleAreasInScreens( allScreens, nullptr ); - - SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers(); - m_schematic->ConnectionGraph()->Recalculate( sheets, true ); - - ERC_TESTER tester( m_schematic.get() ); - tester.RunRuleAreaERC(); - - errors.SetSeverities( RPT_SEVERITY_ERROR | RPT_SEVERITY_WARNING ); - - ERC_REPORT reportWriter( m_schematic.get(), EDA_UNITS::MILLIMETRES ); - - BOOST_CHECK_MESSAGE( errors.GetCount() == test.second, - "Expected " << test.second << " errors in " << test.first.ToStdString() - << " but got " << errors.GetCount() << "\n" - << reportWriter.GetTextReport() ); - } -} diff --git a/qa/tests/eeschema/test_sch_netclass.cpp b/qa/tests/eeschema/test_sch_netclass.cpp index d2df6711de..fba57c058f 100644 --- a/qa/tests/eeschema/test_sch_netclass.cpp +++ b/qa/tests/eeschema/test_sch_netclass.cpp @@ -22,6 +22,8 @@ #include #include +#include +#include class TEST_SCH_NETCLASS_FIXTURE : public KI_TEST::SCHEMATIC_TEST_FIXTURE {}; @@ -49,4 +51,36 @@ BOOST_AUTO_TEST_CASE( TestSubsheetNetclass ) } } +BOOST_AUTO_TEST_CASE( TestMultiNetclasses ) +{ + LoadSchematic( "multinetclasses" ); + + std::shared_ptr& netSettings = m_schematic.Prj().GetProjectFile().m_NetSettings; + + std::shared_ptr nc = netSettings->GetEffectiveNetClass( "/BUS.SIGNAL" ); + BOOST_CHECK_EQUAL( nc->GetVariableSubstitutionName(), "CLASS2,CLASS1,Default" ); + + nc = netSettings->GetEffectiveNetClass( "/BUS.A0" ); + BOOST_CHECK_EQUAL( nc->GetVariableSubstitutionName(), "CLASS1,CLASS3,Default" ); + + nc = netSettings->GetEffectiveNetClass( "/BUS.A1" ); + BOOST_CHECK_EQUAL( nc->GetVariableSubstitutionName(), "CLASS1,Default" ); + + nc = netSettings->GetEffectiveNetClass( "/BUS.A2" ); + wxString name = nc->GetName(); + BOOST_CHECK_EQUAL( nc->GetVariableSubstitutionName(), "CLASS1,CLASS4,Default" ); + + nc = netSettings->GetEffectiveNetClass( "/NET_1" ); + BOOST_CHECK_EQUAL( nc->GetVariableSubstitutionName(), "CLASS2,CLASS3,Default" ); + + nc = netSettings->GetEffectiveNetClass( "/NET_2" ); + BOOST_CHECK_EQUAL( nc->GetVariableSubstitutionName(), "CLASS_COMPLETE" ); + + nc = netSettings->GetEffectiveNetClass( "/NET_3" ); + BOOST_CHECK_EQUAL( nc->GetVariableSubstitutionName(), "CLASS_COMPLETE,CLASS3,CLASS4" ); + + nc = netSettings->GetEffectiveNetClass( "/NET_4" ); + BOOST_CHECK_EQUAL( nc->GetVariableSubstitutionName(), "CLASS_COMPLETE,CLASS3,CLASS4" ); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/qa/tests/pcbnew/CMakeLists.txt b/qa/tests/pcbnew/CMakeLists.txt index 4e13189951..9c0afc7008 100644 --- a/qa/tests/pcbnew/CMakeLists.txt +++ b/qa/tests/pcbnew/CMakeLists.txt @@ -57,6 +57,7 @@ set( QA_PCBNEW_SRCS drc/test_drc_copper_graphics.cpp drc/test_drc_copper_sliver.cpp drc/test_solder_mask_bridging.cpp + drc/test_drc_multi_netclasses.cpp pcb_io/altium/test_altium_rule_transformer.cpp pcb_io/altium/test_altium_pcblib_import.cpp diff --git a/qa/tests/pcbnew/drc/test_drc_multi_netclasses.cpp b/qa/tests/pcbnew/drc/test_drc_multi_netclasses.cpp new file mode 100644 index 0000000000..7e3c48af2c --- /dev/null +++ b/qa/tests/pcbnew/drc/test_drc_multi_netclasses.cpp @@ -0,0 +1,110 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +struct DRC_REGRESSION_TEST_FIXTURE +{ + DRC_REGRESSION_TEST_FIXTURE() : + m_settingsManager( true /* headless */ ) + { } + + SETTINGS_MANAGER m_settingsManager; + std::unique_ptr m_board; +}; + + +BOOST_FIXTURE_TEST_CASE( DRCMultiNetclasses, DRC_REGRESSION_TEST_FIXTURE ) +{ + // Check for minimum copper connection errors + + std::vector> tests = + { + { "multinetclasses_drc", 2 } + }; + + for( const std::pair& test : tests ) + { + KI_TEST::LoadBoard( m_settingsManager, test.first, m_board ); + KI_TEST::FillZones( m_board.get() ); + + std::vector violations; + BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); + + // Disable DRC tests not useful or not handled in this testcase + bds.m_DRCSeverities[ DRCE_INVALID_OUTLINE ] = SEVERITY::RPT_SEVERITY_IGNORE; + bds.m_DRCSeverities[ DRCE_UNCONNECTED_ITEMS ] = SEVERITY::RPT_SEVERITY_IGNORE; + bds.m_DRCSeverities[ DRCE_COPPER_SLIVER ] = SEVERITY::RPT_SEVERITY_IGNORE; + bds.m_DRCSeverities[ DRCE_STARVED_THERMAL ] = SEVERITY::RPT_SEVERITY_IGNORE; + bds.m_DRCSeverities[ DRCE_DRILL_OUT_OF_RANGE ] = SEVERITY::RPT_SEVERITY_IGNORE; + bds.m_DRCSeverities[ DRCE_VIA_DIAMETER ] = SEVERITY::RPT_SEVERITY_IGNORE; + // These DRC tests are not useful and do not work because they need a footprint library + // associated to the board + bds.m_DRCSeverities[ DRCE_LIB_FOOTPRINT_ISSUES ] = SEVERITY::RPT_SEVERITY_IGNORE; + bds.m_DRCSeverities[ DRCE_LIB_FOOTPRINT_MISMATCH ] = SEVERITY::RPT_SEVERITY_IGNORE; + + // Ensure that our desired error is fired + bds.m_DRCSeverities[ DRCE_TRACK_WIDTH ] = SEVERITY::RPT_SEVERITY_ERROR; + + bds.m_DRCEngine->SetViolationHandler( + [&]( const std::shared_ptr& aItem, VECTOR2I aPos, int aLayer ) + { + if( bds.GetSeverity( aItem->GetErrorCode() ) == SEVERITY::RPT_SEVERITY_ERROR ) + violations.push_back( *aItem ); + } ); + + bds.m_DRCEngine->RunTests( EDA_UNITS::MILLIMETRES, true, false ); + + if( violations.size() == test.second ) + { + BOOST_CHECK_EQUAL( 1, 1 ); // quiet "did not check any assertions" warning + BOOST_TEST_MESSAGE( wxString::Format( "DRC connection width: %s, passed", test.first ) ); + } + else + { + UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::INCHES ); + + std::map itemMap; + m_board->FillItemMap( itemMap ); + + for( const DRC_ITEM& item : violations ) + { + BOOST_TEST_MESSAGE( item.ShowReport( &unitsProvider, RPT_SEVERITY_ERROR, + itemMap ) ); + } + + BOOST_ERROR( wxString::Format( "DRC track width: %s, failed (violations found %d expected %d)", + test.first, (int)violations.size(), test.second ) ); + } + } +} diff --git a/resources/bitmaps_png/CMakeLists.txt b/resources/bitmaps_png/CMakeLists.txt index 9f5b13bbe8..434d95e34d 100644 --- a/resources/bitmaps_png/CMakeLists.txt +++ b/resources/bitmaps_png/CMakeLists.txt @@ -722,6 +722,7 @@ set( BMAPS_OTHER stroke_dashdotdot stroke_dot stroke_solid + stroke_none twistedpair viacalc ) diff --git a/resources/bitmaps_png/png/stroke_none.png b/resources/bitmaps_png/png/stroke_none.png new file mode 100644 index 0000000000000000000000000000000000000000..1d1605261e3873802b3117c71b48599a26658e60 GIT binary patch literal 268 zcmeAS@N?(olHy`uVBq!ia0vp^4nQox!3HFkJ+IURQk(@Ik;M!Qe1}1p@p%4<6riAF ziEBhjaDG}zd16s2LwR|*US?i)adKios$PCk`s{Z$Qb0vPAVtpk1(ija=@}&q&dv&s zB_&0fNu?#3`FXm*89=R$Ihon13K=CO1y=g{$wjG&C7ETZ$@#gt`FX`4lk{^klT-7G zQ;YSJDs_t!^-c5)^bdz5u>wuE_H=O!iD-R$!BLPwf#-n1f&I^Y-Q-NTs`eTe*L^E# qxW*v6z|?^~gZBbs6f+9<78CDLX4%xTg#AEc7(8A5T-G@yGywoxLsYx~ literal 0 HcmV?d00001 diff --git a/resources/bitmaps_png/png/stroke_none_dark.png b/resources/bitmaps_png/png/stroke_none_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..1d1605261e3873802b3117c71b48599a26658e60 GIT binary patch literal 268 zcmeAS@N?(olHy`uVBq!ia0vp^4nQox!3HFkJ+IURQk(@Ik;M!Qe1}1p@p%4<6riAF ziEBhjaDG}zd16s2LwR|*US?i)adKios$PCk`s{Z$Qb0vPAVtpk1(ija=@}&q&dv&s zB_&0fNu?#3`FXm*89=R$Ihon13K=CO1y=g{$wjG&C7ETZ$@#gt`FX`4lk{^klT-7G zQ;YSJDs_t!^-c5)^bdz5u>wuE_H=O!iD-R$!BLPwf#-n1f&I^Y-Q-NTs`eTe*L^E# qxW*v6z|?^~gZBbs6f+9<78CDLX4%xTg#AEc7(8A5T-G@yGywoxLsYx~ literal 0 HcmV?d00001 diff --git a/resources/bitmaps_png/sources/dark/stroke_none.svg b/resources/bitmaps_png/sources/dark/stroke_none.svg new file mode 100644 index 0000000000..660822305d --- /dev/null +++ b/resources/bitmaps_png/sources/dark/stroke_none.svg @@ -0,0 +1,68 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/resources/bitmaps_png/sources/light/stroke_none.svg b/resources/bitmaps_png/sources/light/stroke_none.svg new file mode 100644 index 0000000000..2d019c31d3 --- /dev/null +++ b/resources/bitmaps_png/sources/light/stroke_none.svg @@ -0,0 +1,68 @@ + + + + + + image/svg+xml + + + + + + + + +