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