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