KiCad PCB EDA Suite
Loading...
Searching...
No Matches
rc_item.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
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20
21#include <wx/wupdlock.h>
22#include <wx/dataview.h>
23#include <wx/settings.h>
24#include <widgets/ui_common.h>
26#include <marker_base.h>
27#include <eda_draw_frame.h>
28#include <rc_item.h>
29#include <rc_json_schema.h>
30#include <eda_item.h>
31#include <base_units.h>
32#include <units_provider.h>
33
34#define WX_DATAVIEW_WINDOW_PADDING 6
35
36
37wxString RC_ITEM::GetErrorMessage( bool aTranslate ) const
38{
39 if( m_errorMessage.IsEmpty() )
40 return GetErrorText( aTranslate );
41 else
42 return m_errorMessage;
43}
44
45
46static wxString showCoord( UNITS_PROVIDER* aUnitsProvider, const VECTOR2I& aPos )
47{
48 return wxString::Format( wxT( "@(%s, %s)" ),
49 aUnitsProvider->MessageTextFromValue( aPos.x ),
50 aUnitsProvider->MessageTextFromValue( aPos.y ) );
51}
52
53
55{
56 m_ids.push_back( aItem->m_Uuid );
57}
58
59
60void RC_ITEM::SetItems( const EDA_ITEM* aItem, const EDA_ITEM* bItem,
61 const EDA_ITEM* cItem, const EDA_ITEM* dItem )
62{
63 m_ids.clear();
64
65 if( aItem )
66 m_ids.push_back( aItem->m_Uuid );
67
68 if( bItem )
69 m_ids.push_back( bItem->m_Uuid );
70
71 if( cItem )
72 m_ids.push_back( cItem->m_Uuid );
73
74 if( dItem )
75 m_ids.push_back( dItem->m_Uuid );
76}
77
78
79wxString RC_ITEM::getItemDescription( EDA_ITEM* aItem, int /*aIndex*/,
80 UNITS_PROVIDER* aUnitsProvider ) const
81{
82 return aItem->GetItemDescription( aUnitsProvider, true );
83}
84
85
87{
88 wxString severity;
89
90 switch( aSeverity )
91 {
92 case RPT_SEVERITY_ERROR: severity = wxS( "error" ); break;
93 case RPT_SEVERITY_WARNING: severity = wxS( "warning" ); break;
94 case RPT_SEVERITY_ACTION: severity = wxS( "action" ); break;
95 case RPT_SEVERITY_INFO: severity = wxS( "info" ); break;
96 case RPT_SEVERITY_EXCLUSION: severity = wxS( "exclusion" ); break;
97 case RPT_SEVERITY_DEBUG: severity = wxS( "debug" ); break;
98 default:;
99 };
100
101 return severity;
102}
103
104
105wxString RC_ITEM::ShowReport( UNITS_PROVIDER* aUnitsProvider, SEVERITY aSeverity,
106 const std::map<KIID, EDA_ITEM*>& aItemMap ) const
107{
108 wxString severity = getSeverityString( aSeverity );
109 bool excluded = m_parent && m_parent->IsTreatedAsExcluded();
110
111 if( excluded )
112 severity += wxT( " (excluded)" );
113
114 EDA_ITEM* mainItem = nullptr;
115 EDA_ITEM* auxItem = nullptr;
116
117 auto ii = aItemMap.find( GetMainItemID() );
118
119 if( ii != aItemMap.end() )
120 mainItem = ii->second;
121
122 ii = aItemMap.find( GetAuxItemID() );
123
124 if( ii != aItemMap.end() )
125 auxItem = ii->second;
126
127 wxString errorMessage = HYPERLINK_DV_RENDERER::StripMarkup( GetErrorMessage( false ) );
128 wxString ruleDesc = HYPERLINK_DV_RENDERER::StripMarkup( GetViolatingRuleDesc( false ) );
129
130 // Note: some customers machine-process these. So:
131 // 1) don't translate
132 // 2) try not to re-order or change syntax
133 // 3) report settings key (which should be more stable) in addition to message
134
135 wxString msg;
136
137 if( mainItem && auxItem )
138 {
139 msg.Printf( wxT( "[%s]: %s\n %s; %s\n %s: %s\n %s: %s\n" ), GetSettingsKey(), errorMessage, ruleDesc,
140 severity, showCoord( aUnitsProvider, mainItem->GetPosition() ),
141 getItemDescription( mainItem, 0, aUnitsProvider ),
142 showCoord( aUnitsProvider, auxItem->GetPosition() ),
143 getItemDescription( auxItem, 1, aUnitsProvider ) );
144 }
145 else if( mainItem )
146 {
147 msg.Printf( wxT( "[%s]: %s\n %s; %s\n %s: %s\n" ), GetSettingsKey(), errorMessage, ruleDesc, severity,
148 showCoord( aUnitsProvider, mainItem->GetPosition() ),
149 getItemDescription( mainItem, 0, aUnitsProvider ) );
150 }
151 else
152 {
153 msg.Printf( wxT( "[%s]: %s\n %s; %s\n" ), GetSettingsKey(), errorMessage, ruleDesc, severity );
154 }
155
156 if( excluded && m_parent && !m_parent->GetComment().IsEmpty() )
157 msg += wxString::Format( wxS( " %s\n" ), m_parent->GetComment() );
158
159 return msg;
160}
161
162
164 SEVERITY aSeverity, const std::map<KIID, EDA_ITEM*>& aItemMap ) const
165{
166 aViolation.severity = getSeverityString( aSeverity );
168 aViolation.type = GetSettingsKey();
169
170 if( m_parent && m_parent->IsTreatedAsExcluded() )
171 {
172 aViolation.excluded = true;
173 aViolation.comment = m_parent->GetComment();
174 }
175 else
176 {
177 aViolation.excluded = false;
178 }
179
180 EDA_ITEM* mainItem = nullptr;
181 EDA_ITEM* auxItem = nullptr;
182
183 auto ii = aItemMap.find( GetMainItemID() );
184
185 if( ii != aItemMap.end() )
186 mainItem = ii->second;
187
188 ii = aItemMap.find( GetAuxItemID() );
189
190 if( ii != aItemMap.end() )
191 auxItem = ii->second;
192
193 if( mainItem )
194 {
196 item.description = getItemDescription( mainItem, 0, aUnitsProvider );
197 item.uuid = mainItem->m_Uuid.AsString();
198 item.pos.x = EDA_UNIT_UTILS::UI::ToUserUnit( aUnitsProvider->GetIuScale(),
199 aUnitsProvider->GetUserUnits(),
200 mainItem->GetPosition().x );
201 item.pos.y = EDA_UNIT_UTILS::UI::ToUserUnit( aUnitsProvider->GetIuScale(),
202 aUnitsProvider->GetUserUnits(),
203 mainItem->GetPosition().y );
204 aViolation.items.emplace_back( item );
205 }
206
207 if( auxItem )
208 {
210 item.description = getItemDescription( auxItem, 1, aUnitsProvider );
211 item.uuid = auxItem->m_Uuid.AsString();
212 item.pos.x = EDA_UNIT_UTILS::UI::ToUserUnit( aUnitsProvider->GetIuScale(),
213 aUnitsProvider->GetUserUnits(),
214 auxItem->GetPosition().x );
215 item.pos.y = EDA_UNIT_UTILS::UI::ToUserUnit( aUnitsProvider->GetIuScale(),
216 aUnitsProvider->GetUserUnits(),
217 auxItem->GetPosition().y );
218 aViolation.items.emplace_back( item );
219 }
220}
221
222
223KIID RC_TREE_MODEL::ToUUID( wxDataViewItem aItem )
224{
225 const RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aItem );
226
227 if( node && node->m_RcItem )
228 {
229 const std::shared_ptr<RC_ITEM> rc_item = node->m_RcItem;
230
231 switch( node->m_Type )
232 {
235 // rc_item->GetParent() can be null, if the parent is not existing
236 // when a RC item has no corresponding ERC/DRC marker
237 if( rc_item->GetParent() )
238 return rc_item->GetParent()->GetUUID();
239
240 break;
241
242 case RC_TREE_NODE::MAIN_ITEM: return rc_item->GetMainItemID();
243 case RC_TREE_NODE::AUX_ITEM: return rc_item->GetAuxItemID();
244 case RC_TREE_NODE::AUX_ITEM2: return rc_item->GetAuxItem2ID();
245 case RC_TREE_NODE::AUX_ITEM3: return rc_item->GetAuxItem3ID();
246 }
247 }
248
249 return niluuid;
250}
251
252
253RC_TREE_MODEL::RC_TREE_MODEL( EDA_DRAW_FRAME* aParentFrame, wxDataViewCtrl* aView ) :
254 m_editFrame( aParentFrame ),
255 m_view( aView ),
256 m_severities( 0 ),
257 m_rcItemsProvider( nullptr )
258{
259}
260
261
263 const std::shared_ptr<RC_ITEM>& aRcItem,
265{
266 RC_TREE_NODE* node = new RC_TREE_NODE( aParent, aRcItem, aType );
267
268 node->m_Handle = &m_handles.emplace_back();
269 node->m_Handle->m_Node = node;
270
271 return node;
272}
273
274
276{
277 if( !aNode )
278 return;
279
280 if( aNode->m_Handle )
281 aNode->m_Handle->m_Node = nullptr;
282
283 for( RC_TREE_NODE* child : aNode->m_Children )
284 retireNodeTree( child );
285}
286
287
289{
290 if( !aNode )
291 return;
292
293 delete aNode;
294}
295
296
298{
299 for( RC_TREE_NODE* topLevelNode : m_tree )
300 {
301 retireNodeTree( topLevelNode );
302 deleteNodeTree( topLevelNode );
303 }
304
305 m_tree.clear();
306}
307
308
313
314
315void RC_TREE_MODEL::rebuildTree( std::shared_ptr<RC_ITEMS_PROVIDER> aProvider, int aSeverities )
316{
317 m_rcItemsProvider = std::move( aProvider );
318
319 if( aSeverities != m_severities )
320 m_severities = aSeverities;
321
323 m_rcItemsProvider->SetSeverities( m_severities );
324
325 clearTree();
326
327 // wxDataView::ExpandAll() pukes with large lists
328 int count = 0;
329
331 count = std::min( 1000, m_rcItemsProvider->GetCount() );
332
333 for( int i = 0; i < count; ++i )
334 {
335 std::shared_ptr<RC_ITEM> rcItem = m_rcItemsProvider->GetItem( i );
336
337 m_tree.push_back( createNode( nullptr, rcItem, RC_TREE_NODE::MARKER ) );
338 RC_TREE_NODE* n = m_tree.back();
339
340 if( rcItem->GetMainItemID() != niluuid )
341 n->m_Children.push_back( createNode( n, rcItem, RC_TREE_NODE::MAIN_ITEM ) );
342
343 if( rcItem->GetAuxItemID() != niluuid )
344 n->m_Children.push_back( createNode( n, rcItem, RC_TREE_NODE::AUX_ITEM ) );
345
346 if( rcItem->GetAuxItem2ID() != niluuid )
347 n->m_Children.push_back( createNode( n, rcItem, RC_TREE_NODE::AUX_ITEM2 ) );
348
349 if( rcItem->GetAuxItem3ID() != niluuid )
350 n->m_Children.push_back( createNode( n, rcItem, RC_TREE_NODE::AUX_ITEM3 ) );
351
352 if( MARKER_BASE* marker = rcItem->GetParent() )
353 {
354 if( marker->IsExcluded() && !marker->GetComment().IsEmpty() )
355 n->m_Children.push_back( createNode( n, rcItem, RC_TREE_NODE::COMMENT ) );
356 }
357 }
358}
359
360
361void RC_TREE_MODEL::rebuildModel( std::shared_ptr<RC_ITEMS_PROVIDER> aProvider, int aSeverities )
362{
363 wxWindowUpdateLocker updateLock( m_view );
364
365 std::shared_ptr<RC_ITEM> selectedRcItem = nullptr;
366
367 if( m_view )
368 {
369 RC_TREE_NODE* selectedNode = ToNode( m_view->GetSelection() );
370 selectedRcItem = selectedNode ? selectedNode->m_RcItem : nullptr;
371
372 // Even with the updateLock, wxWidgets sometimes ties its knickers in a knot trying
373 // to run a wxdataview_selection_changed_callback() on a row that has been deleted.
374 m_view->UnselectAll();
375 }
376
377 BeforeReset();
378
379 rebuildTree( std::move( aProvider ), aSeverities );
380
381 // Must be called after a significant change of items to force the
382 // wxDataViewModel to reread all of them, repopulating itself entirely.
383 AfterReset();
384
385#ifdef __WXGTK__
386 // The fastest method to update wxDataViewCtrl is to rebuild from
387 // scratch by calling Cleared(). Linux requires to reassociate model to
388 // display data, but Windows will create multiple associations.
389 // On MacOS, this crashes KiCad. See https://gitlab.com/kicad/code/kicad/-/issues/3666
390 // and https://gitlab.com/kicad/code/kicad/-/issues/3653
391 m_view->AssociateModel( this );
392#endif
393
394 if( !m_enableHyperlinks )
395 {
396 m_view->ClearColumns();
397
398 int width = m_view->GetClientSize().GetWidth() - WX_DATAVIEW_WINDOW_PADDING;
399
400 if( width <= 0 )
401 width = 600;
402
403 m_view->AppendTextColumn( wxEmptyString, 0, wxDATAVIEW_CELL_INERT, width );
404 }
405
406 ExpandAll();
407
408 // Most annoyingly wxWidgets won't tell us the scroll position (and no, all the usual
409 // routines don't work), so we can only restore the scroll position based on a selection.
410 if( selectedRcItem )
411 {
412 for( RC_TREE_NODE* candidate : m_tree )
413 {
414 if( candidate->m_RcItem == selectedRcItem )
415 {
416 m_view->Select( ToItem( candidate ) );
417 m_view->EnsureVisible( ToItem( candidate ) );
418 break;
419 }
420 }
421 }
422}
423
424
425void RC_TREE_MODEL::Update( std::shared_ptr<RC_ITEMS_PROVIDER> aProvider, int aSeverities )
426{
427 rebuildModel( aProvider, aSeverities );
428}
429
430
432{
433 m_enableHyperlinks = aEnable;
434
435 if( !aEnable || !m_view || m_view->GetColumnCount() > 0 )
436 return;
437
440 new wxDataViewColumn( wxEmptyString, renderer, 0, std::max( 200, m_view->GetClientSize().GetWidth() ),
441 wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE );
442 m_view->AppendColumn( m_hyperlinkColumn );
443 m_view->Bind( wxEVT_SIZE, &RC_TREE_MODEL::onViewSize, this );
444}
445
446
447void RC_TREE_MODEL::onViewSize( wxSizeEvent& aEvent )
448{
449 aEvent.Skip();
450
452 m_hyperlinkColumn->SetWidth( std::max( 200, m_view->GetClientSize().GetWidth() ) );
453}
454
455
457{
458 for( RC_TREE_NODE* topLevelNode : m_tree )
459 m_view->Expand( ToItem( topLevelNode ) );
460}
461
462
463bool RC_TREE_MODEL::IsContainer( wxDataViewItem const& aItem ) const
464{
465 const RC_TREE_NODE* node = ToNode( aItem );
466
467 if( !aItem.IsOk() ) // tree root
468 return true;
469
470 if( node == nullptr )
471 return false;
472
473 return node->m_Type == RC_TREE_NODE::MARKER;
474}
475
476
477wxDataViewItem RC_TREE_MODEL::GetParent( wxDataViewItem const& aItem ) const
478{
479 const RC_TREE_NODE* node = ToNode( aItem );
480 return node ? ToItem( node->m_Parent ) : wxDataViewItem();
481}
482
483
484unsigned int RC_TREE_MODEL::GetChildren( wxDataViewItem const& aItem,
485 wxDataViewItemArray& aChildren ) const
486{
487 const RC_TREE_NODE* node = ToNode( aItem );
488 const std::vector<RC_TREE_NODE*>& children = node ? node->m_Children : m_tree;
489
490 if( aItem.IsOk() && !node )
491 return 0;
492
493 for( const RC_TREE_NODE* child : children )
494 aChildren.push_back( ToItem( child ) );
495
496 return children.size();
497}
498
499
500void RC_TREE_MODEL::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
501 unsigned int aCol ) const
502{
503 if( !aItem.IsOk() || m_view->IsFrozen() || m_tree.empty() )
504 return;
505
506 const RC_TREE_NODE* node = ToNode( aItem );
507
508 if( !node || !node->m_RcItem )
509 return;
510
511 const std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
512 MARKER_BASE* marker = rcItem->GetParent();
513 EDA_ITEM* item = nullptr;
514 wxString msg;
515
516 switch( node->m_Type )
517 {
519 if( marker )
520 {
521 SEVERITY severity = marker->GetSeverity();
522
523 if( severity == RPT_SEVERITY_EXCLUSION )
524 {
525 if( m_editFrame->GetSeverity( rcItem->GetErrorCode() ) == RPT_SEVERITY_WARNING )
526 msg = _( "Excluded warning: " );
527 else
528 msg = _( "Excluded error: " );
529 }
530 else if( severity == RPT_SEVERITY_WARNING )
531 {
532 msg = _( "Warning: " );
533 }
534 else
535 {
536 msg = _( "Error: " );
537 }
538 }
539
540 msg += rcItem->GetErrorMessage( true );
541 break;
542
544 if( marker && marker->GetMarkerType() == MARKER_BASE::MARKER_DRAWING_SHEET )
545 msg = _( "Drawing Sheet" );
546 else
547 item = m_editFrame->ResolveItem( rcItem->GetMainItemID() );
548
549 break;
550
552 item = m_editFrame->ResolveItem( rcItem->GetAuxItemID() );
553 break;
554
556 item = m_editFrame->ResolveItem( rcItem->GetAuxItem2ID() );
557 break;
558
560 item = m_editFrame->ResolveItem( rcItem->GetAuxItem3ID() );
561 break;
562
564 if( marker )
565 msg = marker->GetComment();
566
567 break;
568 }
569
570 if( item )
571 msg += item->GetItemDescription( m_editFrame, true );
572
573 msg.Replace( wxS( "\n" ), wxS( " " ) );
574 aVariant = msg;
575}
576
577
578bool RC_TREE_MODEL::GetAttr( wxDataViewItem const& aItem,
579 unsigned int aCol,
580 wxDataViewItemAttr& aAttr ) const
581{
582 if( !aItem.IsOk() || m_view->IsFrozen() || m_tree.empty() )
583 return false;
584
585 const RC_TREE_NODE* node = ToNode( aItem );
586
587 if( !node || !node->m_RcItem )
588 return false;
589
590 bool ret = false;
591 bool heading = node->m_Type == RC_TREE_NODE::MARKER;
592
593 if( heading )
594 {
595 aAttr.SetBold( true );
596 ret = true;
597 }
598
599 if( node->m_RcItem->GetParent()
601 {
602 wxColour textColour = wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOXTEXT );
603 double brightness = KIGFX::COLOR4D( textColour ).GetBrightness();
604
605 if( brightness > 0.5 )
606 {
607 int lightness = static_cast<int>( brightness * ( heading ? 50 : 60 ) );
608 aAttr.SetColour( textColour.ChangeLightness( lightness ) );
609 }
610 else
611 {
612 aAttr.SetColour( textColour.ChangeLightness( heading ? 170 : 165 ) );
613 }
614
615 aAttr.SetItalic( true ); // Strikethrough would be better, if wxWidgets supported it
616 ret = true;
617 }
618
619 return ret;
620}
621
622
624{
625 if( aNode->m_Type != RC_TREE_NODE::MARKER )
626 {
627 ValueChanged( aNode->m_Parent );
628 return;
629 }
630
631 wxDataViewItem markerItem = ToItem( aNode );
632
633 wxDataViewModel::ValueChanged( markerItem, 0 );
634
635 for( const RC_TREE_NODE* child : aNode->m_Children )
636 wxDataViewModel::ValueChanged( ToItem( child ), 0 );
637
638 // Comment items can come and go depening on exclusion state and comment content.
639 //
640 const std::shared_ptr<RC_ITEM> rcItem = aNode->m_RcItem;
641 MARKER_BASE* marker = rcItem ? rcItem->GetParent() : nullptr;
642
643 if( marker )
644 {
645 bool needsCommentNode = marker->IsExcluded() && !marker->GetComment().IsEmpty();
646 RC_TREE_NODE* commentNode = aNode->m_Children.empty() ? nullptr : aNode->m_Children.back();
647
648 if( commentNode && commentNode->m_Type != RC_TREE_NODE::COMMENT )
649 commentNode = nullptr;
650
651 if( needsCommentNode && !commentNode )
652 {
653 commentNode = createNode( aNode, rcItem, RC_TREE_NODE::COMMENT );
654 wxDataViewItemArray newItems;
655 newItems.push_back( ToItem( commentNode ) );
656
657 aNode->m_Children.push_back( commentNode );
658 ItemsAdded( markerItem, newItems );
659 }
660 else if( commentNode && !needsCommentNode )
661 {
662 wxDataViewItemArray deletedItems;
663 deletedItems.push_back( ToItem( commentNode ) );
664
665 aNode->m_Children.erase( aNode->m_Children.end() - 1 );
666 retireNodeTree( commentNode );
667 ItemsDeleted( markerItem, deletedItems );
668 deleteNodeTree( commentNode );
669 }
670 }
671}
672
673
675{
676 DeleteItems( true, true, aDeep );
677}
678
679
680void RC_TREE_MODEL::DeleteItems( bool aCurrentOnly, bool aIncludeExclusions, bool aDeep )
681{
682 RC_TREE_NODE* current_node = m_view ? ToNode( m_view->GetCurrentItem() ) : nullptr;
683 const std::shared_ptr<RC_ITEM> current_item = current_node ? current_node->m_RcItem : nullptr;
684
685 std::vector<wxDataViewItem> expanded;
686
687 if( aCurrentOnly && !current_item )
688 {
689 wxBell();
690 return;
691 }
692
693 // wxWidgets 3.1.x on MacOS (at least) loses the expanded state of the tree when deleting
694 // items.
695 if( m_view && aCurrentOnly )
696 {
697 for( RC_TREE_NODE* node : m_tree )
698 {
699 if( m_view->IsExpanded( ToItem( node ) ) )
700 expanded.push_back( ToItem( node ) );
701 }
702 }
703
704 int lastGood = -1;
705 bool itemDeleted = false;
706
707 if( m_view )
708 {
709 m_view->UnselectAll();
710 m_view->Freeze();
711 }
712
713 if( !m_rcItemsProvider )
714 {
715 if( m_view )
716 m_view->Thaw();
717
718 return;
719 }
720
721 for( int i = m_rcItemsProvider->GetCount() - 1; i >= 0; --i )
722 {
723 std::shared_ptr<RC_ITEM> rcItem = m_rcItemsProvider->GetItem( i );
724 MARKER_BASE* marker = rcItem->GetParent();
725 bool excluded = false;
726
727 if( marker && marker->GetSeverity() == RPT_SEVERITY_EXCLUSION )
728 excluded = true;
729
730 if( aCurrentOnly && itemDeleted && lastGood >= 0 )
731 break;
732
733 if( aCurrentOnly && rcItem != current_item )
734 {
735 lastGood = i;
736 continue;
737 }
738
739 if( excluded && !aIncludeExclusions )
740 continue;
741
742 if( i < (int) m_tree.size() ) // Careful; tree is truncated for large datasets
743 {
744 wxDataViewItem markerItem = ToItem( m_tree[i] );
745 wxDataViewItemArray childItems;
746 wxDataViewItem parentItem = ToItem( m_tree[i]->m_Parent );
747
748 for( RC_TREE_NODE* child : m_tree[i]->m_Children )
749 {
750 childItems.push_back( ToItem( child ) );
751 retireNodeTree( child );
752 }
753
754 ItemsDeleted( markerItem, childItems );
755
757 RC_TREE_NODE* deletedNode = m_tree[i];
758 m_tree.erase( m_tree.begin() + i );
759 ItemDeleted( parentItem, markerItem );
760 deleteNodeTree( deletedNode );
761 }
762
763 // Only deep delete the current item here; others will be done by the caller, which
764 // can more efficiently delete all markers on the board.
765 m_rcItemsProvider->DeleteItem( i, aDeep && aCurrentOnly );
766
767 if( lastGood > i )
768 lastGood--;
769
770 itemDeleted = true;
771 }
772
773 if( m_view && aCurrentOnly && lastGood >= 0 )
774 {
775 for( const wxDataViewItem& item : expanded )
776 {
777 if( item.IsOk() )
778 m_view->Expand( item );
779 }
780
781 wxDataViewItem selItem = ToItem( m_tree[ lastGood ] );
782 m_view->Select( selItem );
783
784 // wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED doesn't get propogated from the Select()
785 // call on (at least) MSW.
786 wxDataViewEvent selectEvent( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, m_view, selItem );
787 m_view->GetEventHandler()->ProcessEvent( selectEvent );
788 }
789
790 if( m_view )
791 m_view->Thaw();
792}
793
794
796{
797 RC_TREE_NODE* currentNode = ToNode( m_view->GetCurrentItem() );
798 RC_TREE_NODE* prevMarker = nullptr;
799
800 while( currentNode && currentNode->m_Type != RC_TREE_NODE::MARKER )
801 currentNode = currentNode->m_Parent;
802
803 for( RC_TREE_NODE* candidate : m_tree )
804 {
805 if( candidate == currentNode )
806 break;
807 else
808 prevMarker = candidate;
809 }
810
811 if( prevMarker )
812 m_view->Select( ToItem( prevMarker ) );
813}
814
815
817{
818 RC_TREE_NODE* currentNode = ToNode( m_view->GetCurrentItem() );
819
820 while( currentNode && currentNode->m_Type != RC_TREE_NODE::MARKER )
821 currentNode = currentNode->m_Parent;
822
823 RC_TREE_NODE* nextMarker = nullptr;
824 bool trigger = currentNode == nullptr;
825
826 for( RC_TREE_NODE* candidate : m_tree )
827 {
828 if( candidate == currentNode )
829 {
830 trigger = true;
831 }
832 else if( trigger )
833 {
834 nextMarker = candidate;
835 break;
836 }
837 }
838
839 if( nextMarker )
840 m_view->Select( ToItem( nextMarker ) );
841}
842
843
845{
846 wxCHECK( !m_view->IsFrozen(), /* void */ );
847
848 for( RC_TREE_NODE* candidate : m_tree )
849 {
850 if( candidate->m_RcItem->GetParent() == aMarker )
851 {
852 m_view->Select( ToItem( candidate ) );
853 return;
854 }
855 }
856}
857
858
860{
861 wxCHECK( !m_view->IsFrozen(), /* void */ );
862
863 for( RC_TREE_NODE* candidate : m_tree )
864 {
865 if( candidate->m_RcItem->GetParent() == aMarker )
866 {
867 m_view->EnsureVisible( ToItem( candidate ) );
868 return;
869 }
870 }
871}
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
virtual VECTOR2I GetPosition() const
Definition eda_item.h:348
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
Definition eda_item.cpp:304
const KIID m_Uuid
Definition eda_item.h:597
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
double GetBrightness() const
Returns the brightness value of the color ranged from 0.0 to 1.0.
Definition color4d.h:330
Definition kiid.h:46
wxString AsString() const
Definition kiid.cpp:264
Marker are mainly used to show a DRC or ERC error or warning.
Definition marker_base.h:45
virtual SEVERITY GetSeverity() const
Definition marker_base.h:98
bool IsExcluded() const
Definition marker_base.h:89
@ MARKER_DRAWING_SHEET
Definition marker_base.h:52
enum MARKER_T GetMarkerType() const
Definition marker_base.h:87
wxString GetComment() const
Definition marker_base.h:96
wxString GetErrorText(bool aTranslate) const
Definition rc_item.h:171
virtual void GetJsonViolation(RC_JSON::VIOLATION &aViolation, UNITS_PROVIDER *aUnitsProvider, SEVERITY aSeverity, const std::map< KIID, EDA_ITEM * > &aItemMap) const
Translate this object into an RC_JSON::VIOLATION object.
Definition rc_item.cpp:163
static wxString getSeverityString(SEVERITY aSeverity)
Definition rc_item.cpp:86
virtual wxString GetViolatingRuleDesc(bool aTranslate) const
Definition rc_item.h:184
MARKER_BASE * GetParent() const
Definition rc_item.h:134
void AddItem(EDA_ITEM *aItem)
Definition rc_item.cpp:54
MARKER_BASE * m_parent
The marker this item belongs to, if any.
Definition rc_item.h:208
KIIDS m_ids
Definition rc_item.h:210
virtual KIID GetMainItemID() const
Definition rc_item.h:126
virtual KIID GetAuxItemID() const
Definition rc_item.h:127
virtual wxString ShowReport(UNITS_PROVIDER *aUnitsProvider, SEVERITY aSeverity, const std::map< KIID, EDA_ITEM * > &aItemMap) const
Translate this object into a text string suitable for saving to disk in a report.
Definition rc_item.cpp:105
wxString m_errorMessage
A message describing the details of this specific error.
Definition rc_item.h:205
wxString GetSettingsKey() const
Definition rc_item.h:179
virtual wxString GetErrorMessage(bool aTranslate) const
Definition rc_item.cpp:37
virtual wxString getItemDescription(EDA_ITEM *aItem, int aIndex, UNITS_PROVIDER *aUnitsProvider) const
Resolve the description string used for an affected item in ShowReport and GetJsonViolation.
Definition rc_item.cpp:79
void SetItems(const KIIDS &aIds)
Definition rc_item.h:108
void ExpandAll()
Definition rc_item.cpp:456
std::deque< RC_TREE_NODE::HANDLE > m_handles
Stable wx item IDs.
Definition rc_item.h:379
void PrevMarker()
Definition rc_item.cpp:795
int m_severities
Definition rc_item.h:371
void onViewSize(wxSizeEvent &aEvent)
Definition rc_item.cpp:447
wxDataViewColumn * m_hyperlinkColumn
Definition rc_item.h:373
void GetValue(wxVariant &aVariant, wxDataViewItem const &aItem, unsigned int aCol) const override
Called by the wxDataView to fetch an item's value.
Definition rc_item.cpp:500
std::vector< RC_TREE_NODE * > m_tree
Definition rc_item.h:380
unsigned int GetChildren(wxDataViewItem const &aItem, wxDataViewItemArray &aChildren) const override
Definition rc_item.cpp:484
EDA_DRAW_FRAME * m_editFrame
Definition rc_item.h:369
void retireNodeTree(RC_TREE_NODE *aNode)
Definition rc_item.cpp:275
static wxDataViewItem ToItem(RC_TREE_NODE const *aNode)
Definition rc_item.h:262
void rebuildTree(std::shared_ptr< RC_ITEMS_PROVIDER > aProvider, int aSeverities)
Repopulate the node tree from aProvider.
Definition rc_item.cpp:315
bool m_enableHyperlinks
Definition rc_item.h:372
void clearTree()
Retire and destroy every node in the tree.
Definition rc_item.cpp:297
void SelectMarker(const MARKER_BASE *aMarker)
Definition rc_item.cpp:844
RC_TREE_MODEL(EDA_DRAW_FRAME *aParentFrame, wxDataViewCtrl *aView)
Definition rc_item.cpp:253
void deleteNodeTree(RC_TREE_NODE *aNode)
Definition rc_item.cpp:288
static RC_TREE_NODE * ToNode(wxDataViewItem aItem)
Definition rc_item.h:267
void ValueChanged(RC_TREE_NODE *aNode)
Definition rc_item.cpp:623
void Update(std::shared_ptr< RC_ITEMS_PROVIDER > aProvider, int aSeverities)
Definition rc_item.cpp:425
bool GetAttr(wxDataViewItem const &aItem, unsigned int aCol, wxDataViewItemAttr &aAttr) const override
Called by the wxDataView to fetch an item's formatting.
Definition rc_item.cpp:578
void DeleteItems(bool aCurrentOnly, bool aIncludeExclusions, bool aDeep)
Delete the current item or all items.
Definition rc_item.cpp:680
RC_TREE_NODE * createNode(RC_TREE_NODE *aParent, const std::shared_ptr< RC_ITEM > &aRcItem, RC_TREE_NODE::NODE_TYPE aType)
Definition rc_item.cpp:262
void DeleteCurrentItem(bool aDeep)
Definition rc_item.cpp:674
wxDataViewItem GetParent(wxDataViewItem const &aItem) const override
Definition rc_item.cpp:477
void CenterMarker(const MARKER_BASE *aMarker)
Definition rc_item.cpp:859
void EnableHyperlinks(bool aEnable)
Render [label](url) markup as clickable links.
Definition rc_item.cpp:431
static KIID ToUUID(wxDataViewItem aItem)
Definition rc_item.cpp:223
wxDataViewCtrl * m_view
Definition rc_item.h:370
std::shared_ptr< RC_ITEMS_PROVIDER > m_rcItemsProvider
Definition rc_item.h:374
void NextMarker()
Definition rc_item.cpp:816
bool IsContainer(wxDataViewItem const &aItem) const override
Definition rc_item.cpp:463
void rebuildModel(std::shared_ptr< RC_ITEMS_PROVIDER > aProvider, int aSeverities)
Definition rc_item.cpp:361
std::shared_ptr< RC_ITEM > m_RcItem
Definition rc_item.h:251
RC_TREE_NODE * m_Parent
Definition rc_item.h:254
std::vector< RC_TREE_NODE * > m_Children
Definition rc_item.h:255
HANDLE * m_Handle
Definition rc_item.h:253
NODE_TYPE m_Type
Definition rc_item.h:250
const EDA_IU_SCALE & GetIuScale() const
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
#define _(s)
KIID niluuid(0)
KICOMMON_API double ToUserUnit(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnit, double aValue)
Convert aValue in internal units to the appropriate user units defined by aUnit.
static wxString showCoord(UNITS_PROVIDER *aUnitsProvider, const VECTOR2I &aPos)
Definition rc_item.cpp:46
#define WX_DATAVIEW_WINDOW_PADDING
Definition rc_item.cpp:34
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_EXCLUSION
@ RPT_SEVERITY_DEBUG
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
std::vector< AFFECTED_ITEM > items
RC_TREE_NODE * m_Node
Definition rc_item.h:246
Functions to provide common constants and other functions to assist in making a consistent UI.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683