KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_net_inspector_panel_data_model.h
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 (C) 2024 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
20#ifndef PCB_NET_INSPECTOR_PANEL_DATA_MODEL
21#define PCB_NET_INSPECTOR_PANEL_DATA_MODEL
22
23#include <eda_pattern_match.h>
24
25
32{
33public:
34 enum class GROUP_TYPE
35 {
36 NONE,
39 };
40
41 LIST_ITEM( unsigned int aGroupNumber, const wxString& aGroupName, GROUP_TYPE aGroupType ) :
42 m_group_type( aGroupType ),
43 m_group_number( aGroupNumber ),
44 m_net_name( aGroupName )
45 {
46 m_group_name = aGroupName;
48 }
49
52 m_net( aNet )
53 {
54 wxASSERT( aNet );
58 }
59
61
62 LIST_ITEM& operator=( const LIST_ITEM& ) = delete;
63
64 bool GetIsGroup() const { return m_group_type != GROUP_TYPE::NONE; }
65 const wxString& GetGroupName() const { return m_group_name; }
67 int GetGroupNumber() const { return m_group_number; }
68
69 auto ChildrenBegin() const { return m_children.begin(); }
70 auto ChildrenEnd() const { return m_children.end(); }
71 unsigned int ChildrenCount() const { return m_children.size(); }
72
73 NETINFO_ITEM* GetNet() const { return m_net; }
74
75 int GetNetCode() const
76 {
77 return GetIsGroup() ? ( 0 - int( m_group_number ) - 1 ) : m_net->GetNetCode();
78 }
79
80 const wxString& GetNetName() const { return m_net_name; }
81 const wxString& GetNetclassName() const { return m_net_class; }
82
84 {
85 std::fill( m_column_changed.begin(), m_column_changed.end(), 0 );
86 }
87
88 unsigned int GetPadCount() const { return m_pad_count; }
89
91
92 void SetPadCount( unsigned int aValue )
93 {
94 if( m_parent )
96
98 m_pad_count = aValue;
99 }
100
101 void AddPadCount( unsigned int aValue )
102 {
103 if( m_parent )
104 m_parent->AddPadCount( aValue );
105
106 m_column_changed[COLUMN_PAD_COUNT] |= ( aValue != 0 );
107 m_pad_count += aValue;
108 }
109
110 void SubPadCount( unsigned int aValue )
111 {
112 if( m_parent )
113 m_parent->SubPadCount( aValue );
114
115 m_column_changed[COLUMN_PAD_COUNT] |= ( aValue != 0 );
116 m_pad_count -= aValue;
117 }
118
119 unsigned GetViaCount() const { return m_via_count; }
120
122
123 void SetViaCount( unsigned int aValue )
124 {
125 if( m_parent )
127
129 m_via_count = aValue;
130 }
131
132 void AddViaCount( unsigned int aValue )
133 {
134 if( m_parent )
135 m_parent->AddViaCount( aValue );
136
137 m_column_changed[COLUMN_VIA_COUNT] |= ( aValue != 0 );
138 m_via_count += aValue;
139 }
140
141 void SubViaCount( unsigned int aValue )
142 {
143 if( m_parent )
144 m_parent->SubViaCount( aValue );
145
146 m_column_changed[COLUMN_VIA_COUNT] |= ( aValue != 0 );
147 m_via_count -= aValue;
148 }
149
150 uint64_t GetViaLength() const { return m_via_length; }
151
153
154 void SetViaLength( unsigned int aValue )
155 {
156 if( m_parent )
158
160 m_via_length = aValue;
161 }
162
163 void AddViaLength( unsigned int aValue )
164 {
165 if( m_parent )
166 m_parent->AddViaLength( aValue );
167
168 m_column_changed[COLUMN_VIA_LENGTH] |= ( aValue != 0 );
169 m_via_length += aValue;
170 }
171
172 void SubViaLength( uint64_t aValue )
173 {
174 if( m_parent )
175 m_parent->SubViaLength( aValue );
176
177 m_column_changed[COLUMN_VIA_LENGTH] |= ( aValue != 0 );
178 m_via_length -= aValue;
179 }
180
181 uint64_t GetBoardWireLength() const
182 {
183 uint64_t retval = 0;
184
185 for( uint64_t val : m_layer_wire_length )
186 retval += val;
187
188 return retval;
189 }
190
191 uint64_t GetLayerWireLength( size_t aLayer ) const
192 {
193 wxCHECK_MSG( aLayer < m_layer_wire_length.size(), 0, wxT( "Invalid layer specified" ) );
194
195 return m_layer_wire_length[aLayer];
196 }
197
199
200 void SetLayerWireLength( const uint64_t aValue, size_t aLayer )
201 {
202 wxCHECK_RET( aLayer < m_layer_wire_length.size(), wxT( "Invalid layer specified" ) );
203
204 if( m_parent )
205 {
207 - m_layer_wire_length[aLayer] + aValue,
208 aLayer );
209 }
210
212 m_layer_wire_length[aLayer] = aValue;
213 }
214
215 void AddLayerWireLength( const uint64_t aValue, size_t aLayer )
216 {
217 if( m_parent )
218 m_parent->AddLayerWireLength( aValue, aLayer );
219
221 m_layer_wire_length[aLayer] += aValue;
222 }
223
224 void SubLayerWireLength( const uint64_t aValue, size_t aLayer )
225 {
226 if( m_parent )
227 m_parent->SubLayerWireLength( aValue, aLayer );
228
230 m_layer_wire_length[aLayer] -= aValue;
231 }
232
233 uint64_t GetPadDieLength() const { return m_pad_die_length; }
234
236
237 void SetPadDieLength( uint64_t aValue )
238 {
239 if( m_parent )
241
243 m_pad_die_length = aValue;
244 }
245
246 void AddPadDieLength( uint64_t aValue )
247 {
248 if( m_parent )
249 m_parent->AddPadDieLength( aValue );
250
251 m_column_changed[COLUMN_PAD_DIE_LENGTH] |= ( aValue != 0 );
252 m_pad_die_length += aValue;
253 }
254
255 void SubPadDieLength( uint64_t aValue )
256 {
257 if( m_parent )
258 m_parent->SubPadDieLength( aValue );
259
260 m_column_changed[COLUMN_PAD_DIE_LENGTH] |= ( aValue != 0 );
261 m_pad_die_length -= aValue;
262 }
263
264 // the total length column is always computed, never stored.
265 unsigned long long int GetTotalLength() const
266 {
268 }
269
271 {
273 }
274
275 LIST_ITEM* Parent() const { return m_parent; }
276
277 void SetParent( LIST_ITEM* aParent )
278 {
279 if( m_parent == aParent )
280 return;
281
282 if( m_parent != nullptr )
283 {
287
288 for( size_t ii = 0; ii < m_layer_wire_length.size(); ++ii )
290
292
293 m_parent->m_children.erase( std::find( m_parent->m_children.begin(),
294 m_parent->m_children.end(), this ) );
295 }
296
297 m_parent = aParent;
298
299 if( m_parent != nullptr )
300 {
304
305 for( size_t ii = 0; ii < m_layer_wire_length.size(); ++ii )
307
309
310 m_parent->m_children.push_back( this );
311 }
312 }
313
314private:
315 LIST_ITEM* m_parent = nullptr;
316 std::vector<LIST_ITEM*> m_children;
317
319 unsigned int m_group_number = 0;
320 NETINFO_ITEM* m_net = nullptr;
321 unsigned int m_pad_count = 0;
322 unsigned int m_via_count = 0;
323 uint64_t m_via_length = 0;
324 uint64_t m_pad_die_length = 0;
325
326 std::array<uint64_t, MAX_CU_LAYERS> m_layer_wire_length{};
327
328 // Dirty bits to record when some attribute has changed, in order to avoid unnecessary sort
329 // operations.
330 // The values are semantically bools, but STL auto-promotes a std::vector<bool> to a bitset,
331 // and then operator|= doesn't work.
332 std::vector<int> m_column_changed;
333
334 // cached formatted names for faster display sorting
335 wxString m_net_name;
336 wxString m_net_class;
337 wxString m_group_name;
338};
339
340
342{
343 template <typename T>
344 bool operator()( const T& a, const T& b ) const
345 {
346 return a->GetNetCode() < b->GetNetCode();
347 }
348
349 template <typename T>
350 bool operator()( const T& a, int b ) const
351 {
352 return a->GetNetCode() < b;
353 }
354
355 template <typename T>
356 bool operator()( int a, const T& b ) const
357 {
358 return a < b->GetNetCode();
359 }
360};
361
362
364{
365 template <typename T>
366 bool operator()( const T& a, const T& b ) const
367 {
368 return a->GetGroupNumber() < b->GetGroupNumber();
369 }
370
371 template <typename T>
372 bool operator()( const T& a, int b ) const
373 {
374 return a->GetGroupNumber() < b;
375 }
376
377 template <typename T>
378 bool operator()( int a, const T& b ) const
379 {
380 return a < b->GetGroupNumber();
381 }
382};
383
384
388class PCB_NET_INSPECTOR_PANEL::DATA_MODEL : public wxDataViewModel
389{
390public:
392
393 unsigned int columnCount() const { return m_parent.m_columns.size(); }
394
395 unsigned int itemCount() const { return m_items.size(); }
396
397 wxVariant valueAt( unsigned int aCol, unsigned int aRow ) const
398 {
399 wxVariant r;
400 GetValue( r, wxDataViewItem( const_cast<LIST_ITEM*>( &*( m_items[aRow] ) ) ), aCol );
401 return r;
402 }
403
404 const LIST_ITEM& itemAt( unsigned int aRow ) const { return *m_items.at( aRow ); }
405
406 std::vector<std::pair<wxString, wxDataViewItem>> getGroupDataViewItems()
407 {
408 std::vector<std::pair<wxString, wxDataViewItem>> ret;
409
410 for( std::unique_ptr<LIST_ITEM>& item : m_items )
411 {
412 if( item->GetIsGroup() )
413 {
414 ret.push_back( std::make_pair( item->GetGroupName(),
415 wxDataViewItem( item.get() ) ) );
416 }
417 }
418
419 return ret;
420 }
421
422
423 std::optional<LIST_ITEM_ITER> findItem( int aNetCode )
424 {
425 auto i = std::lower_bound( m_items.begin(), m_items.end(), aNetCode,
427
428 if( i == m_items.end() || ( *i )->GetNetCode() != aNetCode )
429 return std::nullopt;
430
431 return { i };
432 }
433
434
435 std::optional<LIST_ITEM_ITER> findItem( NETINFO_ITEM* aNet )
436 {
437 if( aNet != nullptr )
438 return findItem( aNet->GetNetCode() );
439 else
440 return std::nullopt;
441 }
442
443
444 std::optional<LIST_ITEM_ITER> findGroupItem( int aGroupNumber )
445 {
446 auto i = std::lower_bound( m_items.begin(), m_items.end(), aGroupNumber,
448
449 if( i == m_items.end() || ( *i )->GetGroupNumber() != aGroupNumber )
450 return std::nullopt;
451
452 return { i };
453 }
454
455
457 wxString groupName, LIST_ITEM::GROUP_TYPE groupType )
458 {
459 LIST_ITEM_ITER group = std::find_if( groupsBegin, groupsEnd,
460 [&]( const std::unique_ptr<LIST_ITEM>& x )
461 {
462 return x->GetGroupName() == groupName
463 && x->GetGroupType() == groupType;
464 } );
465
466 if( group == groupsEnd )
467 {
468 int dist = std::distance( groupsBegin, groupsEnd );
469 std::unique_ptr<LIST_ITEM> groupItem = std::make_unique<LIST_ITEM>( dist, groupName,
470 groupType );
471 group = m_items.insert( groupsEnd, std::move( groupItem ) );
472 ItemAdded( wxDataViewItem( ( *group )->Parent() ), wxDataViewItem( &**group ) );
473 }
474
475 return group;
476 }
477
478
479 std::optional<LIST_ITEM_ITER> addItem( std::unique_ptr<LIST_ITEM> aItem )
480 {
481 if( aItem == nullptr )
482 return {};
483
484 bool groupMatched = false;
485
486 // First see if item matches a group-by rule
487 if( m_parent.m_custom_group_rules.size() > 0 )
488 {
489 wxString searchName = aItem->GetNetName().Upper();
490
491 for( const std::unique_ptr<EDA_COMBINED_MATCHER>& rule : m_parent.m_custom_group_rules )
492 {
493 if( rule->Find( searchName.Upper() ) )
494 {
495 aItem->SetParent( m_custom_group_map[ rule->GetPattern() ] );
496 groupMatched = true;
497 break;
498 }
499 }
500 }
501
502 // Then add any netclass groups required by this item
503 if( m_parent.m_group_by_netclass && !groupMatched )
504 {
505 LIST_ITEM_ITER groups_begin = m_items.begin();
506 LIST_ITEM_ITER groups_end = std::find_if_not( m_items.begin(), m_items.end(),
507 []( const std::unique_ptr<LIST_ITEM>& x )
508 {
509 return x->GetIsGroup();
510 } );
511
512 wxString match_str = aItem->GetNetclassName();
513 LIST_ITEM_ITER group = addGroup( groups_begin, groups_end, match_str,
515 aItem->SetParent( &**group );
516 }
517
518 // Now add the item itself. Usually when new nets are added,
519 // they always get a higher netcode number than the already existing ones.
520 // however, if we've got filtering enabled, we might not have all the nets in
521 // our list, so do a sorted insertion.
522 auto new_iter = std::lower_bound( m_items.begin(), m_items.end(), aItem->GetNetCode(),
524
525 new_iter = m_items.insert( new_iter, std::move( aItem ) );
526 const std::unique_ptr<LIST_ITEM>& new_item = *new_iter;
527
528 ItemAdded( wxDataViewItem( new_item->Parent() ), wxDataViewItem( new_item.get() ) );
529
530 return { new_iter };
531 }
532
533 void addItems( std::vector<std::unique_ptr<LIST_ITEM>> aItems )
534 {
535 m_items.reserve( m_items.size() + aItems.size() );
536
537 for( std::unique_ptr<LIST_ITEM>& i : aItems )
538 addItem( std::move( i ) );
539 }
540
541 std::unique_ptr<LIST_ITEM> deleteItem( const std::optional<LIST_ITEM_ITER>& aRow )
542 {
543 if( !aRow )
544 return {};
545
546 std::unique_ptr<LIST_ITEM> i = std::move( **aRow );
547
548 LIST_ITEM* parent = i->Parent();
549 i->SetParent( nullptr );
550
551 m_items.erase( *aRow );
552 ItemDeleted( wxDataViewItem( parent ), wxDataViewItem( &*i ) );
553
554 if( parent )
555 {
556 ItemChanged( wxDataViewItem( parent ) );
557
558 if( m_parent.m_group_by_netclass && parent != nullptr && parent->ChildrenCount() == 0 )
559 {
560 auto p = std::find_if( m_items.begin(), m_items.end(),
561 [&]( std::unique_ptr<LIST_ITEM>& x )
562 {
563 return x.get() == parent;
564 } );
565
566 wxASSERT( p != m_items.end() );
567 m_items.erase( p );
568
569 ItemDeleted( wxDataViewItem( parent->Parent() ), wxDataViewItem( parent ) );
570 }
571 }
572
573 Resort();
574 return i;
575 }
576
577
584 {
585 m_custom_group_map.clear();
586 int groupId = 0;
587
588 for( const std::unique_ptr<EDA_COMBINED_MATCHER>& rule : m_parent.m_custom_group_rules )
589 {
590 std::unique_ptr<LIST_ITEM>& group = m_items.emplace_back( std::make_unique<LIST_ITEM>(
591 groupId, rule->GetPattern(), LIST_ITEM::GROUP_TYPE::USER_DEFINED ) );
592 m_custom_group_map[ rule->GetPattern() ] = group.get();
593 ItemAdded( wxDataViewItem( group->Parent() ), wxDataViewItem( group.get() ) );
594 ++groupId;
595 }
596 }
597
598
600 {
601 BeforeReset();
602 m_items.clear();
603 AfterReset();
604 }
605
606 void updateItem( const std::optional<LIST_ITEM_ITER>& aRow )
607 {
608 if( aRow )
609 {
610 const std::unique_ptr<LIST_ITEM>& listItem = *aRow.value();
611
612 if( listItem->Parent() )
613 ItemChanged( wxDataViewItem( listItem->Parent() ) );
614
615 ItemChanged( wxDataViewItem( listItem.get() ) );
616 resortIfChanged( listItem.get() );
617 }
618 }
619
621 {
622 for( std::unique_ptr<LIST_ITEM>& i : m_items )
623 ItemChanged( wxDataViewItem( i.get() ) );
624 }
625
627 {
628 if( wxDataViewColumn* column = m_parent.m_netsList->GetSortingColumn() )
629 {
630 bool changed = false;
631
632 for( const LIST_ITEM* i = aItem; i != nullptr; i = i->Parent() )
633 changed |= itemColumnChanged( i, column->GetModelColumn() );
634
635 for( LIST_ITEM* i = aItem; i != nullptr; i = i->Parent() )
636 i->ResetColumnChangedBits();
637
638 if( changed )
639 Resort();
640 }
641 }
642
643 bool itemColumnChanged( const LIST_ITEM* aItem, unsigned int aCol ) const
644 {
645 if( aItem == nullptr || aCol >= m_parent.m_columns.size() )
646 return false;
647
648 if( aCol == COLUMN_PAD_COUNT )
649 return aItem->PadCountChanged();
650
651 else if( aCol == COLUMN_VIA_COUNT )
652 return aItem->ViaCountChanged();
653
654 else if( aCol == COLUMN_VIA_LENGTH )
655 return aItem->ViaLengthChanged();
656
657 else if( aCol == COLUMN_BOARD_LENGTH )
658 return aItem->BoardWireLengthChanged();
659
660 else if( aCol == COLUMN_PAD_DIE_LENGTH )
661 return aItem->PadDieLengthChanged();
662
663 else if( aCol == COLUMN_TOTAL_LENGTH )
664 return aItem->TotalLengthChanged();
665
666 else if( aCol > COLUMN_LAST_STATIC_COL )
667 return aItem->BoardWireLengthChanged();
668
669
670 return false;
671 }
672
673 // implementation of wxDataViewModel interface
674 // these are used to query the data model by the GUI view implementation.
675 // these are not supposed to be used to modify the data model. for that
676 // use the public functions above.
677
678protected:
679 unsigned int GetColumnCount() const override { return columnCount(); }
680
681 void GetValue( wxVariant& aOutValue, const wxDataViewItem& aItem,
682 unsigned int aCol ) const override
683 {
684 if( LIST_ITEM* i = static_cast<LIST_ITEM*>( aItem.GetID() ) )
685 {
686 if( i->GetIsGroup() )
687 {
688 if( aCol == COLUMN_NAME )
689 {
690 switch( i->GetGroupType() )
691 {
693 aOutValue = _( "Netclass" ) + ": " + i->GetGroupName();
694 break;
696 aOutValue = _( "Custom" ) + ": " + i->GetGroupName();
697 break;
698 default:
699 aOutValue = i->GetGroupName();
700 break;
701 }
702 }
703 else
704 {
705 aOutValue = "";
706 }
707 }
708
709 else if( aCol == COLUMN_NAME )
710 aOutValue = i->GetNetName();
711
712 else if( aCol == COLUMN_NETCLASS )
713 aOutValue = i->GetNetclassName();
714
715 else if( aCol == COLUMN_PAD_COUNT )
716 aOutValue = m_parent.formatCount( i->GetPadCount() );
717
718 else if( aCol == COLUMN_VIA_COUNT )
719 aOutValue = m_parent.formatCount( i->GetViaCount() );
720
721 else if( aCol == COLUMN_VIA_LENGTH )
722 aOutValue = m_parent.formatLength( i->GetViaLength() );
723
724 else if( aCol == COLUMN_BOARD_LENGTH )
725 aOutValue = m_parent.formatLength( i->GetBoardWireLength() );
726
727 else if( aCol == COLUMN_PAD_DIE_LENGTH )
728 aOutValue = m_parent.formatLength( i->GetPadDieLength() );
729
730 else if( aCol == COLUMN_TOTAL_LENGTH )
731 aOutValue = m_parent.formatLength( i->GetTotalLength() );
732
733 else if( aCol > COLUMN_LAST_STATIC_COL && aCol <= m_parent.m_columns.size() )
734 aOutValue = m_parent.formatLength( i->GetLayerWireLength( m_parent.m_columns[aCol].layer ) );
735
736 else
737 aOutValue = "";
738 }
739 }
740
741 static int compareUInt( uint64_t aValue1, uint64_t aValue2, bool aAsc )
742 {
743 if( aAsc )
744 return aValue1 < aValue2 ? -1 : 1;
745 else
746 return aValue2 < aValue1 ? -1 : 1;
747 }
748
749 int Compare( const wxDataViewItem& aItem1, const wxDataViewItem& aItem2, unsigned int aCol,
750 bool aAsc ) const override
751 {
752 const LIST_ITEM& i1 = *static_cast<const LIST_ITEM*>( aItem1.GetID() );
753 const LIST_ITEM& i2 = *static_cast<const LIST_ITEM*>( aItem2.GetID() );
754
755 if( i1.GetIsGroup() && !i2.GetIsGroup() )
756 return -1;
757
758 if( i2.GetIsGroup() && !i1.GetIsGroup() )
759 return 1;
760
761 if( aCol == COLUMN_NAME )
762 {
763 const wxString& s1 = i1.GetNetName();
764 const wxString& s2 = i2.GetNetName();
765
766 int res = aAsc ? ValueStringCompare( s1, s2 ) : ValueStringCompare( s2, s1 );
767
768 if( res != 0 )
769 return res;
770 }
771
772 else if( aCol == COLUMN_PAD_COUNT && i1.GetPadCount() != i2.GetPadCount() )
773 return compareUInt( i1.GetPadCount(), i2.GetPadCount(), aAsc );
774
775 else if( aCol == COLUMN_VIA_COUNT && i1.GetViaCount() != i2.GetViaCount() )
776 return compareUInt( i1.GetViaCount(), i2.GetViaCount(), aAsc );
777
778 else if( aCol == COLUMN_VIA_LENGTH && i1.GetViaLength() != i2.GetViaLength() )
779 return compareUInt( i1.GetViaLength(), i2.GetViaLength(), aAsc );
780
781 else if( aCol == COLUMN_BOARD_LENGTH && i1.GetBoardWireLength() != i2.GetBoardWireLength() )
782 return compareUInt( i1.GetBoardWireLength(), i2.GetBoardWireLength(), aAsc );
783
784 else if( aCol == COLUMN_PAD_DIE_LENGTH && i1.GetPadDieLength() != i2.GetPadDieLength() )
785 return compareUInt( i1.GetPadDieLength(), i2.GetPadDieLength(), aAsc );
786
787 else if( aCol == COLUMN_TOTAL_LENGTH && i1.GetTotalLength() != i2.GetTotalLength() )
788 return compareUInt( i1.GetTotalLength(), i2.GetTotalLength(), aAsc );
789
790 else if( aCol > COLUMN_LAST_STATIC_COL && aCol < m_parent.m_columns.size()
791 && i1.GetLayerWireLength( m_parent.m_columns[aCol].layer )
792 != i2.GetLayerWireLength( m_parent.m_columns[aCol].layer ) )
793 {
794 return compareUInt( i1.GetLayerWireLength( m_parent.m_columns[aCol].layer ),
795 i2.GetLayerWireLength( m_parent.m_columns[aCol].layer ), aAsc );
796 }
797
798 // when the item values compare equal resort to pointer comparison.
799 wxUIntPtr id1 = wxPtrToUInt( aItem1.GetID() );
800 wxUIntPtr id2 = wxPtrToUInt( aItem2.GetID() );
801
802 return aAsc ? id1 - id2 : id2 - id1;
803 }
804
805 bool SetValue( const wxVariant& aInValue, const wxDataViewItem& aItem,
806 unsigned int aCol ) override
807 {
808 return false;
809 }
810
811 wxDataViewItem GetParent( const wxDataViewItem& aItem ) const override
812 {
813 if( !aItem.IsOk() )
814 return wxDataViewItem();
815
816 return wxDataViewItem( static_cast<const LIST_ITEM*>( aItem.GetID() )->Parent() );
817 }
818
819 bool IsContainer( const wxDataViewItem& aItem ) const override
820 {
821 if( !aItem.IsOk() )
822 return true;
823
824 return static_cast<const LIST_ITEM*>( aItem.GetID() )->GetIsGroup();
825 }
826
827 bool HasContainerColumns( const wxDataViewItem& aItem ) const override
828 {
829 return IsContainer( aItem );
830 }
831
832 unsigned int GetChildren( const wxDataViewItem& aParent,
833 wxDataViewItemArray& aChildren ) const override
834 {
835 const LIST_ITEM* p = static_cast<const LIST_ITEM*>( aParent.GetID() );
836
837 if( !aParent.IsOk() )
838 {
839 aChildren.Alloc( m_items.size() );
840
841 for( const std::unique_ptr<LIST_ITEM>& i : m_items )
842 {
843 if( i->Parent() == nullptr )
844 aChildren.Add( wxDataViewItem( &*i ) );
845 }
846
847 return aChildren.GetCount();
848 }
849 else if( p->GetIsGroup() )
850 {
851 const int count = p->ChildrenCount();
852
853 if( count == 0 )
854 return 0;
855
856 aChildren.Alloc( count );
857
858 for( auto i = p->ChildrenBegin(), end = p->ChildrenEnd(); i != end; ++i )
859 aChildren.Add( wxDataViewItem( *i ) );
860
861 return aChildren.GetCount();
862 }
863
864 return 0;
865 }
866
867 wxString GetColumnType( unsigned int /* aCol */ ) const override { return wxS( "string" ); }
868
869private:
871
872 // primary container, sorted by netcode number.
873 // groups have netcode < 0, so they always come first, in the order
874 // of the filter strings as input by the user
875 std::vector<std::unique_ptr<LIST_ITEM>> m_items;
876
878 std::map<wxString, LIST_ITEM*> m_custom_group_map;
879};
880
881#endif
A collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:44
const wxString GetName() const
Definition: netclass.h:62
Handle the data for a net.
Definition: netinfo.h:56
const wxString & GetNetname() const
Definition: netinfo.h:114
NETCLASS * GetNetClass()
Definition: netinfo.h:101
int GetNetCode() const
Definition: netinfo.h:108
wxDataViewCtrl * m_netsList
Data model for display in the Net Inspector panel.
std::unique_ptr< LIST_ITEM > deleteItem(const std::optional< LIST_ITEM_ITER > &aRow)
bool IsContainer(const wxDataViewItem &aItem) const override
bool itemColumnChanged(const LIST_ITEM *aItem, unsigned int aCol) const
void addCustomGroups()
Adds all custom group-by entries to the items table.
wxString GetColumnType(unsigned int) const override
wxDataViewItem GetParent(const wxDataViewItem &aItem) const override
bool HasContainerColumns(const wxDataViewItem &aItem) const override
bool SetValue(const wxVariant &aInValue, const wxDataViewItem &aItem, unsigned int aCol) override
void addItems(std::vector< std::unique_ptr< LIST_ITEM > > aItems)
void GetValue(wxVariant &aOutValue, const wxDataViewItem &aItem, unsigned int aCol) const override
std::vector< std::pair< wxString, wxDataViewItem > > getGroupDataViewItems()
std::optional< LIST_ITEM_ITER > findItem(NETINFO_ITEM *aNet)
static int compareUInt(uint64_t aValue1, uint64_t aValue2, bool aAsc)
unsigned int GetChildren(const wxDataViewItem &aParent, wxDataViewItemArray &aChildren) const override
std::optional< LIST_ITEM_ITER > findItem(int aNetCode)
std::map< wxString, LIST_ITEM * > m_custom_group_map
Map of custom group names to their representative list item.
wxVariant valueAt(unsigned int aCol, unsigned int aRow) const
int Compare(const wxDataViewItem &aItem1, const wxDataViewItem &aItem2, unsigned int aCol, bool aAsc) const override
std::optional< LIST_ITEM_ITER > findGroupItem(int aGroupNumber)
std::vector< std::unique_ptr< LIST_ITEM > > m_items
const LIST_ITEM & itemAt(unsigned int aRow) const
void updateItem(const std::optional< LIST_ITEM_ITER > &aRow)
LIST_ITEM_ITER addGroup(LIST_ITEM_ITER groupsBegin, LIST_ITEM_ITER groupsEnd, wxString groupName, LIST_ITEM::GROUP_TYPE groupType)
std::optional< LIST_ITEM_ITER > addItem(std::unique_ptr< LIST_ITEM > aItem)
Primary data item for entries in the Net Inspector list.
LIST_ITEM(unsigned int aGroupNumber, const wxString &aGroupName, GROUP_TYPE aGroupType)
void SubLayerWireLength(const uint64_t aValue, size_t aLayer)
LIST_ITEM & operator=(const LIST_ITEM &)=delete
void SetLayerWireLength(const uint64_t aValue, size_t aLayer)
void AddLayerWireLength(const uint64_t aValue, size_t aLayer)
std::array< uint64_t, MAX_CU_LAYERS > m_layer_wire_length
Net inspection panel for pcbnew.
std::vector< std::unique_ptr< LIST_ITEM > >::iterator LIST_ITEM_ITER
wxString formatCount(unsigned int aValue) const
std::vector< std::unique_ptr< EDA_COMBINED_MATCHER > > m_custom_group_rules
wxString formatLength(int64_t aValue) const
std::vector< COLUMN_DESC > m_columns
All displayed (or hidden) columns.
#define _(s)
Abstract pattern-matching tool and implementations.
#define MAX_CU_LAYERS
Definition: layer_ids.h:142
wxString UnescapeString(const wxString &aSource)
int ValueStringCompare(const wxString &strFWord, const wxString &strSWord)
Compare strings like the strcmp function but handle numbers and modifiers within the string text corr...
VECTOR3I res