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