KiCad PCB EDA Suite
dialog_drc.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) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2009-2016 Dick Hollenbeck, dick@softplc.com
6  * Copyright (C) 2004-2020 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 <bitmaps.h>
27 #include <confirm.h>
28 #include <dialog_drc.h>
29 #include <kiface_i.h>
30 #include <pcb_edit_frame.h>
31 #include <pcbnew_settings.h>
32 #include <pgm_base.h>
33 #include <tool/tool_manager.h>
34 #include <tools/pcb_actions.h>
36 #include <pcb_marker.h>
37 #include <wx/wupdlock.h>
39 #include <widgets/number_badge.h>
40 #include <widgets/ui_common.h>
44 #include <tools/drc_tool.h>
45 #include <kiplatform/ui.h>
46 
47 DIALOG_DRC::DIALOG_DRC( PCB_EDIT_FRAME* aEditorFrame, wxWindow* aParent ) :
48  DIALOG_DRC_BASE( aParent ),
49  PROGRESS_REPORTER( 1 ),
50  m_running( false ),
51  m_cancelled( false ),
52  m_drcRun( false ),
53  m_footprintTestsRun( false ),
54  m_markersProvider( nullptr ),
55  m_markerTreeModel( nullptr ),
56  m_unconnectedItemsProvider( nullptr ),
57  m_unconnectedTreeModel( nullptr ),
58  m_footprintWarningsProvider( nullptr ),
59  m_footprintWarningsTreeModel( nullptr ),
61 {
62  SetName( DIALOG_DRC_WINDOW_NAME ); // Set a window name to be able to find it
63 
64  m_brdEditor = aEditorFrame;
66 
68 
70  m_markerDataView->AssociateModel( m_markerTreeModel );
71 
74 
77 
78  if( Kiface().IsSingle() )
79  m_cbTestFootprints->Hide();
80 
81  // We use a sdbSizer here to get the order right, which is platform-dependent
82  m_sdbSizerOK->SetLabel( _( "Run DRC" ) );
83  m_sdbSizerCancel->SetLabel( _( "Close" ) );
84  m_sizerButtons->Layout();
85 
86  m_sdbSizerOK->SetDefault();
87 
88  initValues();
90 
92 }
93 
94 
96 {
97  m_brdEditor->FocusOnItem( nullptr );
98 
100  settings->m_DrcDialog.refill_zones = m_cbRefillZones->GetValue();
102 
103  if( !Kiface().IsSingle() )
104  settings->m_DrcDialog.test_footprints = m_cbTestFootprints->GetValue();
105 
106  settings->m_DrcDialog.severities = m_severities;
107 
108  m_markerTreeModel->DecRef();
109 }
110 
111 
112 void DIALOG_DRC::OnActivateDlg( wxActivateEvent& aEvent )
113 {
115  {
116  // If m_currentBoard is not the current board, (for instance because a new board
117  // was loaded), close the dialog, because many pointers are now invalid in lists
118  SetReturnCode( wxID_CANCEL );
119  Close();
120 
122  drcTool->DestroyDRCDialog();
123  }
124 }
125 
126 
128 {
129  m_markersTitleTemplate = m_Notebook->GetPageText( 0 );
130  m_unconnectedTitleTemplate = m_Notebook->GetPageText( 1 );
131  m_footprintsTitleTemplate = m_Notebook->GetPageText( 2 );
132 
133  auto cfg = m_brdEditor->GetPcbNewSettings();
134 
135  m_cbRefillZones->SetValue( cfg->m_DrcDialog.refill_zones );
136  m_cbReportAllTrackErrors->SetValue( cfg->m_DrcDialog.test_all_track_errors );
137 
138  if( Kiface().IsSingle() )
139  m_cbTestFootprints->SetValue( cfg->m_DrcDialog.test_footprints );
140 
141  m_severities = cfg->m_DrcDialog.severities;
145 
146  Layout(); // adding the units above expanded Clearance text, now resize.
147 
148  SetFocus();
149 }
150 
151 
152 // PROGRESS_REPORTER calls
153 
155 {
156  double cur = (double) m_progress.load() / m_maxProgress;
157  cur = std::max( 0.0, std::min( cur, 1.0 ) );
158 
159  m_gauge->SetValue( KiROUND( cur * 1000.0 ) );
160  wxSafeYield( this );
161 
162  return !m_cancelled;
163 }
164 
165 
166 void DIALOG_DRC::AdvancePhase( const wxString& aMessage )
167 {
169  SetCurrentProgress( 0.0 );
170 
171  m_messages->Report( aMessage );
172 }
173 
174 
175 // Don't globally define this; different facilities use different definitions of "ALL"
177 
178 
180 {
181  m_showAll->SetValue( m_severities == RPT_SEVERITY_ALL );
185 }
186 
187 
188 void DIALOG_DRC::OnErrorLinkClicked( wxHtmlLinkEvent& event )
189 {
190  m_brdEditor->ShowBoardSetupDialog( _( "Rules" ) );
191 }
192 
193 
194 void DIALOG_DRC::OnRunDRCClick( wxCommandEvent& aEvent )
195 {
197  bool refillZones = m_cbRefillZones->GetValue();
198  bool reportAllTrackErrors = m_cbReportAllTrackErrors->GetValue();
199  bool testFootprints = m_cbTestFootprints->GetValue();
200 
201  // This is not the time to have stale or buggy rules. Ensure they're up-to-date
202  // and that they at least parse.
203  try
204  {
205  drcTool->GetDRCEngine()->InitEngine( m_brdEditor->GetDesignRulesPath() );
206  }
207  catch( PARSE_ERROR& pe )
208  {
209  m_runningResultsBook->ChangeSelection( 0 ); // Display the "Tests Running..." tab
210  m_DeleteCurrentMarkerButton->Enable( false );
211  m_DeleteAllMarkersButton->Enable( false );
212  m_saveReport->Enable( false );
213 
214  m_messages->Clear();
215  m_messages->Report( _( "DRC incomplete: could not compile design rules. " )
216  + wxT( "<a href='boardsetup'>" )
217  + _( "Show design rules." )
218  + wxT( "</a>" ) );
219  m_messages->Flush();
220 
221  Raise();
222  return;
223  }
224 
225  m_drcRun = false;
226  m_footprintTestsRun = false;
227  m_cancelled = false;
228 
230  deleteAllMarkers( true );
231  m_unconnectedTreeModel->DeleteItems( false, true, true );
232  m_footprintWarningsTreeModel->DeleteItems( false, true, true );
233 
234  Raise();
235 
236  m_runningResultsBook->ChangeSelection( 0 ); // Display the "Tests Running..." tab
237  m_messages->Clear();
238  wxYield(); // Allow time slice to refresh Messages
239 
240  m_running = true;
241  m_sdbSizerCancel->SetLabel( _( "Cancel" ) );
242  m_sdbSizerOK->Enable( false );
243  m_DeleteCurrentMarkerButton->Enable( false );
244  m_DeleteAllMarkersButton->Enable( false );
245  m_saveReport->Enable( false );
246 
247  drcTool->RunTests( this, refillZones, reportAllTrackErrors, testFootprints );
248 
249  if( m_cancelled )
250  m_messages->Report( _( "-------- DRC cancelled by user.<br><br>" ) );
251  else
252  m_messages->Report( _( "Done.<br><br>" ) );
253 
254  Raise();
255  wxYield(); // Allow time slice to refresh Messages
256 
257  m_running = false;
258  m_sdbSizerCancel->SetLabel( _( "Close" ) );
259  m_sdbSizerOK->Enable( true );
260  m_DeleteCurrentMarkerButton->Enable( true );
261  m_DeleteAllMarkersButton->Enable( true );
262  m_saveReport->Enable( true );
263 
264  if( !m_cancelled )
265  {
266  wxMilliSleep( 500 );
267  m_runningResultsBook->ChangeSelection( 1 );
269  }
270 
272 }
273 
274 
276 {
277  m_markersProvider = aProvider;
280 }
281 
282 
284 {
285  m_unconnectedItemsProvider = aProvider;
288 }
289 
290 
292 {
293  m_footprintWarningsProvider = aProvider;
296 }
297 
298 
299 void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
300 {
301  BOARD* board = m_brdEditor->GetBoard();
302  RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
303  const KIID& itemID = node ? RC_TREE_MODEL::ToUUID( aEvent.GetItem() ) : niluuid;
304  BOARD_ITEM* item = board->GetItem( itemID );
305 
306  if( item && node )
307  {
308  PCB_LAYER_ID principalLayer = item->GetLayer();
309  LSET violationLayers;
310  std::shared_ptr<RC_ITEM> rc_item = node->m_RcItem;
311 
312  if( rc_item->GetErrorCode() == DRCE_MALFORMED_COURTYARD )
313  {
314  BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
315 
316  if( a && ( a->GetFlags() & MALFORMED_B_COURTYARD ) > 0
317  && ( a->GetFlags() & MALFORMED_F_COURTYARD ) == 0 )
318  {
319  principalLayer = B_CrtYd;
320  }
321  else
322  {
323  principalLayer = F_CrtYd;
324  }
325  }
326  else if (rc_item->GetErrorCode() == DRCE_INVALID_OUTLINE )
327  {
328  principalLayer = Edge_Cuts;
329  }
330  else
331  {
332  BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
333  BOARD_ITEM* b = board->GetItem( rc_item->GetAuxItemID() );
334  BOARD_ITEM* c = board->GetItem( rc_item->GetAuxItem2ID() );
335  BOARD_ITEM* d = board->GetItem( rc_item->GetAuxItem3ID() );
336 
337  if( a )
338  violationLayers &= a->GetLayerSet();
339 
340  if( b )
341  violationLayers &= b->GetLayerSet();
342 
343  if( c )
344  violationLayers &= c->GetLayerSet();
345 
346  if( d )
347  violationLayers &= d->GetLayerSet();
348  }
349 
350  if( violationLayers.count() )
351  principalLayer = violationLayers.Seq().front();
352  else
353  violationLayers.set( principalLayer );
354 
355  WINDOW_THAWER thawer( m_brdEditor );
356 
357  m_brdEditor->FocusOnItem( item );
359 
360  if( ( violationLayers & board->GetVisibleLayers() ) == 0 )
361  {
362  m_brdEditor->GetAppearancePanel()->SetLayerVisible( principalLayer, true );
364  }
365 
366  if( board->GetVisibleLayers().test( principalLayer ) )
367  m_brdEditor->SetActiveLayer( principalLayer );
368  }
369 
370  aEvent.Skip();
371 }
372 
373 
374 void DIALOG_DRC::OnDRCItemDClick( wxDataViewEvent& aEvent )
375 {
376  if( aEvent.GetItem().IsOk() )
377  {
378  // turn control over to m_brdEditor, hide this DIALOG_DRC window,
379  // no destruction so we can preserve listbox cursor
380  if( !IsModal() )
381  Show( false );
382  }
383 
384  // Do not skip aVent here: tihs is not useful, and Pcbnew crashes
385  // if skipped (at least on Windows)
386 }
387 
388 
389 void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
390 {
391  RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
392 
393  if( !node )
394  return;
395 
396  std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
397  wxString listName;
398  wxMenu menu;
399  wxString msg;
400 
401  switch( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] )
402  {
403  case RPT_SEVERITY_ERROR: listName = _( "errors" ); break;
404  case RPT_SEVERITY_WARNING: listName = _( "warnings" ); break;
405  default: listName = _( "appropriate" ); break;
406  }
407 
408  if( rcItem->GetParent()->IsExcluded() )
409  {
410  menu.Append( 1, _( "Remove exclusion for this violation" ),
411  wxString::Format( _( "It will be placed back in the %s list" ), listName ) );
412  }
413  else
414  {
415  menu.Append( 2, _( "Exclude this violation" ),
416  wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
417  }
418 
419  menu.AppendSeparator();
420 
421  if( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] == RPT_SEVERITY_WARNING )
422  {
423  msg.Printf( _( "Change severity to Error for all '%s' violations" ),
424  rcItem->GetErrorText(),
425  _( "Violation severities can also be edited in the Board Setup... dialog" ) );
426  menu.Append( 3, msg );
427  }
428  else
429  {
430  msg.Printf( _( "Change severity to Warning for all '%s' violations" ),
431  rcItem->GetErrorText(),
432  _( "Violation severities can also be edited in the Board Setup... dialog" ) );
433  menu.Append( 4, msg );
434  }
435 
436  msg.Printf( _( "Ignore all '%s' violations" ),
437  rcItem->GetErrorText(),
438  _( "Violations will not be checked or reported" ) );
439  menu.Append( 5, msg );
440 
441  menu.AppendSeparator();
442 
443  menu.Append( 6, _( "Edit violation severities..." ), _( "Open the Board Setup... dialog" ) );
444 
445  bool modified = false;
446 
447  switch( GetPopupMenuSelectionFromUser( menu ) )
448  {
449  case 1:
450  {
451  PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
452 
453  if( marker )
454  {
455  marker->SetExcluded( false );
456  m_brdEditor->GetCanvas()->GetView()->Update( marker );
457 
458  // Update view
459  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
460  modified = true;
461  }
462  }
463  break;
464 
465  case 2:
466  {
467  PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
468 
469  if( marker )
470  {
471  marker->SetExcluded( true );
472  m_brdEditor->GetCanvas()->GetView()->Update( marker );
473 
474  // Update view
476  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
477  else
478  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->DeleteCurrentItem( false );
479 
480  modified = true;
481  }
482  }
483  break;
484 
485  case 3:
486  bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_ERROR;
487 
488  for( PCB_MARKER* marker : m_brdEditor->GetBoard()->Markers() )
489  {
490  if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
491  m_brdEditor->GetCanvas()->GetView()->Update( marker );
492  }
493 
494  // Rebuild model and view
495  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->SetProvider( m_markersProvider );
496  modified = true;
497  break;
498 
499  case 4:
500  bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_WARNING;
501 
502  for( PCB_MARKER* marker : m_brdEditor->GetBoard()->Markers() )
503  {
504  if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
505  m_brdEditor->GetCanvas()->GetView()->Update( marker );
506  }
507 
508  // Rebuild model and view
509  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->SetProvider( m_markersProvider );
510  modified = true;
511  break;
512 
513  case 5:
514  {
515  bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_IGNORE;
516 
517  std::vector<PCB_MARKER*>& markers = m_brdEditor->GetBoard()->Markers();
518 
519  for( unsigned i = 0; i < markers.size(); )
520  {
521  if( markers[i]->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
522  {
523  m_brdEditor->GetCanvas()->GetView()->Remove( markers.at( i ) );
524  markers.erase( markers.begin() + i );
525  }
526  else
527  ++i;
528  }
529 
530  // Rebuild model and view
531  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->SetProvider( m_markersProvider );
532  modified = true;
533  }
534  break;
535 
536  case 6:
537  m_brdEditor->ShowBoardSetupDialog( _( "Violation Severity" ) );
538  break;
539  }
540 
541  if( modified )
542  {
546  }
547 }
548 
549 
550 void DIALOG_DRC::OnSeverity( wxCommandEvent& aEvent )
551 {
552  int flag = 0;
553 
554  if( aEvent.GetEventObject() == m_showAll )
555  flag = RPT_SEVERITY_ALL;
556  else if( aEvent.GetEventObject() == m_showErrors )
557  flag = RPT_SEVERITY_ERROR;
558  else if( aEvent.GetEventObject() == m_showWarnings )
559  flag = RPT_SEVERITY_WARNING;
560  else if( aEvent.GetEventObject() == m_showExclusions )
561  flag = RPT_SEVERITY_EXCLUSION;
562 
563  if( aEvent.IsChecked() )
564  m_severities |= flag;
565  else if( aEvent.GetEventObject() == m_showAll )
567  else
568  m_severities &= ~flag;
569 
570  syncCheckboxes();
571 
572  // Set the provider's severity levels through the TreeModel so that the old tree
573  // can be torn down before the severity changes.
574  //
575  // It's not clear this is required, but we've had a lot of issues with wxDataView
576  // being cranky on various platforms.
577 
581 
583 }
584 
585 
586 void DIALOG_DRC::OnSaveReport( wxCommandEvent& aEvent )
587 {
588  wxFileName fn( "./DRC." + ReportFileExtension );
589 
590  wxFileDialog dlg( this, _( "Save Report to File" ), fn.GetPath(), fn.GetFullName(),
591  ReportFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
592 
593  if( dlg.ShowModal() != wxID_OK )
594  return;
595 
596  fn = dlg.GetPath();
597 
598  if( fn.GetExt().IsEmpty() )
599  fn.SetExt( ReportFileExtension );
600 
601  if( !fn.IsAbsolute() )
602  {
603  wxString prj_path = Prj().GetProjectPath();
604  fn.MakeAbsolute( prj_path );
605  }
606 
607  if( writeReport( fn.GetFullPath() ) )
608  {
609  m_messages->Report( wxString::Format( _( "Report file '%s' created<br>" ),
610  fn.GetFullPath() ) );
611  }
612  else
613  {
614  DisplayError( this, wxString::Format( _( "Unable to create report file '%s'<br>" ),
615  fn.GetFullPath() ) );
616  }
617 }
618 
619 
620 void DIALOG_DRC::OnClose( wxCloseEvent& aEvent )
621 {
622  if( m_running )
623  aEvent.Veto();
624 
625  wxCommandEvent dummy;
626 
627  OnCancelClick( dummy );
628 }
629 
630 
631 void DIALOG_DRC::OnCancelClick( wxCommandEvent& aEvent )
632 {
633  if( m_running )
634  {
635  m_cancelled = true;
636  return;
637  }
638 
639  m_brdEditor->FocusOnItem( nullptr );
640 
641  SetReturnCode( wxID_CANCEL );
642 
643  // The dialog can be modal or not modal.
644  // Leave the DRC caller destroy (or not) the dialog
646  drcTool->DestroyDRCDialog();
647 }
648 
649 
650 void DIALOG_DRC::OnChangingNotebookPage( wxNotebookEvent& aEvent )
651 {
652  // Shouldn't be necessary, but is on at least OSX
653  if( aEvent.GetSelection() >= 0 )
654  m_Notebook->ChangeSelection( (unsigned) aEvent.GetSelection() );
655 
656  m_markerDataView->UnselectAll();
657  m_unconnectedDataView->UnselectAll();
658  m_footprintsDataView->UnselectAll();
659 }
660 
661 
663 {
664  WINDOW_THAWER thawer( m_brdEditor );
665 
667 }
668 
669 
671 {
672  if( m_Notebook->IsShown() )
673  {
674  switch( m_Notebook->GetSelection() )
675  {
676  case 0: m_markerTreeModel->PrevMarker(); break;
677  case 1: m_unconnectedTreeModel->PrevMarker(); break;
678  case 2: m_footprintWarningsTreeModel->PrevMarker(); break;
679  }
680  }
681 }
682 
683 
685 {
686  if( m_Notebook->IsShown() )
687  {
688  switch( m_Notebook->GetSelection() )
689  {
690  case 0: m_markerTreeModel->NextMarker(); break;
691  case 1: m_unconnectedTreeModel->NextMarker(); break;
692  case 2: m_footprintWarningsTreeModel->NextMarker(); break;
693  }
694  }
695 }
696 
697 
699 {
700  if( !m_Notebook->IsShown() || m_Notebook->GetSelection() != 0 )
701  return;
702 
703  RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( m_markerDataView->GetCurrentItem() );
704  PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
705 
706  if( marker && !marker->IsExcluded() )
707  {
708  marker->SetExcluded( true );
709  m_brdEditor->GetCanvas()->GetView()->Update( marker );
710 
711  // Update view
714  else
716 
720  }
721 }
722 
723 
724 void DIALOG_DRC::deleteAllMarkers( bool aIncludeExclusions )
725 {
726  // Clear current selection list to avoid selection of deleted items
728 
729  m_markerTreeModel->DeleteItems( false, aIncludeExclusions, true );
730 }
731 
732 
733 bool DIALOG_DRC::writeReport( const wxString& aFullFileName )
734 {
735  FILE* fp = wxFopen( aFullFileName, wxT( "w" ) );
736 
737  if( fp == NULL )
738  return false;
739 
740  std::map<KIID, EDA_ITEM*> itemMap;
741  m_brdEditor->GetBoard()->FillItemMap( itemMap );
742 
743  EDA_UNITS units = GetUserUnits();
745  int count;
746 
747  fprintf( fp, "** Drc report for %s **\n", TO_UTF8( m_brdEditor->GetBoard()->GetFileName() ) );
748 
749  wxDateTime now = wxDateTime::Now();
750 
751  fprintf( fp, "** Created on %s **\n", TO_UTF8( now.Format( wxT( "%F %T" ) ) ) );
752 
753  count = m_markersProvider->GetCount();
754 
755  fprintf( fp, "\n** Found %d DRC violations **\n", count );
756 
757  for( int i = 0; i < count; ++i )
758  {
759  const std::shared_ptr<RC_ITEM>& item = m_markersProvider->GetItem( i );
760  SEVERITY severity = (SEVERITY) bds.GetSeverity( item->GetErrorCode() );
761 
762  fprintf( fp, "%s", TO_UTF8( item->ShowReport( units, severity, itemMap ) ) );
763  }
764 
766 
767  fprintf( fp, "\n** Found %d unconnected pads **\n", count );
768 
769  for( int i = 0; i < count; ++i )
770  {
771  const std::shared_ptr<RC_ITEM>& item = m_unconnectedItemsProvider->GetItem( i );
772  SEVERITY severity = (SEVERITY) bds.GetSeverity( item->GetErrorCode() );
773 
774  fprintf( fp, "%s", TO_UTF8( item->ShowReport( units, severity, itemMap ) ) );
775  }
776 
778 
779  fprintf( fp, "\n** Found %d Footprint errors **\n", count );
780 
781  for( int i = 0; i < count; ++i )
782  {
783  const std::shared_ptr<RC_ITEM>& item = m_footprintWarningsProvider->GetItem( i );
784  SEVERITY severity = (SEVERITY) bds.GetSeverity( item->GetErrorCode() );
785 
786  fprintf( fp, "%s", TO_UTF8( item->ShowReport( units, severity, itemMap ) ) );
787  }
788 
789 
790  fprintf( fp, "\n** End of Report **\n" );
791 
792  fclose( fp );
793 
794  return true;
795 }
796 
797 
798 void DIALOG_DRC::OnDeleteOneClick( wxCommandEvent& aEvent )
799 {
800  if( m_Notebook->GetSelection() == 0 )
801  {
802  // Clear the selection. It may be the selected DRC marker.
804 
806 
807  // redraw the pcb
809  }
810  else if( m_Notebook->GetSelection() == 1 )
811  {
813  }
814  else if( m_Notebook->GetSelection() == 2 )
815  {
817  }
818 
820 }
821 
822 
823 void DIALOG_DRC::OnDeleteAllClick( wxCommandEvent& aEvent )
824 {
825  static bool s_includeExclusions = false;
826 
827  int numExcluded = 0;
828 
829  if( m_markersProvider )
831 
834 
837 
838  if( numExcluded > 0 )
839  {
840  wxRichMessageDialog dlg( this, _( "Do you wish to delete excluded markers as well?" ),
841  _( "Delete All Markers" ),
842  wxOK | wxCANCEL | wxCENTER | wxICON_QUESTION );
843  dlg.ShowCheckBox( _( "Delete exclusions" ), s_includeExclusions );
844 
845  int ret = dlg.ShowModal();
846 
847  if( ret == wxID_CANCEL )
848  return;
849  else
850  s_includeExclusions = dlg.IsCheckBoxChecked();
851  }
852 
853  deleteAllMarkers( s_includeExclusions );
854 
855  m_drcRun = false;
858 }
859 
860 
862 {
863  // Collect counts:
864 
865  int numMarkers = 0;
866  int numUnconnected = 0;
867  int numFootprints = 0;
868 
869  int numErrors = 0;
870  int numWarnings = 0;
871  int numExcluded = 0;
872 
873  if( m_markersProvider )
874  {
875  numMarkers += m_markersProvider->GetCount();
879  }
880 
882  {
883  numUnconnected += m_unconnectedItemsProvider->GetCount();
887  }
888 
890  {
891  numFootprints += m_footprintWarningsProvider->GetCount();
895  }
896 
897  wxString msg;
898 
899  // Update tab headers:
900 
901  if( m_drcRun )
902  {
903  msg.sprintf( m_markersTitleTemplate, numMarkers );
904  m_Notebook->SetPageText( 0, msg );
905 
906  msg.sprintf( m_unconnectedTitleTemplate, numUnconnected );
907  m_Notebook->SetPageText( 1, msg );
908 
909  if( m_footprintTestsRun )
910  msg.sprintf( m_footprintsTitleTemplate, numFootprints );
911  else
912  {
914  msg.Replace( wxT( "%d" ), _( "not run" ) );
915  }
916  m_Notebook->SetPageText( 2, msg );
917  }
918  else
919  {
921  msg.Replace( wxT( "(%d)" ), wxEmptyString );
922  m_Notebook->SetPageText( 0, msg );
923 
925  msg.Replace( wxT( "(%d)" ), wxEmptyString );
926  m_Notebook->SetPageText( 1, msg );
927 
929  msg.Replace( wxT( "(%d)" ), wxEmptyString );
930  m_Notebook->SetPageText( 2, msg );
931  }
932 
933  // Update badges:
934 
935  if( !m_drcRun && numErrors == 0 )
936  numErrors = -1;
937 
938  if( !m_drcRun && numWarnings == 0 )
939  numWarnings = -1;
940 
941  m_errorsBadge->SetMaximumNumber( numErrors );
943 
944  m_warningsBadge->SetMaximumNumber( numWarnings );
946 
947  m_exclusionsBadge->SetMaximumNumber( numExcluded );
949 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:62
wxCheckBox * m_showWarnings
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:761
void initValues()
Definition: dialog_drc.cpp:127
virtual void AdvancePhase()
Uses the next vailable virtual zone of the dialog progress bar.
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:240
void DeleteItems(bool aCurrentOnly, bool aIncludeExclusions, bool aDeep)
Deletes the current item or all items.
Definition: rc_item.cpp:431
void syncCheckboxes()
Definition: dialog_drc.cpp:179
wxCheckBox * m_cbTestFootprints
void OnModify() override
Function OnModify must be called after a board change to set the modified flag.
void NextMarker()
Definition: rc_item.cpp:541
wxNotebook * m_Notebook
void NextMarker()
Definition: dialog_drc.cpp:684
void updateDisplayedCounts()
Definition: dialog_drc.cpp:861
BOARD_DESIGN_SETTINGS & bds()
Definition: dialog_drc.h:105
static int RPT_SEVERITY_ALL
Definition: dialog_drc.cpp:176
KIID niluuid(0)
void OnDRCItemRClick(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:389
void SetProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: rc_item.cpp:264
void OnErrorLinkClicked(wxHtmlLinkEvent &event) override
Definition: dialog_drc.cpp:188
wxCheckBox * m_cbReportAllTrackErrors
void deleteAllMarkers(bool aIncludeExclusions)
Definition: dialog_drc.cpp:724
wxButton * m_DeleteCurrentMarkerButton
wxString GetDesignRulesPath()
Returns the absolute path to the design rules file for the currently-loaded board.
This file is part of the common library.
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
Definition: board_item.h:86
RC_TREE_MODEL * m_markerTreeModel
Definition: dialog_drc.h:119
Class DIALOG_DRC_BASE.
SEVERITY
Definition: ui_common.h:83
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Function Report is a pure virtual function to override in the derived object.
A progress reporter for use in multi-threaded environments.
std::atomic_int m_progress
PCB_EDIT_FRAME * m_brdEditor
Definition: dialog_drc.h:108
wxSimplebook * m_runningResultsBook
MARKERS & Markers()
Definition: board.h:292
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
bool writeReport(const wxString &aFullFileName)
Function writeReport outputs the MARKER items and unconnecte DRC_ITEMs with commentary to an open tex...
Definition: dialog_drc.cpp:733
void refreshBoardEditor()
Definition: dialog_drc.cpp:662
void UpdateNumber(int aNumber, SEVERITY aSeverity)
Update the number displayed on the badge.
void PrevMarker()
Definition: dialog_drc.cpp:670
void OnDeleteOneClick(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:798
bool m_footprintTestsRun
Definition: dialog_drc.h:112
wxString m_footprintsTitleTemplate
Definition: dialog_drc.h:116
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings Returns a bit-mask of all t...
Definition: board.cpp:451
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:141
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:559
virtual int GetCount(int aSeverity=-1)=0
wxButton * m_sdbSizerCancel
static KIID ToUUID(wxDataViewItem aItem)
Definition: rc_item.cpp:119
void ExcludeMarker()
Definition: dialog_drc.cpp:698
RC_ITEMS_PROVIDER * m_markersProvider
Definition: dialog_drc.h:118
PCBNEW_SETTINGS * GetPcbNewSettings()
void OnDRCItemDClick(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:374
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
const wxString & GetFileName() const
Definition: board.h:278
BOARD * m_currentBoard
Definition: dialog_drc.h:107
VTBL_ENTRY const wxString GetProjectPath() const
Function GetProjectPath returns the full path of the project.
Definition: project.cpp:122
virtual std::shared_ptr< RC_ITEM > GetItem(int aIndex)=0
Retrieve a RC_ITEM by index.
virtual void Remove(VIEW_ITEM *aItem) override
Function Remove() Removes a VIEW_ITEM from the view.
Definition: pcb_view.cpp:76
void DeleteCurrentItem(bool aDeep)
Definition: rc_item.cpp:425
void SetSeverities(int aSeverities)
Definition: rc_item.cpp:270
Provide an abstract interface of a RC_ITEM* list manager.
Definition: rc_item.h:43
void OnChangingNotebookPage(wxNotebookEvent &aEvent) override
Definition: dialog_drc.cpp:650
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:131
RC_ITEMS_PROVIDER * m_unconnectedItemsProvider
Definition: dialog_drc.h:121
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:95
wxCheckBox * m_showExclusions
Definition: kiid.h:44
wxString m_markersTitleTemplate
Definition: dialog_drc.h:114
virtual void SetCurrentProgress(double aProgress)
Set the progress value to aProgress (0..1)
PCB_LAYER_ID
A quick note on layer IDs:
wxCheckBox * m_cbRefillZones
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: pcb_view.cpp:94
LSET is a set of PCB_LAYER_IDs.
void SetExcluded(bool aExcluded)
Definition: marker_base.h:110
void ShowBoardSetupDialog(const wxString &aInitialPage=wxEmptyString)
Function ShowBoardSetupDialog.
std::shared_ptr< RC_ITEM > m_RcItem
Definition: rc_item.h:205
wxDataViewCtrl * m_footprintsDataView
#define MALFORMED_B_COURTYARD
Definition: eda_item.h:123
#define NULL
RC_ITEMS_PROVIDER * m_footprintWarningsProvider
Definition: dialog_drc.h:124
wxBoxSizer * m_sizerButtons
wxButton * m_DeleteAllMarkersButton
wxButton * m_sdbSizerOK
void OnDeleteAllClick(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:823
static RC_TREE_NODE * ToNode(wxDataViewItem aItem)
Definition: rc_item.h:220
wxString ReportFileWildcard()
void OnDRCItemSelected(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:299
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
DIALOG_DRC(PCB_EDIT_FRAME *aEditorFrame, wxWindow *aParent)
Constructors.
Definition: dialog_drc.cpp:47
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
RC_TREE_MODEL * m_footprintWarningsTreeModel
Definition: dialog_drc.h:125
void SetFootprintsProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: dialog_drc.cpp:291
std::atomic< bool > m_cancelled
Definition: dialog_drc.h:110
Definition of file extensions used in Kicad.
NUMBER_BADGE * m_exclusionsBadge
#define DIALOG_DRC_WINDOW_NAME
Definition: dialog_drc.h:41
Functions to provide common constants and other functions to assist in making a consistent UI.
NUMBER_BADGE * m_errorsBadge
void OnClose(wxCloseEvent &event) override
Definition: dialog_drc.cpp:620
void PrevMarker()
Definition: rc_item.cpp:520
std::shared_ptr< DRC_ENGINE > GetDRCEngine()
Definition: drc_tool.h:113
virtual KIGFX::PCB_VIEW * GetView() const override
Function GetView() Returns a pointer to the VIEW instance used in the panel.
void OnRunDRCClick(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:194
std::map< int, int > m_DRCSeverities
bool Show(bool show) override
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
void RunTests(PROGRESS_REPORTER *aProgressReporter, bool aRefillZones, bool aReportAllTrackErrors, bool aTestFootprints)
Run the DRC tests.
Definition: drc_tool.cpp:142
RC_TREE_MODEL * m_unconnectedTreeModel
Definition: dialog_drc.h:122
wxDataViewCtrl * m_unconnectedDataView
void OnCancelClick(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:631
wxButton * m_saveReport
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
EDA_UNITS
Definition: eda_units.h:38
#define MALFORMED_F_COURTYARD
Definition: eda_item.h:122
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
void SetMarkersProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: dialog_drc.cpp:275
wxDataViewCtrl * m_markerDataView
Struct PARSE_ERROR contains a filename or source description, a problem input line,...
Definition: ki_exception.h:123
see class PGM_BASE
WX_HTML_REPORT_BOX * m_messages
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
const std::string ReportFileExtension
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:186
void ForceFocus(wxWindow *aWindow)
Pass the current focus to the window.
Definition: gtk/ui.cpp:44
#define _(s)
Definition: 3d_actions.cpp:33
wxCheckBox * m_showErrors
NUMBER_BADGE * m_warningsBadge
wxCheckBox * m_showAll
PCB_EDIT_FRAME is the main frame for Pcbnew.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
void OnActivateDlg(wxActivateEvent &aEvent) override
Definition: dialog_drc.cpp:112
bool m_drcRun
Definition: dialog_drc.h:111
int m_severities
Definition: dialog_drc.h:127
void SetLayerVisible(LAYER_NUM aLayer, bool isVisible)
Manually update visibility for a given layer
std::atomic_int m_maxProgress
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:76
APPEARANCE_CONTROLS * GetAppearancePanel()
DIALOG_DRC m_DrcDialog
BOARD * GetBoard() const
void DestroyDRCDialog()
Closes and frees the DRC dialog.
Definition: drc_tool.cpp:132
int GetSeverity(int aDRCErrorCode)
STATUS_FLAGS GetFlags() const
Definition: eda_item.h:222
void OnSaveReport(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:586
void SetMaximumNumber(int aMax)
Set the maximum number to be shown on the badge.
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
Definition: board_item.h:185
bool m_running
Definition: dialog_drc.h:109
bool updateUI() override
Definition: dialog_drc.cpp:154
void SetActiveLayer(PCB_LAYER_ID aLayer) override
Function SetActiveLayer will change the currently active layer to aLayer and also update the APPEARAN...
void FocusOnItem(BOARD_ITEM *aItem)
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Definition: board.cpp:840
void SetUnconnectedProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: dialog_drc.cpp:283
wxString m_unconnectedTitleTemplate
Definition: dialog_drc.h:115
virtual LSET GetLayerSet() const
Function GetLayerSet returns a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:191
void ValueChanged(RC_TREE_NODE *aNode)
Definition: rc_item.cpp:408
void OnSeverity(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:550
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.