KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_erc.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 (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2012 Wayne Stambaugh <[email protected]>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
27#include <advanced_config.h>
28#include <gestfich.h>
29#include <sch_screen.h>
30#include <sch_edit_frame.h>
31#include <project.h>
32#include <kiface_base.h>
33#include <reporter.h>
35#include <sch_marker.h>
36#include <connection_graph.h>
37#include <tools/sch_actions.h>
39#include <dialog_erc.h>
40#include <erc/erc.h>
41#include <erc/erc_report.h>
42#include <id.h>
43#include <confirm.h>
46#include <string_utils.h>
47#include <kiplatform/ui.h>
48
49#include <wx/ffile.h>
50#include <wx/filedlg.h>
51#include <wx/hyperlink.h>
52#include <wx/msgdlg.h>
53#include <wx/wupdlock.h>
54
55
56wxDEFINE_EVENT( EDA_EVT_CLOSE_ERC_DIALOG, wxCommandEvent );
57
58
59// wxWidgets spends *far* too long calculating column widths (most of it, believe it or
60// not, in repeatedly creating/destroying a wxDC to do the measurement in).
61// Use default column widths instead.
62static int DEFAULT_SINGLE_COL_WIDTH = 660;
63
64
65static SCHEMATIC* g_lastERCSchematic = nullptr;
66static bool g_lastERCRun = false;
67
68static std::vector<std::pair<wxString, int>> g_lastERCIgnored;
69
70
72 DIALOG_ERC_BASE( parent ),
74 m_parent( parent ),
75 m_markerTreeModel( nullptr ),
76 m_running( false ),
77 m_ercRun( false ),
78 m_centerMarkerOnIdle( nullptr ),
79 m_severities( 0 )
80{
81 m_currentSchematic = &parent->Schematic();
82
83 SetName( DIALOG_ERC_WINDOW_NAME ); // Set a window name to be able to find it
85
86 if( EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) )
87 m_severities = cfg->m_Appearance.erc_severities;
88
90
91 m_markerProvider = std::make_shared<SHEETLIST_ERC_ITEMS_PROVIDER>( &m_parent->Schematic() );
92
94 m_markerDataView->AssociateModel( m_markerTreeModel );
96
97 m_ignoredList->InsertColumn( 0, wxEmptyString, wxLIST_FORMAT_LEFT, DEFAULT_SINGLE_COL_WIDTH );
98
100 {
102
103 for( const auto& [ str, code ] : g_lastERCIgnored )
104 {
105 wxListItem listItem;
106 listItem.SetId( m_ignoredList->GetItemCount() );
107 listItem.SetText( str );
108 listItem.SetData( code );
109
110 m_ignoredList->InsertItem( listItem );
111 }
112 }
113
114 m_notebook->SetSelection( 0 );
115
116 SetupStandardButtons( { { wxID_OK, _( "Run ERC" ) },
117 { wxID_CANCEL, _( "Close" ) } } );
118
119 m_violationsTitleTemplate = m_notebook->GetPageText( 0 );
120 m_ignoredTitleTemplate = m_notebook->GetPageText( 1 );
121
125
127
128 Layout();
129
130 SetFocus();
131
134
135 // Now all widgets have the size fixed, call FinishDialogSettings
137}
138
139
141{
144
145 g_lastERCIgnored.clear();
146
147 for( int ii = 0; ii < m_ignoredList->GetItemCount(); ++ii )
148 g_lastERCIgnored.push_back( { m_ignoredList->GetItemText( ii ), m_ignoredList->GetItemData( ii ) } );
149
150 if( EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) )
151 cfg->m_Appearance.erc_severities = m_severities;
152
153 m_markerTreeModel->DecRef();
154}
155
156
158{
160 []( ERCE_T, const wxString&, SCH_REFERENCE*, SCH_REFERENCE* )
161 {
162 } ) )
163 {
164 if( !m_infoBar->IsShownOnScreen() )
165 {
166 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( m_infoBar, wxID_ANY, _( "Show Annotation dialog" ),
167 wxEmptyString );
168
169 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
170 [&]( wxHyperlinkEvent& aEvent )
171 {
172 wxHtmlLinkEvent htmlEvent( aEvent.GetId(), wxHtmlLinkInfo( aEvent.GetURL() ) );
173 OnLinkClicked( htmlEvent );
174 } ) );
175
177 m_infoBar->AddButton( button );
178 m_infoBar->ShowMessage( _( "Schematic is not fully annotated. ERC results will be incomplete." ) );
179 }
180 }
181 else
182 {
183 if( m_infoBar->IsShownOnScreen() )
184 {
186 m_infoBar->Hide();
187 }
188 }
189}
190
191
193{
194 // If ERC checks ever get slow enough we'll want a progress indicator...
195 //
196 // double cur = (double) m_progress.load() / m_maxProgress;
197 // cur = std::max( 0.0, std::min( cur, 1.0 ) );
198 //
199 // m_gauge->SetValue( KiROUND( cur * 1000.0 ) );
200 // wxSafeYield( this );
201
202 return !m_cancelled;
203}
204
205
206void DIALOG_ERC::AdvancePhase( const wxString& aMessage )
207{
208 // Will also call Report( aMessage ):
210 SetCurrentProgress( 0.0 );
211}
212
213
214void DIALOG_ERC::Report( const wxString& aMessage )
215{
216 m_messages->Report( aMessage );
217}
218
219
221{
222 int numErrors = 0;
223 int numWarnings = 0;
224 int numExcluded = 0;
225
226 int numMarkers = 0;
227
228 if( m_markerProvider )
229 {
230 numMarkers += m_markerProvider->GetCount();
231 numErrors += m_markerProvider->GetCount( RPT_SEVERITY_ERROR );
232 numWarnings += m_markerProvider->GetCount( RPT_SEVERITY_WARNING );
233 numExcluded += m_markerProvider->GetCount( RPT_SEVERITY_EXCLUSION );
234 }
235
236 bool markersOverflowed = false;
237
238 // We don't currently have a limit on ERC violations, so the above is always false.
239
240 wxString num;
241 wxString msg;
242
243 if( m_ercRun )
244 {
245 num.Printf( markersOverflowed ? wxT( "%d+" ) : wxT( "%d" ), numMarkers );
246 msg.Printf( m_violationsTitleTemplate, num );
247 }
248 else
249 {
251 msg.Replace( wxT( "(%s)" ), wxEmptyString );
252 }
253
254 m_notebook->SetPageText( 0, msg );
255
256 if( m_ercRun )
257 {
258 num.Printf( wxT( "%d" ), m_ignoredList->GetItemCount() );
259 msg.sprintf( m_ignoredTitleTemplate, num );
260 }
261 else
262 {
264 msg.Replace( wxT( "(%s)" ), wxEmptyString );
265 }
266
267 m_notebook->SetPageText( 1, msg );
268
269 if( !m_ercRun && numErrors == 0 )
270 numErrors = -1;
271
272 if( !m_ercRun && numWarnings == 0 )
273 numWarnings = -1;
274
278}
279
280
281void DIALOG_ERC::OnDeleteOneClick( wxCommandEvent& aEvent )
282{
283 if( m_notebook->GetSelection() == 0 )
284 {
285 // Clear the selection. It may be the selected ERC marker.
287
289
290 // redraw the schematic
292 }
293
295}
296
297
298void DIALOG_ERC::OnDeleteAllClick( wxCommandEvent& event )
299{
300 bool includeExclusions = false;
301 int numExcluded = 0;
302
303 if( m_markerProvider )
304 numExcluded += m_markerProvider->GetCount( RPT_SEVERITY_EXCLUSION );
305
306 if( numExcluded > 0 )
307 {
308 wxMessageDialog dlg( this, _( "Delete exclusions too?" ), _( "Delete All Markers" ),
309 wxYES_NO | wxCANCEL | wxCENTER | wxICON_QUESTION );
310 dlg.SetYesNoLabels( _( "Errors and Warnings Only" ),
311 _( "Errors, Warnings and Exclusions" ) );
312
313 int ret = dlg.ShowModal();
314
315 if( ret == wxID_CANCEL )
316 return;
317 else if( ret == wxID_NO )
318 includeExclusions = true;
319 }
320
321 deleteAllMarkers( includeExclusions );
322
323 // redraw the schematic
326}
327
328
329void DIALOG_ERC::OnCancelClick( wxCommandEvent& aEvent )
330{
331 if( m_running )
332 {
333 m_cancelled = true;
334 return;
335 }
336
338
339 aEvent.Skip();
340}
341
342
343void DIALOG_ERC::OnCloseErcDialog( wxCloseEvent& aEvent )
344{
346
347 // Dialog is mode-less so let the parent know that it needs to be destroyed.
348 if( !IsModal() && !IsQuasiModal() )
349 {
350 wxCommandEvent* evt = new wxCommandEvent( EDA_EVT_CLOSE_ERC_DIALOG, wxID_ANY );
351
352 wxWindow* parent = GetParent();
353
354 if( parent )
355 wxQueueEvent( parent, evt );
356 }
357
358 aEvent.Skip();
359}
360
361
363
364
366{
371}
372
373
374void DIALOG_ERC::OnLinkClicked( wxHtmlLinkEvent& event )
375{
377}
378
379
380void DIALOG_ERC::OnRunERCClick( wxCommandEvent& event )
381{
382 wxBusyCursor busy;
383
384 SCHEMATIC* sch = &m_parent->Schematic();
385
387
388 sch->RecordERCExclusions();
389 deleteAllMarkers( true );
390
391 std::vector<std::reference_wrapper<RC_ITEM>> violations = ERC_ITEM::GetItemsWithSeverities();
392 m_ignoredList->DeleteAllItems();
393
394 for( std::reference_wrapper<RC_ITEM>& item : violations )
395 {
396 if( sch->ErcSettings().GetSeverity( item.get().GetErrorCode() ) == RPT_SEVERITY_IGNORE )
397 {
398 wxListItem listItem;
399 listItem.SetId( m_ignoredList->GetItemCount() );
400 listItem.SetText( wxT( " • " ) + item.get().GetErrorText() );
401 listItem.SetData( item.get().GetErrorCode() );
402
403 m_ignoredList->InsertItem( listItem );
404 }
405 }
406
407 m_ignoredList->SetColumnWidth( 0, m_ignoredList->GetParent()->GetClientSize().x - 20 );
408
409 m_cancelled = false;
410 Raise();
411
412 m_runningResultsBook->ChangeSelection( 0 ); // Display the "Tests Running..." tab
413 m_messages->Clear();
414 wxSafeYield(); // Allow time slice to refresh Messages
415
416 m_running = true;
417 m_sdbSizer1Cancel->SetLabel( _( "Cancel" ) );
418 m_sdbSizer1OK->Enable( false );
419 m_deleteOneMarker->Enable( false );
420 m_deleteAllMarkers->Enable( false );
421 m_saveReport->Enable( false );
422
423 int itemsNotAnnotated = m_parent->CheckAnnotate(
424 []( ERCE_T aType, const wxString& aMsg, SCH_REFERENCE* aItemA, SCH_REFERENCE* aItemB )
425 {
426 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( aType );
427 ercItem->SetErrorMessage( aMsg );
428
429 if( aItemB )
430 ercItem->SetItems( aItemA->GetSymbol(), aItemB->GetSymbol() );
431 else
432 ercItem->SetItems( aItemA->GetSymbol() );
433
434 SCH_MARKER* marker = new SCH_MARKER( ercItem, aItemA->GetSymbol()->GetPosition() );
435 aItemA->GetSheetPath().LastScreen()->Append( marker );
436 } );
437
438 testErc();
439
440 if( itemsNotAnnotated )
441 {
442 m_messages->ReportHead( wxString::Format( _( "%d symbol(s) require annotation.<br><br>" ),
443 itemsNotAnnotated ),
445 }
446
447 if( m_cancelled )
448 // @spellingerror
449 m_messages->Report( _( "-------- ERC canceled by user.<br><br>" ), RPT_SEVERITY_INFO );
450 else
451 m_messages->Report( _( "Done.<br><br>" ), RPT_SEVERITY_INFO );
452
453 Raise();
454 wxSafeYield(); // Allow time slice to refresh Messages
455
456 m_running = false;
457 m_sdbSizer1Cancel->SetLabel( _( "Close" ) );
458 m_sdbSizer1OK->Enable( true );
459 m_deleteOneMarker->Enable( true );
460 m_deleteAllMarkers->Enable( true );
461 m_saveReport->Enable( true );
462
463 if( !m_cancelled )
464 {
465 m_sdbSizer1Cancel->SetDefault();
466
467 // wxWidgets has a tendency to keep both buttons highlighted without the following:
468 m_sdbSizer1OK->Enable( false );
469
470 wxMilliSleep( 500 );
471 m_runningResultsBook->ChangeSelection( 1 );
473
474 // now re-enable m_sdbSizerOK button
475 m_sdbSizer1OK->Enable( true );
476 }
477
478 m_ercRun = true;
481 // set float level again, it can be lost due to window events during test run
483}
484
485
487{
488 WINDOW_THAWER thawer( m_parent );
489
491}
492
493
495{
496 wxFileName fn;
497
498 SCHEMATIC* sch = &m_parent->Schematic();
499
500 SCH_SCREENS screens( sch->Root() );
501 ERC_TESTER tester( sch );
502
503 {
504 wxBusyCursor dummy;
507 }
508
509 // Update marker list:
511
512 // Display new markers from the current screen:
513 for( SCH_ITEM* marker : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
514 {
515 m_parent->GetCanvas()->GetView()->Remove( marker );
516 m_parent->GetCanvas()->GetView()->Add( marker );
517 }
518
520}
521
522
523void DIALOG_ERC::OnERCItemSelected( wxDataViewEvent& aEvent )
524{
525 const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
526 SCH_SHEET_PATH sheet;
527 SCH_ITEM* item = m_parent->Schematic().ResolveItem( itemID, &sheet, true );
528
530 {
531 // we already came from a cross-probe of the marker in the document; don't go
532 // around in circles
533 }
534 else if( item && item->GetClass() != wxT( "DELETED_SHEET_ITEM" ) )
535 {
536 const RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
537
538 if( node )
539 {
540 // Determine the owning sheet for sheet-specific items
541 std::shared_ptr<ERC_ITEM> ercItem = std::static_pointer_cast<ERC_ITEM>( node->m_RcItem );
542
543 switch( node->m_Type )
544 {
546 if( ercItem->IsSheetSpecific() )
547 sheet = ercItem->GetSpecificSheetPath();
548 break;
550 if( ercItem->MainItemHasSheetPath() )
551 sheet = ercItem->GetMainItemSheetPath();
552 break;
554 if( ercItem->AuxItemHasSheetPath() )
555 sheet = ercItem->GetAuxItemSheetPath();
556 break;
557 default:
558 break;
559 }
560 }
561
562 WINDOW_THAWER thawer( m_parent );
563
564 if( !sheet.empty() && sheet != m_parent->GetCurrentSheet() )
565 {
568 }
569
570 m_parent->FocusOnItem( item );
572 }
573
574 aEvent.Skip();
575}
576
577
578void DIALOG_ERC::OnERCItemDClick( wxDataViewEvent& aEvent )
579{
580 if( aEvent.GetItem().IsOk() )
581 {
582 // turn control over to m_parent, hide this DIALOG_ERC window,
583 // no destruction so we can preserve listbox cursor
584 if( !IsModal() )
585 Show( false );
586 }
587
588 aEvent.Skip();
589}
590
591
592void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
593{
595 SCH_INSPECTION_TOOL* inspectionTool = toolMgr->GetTool<SCH_INSPECTION_TOOL>();
596 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
597
598 if( !node )
599 return;
600
602
603 std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
604 wxString listName;
605 wxMenu menu;
606
607 switch( settings.GetSeverity( rcItem->GetErrorCode() ) )
608 {
609 case RPT_SEVERITY_ERROR: listName = _( "errors" ); break;
610 case RPT_SEVERITY_WARNING: listName = _( "warnings" ); break;
611 default: listName = _( "appropriate" ); break;
612 }
613
614 enum MENU_IDS
615 {
616 ID_EDIT_EXCLUSION_COMMENT = 4467,
617 ID_REMOVE_EXCLUSION,
618 ID_REMOVE_EXCLUSION_ALL,
619 ID_ADD_EXCLUSION,
620 ID_ADD_EXCLUSION_WITH_COMMENT,
621 ID_ADD_EXCLUSION_ALL,
622 ID_INSPECT_VIOLATION,
623 ID_EDIT_PIN_CONFLICT_MAP,
624 ID_EDIT_CONNECTION_GRID,
625 ID_SET_SEVERITY_TO_ERROR,
626 ID_SET_SEVERITY_TO_WARNING,
627 ID_SET_SEVERITY_TO_IGNORE,
628 ID_EDIT_SEVERITIES,
629 };
630
631 if( rcItem->GetParent()->IsExcluded() )
632 {
633 menu.Append( ID_REMOVE_EXCLUSION,
634 _( "Remove exclusion for this violation" ),
635 wxString::Format( _( "It will be placed back in the %s list" ), listName ) );
636
637 menu.Append( ID_EDIT_EXCLUSION_COMMENT,
638 _( "Edit exclusion comment..." ) );
639 }
640 else
641 {
642 menu.Append( ID_ADD_EXCLUSION,
643 _( "Exclude this violation" ),
644 wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
645
646 menu.Append( ID_ADD_EXCLUSION_WITH_COMMENT,
647 _( "Exclude with comment..." ),
648 wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
649 }
650
651 wxString inspectERCErrorMenuText = inspectionTool->InspectERCErrorMenuText( rcItem );
652
653 if( !inspectERCErrorMenuText.IsEmpty() )
654 menu.Append( ID_INSPECT_VIOLATION, inspectERCErrorMenuText );
655
656 menu.AppendSeparator();
657
658 if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_WARNING
659 || rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
660 {
661 // Pin to pin severities edited through pin conflict map
662 }
663 else if( settings.GetSeverity( rcItem->GetErrorCode() ) == RPT_SEVERITY_WARNING )
664 {
665 menu.Append( ID_SET_SEVERITY_TO_ERROR,
666 wxString::Format( _( "Change severity to Error for all '%s' violations" ),
667 rcItem->GetErrorText() ),
668 _( "Violation severities can also be edited in the Schematic Setup... dialog" ) );
669 }
670 else
671 {
672 menu.Append( ID_SET_SEVERITY_TO_WARNING,
673 wxString::Format( _( "Change severity to Warning for all '%s' violations" ),
674 rcItem->GetErrorText() ),
675 _( "Violation severities can also be edited in the Schematic Setup... "
676 "dialog" ) );
677 }
678
679 menu.Append( ID_SET_SEVERITY_TO_IGNORE,
680 wxString::Format( _( "Ignore all '%s' violations" ), rcItem->GetErrorText() ),
681 _( "Violations will not be checked or reported" ) );
682
683 menu.AppendSeparator();
684
685 if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_WARNING
686 || rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
687 {
688 menu.Append( ID_EDIT_PIN_CONFLICT_MAP,
689 _( "Edit pin-to-pin conflict map..." ),
690 _( "Open the Schematic Setup... dialog" ) );
691 }
692 else
693 {
694 menu.Append( ID_EDIT_SEVERITIES,
695 _( "Edit violation severities..." ),
696 _( "Open the Schematic Setup... dialog" ) );
697 }
698
699 if( rcItem->GetErrorCode() == ERCE_ENDPOINT_OFF_GRID )
700 {
701 menu.Append( ID_EDIT_CONNECTION_GRID,
702 _( "Edit connection grid spacing..." ),
703 _( "Open the Schematic Setup... dialog" ) );
704 }
705
706 bool modified = false;
707 int command = GetPopupMenuSelectionFromUser( menu );
708
709 switch( command )
710 {
711 case ID_EDIT_EXCLUSION_COMMENT:
712 if( SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ) )
713 {
714 WX_TEXT_ENTRY_DIALOG dlg( this, wxEmptyString, _( "Exclusion Comment" ),
715 marker->GetComment(), true );
716
717 if( dlg.ShowModal() == wxID_CANCEL )
718 break;
719
720 marker->SetExcluded( true, dlg.GetValue() );
721
722 // Update view
723 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
724 modified = true;
725 }
726
727 break;
728
729 case ID_REMOVE_EXCLUSION:
730 if( SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ) )
731 {
732 marker->SetExcluded( false );
733 m_parent->GetCanvas()->GetView()->Update( marker );
734
735 // Update view
736 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
737 modified = true;
738 }
739
740 break;
741
742 case ID_ADD_EXCLUSION:
743 case ID_ADD_EXCLUSION_WITH_COMMENT:
744 if( SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ) )
745 {
746 wxString comment;
747
748 if( command == ID_ADD_EXCLUSION_WITH_COMMENT )
749 {
750 WX_TEXT_ENTRY_DIALOG dlg( this, wxEmptyString, _( "Exclusion Comment" ),
751 wxEmptyString, true );
752
753 if( dlg.ShowModal() == wxID_CANCEL )
754 break;
755
756 comment = dlg.GetValue();
757 }
758
759 marker->SetExcluded( true, comment );
760
761 m_parent->GetCanvas()->GetView()->Update( marker );
762
763 // Update view
765 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
766 else
767 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->DeleteCurrentItem( false );
768
769 modified = true;
770 }
771
772 break;
773
774 case ID_INSPECT_VIOLATION:
775 inspectionTool->InspectERCError( node->m_RcItem );
776 break;
777
778 case ID_SET_SEVERITY_TO_ERROR:
779 settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_ERROR );
780
781 for( SCH_ITEM* item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
782 {
783 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
784
785 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
786 m_parent->GetCanvas()->GetView()->Update( marker );
787 }
788
789 // Rebuild model and view
790 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
791 modified = true;
792 break;
793
794 case ID_SET_SEVERITY_TO_WARNING:
795 settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_WARNING );
796
797 for( SCH_ITEM* item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
798 {
799 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
800
801 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
802 m_parent->GetCanvas()->GetView()->Update( marker );
803 }
804
805 // Rebuild model and view
806 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
807 modified = true;
808 break;
809
810 case ID_SET_SEVERITY_TO_IGNORE:
811 {
812 settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_IGNORE );
813
814 if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
816
817 wxListItem listItem;
818 listItem.SetId( m_ignoredList->GetItemCount() );
819 listItem.SetText( wxT( " • " ) + rcItem->GetErrorText() );
820 listItem.SetData( rcItem->GetErrorCode() );
821
822 m_ignoredList->InsertItem( listItem );
823
824 // Clear the selection before deleting markers. It may be some selected ERC markers.
825 // Deleting a selected marker without deselecting it first generates a crash
827
828 SCH_SCREENS ScreenList( m_parent->Schematic().Root() );
829 ScreenList.DeleteMarkers( MARKER_BASE::MARKER_ERC, rcItem->GetErrorCode() );
830
831 // Rebuild model and view
832 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
833 modified = true;
834 }
835 break;
836
837 case ID_EDIT_PIN_CONFLICT_MAP:
838 m_parent->ShowSchematicSetupDialog( _( "Pin Conflicts Map" ) );
839 break;
840
841 case ID_EDIT_SEVERITIES:
842 m_parent->ShowSchematicSetupDialog( _( "Violation Severity" ) );
843 break;
844
845 case ID_EDIT_CONNECTION_GRID:
846 m_parent->ShowSchematicSetupDialog( _( "Formatting" ) );
847 break;
848 }
849
850 if( modified )
851 {
855 }
856}
857
858
859void DIALOG_ERC::OnIgnoredItemRClick( wxListEvent& event )
860{
862 int errorCode = (int) event.m_item.GetData();
863 wxMenu menu;
864
865 menu.Append( RPT_SEVERITY_ERROR, _( "Error" ), wxEmptyString, wxITEM_CHECK );
866 menu.Append( RPT_SEVERITY_WARNING, _( "Warning" ), wxEmptyString, wxITEM_CHECK );
867 menu.Append( RPT_SEVERITY_IGNORE, _( "Ignore" ), wxEmptyString, wxITEM_CHECK );
868
869 menu.Check( settings.GetSeverity( errorCode ), true );
870
871 int severity = GetPopupMenuSelectionFromUser( menu );
872
873 if( severity > 0 )
874 {
875 if( settings.GetSeverity( errorCode ) != severity )
876 {
877 settings.SetSeverity( errorCode, (SEVERITY) severity );
878
882 }
883 }
884}
885
886
888{
889 if( m_notebook->IsShown() )
890 {
891 if( m_notebook->GetSelection() != 0 )
892 m_notebook->SetSelection( 0 );
893
895 }
896}
897
898
900{
901 if( m_notebook->IsShown() )
902 {
903 if( m_notebook->GetSelection() != 0 )
904 m_notebook->SetSelection( 0 );
905
907 }
908}
909
910
912{
913 if( m_notebook->IsShown() )
914 {
915 m_notebook->SetSelection( 0 );
917
918 // wxWidgets on some platforms fails to correctly ensure that a selected item is
919 // visible, so we have to do it in a separate idle event.
920 m_centerMarkerOnIdle = aMarker;
921 Bind( wxEVT_IDLE, &DIALOG_ERC::centerMarkerIdleHandler, this );
922 }
923}
924
925
926void DIALOG_ERC::centerMarkerIdleHandler( wxIdleEvent& aEvent )
927{
928 if( m_markerTreeModel->GetView()->IsFrozen() )
929 return;
930
932 m_centerMarkerOnIdle = nullptr;
933 Unbind( wxEVT_IDLE, &DIALOG_ERC::centerMarkerIdleHandler, this );
934}
935
936
938{
939 SCH_MARKER* marker = aMarker;
940
941 if( marker != nullptr )
943
944 if( m_notebook->GetSelection() != 0 )
945 return;
946
947 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( m_markerDataView->GetCurrentItem() );
948
949 if( node && node->m_RcItem )
950 marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() );
951
952 if( node && marker && !marker->IsExcluded() )
953 {
954 marker->SetExcluded( true );
955 m_parent->GetCanvas()->GetView()->Update( marker );
956
957 // Update view
960 else
962
966 }
967}
968
969
970void DIALOG_ERC::OnEditViolationSeverities( wxHyperlinkEvent& aEvent )
971{
972 m_parent->ShowSchematicSetupDialog( _( "Violation Severity" ) );
973}
974
975
976void DIALOG_ERC::OnSeverity( wxCommandEvent& aEvent )
977{
978 int flag = 0;
979
980 if( aEvent.GetEventObject() == m_showAll )
982 else if( aEvent.GetEventObject() == m_showErrors )
984 else if( aEvent.GetEventObject() == m_showWarnings )
986 else if( aEvent.GetEventObject() == m_showExclusions )
988
989 if( aEvent.IsChecked() )
991 else if( aEvent.GetEventObject() == m_showAll )
993 else
994 m_severities &= ~flag;
995
997
1000}
1001
1002
1003void DIALOG_ERC::deleteAllMarkers( bool aIncludeExclusions )
1004{
1005 // Clear current selection list to avoid selection of deleted items
1006 // Freeze to avoid repainting the dialog, which can cause a RePaint()
1007 // of the screen as well
1008 wxWindowUpdateLocker updateLock( this );
1009
1011
1012 m_markerTreeModel->DeleteItems( false, aIncludeExclusions, false );
1013
1014 SCH_SCREENS screens( m_parent->Schematic().Root() );
1015 screens.DeleteAllMarkers( MARKER_BASE::MARKER_ERC, aIncludeExclusions );
1016}
1017
1018
1019void DIALOG_ERC::OnSaveReport( wxCommandEvent& aEvent )
1020{
1021 wxFileName fn( wxS( "ERC." ) + wxString( FILEEXT::ReportFileExtension ) );
1022
1023 wxFileDialog dlg( this, _( "Save Report File" ), Prj().GetProjectPath(), fn.GetFullName(),
1025 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1026
1027 if( dlg.ShowModal() != wxID_OK )
1028 return;
1029
1030 fn = dlg.GetPath();
1031
1032 if( fn.GetExt().IsEmpty() )
1033 fn.SetExt( FILEEXT::ReportFileExtension );
1034
1035 if( !fn.IsAbsolute() )
1036 {
1037 wxString prj_path = Prj().GetProjectPath();
1038 fn.MakeAbsolute( prj_path );
1039 }
1040
1041 ERC_REPORT reportWriter( &m_parent->Schematic(), m_parent->GetUserUnits() );
1042
1043 bool success = false;
1044 if( fn.GetExt() == FILEEXT::JsonFileExtension )
1045 success = reportWriter.WriteJsonReport( fn.GetFullPath() );
1046 else
1047 success = reportWriter.WriteTextReport( fn.GetFullPath() );
1048
1049 if( success )
1050 {
1051 m_messages->Report( wxString::Format( _( "Report file '%s' created." ),
1052 fn.GetFullPath() ) );
1053 }
1054 else
1055 {
1056 DisplayErrorMessage( this, wxString::Format( _( "Failed to create file '%s'." ),
1057 fn.GetFullPath() ) );
1058 }
1059}
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: actions.h:221
VECTOR2D m_ScrollCenter
Current scroll center point in logical units.
Definition: base_screen.h:100
Class DIALOG_ERC_BASE.
wxButton * m_saveReport
wxButton * m_sdbSizer1Cancel
wxSimplebook * m_runningResultsBook
wxCheckBox * m_showExclusions
NUMBER_BADGE * m_errorsBadge
WX_INFOBAR * m_infoBar
wxCheckBox * m_showErrors
wxNotebook * m_notebook
wxCheckBox * m_showAll
NUMBER_BADGE * m_exclusionsBadge
wxListCtrl * m_ignoredList
WX_HTML_REPORT_BOX * m_messages
wxDataViewCtrl * m_markerDataView
wxButton * m_deleteAllMarkers
NUMBER_BADGE * m_warningsBadge
wxButton * m_deleteOneMarker
wxCheckBox * m_showWarnings
wxButton * m_sdbSizer1OK
void ExcludeMarker(SCH_MARKER *aMarker=nullptr)
Exclude aMarker from the ERC list.
Definition: dialog_erc.cpp:937
void OnIgnoredItemRClick(wxListEvent &aEvent) override
Definition: dialog_erc.cpp:859
const SCH_MARKER * m_centerMarkerOnIdle
Definition: dialog_erc.h:115
void OnERCItemDClick(wxDataViewEvent &aEvent) override
Definition: dialog_erc.cpp:578
std::shared_ptr< RC_ITEMS_PROVIDER > m_markerProvider
Definition: dialog_erc.h:109
void syncCheckboxes()
Definition: dialog_erc.cpp:365
bool m_ercRun
Definition: dialog_erc.h:113
DIALOG_ERC(SCH_EDIT_FRAME *parent)
Definition: dialog_erc.cpp:71
void testErc()
Definition: dialog_erc.cpp:494
void SelectMarker(const SCH_MARKER *aMarker)
Definition: dialog_erc.cpp:911
bool updateUI() override
Definition: dialog_erc.cpp:192
SCH_EDIT_FRAME * m_parent
Definition: dialog_erc.h:103
wxString m_violationsTitleTemplate
Definition: dialog_erc.h:106
void OnERCItemRClick(wxDataViewEvent &aEvent) override
Definition: dialog_erc.cpp:592
void centerMarkerIdleHandler(wxIdleEvent &aEvent)
Definition: dialog_erc.cpp:926
void OnDeleteAllClick(wxCommandEvent &event) override
Definition: dialog_erc.cpp:298
void OnLinkClicked(wxHtmlLinkEvent &event) override
Definition: dialog_erc.cpp:374
int m_severities
Definition: dialog_erc.h:117
void OnRunERCClick(wxCommandEvent &event) override
Definition: dialog_erc.cpp:380
void deleteAllMarkers(bool aIncludeExclusions)
wxString m_ignoredTitleTemplate
Definition: dialog_erc.h:107
void OnDeleteOneClick(wxCommandEvent &event) override
Definition: dialog_erc.cpp:281
void OnSaveReport(wxCommandEvent &aEvent) override
void PrevMarker()
Definition: dialog_erc.cpp:887
void NextMarker()
Definition: dialog_erc.cpp:899
SCHEMATIC * m_currentSchematic
Definition: dialog_erc.h:104
void OnEditViolationSeverities(wxHyperlinkEvent &aEvent) override
Definition: dialog_erc.cpp:970
void UpdateAnnotationWarning()
Definition: dialog_erc.cpp:157
void redrawDrawPanel()
Definition: dialog_erc.cpp:486
void Report(const wxString &aMessage) override
Display aMessage in the progress bar dialog.
Definition: dialog_erc.cpp:214
void OnERCItemSelected(wxDataViewEvent &aEvent) override
Definition: dialog_erc.cpp:523
RC_TREE_MODEL * m_markerTreeModel
Definition: dialog_erc.h:110
void updateDisplayedCounts()
Definition: dialog_erc.cpp:220
void OnSeverity(wxCommandEvent &aEvent) override
Definition: dialog_erc.cpp:976
bool m_running
Definition: dialog_erc.h:112
void OnCloseErcDialog(wxCloseEvent &event) override
Definition: dialog_erc.cpp:343
void OnCancelClick(wxCommandEvent &event) override
Definition: dialog_erc.cpp:329
bool Show(bool show) override
void SetupStandardButtons(std::map< int, wxString > aLabels={})
bool IsQuasiModal() const
Definition: dialog_shim.h:86
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
int ShowModal() override
virtual void ClearFocus()
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:241
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Definition: erc_item.cpp:302
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition: erc_item.h:76
bool WriteJsonReport(const wxString &aFullFileName)
Writes a JSON formatted ERC Report to the given file path in the c-locale.
Definition: erc_report.cpp:124
bool WriteTextReport(const wxString &aFullFileName)
Writes the text report also available via GetTextReport directly to a given file path.
Definition: erc_report.cpp:110
Container for ERC settings.
Definition: erc_settings.h:132
SEVERITY GetSeverity(int aErrorCode) const
void SetSeverity(int aErrorCode, SEVERITY aSeverity)
Definition: erc.h:52
void RunTests(DS_PROXY_VIEW_ITEM *aDrawingSheet, SCH_EDIT_FRAME *aEditFrame, KIFACE *aCvPcb, PROJECT *aProject, PROGRESS_REPORTER *aProgressReporter)
Definition: erc.cpp:1892
A specialisation of the RC_TREE_MODEL class to enable ERC errors / warnings to be resolved in a speci...
Definition: erc_item.h:38
void Update(const KIGFX::VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: sch_view.cpp:60
DS_PROXY_VIEW_ITEM * GetDrawingSheet() const
Definition: sch_view.h:120
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:298
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:341
Definition: kiid.h:49
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition: kiway.cpp:198
@ FACE_CVPCB
Definition: kiway.h:295
bool IsExcluded() const
Definition: marker_base.h:93
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:107
void SetExcluded(bool aExcluded, const wxString &aComment=wxEmptyString)
Definition: marker_base.h:94
void SetMaximumNumber(int aMax)
Set the maximum number to be shown on the badge.
void UpdateNumber(int aNumber, SEVERITY aSeverity)
Update the number displayed on the badge.
This implements all the tricky bits for thread safety, but the GUI is left to derived classes.
virtual void AdvancePhase() override
Use the next available virtual zone of the dialog progress bar.
virtual void SetCurrentProgress(double aProgress) override
Set the progress value to aProgress (0..1).
virtual void AdvancePhase()=0
Use the next available virtual zone of the dialog progress bar.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:149
void PrevMarker()
Definition: rc_item.cpp:690
void SelectMarker(const MARKER_BASE *aMarker)
Definition: rc_item.cpp:739
const wxDataViewCtrl * GetView() const
Definition: rc_item.h:248
static RC_TREE_NODE * ToNode(wxDataViewItem aItem)
Definition: rc_item.h:243
void ValueChanged(RC_TREE_NODE *aNode)
Definition: rc_item.cpp:518
void Update(std::shared_ptr< RC_ITEMS_PROVIDER > aProvider, int aSeverities)
Definition: rc_item.cpp:361
void DeleteItems(bool aCurrentOnly, bool aIncludeExclusions, bool aDeep)
Delete the current item or all items.
Definition: rc_item.cpp:573
void DeleteCurrentItem(bool aDeep)
Definition: rc_item.cpp:567
void CenterMarker(const MARKER_BASE *aMarker)
Definition: rc_item.cpp:754
static KIID ToUUID(wxDataViewItem aItem)
Definition: rc_item.cpp:217
void NextMarker()
Definition: rc_item.cpp:711
std::shared_ptr< RC_ITEM > m_RcItem
Definition: rc_item.h:228
NODE_TYPE m_Type
Definition: rc_item.h:227
virtual REPORTER & ReportHead(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the beginning of the list for objects that support ordering.
Definition: reporter.h:121
Holds all the data relating to one schematic.
Definition: schematic.h:88
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Definition: schematic.h:134
void RecordERCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: schematic.cpp:884
SCH_SHEET & Root() const
Definition: schematic.h:140
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:363
static TOOL_ACTION changeSheet
Definition: sch_actions.h:217
virtual void RedrawScreen(const VECTOR2I &aCenterPoint, bool aWarpPointer)
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
Schematic editor (Eeschema) main window.
void ShowSchematicSetupDialog(const wxString &aInitialPage=wxEmptyString)
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag and update other data struc...
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SCH_SHEET_PATH & GetCurrentSheet() const
SCHEMATIC & Schematic() const
int CheckAnnotate(ANNOTATION_ERROR_HANDLER aErrorHandler, ANNOTATE_SCOPE_T aAnnotateScope=ANNOTATE_ALL, bool aRecursive=true)
Check for annotation errors.
Definition: annotate.cpp:463
void FocusOnItem(EDA_ITEM *aItem) override
Focus on a particular canvas item.
void InspectERCError(const std::shared_ptr< RC_ITEM > &aERCItem)
wxString InspectERCErrorMenuText(const std::shared_ptr< RC_ITEM > &aERCItem)
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:168
wxString GetClass() const override
Return the class name.
Definition: sch_item.h:178
A helper to define a symbol's reference designator in a schematic.
const SCH_SHEET_PATH & GetSheetPath() const
SCH_SYMBOL * GetSymbol() const
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:758
void DeleteMarkers(enum MARKER_BASE::MARKER_T aMarkerTyp, int aErrorCode, bool aIncludeExclusions=true)
Delete all markers of a particular type and error code.
void DeleteAllMarkers(enum MARKER_BASE::MARKER_T aMarkerType, bool aIncludeExclusions)
Delete all electronic rules check markers of aMarkerType from all the screens in the list.
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:160
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition: sch_screen.h:117
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
bool empty() const
Forwarded method from std::vector.
SCH_SCREEN * LastScreen()
VECTOR2I GetPosition() const override
Definition: sch_symbol.h:767
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
Master controller class:
Definition: tool_manager.h:62
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
EDA_UNITS GetUserUnits() const
void Clear() override
Delete the stored messages.
void SetImmediateMode()
In immediate mode, messages are flushed as they are added.
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: wx_infobar.cpp:371
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: wx_infobar.cpp:327
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: wx_infobar.cpp:156
A KICAD version of wxTextEntryDialog which supports the various improvements/work-arounds from DIALOG...
wxString GetValue() const
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:194
This file is part of the common library.
static int RPT_SEVERITY_ALL
Definition: dialog_erc.cpp:362
static int DEFAULT_SINGLE_COL_WIDTH
Definition: dialog_erc.cpp:62
static bool g_lastERCRun
Definition: dialog_erc.cpp:66
wxDEFINE_EVENT(EDA_EVT_CLOSE_ERC_DIALOG, wxCommandEvent)
static std::vector< std::pair< wxString, int > > g_lastERCIgnored
Definition: dialog_erc.cpp:68
static SCHEMATIC * g_lastERCSchematic
Definition: dialog_erc.cpp:65
#define DIALOG_ERC_WINDOW_NAME
Definition: dialog_erc.h:40
#define _(s)
static int DEFAULT_SINGLE_COL_WIDTH
ERCE_T
ERC error codes.
Definition: erc_settings.h:36
@ ERCE_ENDPOINT_OFF_GRID
Pin or wire-end off grid.
Definition: erc_settings.h:40
@ ERCE_PIN_TO_PIN_WARNING
Definition: erc_settings.h:94
@ ERCE_PIN_TO_PIN_ERROR
Definition: erc_settings.h:95
static const std::string ReportFileExtension
static const std::string JsonFileExtension
static wxString JsonFileWildcard()
static wxString ReportFileWildcard()
void SetFloatLevel(wxWindow *aWindow)
Intended to set the floating window level in macOS on a window.
Definition: wxgtk/ui.cpp:401
void ForceFocus(wxWindow *aWindow)
Pass the current focus to the window.
Definition: wxgtk/ui.cpp:124
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_EXCLUSION
@ RPT_SEVERITY_IGNORE
@ RPT_SEVERITY_INFO
std::vector< FAB_LAYER_COLOR > dummy
@ SCH_MARKER_T
Definition: typeinfo.h:159
Definition of file extensions used in Kicad.
static int RPT_SEVERITY_ALL