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 m_handles.push_back( std::make_unique<RC_TREE_NODE::HANDLE>() );
269 node->m_Handle = m_handles.back().get();
270 node->m_Handle->m_Node = node;
271
272 return node;
273}
274
275
277{
278 if( !aNode )
279 return;
280
281 if( aNode->m_Handle )
282 aNode->m_Handle->m_Node = nullptr;
283
284 for( RC_TREE_NODE* child : aNode->m_Children )
285 retireNodeTree( child );
286}
287
288
290{
291 if( !aNode )
292 return;
293
294 delete aNode;
295}
296
297
299{
300 for( RC_TREE_NODE* topLevelNode : m_tree )
301 {
302 retireNodeTree( topLevelNode );
303 deleteNodeTree( topLevelNode );
304 }
305}
306
307
308void RC_TREE_MODEL::rebuildModel( std::shared_ptr<RC_ITEMS_PROVIDER> aProvider, int aSeverities )
309{
310 wxWindowUpdateLocker updateLock( m_view );
311
312 std::shared_ptr<RC_ITEM> selectedRcItem = nullptr;
313
314 if( m_view )
315 {
316 RC_TREE_NODE* selectedNode = ToNode( m_view->GetSelection() );
317 selectedRcItem = selectedNode ? selectedNode->m_RcItem : nullptr;
318
319 // Even with the updateLock, wxWidgets sometimes ties its knickers in a knot trying
320 // to run a wxdataview_selection_changed_callback() on a row that has been deleted.
321 m_view->UnselectAll();
322 }
323
324 BeforeReset();
325
326 m_rcItemsProvider = std::move( aProvider );
327
328 if( aSeverities != m_severities )
329 m_severities = aSeverities;
330
332 m_rcItemsProvider->SetSeverities( m_severities );
333
334 for( RC_TREE_NODE* topLevelNode : m_tree )
335 {
336 retireNodeTree( topLevelNode );
337 deleteNodeTree( topLevelNode );
338 }
339
340 m_tree.clear();
341 m_handles.clear();
342
343 // wxDataView::ExpandAll() pukes with large lists
344 int count = 0;
345
347 count = std::min( 1000, m_rcItemsProvider->GetCount() );
348
349 for( int i = 0; i < count; ++i )
350 {
351 std::shared_ptr<RC_ITEM> rcItem = m_rcItemsProvider->GetItem( i );
352
353 m_tree.push_back( createNode( nullptr, rcItem, RC_TREE_NODE::MARKER ) );
354 RC_TREE_NODE* n = m_tree.back();
355
356 if( rcItem->GetMainItemID() != niluuid )
357 n->m_Children.push_back( createNode( n, rcItem, RC_TREE_NODE::MAIN_ITEM ) );
358
359 if( rcItem->GetAuxItemID() != niluuid )
360 n->m_Children.push_back( createNode( n, rcItem, RC_TREE_NODE::AUX_ITEM ) );
361
362 if( rcItem->GetAuxItem2ID() != niluuid )
363 n->m_Children.push_back( createNode( n, rcItem, RC_TREE_NODE::AUX_ITEM2 ) );
364
365 if( rcItem->GetAuxItem3ID() != niluuid )
366 n->m_Children.push_back( createNode( n, rcItem, RC_TREE_NODE::AUX_ITEM3 ) );
367
368 if( MARKER_BASE* marker = rcItem->GetParent() )
369 {
370 if( marker->IsExcluded() && !marker->GetComment().IsEmpty() )
371 n->m_Children.push_back( createNode( n, rcItem, RC_TREE_NODE::COMMENT ) );
372 }
373 }
374
375 // Must be called after a significant change of items to force the
376 // wxDataViewModel to reread all of them, repopulating itself entirely.
377 AfterReset();
378
379#ifdef __WXGTK__
380 // The fastest method to update wxDataViewCtrl is to rebuild from
381 // scratch by calling Cleared(). Linux requires to reassociate model to
382 // display data, but Windows will create multiple associations.
383 // On MacOS, this crashes KiCad. See https://gitlab.com/kicad/code/kicad/-/issues/3666
384 // and https://gitlab.com/kicad/code/kicad/-/issues/3653
385 m_view->AssociateModel( this );
386#endif
387
388 if( !m_enableHyperlinks )
389 {
390 m_view->ClearColumns();
391 m_view->AppendTextColumn( wxEmptyString, 0, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE );
392 }
393
394 ExpandAll();
395
396 // Most annoyingly wxWidgets won't tell us the scroll position (and no, all the usual
397 // routines don't work), so we can only restore the scroll position based on a selection.
398 if( selectedRcItem )
399 {
400 for( RC_TREE_NODE* candidate : m_tree )
401 {
402 if( candidate->m_RcItem == selectedRcItem )
403 {
404 m_view->Select( ToItem( candidate ) );
405 m_view->EnsureVisible( ToItem( candidate ) );
406 break;
407 }
408 }
409 }
410}
411
412
413void RC_TREE_MODEL::Update( std::shared_ptr<RC_ITEMS_PROVIDER> aProvider, int aSeverities )
414{
415 rebuildModel( aProvider, aSeverities );
416}
417
418
420{
421 m_enableHyperlinks = aEnable;
422
423 if( !aEnable || !m_view || m_view->GetColumnCount() > 0 )
424 return;
425
428 new wxDataViewColumn( wxEmptyString, renderer, 0, std::max( 200, m_view->GetClientSize().GetWidth() ),
429 wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE );
430 m_view->AppendColumn( m_hyperlinkColumn );
431 m_view->Bind( wxEVT_SIZE, &RC_TREE_MODEL::onViewSize, this );
432}
433
434
435void RC_TREE_MODEL::onViewSize( wxSizeEvent& aEvent )
436{
437 aEvent.Skip();
438
440 m_hyperlinkColumn->SetWidth( std::max( 200, m_view->GetClientSize().GetWidth() ) );
441}
442
443
445{
446 for( RC_TREE_NODE* topLevelNode : m_tree )
447 m_view->Expand( ToItem( topLevelNode ) );
448}
449
450
451bool RC_TREE_MODEL::IsContainer( wxDataViewItem const& aItem ) const
452{
453 const RC_TREE_NODE* node = ToNode( aItem );
454
455 if( !aItem.IsOk() ) // tree root
456 return true;
457
458 if( node == nullptr )
459 return false;
460
461 return node->m_Type == RC_TREE_NODE::MARKER;
462}
463
464
465wxDataViewItem RC_TREE_MODEL::GetParent( wxDataViewItem const& aItem ) const
466{
467 const RC_TREE_NODE* node = ToNode( aItem );
468 return node ? ToItem( node->m_Parent ) : wxDataViewItem();
469}
470
471
472unsigned int RC_TREE_MODEL::GetChildren( wxDataViewItem const& aItem,
473 wxDataViewItemArray& aChildren ) const
474{
475 const RC_TREE_NODE* node = ToNode( aItem );
476 const std::vector<RC_TREE_NODE*>& children = node ? node->m_Children : m_tree;
477
478 if( aItem.IsOk() && !node )
479 return 0;
480
481 for( const RC_TREE_NODE* child : children )
482 aChildren.push_back( ToItem( child ) );
483
484 return children.size();
485}
486
487
488void RC_TREE_MODEL::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
489 unsigned int aCol ) const
490{
491 if( !aItem.IsOk() || m_view->IsFrozen() || m_tree.empty() )
492 return;
493
494 const RC_TREE_NODE* node = ToNode( aItem );
495
496 if( !node || !node->m_RcItem )
497 return;
498
499 const std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
500 MARKER_BASE* marker = rcItem->GetParent();
501 EDA_ITEM* item = nullptr;
502 wxString msg;
503
504 switch( node->m_Type )
505 {
507 if( marker )
508 {
509 SEVERITY severity = marker->GetSeverity();
510
511 if( severity == RPT_SEVERITY_EXCLUSION )
512 {
513 if( m_editFrame->GetSeverity( rcItem->GetErrorCode() ) == RPT_SEVERITY_WARNING )
514 msg = _( "Excluded warning: " );
515 else
516 msg = _( "Excluded error: " );
517 }
518 else if( severity == RPT_SEVERITY_WARNING )
519 {
520 msg = _( "Warning: " );
521 }
522 else
523 {
524 msg = _( "Error: " );
525 }
526 }
527
528 msg += rcItem->GetErrorMessage( true );
529 break;
530
532 if( marker && marker->GetMarkerType() == MARKER_BASE::MARKER_DRAWING_SHEET )
533 msg = _( "Drawing Sheet" );
534 else
535 item = m_editFrame->ResolveItem( rcItem->GetMainItemID() );
536
537 break;
538
540 item = m_editFrame->ResolveItem( rcItem->GetAuxItemID() );
541 break;
542
544 item = m_editFrame->ResolveItem( rcItem->GetAuxItem2ID() );
545 break;
546
548 item = m_editFrame->ResolveItem( rcItem->GetAuxItem3ID() );
549 break;
550
552 if( marker )
553 msg = marker->GetComment();
554
555 break;
556 }
557
558 if( item )
559 msg += item->GetItemDescription( m_editFrame, true );
560
561 msg.Replace( wxS( "\n" ), wxS( " " ) );
562 aVariant = msg;
563}
564
565
566bool RC_TREE_MODEL::GetAttr( wxDataViewItem const& aItem,
567 unsigned int aCol,
568 wxDataViewItemAttr& aAttr ) const
569{
570 if( !aItem.IsOk() || m_view->IsFrozen() || m_tree.empty() )
571 return false;
572
573 const RC_TREE_NODE* node = ToNode( aItem );
574
575 if( !node || !node->m_RcItem )
576 return false;
577
578 bool ret = false;
579 bool heading = node->m_Type == RC_TREE_NODE::MARKER;
580
581 if( heading )
582 {
583 aAttr.SetBold( true );
584 ret = true;
585 }
586
587 if( node->m_RcItem->GetParent()
589 {
590 wxColour textColour = wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOXTEXT );
591 double brightness = KIGFX::COLOR4D( textColour ).GetBrightness();
592
593 if( brightness > 0.5 )
594 {
595 int lightness = static_cast<int>( brightness * ( heading ? 50 : 60 ) );
596 aAttr.SetColour( textColour.ChangeLightness( lightness ) );
597 }
598 else
599 {
600 aAttr.SetColour( textColour.ChangeLightness( heading ? 170 : 165 ) );
601 }
602
603 aAttr.SetItalic( true ); // Strikethrough would be better, if wxWidgets supported it
604 ret = true;
605 }
606
607 return ret;
608}
609
610
612{
613 if( aNode->m_Type != RC_TREE_NODE::MARKER )
614 {
615 ValueChanged( aNode->m_Parent );
616 return;
617 }
618
619 wxDataViewItem markerItem = ToItem( aNode );
620
621 wxDataViewModel::ValueChanged( markerItem, 0 );
622
623 for( const RC_TREE_NODE* child : aNode->m_Children )
624 wxDataViewModel::ValueChanged( ToItem( child ), 0 );
625
626 // Comment items can come and go depening on exclusion state and comment content.
627 //
628 const std::shared_ptr<RC_ITEM> rcItem = aNode->m_RcItem;
629 MARKER_BASE* marker = rcItem ? rcItem->GetParent() : nullptr;
630
631 if( marker )
632 {
633 bool needsCommentNode = marker->IsExcluded() && !marker->GetComment().IsEmpty();
634 RC_TREE_NODE* commentNode = aNode->m_Children.empty() ? nullptr : aNode->m_Children.back();
635
636 if( commentNode && commentNode->m_Type != RC_TREE_NODE::COMMENT )
637 commentNode = nullptr;
638
639 if( needsCommentNode && !commentNode )
640 {
641 commentNode = createNode( aNode, rcItem, RC_TREE_NODE::COMMENT );
642 wxDataViewItemArray newItems;
643 newItems.push_back( ToItem( commentNode ) );
644
645 aNode->m_Children.push_back( commentNode );
646 ItemsAdded( markerItem, newItems );
647 }
648 else if( commentNode && !needsCommentNode )
649 {
650 wxDataViewItemArray deletedItems;
651 deletedItems.push_back( ToItem( commentNode ) );
652
653 aNode->m_Children.erase( aNode->m_Children.end() - 1 );
654 retireNodeTree( commentNode );
655 ItemsDeleted( markerItem, deletedItems );
656 deleteNodeTree( commentNode );
657 }
658 }
659}
660
661
663{
664 DeleteItems( true, true, aDeep );
665}
666
667
668void RC_TREE_MODEL::DeleteItems( bool aCurrentOnly, bool aIncludeExclusions, bool aDeep )
669{
670 RC_TREE_NODE* current_node = m_view ? ToNode( m_view->GetCurrentItem() ) : nullptr;
671 const std::shared_ptr<RC_ITEM> current_item = current_node ? current_node->m_RcItem : nullptr;
672
673 std::vector<wxDataViewItem> expanded;
674
675 if( aCurrentOnly && !current_item )
676 {
677 wxBell();
678 return;
679 }
680
681 // wxWidgets 3.1.x on MacOS (at least) loses the expanded state of the tree when deleting
682 // items.
683 if( m_view && aCurrentOnly )
684 {
685 for( RC_TREE_NODE* node : m_tree )
686 {
687 if( m_view->IsExpanded( ToItem( node ) ) )
688 expanded.push_back( ToItem( node ) );
689 }
690 }
691
692 int lastGood = -1;
693 bool itemDeleted = false;
694
695 if( m_view )
696 {
697 m_view->UnselectAll();
698 m_view->Freeze();
699 }
700
701 if( !m_rcItemsProvider )
702 {
703 if( m_view )
704 m_view->Thaw();
705
706 return;
707 }
708
709 for( int i = m_rcItemsProvider->GetCount() - 1; i >= 0; --i )
710 {
711 std::shared_ptr<RC_ITEM> rcItem = m_rcItemsProvider->GetItem( i );
712 MARKER_BASE* marker = rcItem->GetParent();
713 bool excluded = false;
714
715 if( marker && marker->GetSeverity() == RPT_SEVERITY_EXCLUSION )
716 excluded = true;
717
718 if( aCurrentOnly && itemDeleted && lastGood >= 0 )
719 break;
720
721 if( aCurrentOnly && rcItem != current_item )
722 {
723 lastGood = i;
724 continue;
725 }
726
727 if( excluded && !aIncludeExclusions )
728 continue;
729
730 if( i < (int) m_tree.size() ) // Careful; tree is truncated for large datasets
731 {
732 wxDataViewItem markerItem = ToItem( m_tree[i] );
733 wxDataViewItemArray childItems;
734 wxDataViewItem parentItem = ToItem( m_tree[i]->m_Parent );
735
736 for( RC_TREE_NODE* child : m_tree[i]->m_Children )
737 {
738 childItems.push_back( ToItem( child ) );
739 retireNodeTree( child );
740 }
741
742 ItemsDeleted( markerItem, childItems );
743
745 RC_TREE_NODE* deletedNode = m_tree[i];
746 m_tree.erase( m_tree.begin() + i );
747 ItemDeleted( parentItem, markerItem );
748 deleteNodeTree( deletedNode );
749 }
750
751 // Only deep delete the current item here; others will be done by the caller, which
752 // can more efficiently delete all markers on the board.
753 m_rcItemsProvider->DeleteItem( i, aDeep && aCurrentOnly );
754
755 if( lastGood > i )
756 lastGood--;
757
758 itemDeleted = true;
759 }
760
761 if( m_view && aCurrentOnly && lastGood >= 0 )
762 {
763 for( const wxDataViewItem& item : expanded )
764 {
765 if( item.IsOk() )
766 m_view->Expand( item );
767 }
768
769 wxDataViewItem selItem = ToItem( m_tree[ lastGood ] );
770 m_view->Select( selItem );
771
772 // wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED doesn't get propogated from the Select()
773 // call on (at least) MSW.
774 wxDataViewEvent selectEvent( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, m_view, selItem );
775 m_view->GetEventHandler()->ProcessEvent( selectEvent );
776 }
777
778 if( m_view )
779 m_view->Thaw();
780}
781
782
784{
785 RC_TREE_NODE* currentNode = ToNode( m_view->GetCurrentItem() );
786 RC_TREE_NODE* prevMarker = nullptr;
787
788 while( currentNode && currentNode->m_Type != RC_TREE_NODE::MARKER )
789 currentNode = currentNode->m_Parent;
790
791 for( RC_TREE_NODE* candidate : m_tree )
792 {
793 if( candidate == currentNode )
794 break;
795 else
796 prevMarker = candidate;
797 }
798
799 if( prevMarker )
800 m_view->Select( ToItem( prevMarker ) );
801}
802
803
805{
806 RC_TREE_NODE* currentNode = ToNode( m_view->GetCurrentItem() );
807
808 while( currentNode && currentNode->m_Type != RC_TREE_NODE::MARKER )
809 currentNode = currentNode->m_Parent;
810
811 RC_TREE_NODE* nextMarker = nullptr;
812 bool trigger = currentNode == nullptr;
813
814 for( RC_TREE_NODE* candidate : m_tree )
815 {
816 if( candidate == currentNode )
817 {
818 trigger = true;
819 }
820 else if( trigger )
821 {
822 nextMarker = candidate;
823 break;
824 }
825 }
826
827 if( nextMarker )
828 m_view->Select( ToItem( nextMarker ) );
829}
830
831
833{
834 wxCHECK( !m_view->IsFrozen(), /* void */ );
835
836 for( RC_TREE_NODE* candidate : m_tree )
837 {
838 if( candidate->m_RcItem->GetParent() == aMarker )
839 {
840 m_view->Select( ToItem( candidate ) );
841 return;
842 }
843 }
844}
845
846
848{
849 wxCHECK( !m_view->IsFrozen(), /* void */ );
850
851 for( RC_TREE_NODE* candidate : m_tree )
852 {
853 if( candidate->m_RcItem->GetParent() == aMarker )
854 {
855 m_view->EnsureVisible( ToItem( candidate ) );
856 return;
857 }
858 }
859}
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:96
virtual VECTOR2I GetPosition() const
Definition eda_item.h:282
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
Definition eda_item.cpp:169
const KIID m_Uuid
Definition eda_item.h:531
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:44
wxString AsString() const
Definition kiid.cpp:242
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:170
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:183
MARKER_BASE * GetParent() const
Definition rc_item.h:132
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:207
KIIDS m_ids
Definition rc_item.h:209
virtual KIID GetMainItemID() const
Definition rc_item.h:124
virtual KIID GetAuxItemID() const
Definition rc_item.h:125
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:204
wxString GetSettingsKey() const
Definition rc_item.h:178
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:106
void ExpandAll()
Definition rc_item.cpp:444
void PrevMarker()
Definition rc_item.cpp:783
int m_severities
Definition rc_item.h:364
void onViewSize(wxSizeEvent &aEvent)
Definition rc_item.cpp:435
wxDataViewColumn * m_hyperlinkColumn
Definition rc_item.h:366
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:488
std::vector< RC_TREE_NODE * > m_tree
Definition rc_item.h:370
unsigned int GetChildren(wxDataViewItem const &aItem, wxDataViewItemArray &aChildren) const override
Definition rc_item.cpp:472
std::vector< std::unique_ptr< RC_TREE_NODE::HANDLE > > m_handles
Definition rc_item.h:369
EDA_DRAW_FRAME * m_editFrame
Definition rc_item.h:362
void retireNodeTree(RC_TREE_NODE *aNode)
Definition rc_item.cpp:276
static wxDataViewItem ToItem(RC_TREE_NODE const *aNode)
Definition rc_item.h:262
bool m_enableHyperlinks
Definition rc_item.h:365
void SelectMarker(const MARKER_BASE *aMarker)
Definition rc_item.cpp:832
RC_TREE_MODEL(EDA_DRAW_FRAME *aParentFrame, wxDataViewCtrl *aView)
Definition rc_item.cpp:253
void deleteNodeTree(RC_TREE_NODE *aNode)
Definition rc_item.cpp:289
static RC_TREE_NODE * ToNode(wxDataViewItem aItem)
Definition rc_item.h:267
void ValueChanged(RC_TREE_NODE *aNode)
Definition rc_item.cpp:611
void Update(std::shared_ptr< RC_ITEMS_PROVIDER > aProvider, int aSeverities)
Definition rc_item.cpp:413
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:566
void DeleteItems(bool aCurrentOnly, bool aIncludeExclusions, bool aDeep)
Delete the current item or all items.
Definition rc_item.cpp:668
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:662
wxDataViewItem GetParent(wxDataViewItem const &aItem) const override
Definition rc_item.cpp:465
void CenterMarker(const MARKER_BASE *aMarker)
Definition rc_item.cpp:847
void EnableHyperlinks(bool aEnable)
Render [label](url) markup as clickable links.
Definition rc_item.cpp:419
static KIID ToUUID(wxDataViewItem aItem)
Definition rc_item.cpp:223
wxDataViewCtrl * m_view
Definition rc_item.h:363
std::shared_ptr< RC_ITEMS_PROVIDER > m_rcItemsProvider
Definition rc_item.h:367
void NextMarker()
Definition rc_item.cpp:804
bool IsContainer(wxDataViewItem const &aItem) const override
Definition rc_item.cpp:451
void rebuildModel(std::shared_ptr< RC_ITEMS_PROVIDER > aProvider, int aSeverities)
Definition rc_item.cpp:308
std::shared_ptr< RC_ITEM > m_RcItem
Definition rc_item.h:246
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:245
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
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:250
Functions to provide common constants and other functions to assist in making a consistent UI.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683