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 (C) 1992-2024 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
26#include <advanced_config.h>
27#include <gestfich.h>
28#include <sch_screen.h>
29#include <sch_edit_frame.h>
30#include <schematic.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/ee_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>
44#include <common.h>
47#include <erc/erc_item.h>
48#include <eeschema_settings.h>
49#include <string_utils.h>
50#include <kiplatform/ui.h>
51
52#include <wx/ffile.h>
53#include <wx/filedlg.h>
54#include <wx/hyperlink.h>
55#include <wx/msgdlg.h>
56
57
58wxDEFINE_EVENT( EDA_EVT_CLOSE_ERC_DIALOG, wxCommandEvent );
59
60
61// wxWidgets spends *far* too long calcuating column widths (most of it, believe it or
62// not, in repeatedly creating/destroying a wxDC to do the measurement in).
63// Use default column widths instead.
64static int DEFAULT_SINGLE_COL_WIDTH = 660;
65
66
67static SCHEMATIC* g_lastERCSchematic = nullptr;
68static bool g_lastERCRun = false;
69
70static std::vector<std::pair<wxString, int>> g_lastERCIgnored;
71
72
74 DIALOG_ERC_BASE( parent ),
76 m_parent( parent ),
77 m_markerTreeModel( nullptr ),
78 m_running( false ),
79 m_ercRun( false ),
80 m_centerMarkerOnIdle( nullptr ),
81 m_severities( 0 )
82{
83 m_currentSchematic = &parent->Schematic();
84
85 SetName( DIALOG_ERC_WINDOW_NAME ); // Set a window name to be able to find it
87
88 EESCHEMA_SETTINGS* settings = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
90
92
93 m_markerProvider = std::make_shared<SHEETLIST_ERC_ITEMS_PROVIDER>( &m_parent->Schematic() );
94
96 m_markerDataView->AssociateModel( m_markerTreeModel );
98
99 m_ignoredList->InsertColumn( 0, wxEmptyString, wxLIST_FORMAT_LEFT, DEFAULT_SINGLE_COL_WIDTH );
100
102 {
104
105 for( const auto& [ str, code ] : g_lastERCIgnored )
106 {
107 wxListItem listItem;
108 listItem.SetId( m_ignoredList->GetItemCount() );
109 listItem.SetText( str );
110 listItem.SetData( code );
111
112 m_ignoredList->InsertItem( listItem );
113 }
114 }
115
116 m_notebook->SetSelection( 0 );
117
118 SetupStandardButtons( { { wxID_OK, _( "Run ERC" ) },
119 { wxID_CANCEL, _( "Close" ) } } );
120
121 m_violationsTitleTemplate = m_notebook->GetPageText( 0 );
122 m_ignoredTitleTemplate = m_notebook->GetPageText( 1 );
123
127
129
130 Layout();
131
132 SetFocus();
133
136
137 // Now all widgets have the size fixed, call FinishDialogSettings
139}
140
141
143{
146
147 g_lastERCIgnored.clear();
148
149 for( int ii = 0; ii < m_ignoredList->GetItemCount(); ++ii )
150 {
151 g_lastERCIgnored.push_back( { m_ignoredList->GetItemText( ii ),
152 m_ignoredList->GetItemData( ii ) } );
153 }
154
155 EESCHEMA_SETTINGS* settings = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
156 wxASSERT( settings );
157
158 if( settings )
160
161 m_markerTreeModel->DecRef();
162}
163
164
166{
167 if( m_parent->CheckAnnotate( []( ERCE_T, const wxString&, SCH_REFERENCE*, SCH_REFERENCE* )
168 { } ) )
169 {
170 if( !m_infoBar->IsShownOnScreen() )
171 {
172 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( m_infoBar, wxID_ANY,
173 _( "Show Annotation dialog" ),
174 wxEmptyString );
175
176 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
177 [&]( wxHyperlinkEvent& aEvent )
178 {
179 wxHtmlLinkEvent htmlEvent( aEvent.GetId(),
180 wxHtmlLinkInfo( aEvent.GetURL() ) );
181 OnLinkClicked( htmlEvent );
182 } ) );
183
185 m_infoBar->AddButton( button );
186 m_infoBar->ShowMessage( _( "Schematic is not fully annotated. "
187 "ERC results will be incomplete." ) );
188 }
189 }
190 else
191 {
192 if( m_infoBar->IsShownOnScreen() )
193 {
195 m_infoBar->Hide();
196 }
197 }
198}
199
200
202{
203 // If ERC checks ever get slow enough we'll want a progress indicator...
204 //
205 // double cur = (double) m_progress.load() / m_maxProgress;
206 // cur = std::max( 0.0, std::min( cur, 1.0 ) );
207 //
208 // m_gauge->SetValue( KiROUND( cur * 1000.0 ) );
209 // wxSafeYield( this );
210
211 return !m_cancelled;
212}
213
214
215void DIALOG_ERC::AdvancePhase( const wxString& aMessage )
216{
217 // Will also call Report( aMessage ):
219 SetCurrentProgress( 0.0 );
220}
221
222
223void DIALOG_ERC::Report( const wxString& aMessage )
224{
225 m_messages->Report( aMessage );
226}
227
228
230{
231 int numErrors = 0;
232 int numWarnings = 0;
233 int numExcluded = 0;
234
235 int numMarkers = 0;
236
237 if( m_markerProvider )
238 {
239 numMarkers += m_markerProvider->GetCount();
240 numErrors += m_markerProvider->GetCount( RPT_SEVERITY_ERROR );
241 numWarnings += m_markerProvider->GetCount( RPT_SEVERITY_WARNING );
242 numExcluded += m_markerProvider->GetCount( RPT_SEVERITY_EXCLUSION );
243 }
244
245 bool markersOverflowed = false;
246
247 // We don't currently have a limit on ERC violations, so the above is always false.
248
249 wxString num;
250 wxString msg;
251
252 if( m_ercRun )
253 {
254 num.Printf( markersOverflowed ? wxT( "%d+" ) : wxT( "%d" ), numMarkers );
255 msg.Printf( m_violationsTitleTemplate, num );
256 }
257 else
258 {
260 msg.Replace( wxT( "(%s)" ), wxEmptyString );
261 }
262
263 m_notebook->SetPageText( 0, msg );
264
265 if( m_ercRun )
266 {
267 num.Printf( wxT( "%d" ), m_ignoredList->GetItemCount() );
268 msg.sprintf( m_ignoredTitleTemplate, num );
269 }
270 else
271 {
273 msg.Replace( wxT( "(%s)" ), wxEmptyString );
274 }
275
276 m_notebook->SetPageText( 1, msg );
277
278 if( !m_ercRun && numErrors == 0 )
279 numErrors = -1;
280
281 if( !m_ercRun && numWarnings == 0 )
282 numWarnings = -1;
283
287}
288
289
290void DIALOG_ERC::OnDeleteOneClick( wxCommandEvent& aEvent )
291{
292 if( m_notebook->GetSelection() == 0 )
293 {
294 // Clear the selection. It may be the selected ERC marker.
296
298
299 // redraw the schematic
301 }
302
304}
305
306
307void DIALOG_ERC::OnDeleteAllClick( wxCommandEvent& event )
308{
309 bool includeExclusions = false;
310 int numExcluded = 0;
311
312 if( m_markerProvider )
313 numExcluded += m_markerProvider->GetCount( RPT_SEVERITY_EXCLUSION );
314
315 if( numExcluded > 0 )
316 {
317 wxMessageDialog dlg( this, _( "Delete exclusions too?" ), _( "Delete All Markers" ),
318 wxYES_NO | wxCANCEL | wxCENTER | wxICON_QUESTION );
319 dlg.SetYesNoLabels( _( "Errors and Warnings Only" ),
320 _( "Errors, Warnings and Exclusions" ) );
321
322 int ret = dlg.ShowModal();
323
324 if( ret == wxID_CANCEL )
325 return;
326 else if( ret == wxID_NO )
327 includeExclusions = true;
328 }
329
330 deleteAllMarkers( includeExclusions );
331
332 // redraw the schematic
335}
336
337
338void DIALOG_ERC::OnCancelClick( wxCommandEvent& aEvent )
339{
340 if( m_running )
341 {
342 m_cancelled = true;
343 return;
344 }
345
346 m_parent->FocusOnItem( nullptr );
347
348 aEvent.Skip();
349}
350
351
352void DIALOG_ERC::OnCloseErcDialog( wxCloseEvent& aEvent )
353{
354 m_parent->FocusOnItem( nullptr );
355
356 // Dialog is mode-less so let the parent know that it needs to be destroyed.
357 if( !IsModal() && !IsQuasiModal() )
358 {
359 wxCommandEvent* evt = new wxCommandEvent( EDA_EVT_CLOSE_ERC_DIALOG, wxID_ANY );
360
361 wxWindow* parent = GetParent();
362
363 if( parent )
364 wxQueueEvent( parent, evt );
365 }
366
367 aEvent.Skip();
368}
369
370
372
373
375{
380}
381
382
383void DIALOG_ERC::OnLinkClicked( wxHtmlLinkEvent& event )
384{
385 wxCommandEvent dummy;
387}
388
389
390void DIALOG_ERC::OnRunERCClick( wxCommandEvent& event )
391{
392 wxBusyCursor busy;
393
394 SCHEMATIC* sch = &m_parent->Schematic();
395
397
398 sch->RecordERCExclusions();
399 deleteAllMarkers( true );
400
401 std::vector<std::reference_wrapper<RC_ITEM>> violations = ERC_ITEM::GetItemsWithSeverities();
402 m_ignoredList->DeleteAllItems();
403
404 for( std::reference_wrapper<RC_ITEM>& item : violations )
405 {
406 if( sch->ErcSettings().GetSeverity( item.get().GetErrorCode() ) == RPT_SEVERITY_IGNORE )
407 {
408 wxListItem listItem;
409 listItem.SetId( m_ignoredList->GetItemCount() );
410 listItem.SetText( wxT( " • " ) + item.get().GetErrorText() );
411 listItem.SetData( item.get().GetErrorCode() );
412
413 m_ignoredList->InsertItem( listItem );
414 }
415 }
416
417 m_ignoredList->SetColumnWidth( 0, m_ignoredList->GetParent()->GetClientSize().x - 20 );
418
419 m_cancelled = false;
420 Raise();
421
422 m_runningResultsBook->ChangeSelection( 0 ); // Display the "Tests Running..." tab
423 m_messages->Clear();
424 wxYield(); // Allow time slice to refresh Messages
425
426 m_running = true;
427 m_sdbSizer1Cancel->SetLabel( _( "Cancel" ) );
428 m_sdbSizer1OK->Enable( false );
429 m_deleteOneMarker->Enable( false );
430 m_deleteAllMarkers->Enable( false );
431 m_saveReport->Enable( false );
432
433 int itemsNotAnnotated = m_parent->CheckAnnotate(
434 []( ERCE_T aType, const wxString& aMsg, SCH_REFERENCE* aItemA, SCH_REFERENCE* aItemB )
435 {
436 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( aType );
437 ercItem->SetErrorMessage( aMsg );
438
439 if( aItemB )
440 ercItem->SetItems( aItemA->GetSymbol(), aItemB->GetSymbol() );
441 else
442 ercItem->SetItems( aItemA->GetSymbol() );
443
444 SCH_MARKER* marker = new SCH_MARKER( ercItem, aItemA->GetSymbol()->GetPosition() );
445 aItemA->GetSheetPath().LastScreen()->Append( marker );
446 } );
447
448 testErc();
449
450 if( itemsNotAnnotated )
451 m_messages->ReportHead( wxString::Format( _( "%d symbol(s) require annotation.<br><br>" ),
452 itemsNotAnnotated ), RPT_SEVERITY_INFO );
453
454 if( m_cancelled )
455 m_messages->Report( _( "-------- ERC cancelled by user.<br><br>" ), RPT_SEVERITY_INFO );
456 else
457 m_messages->Report( _( "Done.<br><br>" ), RPT_SEVERITY_INFO );
458
459 Raise();
460 wxYield(); // Allow time slice to refresh Messages
461
462 m_running = false;
463 m_sdbSizer1Cancel->SetLabel( _( "Close" ) );
464 m_sdbSizer1OK->Enable( true );
465 m_deleteOneMarker->Enable( true );
466 m_deleteAllMarkers->Enable( true );
467 m_saveReport->Enable( true );
468
469 if( !m_cancelled )
470 {
471 m_sdbSizer1Cancel->SetDefault();
472 // wxWidgets has a tendency to keep both buttons highlighted without the following:
473 m_sdbSizer1OK->Enable( false );
474
475 wxMilliSleep( 500 );
476 m_runningResultsBook->ChangeSelection( 1 );
478
479 // now re-enable m_sdbSizerOK button
480 m_sdbSizer1OK->Enable( true );
481 }
482
483 m_ercRun = true;
486 // set float level again, it can be lost due to window events during test run
488}
489
490
492{
493 WINDOW_THAWER thawer( m_parent );
494
496}
497
498
500{
501 wxFileName fn;
502
503 SCHEMATIC* sch = &m_parent->Schematic();
504
505 SCH_SCREENS screens( sch->Root() );
506 ERC_TESTER tester( sch );
507
508 {
509 wxBusyCursor dummy;
512 }
513
514 // Update marker list:
516
517 // Display new markers from the current screen:
518 for( SCH_ITEM* marker : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
519 {
520 m_parent->GetCanvas()->GetView()->Remove( marker );
521 m_parent->GetCanvas()->GetView()->Add( marker );
522 }
523
525}
526
527
528void DIALOG_ERC::OnERCItemSelected( wxDataViewEvent& aEvent )
529{
530 const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
531 SCH_SHEET_PATH sheet;
532 SCH_ITEM* item = m_parent->Schematic().GetItem( itemID, &sheet );
533
535 {
536 // we already came from a cross-probe of the marker in the document; don't go
537 // around in circles
538 }
539 else if( item && item->GetClass() != wxT( "DELETED_SHEET_ITEM" ) )
540 {
541 const RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
542
543 if( node )
544 {
545 // Determine the owning sheet for sheet-specific items
546 std::shared_ptr<ERC_ITEM> ercItem =
547 std::static_pointer_cast<ERC_ITEM>( node->m_RcItem );
548 switch( node->m_Type )
549 {
551 if( ercItem->IsSheetSpecific() )
552 sheet = ercItem->GetSpecificSheetPath();
553 break;
555 if( ercItem->MainItemHasSheetPath() )
556 sheet = ercItem->GetMainItemSheetPath();
557 break;
559 if( ercItem->AuxItemHasSheetPath() )
560 sheet = ercItem->GetAuxItemSheetPath();
561 break;
562 default:
563 break;
564 }
565 }
566
567 WINDOW_THAWER thawer( m_parent );
568
569 if( !sheet.empty() && sheet != m_parent->GetCurrentSheet() )
570 {
573
574 m_parent->SetCurrentSheet( sheet );
577 }
578
579 m_parent->FocusOnItem( item );
581 }
582
583 aEvent.Skip();
584}
585
586
587void DIALOG_ERC::OnERCItemDClick( wxDataViewEvent& aEvent )
588{
589 if( aEvent.GetItem().IsOk() )
590 {
591 // turn control over to m_parent, hide this DIALOG_ERC window,
592 // no destruction so we can preserve listbox cursor
593 if( !IsModal() )
594 Show( false );
595 }
596
597 aEvent.Skip();
598}
599
600
601void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
602{
604 EE_INSPECTION_TOOL* inspectionTool = toolMgr->GetTool<EE_INSPECTION_TOOL>();
605 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
606
607 if( !node )
608 return;
609
611
612 std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
613 wxString listName;
614 wxMenu menu;
615
616 switch( settings.GetSeverity( rcItem->GetErrorCode() ) )
617 {
618 case RPT_SEVERITY_ERROR: listName = _( "errors" ); break;
619 case RPT_SEVERITY_WARNING: listName = _( "warnings" ); break;
620 default: listName = _( "appropriate" ); break;
621 }
622
623 enum MENU_IDS
624 {
625 ID_EDIT_EXCLUSION_COMMENT = 4467,
626 ID_REMOVE_EXCLUSION,
627 ID_REMOVE_EXCLUSION_ALL,
628 ID_ADD_EXCLUSION,
629 ID_ADD_EXCLUSION_WITH_COMMENT,
630 ID_ADD_EXCLUSION_ALL,
631 ID_INSPECT_VIOLATION,
632 ID_EDIT_PIN_CONFLICT_MAP,
633 ID_EDIT_CONNECTION_GRID,
634 ID_SET_SEVERITY_TO_ERROR,
635 ID_SET_SEVERITY_TO_WARNING,
636 ID_SET_SEVERITY_TO_IGNORE,
637 ID_EDIT_SEVERITIES,
638 };
639
640 if( rcItem->GetParent()->IsExcluded() )
641 {
642 menu.Append( ID_REMOVE_EXCLUSION,
643 _( "Remove exclusion for this violation" ),
644 wxString::Format( _( "It will be placed back in the %s list" ), listName ) );
645
646 menu.Append( ID_EDIT_EXCLUSION_COMMENT,
647 _( "Edit exclusion comment..." ) );
648 }
649 else
650 {
651 menu.Append( ID_ADD_EXCLUSION,
652 _( "Exclude this violation" ),
653 wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
654
655 menu.Append( ID_ADD_EXCLUSION_WITH_COMMENT,
656 _( "Exclude with comment..." ),
657 wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
658 }
659
660 wxString inspectERCErrorMenuText = inspectionTool->InspectERCErrorMenuText( rcItem );
661
662 if( !inspectERCErrorMenuText.IsEmpty() )
663 menu.Append( ID_INSPECT_VIOLATION, inspectERCErrorMenuText );
664
665 menu.AppendSeparator();
666
667 if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_WARNING
668 || rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
669 {
670 // Pin to pin severities edited through pin conflict map
671 }
672 else if( settings.GetSeverity( rcItem->GetErrorCode() ) == RPT_SEVERITY_WARNING )
673 {
674 menu.Append( ID_SET_SEVERITY_TO_ERROR,
675 wxString::Format( _( "Change severity to Error for all '%s' violations" ),
676 rcItem->GetErrorText() ),
677 _( "Violation severities can also be edited in the Schematic Setup... dialog" ) );
678 }
679 else
680 {
681 menu.Append( ID_SET_SEVERITY_TO_WARNING,
682 wxString::Format( _( "Change severity to Warning for all '%s' violations" ),
683 rcItem->GetErrorText() ),
684 _( "Violation severities can also be edited in the Schematic Setup... dialog" ) );
685 }
686
687 menu.Append( ID_SET_SEVERITY_TO_IGNORE,
688 wxString::Format( _( "Ignore all '%s' violations" ), rcItem->GetErrorText() ),
689 _( "Violations will not be checked or reported" ) );
690
691 menu.AppendSeparator();
692
693 if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_WARNING
694 || rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
695 {
696 menu.Append( ID_EDIT_PIN_CONFLICT_MAP,
697 _( "Edit pin-to-pin conflict map..." ),
698 _( "Open the Schematic Setup... dialog" ) );
699 }
700 else
701 {
702 menu.Append( ID_EDIT_SEVERITIES,
703 _( "Edit violation severities..." ),
704 _( "Open the Schematic Setup... dialog" ) );
705 }
706
707 if( rcItem->GetErrorCode() == ERCE_ENDPOINT_OFF_GRID )
708 {
709 menu.Append( ID_EDIT_CONNECTION_GRID,
710 _( "Edit connection grid spacing..." ),
711 _( "Open the Schematic Setup... dialog" ) );
712 }
713
714 bool modified = false;
715 int command = GetPopupMenuSelectionFromUser( menu );
716
717 switch( command )
718 {
719 case ID_EDIT_EXCLUSION_COMMENT:
720 if( SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ) )
721 {
722 WX_TEXT_ENTRY_DIALOG dlg( this, wxEmptyString, _( "Exclusion Comment" ),
723 marker->GetComment(), true );
724
725 if( dlg.ShowModal() == wxID_CANCEL )
726 break;
727
728 marker->SetExcluded( true, dlg.GetValue() );
729
730 // Update view
731 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
732 modified = true;
733 }
734
735 break;
736
737 case ID_REMOVE_EXCLUSION:
738 if( SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ) )
739 {
740 marker->SetExcluded( false );
741 m_parent->GetCanvas()->GetView()->Update( marker );
742
743 // Update view
744 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
745 modified = true;
746 }
747
748 break;
749
750 case ID_ADD_EXCLUSION:
751 case ID_ADD_EXCLUSION_WITH_COMMENT:
752 if( SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ) )
753 {
754 wxString comment;
755
756 if( command == ID_ADD_EXCLUSION_WITH_COMMENT )
757 {
758 WX_TEXT_ENTRY_DIALOG dlg( this, wxEmptyString, _( "Exclusion Comment" ),
759 wxEmptyString, true );
760
761 if( dlg.ShowModal() == wxID_CANCEL )
762 break;
763
764 comment = dlg.GetValue();
765 }
766
767 marker->SetExcluded( true, comment );
768
769 m_parent->GetCanvas()->GetView()->Update( marker );
770
771 // Update view
773 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
774 else
775 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->DeleteCurrentItem( false );
776
777 modified = true;
778 }
779
780 break;
781
782 case ID_INSPECT_VIOLATION:
783 inspectionTool->InspectERCError( node->m_RcItem );
784 break;
785
786 case ID_SET_SEVERITY_TO_ERROR:
787 settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_ERROR );
788
789 for( SCH_ITEM* item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
790 {
791 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
792
793 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
794 m_parent->GetCanvas()->GetView()->Update( marker );
795 }
796
797 // Rebuild model and view
798 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
799 modified = true;
800 break;
801
802 case ID_SET_SEVERITY_TO_WARNING:
803 settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_WARNING );
804
805 for( SCH_ITEM* item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
806 {
807 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
808
809 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
810 m_parent->GetCanvas()->GetView()->Update( marker );
811 }
812
813 // Rebuild model and view
814 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
815 modified = true;
816 break;
817
818 case ID_SET_SEVERITY_TO_IGNORE:
819 {
820 settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_IGNORE );
821
822 if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
824
825 wxListItem listItem;
826 listItem.SetId( m_ignoredList->GetItemCount() );
827 listItem.SetText( wxT( " • " ) + rcItem->GetErrorText() );
828 listItem.SetData( rcItem->GetErrorCode() );
829
830 m_ignoredList->InsertItem( listItem );
831
832 // Clear the selection before deleting markers. It may be some selected ERC markers.
833 // Deleting a selected marker without deselecting it first generates a crash
835
836 SCH_SCREENS ScreenList( m_parent->Schematic().Root() );
837 ScreenList.DeleteMarkers( MARKER_BASE::MARKER_ERC, rcItem->GetErrorCode() );
838
839 // Rebuild model and view
840 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
841 modified = true;
842 }
843 break;
844
845 case ID_EDIT_PIN_CONFLICT_MAP:
846 m_parent->ShowSchematicSetupDialog( _( "Pin Conflicts Map" ) );
847 break;
848
849 case ID_EDIT_SEVERITIES:
850 m_parent->ShowSchematicSetupDialog( _( "Violation Severity" ) );
851 break;
852
853 case ID_EDIT_CONNECTION_GRID:
854 m_parent->ShowSchematicSetupDialog( _( "Formatting" ) );
855 break;
856 }
857
858 if( modified )
859 {
863 }
864}
865
866
867void DIALOG_ERC::OnIgnoredItemRClick( wxListEvent& event )
868{
870 int errorCode = (int) event.m_item.GetData();
871 wxMenu menu;
872
873 menu.Append( RPT_SEVERITY_ERROR, _( "Error" ), wxEmptyString, wxITEM_CHECK );
874 menu.Append( RPT_SEVERITY_WARNING, _( "Warning" ), wxEmptyString, wxITEM_CHECK );
875 menu.Append( RPT_SEVERITY_IGNORE, _( "Ignore" ), wxEmptyString, wxITEM_CHECK );
876
877 menu.Check( settings.GetSeverity( errorCode ), true );
878
879 int severity = GetPopupMenuSelectionFromUser( menu );
880
881 if( severity > 0 )
882 {
883 if( settings.GetSeverity( errorCode ) != severity )
884 {
885 settings.SetSeverity( errorCode, (SEVERITY) severity );
886
890 }
891 }
892}
893
894
896{
897 if( m_notebook->IsShown() )
898 {
899 if( m_notebook->GetSelection() != 0 )
900 m_notebook->SetSelection( 0 );
901
903 }
904}
905
906
908{
909 if( m_notebook->IsShown() )
910 {
911 if( m_notebook->GetSelection() != 0 )
912 m_notebook->SetSelection( 0 );
913
915 }
916}
917
918
920{
921 if( m_notebook->IsShown() )
922 {
923 m_notebook->SetSelection( 0 );
925
926 // wxWidgets on some platforms fails to correctly ensure that a selected item is
927 // visible, so we have to do it in a separate idle event.
928 m_centerMarkerOnIdle = aMarker;
929 Bind( wxEVT_IDLE, &DIALOG_ERC::centerMarkerIdleHandler, this );
930 }
931}
932
933
934void DIALOG_ERC::centerMarkerIdleHandler( wxIdleEvent& aEvent )
935{
937 m_centerMarkerOnIdle = nullptr;
938 Unbind( wxEVT_IDLE, &DIALOG_ERC::centerMarkerIdleHandler, this );
939}
940
941
943{
944 SCH_MARKER* marker = aMarker;
945
946 if( marker != nullptr )
948
949 if( m_notebook->GetSelection() != 0 )
950 return;
951
952 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( m_markerDataView->GetCurrentItem() );
953
954 if( node && node->m_RcItem )
955 marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() );
956
957 if( node && marker && !marker->IsExcluded() )
958 {
959 marker->SetExcluded( true );
960 m_parent->GetCanvas()->GetView()->Update( marker );
961
962 // Update view
965 else
967
971 }
972}
973
974
975void DIALOG_ERC::OnEditViolationSeverities( wxHyperlinkEvent& aEvent )
976{
977 m_parent->ShowSchematicSetupDialog( _( "Violation Severity" ) );
978}
979
980
981void DIALOG_ERC::OnSeverity( wxCommandEvent& aEvent )
982{
983 int flag = 0;
984
985 if( aEvent.GetEventObject() == m_showAll )
987 else if( aEvent.GetEventObject() == m_showErrors )
989 else if( aEvent.GetEventObject() == m_showWarnings )
991 else if( aEvent.GetEventObject() == m_showExclusions )
993
994 if( aEvent.IsChecked() )
996 else if( aEvent.GetEventObject() == m_showAll )
998 else
999 m_severities &= ~flag;
1000
1002
1005}
1006
1007
1008void DIALOG_ERC::deleteAllMarkers( bool aIncludeExclusions )
1009{
1010 // Clear current selection list to avoid selection of deleted items
1012
1013 m_markerTreeModel->DeleteItems( false, aIncludeExclusions, false );
1014
1015 SCH_SCREENS screens( m_parent->Schematic().Root() );
1016 screens.DeleteAllMarkers( MARKER_BASE::MARKER_ERC, aIncludeExclusions );
1017}
1018
1019
1020void DIALOG_ERC::OnSaveReport( wxCommandEvent& aEvent )
1021{
1022 wxFileName fn( wxS( "ERC." ) + wxString( FILEEXT::ReportFileExtension ) );
1023
1024 wxFileDialog dlg( this, _( "Save Report File" ), Prj().GetProjectPath(), fn.GetFullName(),
1026 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1027
1028 if( dlg.ShowModal() != wxID_OK )
1029 return;
1030
1031 fn = dlg.GetPath();
1032
1033 if( fn.GetExt().IsEmpty() )
1034 fn.SetExt( FILEEXT::ReportFileExtension );
1035
1036 if( !fn.IsAbsolute() )
1037 {
1038 wxString prj_path = Prj().GetProjectPath();
1039 fn.MakeAbsolute( prj_path );
1040 }
1041
1042 ERC_REPORT reportWriter( &m_parent->Schematic(), m_parent->GetUserUnits() );
1043
1044 bool success = false;
1045 if( fn.GetExt() == FILEEXT::JsonFileExtension )
1046 success = reportWriter.WriteJsonReport( fn.GetFullPath() );
1047 else
1048 success = reportWriter.WriteTextReport( fn.GetFullPath() );
1049
1050 if( success )
1051 {
1052 m_messages->Report( wxString::Format( _( "Report file '%s' created." ),
1053 fn.GetFullPath() ) );
1054 }
1055 else
1056 {
1057 DisplayError( this, wxString::Format( _( "Failed to create file '%s'." ),
1058 fn.GetFullPath() ) );
1059 }
1060}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
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:942
void OnIgnoredItemRClick(wxListEvent &aEvent) override
Definition: dialog_erc.cpp:867
const SCH_MARKER * m_centerMarkerOnIdle
Definition: dialog_erc.h:115
void OnERCItemDClick(wxDataViewEvent &aEvent) override
Definition: dialog_erc.cpp:587
std::shared_ptr< RC_ITEMS_PROVIDER > m_markerProvider
Definition: dialog_erc.h:109
void syncCheckboxes()
Definition: dialog_erc.cpp:374
bool m_ercRun
Definition: dialog_erc.h:113
DIALOG_ERC(SCH_EDIT_FRAME *parent)
Definition: dialog_erc.cpp:73
void testErc()
Definition: dialog_erc.cpp:499
void SelectMarker(const SCH_MARKER *aMarker)
Definition: dialog_erc.cpp:919
bool updateUI() override
Definition: dialog_erc.cpp:201
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:601
void centerMarkerIdleHandler(wxIdleEvent &aEvent)
Definition: dialog_erc.cpp:934
void OnDeleteAllClick(wxCommandEvent &event) override
Definition: dialog_erc.cpp:307
void OnLinkClicked(wxHtmlLinkEvent &event) override
Definition: dialog_erc.cpp:383
int m_severities
Definition: dialog_erc.h:117
void OnRunERCClick(wxCommandEvent &event) override
Definition: dialog_erc.cpp:390
void deleteAllMarkers(bool aIncludeExclusions)
wxString m_ignoredTitleTemplate
Definition: dialog_erc.h:107
void OnDeleteOneClick(wxCommandEvent &event) override
Definition: dialog_erc.cpp:290
void OnSaveReport(wxCommandEvent &aEvent) override
void PrevMarker()
Definition: dialog_erc.cpp:895
void NextMarker()
Definition: dialog_erc.cpp:907
SCHEMATIC * m_currentSchematic
Definition: dialog_erc.h:104
void OnEditViolationSeverities(wxHyperlinkEvent &aEvent) override
Definition: dialog_erc.cpp:975
void UpdateAnnotationWarning()
Definition: dialog_erc.cpp:165
void redrawDrawPanel()
Definition: dialog_erc.cpp:491
void Report(const wxString &aMessage) override
Display aMessage in the progress bar dialog.
Definition: dialog_erc.cpp:223
void OnERCItemSelected(wxDataViewEvent &aEvent) override
Definition: dialog_erc.cpp:528
RC_TREE_MODEL * m_markerTreeModel
Definition: dialog_erc.h:110
void updateDisplayedCounts()
Definition: dialog_erc.cpp:229
void OnSeverity(wxCommandEvent &aEvent) override
Definition: dialog_erc.cpp:981
bool m_running
Definition: dialog_erc.h:112
void OnCloseErcDialog(wxCloseEvent &event) override
Definition: dialog_erc.cpp:352
void OnCancelClick(wxCommandEvent &event) override
Definition: dialog_erc.cpp:338
bool Show(bool show) override
void SetupStandardButtons(std::map< int, wxString > aLabels={})
bool IsQuasiModal() const
Definition: dialog_shim.h:111
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:56
void InspectERCError(const std::shared_ptr< RC_ITEM > &aERCItem)
wxString InspectERCErrorMenuText(const std::shared_ptr< RC_ITEM > &aERCItem)
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Definition: erc_item.cpp:294
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.
Definition: erc_report.cpp:109
bool WriteTextReport(const wxString &aFullFileName)
Writes the text report also available via GetTextReport directly to a given file path.
Definition: erc_report.cpp:95
Container for ERC settings.
Definition: erc_settings.h:127
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:1571
A specialisation of the RC_TREE_MODEL class to enable ERC errors / warnings to be resolved in a speci...
Definition: erc_item.h:38
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:95
DS_PROXY_VIEW_ITEM * GetDrawingSheet() const
Definition: sch_view.h:103
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:317
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:357
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1687
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:202
@ FACE_CVPCB
Definition: kiway.h:288
bool IsExcluded() const
Definition: marker_base.h:98
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:112
void SetExcluded(bool aExcluded, const wxString &aComment=wxEmptyString)
Definition: marker_base.h:99
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:135
void PrevMarker()
Definition: rc_item.cpp:689
void SelectMarker(const MARKER_BASE *aMarker)
Definition: rc_item.cpp:738
static RC_TREE_NODE * ToNode(wxDataViewItem aItem)
Definition: rc_item.h:236
void ValueChanged(RC_TREE_NODE *aNode)
Definition: rc_item.cpp:517
void Update(std::shared_ptr< RC_ITEMS_PROVIDER > aProvider, int aSeverities)
Definition: rc_item.cpp:364
void DeleteItems(bool aCurrentOnly, bool aIncludeExclusions, bool aDeep)
Deletes the current item or all items.
Definition: rc_item.cpp:572
void DeleteCurrentItem(bool aDeep)
Definition: rc_item.cpp:566
void CenterMarker(const MARKER_BASE *aMarker)
Definition: rc_item.cpp:751
static KIID ToUUID(wxDataViewItem aItem)
Definition: rc_item.cpp:220
void NextMarker()
Definition: rc_item.cpp:710
std::shared_ptr< RC_ITEM > m_RcItem
Definition: rc_item.h:221
NODE_TYPE m_Type
Definition: rc_item.h:220
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:108
Holds all the data relating to one schematic.
Definition: schematic.h:76
void RecordERCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: schematic.cpp:811
SCH_ITEM * GetItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr) const
Definition: schematic.h:108
SCH_SHEET & Root() const
Definition: schematic.h:113
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:304
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
void OnAnnotate(wxCommandEvent &event)
int CheckAnnotate(ANNOTATION_ERROR_HANDLER aErrorHandler, ANNOTATE_SCOPE_T aAnnotateScope=ANNOTATE_ALL, bool aRecursive=true)
Check for annotation errors.
Definition: annotate.cpp:460
void SetCurrentSheet(const SCH_SHEET_PATH &aSheet)
void DisplayCurrentSheet()
Draw the current sheet on the display.
void FocusOnItem(SCH_ITEM *aItem)
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:166
wxString GetClass() const override
Return the class name.
Definition: sch_item.h:176
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:710
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:152
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:108
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:802
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()
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:304
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: wx_infobar.cpp:263
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: wx_infobar.cpp:154
A KICAD version of wxTextEntryDialog which supports the various improvements/work-arounds from DIALOG...
wxString GetValue() const
The common library.
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
This file is part of the common library.
static int RPT_SEVERITY_ALL
Definition: dialog_erc.cpp:371
static int DEFAULT_SINGLE_COL_WIDTH
Definition: dialog_erc.cpp:64
static bool g_lastERCRun
Definition: dialog_erc.cpp:68
wxDEFINE_EVENT(EDA_EVT_CLOSE_ERC_DIALOG, wxCommandEvent)
static std::vector< std::pair< wxString, int > > g_lastERCIgnored
Definition: dialog_erc.cpp:70
static SCHEMATIC * g_lastERCSchematic
Definition: dialog_erc.cpp:67
#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:37
@ ERCE_ENDPOINT_OFF_GRID
Pin or wire-end off grid.
Definition: erc_settings.h:41
@ ERCE_PIN_TO_PIN_WARNING
Definition: erc_settings.h:96
@ ERCE_PIN_TO_PIN_ERROR
Definition: erc_settings.h:97
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:329
void ForceFocus(wxWindow *aWindow)
Pass the current focus to the window.
Definition: wxgtk/ui.cpp:67
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:158
Definition of file extensions used in Kicad.
static int RPT_SEVERITY_ALL