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 
139  if( !Kiface().IsSingle() )
140  m_cbTestFootprints->SetValue( cfg->m_DrcDialog.test_footprints );
141 
142  m_severities = cfg->m_DrcDialog.severities;
146 
147  Layout(); // adding the units above expanded Clearance text, now resize.
148 
149  SetFocus();
150 }
151 
152 
153 // PROGRESS_REPORTER calls
154 
156 {
157  double cur = (double) m_progress.load() / m_maxProgress;
158  cur = std::max( 0.0, std::min( cur, 1.0 ) );
159 
160  m_gauge->SetValue( KiROUND( cur * 1000.0 ) );
161  wxSafeYield( this );
162 
163  return !m_cancelled;
164 }
165 
166 
167 void DIALOG_DRC::AdvancePhase( const wxString& aMessage )
168 {
170  SetCurrentProgress( 0.0 );
171 
172  m_messages->Report( aMessage );
173 }
174 
175 
176 // Don't globally define this; different facilities use different definitions of "ALL"
178 
179 
181 {
182  m_showAll->SetValue( m_severities == RPT_SEVERITY_ALL );
186 }
187 
188 
189 void DIALOG_DRC::OnErrorLinkClicked( wxHtmlLinkEvent& event )
190 {
191  m_brdEditor->ShowBoardSetupDialog( _( "Rules" ) );
192 }
193 
194 
195 void DIALOG_DRC::OnRunDRCClick( wxCommandEvent& aEvent )
196 {
198  bool refillZones = m_cbRefillZones->GetValue();
199  bool reportAllTrackErrors = m_cbReportAllTrackErrors->GetValue();
200  bool testFootprints = m_cbTestFootprints->GetValue();
201 
202  // This is not the time to have stale or buggy rules. Ensure they're up-to-date
203  // and that they at least parse.
204  try
205  {
206  drcTool->GetDRCEngine()->InitEngine( m_brdEditor->GetDesignRulesPath() );
207  }
208  catch( PARSE_ERROR& )
209  {
210  m_runningResultsBook->ChangeSelection( 0 ); // Display the "Tests Running..." tab
211  m_DeleteCurrentMarkerButton->Enable( false );
212  m_DeleteAllMarkersButton->Enable( false );
213  m_saveReport->Enable( false );
214 
215  m_messages->Clear();
216  m_messages->Report( _( "DRC incomplete: could not compile custom design rules. " )
217  + wxT( "<a href='boardsetup'>" )
218  + _( "Show design rules." )
219  + wxT( "</a>" ) );
220  m_messages->Flush();
221 
222  Raise();
223  return;
224  }
225 
226  m_drcRun = false;
227  m_footprintTestsRun = false;
228  m_cancelled = false;
229 
231  deleteAllMarkers( true );
232  m_unconnectedTreeModel->DeleteItems( false, true, true );
233  m_footprintWarningsTreeModel->DeleteItems( false, true, true );
234 
235  Raise();
236 
237  m_runningResultsBook->ChangeSelection( 0 ); // Display the "Tests Running..." tab
238  m_messages->Clear();
239  wxYield(); // Allow time slice to refresh Messages
240 
241  m_running = true;
242  m_sdbSizerCancel->SetLabel( _( "Cancel" ) );
243  m_sdbSizerOK->Enable( false );
244  m_DeleteCurrentMarkerButton->Enable( false );
245  m_DeleteAllMarkersButton->Enable( false );
246  m_saveReport->Enable( false );
247 
248  drcTool->RunTests( this, refillZones, reportAllTrackErrors, testFootprints );
249 
250  if( m_cancelled )
251  m_messages->Report( _( "-------- DRC cancelled by user.<br><br>" ) );
252  else
253  m_messages->Report( _( "Done.<br><br>" ) );
254 
255  Raise();
256  wxYield(); // Allow time slice to refresh Messages
257 
258  m_running = false;
259  m_sdbSizerCancel->SetLabel( _( "Close" ) );
260  m_sdbSizerOK->Enable( true );
261  m_DeleteCurrentMarkerButton->Enable( true );
262  m_DeleteAllMarkersButton->Enable( true );
263  m_saveReport->Enable( true );
264 
265  if( !m_cancelled )
266  {
267  wxMilliSleep( 500 );
268  m_runningResultsBook->ChangeSelection( 1 );
270  }
271 
273 }
274 
275 
277 {
278  m_markersProvider = aProvider;
281 }
282 
283 
285 {
286  m_unconnectedItemsProvider = aProvider;
289 }
290 
291 
293 {
294  m_footprintWarningsProvider = aProvider;
297 }
298 
299 
300 void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
301 {
302  BOARD* board = m_brdEditor->GetBoard();
303  RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
304  const KIID& itemID = node ? RC_TREE_MODEL::ToUUID( aEvent.GetItem() ) : niluuid;
305  BOARD_ITEM* item = board->GetItem( itemID );
306 
307  auto getActiveLayers =
308  []( BOARD_ITEM* aItem ) -> LSET
309  {
310  if( aItem->Type() == PCB_PAD_T )
311  {
312  PAD* pad = static_cast<PAD*>( aItem );
313  LSET layers;
314 
315  for( int layer : aItem->GetLayerSet().Seq() )
316  {
317  if( pad->FlashLayer( layer ) )
318  layers.set( layer );
319  }
320 
321  return layers;
322  }
323  else
324  {
325  return aItem->GetLayerSet();
326  }
327  };
328 
329  if( item && node )
330  {
331  PCB_LAYER_ID principalLayer = item->GetLayer();
332  LSET violationLayers;
333  std::shared_ptr<RC_ITEM> rc_item = node->m_RcItem;
334 
335  if( rc_item->GetErrorCode() == DRCE_MALFORMED_COURTYARD )
336  {
337  BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
338 
339  if( a && ( a->GetFlags() & MALFORMED_B_COURTYARD ) > 0
340  && ( a->GetFlags() & MALFORMED_F_COURTYARD ) == 0 )
341  {
342  principalLayer = B_CrtYd;
343  }
344  else
345  {
346  principalLayer = F_CrtYd;
347  }
348  }
349  else if (rc_item->GetErrorCode() == DRCE_INVALID_OUTLINE )
350  {
351  principalLayer = Edge_Cuts;
352  }
353  else
354  {
355  BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
356  BOARD_ITEM* b = board->GetItem( rc_item->GetAuxItemID() );
357  BOARD_ITEM* c = board->GetItem( rc_item->GetAuxItem2ID() );
358  BOARD_ITEM* d = board->GetItem( rc_item->GetAuxItem3ID() );
359 
360  if( a || b || c || d )
361  violationLayers = LSET::AllLayersMask();
362 
363  if( a )
364  violationLayers &= getActiveLayers( a );
365 
366  if( b )
367  violationLayers &= getActiveLayers( b );
368 
369  if( c )
370  violationLayers &= getActiveLayers( c );
371 
372  if( d )
373  violationLayers &= getActiveLayers( d );
374  }
375 
376  if( violationLayers.count() )
377  principalLayer = violationLayers.Seq().front();
378  else
379  violationLayers.set( principalLayer );
380 
381  WINDOW_THAWER thawer( m_brdEditor );
382 
383  m_brdEditor->FocusOnItem( item );
385 
386  if( ( violationLayers & board->GetVisibleLayers() ) == 0 )
387  {
388  m_brdEditor->GetAppearancePanel()->SetLayerVisible( principalLayer, true );
390  }
391 
392  if( board->GetVisibleLayers().test( principalLayer ) )
393  m_brdEditor->SetActiveLayer( principalLayer );
394  }
395 
396  aEvent.Skip();
397 }
398 
399 
400 void DIALOG_DRC::OnDRCItemDClick( wxDataViewEvent& aEvent )
401 {
402  if( aEvent.GetItem().IsOk() )
403  {
404  // turn control over to m_brdEditor, hide this DIALOG_DRC window,
405  // no destruction so we can preserve listbox cursor
406  if( !IsModal() )
407  Show( false );
408  }
409 
410  // Do not skip aVent here: tihs is not useful, and Pcbnew crashes
411  // if skipped (at least on Windows)
412 }
413 
414 
415 void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
416 {
417  RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
418 
419  if( !node )
420  return;
421 
422  std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
423  wxString listName;
424  wxMenu menu;
425  wxString msg;
426 
427  switch( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] )
428  {
429  case RPT_SEVERITY_ERROR: listName = _( "errors" ); break;
430  case RPT_SEVERITY_WARNING: listName = _( "warnings" ); break;
431  default: listName = _( "appropriate" ); break;
432  }
433 
434  if( rcItem->GetParent()->IsExcluded() )
435  {
436  menu.Append( 1, _( "Remove exclusion for this violation" ),
437  wxString::Format( _( "It will be placed back in the %s list" ), listName ) );
438  }
439  else
440  {
441  menu.Append( 2, _( "Exclude this violation" ),
442  wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
443  }
444 
445  menu.AppendSeparator();
446 
447  if( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] == RPT_SEVERITY_WARNING )
448  {
449  msg.Printf( _( "Change severity to Error for all '%s' violations" ),
450  rcItem->GetErrorText(),
451  _( "Violation severities can also be edited in the Board Setup... dialog" ) );
452  menu.Append( 3, msg );
453  }
454  else
455  {
456  msg.Printf( _( "Change severity to Warning for all '%s' violations" ),
457  rcItem->GetErrorText(),
458  _( "Violation severities can also be edited in the Board Setup... dialog" ) );
459  menu.Append( 4, msg );
460  }
461 
462  msg.Printf( _( "Ignore all '%s' violations" ),
463  rcItem->GetErrorText(),
464  _( "Violations will not be checked or reported" ) );
465  menu.Append( 5, msg );
466 
467  menu.AppendSeparator();
468 
469  menu.Append( 6, _( "Edit violation severities..." ), _( "Open the Board Setup... dialog" ) );
470 
471  bool modified = false;
472 
473  switch( GetPopupMenuSelectionFromUser( menu ) )
474  {
475  case 1:
476  {
477  PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
478 
479  if( marker )
480  {
481  marker->SetExcluded( false );
482  m_brdEditor->GetCanvas()->GetView()->Update( marker );
483 
484  // Update view
485  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
486  modified = true;
487  }
488  }
489  break;
490 
491  case 2:
492  {
493  PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
494 
495  if( marker )
496  {
497  marker->SetExcluded( true );
498  m_brdEditor->GetCanvas()->GetView()->Update( marker );
499 
500  // Update view
502  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
503  else
504  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->DeleteCurrentItem( false );
505 
506  modified = true;
507  }
508  }
509  break;
510 
511  case 3:
512  bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_ERROR;
513 
514  for( PCB_MARKER* marker : m_brdEditor->GetBoard()->Markers() )
515  {
516  if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
517  m_brdEditor->GetCanvas()->GetView()->Update( marker );
518  }
519 
520  // Rebuild model and view
521  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->SetProvider( m_markersProvider );
522  modified = true;
523  break;
524 
525  case 4:
526  bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_WARNING;
527 
528  for( PCB_MARKER* marker : m_brdEditor->GetBoard()->Markers() )
529  {
530  if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
531  m_brdEditor->GetCanvas()->GetView()->Update( marker );
532  }
533 
534  // Rebuild model and view
535  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->SetProvider( m_markersProvider );
536  modified = true;
537  break;
538 
539  case 5:
540  {
541  bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_IGNORE;
542 
543  std::vector<PCB_MARKER*>& markers = m_brdEditor->GetBoard()->Markers();
544 
545  for( unsigned i = 0; i < markers.size(); )
546  {
547  if( markers[i]->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
548  {
549  m_brdEditor->GetCanvas()->GetView()->Remove( markers.at( i ) );
550  markers.erase( markers.begin() + i );
551  }
552  else
553  ++i;
554  }
555 
556  // Rebuild model and view
557  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->SetProvider( m_markersProvider );
558  modified = true;
559  }
560  break;
561 
562  case 6:
563  m_brdEditor->ShowBoardSetupDialog( _( "Violation Severity" ) );
564  break;
565  }
566 
567  if( modified )
568  {
572  }
573 }
574 
575 
576 void DIALOG_DRC::OnSeverity( wxCommandEvent& aEvent )
577 {
578  int flag = 0;
579 
580  if( aEvent.GetEventObject() == m_showAll )
581  flag = RPT_SEVERITY_ALL;
582  else if( aEvent.GetEventObject() == m_showErrors )
583  flag = RPT_SEVERITY_ERROR;
584  else if( aEvent.GetEventObject() == m_showWarnings )
585  flag = RPT_SEVERITY_WARNING;
586  else if( aEvent.GetEventObject() == m_showExclusions )
587  flag = RPT_SEVERITY_EXCLUSION;
588 
589  if( aEvent.IsChecked() )
590  m_severities |= flag;
591  else if( aEvent.GetEventObject() == m_showAll )
593  else
594  m_severities &= ~flag;
595 
596  syncCheckboxes();
597 
598  // Set the provider's severity levels through the TreeModel so that the old tree
599  // can be torn down before the severity changes.
600  //
601  // It's not clear this is required, but we've had a lot of issues with wxDataView
602  // being cranky on various platforms.
603 
607 
609 }
610 
611 
612 void DIALOG_DRC::OnSaveReport( wxCommandEvent& aEvent )
613 {
614  wxFileName fn( "./DRC." + ReportFileExtension );
615 
616  wxFileDialog dlg( this, _( "Save Report to File" ), fn.GetPath(), fn.GetFullName(),
617  ReportFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
618 
619  if( dlg.ShowModal() != wxID_OK )
620  return;
621 
622  fn = dlg.GetPath();
623 
624  if( fn.GetExt().IsEmpty() )
625  fn.SetExt( ReportFileExtension );
626 
627  if( !fn.IsAbsolute() )
628  {
629  wxString prj_path = Prj().GetProjectPath();
630  fn.MakeAbsolute( prj_path );
631  }
632 
633  if( writeReport( fn.GetFullPath() ) )
634  {
635  m_messages->Report( wxString::Format( _( "Report file '%s' created<br>" ),
636  fn.GetFullPath() ) );
637  }
638  else
639  {
640  DisplayError( this, wxString::Format( _( "Unable to create report file '%s'<br>" ),
641  fn.GetFullPath() ) );
642  }
643 }
644 
645 
646 void DIALOG_DRC::OnClose( wxCloseEvent& aEvent )
647 {
648  if( m_running )
649  aEvent.Veto();
650 
651  wxCommandEvent dummy;
652 
653  OnCancelClick( dummy );
654 }
655 
656 
657 void DIALOG_DRC::OnCancelClick( wxCommandEvent& aEvent )
658 {
659  if( m_running )
660  {
661  m_cancelled = true;
662  return;
663  }
664 
665  m_brdEditor->FocusOnItem( nullptr );
666 
667  SetReturnCode( wxID_CANCEL );
668 
669  // The dialog can be modal or not modal.
670  // Leave the DRC caller destroy (or not) the dialog
672  drcTool->DestroyDRCDialog();
673 }
674 
675 
676 void DIALOG_DRC::OnChangingNotebookPage( wxNotebookEvent& aEvent )
677 {
678  // Shouldn't be necessary, but is on at least OSX
679  if( aEvent.GetSelection() >= 0 )
680  m_Notebook->ChangeSelection( (unsigned) aEvent.GetSelection() );
681 
682  m_markerDataView->UnselectAll();
683  m_unconnectedDataView->UnselectAll();
684  m_footprintsDataView->UnselectAll();
685 }
686 
687 
689 {
690  WINDOW_THAWER thawer( m_brdEditor );
691 
693 }
694 
695 
697 {
698  if( m_Notebook->IsShown() )
699  {
700  switch( m_Notebook->GetSelection() )
701  {
702  case 0: m_markerTreeModel->PrevMarker(); break;
703  case 1: m_unconnectedTreeModel->PrevMarker(); break;
704  case 2: m_footprintWarningsTreeModel->PrevMarker(); break;
705  }
706  }
707 }
708 
709 
711 {
712  if( m_Notebook->IsShown() )
713  {
714  switch( m_Notebook->GetSelection() )
715  {
716  case 0: m_markerTreeModel->NextMarker(); break;
717  case 1: m_unconnectedTreeModel->NextMarker(); break;
718  case 2: m_footprintWarningsTreeModel->NextMarker(); break;
719  }
720  }
721 }
722 
723 
725 {
726  if( !m_Notebook->IsShown() || m_Notebook->GetSelection() != 0 )
727  return;
728 
729  RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( m_markerDataView->GetCurrentItem() );
730  PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
731 
732  if( marker && !marker->IsExcluded() )
733  {
734  marker->SetExcluded( true );
735  m_brdEditor->GetCanvas()->GetView()->Update( marker );
736 
737  // Update view
740  else
742 
746  }
747 }
748 
749 
750 void DIALOG_DRC::deleteAllMarkers( bool aIncludeExclusions )
751 {
752  // Clear current selection list to avoid selection of deleted items
754 
755  m_markerTreeModel->DeleteItems( false, aIncludeExclusions, true );
756 }
757 
758 
759 bool DIALOG_DRC::writeReport( const wxString& aFullFileName )
760 {
761  FILE* fp = wxFopen( aFullFileName, wxT( "w" ) );
762 
763  if( fp == NULL )
764  return false;
765 
766  std::map<KIID, EDA_ITEM*> itemMap;
767  m_brdEditor->GetBoard()->FillItemMap( itemMap );
768 
769  EDA_UNITS units = GetUserUnits();
771  int count;
772 
773  fprintf( fp, "** Drc report for %s **\n", TO_UTF8( m_brdEditor->GetBoard()->GetFileName() ) );
774 
775  wxDateTime now = wxDateTime::Now();
776 
777  fprintf( fp, "** Created on %s **\n", TO_UTF8( now.Format( wxT( "%F %T" ) ) ) );
778 
779  count = m_markersProvider->GetCount();
780 
781  fprintf( fp, "\n** Found %d DRC violations **\n", count );
782 
783  for( int i = 0; i < count; ++i )
784  {
785  const std::shared_ptr<RC_ITEM>& item = m_markersProvider->GetItem( i );
786  SEVERITY severity = bds.GetSeverity( item->GetErrorCode() );
787 
788  fprintf( fp, "%s", TO_UTF8( item->ShowReport( units, severity, itemMap ) ) );
789  }
790 
792 
793  fprintf( fp, "\n** Found %d unconnected pads **\n", count );
794 
795  for( int i = 0; i < count; ++i )
796  {
797  const std::shared_ptr<RC_ITEM>& item = m_unconnectedItemsProvider->GetItem( i );
798  SEVERITY severity = bds.GetSeverity( item->GetErrorCode() );
799 
800  fprintf( fp, "%s", TO_UTF8( item->ShowReport( units, severity, itemMap ) ) );
801  }
802 
804 
805  fprintf( fp, "\n** Found %d Footprint errors **\n", count );
806 
807  for( int i = 0; i < count; ++i )
808  {
809  const std::shared_ptr<RC_ITEM>& item = m_footprintWarningsProvider->GetItem( i );
810  SEVERITY severity = bds.GetSeverity( item->GetErrorCode() );
811 
812  fprintf( fp, "%s", TO_UTF8( item->ShowReport( units, severity, itemMap ) ) );
813  }
814 
815 
816  fprintf( fp, "\n** End of Report **\n" );
817 
818  fclose( fp );
819 
820  return true;
821 }
822 
823 
824 void DIALOG_DRC::OnDeleteOneClick( wxCommandEvent& aEvent )
825 {
826  if( m_Notebook->GetSelection() == 0 )
827  {
828  // Clear the selection. It may be the selected DRC marker.
830 
832 
833  // redraw the pcb
835  }
836  else if( m_Notebook->GetSelection() == 1 )
837  {
839  }
840  else if( m_Notebook->GetSelection() == 2 )
841  {
843  }
844 
846 }
847 
848 
849 void DIALOG_DRC::OnDeleteAllClick( wxCommandEvent& aEvent )
850 {
851  static bool s_includeExclusions = false;
852 
853  int numExcluded = 0;
854 
855  if( m_markersProvider )
857 
860 
863 
864  if( numExcluded > 0 )
865  {
866  wxRichMessageDialog dlg( this, _( "Do you wish to delete excluded markers as well?" ),
867  _( "Delete All Markers" ),
868  wxOK | wxCANCEL | wxCENTER | wxICON_QUESTION );
869  dlg.ShowCheckBox( _( "Delete exclusions" ), s_includeExclusions );
870 
871  int ret = dlg.ShowModal();
872 
873  if( ret == wxID_CANCEL )
874  return;
875  else
876  s_includeExclusions = dlg.IsCheckBoxChecked();
877  }
878 
879  deleteAllMarkers( s_includeExclusions );
880 
881  m_drcRun = false;
884 }
885 
886 
888 {
889  // Collect counts:
890 
891  int numMarkers = 0;
892  int numUnconnected = 0;
893  int numFootprints = 0;
894 
895  int numErrors = 0;
896  int numWarnings = 0;
897  int numExcluded = 0;
898 
899  if( m_markersProvider )
900  {
901  numMarkers += m_markersProvider->GetCount();
905  }
906 
908  {
909  numUnconnected += m_unconnectedItemsProvider->GetCount();
913  }
914 
916  {
917  numFootprints += m_footprintWarningsProvider->GetCount();
921  }
922 
923  wxString msg;
924 
925  // Update tab headers:
926 
927  if( m_drcRun )
928  {
929  msg.sprintf( m_markersTitleTemplate, numMarkers );
930  m_Notebook->SetPageText( 0, msg );
931 
932  msg.sprintf( m_unconnectedTitleTemplate, numUnconnected );
933  m_Notebook->SetPageText( 1, msg );
934 
935  if( m_footprintTestsRun )
936  msg.sprintf( m_footprintsTitleTemplate, numFootprints );
937  else
938  {
940  msg.Replace( wxT( "%d" ), _( "not run" ) );
941  }
942  m_Notebook->SetPageText( 2, msg );
943  }
944  else
945  {
947  msg.Replace( wxT( "(%d)" ), wxEmptyString );
948  m_Notebook->SetPageText( 0, msg );
949 
951  msg.Replace( wxT( "(%d)" ), wxEmptyString );
952  m_Notebook->SetPageText( 1, msg );
953 
955  msg.Replace( wxT( "(%d)" ), wxEmptyString );
956  m_Notebook->SetPageText( 2, msg );
957  }
958 
959  // Update badges:
960 
961  if( !m_drcRun && numErrors == 0 )
962  numErrors = -1;
963 
964  if( !m_drcRun && numWarnings == 0 )
965  numWarnings = -1;
966 
967  m_errorsBadge->SetMaximumNumber( numErrors );
969 
970  m_warningsBadge->SetMaximumNumber( numWarnings );
972 
973  m_exclusionsBadge->SetMaximumNumber( numExcluded );
975 }
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:63
wxCheckBox * m_showWarnings
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:792
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:253
void DeleteItems(bool aCurrentOnly, bool aIncludeExclusions, bool aDeep)
Deletes the current item or all items.
Definition: rc_item.cpp:438
void syncCheckboxes()
Definition: dialog_drc.cpp:180
wxCheckBox * m_cbTestFootprints
void OnModify() override
Must be called after a board change to set the modified flag.
void NextMarker()
Definition: rc_item.cpp:548
wxNotebook * m_Notebook
void NextMarker()
Definition: dialog_drc.cpp:710
void updateDisplayedCounts()
Definition: dialog_drc.cpp:887
BOARD_DESIGN_SETTINGS & bds()
Definition: dialog_drc.h:105
static int RPT_SEVERITY_ALL
Definition: dialog_drc.cpp:177
KIID niluuid(0)
void OnDRCItemRClick(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:415
void SetProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: rc_item.cpp:264
void OnErrorLinkClicked(wxHtmlLinkEvent &event) override
Definition: dialog_drc.cpp:189
wxCheckBox * m_cbReportAllTrackErrors
void deleteAllMarkers(bool aIncludeExclusions)
Definition: dialog_drc.cpp:750
wxButton * m_DeleteCurrentMarkerButton
wxString GetDesignRulesPath()
Return the absolute path to the design rules file for the currently-loaded board.
This file is part of the common library.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
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
Report a string with a given severity.
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:312
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:759
void refreshBoardEditor()
Definition: dialog_drc.cpp:688
void UpdateNumber(int aNumber, SEVERITY aSeverity)
Update the number displayed on the badge.
void PrevMarker()
Definition: dialog_drc.cpp:696
void OnDeleteOneClick(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:824
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:461
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:141
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
Definition: sch_symbol.cpp:69
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:591
virtual int GetCount(int aSeverity=-1)=0
class PAD, a pad in a footprint
Definition: typeinfo.h:89
wxButton * m_sdbSizerCancel
static KIID ToUUID(wxDataViewItem aItem)
Definition: rc_item.cpp:119
void ExcludeMarker()
Definition: dialog_drc.cpp:724
RC_ITEMS_PROVIDER * m_markersProvider
Definition: dialog_drc.h:118
void OnDRCItemDClick(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:400
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:298
BOARD * m_currentBoard
Definition: dialog_drc.h:107
virtual const wxString GetProjectPath() const
Return the full path of the project.
virtual std::shared_ptr< RC_ITEM > GetItem(int aIndex)=0
Retrieve a RC_ITEM by index.
virtual void Remove(VIEW_ITEM *aItem) override
Remove a VIEW_ITEM from the view.
Definition: pcb_view.cpp:75
void DeleteCurrentItem(bool aDeep)
Definition: rc_item.cpp:432
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:676
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:120
RC_ITEMS_PROVIDER * m_unconnectedItemsProvider
Definition: dialog_drc.h:121
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
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, inform the associated VIEW that the graphical representation of this item has chan...
Definition: pcb_view.cpp:92
bool FlashLayer(int aLayer) const
Check to see whether the pad should be flashed on the specific layer.
Definition: pcbnew/pad.cpp:202
LSET is a set of PCB_LAYER_IDs.
void SetExcluded(bool aExcluded)
Definition: marker_base.h:95
void ShowBoardSetupDialog(const wxString &aInitialPage=wxEmptyString)
std::shared_ptr< RC_ITEM > m_RcItem
Definition: rc_item.h:205
wxDataViewCtrl * m_footprintsDataView
#define MALFORMED_B_COURTYARD
Definition: eda_item.h:124
#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:849
static RC_TREE_NODE * ToNode(wxDataViewItem aItem)
Definition: rc_item.h:220
wxString ReportFileWildcard()
void OnDRCItemSelected(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:300
PROJECT & Prj() const
Return 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:292
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
static LSET AllLayersMask()
Definition: lset.cpp:787
SEVERITY GetSeverity(int aDRCErrorCode)
void OnClose(wxCloseEvent &event) override
Definition: dialog_drc.cpp:646
void PrevMarker()
Definition: rc_item.cpp:527
std::shared_ptr< DRC_ENGINE > GetDRCEngine()
Definition: drc_tool.h:90
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
void OnRunDRCClick(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:195
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:129
RC_TREE_MODEL * m_unconnectedTreeModel
Definition: dialog_drc.h:122
wxDataViewCtrl * m_unconnectedDataView
void OnCancelClick(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:657
wxButton * m_saveReport
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
EDA_UNITS
Definition: eda_units.h:38
#define MALFORMED_F_COURTYARD
Definition: eda_item.h:123
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:276
wxDataViewCtrl * m_markerDataView
A filename or source description, a problem input line, a line number, a byte offset,...
Definition: ki_exception.h:118
see class PGM_BASE
WX_HTML_REPORT_BOX * m_messages
const std::string ReportFileExtension
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
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
std::map< int, SEVERITY > m_DRCSeverities
NUMBER_BADGE * m_warningsBadge
wxCheckBox * m_showAll
The main frame for Pcbnew.
PCBNEW_SETTINGS * GetPcbNewSettings() const
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)
std::atomic_int m_maxProgress
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
APPEARANCE_CONTROLS * GetAppearancePanel()
DIALOG_DRC m_DrcDialog
BOARD * GetBoard() const
void DestroyDRCDialog()
Close and free the DRC dialog.
Definition: drc_tool.cpp:119
Definition: pad.h:60
STATUS_FLAGS GetFlags() const
Definition: eda_item.h:204
void OnSaveReport(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:612
void SetMaximumNumber(int aMax)
Set the maximum number to be shown on the badge.
bool m_running
Definition: dialog_drc.h:109
bool updateUI() override
Definition: dialog_drc.cpp:155
void SetActiveLayer(PCB_LAYER_ID aLayer) override
Change the currently active layer to aLayer and also update the APPEARANCE_CONTROLS.
void FocusOnItem(BOARD_ITEM *aItem)
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Definition: board.cpp:871
void SetUnconnectedProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: dialog_drc.cpp:284
wxString m_unconnectedTitleTemplate
Definition: dialog_drc.h:115
void ValueChanged(RC_TREE_NODE *aNode)
Definition: rc_item.cpp:415
void OnSeverity(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:576
Container for design settings for a BOARD object.