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 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
20#ifndef PCB_NET_INSPECTOR_PANEL_DATA_MODEL
21#define PCB_NET_INSPECTOR_PANEL_DATA_MODEL
22
23#include <eda_pattern_match.h>
24#include <string_utils.h>
25
26
33{
34public:
41
42 LIST_ITEM( unsigned int aGroupNumber, const wxString& aGroupName, GROUP_TYPE aGroupType ) :
43 m_group_type( aGroupType ),
44 m_group_number( aGroupNumber ),
45 m_net_name( aGroupName )
46 {
47 m_group_name = aGroupName;
48 m_column_changed.resize( COLUMN_LAST_STATIC_COL + 1 + 2, 0 ); // 2 for default layer count
49 }
50
53 m_net( aNet )
54 {
55 wxASSERT( aNet );
58 m_column_changed.resize( COLUMN_LAST_STATIC_COL + 1 + 2, 0 );
59 }
60
62
63 LIST_ITEM& operator=( const LIST_ITEM& ) = delete;
64
65 bool GetIsGroup() const { return m_group_type != GROUP_TYPE::NONE; }
66 const wxString& GetGroupName() const { return m_group_name; }
68 int GetGroupNumber() const { return m_group_number; }
69
70 auto ChildrenBegin() const { return m_children.begin(); }
71 auto ChildrenEnd() const { return m_children.end(); }
72 unsigned int ChildrenCount() const { return m_children.size(); }
73
74 void SetLayerCount( unsigned int aValue )
75 {
76 m_column_changed.resize( COLUMN_LAST_STATIC_COL + 1 + aValue, 0 );
77 }
78
79 NETINFO_ITEM* GetNet() const { return m_net; }
80
81 int GetNetCode() const
82 {
83 return GetIsGroup() ? ( 0 - int( m_group_number ) - 1 ) : m_net->GetNetCode();
84 }
85
86 const wxString& GetNetName() const { return m_net_name; }
87 const wxString& GetNetclassName() const { return m_net_class; }
88
90 {
91 std::fill( m_column_changed.begin(), m_column_changed.end(), 0 );
92 }
93
94 unsigned int GetPadCount() const { return m_pad_count; }
95
97
98 void SetPadCount( unsigned int aValue )
99 {
100 if( m_parent )
101 m_parent->SetPadCount( m_parent->GetPadCount() - m_pad_count + aValue );
102
104 m_pad_count = aValue;
105 }
106
107 void AddPadCount( unsigned int aValue )
108 {
109 if( m_parent )
110 m_parent->AddPadCount( aValue );
111
112 m_column_changed[COLUMN_PAD_COUNT] |= ( aValue != 0 );
113 m_pad_count += aValue;
114 }
115
116 void SubPadCount( unsigned int aValue )
117 {
118 if( m_parent )
119 m_parent->SubPadCount( aValue );
120
121 m_column_changed[COLUMN_PAD_COUNT] |= ( aValue != 0 );
122 m_pad_count -= aValue;
123 }
124
125 unsigned GetViaCount() const { return m_via_count; }
126
128
129 void SetViaCount( unsigned int aValue )
130 {
131 if( m_parent )
132 m_parent->SetViaCount( m_parent->GetViaCount() - m_via_count + aValue );
133
135 m_via_count = aValue;
136 }
137
138 void AddViaCount( unsigned int aValue )
139 {
140 if( m_parent )
141 m_parent->AddViaCount( aValue );
142
143 m_column_changed[COLUMN_VIA_COUNT] |= ( aValue != 0 );
144 m_via_count += aValue;
145 }
146
147 void SubViaCount( unsigned int aValue )
148 {
149 if( m_parent )
150 m_parent->SubViaCount( aValue );
151
152 m_column_changed[COLUMN_VIA_COUNT] |= ( aValue != 0 );
153 m_via_count -= aValue;
154 }
155
156 int64_t GetViaLength() const { return m_via_length; }
157
159
160 void SetViaLength( unsigned int aValue )
161 {
162 if( m_parent )
163 m_parent->SetViaLength( m_parent->GetViaLength() - m_via_length + aValue );
164
166 m_via_length = aValue;
167 }
168
169 void AddViaLength( unsigned int aValue )
170 {
171 if( m_parent )
172 m_parent->AddViaLength( aValue );
173
174 m_column_changed[COLUMN_VIA_LENGTH] |= ( aValue != 0 );
175 m_via_length += aValue;
176 }
177
178 void SubViaLength( int64_t aValue )
179 {
180 if( m_parent )
181 m_parent->SubViaLength( aValue );
182
183 m_column_changed[COLUMN_VIA_LENGTH] |= ( aValue != 0 );
184 m_via_length -= aValue;
185 }
186
187 int64_t GetViaDelay() const { return m_via_delay; }
188
189 void SetViaDelay( unsigned int aValue )
190 {
191 if( m_parent )
192 m_parent->SetViaDelay( m_parent->GetViaDelay() - m_via_delay + aValue );
193
195 m_via_delay = aValue;
196 }
197
198 void AddViaDelay( unsigned int aValue )
199 {
200 if( m_parent )
201 m_parent->AddViaDelay( aValue );
202
203 m_column_changed[COLUMN_VIA_LENGTH] |= ( aValue != 0 );
204 m_via_delay += aValue;
205 }
206
207 void SubViaDelay( int64_t aValue )
208 {
209 if( m_parent )
210 m_parent->SubViaDelay( aValue );
211
212 m_column_changed[COLUMN_VIA_LENGTH] |= ( aValue != 0 );
213 m_via_delay -= aValue;
214 }
215
216 int64_t GetBoardWireLength() const
217 {
218 int64_t retval = 0;
219
220 for( auto& [layer, length] : m_layer_wire_length )
221 retval += length;
222
223 return retval;
224 }
225
226 int64_t GetBoardWireDelay() const
227 {
228 int64_t retval = 0;
229
230 for( auto& [layer, delay] : m_layer_wire_delay )
231 retval += delay;
232
233 return retval;
234 }
235
236 int64_t GetLayerWireLength( PCB_LAYER_ID aLayer ) const
237 {
238 auto it = m_layer_wire_length.find( aLayer );
239 return it != m_layer_wire_length.end() ? it->second : 0;
240 }
241
242 int64_t GetLayerWireDelay( PCB_LAYER_ID aLayer ) const
243 {
244 auto it = m_layer_wire_delay.find( aLayer );
245 return it != m_layer_wire_delay.end() ? it->second : 0;
246 }
247
249
250 void SetLayerWireLength( const int64_t aValue, PCB_LAYER_ID aLayer )
251 {
252 auto it = m_layer_wire_length.find( aLayer );
253
254 wxCHECK_RET( it != m_layer_wire_length.end(), wxT( "Invalid layer specified" ) );
255
256 auto& [_, length] = *it;
257
258 if( m_parent )
259 {
260 m_parent->SetLayerWireLength( m_parent->GetBoardWireLength() - length + aValue,
261 aLayer );
262 }
263
264 m_column_changed[COLUMN_BOARD_LENGTH] |= ( length != aValue );
265 length = aValue;
266 }
267
268 std::map<PCB_LAYER_ID, int64_t> GetLayerWireLengths() const { return m_layer_wire_length; }
269
270 std::map<PCB_LAYER_ID, int64_t> GetLayerWireDelays() const { return m_layer_wire_delay; }
271
272 void SetLayerWireLengths( const std::map<PCB_LAYER_ID, int64_t>& aValue )
273 {
274 if( m_parent )
275 {
276 for( auto& [oldLayer, oldLength] : m_layer_wire_length )
277 m_parent->SubLayerWireLength( oldLength, oldLayer );
278
279 for( auto& [newLayer, newLength] : aValue )
280 m_parent->AddLayerWireLength( newLength, newLayer );
281 }
282
283 m_layer_wire_length = aValue;
284 }
285
286 void AddLayerWireLength( const int64_t aValue, PCB_LAYER_ID aLayer )
287 {
288 if( m_parent )
289 m_parent->AddLayerWireLength( aValue, aLayer );
290
292 m_layer_wire_length[aLayer] += aValue;
293 }
294
295 void SubLayerWireLength( const int64_t aValue, PCB_LAYER_ID aLayer )
296 {
297 if( m_parent )
298 m_parent->SubLayerWireLength( aValue, aLayer );
299
301 m_layer_wire_length[aLayer] -= aValue;
302 }
303
304 void SetLayerWireDelays( const std::map<PCB_LAYER_ID, int64_t>& aValue )
305 {
306 if( m_parent )
307 {
308 for( auto& [oldLayer, oldLength] : m_layer_wire_delay )
309 m_parent->SubLayerWireDelay( oldLength, oldLayer );
310
311 for( auto& [newLayer, newLength] : aValue )
312 m_parent->AddLayerWireDelay( newLength, newLayer );
313 }
314
315 m_layer_wire_delay = aValue;
316 }
317
318 void AddLayerWireDelay( const int64_t aValue, PCB_LAYER_ID aLayer )
319 {
320 if( m_parent )
321 m_parent->AddLayerWireDelay( aValue, aLayer );
322
324 m_layer_wire_delay[aLayer] += aValue;
325 }
326
327 void SubLayerWireDelay( const int64_t aValue, PCB_LAYER_ID aLayer )
328 {
329 if( m_parent )
330 m_parent->SubLayerWireDelay( aValue, aLayer );
331
333 m_layer_wire_delay[aLayer] -= aValue;
334 }
335
336 int64_t GetPadDieLength() const { return m_pad_die_length; }
337
339
340 void SetPadDieLength( int64_t aValue )
341 {
342 if( m_parent )
343 m_parent->SetPadDieLength( m_parent->GetPadDieLength() - m_pad_die_length + aValue );
344
346 m_pad_die_length = aValue;
347 }
348
349 void AddPadDieLength( int64_t aValue )
350 {
351 if( m_parent )
352 m_parent->AddPadDieLength( aValue );
353
354 m_column_changed[COLUMN_PAD_DIE_LENGTH] |= ( aValue != 0 );
355 m_pad_die_length += aValue;
356 }
357
358 void SubPadDieLength( int64_t aValue )
359 {
360 if( m_parent )
361 m_parent->SubPadDieLength( aValue );
362
363 m_column_changed[COLUMN_PAD_DIE_LENGTH] |= ( aValue != 0 );
364 m_pad_die_length -= aValue;
365 }
366
367 int64_t GetPadDieDelay() const { return m_pad_die_delay; }
368
369 void SetPadDieDelay( int64_t aValue )
370 {
371 if( m_parent )
372 m_parent->SetPadDieDelay( m_parent->GetPadDieDelay() - m_pad_die_delay + aValue );
373
375 m_pad_die_delay = aValue;
376 }
377
378 void AddPadDieDelay( int64_t aValue )
379 {
380 if( m_parent )
381 m_parent->AddPadDieDelay( aValue );
382
383 m_column_changed[COLUMN_PAD_DIE_LENGTH] |= ( aValue != 0 );
384 m_pad_die_delay += aValue;
385 }
386
387 void SubPadDieDelay( int64_t aValue )
388 {
389 if( m_parent )
390 m_parent->SubPadDieDelay( aValue );
391
392 m_column_changed[COLUMN_PAD_DIE_LENGTH] |= ( aValue != 0 );
393 m_pad_die_delay -= aValue;
394 }
395
396 // the total length column is always computed, never stored.
397 unsigned long long int GetTotalLength() const
398 {
400 }
401
402 unsigned long long int GetTotalDelay() const { return GetBoardWireDelay() + GetViaDelay() + GetPadDieDelay(); }
403
405 {
407 }
408
409 LIST_ITEM* Parent() const { return m_parent; }
410
411 void SetParent( LIST_ITEM* aParent )
412 {
413 if( m_parent == aParent )
414 return;
415
416 if( m_parent != nullptr )
417 {
418 m_parent->SubPadCount( GetPadCount() );
419 m_parent->SubViaCount( GetViaCount() );
420 m_parent->SubViaLength( GetViaLength() );
421 m_parent->SubViaDelay( GetViaDelay() );
422
423 for( auto& [layer, length] : m_layer_wire_length )
424 m_parent->SubLayerWireLength( length, layer );
425
426 for( auto& [layer, delay] : m_layer_wire_delay )
427 m_parent->SubLayerWireDelay( delay, layer );
428
429 m_parent->SubPadDieLength( GetPadDieLength() );
430 m_parent->SubPadDieDelay( GetPadDieDelay() );
431
432 m_parent->m_children.erase( std::find( m_parent->m_children.begin(),
433 m_parent->m_children.end(), this ) );
434 }
435
436 m_parent = aParent;
437
438 if( m_parent != nullptr )
439 {
440 m_parent->AddPadCount( GetPadCount() );
441 m_parent->AddViaCount( GetViaCount() );
442 m_parent->AddViaLength( GetViaLength() );
443 m_parent->AddViaDelay( GetViaDelay() );
444
445 for( auto& [layer, length] : m_layer_wire_length )
446 m_parent->AddLayerWireLength( length, layer );
447
448 for( auto& [layer, delay] : m_layer_wire_delay )
449 m_parent->AddLayerWireDelay( delay, layer );
450
451 m_parent->AddPadDieLength( GetPadDieLength() );
452 m_parent->AddPadDieDelay( GetPadDieDelay() );
453
454 m_parent->m_children.push_back( this );
455 }
456 }
457
458private:
459 LIST_ITEM* m_parent = nullptr;
460 std::vector<LIST_ITEM*> m_children;
461
463 unsigned int m_group_number = 0;
464 NETINFO_ITEM* m_net = nullptr;
465 unsigned int m_pad_count = 0;
466 unsigned int m_via_count = 0;
467 int64_t m_via_length = 0;
468 int64_t m_via_delay = 0;
469 int64_t m_pad_die_length = 0;
470 int64_t m_pad_die_delay = 0;
471
472 std::map<PCB_LAYER_ID, int64_t> m_layer_wire_length{};
473 std::map<PCB_LAYER_ID, int64_t> m_layer_wire_delay{};
474
475 // Dirty bits to record when some attribute has changed, in order to avoid unnecessary sort
476 // operations.
477 // The values are semantically bools, but STL auto-promotes a std::vector<bool> to a bitset,
478 // and then operator|= doesn't work.
479 std::vector<int> m_column_changed;
480
481 // cached formatted names for faster display sorting
482 wxString m_net_name;
483 wxString m_net_class;
484 wxString m_group_name;
485};
486
487
489{
490 template <typename T>
491 bool operator()( const T& a, const T& b ) const
492 {
493 return a->GetNetCode() < b->GetNetCode();
494 }
495
496 template <typename T>
497 bool operator()( const T& a, int b ) const
498 {
499 return a->GetNetCode() < b;
500 }
501
502 template <typename T>
503 bool operator()( int a, const T& b ) const
504 {
505 return a < b->GetNetCode();
506 }
507};
508
509
511{
512 template <typename T>
513 bool operator()( const T& a, const T& b ) const
514 {
515 return a->GetGroupNumber() < b->GetGroupNumber();
516 }
517
518 template <typename T>
519 bool operator()( const T& a, int b ) const
520 {
521 return a->GetGroupNumber() < b;
522 }
523
524 template <typename T>
525 bool operator()( int a, const T& b ) const
526 {
527 return a < b->GetGroupNumber();
528 }
529};
530
531
535class PCB_NET_INSPECTOR_PANEL::DATA_MODEL : public wxDataViewModel
536{
537public:
539
540 unsigned int columnCount() const { return m_parent.m_columns.size(); }
541
542 unsigned int itemCount() const { return m_items.size(); }
543
544 wxVariant valueAt( unsigned int aCol, unsigned int aRow ) const
545 {
546 wxVariant r;
547 GetValue( r, wxDataViewItem( const_cast<LIST_ITEM*>( &*( m_items[aRow] ) ) ), aCol );
548 return r;
549 }
550
551 const LIST_ITEM& itemAt( unsigned int aRow ) const { return *m_items.at( aRow ); }
552
553 std::vector<std::pair<wxString, wxDataViewItem>> getGroupDataViewItems()
554 {
555 std::vector<std::pair<wxString, wxDataViewItem>> ret;
556
557 for( std::unique_ptr<LIST_ITEM>& item : m_items )
558 {
559 if( item->GetIsGroup() )
560 {
561 ret.push_back( std::make_pair( item->GetGroupName(),
562 wxDataViewItem( item.get() ) ) );
563 }
564 }
565
566 return ret;
567 }
568
569
570 std::optional<LIST_ITEM_ITER> findItem( int aNetCode )
571 {
572 auto i = std::lower_bound( m_items.begin(), m_items.end(), aNetCode,
574
575 if( i == m_items.end() || ( *i )->GetNetCode() != aNetCode )
576 return std::nullopt;
577
578 return { i };
579 }
580
581
582 std::optional<LIST_ITEM_ITER> findItem( NETINFO_ITEM* aNet )
583 {
584 if( aNet != nullptr )
585 return findItem( aNet->GetNetCode() );
586 else
587 return std::nullopt;
588 }
589
590
591 std::optional<LIST_ITEM_ITER> findGroupItem( int aGroupNumber )
592 {
593 auto i = std::lower_bound( m_items.begin(), m_items.end(), aGroupNumber,
595
596 if( i == m_items.end() || ( *i )->GetGroupNumber() != aGroupNumber )
597 return std::nullopt;
598
599 return { i };
600 }
601
602
604 wxString groupName, LIST_ITEM::GROUP_TYPE groupType )
605 {
606 LIST_ITEM_ITER group = std::find_if( groupsBegin, groupsEnd,
607 [&]( const std::unique_ptr<LIST_ITEM>& x )
608 {
609 return x->GetGroupName() == groupName
610 && x->GetGroupType() == groupType;
611 } );
612
613 if( group == groupsEnd )
614 {
615 int dist = std::distance( groupsBegin, groupsEnd );
616 std::unique_ptr<LIST_ITEM> groupItem = std::make_unique<LIST_ITEM>( dist, groupName, groupType );
617
618 group = m_items.insert( groupsEnd, std::move( groupItem ) );
619 ItemAdded( wxDataViewItem( ( *group )->Parent() ), wxDataViewItem( ( *group ).get() ) );
620 }
621
622 return ( *group ).get();
623 }
624
625
626 std::optional<LIST_ITEM_ITER> addItem( std::unique_ptr<LIST_ITEM> aItem )
627 {
628 if( aItem == nullptr )
629 return {};
630
631 bool groupMatched = false;
632
633 // First see if item matches a group-by rule
634 if( m_parent.m_custom_group_rules.size() > 0 )
635 {
636 wxString searchName = aItem->GetNetName();
637
638 for( const std::unique_ptr<EDA_COMBINED_MATCHER>& rule : m_parent.m_custom_group_rules )
639 {
640 if( rule->Find( searchName ) )
641 {
642 aItem->SetParent( m_custom_group_map[ rule->GetPattern() ] );
643 groupMatched = true;
644 break;
645 }
646 }
647 }
648
649 // Then add any netclass groups required by this item
650 if( m_parent.m_groupByNetclass && !groupMatched )
651 {
652 LIST_ITEM_ITER groups_begin = m_items.begin();
653 LIST_ITEM_ITER groups_end = std::find_if_not( m_items.begin(), m_items.end(),
654 []( const std::unique_ptr<LIST_ITEM>& x )
655 {
656 return x->GetIsGroup();
657 } );
658
659 wxString match_str = aItem->GetNetclassName();
660 LIST_ITEM* group = addGroup( groups_begin, groups_end, match_str,
662 aItem->SetParent( group );
663 }
664
665 // Now add the item itself. Usually when new nets are added,
666 // they always get a higher netcode number than the already existing ones.
667 // however, if we've got filtering enabled, we might not have all the nets in
668 // our list, so do a sorted insertion.
669 auto new_iter = std::lower_bound( m_items.begin(), m_items.end(), aItem->GetNetCode(),
671
672 new_iter = m_items.insert( new_iter, std::move( aItem ) );
673 const std::unique_ptr<LIST_ITEM>& new_item = *new_iter;
674
675 ItemAdded( wxDataViewItem( new_item->Parent() ), wxDataViewItem( new_item.get() ) );
676
677 return { new_iter };
678 }
679
680 void addItems( std::vector<std::unique_ptr<LIST_ITEM>>& aItems )
681 {
682 m_items.reserve( m_items.size() + aItems.size() );
683
684 for( std::unique_ptr<LIST_ITEM>& i : aItems )
685 addItem( std::move( i ) );
686 }
687
688 std::unique_ptr<LIST_ITEM> deleteItem( const std::optional<LIST_ITEM_ITER>& aRow )
689 {
690 if( !aRow )
691 return {};
692
693 std::unique_ptr<LIST_ITEM> i = std::move( **aRow );
694
695 LIST_ITEM* parent = i->Parent();
696 i->SetParent( nullptr );
697
698 m_items.erase( *aRow );
699 ItemDeleted( wxDataViewItem( parent ), wxDataViewItem( &*i ) );
700
701 if( parent )
702 {
703 ItemChanged( wxDataViewItem( parent ) );
704
705 if( m_parent.m_groupByNetclass && parent != nullptr && parent->ChildrenCount() == 0 )
706 {
707 auto p = std::find_if( m_items.begin(), m_items.end(),
708 [&]( std::unique_ptr<LIST_ITEM>& x )
709 {
710 return x.get() == parent;
711 } );
712
713 wxASSERT( p != m_items.end() );
714 m_items.erase( p );
715
716 ItemDeleted( wxDataViewItem( parent->Parent() ), wxDataViewItem( parent ) );
717 }
718 }
719
720 Resort();
721 return i;
722 }
723
724
731 {
732 m_custom_group_map.clear();
733 int groupId = 0;
734
735 for( const std::unique_ptr<EDA_COMBINED_MATCHER>& rule : m_parent.m_custom_group_rules )
736 {
737 std::unique_ptr<LIST_ITEM>& group = m_items.emplace_back( std::make_unique<LIST_ITEM>(
738 groupId, rule->GetPattern(), LIST_ITEM::GROUP_TYPE::USER_DEFINED ) );
739 m_custom_group_map[ rule->GetPattern() ] = group.get();
740 group->SetLayerCount( m_parent.m_board->GetCopperLayerCount() );
741 ItemAdded( wxDataViewItem( group->Parent() ), wxDataViewItem( group.get() ) );
742 ++groupId;
743 }
744 }
745
746
748 {
749 BeforeReset();
750 m_items.clear();
751 AfterReset();
752 }
753
754 void updateItem( const std::optional<LIST_ITEM_ITER>& aRow )
755 {
756 if( aRow )
757 {
758 const std::unique_ptr<LIST_ITEM>& listItem = *aRow.value();
759
760 if( listItem->Parent() )
761 ItemChanged( wxDataViewItem( listItem->Parent() ) );
762
763 ItemChanged( wxDataViewItem( listItem.get() ) );
764 resortIfChanged( listItem.get() );
765 }
766 }
767
769 {
770 for( std::unique_ptr<LIST_ITEM>& i : m_items )
771 ItemChanged( wxDataViewItem( i.get() ) );
772 }
773
775 {
776 if( wxDataViewColumn* column = m_parent.m_netsList->GetSortingColumn() )
777 {
778 bool changed = false;
779
780 for( const LIST_ITEM* i = aItem; i != nullptr; i = i->Parent() )
781 changed |= itemColumnChanged( i, column->GetModelColumn() );
782
783 for( LIST_ITEM* i = aItem; i != nullptr; i = i->Parent() )
784 i->ResetColumnChangedBits();
785
786 if( changed )
787 Resort();
788 }
789 }
790
791 bool itemColumnChanged( const LIST_ITEM* aItem, unsigned int aCol ) const
792 {
793 if( aItem == nullptr || aCol >= m_parent.m_columns.size() )
794 return false;
795
796 if( aCol == COLUMN_PAD_COUNT )
797 return aItem->PadCountChanged();
798
799 else if( aCol == COLUMN_VIA_COUNT )
800 return aItem->ViaCountChanged();
801
802 else if( aCol == COLUMN_VIA_LENGTH )
803 return aItem->ViaLengthChanged();
804
805 else if( aCol == COLUMN_BOARD_LENGTH )
806 return aItem->BoardWireLengthChanged();
807
808 else if( aCol == COLUMN_PAD_DIE_LENGTH )
809 return aItem->PadDieLengthChanged();
810
811 else if( aCol == COLUMN_TOTAL_LENGTH )
812 return aItem->TotalLengthChanged();
813
814 else if( aCol > COLUMN_LAST_STATIC_COL )
815 return aItem->BoardWireLengthChanged();
816
817
818 return false;
819 }
820
821 void SetIsTimeDomain( const bool aIsTimeDomain ) { m_show_time_domain_details = aIsTimeDomain; }
822
823 // implementation of wxDataViewModel interface
824 // these are used to query the data model by the GUI view implementation.
825 // these are not supposed to be used to modify the data model. for that
826 // use the public functions above.
827
828protected:
829 unsigned int GetColumnCount() const override { return columnCount(); }
830
831 void GetValue( wxVariant& aOutValue, const wxDataViewItem& aItem,
832 unsigned int aCol ) const override
833 {
834 if( LIST_ITEM* i = static_cast<LIST_ITEM*>( aItem.GetID() ) )
835 {
836 if( aCol == COLUMN_NAME )
837 {
838 if( i->GetIsGroup() )
839 {
840 switch( i->GetGroupType() )
841 {
843 aOutValue = _( "Netclass" ) + ": " + i->GetGroupName();
844 break;
846 aOutValue = _( "Custom" ) + ": " + i->GetGroupName();
847 break;
848 default:
849 aOutValue = i->GetGroupName();
850 break;
851 }
852 }
853 else
854 {
855 aOutValue = i->GetNetName();
856 }
857 }
858
859 else if( aCol == COLUMN_NETCLASS )
860 aOutValue = i->GetNetclassName();
861
862 else if( aCol == COLUMN_PAD_COUNT )
863 aOutValue = m_parent.formatCount( i->GetPadCount() );
864
865 else if( aCol == COLUMN_VIA_COUNT )
866 aOutValue = m_parent.formatCount( i->GetViaCount() );
867
868 else if( aCol == COLUMN_VIA_LENGTH )
869 {
871 aOutValue = m_parent.formatDelay( i->GetViaDelay() );
872 else
873 aOutValue = m_parent.formatLength( i->GetViaLength() );
874 }
875
876 else if( aCol == COLUMN_BOARD_LENGTH )
877 {
879 aOutValue = m_parent.formatDelay( i->GetBoardWireDelay() );
880 else
881 aOutValue = m_parent.formatLength( i->GetBoardWireLength() );
882 }
883
884 else if( aCol == COLUMN_PAD_DIE_LENGTH )
885 {
887 aOutValue = m_parent.formatDelay( i->GetPadDieDelay() );
888 else
889 aOutValue = m_parent.formatLength( i->GetPadDieLength() );
890 }
891
892 else if( aCol == COLUMN_TOTAL_LENGTH )
893 {
895 aOutValue = m_parent.formatDelay( i->GetTotalDelay() );
896 else
897 aOutValue = m_parent.formatLength( i->GetTotalLength() );
898 }
899
900 else if( aCol > COLUMN_LAST_STATIC_COL && aCol <= m_parent.m_columns.size() )
901 {
903 aOutValue = m_parent.formatDelay( i->GetLayerWireDelay( m_parent.m_columns[aCol].layer ) );
904 else
905 aOutValue = m_parent.formatLength( i->GetLayerWireLength( m_parent.m_columns[aCol].layer ) );
906 }
907
908 else
909 aOutValue = "";
910 }
911 }
912
913 static int compareUInt( int64_t aValue1, int64_t aValue2, bool aAsc )
914 {
915 if( aAsc )
916 return aValue1 < aValue2 ? -1 : 1;
917 else
918 return aValue2 < aValue1 ? -1 : 1;
919 }
920
921 int Compare( const wxDataViewItem& aItem1, const wxDataViewItem& aItem2, unsigned int aCol,
922 bool aAsc ) const override
923 {
924 const LIST_ITEM& i1 = *static_cast<const LIST_ITEM*>( aItem1.GetID() );
925 const LIST_ITEM& i2 = *static_cast<const LIST_ITEM*>( aItem2.GetID() );
926
927 if( i1.GetIsGroup() && !i2.GetIsGroup() )
928 return -1;
929
930 if( i2.GetIsGroup() && !i1.GetIsGroup() )
931 return 1;
932
933 if( aCol == COLUMN_NAME )
934 {
935 const wxString& s1 = i1.GetNetName();
936 const wxString& s2 = i2.GetNetName();
937
938 int res = aAsc ? ValueStringCompare( s1, s2 ) : ValueStringCompare( s2, s1 );
939
940 if( res != 0 )
941 return res;
942 }
943
944 else if( aCol == COLUMN_PAD_COUNT && i1.GetPadCount() != i2.GetPadCount() )
945 return compareUInt( i1.GetPadCount(), i2.GetPadCount(), aAsc );
946
947 else if( aCol == COLUMN_VIA_COUNT && i1.GetViaCount() != i2.GetViaCount() )
948 return compareUInt( i1.GetViaCount(), i2.GetViaCount(), aAsc );
949
950 else if( aCol == COLUMN_VIA_LENGTH )
951 {
953 return compareUInt( i1.GetViaDelay(), i2.GetViaDelay(), aAsc );
954
956 return compareUInt( i1.GetViaLength(), i2.GetViaLength(), aAsc );
957 }
958
959 else if( aCol == COLUMN_BOARD_LENGTH )
960 {
962 return compareUInt( i1.GetBoardWireDelay(), i2.GetBoardWireDelay(), aAsc );
963
965 return compareUInt( i1.GetBoardWireLength(), i2.GetBoardWireLength(), aAsc );
966 }
967
968 else if( aCol == COLUMN_PAD_DIE_LENGTH )
969 {
971 return compareUInt( i1.GetPadDieDelay(), i2.GetPadDieDelay(), aAsc );
972
974 return compareUInt( i1.GetPadDieLength(), i2.GetPadDieLength(), aAsc );
975 }
976
977 else if( aCol == COLUMN_TOTAL_LENGTH )
978 {
980 return compareUInt( i1.GetTotalDelay(), i2.GetTotalDelay(), aAsc );
981
983 return compareUInt( i1.GetTotalLength(), i2.GetTotalLength(), aAsc );
984 }
985
986 else if( aCol > COLUMN_LAST_STATIC_COL && aCol < m_parent.m_columns.size() )
987 {
989 && i1.GetLayerWireDelay( m_parent.m_columns[aCol].layer )
990 != i2.GetLayerWireDelay( m_parent.m_columns[aCol].layer ) )
991 {
992 return compareUInt( i1.GetLayerWireDelay( m_parent.m_columns[aCol].layer ),
993 i2.GetLayerWireDelay( m_parent.m_columns[aCol].layer ), aAsc );
994 }
995
997 && i1.GetLayerWireLength( m_parent.m_columns[aCol].layer )
998 != i2.GetLayerWireLength( m_parent.m_columns[aCol].layer ) )
999 {
1000 return compareUInt( i1.GetLayerWireLength( m_parent.m_columns[aCol].layer ),
1001 i2.GetLayerWireLength( m_parent.m_columns[aCol].layer ), aAsc );
1002 }
1003 }
1004
1005 // when the item values compare equal resort to pointer comparison.
1006 wxUIntPtr id1 = wxPtrToUInt( aItem1.GetID() );
1007 wxUIntPtr id2 = wxPtrToUInt( aItem2.GetID() );
1008
1009 return aAsc ? id1 - id2 : id2 - id1;
1010 }
1011
1012 bool SetValue( const wxVariant& aInValue, const wxDataViewItem& aItem,
1013 unsigned int aCol ) override
1014 {
1015 return false;
1016 }
1017
1018 wxDataViewItem GetParent( const wxDataViewItem& aItem ) const override
1019 {
1020 if( !aItem.IsOk() )
1021 return wxDataViewItem();
1022
1023 return wxDataViewItem( static_cast<const LIST_ITEM*>( aItem.GetID() )->Parent() );
1024 }
1025
1026 bool IsContainer( const wxDataViewItem& aItem ) const override
1027 {
1028 if( !aItem.IsOk() )
1029 return true;
1030
1031 return static_cast<const LIST_ITEM*>( aItem.GetID() )->GetIsGroup();
1032 }
1033
1034 bool HasContainerColumns( const wxDataViewItem& aItem ) const override
1035 {
1036 return IsContainer( aItem );
1037 }
1038
1039 unsigned int GetChildren( const wxDataViewItem& aParent,
1040 wxDataViewItemArray& aChildren ) const override
1041 {
1042 const LIST_ITEM* p = static_cast<const LIST_ITEM*>( aParent.GetID() );
1043
1044 if( !aParent.IsOk() )
1045 {
1046 aChildren.Alloc( m_items.size() );
1047
1048 for( const std::unique_ptr<LIST_ITEM>& i : m_items )
1049 {
1050 if( i->Parent() == nullptr )
1051 aChildren.Add( wxDataViewItem( &*i ) );
1052 }
1053
1054 return aChildren.GetCount();
1055 }
1056 else if( p->GetIsGroup() )
1057 {
1058 const int count = p->ChildrenCount();
1059
1060 if( count == 0 )
1061 return 0;
1062
1063 aChildren.Alloc( count );
1064
1065 for( auto i = p->ChildrenBegin(), end = p->ChildrenEnd(); i != end; ++i )
1066 aChildren.Add( wxDataViewItem( *i ) );
1067
1068 return aChildren.GetCount();
1069 }
1070
1071 return 0;
1072 }
1073
1074 wxString GetColumnType( unsigned int /* aCol */ ) const override { return wxS( "string" ); }
1075
1076private:
1078
1079 // primary container, sorted by netcode number.
1080 // groups have netcode < 0, so they always come first, in the order
1081 // of the filter strings as input by the user
1082 std::vector<std::unique_ptr<LIST_ITEM>> m_items;
1083
1085 std::map<wxString, LIST_ITEM*> m_custom_group_map;
1086
1088};
1089
1090#endif
const wxString GetHumanReadableName() const
Gets the consolidated name of this netclass (which may be an aggregate).
Definition netclass.cpp:288
Handle the data for a net.
Definition netinfo.h:54
const wxString & GetNetname() const
Definition netinfo.h:112
NETCLASS * GetNetClass()
Definition netinfo.h:99
int GetNetCode() const
Definition netinfo.h:106
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
static int compareUInt(int64_t aValue1, int64_t aValue2, bool aAsc)
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 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)
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
void addItems(std::vector< std::unique_ptr< LIST_ITEM > > &aItems)
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 * 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)
std::map< PCB_LAYER_ID, int64_t > m_layer_wire_length
void AddLayerWireDelay(const int64_t aValue, PCB_LAYER_ID aLayer)
void SetLayerWireLengths(const std::map< PCB_LAYER_ID, int64_t > &aValue)
void AddLayerWireLength(const int64_t aValue, PCB_LAYER_ID aLayer)
std::map< PCB_LAYER_ID, int64_t > m_layer_wire_delay
LIST_ITEM & operator=(const LIST_ITEM &)=delete
int64_t GetLayerWireDelay(PCB_LAYER_ID aLayer) const
std::map< PCB_LAYER_ID, int64_t > GetLayerWireDelays() const
std::map< PCB_LAYER_ID, int64_t > GetLayerWireLengths() const
int64_t GetLayerWireLength(PCB_LAYER_ID aLayer) const
void SetLayerWireLength(const int64_t aValue, PCB_LAYER_ID aLayer)
void SubLayerWireDelay(const int64_t aValue, PCB_LAYER_ID aLayer)
void SetLayerWireDelays(const std::map< PCB_LAYER_ID, int64_t > &aValue)
void SubLayerWireLength(const int64_t aValue, PCB_LAYER_ID aLayer)
PCB_NET_INSPECTOR_PANEL(wxWindow *parent, PCB_EDIT_FRAME *aFrame)
std::vector< std::unique_ptr< LIST_ITEM > >::iterator LIST_ITEM_ITER
#define _(s)
Abstract pattern-matching tool and implementations.
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
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
VECTOR2I end