KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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, [email protected]
6 * Copyright (C) 2004-2023 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>
29#include <kiface_base.h>
30#include <macros.h>
31#include <pad.h>
32#include <drc/drc_item.h>
33#include <drc/drc_report.h>
37#include <pcb_edit_frame.h>
38#include <pcbnew_settings.h>
39#include <tool/tool_manager.h>
40#include <tools/pcb_actions.h>
42#include <pcb_marker.h>
43#include <pgm_base.h>
44#include <wx/app.h>
45#include <wx/filedlg.h>
46#include <wx/msgdlg.h>
47#include <wx/wupdlock.h>
49#include <widgets/ui_common.h>
54#include <tools/drc_tool.h>
57#include <kiplatform/ui.h>
58
59// wxWidgets spends *far* too long calcuating column widths (most of it, believe it or
60// not, in repeatedly creating/destroying a wxDC to do the measurement in).
61// Use default column widths instead.
62static int DEFAULT_SINGLE_COL_WIDTH = 660;
63
64static BOARD* g_lastDRCBoard = nullptr;
65static bool g_lastDRCRun = false;
66static bool g_lastFootprintTestsRun = false;
67
68static std::vector<std::pair<wxString, int>> g_lastIgnored;
69
70
71DIALOG_DRC::DIALOG_DRC( PCB_EDIT_FRAME* aEditorFrame, wxWindow* aParent ) :
72 DIALOG_DRC_BASE( aParent ),
74 m_running( false ),
75 m_drcRun( false ),
76 m_footprintTestsRun( false ),
77 m_markersTreeModel( nullptr ),
78 m_unconnectedTreeModel( nullptr ),
79 m_fpWarningsTreeModel( nullptr ),
81 m_lastUpdateUi( std::chrono::steady_clock::now() )
82{
83 SetName( DIALOG_DRC_WINDOW_NAME ); // Set a window name to be able to find it
85
86 m_frame = aEditorFrame;
88
90
93
94 m_markersProvider = std::make_shared<DRC_ITEMS_PROVIDER>( m_currentBoard,
97
98 m_ratsnestProvider = std::make_shared<DRC_ITEMS_PROVIDER>( m_currentBoard,
100
101 m_fpWarningsProvider = std::make_shared<DRC_ITEMS_PROVIDER>( m_currentBoard,
103
105 m_markerDataView->AssociateModel( m_markersTreeModel );
107
111
115
116 m_ignoredList->InsertColumn( 0, wxEmptyString, wxLIST_FORMAT_LEFT, DEFAULT_SINGLE_COL_WIDTH );
117
119 {
122
123 for( const auto& [ str, code ] : g_lastIgnored )
124 {
125 wxListItem listItem;
126 listItem.SetId( m_ignoredList->GetItemCount() );
127 listItem.SetText( str );
128 listItem.SetData( code );
129
130 m_ignoredList->InsertItem( listItem );
131 }
132 }
133
134 m_Notebook->SetSelection( 0 );
135
136 if( Kiface().IsSingle() )
137 m_cbTestFootprints->Hide();
138
139 SetupStandardButtons( { { wxID_OK, _( "Run DRC" ) },
140 { wxID_CANCEL, _( "Close" ) } } );
141
142 m_markersTitleTemplate = m_Notebook->GetPageText( 0 );
143 m_unconnectedTitleTemplate = m_Notebook->GetPageText( 1 );
144 m_footprintsTitleTemplate = m_Notebook->GetPageText( 2 );
145 m_ignoredTitleTemplate = m_Notebook->GetPageText( 3 );
146
147 m_cbRefillZones->SetValue( cfg->m_DrcDialog.refill_zones );
149
150 if( !Kiface().IsSingle() )
152
153 Layout(); // adding the units above expanded Clearance text, now resize.
154
155 SetFocus();
156
158
160}
161
162
164{
165 m_frame->FocusOnItem( nullptr );
166
170
171 g_lastIgnored.clear();
172
173 for( int ii = 0; ii < m_ignoredList->GetItemCount(); ++ii )
174 {
175 g_lastIgnored.push_back( { m_ignoredList->GetItemText( ii ),
176 m_ignoredList->GetItemData( ii ) } );
177 }
178
179 PCBNEW_SETTINGS* cfg = nullptr;
180
181 try
182 {
183 cfg = m_frame->GetPcbNewSettings();
184 }
185 catch( const std::runtime_error& e )
186 {
187 wxFAIL_MSG( e.what() );
188 }
189
190 if( cfg )
191 {
192 cfg->m_DrcDialog.refill_zones = m_cbRefillZones->GetValue();
194
195 if( !Kiface().IsSingle() )
197
199 }
200
201 m_markersTreeModel->DecRef();
202 m_unconnectedTreeModel->DecRef();
203 m_fpWarningsTreeModel->DecRef();
204}
205
206
207void DIALOG_DRC::OnActivateDlg( wxActivateEvent& aEvent )
208{
210 {
211 // If m_currentBoard is not the current board, (for instance because a new board
212 // was loaded), close the dialog, because many pointers are now invalid in lists
213 SetReturnCode( wxID_CANCEL );
214 Close();
215
217 drcTool->DestroyDRCDialog();
218 }
219}
220
221
222// PROGRESS_REPORTER calls
223
225{
226 double cur = alg::clamp( 0.0, (double) m_progress.load() / m_maxProgress, 1.0 );
227
228 int newValue = KiROUND( cur * 1000.0 );
229 m_gauge->SetValue( newValue );
230
231 // There is significant overhead on at least Windows when updateUi is called constantly thousands of times
232 // in the drc process and safeyieldfor is called each time.
233 // Gate the yield to a limited rate which still allows the UI to function without slowing down the main thread
234 // which is also running DRC
235 std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
236 if( std::chrono::duration_cast<std::chrono::milliseconds>( now - m_lastUpdateUi ).count()
237 > 100 )
238 {
239 Pgm().App().SafeYieldFor( this, wxEVT_CATEGORY_NATIVE_EVENTS );
240 m_lastUpdateUi = now;
241 }
242
243 return !m_cancelled;
244}
245
246
247void DIALOG_DRC::AdvancePhase( const wxString& aMessage )
248{
250 SetCurrentProgress( 0.0 );
251
252 m_messages->Report( aMessage );
253}
254
255
256// Don't globally define this; different facilities use different definitions of "ALL"
258
259
261{
266}
267
268
269void DIALOG_DRC::OnErrorLinkClicked( wxHtmlLinkEvent& event )
270{
271 m_frame->ShowBoardSetupDialog( _( "Custom Rules" ) );
272}
273
274
275void DIALOG_DRC::OnRunDRCClick( wxCommandEvent& aEvent )
276{
277 TOOL_MANAGER* toolMgr = m_frame->GetToolManager();
278 DRC_TOOL* drcTool = toolMgr->GetTool<DRC_TOOL>();
279 ZONE_FILLER_TOOL* zoneFillerTool = toolMgr->GetTool<ZONE_FILLER_TOOL>();
280 bool refillZones = m_cbRefillZones->GetValue();
281 bool reportAllTrackErrors = m_cbReportAllTrackErrors->GetValue();
282 bool testFootprints = m_cbTestFootprints->GetValue();
283
284 if( zoneFillerTool->IsBusy() )
285 {
286 wxBell();
287 return;
288 }
289
290 // This is not the time to have stale or buggy rules. Ensure they're up-to-date
291 // and that they at least parse.
292 try
293 {
294 drcTool->GetDRCEngine()->InitEngine( m_frame->GetDesignRulesPath() );
295 }
296 catch( PARSE_ERROR& )
297 {
298 m_runningResultsBook->ChangeSelection( 0 ); // Display the "Tests Running..." tab
299 m_DeleteCurrentMarkerButton->Enable( false );
300 m_DeleteAllMarkersButton->Enable( false );
301 m_saveReport->Enable( false );
302
303 m_messages->Clear();
304 m_messages->Report( _( "DRC incomplete: could not compile custom design rules." )
305 + wxS( "&nbsp;&nbsp;" )
306 + wxS( "<a href='$CUSTOM_RULES'>" ) + _( "Show design rules." ) + wxT( "</a>" ) );
307 m_messages->Flush();
308
309 Raise();
310
311 // set float level again, it can be lost due to window events during test run
313 return;
314 }
315
316 m_footprintTestsRun = false;
317 m_cancelled = false;
318
320 deleteAllMarkers( true );
321
322 std::vector<std::reference_wrapper<RC_ITEM>> violations = DRC_ITEM::GetItemsWithSeverities();
323 m_ignoredList->DeleteAllItems();
324
325 for( std::reference_wrapper<RC_ITEM>& item : violations )
326 {
327 if( bds().GetSeverity( item.get().GetErrorCode() ) == RPT_SEVERITY_IGNORE )
328 {
329 wxListItem listItem;
330 listItem.SetId( m_ignoredList->GetItemCount() );
331 listItem.SetText( wxT( " • " ) + item.get().GetErrorText() );
332 listItem.SetData( item.get().GetErrorCode() );
333
334 m_ignoredList->InsertItem( listItem );
335 }
336 }
337
338 m_ignoredList->SetColumnWidth( 0, m_ignoredList->GetParent()->GetClientSize().x - 20 );
339
340 Raise();
341
342 m_runningResultsBook->ChangeSelection( 0 ); // Display the "Tests Running..." tab
343 m_messages->Clear();
344 wxYield(); // Allow time slice to refresh Messages
345
346 m_running = true;
347 m_sdbSizerCancel->SetLabel( _( "Cancel" ) );
348 m_sdbSizerOK->Enable( false );
349 m_DeleteCurrentMarkerButton->Enable( false );
350 m_DeleteAllMarkersButton->Enable( false );
351 m_saveReport->Enable( false );
352
353 {
354 wxBusyCursor dummy;
355 drcTool->RunTests( this, refillZones, reportAllTrackErrors, testFootprints );
356 }
357
358 if( m_cancelled )
359 m_messages->Report( _( "-------- DRC cancelled by user.<br><br>" ) );
360 else
361 m_messages->Report( _( "Done.<br><br>" ) );
362
363 Raise();
364 wxYield(); // Allow time slice to refresh Messages
365
366 m_running = false;
367 m_sdbSizerCancel->SetLabel( _( "Close" ) );
368 m_sdbSizerOK->Enable( true );
369 m_DeleteCurrentMarkerButton->Enable( true );
370 m_DeleteAllMarkersButton->Enable( true );
371 m_saveReport->Enable( true );
372
373 if( !m_cancelled )
374 {
375 m_sdbSizerCancel->SetDefault();
376 // wxWidgets has a tendency to keep both buttons highlighted without the following:
377 m_sdbSizerOK->Enable( false );
378
379 wxMilliSleep( 500 );
380 m_runningResultsBook->ChangeSelection( 1 );
382
383 // now re-enable m_sdbSizerOK button
384 m_sdbSizerOK->Enable( true );
385 }
386
387 // set float level again, it can be lost due to window events during test run
390}
391
392
394{
398
400}
401
402
403void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
404{
405 BOARD* board = m_frame->GetBoard();
406 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
407
408 auto getActiveLayers =
409 []( BOARD_ITEM* aItem ) -> LSET
410 {
411 if( aItem->Type() == PCB_PAD_T )
412 {
413 PAD* pad = static_cast<PAD*>( aItem );
414 LSET layers;
415
416 for( int layer : aItem->GetLayerSet().Seq() )
417 {
418 if( pad->FlashLayer( layer ) )
419 layers.set( layer );
420 }
421
422 return layers;
423 }
424 else
425 {
426 return aItem->GetLayerSet();
427 }
428 };
429
430 if( !node )
431 {
432 // list is being freed; don't do anything with null ptrs
433
434 aEvent.Skip();
435 return;
436 }
437
438 std::shared_ptr<RC_ITEM> rc_item = node->m_RcItem;
439
440 if( rc_item->GetErrorCode() == DRCE_UNRESOLVED_VARIABLE
441 && rc_item->GetParent()->GetMarkerType() == MARKER_BASE::MARKER_DRAWING_SHEET )
442 {
443 m_frame->FocusOnLocation( node->m_RcItem->GetParent()->GetPos() );
444
445 aEvent.Skip();
446 return;
447 }
448
449 const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
450 BOARD_ITEM* item = board->GetItem( itemID );
451
452 if( !item || item == DELETED_BOARD_ITEM::GetInstance() )
453 {
454 // nothing to highlight / focus on
455
456 aEvent.Skip();
457 return;
458 }
459
460 PCB_LAYER_ID principalLayer;
461 LSET violationLayers;
462 BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
463 BOARD_ITEM* b = board->GetItem( rc_item->GetAuxItemID() );
464 BOARD_ITEM* c = board->GetItem( rc_item->GetAuxItem2ID() );
465 BOARD_ITEM* d = board->GetItem( rc_item->GetAuxItem3ID() );
466
467 if( rc_item->GetErrorCode() == DRCE_MALFORMED_COURTYARD )
468 {
469 if( a && ( a->GetFlags() & MALFORMED_B_COURTYARD ) > 0
470 && ( a->GetFlags() & MALFORMED_F_COURTYARD ) == 0 )
471 {
472 principalLayer = B_CrtYd;
473 }
474 else
475 {
476 principalLayer = F_CrtYd;
477 }
478 }
479 else if (rc_item->GetErrorCode() == DRCE_INVALID_OUTLINE )
480 {
481 principalLayer = Edge_Cuts;
482 }
483 else
484 {
485 principalLayer = UNDEFINED_LAYER;
486
487 if( a || b || c || d )
488 violationLayers = LSET::AllLayersMask();
489
490 // Try to initialize principalLayer to a valid layer. Note that some markers have
491 // a layer set to UNDEFINED_LAYER, so we may need to keep looking.
492
493 for( BOARD_ITEM* it: { a, b, c, d } )
494 {
495 if( !it )
496 continue;
497
498 LSET layersList = getActiveLayers( it );
499 violationLayers &= layersList;
500
501 if( principalLayer <= UNDEFINED_LAYER && layersList.count() )
502 principalLayer = layersList.Seq().front();
503 }
504 }
505
506 if( violationLayers.count() )
507 principalLayer = violationLayers.Seq().front();
508 else if( !(principalLayer <= UNDEFINED_LAYER ) )
509 violationLayers.set( principalLayer );
510
511 WINDOW_THAWER thawer( m_frame );
512
513 if( principalLayer > UNDEFINED_LAYER && ( violationLayers & board->GetVisibleLayers() ) == 0 )
514 m_frame->GetAppearancePanel()->SetLayerVisible( principalLayer, true );
515
516 if( principalLayer > UNDEFINED_LAYER && board->GetVisibleLayers().test( principalLayer ) )
517 m_frame->SetActiveLayer( principalLayer );
518
519 if( rc_item->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
520 {
523
524 if( item->Type() == PCB_ZONE_T )
525 {
526 m_frame->FocusOnItem( item, principalLayer );
527
528 m_frame->GetBoard()->GetConnectivity()->RunOnUnconnectedEdges(
529 [&]( CN_EDGE& edge )
530 {
531 // Connectivity was valid when DRC was run, but this is a modeless dialog
532 // so it might not be now.
533 if( !edge.GetSourceNode() || edge.GetSourceNode()->Dirty() )
534 return true;
535
536 if( !edge.GetTargetNode() || edge.GetTargetNode()->Dirty() )
537 return true;
538
539 if( edge.GetSourceNode()->Parent() == a
540 && edge.GetTargetNode()->Parent() == b )
541 {
542 VECTOR2I focusPos;
543
544 if( item == a && item == b )
545 {
546 focusPos = ( node->m_Type == RC_TREE_NODE::MAIN_ITEM )
547 ? edge.GetSourcePos()
548 : edge.GetTargetPos();
549 }
550 else
551 {
552 focusPos = ( item == edge.GetSourceNode()->Parent() )
553 ? edge.GetSourcePos()
554 : edge.GetTargetPos();
555 }
556
557 m_frame->FocusOnLocation( focusPos );
559
560 return false;
561 }
562
563 return true;
564 } );
565 }
566 else
567 {
568 m_frame->FocusOnItem( item, principalLayer );
569 }
570 }
571 else if( rc_item->GetErrorCode() == DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG )
572 {
573 BOARD_CONNECTED_ITEM* track = dynamic_cast<PCB_TRACK*>( item );
574 std::vector<BOARD_ITEM*> items;
575
576 if( track )
577 {
578 int net = track->GetNetCode();
579
580 wxASSERT( net > 0 ); // Without a net how can it be a diff-pair?
581
582 for( const KIID& id : rc_item->GetIDs() )
583 {
584 auto* candidate = dynamic_cast<BOARD_CONNECTED_ITEM*>( board->GetItem( id ) );
585
586 if( candidate && candidate->GetNetCode() == net )
587 items.push_back( candidate );
588 }
589 }
590 else
591 {
592 items.push_back( item );
593 }
594
595 m_frame->FocusOnItems( items, principalLayer );
596 }
597 else
598 {
599 m_frame->FocusOnItem( item, principalLayer );
600 }
601
602 aEvent.Skip();
603}
604
605
606void DIALOG_DRC::OnDRCItemDClick( wxDataViewEvent& aEvent )
607{
608 if( aEvent.GetItem().IsOk() )
609 {
610 // turn control over to m_frame, hide this DIALOG_DRC window,
611 // no destruction so we can preserve listbox cursor
612 if( !IsModal() )
613 Show( false );
614 }
615
616 // Do not skip aEvent here: this is not useful, and Pcbnew crashes
617 // if skipped (at least on Windows)
618}
619
620
621void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
622{
623 TOOL_MANAGER* toolMgr = m_frame->GetToolManager();
624 BOARD_INSPECTION_TOOL* inspectionTool = toolMgr->GetTool<BOARD_INSPECTION_TOOL>();
625 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
626
627 if( !node )
628 return;
629
630 std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
631 DRC_ITEM* drcItem = static_cast<DRC_ITEM*>( rcItem.get() );
632 std::shared_ptr<CONNECTIVITY_DATA> conn = m_currentBoard->GetConnectivity();
633 wxString listName;
634 wxMenu menu;
635
636 switch( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] )
637 {
638 case RPT_SEVERITY_ERROR: listName = _( "errors" ); break;
639 case RPT_SEVERITY_WARNING: listName = _( "warnings" ); break;
640 default: listName = _( "appropriate" ); break;
641 }
642
643 enum MENU_IDS
644 {
645 ID_EDIT_EXCLUSION_COMMENT = 4467,
646 ID_REMOVE_EXCLUSION,
647 ID_REMOVE_EXCLUSION_ALL,
648 ID_ADD_EXCLUSION,
649 ID_ADD_EXCLUSION_ALL,
650 ID_INSPECT_VIOLATION,
651 ID_SET_SEVERITY_TO_ERROR,
652 ID_SET_SEVERITY_TO_WARNING,
653 ID_SET_SEVERITY_TO_IGNORE,
654 ID_EDIT_SEVERITIES
655 };
656
657 if( rcItem->GetParent()->IsExcluded() )
658 {
659 menu.Append( ID_EDIT_EXCLUSION_COMMENT,
660 _( "Edit exclusion comment..." ) );
661
662 menu.Append( ID_REMOVE_EXCLUSION,
663 _( "Remove exclusion for this violation" ),
664 wxString::Format( _( "It will be placed back in the %s list" ), listName ) );
665
666 if( drcItem->GetViolatingRule() && !drcItem->GetViolatingRule()->m_Implicit )
667 {
668 menu.Append( ID_REMOVE_EXCLUSION_ALL,
669 wxString::Format( _( "Remove all exclusions for violations of rule '%s'" ),
670 drcItem->GetViolatingRule()->m_Name ),
671 wxString::Format( _( "They will be placed back in the %s list" ), listName ) );
672 }
673 }
674 else
675 {
676 menu.Append( ID_ADD_EXCLUSION,
677 _( "Exclude this violation..." ),
678 wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
679
680 if( drcItem->GetViolatingRule() && !drcItem->GetViolatingRule()->m_Implicit )
681 {
682 menu.Append( ID_ADD_EXCLUSION_ALL,
683 wxString::Format( _( "Exclude all violations of rule '%s'..." ),
684 drcItem->GetViolatingRule()->m_Name ),
685 wxString::Format( _( "They will be excluded from the %s list" ), listName ) );
686 }
687 }
688
689 wxString inspectDRCErrorMenuText = inspectionTool->InspectDRCErrorMenuText( rcItem );
690
691 if( !inspectDRCErrorMenuText.IsEmpty() )
692 menu.Append( ID_INSPECT_VIOLATION, inspectDRCErrorMenuText );
693
694 menu.AppendSeparator();
695
696 if( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] == RPT_SEVERITY_WARNING )
697 {
698 menu.Append( ID_SET_SEVERITY_TO_ERROR,
699 wxString::Format( _( "Change severity to Error for all '%s' violations" ),
700 rcItem->GetErrorText() ),
701 _( "Violation severities can also be edited in the Board Setup... dialog" ) );
702 }
703 else
704 {
705 menu.Append( ID_SET_SEVERITY_TO_WARNING,
706 wxString::Format( _( "Change severity to Warning for all '%s' violations" ),
707 rcItem->GetErrorText() ),
708 _( "Violation severities can also be edited in the Board Setup... dialog" ) );
709 }
710
711 menu.Append( ID_SET_SEVERITY_TO_IGNORE,
712 wxString::Format( _( "Ignore all '%s' violations" ), rcItem->GetErrorText() ),
713 _( "Violations will not be checked or reported" ) );
714
715 menu.AppendSeparator();
716
717 menu.Append( ID_EDIT_SEVERITIES,
718 _( "Edit violation severities..." ),
719 _( "Open the Board Setup... dialog" ) );
720
721 bool modified = false;
722
723 switch( GetPopupMenuSelectionFromUser( menu ) )
724 {
725 case ID_EDIT_EXCLUSION_COMMENT:
726 if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() ) )
727 {
728 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Optional comment:" ), _( "Exclusion Comment" ),
729 marker->GetComment(), true );
730
731 if( dlg.ShowModal() == wxID_CANCEL )
732 break;
733
734 marker->SetExcluded( true, dlg.GetValue() );
735
736 wxString serialized = marker->SerializeToString();
737 m_frame->GetDesignSettings().m_DrcExclusions.insert( serialized );
739
740 // Update view
741 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
742 modified = true;
743 }
744
745 break;
746
747 case ID_REMOVE_EXCLUSION:
748 if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( rcItem->GetParent() ) )
749 {
750 marker->SetExcluded( false );
751
752 wxString serialized = marker->SerializeToString();
753 m_frame->GetDesignSettings().m_DrcExclusions.erase( serialized );
754 m_frame->GetDesignSettings().m_DrcExclusionComments.erase( serialized );
755
756 if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
757 {
760 }
761 else
762 {
763 m_frame->GetCanvas()->GetView()->Update( marker );
764 }
765
766 // Update view
767 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
768 modified = true;
769 }
770
771 break;
772
773 case ID_ADD_EXCLUSION:
774 if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( rcItem->GetParent() ) )
775 {
776 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Optional comment:" ), _( "Exclusion Comment" ),
777 wxEmptyString, true );
778
779 if( dlg.ShowModal() == wxID_CANCEL )
780 break;
781
782 marker->SetExcluded( true, dlg.GetValue() );
783
784 wxString serialized = marker->SerializeToString();
785 m_frame->GetDesignSettings().m_DrcExclusions.insert( serialized );
787
788 if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
789 {
792 }
793 else
794 {
795 m_frame->GetCanvas()->GetView()->Update( marker );
796 }
797
798 // Update view
800 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
801 else
802 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->DeleteCurrentItem( false );
803
804 modified = true;
805 }
806
807 break;
808
809 case ID_REMOVE_EXCLUSION_ALL:
810 for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
811 {
812 DRC_ITEM* candidateDrcItem = static_cast<DRC_ITEM*>( marker->GetRCItem().get() );
813
814 if( candidateDrcItem->GetViolatingRule() == drcItem->GetViolatingRule() )
815 {
816 marker->SetExcluded( false );
817
818 wxString serialized = marker->SerializeToString();
819 m_frame->GetDesignSettings().m_DrcExclusions.erase( serialized );
820 m_frame->GetDesignSettings().m_DrcExclusionComments.erase( serialized );
821 }
822 }
823
824 // Rebuild model and view
825 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markersProvider, m_severities );
826 modified = true;
827 break;
828
829 case ID_ADD_EXCLUSION_ALL:
830 for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
831 {
832 DRC_ITEM* candidateDrcItem = static_cast<DRC_ITEM*>( marker->GetRCItem().get() );
833
834 if( candidateDrcItem->GetViolatingRule() == drcItem->GetViolatingRule() )
835 {
836 marker->SetExcluded( true );
837
838 wxString serialized = marker->SerializeToString();
839 m_frame->GetDesignSettings().m_DrcExclusions.insert( serialized );
840 }
841 }
842
843 // Rebuild model and view
844 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markersProvider, m_severities );
845 modified = true;
846 break;
847
848 case ID_INSPECT_VIOLATION:
849 inspectionTool->InspectDRCError( node->m_RcItem );
850 break;
851
852 case ID_SET_SEVERITY_TO_ERROR:
853 bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_ERROR;
854
855 for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
856 {
857 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
858 m_frame->GetCanvas()->GetView()->Update( marker );
859 }
860
861 // Rebuild model and view
862 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markersProvider, m_severities );
863 modified = true;
864 break;
865
866 case ID_SET_SEVERITY_TO_WARNING:
867 bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_WARNING;
868
869 for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
870 {
871 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
872 m_frame->GetCanvas()->GetView()->Update( marker );
873 }
874
875 // Rebuild model and view
876 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markersProvider, m_severities );
877 modified = true;
878 break;
879
880 case ID_SET_SEVERITY_TO_IGNORE:
881 {
882 bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_IGNORE;
883
884 wxListItem listItem;
885 listItem.SetId( m_ignoredList->GetItemCount() );
886 listItem.SetText( wxT( " • " ) + rcItem->GetErrorText() );
887 listItem.SetData( rcItem->GetErrorCode() );
888
889 m_ignoredList->InsertItem( listItem );
890
891 BOARD* board = m_frame->GetBoard();
892
893 std::vector<BOARD_ITEM*> toRemove;
894
895 for( PCB_MARKER* marker : board->Markers() )
896 {
897 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
898 {
899 m_frame->GetCanvas()->GetView()->Remove( marker );
900 toRemove.emplace_back( marker );
901 }
902 }
903
904 for( BOARD_ITEM* marker : toRemove )
905 board->Remove( marker, REMOVE_MODE::BULK );
906
907 board->FinalizeBulkRemove( toRemove );
908
909 if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
911
912 // Rebuild model and view
913 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markersProvider, m_severities );
914 modified = true;
915 break;
916 }
917
918 case ID_EDIT_SEVERITIES:
919 m_frame->ShowBoardSetupDialog( _( "Violation Severity" ) );
920 break;
921 }
922
923 if( modified )
924 {
927 m_frame->OnModify();
928 }
929}
930
931
932void DIALOG_DRC::OnIgnoredItemRClick( wxListEvent& event )
933{
934 int errorCode = (int) event.m_item.GetData();
935 wxMenu menu;
936
937 menu.Append( RPT_SEVERITY_ERROR, _( "Error" ), wxEmptyString, wxITEM_CHECK );
938 menu.Append( RPT_SEVERITY_WARNING, _( "Warning" ), wxEmptyString, wxITEM_CHECK );
939 menu.Append( RPT_SEVERITY_IGNORE, _( "Ignore" ), wxEmptyString, wxITEM_CHECK );
940
941 menu.Check( bds().GetSeverity( errorCode ), true );
942
943 int severity = GetPopupMenuSelectionFromUser( menu );
944
945 if( severity > 0 )
946 {
947 if( bds().m_DRCSeverities[ errorCode ] != severity )
948 {
949 bds().m_DRCSeverities[ errorCode ] = (SEVERITY) severity;
950
953 m_frame->OnModify();
954 }
955 }
956}
957
958
959void DIALOG_DRC::OnEditViolationSeverities( wxHyperlinkEvent& aEvent )
960{
961 m_frame->ShowBoardSetupDialog( _( "Violation Severity" ) );
962}
963
964
965void DIALOG_DRC::OnSeverity( wxCommandEvent& aEvent )
966{
967 int flag = 0;
968
969 if( aEvent.GetEventObject() == m_showAll )
971 else if( aEvent.GetEventObject() == m_showErrors )
973 else if( aEvent.GetEventObject() == m_showWarnings )
975 else if( aEvent.GetEventObject() == m_showExclusions )
977
978 if( aEvent.IsChecked() )
980 else if( aEvent.GetEventObject() == m_showAll )
982 else
983 m_severities &= ~flag;
984
986 UpdateData();
987}
988
989
990void DIALOG_DRC::OnSaveReport( wxCommandEvent& aEvent )
991{
992 wxFileName fn( "DRC." + FILEEXT::ReportFileExtension );
993
994 wxFileDialog dlg( this, _( "Save Report File" ), Prj().GetProjectPath(), fn.GetFullName(),
996 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
997
998 if( dlg.ShowModal() != wxID_OK )
999 return;
1000
1001 fn = dlg.GetPath();
1002
1003 if( fn.GetExt().IsEmpty() )
1004 fn.SetExt( FILEEXT::ReportFileExtension );
1005
1006 if( !fn.IsAbsolute() )
1007 {
1008 wxString prj_path = Prj().GetProjectPath();
1009 fn.MakeAbsolute( prj_path );
1010 }
1011
1014
1015 bool success = false;
1016 if( fn.GetExt() == FILEEXT::JsonFileExtension )
1017 success = reportWriter.WriteJsonReport( fn.GetFullPath() );
1018 else
1019 success = reportWriter.WriteTextReport( fn.GetFullPath() );
1020
1021 if( success )
1022 {
1023 m_messages->Report( wxString::Format( _( "Report file '%s' created<br>" ),
1024 fn.GetFullPath() ) );
1025 }
1026 else
1027 {
1028 DisplayError( this, wxString::Format( _( "Failed to create file '%s'." ),
1029 fn.GetFullPath() ) );
1030 }
1031}
1032
1033
1034void DIALOG_DRC::OnClose( wxCloseEvent& aEvent )
1035{
1036 if( m_running )
1037 aEvent.Veto();
1038
1039 wxCommandEvent dummy;
1040
1042}
1043
1044
1045void DIALOG_DRC::OnCancelClick( wxCommandEvent& aEvent )
1046{
1047 if( m_running )
1048 {
1049 m_cancelled = true;
1050 return;
1051 }
1052
1053 m_frame->FocusOnItem( nullptr );
1054
1055 SetReturnCode( wxID_CANCEL );
1056
1057 // The dialog can be modal or not modal.
1058 // Leave the DRC caller destroy (or not) the dialog
1060 drcTool->DestroyDRCDialog();
1061}
1062
1063
1064void DIALOG_DRC::OnChangingNotebookPage( wxNotebookEvent& aEvent )
1065{
1066 m_markerDataView->UnselectAll();
1067 m_unconnectedDataView->UnselectAll();
1068 m_footprintsDataView->UnselectAll();
1069
1070 aEvent.Skip();
1071}
1072
1073
1075{
1076 WINDOW_THAWER thawer( m_frame );
1077
1079}
1080
1081
1083{
1084 if( m_Notebook->IsShown() )
1085 {
1086 switch( m_Notebook->GetSelection() )
1087 {
1088 case 0: m_markersTreeModel->PrevMarker(); break;
1089 case 1: m_unconnectedTreeModel->PrevMarker(); break;
1090 case 2: m_fpWarningsTreeModel->PrevMarker(); break;
1091 case 3: break;
1092 }
1093 }
1094}
1095
1096
1098{
1099 if( m_Notebook->IsShown() )
1100 {
1101 switch( m_Notebook->GetSelection() )
1102 {
1103 case 0: m_markersTreeModel->NextMarker(); break;
1104 case 1: m_unconnectedTreeModel->NextMarker(); break;
1105 case 2: m_fpWarningsTreeModel->NextMarker(); break;
1106 case 3: break;
1107 }
1108 }
1109}
1110
1111
1113{
1114 if( m_Notebook->IsShown() )
1115 {
1116 m_Notebook->SetSelection( 0 );
1117 m_markersTreeModel->SelectMarker( aMarker );
1118
1119 CallAfter(
1120 [this, aMarker]
1121 {
1122 m_markersTreeModel->CenterMarker( aMarker );
1123 } );
1124 }
1125}
1126
1127
1129{
1130 if( !m_Notebook->IsShown() || m_Notebook->GetSelection() != 0 )
1131 return;
1132
1133 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( m_markerDataView->GetCurrentItem() );
1134 PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
1135
1136 if( marker && marker->GetSeverity() != RPT_SEVERITY_EXCLUSION )
1137 {
1138 marker->SetExcluded( true );
1140 m_frame->GetCanvas()->GetView()->Update( marker );
1141
1142 // Update view
1145 else
1147
1149 refreshEditor();
1150 m_frame->OnModify();
1151 }
1152}
1153
1154
1155void DIALOG_DRC::deleteAllMarkers( bool aIncludeExclusions )
1156{
1157 // Clear current selection list to avoid selection of deleted items
1159
1160 m_markersTreeModel->DeleteItems( false, aIncludeExclusions, false );
1161 m_unconnectedTreeModel->DeleteItems( false, aIncludeExclusions, false );
1162 m_fpWarningsTreeModel->DeleteItems( false, aIncludeExclusions, false );
1163
1164 m_frame->GetBoard()->DeleteMARKERs( true, aIncludeExclusions );
1165}
1166
1167
1168void DIALOG_DRC::OnDeleteOneClick( wxCommandEvent& aEvent )
1169{
1170 if( m_Notebook->GetSelection() == 0 )
1171 {
1172 // Clear the selection. It may be the selected DRC marker.
1174
1176
1177 // redraw the pcb
1178 refreshEditor();
1179 }
1180 else if( m_Notebook->GetSelection() == 1 )
1181 {
1183 }
1184 else if( m_Notebook->GetSelection() == 2 )
1185 {
1187 }
1188
1190}
1191
1192
1193void DIALOG_DRC::OnDeleteAllClick( wxCommandEvent& aEvent )
1194{
1195 static bool s_includeExclusions = false;
1196
1197 int numExcluded = 0;
1198
1199 if( m_markersProvider )
1200 numExcluded += m_markersProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1201
1202 if( m_ratsnestProvider )
1203 numExcluded += m_ratsnestProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1204
1206 numExcluded += m_fpWarningsProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1207
1208 if( numExcluded > 0 )
1209 {
1210 wxMessageDialog dlg( this, _( "Delete exclusions too?" ), _( "Delete All Markers" ),
1211 wxYES_NO | wxCANCEL | wxCENTER | wxICON_QUESTION );
1212 dlg.SetYesNoLabels( _( "Errors and Warnings Only" ),
1213 _( "Errors, Warnings and Exclusions" ) );
1214
1215 int ret = dlg.ShowModal();
1216
1217 if( ret == wxID_CANCEL )
1218 return;
1219 else if( ret == wxID_NO )
1220 s_includeExclusions = true;
1221 }
1222
1223 deleteAllMarkers( s_includeExclusions );
1224
1225 refreshEditor();
1227}
1228
1229
1231{
1234 DRC_ENGINE* drcEngine = drcTool->GetDRCEngine().get();
1235
1236 // Collect counts:
1237
1238 int numMarkers = 0;
1239 int numUnconnected = 0;
1240 int numFootprints = 0;
1241
1242 int numErrors = 0;
1243 int numWarnings = 0;
1244 int numExcluded = 0;
1245
1246 if( m_markersProvider )
1247 {
1248 numMarkers += m_markersProvider->GetCount();
1249 numErrors += m_markersProvider->GetCount( RPT_SEVERITY_ERROR );
1250 numWarnings += m_markersProvider->GetCount( RPT_SEVERITY_WARNING );
1251 numExcluded += m_markersProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1252 }
1253
1254 if( m_ratsnestProvider )
1255 {
1256 numUnconnected += m_ratsnestProvider->GetCount();
1257 numErrors += m_ratsnestProvider->GetCount( RPT_SEVERITY_ERROR );
1258 numWarnings += m_ratsnestProvider->GetCount( RPT_SEVERITY_WARNING );
1259 numExcluded += m_ratsnestProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1260 }
1261
1263 {
1264 numFootprints += m_fpWarningsProvider->GetCount();
1265 numErrors += m_fpWarningsProvider->GetCount( RPT_SEVERITY_ERROR );
1266 numWarnings += m_fpWarningsProvider->GetCount( RPT_SEVERITY_WARNING );
1267 numExcluded += m_fpWarningsProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1268 }
1269
1270 bool showErrors = m_showErrors->GetValue();
1271 bool showWarnings = m_showWarnings->GetValue();
1272 bool errorsOverflowed = false;
1273 bool warningsOverflowed = false;
1274 bool markersOverflowed = false;
1275 bool unconnectedOverflowed = false;
1276 bool footprintsOverflowed = false;
1277
1278 for( int ii = DRCE_FIRST; ii < DRCE_LAST; ++ii )
1279 {
1280 if( drcEngine->IsErrorLimitExceeded( ii ) )
1281 {
1282 if( bds.GetSeverity( ii ) == RPT_SEVERITY_ERROR )
1283 errorsOverflowed = true;
1284 else if( bds.GetSeverity( ii ) == RPT_SEVERITY_WARNING )
1285 warningsOverflowed = true;
1286
1287 if( ii == DRCE_UNCONNECTED_ITEMS )
1288 {
1289 if( showWarnings && bds.GetSeverity( ii ) == RPT_SEVERITY_WARNING )
1290 unconnectedOverflowed = true;
1291 else if( showErrors && bds.GetSeverity( ii ) == RPT_SEVERITY_ERROR )
1292 unconnectedOverflowed = true;
1293 }
1294 else if( ii == DRCE_MISSING_FOOTPRINT
1296 || ii == DRCE_EXTRA_FOOTPRINT
1297 || ii == DRCE_NET_CONFLICT
1299 {
1300 if( showWarnings && bds.GetSeverity( ii ) == RPT_SEVERITY_WARNING )
1301 footprintsOverflowed = true;
1302 else if( showErrors && bds.GetSeverity( ii ) == RPT_SEVERITY_ERROR )
1303 footprintsOverflowed = true;
1304 }
1305 else
1306 {
1307 if( showWarnings && bds.GetSeverity( ii ) == RPT_SEVERITY_WARNING )
1308 markersOverflowed = true;
1309 else if( showErrors && bds.GetSeverity( ii ) == RPT_SEVERITY_ERROR )
1310 markersOverflowed = true;
1311 }
1312 }
1313 }
1314
1315 wxString msg;
1316 wxString num;
1317
1318 // Update tab headers:
1319
1320 if( m_drcRun )
1321 {
1322 num.Printf( markersOverflowed ? wxT( "%d+" ) : wxT( "%d" ), numMarkers );
1323 msg.Printf( m_markersTitleTemplate, num );
1324 }
1325 else
1326 {
1328 msg.Replace( wxT( "(%s)" ), wxEmptyString );
1329 }
1330
1331 m_Notebook->SetPageText( 0, msg );
1332
1333 if( m_drcRun )
1334 {
1335 num.Printf( unconnectedOverflowed ? wxT( "%d+" ) : wxT( "%d" ), numUnconnected );
1336 msg.sprintf( m_unconnectedTitleTemplate, num );
1337 }
1338 else
1339 {
1341 msg.Replace( wxT( "(%s)" ), wxEmptyString );
1342 }
1343
1344 m_Notebook->SetPageText( 1, msg );
1345
1347 {
1348 num.Printf( footprintsOverflowed ? wxT( "%d+" ) : wxT( "%d" ), numFootprints );
1349 msg.sprintf( m_footprintsTitleTemplate, num );
1350 }
1351 else if( m_drcRun )
1352 {
1354 msg.Replace( wxT( "%s" ), _( "not run" ) );
1355 }
1356 else
1357 {
1359 msg.Replace( wxT( "(%s)" ), wxEmptyString );
1360 }
1361
1362 m_Notebook->SetPageText( 2, msg );
1363
1364 if( m_drcRun )
1365 {
1366 num.Printf( wxT( "%d" ), m_ignoredList->GetItemCount() );
1367 msg.sprintf( m_ignoredTitleTemplate, num );
1368 }
1369 else
1370 {
1372 msg.Replace( wxT( "(%s)" ), wxEmptyString );
1373 }
1374
1375 m_Notebook->SetPageText( 3, msg );
1376
1377 // Update badges:
1378
1379 if( !m_drcRun && numErrors == 0 )
1380 numErrors = -1;
1381
1382 if( !m_drcRun && numWarnings == 0 )
1383 numWarnings = -1;
1384
1385 m_errorsBadge->SetMaximumNumber( numErrors );
1386 m_errorsBadge->UpdateNumber( errorsOverflowed ? numErrors + 1 : numErrors,
1388
1389 m_warningsBadge->SetMaximumNumber( numWarnings );
1390 m_warningsBadge->UpdateNumber( warningsOverflowed ? numWarnings + 1 : numWarnings,
1392
1393 m_exclusionsBadge->SetMaximumNumber( numExcluded );
1395}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
void SetLayerVisible(int aLayer, bool isVisible)
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
Container for design settings for a BOARD object.
std::map< wxString, wxString > m_DrcExclusionComments
std::map< int, SEVERITY > m_DRCSeverities
std::set< wxString > m_DrcExclusions
SEVERITY GetSeverity(int aDRCErrorCode)
Tool for pcb inspection.
void InspectDRCError(const std::shared_ptr< RC_ITEM > &aDRCItem)
Show the clearance resolution for two selected items.
wxString InspectDRCErrorMenuText(const std::shared_ptr< RC_ITEM > &aDRCItem)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:77
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:282
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:691
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:1290
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: board.cpp:317
const MARKERS & Markers() const
Definition: board.h:331
void FinalizeBulkRemove(std::vector< BOARD_ITEM * > &aRemovedItems)
Must be used if Remove() is used using a BULK_x REMOVE_MODE to generate a change event for listeners.
Definition: board.cpp:1014
void UpdateRatsnestExclusions()
Update the visibility flags on the current unconnected ratsnest lines.
Definition: board.cpp:286
void DeleteMARKERs()
Delete all MARKERS from the board.
Definition: board.cpp:1239
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: board.cpp:1020
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:460
CN_EDGE represents a point-to-point connection, whether realized or unrealized (ie: tracks etc.
std::shared_ptr< const CN_ANCHOR > GetSourceNode() const
std::shared_ptr< const CN_ANCHOR > GetTargetNode() const
static DELETED_BOARD_ITEM * GetInstance()
Definition: board_item.h:432
Class DIALOG_DRC_BASE.
wxCheckBox * m_cbRefillZones
wxCheckBox * m_showAll
wxButton * m_DeleteAllMarkersButton
wxCheckBox * m_showExclusions
wxNotebook * m_Notebook
wxCheckBox * m_showErrors
wxDataViewCtrl * m_unconnectedDataView
wxDataViewCtrl * m_footprintsDataView
NUMBER_BADGE * m_warningsBadge
wxCheckBox * m_cbReportAllTrackErrors
NUMBER_BADGE * m_exclusionsBadge
wxSimplebook * m_runningResultsBook
wxButton * m_DeleteCurrentMarkerButton
wxButton * m_sdbSizerCancel
wxButton * m_saveReport
wxCheckBox * m_cbTestFootprints
wxCheckBox * m_showWarnings
wxButton * m_sdbSizerOK
wxListCtrl * m_ignoredList
NUMBER_BADGE * m_errorsBadge
WX_HTML_REPORT_BOX * m_messages
wxDataViewCtrl * m_markerDataView
bool updateUI() override
Definition: dialog_drc.cpp:224
void OnDRCItemSelected(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:403
wxString m_footprintsTitleTemplate
Definition: dialog_drc.h:120
void UpdateData()
Rebuild the contents of the violation tabs based on the current markers and severties.
Definition: dialog_drc.cpp:393
std::shared_ptr< RC_ITEMS_PROVIDER > m_ratsnestProvider
Definition: dialog_drc.h:124
wxString m_markersTitleTemplate
Definition: dialog_drc.h:118
int m_severities
Definition: dialog_drc.h:131
bool m_footprintTestsRun
Definition: dialog_drc.h:116
DIALOG_DRC(PCB_EDIT_FRAME *aEditorFrame, wxWindow *aParent)
Constructors.
Definition: dialog_drc.cpp:71
void OnEditViolationSeverities(wxHyperlinkEvent &aEvent) override
Definition: dialog_drc.cpp:959
void OnDeleteOneClick(wxCommandEvent &aEvent) override
RC_TREE_MODEL * m_fpWarningsTreeModel
Definition: dialog_drc.h:129
bool m_running
Definition: dialog_drc.h:114
void OnDeleteAllClick(wxCommandEvent &aEvent) override
void OnErrorLinkClicked(wxHtmlLinkEvent &event) override
Definition: dialog_drc.cpp:269
BOARD_DESIGN_SETTINGS & bds()
Definition: dialog_drc.h:110
void SelectMarker(const PCB_MARKER *aMarker)
std::chrono::steady_clock::time_point m_lastUpdateUi
Used to slow down the rate of yields in updateUi()
Definition: dialog_drc.h:134
void OnClose(wxCloseEvent &event) override
void syncCheckboxes()
Definition: dialog_drc.cpp:260
BOARD * m_currentBoard
Definition: dialog_drc.h:112
void OnDRCItemRClick(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:621
void PrevMarker()
void OnRunDRCClick(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:275
wxString m_ignoredTitleTemplate
Definition: dialog_drc.h:121
void OnDRCItemDClick(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:606
void deleteAllMarkers(bool aIncludeExclusions)
void updateDisplayedCounts()
RC_TREE_MODEL * m_unconnectedTreeModel
Definition: dialog_drc.h:128
void refreshEditor()
wxString m_unconnectedTitleTemplate
Definition: dialog_drc.h:119
std::shared_ptr< RC_ITEMS_PROVIDER > m_fpWarningsProvider
Definition: dialog_drc.h:125
std::shared_ptr< RC_ITEMS_PROVIDER > m_markersProvider
Definition: dialog_drc.h:123
void OnSeverity(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:965
PCB_EDIT_FRAME * m_frame
Definition: dialog_drc.h:113
bool m_drcRun
Definition: dialog_drc.h:115
void OnIgnoredItemRClick(wxListEvent &event) override
Definition: dialog_drc.cpp:932
void OnCancelClick(wxCommandEvent &aEvent) override
void NextMarker()
void OnActivateDlg(wxActivateEvent &aEvent) override
Definition: dialog_drc.cpp:207
void OnChangingNotebookPage(wxNotebookEvent &aEvent) override
void OnSaveReport(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:990
void ExcludeMarker()
RC_TREE_MODEL * m_markersTreeModel
Definition: dialog_drc.h:127
bool Show(bool show) override
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:127
Design Rule Checker object that performs all the DRC tests.
Definition: drc_engine.h:83
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition: drc_item.h:123
DRC_RULE * GetViolatingRule() const
Definition: drc_item.h:129
bool WriteJsonReport(const wxString &aFullFileName)
Definition: drc_report.cpp:114
bool WriteTextReport(const wxString &aFullFileName)
Definition: drc_report.cpp:47
bool m_Implicit
Definition: drc_rule.h:110
wxString m_Name
Definition: drc_rule.h:112
void DestroyDRCDialog()
Close and free the DRC dialog.
Definition: drc_tool.cpp:122
std::shared_ptr< DRC_ENGINE > GetDRCEngine()
Definition: drc_tool.h:78
void RunTests(PROGRESS_REPORTER *aProgressReporter, bool aRefillZones, bool aReportAllTrackErrors, bool aTestFootprints)
Run the DRC tests.
Definition: drc_tool.cpp:132
void RefreshCanvas() override
void FocusOnLocation(const VECTOR2I &aPos)
Useful to focus on a particular location, in find functions.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:129
bool IsSingle() const
Is this KIFACE running under single_top?
Definition: kiface_base.h:107
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:75
virtual void Remove(VIEW_ITEM *aItem) override
Remove a VIEW_ITEM from the view.
Definition: pcb_view.cpp:66
Definition: kiid.h:49
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:575
static LSET AllLayersMask()
Definition: lset.cpp:898
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:418
@ MARKER_DRAWING_SHEET
Definition: marker_base.h:56
void SetExcluded(bool aExcluded, const wxString &aComment=wxEmptyString)
Definition: marker_base.h:99
void SetMaximumNumber(int aMax)
Set the maximum number to be shown on the badge.
void UpdateNumber(int aNumber, SEVERITY aSeverity)
Update the number displayed on the badge.
Definition: pad.h:53
DISPLAY_OPTIONS m_Display
DIALOG_DRC m_DrcDialog
static TOOL_ACTION showRatsnest
Definition: pcb_actions.h:325
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:68
wxString GetDesignRulesPath()
Return the absolute path to the design rules file for the currently-loaded board.
APPEARANCE_CONTROLS * GetAppearancePanel()
PCBNEW_SETTINGS * GetPcbNewSettings() const
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
BOARD * GetBoard() const
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project.
void FocusOnItem(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
void RedrawRatsnest()
Return the bounding box of the view that should be used if model is not valid.
The main frame for Pcbnew.
void ShowBoardSetupDialog(const wxString &aInitialPage=wxEmptyString)
void SetActiveLayer(PCB_LAYER_ID aLayer) override
Change the currently active layer to aLayer and also update the APPEARANCE_CONTROLS.
void OnModify() override
Must be called after a board change to set the modified flag.
SEVERITY GetSeverity() const override
Definition: pcb_marker.cpp:277
wxString SerializeToString() const
Definition: pcb_marker.cpp:96
virtual wxApp & App()
Returns a bare naked wxApp which may come from wxPython, SINGLE_TOP, or kicad.exe.
Definition: pgm_base.cpp:181
This implements all the tricky bits for thread safety, but the GUI is left to derived classes.
virtual void AdvancePhase() override
Use the next available virtual zone of the dialog progress bar.
virtual void SetCurrentProgress(double aProgress) override
Set the progress value to aProgress (0..1).
virtual void AdvancePhase()=0
Use the next available virtual zone of the dialog progress bar.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:135
void PrevMarker()
Definition: rc_item.cpp:689
void SelectMarker(const MARKER_BASE *aMarker)
Definition: rc_item.cpp:738
static RC_TREE_NODE * ToNode(wxDataViewItem aItem)
Definition: rc_item.h:236
void ValueChanged(RC_TREE_NODE *aNode)
Definition: rc_item.cpp:517
void Update(std::shared_ptr< RC_ITEMS_PROVIDER > aProvider, int aSeverities)
Definition: rc_item.cpp:364
void DeleteItems(bool aCurrentOnly, bool aIncludeExclusions, bool aDeep)
Deletes the current item or all items.
Definition: rc_item.cpp:572
void DeleteCurrentItem(bool aDeep)
Definition: rc_item.cpp:566
void CenterMarker(const MARKER_BASE *aMarker)
Definition: rc_item.cpp:751
static KIID ToUUID(wxDataViewItem aItem)
Definition: rc_item.cpp:220
void NextMarker()
Definition: rc_item.cpp:710
std::shared_ptr< RC_ITEM > m_RcItem
Definition: rc_item.h:221
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
Master controller class:
Definition: tool_manager.h:62
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
void Clear()
Delete the stored messages.
void SetImmediateMode()
In immediate mode, messages are flushed as they are added.
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
void Flush()
Build the HTML messages page.
A KICAD version of wxTextEntryDialog which supports the various improvements/work-arounds from DIALOG...
wxString GetValue() const
Handle actions specific to filling copper zones.
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:161
This file is part of the common library.
static bool g_lastDRCRun
Definition: dialog_drc.cpp:65
static int RPT_SEVERITY_ALL
Definition: dialog_drc.cpp:257
static int DEFAULT_SINGLE_COL_WIDTH
Definition: dialog_drc.cpp:62
static BOARD * g_lastDRCBoard
Definition: dialog_drc.cpp:64
static bool g_lastFootprintTestsRun
Definition: dialog_drc.cpp:66
static std::vector< std::pair< wxString, int > > g_lastIgnored
Definition: dialog_drc.cpp:68
#define DIALOG_DRC_WINDOW_NAME
Definition: dialog_drc.h:42
@ DRCE_UNCONNECTED_ITEMS
Definition: drc_item.h:39
@ DRCE_INVALID_OUTLINE
Definition: drc_item.h:68
@ DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG
Definition: drc_item.h:100
@ DRCE_MALFORMED_COURTYARD
Definition: drc_item.h:63
@ DRCE_FIRST
Definition: drc_item.h:38
@ DRCE_UNRESOLVED_VARIABLE
Definition: drc_item.h:82
@ DRCE_DUPLICATE_FOOTPRINT
Definition: drc_item.h:71
@ DRCE_EXTRA_FOOTPRINT
Definition: drc_item.h:72
@ DRCE_LAST
Definition: drc_item.h:102
@ DRCE_NET_CONFLICT
Definition: drc_item.h:73
@ DRCE_MISSING_FOOTPRINT
Definition: drc_item.h:70
@ DRCE_SCHEMATIC_PARITY_ISSUES
Definition: drc_item.h:74
#define _(s)
#define MALFORMED_F_COURTYARD
#define MALFORMED_B_COURTYARD
static int DEFAULT_SINGLE_COL_WIDTH
static const std::string ReportFileExtension
static const std::string JsonFileExtension
static wxString JsonFileWildcard()
static wxString ReportFileWildcard()
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ F_CrtYd
Definition: layer_ids.h:117
@ Edge_Cuts
Definition: layer_ids.h:113
@ B_CrtYd
Definition: layer_ids.h:116
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
This file contains miscellaneous commonly used macros and functions.
void SetFloatLevel(wxWindow *aWindow)
Intended to set the floating window level in macOS on a window.
Definition: gtk/ui.cpp:324
void ForceFocus(wxWindow *aWindow)
Pass the current focus to the window.
Definition: gtk/ui.cpp:67
T clamp(T min, T value, T max)
Definition: kicad_algo.h:205
STL namespace.
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1059
see class PGM_BASE
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_EXCLUSION
@ RPT_SEVERITY_IGNORE
std::vector< FAB_LAYER_COLOR > dummy
A filename or source description, a problem input line, a line number, a byte offset,...
Definition: ki_exception.h:120
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:107
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
Functions to provide common constants and other functions to assist in making a consistent UI.
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:118
Definition of file extensions used in Kicad.
static int RPT_SEVERITY_ALL