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