KiCad PCB EDA Suite
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-2022 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 <gestfich.h>
27#include <sch_screen.h>
28#include <sch_edit_frame.h>
29#include <schematic.h>
30#include <project.h>
31#include <kiface_base.h>
32#include <reporter.h>
34#include <sch_marker.h>
35#include <connection_graph.h>
36#include <tools/ee_actions.h>
38#include <dialog_erc.h>
39#include <erc.h>
40#include <id.h>
41#include <confirm.h>
43#include <wx/ffile.h>
44#include <wx/filedlg.h>
45#include <wx/hyperlink.h>
46#include <erc_item.h>
47#include <eeschema_settings.h>
48#include <string_utils.h>
49#include <kiplatform/ui.h>
50
51// wxWidgets spends *far* too long calcuating column widths (most of it, believe it or
52// not, in repeatedly creating/destroying a wxDC to do the measurement in).
53// Use default column widths instead.
54static int DEFAULT_SINGLE_COL_WIDTH = 660;
55
56
57static SCHEMATIC* g_lastERCSchematic = nullptr;
58static bool g_lastERCRun = false;
59static std::vector<wxString> g_lastERCIgnored;
60
61
63 DIALOG_ERC_BASE( parent ),
65 m_parent( parent ),
66 m_markerTreeModel( nullptr ),
67 m_running( false ),
68 m_ercRun( false ),
69 m_centerMarkerOnIdle( nullptr ),
70 m_severities( 0 )
71{
72 m_currentSchematic = &parent->Schematic();
73
74 SetName( DIALOG_ERC_WINDOW_NAME ); // Set a window name to be able to find it
75
76 EESCHEMA_SETTINGS* settings = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
78
80
81 m_markerProvider = std::make_shared<SHEETLIST_ERC_ITEMS_PROVIDER>( &m_parent->Schematic() );
82
84 m_markerDataView->AssociateModel( m_markerTreeModel );
86
87 m_ignoredList->InsertColumn( 0, wxEmptyString, wxLIST_FORMAT_LEFT, DEFAULT_SINGLE_COL_WIDTH );
88
90 {
92
93 for( const wxString& str : g_lastERCIgnored )
94 m_ignoredList->InsertItem( m_ignoredList->GetItemCount(), str );
95 }
96
97 m_notebook->SetSelection( 0 );
98
99 SetupStandardButtons( { { wxID_OK, _( "Run ERC" ) },
100 { wxID_CANCEL, _( "Close" ) } } );
101
102 m_violationsTitleTemplate = m_notebook->GetPageText( 0 );
103 m_ignoredTitleTemplate = m_notebook->GetPageText( 1 );
104
108
110
111 Layout();
112
113 SetFocus();
114
117
118 // Now all widgets have the size fixed, call FinishDialogSettings
120}
121
122
124{
127
128 g_lastERCIgnored.clear();
129
130 for( int ii = 0; ii < m_ignoredList->GetItemCount(); ++ii )
131 g_lastERCIgnored.push_back( m_ignoredList->GetItemText( ii ) );
132
133 EESCHEMA_SETTINGS* settings = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
134 wxASSERT( settings );
135
136 if( settings )
138
139 m_markerTreeModel->DecRef();
140}
141
142
144{
145 if( m_parent->CheckAnnotate( []( ERCE_T, const wxString&, SCH_REFERENCE*, SCH_REFERENCE* )
146 { } ) )
147 {
148 if( !m_infoBar->IsShown() )
149 {
150 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( m_infoBar, wxID_ANY,
151 _( "Show Annotation dialog" ),
152 wxEmptyString );
153
154 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
155 [&]( wxHyperlinkEvent& aEvent )
156 {
157 wxHtmlLinkEvent htmlEvent( aEvent.GetId(),
158 wxHtmlLinkInfo( aEvent.GetURL() ) );
159 OnLinkClicked( htmlEvent );
160 } ) );
161
163 m_infoBar->AddButton( button );
164 m_infoBar->ShowMessage( _( "Schematic is not fully annotated. "
165 "ERC results will be incomplete." ) );
166 }
167 }
168 else
169 {
170 if( m_infoBar->IsShown() )
171 {
173 m_infoBar->Hide();
174 }
175 }
176}
177
178
179// PROGRESS_REPORTER calls
180
182{
183 // If ERC checks ever get slow enough we'll want a progress indicator...
184 //
185 // double cur = (double) m_progress.load() / m_maxProgress;
186 // cur = std::max( 0.0, std::min( cur, 1.0 ) );
187 //
188 // m_gauge->SetValue( KiROUND( cur * 1000.0 ) );
189 // wxSafeYield( this );
190
191 return !m_cancelled;
192}
193
194
195void DIALOG_ERC::AdvancePhase( const wxString& aMessage )
196{
197 // Will also call Report( aMessage ):
199 SetCurrentProgress( 0.0 );
200}
201
202
203void DIALOG_ERC::Report( const wxString& aMessage )
204{
205 m_messages->Report( aMessage );
206}
207
208
210{
211 int numErrors = 0;
212 int numWarnings = 0;
213 int numExcluded = 0;
214
215 int numMarkers = 0;
216
217 if( m_markerProvider )
218 {
219 numMarkers += m_markerProvider->GetCount();
220 numErrors += m_markerProvider->GetCount( RPT_SEVERITY_ERROR );
221 numWarnings += m_markerProvider->GetCount( RPT_SEVERITY_WARNING );
222 numExcluded += m_markerProvider->GetCount( RPT_SEVERITY_EXCLUSION );
223 }
224
225 bool markersOverflowed = false;
226
227 // We don't currently have a limit on ERC violations, so the above is always false.
228
229 wxString num;
230 wxString msg;
231
232 if( m_ercRun )
233 {
234 num.Printf( markersOverflowed ? wxT( "%d+" ) : wxT( "%d" ), numMarkers );
235 msg.Printf( m_violationsTitleTemplate, num );
236 }
237 else
238 {
240 msg.Replace( wxT( "(%s)" ), wxEmptyString );
241 }
242
243 m_notebook->SetPageText( 0, msg );
244
245 if( m_ercRun )
246 {
247 num.Printf( wxT( "%d" ), m_ignoredList->GetItemCount() );
248 msg.sprintf( m_ignoredTitleTemplate, num );
249 }
250 else
251 {
253 msg.Replace( wxT( "(%s)" ), wxEmptyString );
254 }
255
256 m_notebook->SetPageText( 1, msg );
257
258 if( !m_ercRun && numErrors == 0 )
259 numErrors = -1;
260
261 if( !m_ercRun && numWarnings == 0 )
262 numWarnings = -1;
263
267}
268
269
270void DIALOG_ERC::OnDeleteOneClick( wxCommandEvent& aEvent )
271{
272 if( m_notebook->GetSelection() == 0 )
273 {
274 // Clear the selection. It may be the selected ERC marker.
276
278
279 // redraw the schematic
281 }
282
284}
285
286
287/* Delete the old ERC markers, over the whole hierarchy
288 */
289void DIALOG_ERC::OnDeleteAllClick( wxCommandEvent& event )
290{
291 bool includeExclusions = false;
292 int numExcluded = 0;
293
294 if( m_markerProvider )
295 numExcluded += m_markerProvider->GetCount( RPT_SEVERITY_EXCLUSION );
296
297 if( numExcluded > 0 )
298 {
299 wxMessageDialog dlg( this, _( "Delete exclusions too?" ), _( "Delete All Markers" ),
300 wxYES_NO | wxCANCEL | wxCENTER | wxICON_QUESTION );
301 dlg.SetYesNoLabels( _( "Errors and Warnings Only" ) , _( "Errors, Warnings and Exclusions" ) );
302
303 int ret = dlg.ShowModal();
304
305 if( ret == wxID_CANCEL )
306 return;
307 else if( ret == wxID_NO )
308 includeExclusions = true;
309 }
310
311 deleteAllMarkers( includeExclusions );
312
313 // redraw the schematic
316}
317
318
319// This is a modeless dialog so we have to handle these ourselves.
320void DIALOG_ERC::OnCancelClick( wxCommandEvent& aEvent )
321{
322 if( m_running )
323 {
324 m_cancelled = true;
325 return;
326 }
327
328 m_parent->FocusOnItem( nullptr );
329
330 Close();
331}
332
333
334void DIALOG_ERC::OnCloseErcDialog( wxCloseEvent& event )
335{
336 m_parent->FocusOnItem( nullptr );
337
338 m_parent->GetToolManager()->GetTool<EE_INSPECTION_TOOL>()->DestroyERCDialog();
339}
340
341
343
344
346{
351}
352
353
354void DIALOG_ERC::OnLinkClicked( wxHtmlLinkEvent& event )
355{
356 wxCommandEvent dummy;
358}
359
360
361void DIALOG_ERC::OnRunERCClick( wxCommandEvent& event )
362{
363 wxBusyCursor busy;
364
365 SCHEMATIC* sch = &m_parent->Schematic();
366
368
370 deleteAllMarkers( true );
371
372 std::vector<std::reference_wrapper<RC_ITEM>> violations = ERC_ITEM::GetItemsWithSeverities();
373 m_ignoredList->DeleteAllItems();
374
375 for( std::reference_wrapper<RC_ITEM>& item : violations )
376 {
377 if( sch->ErcSettings().GetSeverity( item.get().GetErrorCode() ) == RPT_SEVERITY_IGNORE )
378 {
379 m_ignoredList->InsertItem( m_ignoredList->GetItemCount(),
380 wxT( " • " ) + item.get().GetErrorText() );
381 }
382 }
383
384 Raise();
385
386 m_runningResultsBook->ChangeSelection( 0 ); // Display the "Tests Running..." tab
387 m_messages->Clear();
388 wxYield(); // Allow time slice to refresh Messages
389
390 m_running = true;
391 m_sdbSizer1Cancel->SetLabel( _( "Cancel" ) );
392 m_sdbSizer1OK->Enable( false );
393 m_deleteOneMarker->Enable( false );
394 m_deleteAllMarkers->Enable( false );
395 m_saveReport->Enable( false );
396
398
399 int itemsNotAnnotated = m_parent->CheckAnnotate(
400 []( ERCE_T aType, const wxString& aMsg, SCH_REFERENCE* aItemA, SCH_REFERENCE* aItemB )
401 {
402 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( aType );
403 ercItem->SetErrorMessage( aMsg );
404
405 if( aItemB )
406 ercItem->SetItems( aItemA->GetSymbol(), aItemB->GetSymbol() );
407 else
408 ercItem->SetItems( aItemA->GetSymbol() );
409
410 SCH_MARKER* marker = new SCH_MARKER( ercItem, aItemA->GetSymbol()->GetPosition() );
411 aItemA->GetSheetPath().LastScreen()->Append( marker );
412 } );
413
414 testErc();
415
416 if( itemsNotAnnotated )
417 m_messages->ReportHead( wxString::Format( _( "%d symbol(s) require annotation.<br><br>" ),
418 itemsNotAnnotated ), RPT_SEVERITY_INFO );
419
420 if( m_cancelled )
421 m_messages->Report( _( "-------- ERC cancelled by user.<br><br>" ), RPT_SEVERITY_INFO );
422 else
423 m_messages->Report( _( "Done.<br><br>" ), RPT_SEVERITY_INFO );
424
425 Raise();
426 wxYield(); // Allow time slice to refresh Messages
427
428 m_running = false;
429 m_sdbSizer1Cancel->SetLabel( _( "Close" ) );
430 m_sdbSizer1OK->Enable( true );
431 m_deleteOneMarker->Enable( true );
432 m_deleteAllMarkers->Enable( true );
433 m_saveReport->Enable( true );
434
435 if( !m_cancelled )
436 {
437 wxMilliSleep( 500 );
438 m_runningResultsBook->ChangeSelection( 1 );
440 }
441
442 m_ercRun = true;
445}
446
447
449{
450 WINDOW_THAWER thawer( m_parent );
451
453}
454
455
457{
458 wxFileName fn;
459
460 SCHEMATIC* sch = &m_parent->Schematic();
461
462 // Build the whole sheet list in hierarchy (sheet, not screen)
464
465 SCH_SCREENS screens( sch->Root() );
466 ERC_SETTINGS& settings = sch->ErcSettings();
467 ERC_TESTER tester( sch );
468
469 // Test duplicate sheet names inside a given sheet. While one can have multiple references
470 // to the same file, each must have a unique name.
472 {
473 AdvancePhase( _( "Checking sheet names..." ) );
474 tester.TestDuplicateSheetNames( true );
475 }
476
477 if( settings.IsTestEnabled( ERCE_BUS_ALIAS_CONFLICT ) )
478 {
479 AdvancePhase( _( "Checking bus conflicts..." ) );
481 }
482
483 // The connection graph has a whole set of ERC checks it can run
484 AdvancePhase( _( "Checking conflicts..." ) );
486 sch->ConnectionGraph()->RunERC();
487
488 // Test is all units of each multiunit symbol have the same footprint assigned.
489 if( settings.IsTestEnabled( ERCE_DIFFERENT_UNIT_FP ) )
490 {
491 AdvancePhase( _( "Checking footprints..." ) );
493 }
494
495 AdvancePhase( _( "Checking pins..." ) );
496
497 if( settings.IsTestEnabled( ERCE_DIFFERENT_UNIT_NET ) )
499
500 // Test pins on each net against the pin connection table
503 || settings.IsTestEnabled( ERCE_PIN_NOT_DRIVEN ) )
504 {
505 tester.TestPinToPin();
506 }
507
508 // Test similar labels (i;e. labels which are identical when
509 // using case insensitive comparisons)
510 if( settings.IsTestEnabled( ERCE_SIMILAR_LABELS ) )
511 {
512 AdvancePhase( _( "Checking labels..." ) );
513 tester.TestSimilarLabels();
514 }
515
517 {
518 AdvancePhase( _( "Checking for unresolved variables..." ) );
520 }
521
522 if( settings.IsTestEnabled( ERCE_SIMULATION_MODEL ) )
523 {
524 AdvancePhase( _( "Checking SPICE models..." ) );
525 tester.TestSimModelIssues();
526 }
527
529 {
530 AdvancePhase( _( "Checking no connect pins for connections..." ) );
531 tester.TestNoConnectPins();
532 }
533
534 if( settings.IsTestEnabled( ERCE_LIB_SYMBOL_ISSUES ) )
535 {
536 AdvancePhase( _( "Checking for library symbol issues..." ) );
537 tester.TestLibSymbolIssues();
538 }
539
540 if( settings.IsTestEnabled( ERCE_ENDPOINT_OFF_GRID ) )
541 {
542 AdvancePhase( _( "Checking for off grid pins and wires..." ) );
544 }
545
547
548 // Update marker list:
550
551 // Display new markers from the current screen:
552 for( SCH_ITEM* marker : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
553 {
554 m_parent->GetCanvas()->GetView()->Remove( marker );
555 m_parent->GetCanvas()->GetView()->Add( marker );
556 }
557
559}
560
561
562void DIALOG_ERC::OnERCItemSelected( wxDataViewEvent& aEvent )
563{
564 const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
565 SCH_SHEET_PATH sheet;
566 SCH_ITEM* item = m_parent->Schematic().GetSheets().GetItem( itemID, &sheet );
567
569 {
570 // we already came from a cross-probe of the marker in the document; don't go
571 // around in circles
572 }
573 else if( item && item->GetClass() != wxT( "DELETED_SHEET_ITEM" ) )
574 {
575 WINDOW_THAWER thawer( m_parent );
576
577 if( !sheet.empty() && sheet != m_parent->GetCurrentSheet() )
578 {
581
582 m_parent->SetCurrentSheet( sheet );
584 m_parent->RedrawScreen( (wxPoint) m_parent->GetScreen()->m_ScrollCenter, false );
585 }
586
587 m_parent->FocusOnItem( item );
589 }
590
591 aEvent.Skip();
592}
593
594
595void DIALOG_ERC::OnERCItemDClick( wxDataViewEvent& aEvent )
596{
597 if( aEvent.GetItem().IsOk() )
598 {
599 // turn control over to m_parent, hide this DIALOG_ERC window,
600 // no destruction so we can preserve listbox cursor
601 if( !IsModal() )
602 Show( false );
603 }
604
605 aEvent.Skip();
606}
607
608
609void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
610{
611 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
612
613 if( !node )
614 return;
615
617
618 std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
619 wxString listName;
620 wxMenu menu;
621
622 switch( settings.GetSeverity( rcItem->GetErrorCode() ) )
623 {
624 case RPT_SEVERITY_ERROR: listName = _( "errors" ); break;
625 case RPT_SEVERITY_WARNING: listName = _( "warnings" ); break;
626 default: listName = _( "appropriate" ); break;
627 }
628
629 if( rcItem->GetParent()->IsExcluded() )
630 {
631 menu.Append( 1, _( "Remove exclusion for this violation" ),
632 wxString::Format( _( "It will be placed back in the %s list" ), listName ) );
633 }
634 else
635 {
636 menu.Append( 2, _( "Exclude this violation" ),
637 wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
638 }
639
640 menu.AppendSeparator();
641
642 if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_WARNING
643 || rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
644 {
645 // Pin to pin severities edited through pin conflict map
646 }
647 else if( settings.GetSeverity( rcItem->GetErrorCode() ) == RPT_SEVERITY_WARNING )
648 {
649 menu.Append( 4, wxString::Format( _( "Change severity to Error for all '%s' violations" ),
650 rcItem->GetErrorText() ),
651 _( "Violation severities can also be edited in the Board Setup... dialog" ) );
652 }
653 else
654 {
655 menu.Append( 5, wxString::Format( _( "Change severity to Warning for all '%s' violations" ),
656 rcItem->GetErrorText() ),
657 _( "Violation severities can also be edited in the Board Setup... dialog" ) );
658 }
659
660 menu.Append( 6, wxString::Format( _( "Ignore all '%s' violations" ), rcItem->GetErrorText() ),
661 _( "Violations will not be checked or reported" ) );
662
663 menu.AppendSeparator();
664
665 if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_WARNING
666 || rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
667 {
668 menu.Append( 7, _( "Edit pin-to-pin conflict map..." ) );
669 }
670 else
671 {
672 menu.Append( 8, _( "Edit violation severities..." ),
673 _( "Open the Schematic Setup... dialog" ) );
674 }
675
676 bool modified = false;
677
678 switch( GetPopupMenuSelectionFromUser( menu ) )
679 {
680 case 1:
681 {
682 SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() );
683
684 if( marker )
685 {
686 marker->SetExcluded( false );
687 m_parent->GetCanvas()->GetView()->Update( marker );
688
689 // Update view
690 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
691 modified = true;
692 }
693 }
694 break;
695
696 case 2:
697 {
698 SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() );
699
700 if( marker )
701 {
702 marker->SetExcluded( true );
703 m_parent->GetCanvas()->GetView()->Update( marker );
704
705 // Update view
707 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
708 else
709 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->DeleteCurrentItem( false );
710
711 modified = true;
712 }
713 }
714 break;
715
716 case 4:
717 settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_ERROR );
718
719 for( SCH_ITEM* item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
720 {
721 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
722
723 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
724 m_parent->GetCanvas()->GetView()->Update( marker );
725 }
726
727 // Rebuild model and view
728 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
729 modified = true;
730 break;
731
732 case 5:
733 settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_WARNING );
734
735 for( SCH_ITEM* item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
736 {
737 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
738
739 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
740 m_parent->GetCanvas()->GetView()->Update( marker );
741 }
742
743 // Rebuild model and view
744 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
745 modified = true;
746 break;
747
748 case 6:
749 {
750 settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_IGNORE );
751
752 if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
754
755 SCH_SCREENS ScreenList( m_parent->Schematic().Root() );
756 ScreenList.DeleteMarkers( MARKER_BASE::MARKER_ERC, rcItem->GetErrorCode() );
757
758 // Rebuild model and view
759 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
760 modified = true;
761 }
762 break;
763
764 case 7:
765 m_parent->ShowSchematicSetupDialog( _( "Pin Conflicts Map" ) );
766 break;
767
768 case 8:
769 m_parent->ShowSchematicSetupDialog( _( "Violation Severity" ) );
770 break;
771 }
772
773 if( modified )
774 {
778 }
779}
780
781
783{
784 if( m_notebook->IsShown() )
785 {
786 if( m_notebook->GetSelection() != 0 )
787 m_notebook->SetSelection( 0 );
788
790 }
791}
792
793
795{
796 if( m_notebook->IsShown() )
797 {
798 if( m_notebook->GetSelection() != 0 )
799 m_notebook->SetSelection( 0 );
800
802 }
803}
804
805
807{
808 if( m_notebook->IsShown() )
809 {
810 m_notebook->SetSelection( 0 );
812
813 // wxWidgets on some platforms fails to correctly ensure that a selected item is
814 // visible, so we have to do it in a separate idle event.
815 m_centerMarkerOnIdle = aMarker;
816 Bind( wxEVT_IDLE, &DIALOG_ERC::centerMarkerIdleHandler, this );
817 }
818}
819
820
821void DIALOG_ERC::centerMarkerIdleHandler( wxIdleEvent& aEvent )
822{
824 m_centerMarkerOnIdle = nullptr;
825 Unbind( wxEVT_IDLE, &DIALOG_ERC::centerMarkerIdleHandler, this );
826}
827
828
830{
831 SCH_MARKER* marker = aMarker;
832
833 if( marker != nullptr )
835
836 if( m_notebook->GetSelection() != 0 )
837 return;
838
839 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( m_markerDataView->GetCurrentItem() );
840
841 if( node && node->m_RcItem )
842 marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() );
843
844 if( node && marker && !marker->IsExcluded() )
845 {
846 marker->SetExcluded( true );
847 m_parent->GetCanvas()->GetView()->Update( marker );
848
849 // Update view
852 else
854
858 }
859}
860
861
862void DIALOG_ERC::OnIgnoreItemRClick( wxListEvent& event )
863{
864 wxMenu menu;
865
866 menu.Append( 1, _( "Edit ignored violations..." ), _( "Open the Schematic Setup... dialog" ) );
867
868 switch( GetPopupMenuSelectionFromUser( menu ) )
869 {
870 case 1:
871 m_parent->ShowSchematicSetupDialog( _( "Violation Severity" ) );
872 break;
873 }
874}
875
876
877void DIALOG_ERC::OnSeverity( wxCommandEvent& aEvent )
878{
879 int flag = 0;
880
881 if( aEvent.GetEventObject() == m_showAll )
883 else if( aEvent.GetEventObject() == m_showErrors )
885 else if( aEvent.GetEventObject() == m_showWarnings )
887 else if( aEvent.GetEventObject() == m_showExclusions )
889
890 if( aEvent.IsChecked() )
892 else if( aEvent.GetEventObject() == m_showAll )
894 else
895 m_severities &= ~flag;
896
898
901}
902
903
904void DIALOG_ERC::deleteAllMarkers( bool aIncludeExclusions )
905{
906 // Clear current selection list to avoid selection of deleted items
908
909 m_markerTreeModel->DeleteItems( false, aIncludeExclusions, false );
910
911 SCH_SCREENS screens( m_parent->Schematic().Root() );
912 screens.DeleteAllMarkers( MARKER_BASE::MARKER_ERC, aIncludeExclusions );
913}
914
915
916void DIALOG_ERC::OnSaveReport( wxCommandEvent& aEvent )
917{
918 wxFileName fn( "ERC." + ReportFileExtension );
919
920 wxFileDialog dlg( this, _( "Save Report to File" ), Prj().GetProjectPath(), fn.GetFullName(),
921 ReportFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
922
923 if( dlg.ShowModal() != wxID_OK )
924 return;
925
926 fn = dlg.GetPath();
927
928 if( fn.GetExt().IsEmpty() )
929 fn.SetExt( ReportFileExtension );
930
931 if( !fn.IsAbsolute() )
932 {
933 wxString prj_path = Prj().GetProjectPath();
934 fn.MakeAbsolute( prj_path );
935 }
936
937 if( writeReport( fn.GetFullPath() ) )
938 {
939 m_messages->Report( wxString::Format( _( "Report file '%s' created." ),
940 fn.GetFullPath() ) );
941 }
942 else
943 {
944 DisplayError( this, wxString::Format( _( "Failed to create file '%s'." ),
945 fn.GetFullPath() ) );
946 }
947}
948
949
950bool DIALOG_ERC::writeReport( const wxString& aFullFileName )
951{
952 wxFFile file( aFullFileName, wxT( "wt" ) );
953
954 if( !file.IsOpened() )
955 return false;
956
957 wxString msg = wxString::Format( _( "ERC report (%s, Encoding UTF8)\n" ), DateAndTime() );
958
959 std::map<KIID, EDA_ITEM*> itemMap;
960
961 int err_count = 0;
962 int warn_count = 0;
963 int total_count = 0;
965
966 sheetList.FillItemMap( itemMap );
967
969
970 for( unsigned i = 0; i < sheetList.size(); i++ )
971 {
972 msg << wxString::Format( _( "\n***** Sheet %s\n" ), sheetList[i].PathHumanReadable() );
973
974 for( SCH_ITEM* aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
975 {
976 const SCH_MARKER* marker = static_cast<const SCH_MARKER*>( aItem );
977 RC_ITEM* item = marker->GetRCItem().get();
978 SEVERITY severity = settings.GetSeverity( item->GetErrorCode() );
979
980 if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
981 continue;
982
983 total_count++;
984
985 switch( severity )
986 {
987 case RPT_SEVERITY_ERROR: err_count++; break;
988 case RPT_SEVERITY_WARNING: warn_count++; break;
989 default: break;
990 }
991
992 msg << marker->GetRCItem()->ShowReport( m_parent, severity, itemMap );
993 }
994 }
995
996 msg << wxString::Format( _( "\n ** ERC messages: %d Errors %d Warnings %d\n" ),
997 total_count, err_count, warn_count );
998
999 // Currently: write report using UTF8 (as usual in Kicad).
1000 // TODO: see if we can use the current encoding page (mainly for Windows users),
1001 // Or other format (HTML?)
1002 file.Write( msg );
1003
1004 // wxFFile dtor will close the file.
1005
1006 return true;
1007}
1008
1009
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
static TOOL_ACTION cancelInteractive
Definition: actions.h:63
VECTOR2D m_ScrollCenter
Current scroll center point in logical units.
Definition: base_screen.h:100
int RunERC()
Runs electrical rule checks on the connectivity graph.
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:829
const SCH_MARKER * m_centerMarkerOnIdle
Definition: dialog_erc.h:111
void OnERCItemDClick(wxDataViewEvent &aEvent) override
Definition: dialog_erc.cpp:595
std::shared_ptr< RC_ITEMS_PROVIDER > m_markerProvider
Definition: dialog_erc.h:105
void syncCheckboxes()
Definition: dialog_erc.cpp:345
bool m_ercRun
Definition: dialog_erc.h:109
DIALOG_ERC(SCH_EDIT_FRAME *parent)
Definition: dialog_erc.cpp:62
void testErc()
Definition: dialog_erc.cpp:456
void SelectMarker(const SCH_MARKER *aMarker)
Definition: dialog_erc.cpp:806
bool updateUI() override
Definition: dialog_erc.cpp:181
SCH_EDIT_FRAME * m_parent
Definition: dialog_erc.h:99
void OnIgnoreItemRClick(wxListEvent &event) override
Definition: dialog_erc.cpp:862
wxString m_violationsTitleTemplate
Definition: dialog_erc.h:102
void OnERCItemRClick(wxDataViewEvent &aEvent) override
Definition: dialog_erc.cpp:609
bool writeReport(const wxString &aFullFileName)
Definition: dialog_erc.cpp:950
void centerMarkerIdleHandler(wxIdleEvent &aEvent)
Definition: dialog_erc.cpp:821
void OnDeleteAllClick(wxCommandEvent &event) override
Definition: dialog_erc.cpp:289
void OnLinkClicked(wxHtmlLinkEvent &event) override
Definition: dialog_erc.cpp:354
int m_severities
Definition: dialog_erc.h:113
void OnRunERCClick(wxCommandEvent &event) override
Definition: dialog_erc.cpp:361
void deleteAllMarkers(bool aIncludeExclusions)
Definition: dialog_erc.cpp:904
wxString m_ignoredTitleTemplate
Definition: dialog_erc.h:103
void OnDeleteOneClick(wxCommandEvent &event) override
Definition: dialog_erc.cpp:270
void OnSaveReport(wxCommandEvent &aEvent) override
Definition: dialog_erc.cpp:916
void PrevMarker()
Definition: dialog_erc.cpp:782
void NextMarker()
Definition: dialog_erc.cpp:794
SCHEMATIC * m_currentSchematic
Definition: dialog_erc.h:100
void UpdateAnnotationWarning()
Definition: dialog_erc.cpp:143
void redrawDrawPanel()
Definition: dialog_erc.cpp:448
void Report(const wxString &aMessage) override
Display aMessage in the progress bar dialog.
Definition: dialog_erc.cpp:203
void OnERCItemSelected(wxDataViewEvent &aEvent) override
Definition: dialog_erc.cpp:562
RC_TREE_MODEL * m_markerTreeModel
Definition: dialog_erc.h:106
void updateDisplayedCounts()
Definition: dialog_erc.cpp:209
void OnSeverity(wxCommandEvent &aEvent) override
Definition: dialog_erc.cpp:877
bool m_running
Definition: dialog_erc.h:108
void OnCloseErcDialog(wxCloseEvent &event) override
Definition: dialog_erc.cpp:334
void OnCancelClick(wxCommandEvent &event) override
Definition: dialog_erc.cpp:320
bool Show(bool show) override
void SetupStandardButtons(std::map< int, wxString > aLabels={})
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
Update the board display after modifying it by a python script (note: it is automatically called by a...
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:56
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:207
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition: erc_item.h:50
Container for ERC settings.
Definition: erc_settings.h:110
bool IsTestEnabled(int aErrorCode) const
Definition: erc_settings.h:126
SEVERITY GetSeverity(int aErrorCode) const
void SetSeverity(int aErrorCode, SEVERITY aSeverity)
Definition: erc.h:48
int TestLibSymbolIssues()
Test symbols for changed library symbols and broken symbol library links.
Definition: erc.cpp:709
void TestTextVars(DS_PROXY_VIEW_ITEM *aDrawingSheet)
Check for any unresolved text variable references.
Definition: erc.cpp:169
int TestPinToPin()
Checks the full netlist against the pin-to-pin connectivity requirements.
Definition: erc.cpp:452
int TestSimilarLabels()
Checks for labels that differ only in capitalization.
Definition: erc.cpp:657
int TestDuplicateSheetNames(bool aCreateMarker)
Inside a given sheet, one cannot have sheets with duplicate names (file names can be duplicated).
Definition: erc.cpp:123
int TestMultUnitPinConflicts()
Checks if shared pins on multi-unit symbols have been connected to different nets.
Definition: erc.cpp:599
int TestOffGridEndpoints(int aGridSize)
Test pins and wire ends for being off grid.
Definition: erc.cpp:799
int TestConflictingBusAliases()
Check that there are no conflicting bus alias definitions in the schematic.
Definition: erc.cpp:298
int TestNoConnectPins()
In KiCad 5 and earlier, you could connect stuff up to pins with NC electrical type.
Definition: erc.cpp:410
int TestSimModelIssues()
Test SPICE models for various issues.
Definition: erc.cpp:871
int TestMultiunitFootprints()
Test if all units of each multiunit symbol have the same footprint assigned.
Definition: erc.cpp:345
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:93
const VECTOR2D & GetGridSize() const
Return the grid size.
DS_PROXY_VIEW_ITEM * GetDrawingSheet() const
Definition: sch_view.h:100
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:316
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:346
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:1574
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:195
Definition: kiid.h:48
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
bool IsExcluded() const
Definition: marker_base.h:97
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:105
enum TYPEMARKER GetMarkerType() const
Definition: marker_base.h:95
void SetExcluded(bool aExcluded)
Definition: marker_base.h:98
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 const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:126
A holder for a rule check item, DRC in Pcbnew or ERC in Eeschema.
Definition: rc_item.h:75
int GetErrorCode() const
Definition: rc_item.h:136
void PrevMarker()
Definition: rc_item.cpp:558
void SelectMarker(const MARKER_BASE *aMarker)
Definition: rc_item.cpp:607
static RC_TREE_NODE * ToNode(wxDataViewItem aItem)
Definition: rc_item.h:209
void Update(std::shared_ptr< RC_ITEMS_PROVIDER > aProvider, int aSeverities)
Definition: rc_item.cpp:289
void DeleteItems(bool aCurrentOnly, bool aIncludeExclusions, bool aDeep)
Deletes the current item or all items.
Definition: rc_item.cpp:469
void DeleteCurrentItem(bool aDeep)
Definition: rc_item.cpp:463
void CenterMarker(const MARKER_BASE *aMarker)
Definition: rc_item.cpp:620
static KIID ToUUID(wxDataViewItem aItem)
Definition: rc_item.cpp:149
void NextMarker()
Definition: rc_item.cpp:579
void ValueChanged(const RC_TREE_NODE *aNode)
Definition: rc_item.cpp:446
std::shared_ptr< RC_ITEM > m_RcItem
Definition: rc_item.h:194
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:61
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:130
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:86
SCH_SHEET & Root() const
Definition: schematic.h:91
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:179
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.
void RecordERCExclusions()
Scan existing markers and record data from any that are Excluded.
SCH_SHEET_PATH & GetCurrentSheet() const
SCHEMATIC & Schematic() const
void RecalculateConnections(SCH_CLEANUP_FLAGS aCleanupFlags)
Generate the connection data for the entire schematic hierarchy.
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:441
void SetCurrentSheet(const SCH_SHEET_PATH &aSheet)
void DisplayCurrentSheet()
Draw the current sheet on the display.
void ResolveERCExclusions()
Update markers to match recorded exclusions.
void FocusOnItem(SCH_ITEM *aItem)
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
virtual wxString GetClass() const override
Return the class name.
Definition: sch_item.h:157
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:608
void DeleteMarkers(enum MARKER_BASE::TYPEMARKER aMarkerTyp, int aErrorCode, bool aIncludeExclusions=true)
Delete all markers of a particular type and error code.
void DeleteAllMarkers(enum MARKER_BASE::TYPEMARKER aMarkerType, bool aIncludeExclusions)
Delete all electronic rules check markers of aMarkerType from all the screens in the list.
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:109
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:141
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
SCH_ITEM * GetItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr) const
Fetch a SCH_ITEM by ID.
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Fill an item cache for temporary use when many items need to be fetched.
void AnnotatePowerSymbols()
Silently annotate the not yet annotated power symbols of the entire hierarchy of the sheet path list.
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:718
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
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: infobar.cpp:286
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: infobar.cpp:245
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: infobar.cpp:142
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:280
This file is part of the common library.
static int RPT_SEVERITY_ALL
Definition: dialog_erc.cpp:342
static std::vector< wxString > g_lastERCIgnored
Definition: dialog_erc.cpp:59
static int DEFAULT_SINGLE_COL_WIDTH
Definition: dialog_erc.cpp:54
static bool g_lastERCRun
Definition: dialog_erc.cpp:58
static SCHEMATIC * g_lastERCSchematic
Definition: dialog_erc.cpp:57
#define DIALOG_ERC_WINDOW_NAME
Definition: dialog_erc.h:37
#define _(s)
ERCE_T
ERC error codes.
Definition: erc_settings.h:37
@ ERCE_POWERPIN_NOT_DRIVEN
Power input pin connected to some others pins but no power out pin to drive it.
Definition: erc_settings.h:45
@ ERCE_SIMILAR_LABELS
2 labels are equal for case insensitive comparisons.
Definition: erc_settings.h:51
@ ERCE_ENDPOINT_OFF_GRID
Pin or wire-end off grid.
Definition: erc_settings.h:41
@ ERCE_DIFFERENT_UNIT_NET
Shared pin in a multi-unit symbol is connected to more than one net.
Definition: erc_settings.h:54
@ ERCE_UNRESOLVED_VARIABLE
A text variable could not be resolved.
Definition: erc_settings.h:66
@ ERCE_SIMULATION_MODEL
An error was found in the simulation model.
Definition: erc_settings.h:67
@ ERCE_DIFFERENT_UNIT_FP
Different units of the same symbol have different footprints assigned.
Definition: erc_settings.h:52
@ ERCE_NOCONNECT_CONNECTED
A no connect symbol is connected to more than 1 pin.
Definition: erc_settings.h:48
@ ERCE_PIN_TO_PIN_WARNING
Definition: erc_settings.h:81
@ ERCE_PIN_NOT_DRIVEN
Pin connected to some others pins but no pin to drive it.
Definition: erc_settings.h:43
@ ERCE_DUPLICATE_SHEET_NAME
Duplicate sheet names within a given sheet.
Definition: erc_settings.h:40
@ ERCE_LIB_SYMBOL_ISSUES
Library symbol changed from current symbol in schematic or the library symbol link no longer valid.
Definition: erc_settings.h:69
@ ERCE_BUS_ALIAS_CONFLICT
Conflicting bus alias definitions across sheets.
Definition: erc_settings.h:56
@ ERCE_PIN_TO_PIN_ERROR
Definition: erc_settings.h:82
const std::string ReportFileExtension
wxString ReportFileWildcard()
void ForceFocus(wxWindow *aWindow)
Pass the current focus to the window.
Definition: gtk/ui.cpp:44
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_EXCLUSION
@ RPT_SEVERITY_IGNORE
@ RPT_SEVERITY_INFO
@ NO_CLEANUP
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:74
wxString DateAndTime()
@ SCH_MARKER_T
Definition: typeinfo.h:141
Definition of file extensions used in Kicad.