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 <confirm.h>
27 #include <dialog_drc.h>
28 #include <kiface_i.h>
29 #include <macros.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/ui_common.h>
43 #include <tools/drc_tool.h>
44 #include <kiplatform/ui.h>
45 
46 DIALOG_DRC::DIALOG_DRC( PCB_EDIT_FRAME* aEditorFrame, wxWindow* aParent ) :
47  DIALOG_DRC_BASE( aParent ),
48  PROGRESS_REPORTER( 1 ),
49  m_running( false ),
50  m_cancelled( false ),
51  m_drcRun( false ),
52  m_footprintTestsRun( false ),
53  m_markersProvider( nullptr ),
54  m_markersTreeModel( nullptr ),
55  m_unconnectedItemsProvider( nullptr ),
56  m_unconnectedTreeModel( nullptr ),
57  m_footprintWarningsProvider( nullptr ),
58  m_footprintWarningsTreeModel( nullptr ),
60 {
61  SetName( DIALOG_DRC_WINDOW_NAME ); // Set a window name to be able to find it
62 
63  m_frame = aEditorFrame;
65 
67 
69  m_markerDataView->AssociateModel( m_markersTreeModel );
70 
73 
76 
77  if( Kiface().IsSingle() )
78  m_cbTestFootprints->Hide();
79 
80  // We use a sdbSizer here to get the order right, which is platform-dependent
81  m_sdbSizerOK->SetLabel( _( "Run DRC" ) );
82  m_sdbSizerCancel->SetLabel( _( "Close" ) );
83  m_sizerButtons->Layout();
84 
85  m_sdbSizerOK->SetDefault();
86 
87  initValues();
89 
91 }
92 
93 
95 {
96  m_frame->FocusOnItem( nullptr );
97 
99  settings->m_DrcDialog.refill_zones = m_cbRefillZones->GetValue();
101 
102  if( !Kiface().IsSingle() )
103  settings->m_DrcDialog.test_footprints = m_cbTestFootprints->GetValue();
104 
105  settings->m_DrcDialog.severities = m_severities;
106 
107  m_markersTreeModel->DecRef();
108 }
109 
110 
111 void DIALOG_DRC::OnActivateDlg( wxActivateEvent& aEvent )
112 {
113  if( m_currentBoard != m_frame->GetBoard() )
114  {
115  // If m_currentBoard is not the current board, (for instance because a new board
116  // was loaded), close the dialog, because many pointers are now invalid in lists
117  SetReturnCode( wxID_CANCEL );
118  Close();
119 
120  DRC_TOOL* drcTool = m_frame->GetToolManager()->GetTool<DRC_TOOL>();
121  drcTool->DestroyDRCDialog();
122  }
123 }
124 
125 
127 {
128  m_markersTitleTemplate = m_Notebook->GetPageText( 0 );
129  m_unconnectedTitleTemplate = m_Notebook->GetPageText( 1 );
130  m_footprintsTitleTemplate = m_Notebook->GetPageText( 2 );
131 
132  auto cfg = m_frame->GetPcbNewSettings();
133 
134  m_cbRefillZones->SetValue( cfg->m_DrcDialog.refill_zones );
135  m_cbReportAllTrackErrors->SetValue( cfg->m_DrcDialog.test_all_track_errors );
136 
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_frame->ShowBoardSetupDialog( _( "Rules" ) );
191 }
192 
193 
194 void DIALOG_DRC::OnRunDRCClick( wxCommandEvent& aEvent )
195 {
196  DRC_TOOL* drcTool = m_frame->GetToolManager()->GetTool<DRC_TOOL>();
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_frame->GetDesignRulesPath() );
206  }
207  catch( PARSE_ERROR& )
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 custom 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 
271  refreshEditor();
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_frame->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  auto getActiveLayers =
307  []( BOARD_ITEM* aItem ) -> LSET
308  {
309  if( aItem->Type() == PCB_PAD_T )
310  {
311  PAD* pad = static_cast<PAD*>( aItem );
312  LSET layers;
313 
314  for( int layer : aItem->GetLayerSet().Seq() )
315  {
316  if( pad->FlashLayer( layer ) )
317  layers.set( layer );
318  }
319 
320  return layers;
321  }
322  else
323  {
324  return aItem->GetLayerSet();
325  }
326  };
327 
328  if( node && item )
329  {
330  PCB_LAYER_ID principalLayer = item->GetLayer();
331  LSET violationLayers;
332  std::shared_ptr<RC_ITEM> rc_item = node->m_RcItem;
333 
334  if( rc_item->GetErrorCode() == DRCE_MALFORMED_COURTYARD )
335  {
336  BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
337 
338  if( a && ( a->GetFlags() & MALFORMED_B_COURTYARD ) > 0
339  && ( a->GetFlags() & MALFORMED_F_COURTYARD ) == 0 )
340  {
341  principalLayer = B_CrtYd;
342  }
343  else
344  {
345  principalLayer = F_CrtYd;
346  }
347  }
348  else if (rc_item->GetErrorCode() == DRCE_INVALID_OUTLINE )
349  {
350  principalLayer = Edge_Cuts;
351  }
352  else
353  {
354  BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
355  BOARD_ITEM* b = board->GetItem( rc_item->GetAuxItemID() );
356  BOARD_ITEM* c = board->GetItem( rc_item->GetAuxItem2ID() );
357  BOARD_ITEM* d = board->GetItem( rc_item->GetAuxItem3ID() );
358 
359  if( a || b || c || d )
360  violationLayers = LSET::AllLayersMask();
361 
362  if( a )
363  violationLayers &= getActiveLayers( a );
364 
365  if( b )
366  violationLayers &= getActiveLayers( b );
367 
368  if( c )
369  violationLayers &= getActiveLayers( c );
370 
371  if( d )
372  violationLayers &= getActiveLayers( d );
373  }
374 
375  if( violationLayers.count() )
376  principalLayer = violationLayers.Seq().front();
377  else
378  violationLayers.set( principalLayer );
379 
380  WINDOW_THAWER thawer( m_frame );
381 
382  m_frame->FocusOnItem( item );
383  m_frame->GetCanvas()->Refresh();
384 
385  if( ( violationLayers & board->GetVisibleLayers() ) == 0 )
386  {
387  m_frame->GetAppearancePanel()->SetLayerVisible( principalLayer, true );
388  m_frame->GetCanvas()->Refresh();
389  }
390 
391  if( board->GetVisibleLayers().test( principalLayer ) )
392  m_frame->SetActiveLayer( principalLayer );
393  }
394 
395  aEvent.Skip();
396 }
397 
398 
399 void DIALOG_DRC::OnDRCItemDClick( wxDataViewEvent& aEvent )
400 {
401  if( aEvent.GetItem().IsOk() )
402  {
403  // turn control over to m_frame, hide this DIALOG_DRC window,
404  // no destruction so we can preserve listbox cursor
405  if( !IsModal() )
406  Show( false );
407  }
408 
409  // Do not skip aVent here: tihs is not useful, and Pcbnew crashes
410  // if skipped (at least on Windows)
411 }
412 
413 
414 void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
415 {
416  RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
417 
418  if( !node )
419  return;
420 
421  std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
422  wxString listName;
423  wxMenu menu;
424  wxString msg;
425 
426  switch( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] )
427  {
428  case RPT_SEVERITY_ERROR: listName = _( "errors" ); break;
429  case RPT_SEVERITY_WARNING: listName = _( "warnings" ); break;
430  default: listName = _( "appropriate" ); break;
431  }
432 
433  if( rcItem->GetParent()->IsExcluded() )
434  {
435  menu.Append( 1, _( "Remove exclusion for this violation" ),
436  wxString::Format( _( "It will be placed back in the %s list" ), listName ) );
437  }
438  else
439  {
440  menu.Append( 2, _( "Exclude this violation" ),
441  wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
442  }
443 
444  menu.AppendSeparator();
445 
446  if( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] == RPT_SEVERITY_WARNING )
447  {
448  msg.Printf( _( "Change severity to Error for all '%s' violations" ),
449  rcItem->GetErrorText(),
450  _( "Violation severities can also be edited in the Board Setup... dialog" ) );
451  menu.Append( 3, msg );
452  }
453  else
454  {
455  msg.Printf( _( "Change severity to Warning for all '%s' violations" ),
456  rcItem->GetErrorText(),
457  _( "Violation severities can also be edited in the Board Setup... dialog" ) );
458  menu.Append( 4, msg );
459  }
460 
461  msg.Printf( _( "Ignore all '%s' violations" ),
462  rcItem->GetErrorText(),
463  _( "Violations will not be checked or reported" ) );
464  menu.Append( 5, msg );
465 
466  menu.AppendSeparator();
467 
468  menu.Append( 6, _( "Edit violation severities..." ), _( "Open the Board Setup... dialog" ) );
469 
470  bool modified = false;
471 
472  switch( GetPopupMenuSelectionFromUser( menu ) )
473  {
474  case 1:
475  {
476  PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
477 
478  if( marker )
479  {
480  marker->SetExcluded( false );
481  m_frame->GetCanvas()->GetView()->Update( marker );
482 
483  // Update view
484  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
485  modified = true;
486  }
487  }
488  break;
489 
490  case 2:
491  {
492  PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
493 
494  if( marker )
495  {
496  marker->SetExcluded( true );
497  m_frame->GetCanvas()->GetView()->Update( marker );
498 
499  // Update view
501  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
502  else
503  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->DeleteCurrentItem( false );
504 
505  modified = true;
506  }
507  }
508  break;
509 
510  case 3:
511  bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_ERROR;
512 
513  for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
514  {
515  if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
516  m_frame->GetCanvas()->GetView()->Update( marker );
517  }
518 
519  // Rebuild model and view
520  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->SetProvider( m_markersProvider );
521  modified = true;
522  break;
523 
524  case 4:
525  bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_WARNING;
526 
527  for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
528  {
529  if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
530  m_frame->GetCanvas()->GetView()->Update( marker );
531  }
532 
533  // Rebuild model and view
534  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->SetProvider( m_markersProvider );
535  modified = true;
536  break;
537 
538  case 5:
539  {
540  bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_IGNORE;
541 
542  std::vector<PCB_MARKER*>& markers = m_frame->GetBoard()->Markers();
543 
544  for( unsigned i = 0; i < markers.size(); )
545  {
546  if( markers[i]->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
547  {
548  m_frame->GetCanvas()->GetView()->Remove( markers.at( i ) );
549  markers.erase( markers.begin() + i );
550  }
551  else
552  ++i;
553  }
554 
555  // Rebuild model and view
556  static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->SetProvider( m_markersProvider );
557  modified = true;
558  }
559  break;
560 
561  case 6:
562  m_frame->ShowBoardSetupDialog( _( "Violation Severity" ) );
563  break;
564  }
565 
566  if( modified )
567  {
569  refreshEditor();
570  m_frame->OnModify();
571  }
572 }
573 
574 
575 void DIALOG_DRC::OnSeverity( wxCommandEvent& aEvent )
576 {
577  int flag = 0;
578 
579  if( aEvent.GetEventObject() == m_showAll )
581  else if( aEvent.GetEventObject() == m_showErrors )
583  else if( aEvent.GetEventObject() == m_showWarnings )
585  else if( aEvent.GetEventObject() == m_showExclusions )
587 
588  if( aEvent.IsChecked() )
589  m_severities |= flag;
590  else if( aEvent.GetEventObject() == m_showAll )
592  else
593  m_severities &= ~flag;
594 
595  syncCheckboxes();
596 
597  // Set the provider's severity levels through the TreeModel so that the old tree
598  // can be torn down before the severity changes.
599  //
600  // It's not clear this is required, but we've had a lot of issues with wxDataView
601  // being cranky on various platforms.
602 
606 
608 }
609 
610 
611 void DIALOG_DRC::OnSaveReport( wxCommandEvent& aEvent )
612 {
613  wxFileName fn( "./DRC." + ReportFileExtension );
614 
615  wxFileDialog dlg( this, _( "Save Report to File" ), fn.GetPath(), fn.GetFullName(),
616  ReportFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
617 
618  if( dlg.ShowModal() != wxID_OK )
619  return;
620 
621  fn = dlg.GetPath();
622 
623  if( fn.GetExt().IsEmpty() )
624  fn.SetExt( ReportFileExtension );
625 
626  if( !fn.IsAbsolute() )
627  {
628  wxString prj_path = Prj().GetProjectPath();
629  fn.MakeAbsolute( prj_path );
630  }
631 
632  if( writeReport( fn.GetFullPath() ) )
633  {
634  m_messages->Report( wxString::Format( _( "Report file '%s' created<br>" ),
635  fn.GetFullPath() ) );
636  }
637  else
638  {
639  DisplayError( this, wxString::Format( _( "Unable to create report file '%s'<br>" ),
640  fn.GetFullPath() ) );
641  }
642 }
643 
644 
645 void DIALOG_DRC::OnClose( wxCloseEvent& aEvent )
646 {
647  if( m_running )
648  aEvent.Veto();
649 
650  wxCommandEvent dummy;
651 
652  OnCancelClick( dummy );
653 }
654 
655 
656 void DIALOG_DRC::OnCancelClick( wxCommandEvent& aEvent )
657 {
658  if( m_running )
659  {
660  m_cancelled = true;
661  return;
662  }
663 
664  m_frame->FocusOnItem( nullptr );
665 
666  SetReturnCode( wxID_CANCEL );
667 
668  // The dialog can be modal or not modal.
669  // Leave the DRC caller destroy (or not) the dialog
670  DRC_TOOL* drcTool = m_frame->GetToolManager()->GetTool<DRC_TOOL>();
671  drcTool->DestroyDRCDialog();
672 }
673 
674 
675 void DIALOG_DRC::OnChangingNotebookPage( wxNotebookEvent& aEvent )
676 {
677  // Shouldn't be necessary, but is on at least OSX
678  if( aEvent.GetSelection() >= 0 )
679  m_Notebook->ChangeSelection( (unsigned) aEvent.GetSelection() );
680 
681  m_markerDataView->UnselectAll();
682  m_unconnectedDataView->UnselectAll();
683  m_footprintsDataView->UnselectAll();
684 }
685 
686 
688 {
689  WINDOW_THAWER thawer( m_frame );
690 
691  m_frame->GetCanvas()->Refresh();
692 }
693 
694 
696 {
697  if( m_Notebook->IsShown() )
698  {
699  switch( m_Notebook->GetSelection() )
700  {
701  case 0: m_markersTreeModel->PrevMarker(); break;
702  case 1: m_unconnectedTreeModel->PrevMarker(); break;
703  case 2: m_footprintWarningsTreeModel->PrevMarker(); break;
704  }
705  }
706 }
707 
708 
710 {
711  if( m_Notebook->IsShown() )
712  {
713  switch( m_Notebook->GetSelection() )
714  {
715  case 0: m_markersTreeModel->NextMarker(); break;
716  case 1: m_unconnectedTreeModel->NextMarker(); break;
717  case 2: m_footprintWarningsTreeModel->NextMarker(); break;
718  }
719  }
720 }
721 
722 
724 {
725  if( !m_Notebook->IsShown() || m_Notebook->GetSelection() != 0 )
726  return;
727 
728  RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( m_markerDataView->GetCurrentItem() );
729  PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
730 
731  if( marker && !marker->IsExcluded() )
732  {
733  marker->SetExcluded( true );
734  m_frame->GetCanvas()->GetView()->Update( marker );
735 
736  // Update view
739  else
741 
743  refreshEditor();
744  m_frame->OnModify();
745  }
746 }
747 
748 
749 void DIALOG_DRC::deleteAllMarkers( bool aIncludeExclusions )
750 {
751  // Clear current selection list to avoid selection of deleted items
753 
754  m_markersTreeModel->DeleteItems( false, aIncludeExclusions, true );
755 }
756 
757 
758 bool DIALOG_DRC::writeReport( const wxString& aFullFileName )
759 {
760  FILE* fp = wxFopen( aFullFileName, wxT( "w" ) );
761 
762  if( fp == NULL )
763  return false;
764 
765  std::map<KIID, EDA_ITEM*> itemMap;
766  m_frame->GetBoard()->FillItemMap( itemMap );
767 
768  EDA_UNITS units = GetUserUnits();
770  int count;
771 
772  fprintf( fp, "** Drc report for %s **\n", TO_UTF8( m_frame->GetBoard()->GetFileName() ) );
773 
774  wxDateTime now = wxDateTime::Now();
775 
776  fprintf( fp, "** Created on %s **\n", TO_UTF8( now.Format( wxT( "%F %T" ) ) ) );
777 
778  count = m_markersProvider->GetCount();
779 
780  fprintf( fp, "\n** Found %d DRC violations **\n", count );
781 
782  for( int i = 0; i < count; ++i )
783  {
784  const std::shared_ptr<RC_ITEM>& item = m_markersProvider->GetItem( i );
785  SEVERITY severity = bds.GetSeverity( item->GetErrorCode() );
786 
787  fprintf( fp, "%s", TO_UTF8( item->ShowReport( units, severity, itemMap ) ) );
788  }
789 
791 
792  fprintf( fp, "\n** Found %d unconnected pads **\n", count );
793 
794  for( int i = 0; i < count; ++i )
795  {
796  const std::shared_ptr<RC_ITEM>& item = m_unconnectedItemsProvider->GetItem( i );
797  SEVERITY severity = bds.GetSeverity( item->GetErrorCode() );
798 
799  fprintf( fp, "%s", TO_UTF8( item->ShowReport( units, severity, itemMap ) ) );
800  }
801 
803 
804  fprintf( fp, "\n** Found %d Footprint errors **\n", count );
805 
806  for( int i = 0; i < count; ++i )
807  {
808  const std::shared_ptr<RC_ITEM>& item = m_footprintWarningsProvider->GetItem( i );
809  SEVERITY severity = bds.GetSeverity( item->GetErrorCode() );
810 
811  fprintf( fp, "%s", TO_UTF8( item->ShowReport( units, severity, itemMap ) ) );
812  }
813 
814 
815  fprintf( fp, "\n** End of Report **\n" );
816 
817  fclose( fp );
818 
819  return true;
820 }
821 
822 
823 void DIALOG_DRC::OnDeleteOneClick( wxCommandEvent& aEvent )
824 {
825  if( m_Notebook->GetSelection() == 0 )
826  {
827  // Clear the selection. It may be the selected DRC marker.
829 
831 
832  // redraw the pcb
833  refreshEditor();
834  }
835  else if( m_Notebook->GetSelection() == 1 )
836  {
838  }
839  else if( m_Notebook->GetSelection() == 2 )
840  {
842  }
843 
845 }
846 
847 
848 void DIALOG_DRC::OnDeleteAllClick( wxCommandEvent& aEvent )
849 {
850  static bool s_includeExclusions = false;
851 
852  int numExcluded = 0;
853 
854  if( m_markersProvider )
856 
859 
862 
863  if( numExcluded > 0 )
864  {
865  wxRichMessageDialog dlg( this, _( "Do you wish to delete excluded markers as well?" ),
866  _( "Delete All Markers" ),
867  wxOK | wxCANCEL | wxCENTER | wxICON_QUESTION );
868  dlg.ShowCheckBox( _( "Delete exclusions" ), s_includeExclusions );
869 
870  int ret = dlg.ShowModal();
871 
872  if( ret == wxID_CANCEL )
873  return;
874  else
875  s_includeExclusions = dlg.IsCheckBoxChecked();
876  }
877 
878  deleteAllMarkers( s_includeExclusions );
879 
880  m_drcRun = false;
881  refreshEditor();
883 }
884 
885 
887 {
888  // Collect counts:
889 
890  int numMarkers = 0;
891  int numUnconnected = 0;
892  int numFootprints = 0;
893 
894  int numErrors = 0;
895  int numWarnings = 0;
896  int numExcluded = 0;
897 
898  if( m_markersProvider )
899  {
900  numMarkers += m_markersProvider->GetCount();
904  }
905 
907  {
908  numUnconnected += m_unconnectedItemsProvider->GetCount();
912  }
913 
915  {
916  numFootprints += m_footprintWarningsProvider->GetCount();
920  }
921 
922  wxString msg;
923 
924  // Update tab headers:
925 
926  if( m_drcRun )
927  {
928  msg.sprintf( m_markersTitleTemplate, numMarkers );
929  m_Notebook->SetPageText( 0, msg );
930 
931  msg.sprintf( m_unconnectedTitleTemplate, numUnconnected );
932  m_Notebook->SetPageText( 1, msg );
933 
934  if( m_footprintTestsRun )
935  msg.sprintf( m_footprintsTitleTemplate, numFootprints );
936  else
937  {
939  msg.Replace( wxT( "%d" ), _( "not run" ) );
940  }
941  m_Notebook->SetPageText( 2, msg );
942  }
943  else
944  {
946  msg.Replace( wxT( "(%d)" ), wxEmptyString );
947  m_Notebook->SetPageText( 0, msg );
948 
950  msg.Replace( wxT( "(%d)" ), wxEmptyString );
951  m_Notebook->SetPageText( 1, msg );
952 
954  msg.Replace( wxT( "(%d)" ), wxEmptyString );
955  m_Notebook->SetPageText( 2, msg );
956  }
957 
958  // Update badges:
959 
960  if( !m_drcRun && numErrors == 0 )
961  numErrors = -1;
962 
963  if( !m_drcRun && numWarnings == 0 )
964  numWarnings = -1;
965 
966  m_errorsBadge->SetMaximumNumber( numErrors );
968 
969  m_warningsBadge->SetMaximumNumber( numWarnings );
971 
972  m_exclusionsBadge->SetMaximumNumber( numExcluded );
974 }
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:813
void initValues()
Definition: dialog_drc.cpp:126
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:252
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:179
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:709
void updateDisplayedCounts()
Definition: dialog_drc.cpp:886
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:414
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:749
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
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
wxSimplebook * m_runningResultsBook
MARKERS & Markers()
Definition: board.h:314
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:758
void UpdateNumber(int aNumber, SEVERITY aSeverity)
Update the number displayed on the badge.
void PrevMarker()
Definition: dialog_drc.cpp:695
void OnDeleteOneClick(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:823
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:593
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:723
RC_ITEMS_PROVIDER * m_markersProvider
Definition: dialog_drc.h:118
void OnDRCItemDClick(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:399
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
virtual int GetCount(int aSeverity=-1) const =0
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
APPEARANCE_CONTROLS * GetAppearancePanel()
const wxString & GetFileName() const
Definition: board.h:300
BOARD * m_currentBoard
Definition: dialog_drc.h:107
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:123
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
This file contains miscellaneous commonly used macros and functions.
Provide an abstract interface of a RC_ITEM* list manager.
Definition: rc_item.h:43
void OnChangingNotebookPage(wxNotebookEvent &aEvent) override
Definition: dialog_drc.cpp:675
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
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:125
#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:848
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
Return a reference to the PROJECT associated with this KIWAY.
DIALOG_DRC(PCB_EDIT_FRAME *aEditorFrame, wxWindow *aParent)
Constructors.
Definition: dialog_drc.cpp:46
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
static LSET AllLayersMask()
Definition: lset.cpp:787
SEVERITY GetSeverity(int aDRCErrorCode)
void OnClose(wxCloseEvent &event) override
Definition: dialog_drc.cpp:645
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:194
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:656
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:124
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
virtual std::shared_ptr< RC_ITEM > GetItem(int aIndex) const =0
Retrieve a RC_ITEM by index.
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
void refreshEditor()
Definition: dialog_drc.cpp:687
#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:111
bool m_drcRun
Definition: dialog_drc.h:111
int m_severities
Definition: dialog_drc.h:127
void SetLayerVisible(LAYER_NUM aLayer, bool isVisible)
void ValueChanged(const RC_TREE_NODE *aNode)
Definition: rc_item.cpp:415
std::atomic_int m_maxProgress
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
RC_TREE_MODEL * m_markersTreeModel
Definition: dialog_drc.h:119
DIALOG_DRC m_DrcDialog
BOARD * GetBoard() const
void DestroyDRCDialog()
Close and free the DRC dialog.
Definition: drc_tool.cpp:119
Definition: pad.h:60
PCB_EDIT_FRAME * m_frame
Definition: dialog_drc.h:108
STATUS_FLAGS GetFlags() const
Definition: eda_item.h:205
void OnSaveReport(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:611
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:154
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:892
void SetUnconnectedProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: dialog_drc.cpp:283
wxString m_unconnectedTitleTemplate
Definition: dialog_drc.h:115
void OnSeverity(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:575
Container for design settings for a BOARD object.