KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_net_inspector_panel.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
22
25#include <confirm.h>
28#include <footprint.h>
29#include <pad.h>
30#include <pcb_edit_frame.h>
31#include <pcb_painter.h>
32#include <pcb_track.h>
33#include <pgm_base.h>
35#include <validators.h>
37#include <eda_pattern_match.h>
38
39#include <wx/wupdlock.h>
40#include <wx/headerctrl.h>
41#include <wx/filedlg.h>
42
43#include <algorithm>
44
46 NET_INSPECTOR_PANEL( parent, aFrame ),
47 m_zero_netitem( nullptr ),
48 m_frame( aFrame )
49{
51
52 m_data_model = new DATA_MODEL( *this );
53 m_netsList->AssociateModel( &*m_data_model );
54
55 // Rebuild nets list
56 buildNetsList( true );
57
58 // Register the panel to receive board change notifications
59 if( m_brd != nullptr )
60 {
62 m_brd->AddListener( this );
63 }
64
65 // Connect to board events
66 m_frame->Bind( EDA_EVT_UNITS_CHANGED, &PCB_NET_INSPECTOR_PANEL::onUnitsChanged, this );
67
68 // Connect to wxDataViewCtrl events
69 m_netsList->Bind( wxEVT_DATAVIEW_ITEM_EXPANDED, &PCB_NET_INSPECTOR_PANEL::OnExpandCollapseRow,
70 this );
71 m_netsList->Bind( wxEVT_DATAVIEW_ITEM_COLLAPSED, &PCB_NET_INSPECTOR_PANEL::OnExpandCollapseRow,
72 this );
73 m_netsList->Bind( wxEVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK,
75 m_netsList->Bind( wxEVT_DATAVIEW_ITEM_CONTEXT_MENU,
77 m_netsList->Bind( wxEVT_DATAVIEW_ITEM_ACTIVATED,
79 m_netsList->Bind( wxEVT_DATAVIEW_COLUMN_SORTED,
81}
82
84{
86
87 m_netsList->AssociateModel( nullptr );
88
89 if( m_brd != nullptr )
90 m_brd->RemoveListener( this );
91
92 // Disconnect from board events
93 m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &PCB_NET_INSPECTOR_PANEL::onUnitsChanged, this );
94
95 // Connect to wxDataViewCtrl events
96 m_netsList->Unbind( wxEVT_DATAVIEW_ITEM_EXPANDED, &PCB_NET_INSPECTOR_PANEL::OnExpandCollapseRow,
97 this );
98 m_netsList->Unbind( wxEVT_DATAVIEW_ITEM_COLLAPSED,
100 m_netsList->Unbind( wxEVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK,
102 m_netsList->Unbind( wxEVT_DATAVIEW_ITEM_CONTEXT_MENU,
104 m_netsList->Unbind( wxEVT_DATAVIEW_ITEM_ACTIVATED,
106 m_netsList->Unbind( wxEVT_DATAVIEW_COLUMN_SORTED,
108}
109
110
111/*****************************************************************************************
112 *
113 * Grid / model columns configuration
114 *
115 * ***************************************************************************************/
116
117
119{
120 m_columns.clear();
121
122 // Set up the column display vector
123 m_columns.emplace_back( 0u, UNDEFINED_LAYER, _( "Name" ), _( "Net Name" ),
125 m_columns.emplace_back( 1u, UNDEFINED_LAYER, _( "Netclass" ), _( "Netclass" ),
127 m_columns.emplace_back( 2u, UNDEFINED_LAYER, _( "Total Length" ), _( "Net Length" ),
129 m_columns.emplace_back( 3u, UNDEFINED_LAYER, _( "Via Count" ), _( "Via Count" ),
131 m_columns.emplace_back( 4u, UNDEFINED_LAYER, _( "Via Length" ), _( "Via Length" ),
133 m_columns.emplace_back( 5u, UNDEFINED_LAYER, _( "Track Length" ), _( "Track Length" ),
135 m_columns.emplace_back( 6u, UNDEFINED_LAYER, _( "Die Length" ), _( "Die Length" ),
137 m_columns.emplace_back( 7u, UNDEFINED_LAYER, _( "Pad Count" ), _( "Pad Count" ),
139
140 std::vector<std::function<void( void )>> add_col{
141 [&]()
142 {
143 m_netsList->AppendTextColumn( m_columns[COLUMN_NAME].display_name,
144 m_columns[COLUMN_NAME], wxDATAVIEW_CELL_INERT, -1,
145 wxALIGN_LEFT,
146 wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE );
147 },
148 [&]()
149 {
150 m_netsList->AppendTextColumn( m_columns[COLUMN_NETCLASS].display_name,
151 m_columns[COLUMN_NETCLASS], wxDATAVIEW_CELL_INERT, -1,
152 wxALIGN_LEFT,
153 wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_REORDERABLE
154 | wxDATAVIEW_COL_SORTABLE );
155 },
156 [&]()
157 {
158 m_netsList->AppendTextColumn( m_columns[COLUMN_TOTAL_LENGTH].display_name,
159 m_columns[COLUMN_TOTAL_LENGTH], wxDATAVIEW_CELL_INERT, -1,
160 wxALIGN_CENTER,
161 wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_REORDERABLE
162 | wxDATAVIEW_COL_SORTABLE );
163 },
164 [&]()
165 {
166 m_netsList->AppendTextColumn( m_columns[COLUMN_VIA_COUNT].display_name,
167 m_columns[COLUMN_VIA_COUNT], wxDATAVIEW_CELL_INERT, -1,
168 wxALIGN_CENTER,
169 wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_REORDERABLE
170 | wxDATAVIEW_COL_SORTABLE );
171 },
172 [&]()
173 {
174 m_netsList->AppendTextColumn( m_columns[COLUMN_VIA_LENGTH].display_name,
175 m_columns[COLUMN_VIA_LENGTH], wxDATAVIEW_CELL_INERT, -1,
176 wxALIGN_CENTER,
177 wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_REORDERABLE
178 | wxDATAVIEW_COL_SORTABLE );
179 },
180 [&]()
181 {
182 m_netsList->AppendTextColumn( m_columns[COLUMN_BOARD_LENGTH].display_name,
183 m_columns[COLUMN_BOARD_LENGTH], wxDATAVIEW_CELL_INERT, -1,
184 wxALIGN_CENTER,
185 wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_REORDERABLE
186 | wxDATAVIEW_COL_SORTABLE );
187 },
188 [&]()
189 {
190 m_netsList->AppendTextColumn( m_columns[COLUMN_PAD_DIE_LENGTH].display_name,
191 m_columns[COLUMN_PAD_DIE_LENGTH], wxDATAVIEW_CELL_INERT,
192 -1, wxALIGN_CENTER,
193 wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_REORDERABLE
194 | wxDATAVIEW_COL_SORTABLE );
195 },
196 [&]()
197 {
198 m_netsList->AppendTextColumn( m_columns[COLUMN_PAD_COUNT].display_name,
199 m_columns[COLUMN_PAD_COUNT], wxDATAVIEW_CELL_INERT, -1,
200 wxALIGN_CENTER,
201 wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_REORDERABLE
202 | wxDATAVIEW_COL_SORTABLE );
203 }
204 };
205
206 // If we have not yet loaded the first board, use a dummy local settings object to ensure we
207 // don't over-write existing board settings (note that PCB_EDIT_FRAME loads the local settings
208 // object prior to loading the board; the two are not synced and we need to account for that)
209 PANEL_NET_INSPECTOR_SETTINGS* cfg = nullptr;
210
211 if( m_board_loaded )
212 {
214 cfg = &localSettings.m_NetInspectorPanel;
215 }
216 else
217 {
219 }
220
221 // Count number of copper layers
223
224 for( PCB_LAYER_ID layer : m_brd->GetEnabledLayers().Seq() )
225 {
226 if( IsCopperLayer( layer ) )
228 }
229
230 // Reset the column display settings if column count doesn't match
231 const int totalNumColumns = add_col.size() + m_num_copper_layers;
232
233 if( (int) cfg->col_order.size() != totalNumColumns
234 || (int) cfg->col_hidden.size() != totalNumColumns )
235 {
236 cfg->col_order.resize( totalNumColumns );
237 cfg->col_hidden.resize( totalNumColumns );
238
239 for( int i = 0; i < totalNumColumns; ++i )
240 {
241 cfg->col_order[i] = i;
242 cfg->col_hidden[i] = false;
243 }
244 }
245
246 // Check that all rows are unique to protect against corrupted settings data
247 std::set<int> col_order_set( cfg->col_order.begin(), cfg->col_order.end() );
248 if( col_order_set.size() != cfg->col_order.size() )
249 {
250 for( std::size_t i = 0; i < cfg->col_order.size(); ++i )
251 cfg->col_order[i] = i;
252 }
253
254 // Add column records for copper layers
255 for( PCB_LAYER_ID layer : m_brd->GetEnabledLayers().Seq() )
256 {
257 if( !IsCopperLayer( layer ) )
258 continue;
259
260 m_columns.emplace_back( m_columns.size(), layer, m_brd->GetLayerName( layer ),
262 }
263
264 // Add display columns in settings order
265 for( std::size_t i = 0; i < cfg->col_order.size(); ++i )
266 {
267 const int addModelColumn = cfg->col_order[i];
268
269 if( addModelColumn >= (int) add_col.size() )
270 {
271 m_netsList->AppendTextColumn( m_brd->GetLayerName( m_columns[addModelColumn].layer ),
272 m_columns[addModelColumn], wxDATAVIEW_CELL_INERT, -1,
273 wxALIGN_CENTER,
274 wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_REORDERABLE
275 | wxDATAVIEW_COL_SORTABLE );
276 }
277 else
278 {
279 add_col.at( cfg->col_order[i] )();
280 }
281 }
282
283 // Set the name column as the expander row
284 if( wxDataViewColumn* col = getDisplayedColumnForModelField( COLUMN_NAME ) )
285 {
286 m_netsList->SetExpanderColumn( col );
287 }
288
290
291 // Delete the temporary config if used
292 if( !m_board_loaded )
293 {
294 delete cfg;
295 }
296}
297
298
300{
301 wxWindowUpdateLocker locker( m_netsList );
302
303 if( cfg->col_widths.size() != m_columns.size() )
304 {
305 int minValueWidth = GetTextExtent( wxT( "00000,000 mm" ) ).x;
306 int minNumberWidth = GetTextExtent( wxT( "000" ) ).x;
307 int minNameWidth = GetTextExtent( wxT( "MMMMMMMMMMMM" ) ).x;
308
309 // Considering left and right margins.
310 // For wxRenderGeneric it is 5px.
311 // Also account for the sorting arrow in the column header.
312 // Column 0 also needs space for any potential expander icons.
313 const int margins = 15;
314 const int extra_width = 30;
315
316 auto getTargetWidth =
317 [&]( int columnID )
318 {
319 switch( columnID )
320 {
321 case COLUMN_NAME: return minNameWidth + extra_width;
322 case COLUMN_NETCLASS: return minNameWidth + margins;
323 case COLUMN_VIA_COUNT: return minNumberWidth + margins;
324 case COLUMN_PAD_COUNT: return minNumberWidth + margins;
325 default: return minValueWidth + margins;
326 }
327 };
328
329 wxASSERT( m_columns.size() == cfg->col_order.size() );
330
331 for( size_t i = 0; i < m_columns.size(); ++i )
332 {
333 const int modelColumn = cfg->col_order[i];
334 int titleSize = GetTextExtent( m_columns[modelColumn].display_name ).x;
335 titleSize = modelColumn == COLUMN_NAME ? titleSize + extra_width : titleSize + margins;
336 const int valSize = getTargetWidth( modelColumn );
337 m_netsList->GetColumn( i )->SetWidth( std::max( titleSize, valSize ) );
338 }
339 }
340 else
341 {
342 wxASSERT( m_columns.size() == cfg->col_hidden.size() );
343 wxASSERT( m_columns.size() == cfg->col_widths.size() );
344
345 for( size_t ii = 0; ii < m_columns.size(); ++ii )
346 {
347 const int newWidth = cfg->col_widths[ii];
348 // Make sure we end up with something non-zero so we can resize it
349 m_netsList->GetColumn( ii )->SetWidth( std::max( newWidth, 10 ) );
350 m_netsList->GetColumn( ii )->SetHidden( cfg->col_hidden[ii] );
351 }
352 }
353
354 m_netsList->Refresh();
355}
356
357
358bool PCB_NET_INSPECTOR_PANEL::restoreSortColumn( int sortingColumnId, bool sortOrderAsc )
359{
360 if( sortingColumnId != -1 )
361 {
362 if( wxDataViewColumn* col = getDisplayedColumnForModelField( sortingColumnId ) )
363 {
364 col->SetSortOrder( sortOrderAsc );
365 m_data_model->Resort();
366 return true;
367 }
368 }
369
370 return false;
371}
372
373
375{
376 for( unsigned int i = 0; i < m_netsList->GetColumnCount(); ++i )
377 {
378 wxDataViewColumn* col = m_netsList->GetColumn( i );
379
380 if( (int) col->GetModelColumn() == columnId )
381 {
382 return col;
383 }
384 }
385
386 return nullptr;
387}
388
389
390/*****************************************************************************************
391 *
392 * Nets list generation
393 *
394 * ***************************************************************************************/
395
396
397void PCB_NET_INSPECTOR_PANEL::buildNetsList( bool rebuildColumns )
398{
399 // Only build the list of nets if there is a board present
400 if( !m_brd )
401 return;
402
404
407
408 // Refresh all filtering / grouping settings
414
415 // when rebuilding the netlist, try to keep the row selection
416 wxDataViewItemArray sel;
417 m_netsList->GetSelections( sel );
418
419 std::vector<int> prev_selected_netcodes;
420 prev_selected_netcodes.reserve( sel.GetCount() );
421
422 for( unsigned int i = 0; i < sel.GetCount(); ++i )
423 {
424 const LIST_ITEM* item = static_cast<const LIST_ITEM*>( sel.Item( i ).GetID() );
425 prev_selected_netcodes.push_back( item->GetNetCode() );
426 }
427
428 int sorting_column_id = cfg->sorting_column;
429 bool sort_order_asc = cfg->sort_order_asc;
430
431 if( wxDataViewColumn* sorting_column = m_netsList->GetSortingColumn() )
432 {
433 if( !m_board_loading )
434 {
435 sorting_column_id = static_cast<int>( sorting_column->GetModelColumn() );
436 sort_order_asc = sorting_column->IsSortOrderAscending();
437 }
438
439 // On GTK, wxDVC will crash if you rebuild with a sorting column set.
440 sorting_column->UnsetAsSortKey();
441 }
442
443 if( rebuildColumns )
444 {
445 m_netsList->ClearColumns();
446 buildColumns();
447 }
448
449 m_data_model->deleteAllItems();
450
451 m_custom_group_rules.clear();
452
453 for( const wxString& rule : cfg->custom_group_rules )
454 m_custom_group_rules.push_back( std::make_unique<EDA_COMBINED_MATCHER>( rule, CTX_NET ) );
455
456 m_data_model->addCustomGroups();
457
458 std::vector<std::unique_ptr<LIST_ITEM>> new_items;
459
460 std::vector<CN_ITEM*> prefiltered_cn_items = relevantConnectivityItems();
461
462 struct NET_INFO
463 {
464 int netcode;
465 NETINFO_ITEM* net;
466 unsigned int pad_count;
467 };
468
469 struct NET_INFO_CMP_LESS
470 {
471 bool operator()( const NET_INFO& a, const NET_INFO& b ) const
472 {
473 return a.netcode < b.netcode;
474 }
475 bool operator()( const NET_INFO& a, int b ) const { return a.netcode < b; }
476 bool operator()( int a, const NET_INFO& b ) const { return a < b.netcode; }
477 };
478
479 std::vector<NET_INFO> nets;
480 nets.reserve( m_brd->GetNetInfo().NetsByNetcode().size() );
481
482 for( const std::pair<int, NETINFO_ITEM*> ni : m_brd->GetNetInfo().NetsByNetcode() )
483 {
484 if( ni.first == 0 )
485 m_zero_netitem = ni.second;
486
487 if( netFilterMatches( ni.second, cfg ) )
488 nets.emplace_back( NET_INFO{ ni.first, ni.second, 0 } );
489 }
490
491 // count the pads for each net. since the nets are sorted by netcode
492 // iterating over the footprints' pads is faster.
493 for( FOOTPRINT* footprint : m_brd->Footprints() )
494 {
495 for( PAD* pad : footprint->Pads() )
496 {
497 auto i = std::lower_bound( nets.begin(), nets.end(), pad->GetNetCode(),
498 NET_INFO_CMP_LESS() );
499
500 if( i != nets.end() && i->netcode == pad->GetNetCode() )
501 i->pad_count += 1;
502 }
503 }
504
505 for( NET_INFO& ni : nets )
506 {
507 if( m_show_zero_pad_nets || ni.pad_count > 0 )
508 new_items.emplace_back( buildNewItem( ni.net, ni.pad_count, prefiltered_cn_items ) );
509 }
510
511 m_data_model->addItems( std::move( new_items ) );
512
513 // Re-enable the sorting column
514 if( !restoreSortColumn( sorting_column_id, sort_order_asc ))
515 {
516 // By default sort by Name column
518 }
519
520 // Try to restore the expanded groups
521 if( m_board_loaded )
522 {
523 m_row_expanding = true;
524
525 std::vector<std::pair<wxString, wxDataViewItem>> groupItems =
526 m_data_model->getGroupDataViewItems();
527
528 for( wxString& groupName : cfg->expanded_rows )
529 {
530 auto pred =
531 [&groupName]( const std::pair<wxString, wxDataViewItem>& item )
532 {
533 return groupName == item.first;
534 };
535
536 auto tableItem = std::find_if( groupItems.begin(), groupItems.end(), pred );
537
538 if( tableItem != groupItems.end() )
539 m_netsList->Expand( tableItem->second );
540 }
541
542 m_row_expanding = false;
543 }
544
545 // try to restore the selected rows. Set the ones that we can't find any more to -1.
546 sel.Clear();
547
548 for( int& nc : prev_selected_netcodes )
549 {
550 std::optional<LIST_ITEM_ITER> r = m_data_model->findItem( nc );
551
552 if( r )
553 {
554 const std::unique_ptr<LIST_ITEM>& list_item = *r.value();
555 sel.Add( wxDataViewItem( list_item.get() ) );
556 }
557 else
558 {
559 nc = -1;
560 }
561 }
562
563 if( !sel.IsEmpty() )
564 {
565 m_netsList->SetSelections( sel );
566 m_netsList->EnsureVisible( sel.Item( 0 ) );
567 }
568 else
569 {
570 m_netsList->UnselectAll();
571 }
572
573 alg::delete_matching( prev_selected_netcodes, -1 );
574
575 m_in_build_nets_list = false;
576}
577
578
581{
582 if( cfg == nullptr )
583 {
585 cfg = &localSettings.m_NetInspectorPanel;
586 }
587
588 // Never show the unconnected net
589 if( aNet->GetNetCode() <= 0 )
590 return false;
591
592 wxString filterString = UnescapeString( m_searchCtrl->GetValue() ).Upper();
593 wxString netName = UnescapeString( aNet->GetNetname() ).Upper();
594 NETCLASS* netClass = aNet->GetNetClass();
595 wxString netClassName = UnescapeString( netClass->GetName() ).Upper();
596
597 bool matched = false;
598
599 // No filter - match all
600 if( filterString.Length() == 0 )
601 matched = true;
602
603 // Search on Netclass
604 if( !matched && cfg->filter_by_netclass && netClassName.Find( filterString ) != wxNOT_FOUND )
605 matched = true;
606
607 // Search on Net name
608 if( !matched && cfg->filter_by_net_name && netName.Find( filterString ) != wxNOT_FOUND )
609 matched = true;
610
611 // Remove unconnected nets if required
612 if( matched )
613 {
615 matched = !netName.StartsWith( wxT( "UNCONNECTED-(" ) );
616 }
617
618 return matched;
619}
620
621
623{
624 bool operator()( const CN_ITEM* a, const CN_ITEM* b ) const { return a->Net() < b->Net(); }
625
626 bool operator()( const CN_ITEM* a, int b ) const { return a->Net() < b; }
627
628 bool operator()( int a, const CN_ITEM* b ) const { return a < b->Net(); }
629};
630
631
632std::unique_ptr<PCB_NET_INSPECTOR_PANEL::LIST_ITEM>
634 const std::vector<CN_ITEM*>& aCNItems )
635{
636 std::unique_ptr<LIST_ITEM> new_item = std::make_unique<LIST_ITEM>( aNet );
637
638 new_item->SetPadCount( aPadCount );
639 new_item->SetLayerCount( m_brd->GetCopperLayerCount() );
640
641 const auto cn_items = std::equal_range( aCNItems.begin(), aCNItems.end(), aNet->GetNetCode(),
643
644 for( auto i = cn_items.first; i != cn_items.second; ++i )
645 {
646 BOARD_CONNECTED_ITEM* item = ( *i )->Parent();
647
648 if( item->Type() == PCB_PAD_T )
649 {
650 new_item->AddPadDieLength( static_cast<PAD*>( item )->GetPadToDieLength() );
651 }
652 else if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
653 {
654 new_item->AddLayerWireLength( track->GetLength(), track->GetLayer() );
655
656 if( item->Type() == PCB_VIA_T )
657 {
658 new_item->AddViaCount( 1 );
659 new_item->AddViaLength( calculateViaLength( track ) );
660 }
661 }
662 }
663
664 return new_item;
665}
666
667
669{
670 // pre-filter the connectivity items and sort them by netcode.
671 // this avoids quadratic runtime when building the whole net list and
672 // calculating the total length for each net.
673 const auto type_bits = std::bitset<MAX_STRUCT_TYPE_ID>()
674 .set( PCB_TRACE_T )
675 .set( PCB_ARC_T )
676 .set( PCB_VIA_T )
677 .set( PCB_PAD_T );
678
679 std::vector<CN_ITEM*> cn_items;
680 cn_items.reserve( 1024 );
681
682 for( CN_ITEM* cn_item : m_brd->GetConnectivity()->GetConnectivityAlgo()->ItemList() )
683 {
684 if( cn_item->Valid() && type_bits[cn_item->Parent()->Type()] )
685 cn_items.push_back( cn_item );
686 }
687
688 std::sort( cn_items.begin(), cn_items.end(), NETCODE_CMP_LESS() );
689
690 return cn_items;
691}
692
693
695{
696 const PCB_VIA* via = dynamic_cast<const PCB_VIA*>( aTrack );
697
698 if( !via )
699 return 0;
700
702
703 // Must be static to keep from raising its ugly head in performance profiles
704 static std::initializer_list<KICAD_T> traceAndPadTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_PAD_T };
705
706 // calculate the via length individually from the board stackup and via's start and end layer.
707 if( bds.m_HasStackup )
708 {
709 PCB_LAYER_ID top_layer = UNDEFINED_LAYER;
710 PCB_LAYER_ID bottom_layer = UNDEFINED_LAYER;
711 LSET layers = bds.GetEnabledLayers();
712
713 for( auto layer_it = layers.copper_layers_begin();
714 layer_it != layers.copper_layers_end();
715 ++layer_it )
716 {
717 if( m_brd->GetConnectivity()->IsConnectedOnLayer( via, *layer_it, traceAndPadTypes ) )
718 {
719 if( top_layer == UNDEFINED_LAYER )
720 top_layer = PCB_LAYER_ID( *layer_it );
721 else
722 bottom_layer = PCB_LAYER_ID( *layer_it );
723 }
724 }
725
726 if( top_layer == UNDEFINED_LAYER )
727 top_layer = via->TopLayer();
728 if( bottom_layer == UNDEFINED_LAYER )
729 bottom_layer = via->BottomLayer();
730
731 const BOARD_STACKUP& stackup = bds.GetStackupDescriptor();
732 return stackup.GetLayerDistance( top_layer, bottom_layer );
733 }
734 else
735 {
736 int dielectricLayers = bds.GetCopperLayerCount() - 1;
737 // TODO: not all dielectric layers are the same thickness!
738 int layerThickness = bds.GetBoardThickness() / dielectricLayers;
739 int effectiveBottomLayer;
740
741 if( via->BottomLayer() == B_Cu )
742 effectiveBottomLayer = F_Cu + dielectricLayers;
743 else
744 effectiveBottomLayer = via->BottomLayer();
745
746 int layerCount = effectiveBottomLayer - via->TopLayer();
747
748 return layerCount * layerThickness;
749 }
750}
751
752
754{
755 // something for the specified net has changed, update that row.
756 // ignore nets that are not in our list because the filter doesn't match.
757 if( !netFilterMatches( aNet ) )
758 {
759 m_data_model->deleteItem( m_data_model->findItem( aNet ) );
760 return;
761 }
762
763 // if the net had no pads before, it might not be in the displayed list yet.
764 // if it had pads and now doesn't anymore, we might need to remove it from the list.
765 std::optional<LIST_ITEM_ITER> cur_net_row = m_data_model->findItem( aNet );
766
767 const unsigned int node_count = m_brd->GetNodesCount( aNet->GetNetCode() );
768
769 if( node_count == 0 && !m_show_zero_pad_nets )
770 {
771 m_data_model->deleteItem( cur_net_row );
772 return;
773 }
774
775 std::unique_ptr<LIST_ITEM> new_list_item = buildNewItem( aNet, node_count,
777
778 if( !cur_net_row )
779 {
780 m_data_model->addItem( std::move( new_list_item ) );
781 return;
782 }
783
784 const std::unique_ptr<LIST_ITEM>& cur_list_item = *cur_net_row.value();
785
786 if( cur_list_item->GetNetName() != new_list_item->GetNetName() )
787 {
788 // if the name has changed, it might require re-grouping.
789 // it's easier to remove and re-insert it
790 m_data_model->deleteItem( cur_net_row );
791 m_data_model->addItem( std::move( new_list_item ) );
792 }
793 else
794 {
795 // update fields only
796 cur_list_item->SetPadCount( new_list_item->GetPadCount() );
797 cur_list_item->SetViaCount( new_list_item->GetViaCount() );
798 cur_list_item->SetLayerWireLength( new_list_item->GetLayerWireLength() );
799 cur_list_item->SetPadDieLength( new_list_item->GetPadDieLength() );
800
801 updateDisplayedRowValues( cur_net_row );
802 }
803}
804
805
806/*****************************************************************************************
807 *
808 * Formatting helpers
809 *
810 * ***************************************************************************************/
811
812
814{
815 return wxString::Format( wxT( "%.3d" ), aNet->GetNetCode() );
816}
817
818
820{
821 return UnescapeString( aNet->GetNetname() );
822}
823
824
825wxString PCB_NET_INSPECTOR_PANEL::formatCount( unsigned int aValue ) const
826{
827 return wxString::Format( wxT( "%u" ), aValue );
828}
829
830
831wxString PCB_NET_INSPECTOR_PANEL::formatLength( int64_t aValue ) const
832{
833 return m_frame->MessageTextFromValue( static_cast<long long int>( aValue ),
834 // don't include unit label in the string when reporting
836}
837
838
839void PCB_NET_INSPECTOR_PANEL::updateDisplayedRowValues( const std::optional<LIST_ITEM_ITER>& aRow )
840{
841 if( !aRow )
842 return;
843
844 wxDataViewItemArray sel;
845 m_netsList->GetSelections( sel );
846
847 m_data_model->updateItem( aRow );
848
849 if( !sel.IsEmpty() )
850 {
851 m_netsList->SetSelections( sel );
852 m_netsList->EnsureVisible( sel.Item( 0 ) );
853 }
854}
855
856
857/*****************************************************************************************
858 *
859 * BOARD_LISTENER event handling
860 *
861 * ***************************************************************************************/
862
863
865{
867
868 if( m_brd != nullptr )
869 m_brd->AddListener( this );
870
871 m_board_loaded = true;
872 m_board_loading = true;
873
875 auto& cfg = localSettings.m_NetInspectorPanel;
876 m_searchCtrl->SetValue( cfg.filter_text );
877
878 buildNetsList( true );
879
880 m_board_loading = false;
881}
882
884{
885 if( !IsShownOnScreen() )
886 return;
887
888 if( NETINFO_ITEM* net = dynamic_cast<NETINFO_ITEM*>( aBoardItem ) )
889 {
890 // a new net has been added to the board. add it to our list if it
891 // passes the netname filter test.
892
893 if( netFilterMatches( net ) )
894 {
895 std::unique_ptr<LIST_ITEM> new_item = std::make_unique<LIST_ITEM>( net );
896
897 // the new net could have some pads already assigned, count them.
898 new_item->SetPadCount( m_brd->GetNodesCount( net->GetNetCode() ) );
899 new_item->SetLayerCount( m_brd->GetCopperLayerCount() );
900
901 m_data_model->addItem( std::move( new_item ) );
902 }
903 }
904 else if( BOARD_CONNECTED_ITEM* i = dynamic_cast<BOARD_CONNECTED_ITEM*>( aBoardItem ) )
905 {
906 std::optional<LIST_ITEM_ITER> r = m_data_model->findItem( i->GetNet() );
907
908 if( r )
909 {
910 // try to handle frequent operations quickly.
911 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( i ) )
912 {
913 const std::unique_ptr<LIST_ITEM>& list_item = *r.value();
914 int len = track->GetLength();
915
916 list_item->AddLayerWireLength( len, track->GetLayer() );
917
918 if( track->Type() == PCB_VIA_T )
919 {
920 list_item->AddViaCount( 1 );
921 list_item->AddViaLength( calculateViaLength( track ) );
922 }
923
925 return;
926 }
927 }
928
929 // resort to generic slower net update otherwise.
930 updateNet( i->GetNet() );
931 }
932 else if( FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( aBoardItem ) )
933 {
934 for( const PAD* pad : footprint->Pads() )
935 {
936 std::optional<LIST_ITEM_ITER> r = m_data_model->findItem( pad->GetNet() );
937
938 if( !r )
939 {
940 // if show-zero-pads is off, we might not have this net
941 // in our list yet, so add it first.
942 // notice that at this point we are very certain that this net
943 // will have at least one pad.
944
945 if( netFilterMatches( pad->GetNet() ) )
946 r = m_data_model->addItem( std::make_unique<LIST_ITEM>( pad->GetNet() ) );
947 }
948
949 if( r )
950 {
951 const std::unique_ptr<LIST_ITEM>& list_item = *r.value();
952 int len = pad->GetPadToDieLength();
953
954 list_item->AddPadCount( 1 );
955 list_item->AddPadDieLength( len );
956 list_item->SetLayerCount( m_brd->GetCopperLayerCount() );
957
958 if( list_item->GetPadCount() == 0 && !m_show_zero_pad_nets )
959 m_data_model->deleteItem( r );
960 else
962 }
963 }
964 }
965}
966
967
969 std::vector<BOARD_ITEM*>& aBoardItems )
970{
971 if( !IsShownOnScreen() )
972 return;
973
974 // Rebuild full netlist for large changes
975 if( aBoardItems.size() > 25 )
976 {
978 m_netsList->Refresh();
979 }
980 else
981 {
982 for( BOARD_ITEM* item : aBoardItems )
983 {
984 OnBoardItemAdded( aBoard, item );
985 }
986 }
987}
988
989
991{
992 if( !IsShownOnScreen() )
993 return;
994
995 if( NETINFO_ITEM* net = dynamic_cast<NETINFO_ITEM*>( aBoardItem ) )
996 {
997 m_data_model->deleteItem( m_data_model->findItem( net ) );
998 }
999 else if( FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( aBoardItem ) )
1000 {
1001 for( const PAD* pad : footprint->Pads() )
1002 {
1003 std::optional<LIST_ITEM_ITER> r = m_data_model->findItem( pad->GetNet() );
1004
1005 if( r )
1006 {
1007 const std::unique_ptr<LIST_ITEM>& list_item = *r.value();
1008 int len = pad->GetPadToDieLength();
1009
1010 list_item->SubPadCount( 1 );
1011 list_item->SubPadDieLength( len );
1012
1013 if( list_item->GetPadCount() == 0 && !m_show_zero_pad_nets )
1014 m_data_model->deleteItem( r );
1015 else
1017 }
1018 }
1019 }
1020 else if( BOARD_CONNECTED_ITEM* i = dynamic_cast<BOARD_CONNECTED_ITEM*>( aBoardItem ) )
1021 {
1022 std::optional<LIST_ITEM_ITER> r = m_data_model->findItem( i->GetNet() );
1023
1024 if( r )
1025 {
1026 // try to handle frequent operations quickly.
1027 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( i ) )
1028 {
1029 const std::unique_ptr<LIST_ITEM>& list_item = *r.value();
1030 int len = track->GetLength();
1031
1032 list_item->SubLayerWireLength( len, track->GetLayer() );
1033
1034 if( track->Type() == PCB_VIA_T )
1035 {
1036 list_item->SubViaCount( 1 );
1037 list_item->SubViaLength( calculateViaLength( track ) );
1038 }
1039
1041 return;
1042 }
1043
1044 // resort to generic slower net update otherwise.
1045 updateNet( i->GetNet() );
1046 }
1047 }
1048}
1049
1050
1052 std::vector<BOARD_ITEM*>& aBoardItems )
1053{
1054 if( !IsShownOnScreen() )
1055 return;
1056
1057 if( aBoardItems.size() > 25 )
1058 {
1059 buildNetsList();
1060 m_netsList->Refresh();
1061 }
1062 else
1063 {
1064 for( BOARD_ITEM* item : aBoardItems )
1065 {
1066 OnBoardItemRemoved( aBoard, item );
1067 }
1068 }
1069}
1070
1071
1073{
1074 if( !IsShownOnScreen() )
1075 return;
1076
1077 buildNetsList();
1078 m_netsList->Refresh();
1079}
1080
1081
1083{
1084 if( !IsShownOnScreen() )
1085 return;
1086
1087 if( dynamic_cast<BOARD_CONNECTED_ITEM*>( aBoardItem ) != nullptr
1088 || dynamic_cast<FOOTPRINT*>( aBoardItem ) != nullptr )
1089 {
1090 buildNetsList();
1091 m_netsList->Refresh();
1092 }
1093}
1094
1095
1097 std::vector<BOARD_ITEM*>& aBoardItems )
1098{
1099 if( !IsShownOnScreen() )
1100 return;
1101
1102 buildNetsList();
1103 m_netsList->Refresh();
1104}
1105
1106
1108 std::vector<BOARD_ITEM*>& aAddedItems,
1109 std::vector<BOARD_ITEM*>& aRemovedItems,
1110 std::vector<BOARD_ITEM*>& aDeletedItems )
1111{
1112 if( !IsShownOnScreen() )
1113 return;
1114
1115 buildNetsList();
1116 m_netsList->Refresh();
1117}
1118
1119
1121{
1122 if( m_highlighting_nets || !IsShownOnScreen() )
1123 return;
1124
1125 if( !m_brd->IsHighLightNetON() )
1126 {
1127 m_netsList->UnselectAll();
1128 }
1129 else
1130 {
1131 const std::set<int>& selected_codes = m_brd->GetHighLightNetCodes();
1132
1133 wxDataViewItemArray new_selection;
1134 new_selection.Alloc( selected_codes.size() );
1135
1136 for( int code : selected_codes )
1137 {
1138 if( std::optional<LIST_ITEM_ITER> r = m_data_model->findItem( code ) )
1139 new_selection.Add( wxDataViewItem( &***r ) );
1140 }
1141
1142 m_netsList->SetSelections( new_selection );
1143
1144 if( !new_selection.IsEmpty() )
1145 m_netsList->EnsureVisible( new_selection.Item( 0 ) );
1146 }
1147}
1148
1149
1150/*****************************************************************************************
1151 *
1152 * UI-generated event handling
1153 *
1154 * ***************************************************************************************/
1155
1157{
1158 buildNetsList();
1160}
1161
1162
1164{
1165 bool multipleSelections = false;
1166 const LIST_ITEM* selItem = nullptr;
1167
1168 if( m_netsList->GetSelectedItemsCount() == 1 )
1169 {
1170 selItem = static_cast<const LIST_ITEM*>( m_netsList->GetSelection().GetID() );
1171 }
1172 else
1173 {
1174 if( m_netsList->GetSelectedItemsCount() > 1 )
1175 multipleSelections = true;
1176 }
1177
1178 wxMenu menu;
1179
1180 // Net edit menu items
1181 wxMenuItem* highlightNet = new wxMenuItem( &menu, ID_HIGHLIGHT_SELECTED_NETS,
1182 _( "Highlight Selected Net" ),
1183 wxEmptyString, wxITEM_NORMAL );
1184 menu.Append( highlightNet );
1185
1186 wxMenuItem* clearHighlighting = new wxMenuItem( &menu, ID_CLEAR_HIGHLIGHTING,
1187 _( "Clear Net Highlighting" ),
1188 wxEmptyString, wxITEM_NORMAL );
1189 menu.Append( clearHighlighting );
1190
1191 RENDER_SETTINGS* renderSettings = m_frame->GetCanvas()->GetView()->GetPainter()->GetSettings();
1192 const std::set<int>& selected_codes = renderSettings->GetHighlightNetCodes();
1193
1194 if( selected_codes.size() == 0 )
1195 clearHighlighting->Enable( false );
1196
1197 menu.AppendSeparator();
1198
1199 wxMenuItem* renameNet = new wxMenuItem( &menu, ID_RENAME_NET, _( "Rename Selected Net" ),
1200 wxEmptyString, wxITEM_NORMAL );
1201 menu.Append( renameNet );
1202
1203 wxMenuItem* deleteNet = new wxMenuItem( &menu, ID_DELETE_NET, _( "Delete Selected Net" ),
1204 wxEmptyString, wxITEM_NORMAL );
1205 menu.Append( deleteNet );
1206
1207 menu.AppendSeparator();
1208
1209 wxMenuItem* addNet = new wxMenuItem( &menu, ID_ADD_NET, _( "Add Net" ),
1210 wxEmptyString, wxITEM_NORMAL );
1211 menu.Append( addNet );
1212
1213 if( !selItem && !multipleSelections )
1214 {
1215 highlightNet->Enable( false );
1216 deleteNet->Enable( false );
1217 renameNet->Enable( false );
1218 }
1219 else
1220 {
1221 if( multipleSelections || selItem->GetIsGroup() )
1222 {
1223 highlightNet->SetItemLabel( _( "Highlight Selected Nets" ) );
1224 renameNet->Enable( false );
1225 deleteNet->SetItemLabel( _( "Delete Selected Nets" ) );
1226 }
1227 }
1228
1229 menu.AppendSeparator();
1230
1231 wxMenuItem* removeSelectedGroup = new wxMenuItem( &menu, ID_REMOVE_SELECTED_GROUP,
1232 _( "Remove Selected Custom Group" ),
1233 wxEmptyString, wxITEM_NORMAL );
1234 menu.Append( removeSelectedGroup );
1235
1236 if( !selItem || !selItem->GetIsGroup() )
1237 removeSelectedGroup->Enable( false );
1238
1239 menu.Bind( wxEVT_COMMAND_MENU_SELECTED, &PCB_NET_INSPECTOR_PANEL::onSettingsMenu, this );
1240
1241 PopupMenu( &menu );
1242}
1243
1244
1246{
1247 SaveSettings();
1248 buildNetsList();
1249}
1250
1251
1253{
1254 wxString newGroupName;
1255 NETNAME_VALIDATOR validator( &newGroupName );
1256
1257 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Group name / pattern:" ), _( "New Group" ), newGroupName );
1258 wxStaticText* help = new wxStaticText( &dlg, wxID_ANY,
1259 _( "(Use /.../ to indicate a regular expression.)" ) );
1260 help->SetFont( KIUI::GetInfoFont( this ).Italic() );
1261 dlg.m_ContentSizer->Add( help, 0, wxALL|wxEXPAND, 5 );
1262 dlg.SetTextValidator( validator );
1263 dlg.GetSizer()->SetSizeHints( &dlg );
1264
1265 if( dlg.ShowModal() != wxID_OK || dlg.GetValue().IsEmpty() )
1266 return; //Aborted by user
1267
1268 newGroupName = UnescapeString( dlg.GetValue() );
1269
1270 if( newGroupName == "" )
1271 return;
1272
1273 if( std::find_if( m_custom_group_rules.begin(), m_custom_group_rules.end(),
1274 [&]( std::unique_ptr<EDA_COMBINED_MATCHER>& rule )
1275 {
1276 return rule->GetPattern().Upper() == newGroupName.Upper();
1277 } ) == m_custom_group_rules.end() )
1278 {
1279 m_custom_group_rules.push_back( std::make_unique<EDA_COMBINED_MATCHER>( newGroupName,
1280 CTX_NET ) );
1281 SaveSettings();
1282 }
1283
1284 buildNetsList();
1285}
1286
1287
1289{
1290 m_highlighting_nets = true;
1291
1295
1296 m_highlighting_nets = false;
1297}
1298
1299
1301{
1302 if( !m_row_expanding )
1303 SaveSettings();
1304}
1305
1306
1308{
1309 wxMenu menu;
1311 menu.Bind( wxEVT_COMMAND_MENU_SELECTED, &PCB_NET_INSPECTOR_PANEL::onSettingsMenu, this );
1312 PopupMenu( &menu );
1313}
1314
1315
1316void PCB_NET_INSPECTOR_PANEL::OnConfigButton( wxCommandEvent& event )
1317{
1319 auto& cfg = localSettings.m_NetInspectorPanel;
1320
1321 const LIST_ITEM* selItem = nullptr;
1322
1323 if( m_netsList->GetSelectedItemsCount() == 1 )
1324 {
1325 selItem = static_cast<const LIST_ITEM*>( m_netsList->GetSelection().GetID() );
1326 }
1327
1328 wxMenu menu;
1329
1330 // Filtering menu items
1331 wxMenuItem* filterByNetName = new wxMenuItem( &menu, ID_FILTER_BY_NET_NAME,
1332 _( "Filter by Net Name" ),
1333 wxEmptyString, wxITEM_CHECK );
1334 menu.Append( filterByNetName );
1335 filterByNetName->Check( cfg.filter_by_net_name );
1336
1337 wxMenuItem* filterByNetclass = new wxMenuItem( &menu, ID_FILTER_BY_NETCLASS,
1338 _( "Filter by Netclass" ),
1339 wxEmptyString, wxITEM_CHECK );
1340 menu.Append( filterByNetclass );
1341 filterByNetclass->Check( cfg.filter_by_netclass );
1342
1343 menu.AppendSeparator();
1344
1345 // Grouping menu items
1346 //wxMenuItem* groupConstraint =
1347 // new wxMenuItem( &menu, ID_GROUP_BY_CONSTRAINT, _( "Group by DRC Constraint" ),
1348 // wxEmptyString, wxITEM_CHECK );
1349 //groupConstraint->Check( m_group_by_constraint );
1350 //menu.Append( groupConstraint );
1351
1352 wxMenuItem* groupNetclass = new wxMenuItem( &menu, ID_GROUP_BY_NETCLASS,
1353 _( "Group by Netclass" ),
1354 wxEmptyString, wxITEM_CHECK );
1355 menu.Append( groupNetclass );
1356 groupNetclass->Check( m_group_by_netclass );
1357
1358 menu.AppendSeparator();
1359
1360 wxMenuItem* addGroup = new wxMenuItem( &menu, ID_ADD_GROUP, _( "Add Custom Group" ),
1361 wxEmptyString, wxITEM_NORMAL );
1362 menu.Append( addGroup );
1363
1364 wxMenuItem* removeSelectedGroup = new wxMenuItem( &menu, ID_REMOVE_SELECTED_GROUP,
1365 _( "Remove Selected Custom Group" ),
1366 wxEmptyString, wxITEM_NORMAL );
1367 menu.Append( removeSelectedGroup );
1368
1369 if( !selItem || !selItem->GetIsGroup() )
1370 removeSelectedGroup->Enable( false );
1371
1372 wxMenuItem* removeCustomGroups = new wxMenuItem( &menu, ID_REMOVE_GROUPS,
1373 _( "Remove All Custom Groups" ),
1374 wxEmptyString, wxITEM_NORMAL );
1375 menu.Append( removeCustomGroups );
1376 removeCustomGroups->Enable( m_custom_group_rules.size() != 0 );
1377
1378 menu.AppendSeparator();
1379
1380 wxMenuItem* showZeroNetPads = new wxMenuItem( &menu, ID_SHOW_ZERO_NET_PADS,
1381 _( "Show Zero Pad Nets" ),
1382 wxEmptyString, wxITEM_CHECK );
1383 menu.Append( showZeroNetPads );
1384 showZeroNetPads->Check( m_show_zero_pad_nets );
1385
1386 wxMenuItem* showUnconnectedNets = new wxMenuItem( &menu, ID_SHOW_UNCONNECTED_NETS,
1387 _( "Show Unconnected Nets" ),
1388 wxEmptyString, wxITEM_CHECK );
1389 menu.Append( showUnconnectedNets );
1390 showUnconnectedNets->Check( m_show_unconnected_nets );
1391
1392 menu.AppendSeparator();
1393
1394 // Report generation
1395 wxMenuItem* generateReport = new wxMenuItem( &menu, ID_GENERATE_REPORT,
1396 _( "Save Net Inspector Report" ),
1397 wxEmptyString, wxITEM_NORMAL );
1398 menu.Append( generateReport );
1399
1400 menu.AppendSeparator();
1401
1402 // Show / hide columns menu items
1403 wxMenu* colsMenu = new wxMenu();
1404 generateShowHideColumnMenu( colsMenu );
1405 menu.AppendSubMenu( colsMenu, _( "Show / Hide Columns" ) );
1406
1407 menu.Bind( wxEVT_COMMAND_MENU_SELECTED, &PCB_NET_INSPECTOR_PANEL::onSettingsMenu, this );
1408
1409 PopupMenu( &menu );
1410}
1411
1412
1414{
1415 for( int i = 1; i <= COLUMN_LAST_STATIC_COL; ++i )
1416 {
1417 wxMenuItem* opt = new wxMenuItem( target, ID_HIDE_COLUMN + i, m_columns[i].display_name,
1418 wxEmptyString, wxITEM_CHECK );
1419 wxDataViewColumn* col = getDisplayedColumnForModelField( i );
1420 target->Append( opt );
1421 opt->Check( !col->IsHidden() );
1422 }
1423
1424 target->AppendSeparator();
1425
1426 for( std::size_t i = COLUMN_LAST_STATIC_COL + 1; i < m_columns.size(); ++i )
1427 {
1428 wxMenuItem* opt = new wxMenuItem( target, ID_HIDE_COLUMN + i, m_columns[i].display_name,
1429 wxEmptyString, wxITEM_CHECK );
1430 wxDataViewColumn* col = getDisplayedColumnForModelField( i );
1431 target->Append( opt );
1432 opt->Check( !col->IsHidden() );
1433 }
1434}
1435
1436
1437void PCB_NET_INSPECTOR_PANEL::onSettingsMenu( wxCommandEvent& event )
1438{
1439 bool saveAndRebuild = true;
1440
1441 switch( event.GetId() )
1442 {
1443 case ID_ADD_NET:
1444 onAddNet();
1445 break;
1446
1447 case ID_RENAME_NET:
1449 break;
1450
1451 case ID_DELETE_NET:
1453 break;
1454
1455 case ID_ADD_GROUP:
1456 onAddGroup();
1457 break;
1458
1461 break;
1462
1465 break;
1466
1469 break;
1470
1473 break;
1474
1477 break;
1478
1479 case ID_REMOVE_GROUPS:
1480 m_custom_group_rules.clear();
1481 break;
1482
1485 break;
1486
1489 break;
1490
1491 case ID_GENERATE_REPORT:
1493 saveAndRebuild = false;
1494 break;
1495
1498 saveAndRebuild = false;
1499 break;
1500
1503 saveAndRebuild = false;
1504 break;
1505
1506 default:
1507 if( event.GetId() >= ID_HIDE_COLUMN )
1508 {
1509 const int columnId = event.GetId() - ID_HIDE_COLUMN;
1510 wxDataViewColumn* col = getDisplayedColumnForModelField( columnId );
1511 // Make sure we end up with something non-zero so we can resize it
1512 col->SetWidth( std::max( col->GetWidth(), 10 ) );
1513 col->SetHidden( !col->IsHidden() );
1514 }
1515 break;
1516 }
1517
1518 if( saveAndRebuild )
1519 {
1520 SaveSettings();
1521 buildNetsList();
1522 }
1523}
1524
1525
1527{
1528 if( m_netsList->GetSelectedItemsCount() == 1 )
1529 {
1530 auto* selItem = static_cast<const LIST_ITEM*>( m_netsList->GetSelection().GetID() );
1531
1532 if( selItem->GetIsGroup() )
1533 {
1534 wxString groupName = selItem->GetGroupName();
1535 auto groupIter = std::find_if( m_custom_group_rules.begin(), m_custom_group_rules.end(),
1536 [&]( std::unique_ptr<EDA_COMBINED_MATCHER>& rule )
1537 {
1538 return rule->GetPattern() == groupName;
1539 } );
1540
1541 if( groupIter != m_custom_group_rules.end() )
1542 {
1543 m_custom_group_rules.erase( groupIter );
1544 SaveSettings();
1545 buildNetsList();
1546 }
1547 }
1548 }
1549}
1550
1551
1553{
1554 wxFileDialog dlg( this, _( "Save Net Inspector Report File" ), "", "",
1555 _( "Report file" ) + AddFileExtListToFilter( { "csv" } ),
1556 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1557
1558 if( dlg.ShowModal() == wxID_CANCEL )
1559 return;
1560
1561 wxTextFile f( dlg.GetPath() );
1562
1563 f.Create();
1564
1565 wxString txt;
1566
1567 m_in_reporting = true;
1568
1569 // Print Header:
1570 for( auto&& col : m_columns )
1571 {
1572 txt += '"';
1573
1574 if( col.has_units )
1575 {
1576 txt += wxString::Format( _( "%s (%s)" ),
1577 col.csv_name,
1579 }
1580 else
1581 {
1582 txt += col.csv_name;
1583 }
1584
1585 txt += wxT( "\";" );
1586 }
1587
1588 f.AddLine( txt );
1589
1590 // Print list of nets:
1591 const unsigned int num_rows = m_data_model->itemCount();
1592
1593 for( unsigned int row = 0; row < num_rows; row++ )
1594 {
1595 auto& i = m_data_model->itemAt( row );
1596
1597 if( i.GetIsGroup() || i.GetNetCode() == 0 )
1598 continue;
1599
1600 txt = "";
1601
1602 for( auto&& col : m_columns )
1603 {
1604 if( static_cast<int>( col.csv_flags ) & static_cast<int>( CSV_COLUMN_DESC::CSV_QUOTE ) )
1605 txt += '"' + m_data_model->valueAt( col.num, row ).GetString() + wxT( "\";" );
1606 else
1607 txt += m_data_model->valueAt( col.num, row ).GetString() + ';';
1608 }
1609
1610 f.AddLine( txt );
1611 }
1612
1613 m_in_reporting = false;
1614
1615 f.Write();
1616 f.Close();
1617}
1618
1619
1621{
1623}
1624
1625
1627{
1628 // ignore selection changes while the whole list is being rebuilt.
1630 return;
1631
1632 m_highlighting_nets = true;
1633
1634 RENDER_SETTINGS* renderSettings = m_frame->GetCanvas()->GetView()->GetPainter()->GetSettings();
1635
1636 if( m_netsList->HasSelection() )
1637 {
1638 wxDataViewItemArray sel;
1639 m_netsList->GetSelections( sel );
1640
1641 renderSettings->SetHighlight( false );
1642
1643 for( unsigned int i = 0; i < sel.GetCount(); ++i )
1644 {
1645 const LIST_ITEM* ii = static_cast<const LIST_ITEM*>( sel.Item( i ).GetID() );
1646
1647 if( ii->GetIsGroup() )
1648 {
1649 for( auto c = ii->ChildrenBegin(), end = ii->ChildrenEnd(); c != end; ++c )
1650 renderSettings->SetHighlight( true, ( *c )->GetNetCode(), true );
1651 }
1652 else
1653 {
1654 renderSettings->SetHighlight( true, ii->GetNetCode(), true );
1655 }
1656 }
1657 }
1658 else
1659 {
1660 renderSettings->SetHighlight( false );
1661 }
1662
1665
1666 m_highlighting_nets = false;
1667}
1668
1669
1670void PCB_NET_INSPECTOR_PANEL::OnColumnSorted( wxDataViewEvent& event )
1671{
1672 SaveSettings();
1673}
1674
1675
1677{
1678 // Rebuilt the nets list, and force rebuild of columns in case the stackup has chanaged
1679 buildNetsList( true );
1680 m_netsList->Refresh();
1681}
1682
1683
1685{
1686 wxString newNetName;
1687 NETNAME_VALIDATOR validator( &newNetName );
1688
1689 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Net name:" ), _( "New Net" ), newNetName );
1690 dlg.SetTextValidator( validator );
1691
1692 while( true )
1693 {
1694 if( dlg.ShowModal() != wxID_OK || dlg.GetValue().IsEmpty() )
1695 return; //Aborted by user
1696
1697 newNetName = dlg.GetValue();
1698
1699 if( m_brd->FindNet( newNetName ) )
1700 {
1701 DisplayError( this,
1702 wxString::Format( _( "Net name '%s' is already in use." ), newNetName ) );
1703 newNetName = wxEmptyString;
1704 }
1705 else
1706 {
1707 break;
1708 }
1709 }
1710
1711 NETINFO_ITEM* newnet = new NETINFO_ITEM( m_brd, dlg.GetValue(), 0 );
1712
1713 m_brd->Add( newnet );
1714
1715 // We'll get an OnBoardItemAdded callback from this to update our listbox
1716 m_frame->OnModify();
1717}
1718
1719
1721{
1722 if( m_netsList->GetSelectedItemsCount() == 1 )
1723 {
1724 const LIST_ITEM* sel = static_cast<const LIST_ITEM*>( m_netsList->GetSelection().GetID() );
1725
1726 if( sel->GetIsGroup() )
1727 return;
1728
1729 NETINFO_ITEM* net = sel->GetNet();
1730 wxString fullNetName = net->GetNetname();
1731 wxString netPath;
1732 wxString shortNetName;
1733
1734 if( fullNetName.Contains( wxT( "/" ) ) )
1735 {
1736 netPath = fullNetName.BeforeLast( '/' ) + '/';
1737 shortNetName = fullNetName.AfterLast( '/' );
1738 }
1739 else
1740 {
1741 shortNetName = fullNetName;
1742 }
1743
1744 wxString unescapedShortName = UnescapeString( shortNetName );
1745
1746 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Net name:" ), _( "Rename Net" ), unescapedShortName );
1747 NETNAME_VALIDATOR validator( &unescapedShortName );
1748 dlg.SetTextValidator( validator );
1749
1750 while( true )
1751 {
1752 if( dlg.ShowModal() != wxID_OK || dlg.GetValue() == unescapedShortName )
1753 return;
1754
1755 unescapedShortName = dlg.GetValue();
1756
1757 if( unescapedShortName.IsEmpty() )
1758 {
1759 DisplayError( this, wxString::Format( _( "Net name cannot be empty." ),
1760 unescapedShortName ) );
1761 continue;
1762 }
1763
1764 shortNetName = EscapeString( unescapedShortName, CTX_NETNAME );
1765 fullNetName = netPath + shortNetName;
1766
1767 if( m_brd->FindNet( shortNetName ) || m_brd->FindNet( fullNetName ) )
1768 {
1769 DisplayError( this, wxString::Format( _( "Net name '%s' is already in use." ),
1770 unescapedShortName ) );
1771 unescapedShortName = wxEmptyString;
1772 }
1773 else
1774 {
1775 break;
1776 }
1777 }
1778
1779 for( BOARD_CONNECTED_ITEM* boardItem : m_frame->GetBoard()->AllConnectedItems() )
1780 {
1781 if( boardItem->GetNet() == net )
1782 boardItem->SetFlags( CANDIDATE );
1783 else
1784 boardItem->ClearFlags( CANDIDATE );
1785 }
1786
1787 // the changed name might require re-grouping. remove/re-insert is easier.
1788 auto removed_item = m_data_model->deleteItem( m_data_model->findItem( net ) );
1789
1790 m_brd->Remove( net );
1791 net->SetNetname( fullNetName );
1792 m_brd->Add( net );
1793
1794 for( BOARD_CONNECTED_ITEM* boardItem : m_frame->GetBoard()->AllConnectedItems() )
1795 {
1796 if( boardItem->GetFlags() & CANDIDATE )
1797 boardItem->SetNet( net );
1798 }
1799
1800 buildNetsList();
1801
1802 if( std::optional<LIST_ITEM_ITER> r = m_data_model->findItem( net ) )
1803 m_netsList->Select( wxDataViewItem( r.value()->get() ) );
1804
1805 m_frame->OnModify();
1806
1807 // Currently only tracks and pads have netname annotations and need to be redrawn,
1808 // but zones are likely to follow. Since we don't have a way to ask what is current,
1809 // just refresh all items.
1812 }
1813}
1814
1815
1817{
1818 if( !m_netsList->HasSelection() )
1819 return;
1820
1821 wxDataViewItemArray sel;
1822 m_netsList->GetSelections( sel );
1823
1824 auto delete_one = [this]( const LIST_ITEM* i )
1825 {
1826 if( i->GetPadCount() == 0
1827 || IsOK( this, wxString::Format( _( "Net '%s' is in use. Delete anyway?" ),
1828 i->GetNetName() ) ) )
1829 {
1830 // This is a bit hacky, but it will do for now, since this is the only path
1831 // outside the netlist updater where you can remove a net from a BOARD.
1832 int removedCode = i->GetNetCode();
1833
1835 [removedCode]( KIGFX::VIEW_ITEM* aItem ) -> int
1836 {
1837 auto boardItem = dynamic_cast<BOARD_CONNECTED_ITEM*>( aItem );
1838
1839 if( boardItem && boardItem->GetNetCode() == removedCode )
1840 return KIGFX::REPAINT;
1841
1842 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem );
1843
1844 if( text && text->HasTextVars() )
1845 {
1846 text->ClearRenderCache();
1847 text->ClearBoundingBoxCache();
1849 }
1850
1851 return 0;
1852 } );
1853
1854 m_brd->Remove( i->GetNet() );
1855 m_frame->OnModify();
1856
1857 // We'll get an OnBoardItemRemoved callback from this to update our listbox
1858 }
1859 };
1860
1861 for( unsigned int i = 0; i < sel.GetCount(); ++i )
1862 {
1863 const LIST_ITEM* ii = static_cast<const LIST_ITEM*>( sel.Item( i ).GetID() );
1864
1865 if( ii->GetIsGroup() )
1866 {
1867 if( ii->ChildrenCount() != 0
1868 && IsOK( this, wxString::Format( _( "Delete all nets in group '%s'?" ),
1869 ii->GetGroupName() ) ) )
1870 {
1871 // we can't be iterating the children container and deleting items from
1872 // it at the same time. thus take a copy of it first.
1873 std::vector<const LIST_ITEM*> children;
1874 children.reserve( ii->ChildrenCount() );
1875 std::copy( ii->ChildrenBegin(), ii->ChildrenEnd(), std::back_inserter( children ) );
1876
1877 for( const LIST_ITEM* c : children )
1878 delete_one( c );
1879 }
1880 }
1881 else
1882 {
1883 delete_one( ii );
1884 }
1885 }
1886}
1887
1888/*****************************************************************************************
1889 *
1890 * Application-generated event handling
1891 *
1892 * ***************************************************************************************/
1893
1894
1896{
1897 SaveSettings();
1898 buildNetsList( true );
1899 m_data_model->updateAllItems();
1900}
1901
1902
1903void PCB_NET_INSPECTOR_PANEL::onUnitsChanged( wxCommandEvent& event )
1904{
1905 m_data_model->updateAllItems();
1906 event.Skip();
1907}
1908
1909
1910/*****************************************************************************************
1911 *
1912 * Settings persistence
1913 *
1914 * ***************************************************************************************/
1915
1916
1918{
1919 // Don't save settings if a board has not yet been loaded - events fire while we set up the
1920 // panel which overwrites the settings we haven't yet loaded
1922 return;
1923
1925 auto& cfg = localSettings.m_NetInspectorPanel;
1926
1927 // User-defined filters / grouping
1928 cfg.filter_text = m_searchCtrl->GetValue();
1929 cfg.filter_by_net_name = m_filter_by_net_name;
1930 cfg.filter_by_netclass = m_filter_by_netclass;
1931 cfg.group_by_netclass = m_group_by_netclass;
1932 cfg.group_by_constraint = m_group_by_constraint;
1933 cfg.show_zero_pad_nets = m_show_zero_pad_nets;
1934 cfg.show_unconnected_nets = m_show_unconnected_nets;
1935
1936 // Grid sorting
1937 wxDataViewColumn* sortingCol = m_netsList->GetSortingColumn();
1938 cfg.sorting_column = sortingCol ? static_cast<int>( sortingCol->GetModelColumn() ) : -1;
1939 cfg.sort_order_asc = sortingCol ? sortingCol->IsSortOrderAscending() : true;
1940
1941 // Column arrangement / sizes
1942 cfg.col_order.resize( m_data_model->columnCount() );
1943 cfg.col_widths.resize( m_data_model->columnCount() );
1944 cfg.col_hidden.resize( m_data_model->columnCount() );
1945
1946 for( unsigned int ii = 0; ii < m_data_model->columnCount(); ++ii )
1947 {
1948 cfg.col_order[ii] = (int) m_netsList->GetColumn( ii )->GetModelColumn();
1949 cfg.col_widths[ii] = m_netsList->GetColumn( ii )->GetWidth();
1950 cfg.col_hidden[ii] = m_netsList->GetColumn( ii )->IsHidden();
1951 }
1952
1953 // Expanded rows
1954 cfg.expanded_rows.clear();
1955 std::vector<std::pair<wxString, wxDataViewItem>> groupItems =
1956 m_data_model->getGroupDataViewItems();
1957
1958 for( std::pair<wxString, wxDataViewItem>& item : groupItems )
1959 {
1960 if( m_netsList->IsExpanded( item.second ) )
1961 cfg.expanded_rows.push_back( item.first );
1962 }
1963
1964 // Customer group rules
1965 cfg.custom_group_rules.clear();
1966
1967 for( const std::unique_ptr<EDA_COMBINED_MATCHER>& rule : m_custom_group_rules )
1968 cfg.custom_group_rules.push_back( rule->GetPattern() );
1969}
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
Container for design settings for a BOARD object.
LSET GetEnabledLayers() const
Return a bit-mask of all the layers that are enabled.
int GetBoardThickness() const
The full thickness of the board including copper and masks.
BOARD_STACKUP & GetStackupDescriptor()
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
Manage layers needed to make a physical board.
int GetLayerDistance(PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer) const
Calculate the distance (height) between the two given copper layers.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:295
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:879
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:817
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: board.cpp:1042
const std::set< int > & GetHighLightNetCodes() const
Definition: board.h:540
const std::vector< BOARD_CONNECTED_ITEM * > AllConnectedItems()
Definition: board.cpp:2661
void AddListener(BOARD_LISTENER *aListener)
Add a listener to the board to receive calls whenever something on the board has been modified.
Definition: board.cpp:2716
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1961
int GetCopperLayerCount() const
Definition: board.cpp:780
const FOOTPRINTS & Footprints() const
Definition: board.h:336
unsigned GetNodesCount(int aNet=-1) const
Definition: board.cpp:1696
bool IsHighLightNetON() const
Definition: board.h:556
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:613
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:934
void RemoveListener(BOARD_LISTENER *aListener)
Remove the specified listener.
Definition: board.cpp:2723
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: board.cpp:1176
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:483
CN_ITEM represents a BOARD_CONNETED_ITEM in the connectivity system (ie: a pad, track/arc/via,...
int Net() const
int ShowModal() override
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const std::set< int > & GetHighlightNetCodes() const
Return the netcode of currently highlighted net.
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aMulti=false)
Turns on/off highlighting.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:86
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition: view.cpp:765
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition: view.cpp:1549
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:216
void UpdateAllItemsConditionally(int aUpdateFlags, std::function< bool(VIEW_ITEM *)> aCondition)
Update items in the view according to the given flags and condition.
Definition: view.cpp:1559
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
copper_layers_iterator copper_layers_end() const
Definition: lset.cpp:867
copper_layers_iterator copper_layers_begin() const
Definition: lset.cpp:861
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:295
A collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:45
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
Definition: netclass.cpp:314
Handle the data for a net.
Definition: netinfo.h:56
void SetNetname(const wxString &aNewName)
Set the long netname to aNetName, the short netname to the last token in the long netname's path,...
Definition: netinfo.h:139
const wxString & GetNetname() const
Definition: netinfo.h:114
NETCLASS * GetNetClass()
Definition: netinfo.h:101
int GetNetCode() const
Definition: netinfo.h:108
const NETCODES_MAP & NetsByNetcode() const
Return the netcode map, at least for python.
Definition: netinfo.h:375
A base class used to implement docking net inspector panels.
wxDataViewCtrl * m_netsList
wxSearchCtrl * m_searchCtrl
Definition: pad.h:54
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
BOARD * GetBoard() const
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
The main frame for Pcbnew.
void OnModify() override
Must be called after a board change to set the modified flag.
Data model for display in the Net Inspector panel.
Primary data item for entries in the Net Inspector list.
virtual void OnBoardItemRemoved(BOARD &aBoard, BOARD_ITEM *aBoardItem) override
virtual void OnBoardHighlightNetChanged(BOARD &aBoard) override
void generateReport()
Generates a CSV report from currently disaplyed data.
wxString formatCount(unsigned int aValue) const
PCB_NET_INSPECTOR_PANEL(wxWindow *parent, PCB_EDIT_FRAME *aFrame)
virtual void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems) override
virtual void OnSearchTextChanged(wxCommandEvent &event) override
virtual void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems) override
virtual void OnBoardChanged() override
Update panel when board is changed.
void generateShowHideColumnMenu(wxMenu *target)
Generates a sub-menu for the show / hide columns submenu.
wxString formatNetCode(const NETINFO_ITEM *aNet) const
std::unique_ptr< LIST_ITEM > buildNewItem(NETINFO_ITEM *aNet, unsigned int aPadCount, const std::vector< CN_ITEM * > &aCNItems)
Constructs a LIST_ITEM for storage in the data model from a board net item.
std::vector< std::unique_ptr< EDA_COMBINED_MATCHER > > m_custom_group_rules
wxString formatNetName(const NETINFO_ITEM *aNet) const
void onSettingsMenu(wxCommandEvent &event)
std::vector< CN_ITEM * > relevantConnectivityItems() const
Filters connectivity items from a board update to remove those not related to net / track metrics.
unsigned int calculateViaLength(const PCB_TRACK *) const
Calculates the length of a via from the board stackup.
void highlightSelectedNets()
Highlight the currently selected net.
virtual void OnBoardCompositeUpdate(BOARD &aBoard, std::vector< BOARD_ITEM * > &aAddedItems, std::vector< BOARD_ITEM * > &aRemovedItems, std::vector< BOARD_ITEM * > &aDeletedItems) override
virtual void OnBoardItemsAdded(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems) override
wxObjectDataPtr< DATA_MODEL > m_data_model
void updateNet(NETINFO_ITEM *aNet)
Updates the stored LIST_ITEMs for a given updated board net item.
virtual void OnLanguageChangedImpl() override
Reloads strings on an application language change.
void OnNetsListContextMenu(wxDataViewEvent &event)
virtual void OnBoardNetSettingsChanged(BOARD &aBoard) override
void OnNetsListItemActivated(wxDataViewEvent &event)
void OnColumnSorted(wxDataViewEvent &event)
void updateDisplayedRowValues(const std::optional< LIST_ITEM_ITER > &aRow)
virtual void OnBoardItemAdded(BOARD &aBoard, BOARD_ITEM *aBoardItem) override
virtual void OnParentSetupChanged() override
Updates the netlist based on global board changes (e.g.
void OnHeaderContextMenu(wxCommandEvent &event)
bool netFilterMatches(NETINFO_ITEM *aNet, PANEL_NET_INSPECTOR_SETTINGS *cfg=nullptr) const
Filter to determine whether a board net should be included in the net inspector.
virtual void OnConfigButton(wxCommandEvent &event) override
void buildNetsList(bool rebuildColumns=false)
bool restoreSortColumn(int sortingColumnId, bool sortOrderAsc)
Sets the sort column in the grid to that showing the given model ID column.
wxString formatLength(int64_t aValue) const
virtual void SaveSettings() override
Persist the net inspector configuration to project / global settings.
void onUnitsChanged(wxCommandEvent &event)
void OnExpandCollapseRow(wxCommandEvent &event)
wxDataViewColumn * getDisplayedColumnForModelField(int columnId)
Fetches the displayed grid view column for the given model column ID.
void adjustListColumnSizes(PANEL_NET_INSPECTOR_SETTINGS *cfg)
Adjust the sizing of list columns.
virtual void OnBoardItemChanged(BOARD &aBoard, BOARD_ITEM *aBoardItem) override
std::vector< COLUMN_DESC > m_columns
All displayed (or hidden) columns.
virtual void OnShowPanel() override
Prepare the panel when shown in the editor.
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:125
The project local settings are things that are attached to a particular project, but also might be pa...
PANEL_NET_INSPECTOR_SETTINGS m_NetInspectorPanel
The state of the net inspector panel.
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:206
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
EDA_UNITS GetUserUnits() const
wxBoxSizer * m_ContentSizer
A KICAD version of wxTextEntryDialog which supports the various improvements/work-arounds from DIALOG...
wxString GetValue() const
void SetTextValidator(wxTextValidatorStyle style)
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:250
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
This file is part of the common library.
#define _(s)
#define CANDIDATE
flag indicating that the structure is connected
Abstract pattern-matching tool and implementations.
@ CTX_NET
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:581
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Cu
Definition: layer_ids.h:65
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ F_Cu
Definition: layer_ids.h:64
KICOMMON_API wxString GetLabel(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
Definition: eda_units.cpp:156
@ REPAINT
Item needs to be redrawn.
Definition: view_item.h:58
@ GEOMETRY
Position or shape has changed.
Definition: view_item.h:55
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:155
void delete_matching(_Container &__c, _Value __value)
Covers for the horrifically named std::remove and std::remove_if (neither of which remove anything).
Definition: kicad_algo.h:165
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1073
see class PGM_BASE
static bool highlightNet(TOOL_MANAGER *aToolMgr, const VECTOR2D &aPosition)
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_NETNAME
Definition: string_utils.h:53
bool operator()(const CN_ITEM *a, const CN_ITEM *b) const
bool operator()(int a, const CN_ITEM *b) const
bool operator()(const CN_ITEM *a, int b) const
Persisted state for the net inspector panel.
std::vector< wxString > expanded_rows
std::vector< wxString > custom_group_rules
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
Custom text control validator definitions.
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.
Definition of file extensions used in Kicad.