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
434
435 int itemsNotAnnotated = m_parent->CheckAnnotate(
436 []( ERCE_T aType, const wxString& aMsg, SCH_REFERENCE* aItemA, SCH_REFERENCE* aItemB )
437 {
438 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( aType );
439 ercItem->SetErrorMessage( aMsg );
440
441 if( aItemB )
442 ercItem->SetItems( aItemA->GetSymbol(), aItemB->GetSymbol() );
443 else
444 ercItem->SetItems( aItemA->GetSymbol() );
445
446 SCH_MARKER* marker = new SCH_MARKER( ercItem, aItemA->GetSymbol()->GetPosition() );
447 aItemA->GetSheetPath().LastScreen()->Append( marker );
448 } );
449
450 testErc();
451
452 if( itemsNotAnnotated )
453 m_messages->ReportHead( wxString::Format( _( "%d symbol(s) require annotation.<br><br>" ),
454 itemsNotAnnotated ), RPT_SEVERITY_INFO );
455
456 if( m_cancelled )
457 m_messages->Report( _( "-------- ERC cancelled by user.<br><br>" ), RPT_SEVERITY_INFO );
458 else
459 m_messages->Report( _( "Done.<br><br>" ), RPT_SEVERITY_INFO );
460
461 Raise();
462 wxYield(); // Allow time slice to refresh Messages
463
464 m_running = false;
465 m_sdbSizer1Cancel->SetLabel( _( "Close" ) );
466 m_sdbSizer1OK->Enable( true );
467 m_deleteOneMarker->Enable( true );
468 m_deleteAllMarkers->Enable( true );
469 m_saveReport->Enable( true );
470
471 if( !m_cancelled )
472 {
473 m_sdbSizer1Cancel->SetDefault();
474 // wxWidgets has a tendency to keep both buttons highlighted without the following:
475 m_sdbSizer1OK->Enable( false );
476
477 wxMilliSleep( 500 );
478 m_runningResultsBook->ChangeSelection( 1 );
480
481 // now re-enable m_sdbSizerOK button
482 m_sdbSizer1OK->Enable( true );
483 }
484
485 m_ercRun = true;
488 // set float level again, it can be lost due to window events during test run
490}
491
492
494{
495 WINDOW_THAWER thawer( m_parent );
496
498}
499
500
502{
503 wxFileName fn;
504
505 SCHEMATIC* sch = &m_parent->Schematic();
506
507 SCH_SCREENS screens( sch->Root() );
508 ERC_TESTER tester( sch );
509
510 {
511 wxBusyCursor dummy;
514 }
515
516 // Update marker list:
518
519 // Display new markers from the current screen:
520 for( SCH_ITEM* marker : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
521 {
522 m_parent->GetCanvas()->GetView()->Remove( marker );
523 m_parent->GetCanvas()->GetView()->Add( marker );
524 }
525
527}
528
529
530void DIALOG_ERC::OnERCItemSelected( wxDataViewEvent& aEvent )
531{
532 const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
533 SCH_SHEET_PATH sheet;
534 SCH_ITEM* item = m_parent->Schematic().GetSheets().GetItem( itemID, &sheet );
535
537 {
538 // we already came from a cross-probe of the marker in the document; don't go
539 // around in circles
540 }
541 else if( item && item->GetClass() != wxT( "DELETED_SHEET_ITEM" ) )
542 {
543 const RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
544
545 if( node )
546 {
547 // Determine the owning sheet for sheet-specific items
548 std::shared_ptr<ERC_ITEM> ercItem =
549 std::static_pointer_cast<ERC_ITEM>( node->m_RcItem );
550 switch( node->m_Type )
551 {
553 if( ercItem->IsSheetSpecific() )
554 sheet = ercItem->GetSpecificSheetPath();
555 break;
557 if( ercItem->MainItemHasSheetPath() )
558 sheet = ercItem->GetMainItemSheetPath();
559 break;
561 if( ercItem->AuxItemHasSheetPath() )
562 sheet = ercItem->GetAuxItemSheetPath();
563 break;
564 default:
565 break;
566 }
567 }
568
569 WINDOW_THAWER thawer( m_parent );
570
571 if( !sheet.empty() && sheet != m_parent->GetCurrentSheet() )
572 {
575
576 m_parent->SetCurrentSheet( sheet );
579 }
580
581 m_parent->FocusOnItem( item );
583 }
584
585 aEvent.Skip();
586}
587
588
589void DIALOG_ERC::OnERCItemDClick( wxDataViewEvent& aEvent )
590{
591 if( aEvent.GetItem().IsOk() )
592 {
593 // turn control over to m_parent, hide this DIALOG_ERC window,
594 // no destruction so we can preserve listbox cursor
595 if( !IsModal() )
596 Show( false );
597 }
598
599 aEvent.Skip();
600}
601
602
603void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
604{
606 EE_INSPECTION_TOOL* inspectionTool = toolMgr->GetTool<EE_INSPECTION_TOOL>();
607 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
608
609 if( !node )
610 return;
611
613
614 std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
615 wxString listName;
616 wxMenu menu;
617
618 switch( settings.GetSeverity( rcItem->GetErrorCode() ) )
619 {
620 case RPT_SEVERITY_ERROR: listName = _( "errors" ); break;
621 case RPT_SEVERITY_WARNING: listName = _( "warnings" ); break;
622 default: listName = _( "appropriate" ); break;
623 }
624
625 enum MENU_IDS
626 {
627 ID_EDIT_EXCLUSION_COMMENT = 4467,
628 ID_REMOVE_EXCLUSION,
629 ID_REMOVE_EXCLUSION_ALL,
630 ID_ADD_EXCLUSION,
631 ID_ADD_EXCLUSION_ALL,
632 ID_INSPECT_VIOLATION,
633 ID_EDIT_PIN_CONFLICT_MAP,
634 ID_EDIT_CONNECTION_GRID,
635 ID_SET_SEVERITY_TO_ERROR,
636 ID_SET_SEVERITY_TO_WARNING,
637 ID_SET_SEVERITY_TO_IGNORE,
638 ID_EDIT_SEVERITIES,
639 };
640
641 if( rcItem->GetParent()->IsExcluded() )
642 {
643 menu.Append( ID_EDIT_EXCLUSION_COMMENT,
644 _( "Edit exclusion comment..." ) );
645
646 menu.Append( ID_REMOVE_EXCLUSION,
647 _( "Remove exclusion for this violation" ),
648 wxString::Format( _( "It will be placed back in the %s list" ), listName ) );
649 }
650 else
651 {
652 menu.Append( ID_ADD_EXCLUSION,
653 _( "Exclude this violation..." ),
654 wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
655 }
656
657 wxString inspectERCErrorMenuText = inspectionTool->InspectERCErrorMenuText( rcItem );
658
659 if( !inspectERCErrorMenuText.IsEmpty() )
660 menu.Append( ID_INSPECT_VIOLATION, inspectERCErrorMenuText );
661
662 menu.AppendSeparator();
663
664 if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_WARNING
665 || rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
666 {
667 // Pin to pin severities edited through pin conflict map
668 }
669 else if( settings.GetSeverity( rcItem->GetErrorCode() ) == RPT_SEVERITY_WARNING )
670 {
671 menu.Append( ID_SET_SEVERITY_TO_ERROR,
672 wxString::Format( _( "Change severity to Error for all '%s' violations" ),
673 rcItem->GetErrorText() ),
674 _( "Violation severities can also be edited in the Schematic Setup... dialog" ) );
675 }
676 else
677 {
678 menu.Append( ID_SET_SEVERITY_TO_WARNING,
679 wxString::Format( _( "Change severity to Warning for all '%s' violations" ),
680 rcItem->GetErrorText() ),
681 _( "Violation severities can also be edited in the Schematic Setup... dialog" ) );
682 }
683
684 menu.Append( ID_SET_SEVERITY_TO_IGNORE,
685 wxString::Format( _( "Ignore all '%s' violations" ), rcItem->GetErrorText() ),
686 _( "Violations will not be checked or reported" ) );
687
688 menu.AppendSeparator();
689
690 if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_WARNING
691 || rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
692 {
693 menu.Append( ID_EDIT_PIN_CONFLICT_MAP,
694 _( "Edit pin-to-pin conflict map..." ),
695 _( "Open the Schematic Setup... dialog" ) );
696 }
697 else
698 {
699 menu.Append( ID_EDIT_SEVERITIES,
700 _( "Edit violation severities..." ),
701 _( "Open the Schematic Setup... dialog" ) );
702 }
703
704 if( rcItem->GetErrorCode() == ERCE_ENDPOINT_OFF_GRID )
705 {
706 menu.Append( ID_EDIT_CONNECTION_GRID,
707 _( "Edit connection grid spacing..." ),
708 _( "Open the Schematic Setup... dialog" ) );
709 }
710
711 bool modified = false;
712
713 switch( GetPopupMenuSelectionFromUser( menu ) )
714 {
715 case ID_EDIT_EXCLUSION_COMMENT:
716 if( SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ) )
717 {
718 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Optional comment:" ), _( "Exclusion Comment" ),
719 marker->GetComment(), true );
720
721 if( dlg.ShowModal() == wxID_CANCEL )
722 break;
723
724 marker->SetExcluded( true, dlg.GetValue() );
725
726 // Update view
727 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
728 modified = true;
729 }
730
731 break;
732
733 case ID_REMOVE_EXCLUSION:
734 if( SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ) )
735 {
736 marker->SetExcluded( false );
737 m_parent->GetCanvas()->GetView()->Update( marker );
738
739 // Update view
740 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
741 modified = true;
742 }
743
744 break;
745
746 case ID_ADD_EXCLUSION:
747 if( SCH_MARKER* marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() ) )
748 {
749 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Optional comment:" ), _( "Exclusion Comment" ),
750 wxEmptyString, true );
751
752 if( dlg.ShowModal() == wxID_CANCEL )
753 break;
754
755 marker->SetExcluded( true, dlg.GetValue() );
756
757 m_parent->GetCanvas()->GetView()->Update( marker );
758
759 // Update view
761 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
762 else
763 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->DeleteCurrentItem( false );
764
765 modified = true;
766 }
767
768 break;
769
770 case ID_INSPECT_VIOLATION:
771 inspectionTool->InspectERCError( node->m_RcItem );
772 break;
773
774 case ID_SET_SEVERITY_TO_ERROR:
775 settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_ERROR );
776
777 for( SCH_ITEM* item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
778 {
779 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
780
781 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
782 m_parent->GetCanvas()->GetView()->Update( marker );
783 }
784
785 // Rebuild model and view
786 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
787 modified = true;
788 break;
789
790 case ID_SET_SEVERITY_TO_WARNING:
791 settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_WARNING );
792
793 for( SCH_ITEM* item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
794 {
795 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
796
797 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
798 m_parent->GetCanvas()->GetView()->Update( marker );
799 }
800
801 // Rebuild model and view
802 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
803 modified = true;
804 break;
805
806 case ID_SET_SEVERITY_TO_IGNORE:
807 {
808 settings.SetSeverity( rcItem->GetErrorCode(), RPT_SEVERITY_IGNORE );
809
810 if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR )
812
813 wxListItem listItem;
814 listItem.SetId( m_ignoredList->GetItemCount() );
815 listItem.SetText( wxT( " • " ) + rcItem->GetErrorText() );
816 listItem.SetData( rcItem->GetErrorCode() );
817
818 m_ignoredList->InsertItem( listItem );
819
820 // Clear the selection before deleting markers. It may be some selected ERC markers.
821 // Deleting a selected marker without deselecting it first generates a crash
823
824 SCH_SCREENS ScreenList( m_parent->Schematic().Root() );
825 ScreenList.DeleteMarkers( MARKER_BASE::MARKER_ERC, rcItem->GetErrorCode() );
826
827 // Rebuild model and view
828 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
829 modified = true;
830 }
831 break;
832
833 case ID_EDIT_PIN_CONFLICT_MAP:
834 m_parent->ShowSchematicSetupDialog( _( "Pin Conflicts Map" ) );
835 break;
836
837 case ID_EDIT_SEVERITIES:
838 m_parent->ShowSchematicSetupDialog( _( "Violation Severity" ) );
839 break;
840
841 case ID_EDIT_CONNECTION_GRID:
842 m_parent->ShowSchematicSetupDialog( _( "Formatting" ) );
843 break;
844 }
845
846 if( modified )
847 {
851 }
852}
853
854
855void DIALOG_ERC::OnIgnoredItemRClick( wxListEvent& event )
856{
858 int errorCode = (int) event.m_item.GetData();
859 wxMenu menu;
860
861 menu.Append( RPT_SEVERITY_ERROR, _( "Error" ), wxEmptyString, wxITEM_CHECK );
862 menu.Append( RPT_SEVERITY_WARNING, _( "Warning" ), wxEmptyString, wxITEM_CHECK );
863 menu.Append( RPT_SEVERITY_IGNORE, _( "Ignore" ), wxEmptyString, wxITEM_CHECK );
864
865 menu.Check( settings.GetSeverity( errorCode ), true );
866
867 int severity = GetPopupMenuSelectionFromUser( menu );
868
869 if( severity > 0 )
870 {
871 if( settings.GetSeverity( errorCode ) != severity )
872 {
873 settings.SetSeverity( errorCode, (SEVERITY) severity );
874
878 }
879 }
880}
881
882
884{
885 if( m_notebook->IsShown() )
886 {
887 if( m_notebook->GetSelection() != 0 )
888 m_notebook->SetSelection( 0 );
889
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 m_notebook->SetSelection( 0 );
913
914 // wxWidgets on some platforms fails to correctly ensure that a selected item is
915 // visible, so we have to do it in a separate idle event.
916 m_centerMarkerOnIdle = aMarker;
917 Bind( wxEVT_IDLE, &DIALOG_ERC::centerMarkerIdleHandler, this );
918 }
919}
920
921
922void DIALOG_ERC::centerMarkerIdleHandler( wxIdleEvent& aEvent )
923{
925 m_centerMarkerOnIdle = nullptr;
926 Unbind( wxEVT_IDLE, &DIALOG_ERC::centerMarkerIdleHandler, this );
927}
928
929
931{
932 SCH_MARKER* marker = aMarker;
933
934 if( marker != nullptr )
936
937 if( m_notebook->GetSelection() != 0 )
938 return;
939
940 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( m_markerDataView->GetCurrentItem() );
941
942 if( node && node->m_RcItem )
943 marker = dynamic_cast<SCH_MARKER*>( node->m_RcItem->GetParent() );
944
945 if( node && marker && !marker->IsExcluded() )
946 {
947 marker->SetExcluded( true );
948 m_parent->GetCanvas()->GetView()->Update( marker );
949
950 // Update view
953 else
955
959 }
960}
961
962
963void DIALOG_ERC::OnEditViolationSeverities( wxHyperlinkEvent& aEvent )
964{
965 m_parent->ShowSchematicSetupDialog( _( "Violation Severity" ) );
966}
967
968
969void DIALOG_ERC::OnSeverity( wxCommandEvent& aEvent )
970{
971 int flag = 0;
972
973 if( aEvent.GetEventObject() == m_showAll )
975 else if( aEvent.GetEventObject() == m_showErrors )
977 else if( aEvent.GetEventObject() == m_showWarnings )
979 else if( aEvent.GetEventObject() == m_showExclusions )
981
982 if( aEvent.IsChecked() )
984 else if( aEvent.GetEventObject() == m_showAll )
986 else
987 m_severities &= ~flag;
988
990
993}
994
995
996void DIALOG_ERC::deleteAllMarkers( bool aIncludeExclusions )
997{
998 // Clear current selection list to avoid selection of deleted items
1000
1001 m_markerTreeModel->DeleteItems( false, aIncludeExclusions, false );
1002
1003 SCH_SCREENS screens( m_parent->Schematic().Root() );
1004 screens.DeleteAllMarkers( MARKER_BASE::MARKER_ERC, aIncludeExclusions );
1005}
1006
1007
1008void DIALOG_ERC::OnSaveReport( wxCommandEvent& aEvent )
1009{
1010 wxFileName fn( wxS( "ERC." ) + wxString( FILEEXT::ReportFileExtension ) );
1011
1012 wxFileDialog dlg( this, _( "Save Report File" ), Prj().GetProjectPath(), fn.GetFullName(),
1014 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1015
1016 if( dlg.ShowModal() != wxID_OK )
1017 return;
1018
1019 fn = dlg.GetPath();
1020
1021 if( fn.GetExt().IsEmpty() )
1022 fn.SetExt( FILEEXT::ReportFileExtension );
1023
1024 if( !fn.IsAbsolute() )
1025 {
1026 wxString prj_path = Prj().GetProjectPath();
1027 fn.MakeAbsolute( prj_path );
1028 }
1029
1030 ERC_REPORT reportWriter( &m_parent->Schematic(), m_parent->GetUserUnits() );
1031
1032 bool success = false;
1033 if( fn.GetExt() == FILEEXT::JsonFileExtension )
1034 success = reportWriter.WriteJsonReport( fn.GetFullPath() );
1035 else
1036 success = reportWriter.WriteTextReport( fn.GetFullPath() );
1037
1038 if( success )
1039 {
1040 m_messages->Report( wxString::Format( _( "Report file '%s' created." ),
1041 fn.GetFullPath() ) );
1042 }
1043 else
1044 {
1045 DisplayError( this, wxString::Format( _( "Failed to create file '%s'." ),
1046 fn.GetFullPath() ) );
1047 }
1048}
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
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:930
void OnIgnoredItemRClick(wxListEvent &aEvent) override
Definition: dialog_erc.cpp:855
const SCH_MARKER * m_centerMarkerOnIdle
Definition: dialog_erc.h:115
void OnERCItemDClick(wxDataViewEvent &aEvent) override
Definition: dialog_erc.cpp:589
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:501
void SelectMarker(const SCH_MARKER *aMarker)
Definition: dialog_erc.cpp:907
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:603
void centerMarkerIdleHandler(wxIdleEvent &aEvent)
Definition: dialog_erc.cpp:922
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)
Definition: dialog_erc.cpp:996
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:883
void NextMarker()
Definition: dialog_erc.cpp:895
SCHEMATIC * m_currentSchematic
Definition: dialog_erc.h:104
void OnEditViolationSeverities(wxHyperlinkEvent &aEvent) override
Definition: dialog_erc.cpp:963
void UpdateAnnotationWarning()
Definition: dialog_erc.cpp:165
void redrawDrawPanel()
Definition: dialog_erc.cpp:493
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:530
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:969
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:257
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:121
SEVERITY GetSeverity(int aErrorCode) const
void SetSeverity(int aErrorCode, SEVERITY aSeverity)
Definition: erc.h:50
void RunTests(DS_PROXY_VIEW_ITEM *aDrawingSheet, SCH_EDIT_FRAME *aEditFrame, KIFACE *aCvPcb, PROJECT *aProject, PROGRESS_REPORTER *aProgressReporter)
Definition: erc.cpp:1354
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:315
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:354
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:1631
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:75
void RecordERCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: schematic.cpp:800
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:100
SCH_SHEET & Root() const
Definition: schematic.h:105
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:296
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:441
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:174
wxString GetClass() const override
Return the class name.
Definition: sch_item.h:184
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:703
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:151
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:108
SCH_ITEM * GetItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr) const
Fetch a SCH_ITEM by ID.
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:779
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:301
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: wx_infobar.cpp:260
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:161
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:92
@ ERCE_PIN_TO_PIN_ERROR
Definition: erc_settings.h:93
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: gtk/ui.cpp:324
void ForceFocus(wxWindow *aWindow)
Pass the current focus to the window.
Definition: gtk/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