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, 2024 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <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 = std::clamp( (double) m_progress.load() / m_maxProgress, 0.0, 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() ).none() )
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_WITH_COMMENT,
650 ID_ADD_EXCLUSION_ALL,
651 ID_INSPECT_VIOLATION,
652 ID_SET_SEVERITY_TO_ERROR,
653 ID_SET_SEVERITY_TO_WARNING,
654 ID_SET_SEVERITY_TO_IGNORE,
655 ID_EDIT_SEVERITIES
656 };
657
658 if( rcItem->GetParent()->IsExcluded() )
659 {
660 menu.Append( ID_REMOVE_EXCLUSION,
661 _( "Remove exclusion for this violation" ),
662 wxString::Format( _( "It will be placed back in the %s list" ), listName ) );
663
664 menu.Append( ID_EDIT_EXCLUSION_COMMENT,
665 _( "Edit exclusion comment..." ) );
666
667 if( drcItem->GetViolatingRule() && !drcItem->GetViolatingRule()->m_Implicit )
668 {
669 menu.Append( ID_REMOVE_EXCLUSION_ALL,
670 wxString::Format( _( "Remove all exclusions for violations of rule '%s'" ),
671 drcItem->GetViolatingRule()->m_Name ),
672 wxString::Format( _( "They will be placed back in the %s list" ), listName ) );
673 }
674 }
675 else
676 {
677 menu.Append( ID_ADD_EXCLUSION,
678 _( "Exclude this violation" ),
679 wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
680
681 menu.Append( ID_ADD_EXCLUSION_WITH_COMMENT,
682 _( "Exclude with comment..." ),
683 wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
684
685 if( drcItem->GetViolatingRule() && !drcItem->GetViolatingRule()->m_Implicit )
686 {
687 menu.Append( ID_ADD_EXCLUSION_ALL,
688 wxString::Format( _( "Exclude all violations of rule '%s'..." ),
689 drcItem->GetViolatingRule()->m_Name ),
690 wxString::Format( _( "They will be excluded from the %s list" ), listName ) );
691 }
692 }
693
694 wxString inspectDRCErrorMenuText = inspectionTool->InspectDRCErrorMenuText( rcItem );
695
696 if( !inspectDRCErrorMenuText.IsEmpty() )
697 menu.Append( ID_INSPECT_VIOLATION, inspectDRCErrorMenuText );
698
699 menu.AppendSeparator();
700
701 if( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] == RPT_SEVERITY_WARNING )
702 {
703 menu.Append( ID_SET_SEVERITY_TO_ERROR,
704 wxString::Format( _( "Change severity to Error for all '%s' violations" ),
705 rcItem->GetErrorText() ),
706 _( "Violation severities can also be edited in the Board Setup... dialog" ) );
707 }
708 else
709 {
710 menu.Append( ID_SET_SEVERITY_TO_WARNING,
711 wxString::Format( _( "Change severity to Warning for all '%s' violations" ),
712 rcItem->GetErrorText() ),
713 _( "Violation severities can also be edited in the Board Setup... dialog" ) );
714 }
715
716 menu.Append( ID_SET_SEVERITY_TO_IGNORE,
717 wxString::Format( _( "Ignore all '%s' violations" ), rcItem->GetErrorText() ),
718 _( "Violations will not be checked or reported" ) );
719
720 menu.AppendSeparator();
721
722 menu.Append( ID_EDIT_SEVERITIES,
723 _( "Edit violation severities..." ),
724 _( "Open the Board Setup... dialog" ) );
725
726 bool modified = false;
727 int command = GetPopupMenuSelectionFromUser( menu );
728
729 switch( command )
730 {
731 case ID_EDIT_EXCLUSION_COMMENT:
732 if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() ) )
733 {
734 WX_TEXT_ENTRY_DIALOG dlg( this, wxEmptyString, _( "Exclusion Comment" ),
735 marker->GetComment(), true );
736
737 if( dlg.ShowModal() == wxID_CANCEL )
738 break;
739
740 marker->SetExcluded( true, dlg.GetValue() );
741
742 wxString serialized = marker->SerializeToString();
743 bds().m_DrcExclusions.insert( serialized );
744 bds().m_DrcExclusionComments[serialized] = dlg.GetValue();
745
746 // Update view
747 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
748 modified = true;
749 }
750
751 break;
752
753 case ID_REMOVE_EXCLUSION:
754 if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( rcItem->GetParent() ) )
755 {
756 marker->SetExcluded( false );
757
758 wxString serialized = marker->SerializeToString();
759 bds().m_DrcExclusions.erase( serialized );
760 bds().m_DrcExclusionComments.erase( serialized );
761
762 if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
763 {
766 }
767 else
768 {
769 m_frame->GetCanvas()->GetView()->Update( marker );
770 }
771
772 // Update view
773 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
774 modified = true;
775 }
776
777 break;
778
779 case ID_ADD_EXCLUSION:
780 case ID_ADD_EXCLUSION_WITH_COMMENT:
781 if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( rcItem->GetParent() ) )
782 {
783 wxString comment;
784
785 if( command == ID_ADD_EXCLUSION_WITH_COMMENT )
786 {
787 WX_TEXT_ENTRY_DIALOG dlg( this, wxEmptyString, _( "Exclusion Comment" ),
788 wxEmptyString, true );
789
790 if( dlg.ShowModal() == wxID_CANCEL )
791 break;
792
793 comment = dlg.GetValue();
794 }
795
796 marker->SetExcluded( true, comment );
797
798 wxString serialized = marker->SerializeToString();
799 bds().m_DrcExclusions.insert( serialized );
800 bds().m_DrcExclusionComments[serialized] = comment;
801
802 if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
803 {
806 }
807 else
808 {
809 m_frame->GetCanvas()->GetView()->Update( marker );
810 }
811
812 // Update view
814 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
815 else
816 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->DeleteCurrentItem( false );
817
818 modified = true;
819 }
820
821 break;
822
823 case ID_REMOVE_EXCLUSION_ALL:
824 for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
825 {
826 DRC_ITEM* candidateDrcItem = static_cast<DRC_ITEM*>( marker->GetRCItem().get() );
827
828 if( candidateDrcItem->GetViolatingRule() == drcItem->GetViolatingRule() )
829 {
830 marker->SetExcluded( false );
831
832 wxString serialized = marker->SerializeToString();
833 bds().m_DrcExclusions.erase( serialized );
834 bds().m_DrcExclusionComments.erase( serialized );
835 }
836 }
837
838 // Rebuild model and view
839 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markersProvider, m_severities );
840 modified = true;
841 break;
842
843 case ID_ADD_EXCLUSION_ALL:
844 for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
845 {
846 DRC_ITEM* candidateDrcItem = static_cast<DRC_ITEM*>( marker->GetRCItem().get() );
847
848 if( candidateDrcItem->GetViolatingRule() == drcItem->GetViolatingRule() )
849 {
850 marker->SetExcluded( true );
851
852 wxString serialized = marker->SerializeToString();
853 bds().m_DrcExclusions.insert( serialized );
854 }
855 }
856
857 // Rebuild model and view
858 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markersProvider, m_severities );
859 modified = true;
860 break;
861
862 case ID_INSPECT_VIOLATION:
863 inspectionTool->InspectDRCError( node->m_RcItem );
864 break;
865
866 case ID_SET_SEVERITY_TO_ERROR:
867 bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_ERROR;
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_WARNING:
881 bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_WARNING;
882
883 for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
884 {
885 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
886 m_frame->GetCanvas()->GetView()->Update( marker );
887 }
888
889 // Rebuild model and view
890 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markersProvider, m_severities );
891 modified = true;
892 break;
893
894 case ID_SET_SEVERITY_TO_IGNORE:
895 {
896 bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_IGNORE;
897
898 wxListItem listItem;
899 listItem.SetId( m_ignoredList->GetItemCount() );
900 listItem.SetText( wxT( " • " ) + rcItem->GetErrorText() );
901 listItem.SetData( rcItem->GetErrorCode() );
902
903 m_ignoredList->InsertItem( listItem );
904
905 BOARD* board = m_frame->GetBoard();
906
907 std::vector<BOARD_ITEM*> toRemove;
908
909 for( PCB_MARKER* marker : board->Markers() )
910 {
911 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
912 {
913 m_frame->GetCanvas()->GetView()->Remove( marker );
914 toRemove.emplace_back( marker );
915 }
916 }
917
918 for( BOARD_ITEM* marker : toRemove )
919 board->Remove( marker, REMOVE_MODE::BULK );
920
921 board->FinalizeBulkRemove( toRemove );
922
923 if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
925
926 // Rebuild model and view
927 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markersProvider, m_severities );
928 modified = true;
929 break;
930 }
931
932 case ID_EDIT_SEVERITIES:
933 m_frame->ShowBoardSetupDialog( _( "Violation Severity" ) );
934 break;
935 }
936
937 if( modified )
938 {
941 m_frame->OnModify();
942 }
943}
944
945
946void DIALOG_DRC::OnIgnoredItemRClick( wxListEvent& event )
947{
948 int errorCode = (int) event.m_item.GetData();
949 wxMenu menu;
950
951 menu.Append( RPT_SEVERITY_ERROR, _( "Error" ), wxEmptyString, wxITEM_CHECK );
952 menu.Append( RPT_SEVERITY_WARNING, _( "Warning" ), wxEmptyString, wxITEM_CHECK );
953 menu.Append( RPT_SEVERITY_IGNORE, _( "Ignore" ), wxEmptyString, wxITEM_CHECK );
954
955 menu.Check( bds().GetSeverity( errorCode ), true );
956
957 int severity = GetPopupMenuSelectionFromUser( menu );
958
959 if( severity > 0 )
960 {
961 if( bds().m_DRCSeverities[ errorCode ] != severity )
962 {
963 bds().m_DRCSeverities[ errorCode ] = (SEVERITY) severity;
964
967 m_frame->OnModify();
968 }
969 }
970}
971
972
973void DIALOG_DRC::OnEditViolationSeverities( wxHyperlinkEvent& aEvent )
974{
975 m_frame->ShowBoardSetupDialog( _( "Violation Severity" ) );
976}
977
978
979void DIALOG_DRC::OnSeverity( wxCommandEvent& aEvent )
980{
981 int flag = 0;
982
983 if( aEvent.GetEventObject() == m_showAll )
985 else if( aEvent.GetEventObject() == m_showErrors )
987 else if( aEvent.GetEventObject() == m_showWarnings )
989 else if( aEvent.GetEventObject() == m_showExclusions )
991
992 if( aEvent.IsChecked() )
994 else if( aEvent.GetEventObject() == m_showAll )
996 else
997 m_severities &= ~flag;
998
1000 UpdateData();
1001}
1002
1003
1004void DIALOG_DRC::OnSaveReport( wxCommandEvent& aEvent )
1005{
1006 wxFileName fn( "DRC." + FILEEXT::ReportFileExtension );
1007
1008 wxFileDialog dlg( this, _( "Save Report File" ), Prj().GetProjectPath(), fn.GetFullName(),
1010 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1011
1012 if( dlg.ShowModal() != wxID_OK )
1013 return;
1014
1015 fn = dlg.GetPath();
1016
1017 if( fn.GetExt().IsEmpty() )
1018 fn.SetExt( FILEEXT::ReportFileExtension );
1019
1020 if( !fn.IsAbsolute() )
1021 {
1022 wxString prj_path = Prj().GetProjectPath();
1023 fn.MakeAbsolute( prj_path );
1024 }
1025
1028
1029 bool success = false;
1030 if( fn.GetExt() == FILEEXT::JsonFileExtension )
1031 success = reportWriter.WriteJsonReport( fn.GetFullPath() );
1032 else
1033 success = reportWriter.WriteTextReport( fn.GetFullPath() );
1034
1035 if( success )
1036 {
1037 m_messages->Report( wxString::Format( _( "Report file '%s' created<br>" ),
1038 fn.GetFullPath() ) );
1039 }
1040 else
1041 {
1042 DisplayError( this, wxString::Format( _( "Failed to create file '%s'." ),
1043 fn.GetFullPath() ) );
1044 }
1045}
1046
1047
1048void DIALOG_DRC::OnClose( wxCloseEvent& aEvent )
1049{
1050 if( m_running )
1051 aEvent.Veto();
1052
1053 wxCommandEvent dummy;
1054
1056}
1057
1058
1059void DIALOG_DRC::OnCancelClick( wxCommandEvent& aEvent )
1060{
1061 if( m_running )
1062 {
1063 m_cancelled = true;
1064 return;
1065 }
1066
1067 m_frame->FocusOnItem( nullptr );
1068
1069 SetReturnCode( wxID_CANCEL );
1070
1071 // The dialog can be modal or not modal.
1072 // Leave the DRC caller destroy (or not) the dialog
1074 drcTool->DestroyDRCDialog();
1075}
1076
1077
1078void DIALOG_DRC::OnChangingNotebookPage( wxNotebookEvent& aEvent )
1079{
1080 m_markerDataView->UnselectAll();
1081 m_unconnectedDataView->UnselectAll();
1082 m_footprintsDataView->UnselectAll();
1083
1084 aEvent.Skip();
1085}
1086
1087
1089{
1090 WINDOW_THAWER thawer( m_frame );
1091
1093}
1094
1095
1097{
1098 if( m_Notebook->IsShown() )
1099 {
1100 switch( m_Notebook->GetSelection() )
1101 {
1102 case 0: m_markersTreeModel->PrevMarker(); break;
1103 case 1: m_unconnectedTreeModel->PrevMarker(); break;
1104 case 2: m_fpWarningsTreeModel->PrevMarker(); break;
1105 case 3: break;
1106 }
1107 }
1108}
1109
1110
1112{
1113 if( m_Notebook->IsShown() )
1114 {
1115 switch( m_Notebook->GetSelection() )
1116 {
1117 case 0: m_markersTreeModel->NextMarker(); break;
1118 case 1: m_unconnectedTreeModel->NextMarker(); break;
1119 case 2: m_fpWarningsTreeModel->NextMarker(); break;
1120 case 3: break;
1121 }
1122 }
1123}
1124
1125
1127{
1128 if( m_Notebook->IsShown() )
1129 {
1130 enum MARKER_BASE::MARKER_T markerType = aMarker->GetMarkerType();
1131
1132 if( markerType == MARKER_BASE::MARKER_DRC )
1133 m_Notebook->SetSelection( 0 );
1134 else if( markerType == MARKER_BASE::MARKER_PARITY )
1135 m_Notebook->SetSelection( 2 );
1136
1137 m_markersTreeModel->SelectMarker( aMarker );
1138
1139 CallAfter(
1140 [this, aMarker]
1141 {
1142 m_markersTreeModel->CenterMarker( aMarker );
1143 } );
1144 }
1145}
1146
1147
1149{
1150 if( !m_Notebook->IsShown() || m_Notebook->GetSelection() != 0 )
1151 return;
1152
1153 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( m_markerDataView->GetCurrentItem() );
1154 PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
1155
1156 if( marker && marker->GetSeverity() != RPT_SEVERITY_EXCLUSION )
1157 {
1158 marker->SetExcluded( true );
1159 bds().m_DrcExclusions.insert( marker->SerializeToString() );
1160 m_frame->GetCanvas()->GetView()->Update( marker );
1161
1162 // Update view
1165 else
1167
1169 refreshEditor();
1170 m_frame->OnModify();
1171 }
1172}
1173
1174
1175void DIALOG_DRC::deleteAllMarkers( bool aIncludeExclusions )
1176{
1177 // Clear current selection list to avoid selection of deleted items
1179
1180 m_markersTreeModel->DeleteItems( false, aIncludeExclusions, false );
1181 m_unconnectedTreeModel->DeleteItems( false, aIncludeExclusions, false );
1182 m_fpWarningsTreeModel->DeleteItems( false, aIncludeExclusions, false );
1183
1184 m_frame->GetBoard()->DeleteMARKERs( true, aIncludeExclusions );
1185}
1186
1187
1188void DIALOG_DRC::OnDeleteOneClick( wxCommandEvent& aEvent )
1189{
1190 if( m_Notebook->GetSelection() == 0 )
1191 {
1192 // Clear the selection. It may be the selected DRC marker.
1194
1196
1197 // redraw the pcb
1198 refreshEditor();
1199 }
1200 else if( m_Notebook->GetSelection() == 1 )
1201 {
1203 }
1204 else if( m_Notebook->GetSelection() == 2 )
1205 {
1207 }
1208
1210}
1211
1212
1213void DIALOG_DRC::OnDeleteAllClick( wxCommandEvent& aEvent )
1214{
1215 static bool s_includeExclusions = false;
1216
1217 int numExcluded = 0;
1218
1219 if( m_markersProvider )
1220 numExcluded += m_markersProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1221
1222 if( m_ratsnestProvider )
1223 numExcluded += m_ratsnestProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1224
1226 numExcluded += m_fpWarningsProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1227
1228 if( numExcluded > 0 )
1229 {
1230 wxMessageDialog dlg( this, _( "Delete exclusions too?" ), _( "Delete All Markers" ),
1231 wxYES_NO | wxCANCEL | wxCENTER | wxICON_QUESTION );
1232 dlg.SetYesNoLabels( _( "Errors and Warnings Only" ),
1233 _( "Errors, Warnings and Exclusions" ) );
1234
1235 int ret = dlg.ShowModal();
1236
1237 if( ret == wxID_CANCEL )
1238 return;
1239 else if( ret == wxID_NO )
1240 s_includeExclusions = true;
1241 }
1242
1243 deleteAllMarkers( s_includeExclusions );
1244
1245 refreshEditor();
1247}
1248
1249
1251{
1253 DRC_ENGINE* drcEngine = drcTool->GetDRCEngine().get();
1254
1255 // Collect counts:
1256
1257 int numMarkers = 0;
1258 int numUnconnected = 0;
1259 int numFootprints = 0;
1260
1261 int numErrors = 0;
1262 int numWarnings = 0;
1263 int numExcluded = 0;
1264
1265 if( m_markersProvider )
1266 {
1267 numMarkers += m_markersProvider->GetCount();
1268 numErrors += m_markersProvider->GetCount( RPT_SEVERITY_ERROR );
1269 numWarnings += m_markersProvider->GetCount( RPT_SEVERITY_WARNING );
1270 numExcluded += m_markersProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1271 }
1272
1273 if( m_ratsnestProvider )
1274 {
1275 numUnconnected += m_ratsnestProvider->GetCount();
1276 numErrors += m_ratsnestProvider->GetCount( RPT_SEVERITY_ERROR );
1277 numWarnings += m_ratsnestProvider->GetCount( RPT_SEVERITY_WARNING );
1278 numExcluded += m_ratsnestProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1279 }
1280
1282 {
1283 numFootprints += m_fpWarningsProvider->GetCount();
1284 numErrors += m_fpWarningsProvider->GetCount( RPT_SEVERITY_ERROR );
1285 numWarnings += m_fpWarningsProvider->GetCount( RPT_SEVERITY_WARNING );
1286 numExcluded += m_fpWarningsProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1287 }
1288
1289 bool showErrors = m_showErrors->GetValue();
1290 bool showWarnings = m_showWarnings->GetValue();
1291 bool errorsOverflowed = false;
1292 bool warningsOverflowed = false;
1293 bool markersOverflowed = false;
1294 bool unconnectedOverflowed = false;
1295 bool footprintsOverflowed = false;
1296
1297 for( int ii = DRCE_FIRST; ii < DRCE_LAST; ++ii )
1298 {
1299 const SEVERITY severity = bds().GetSeverity( ii );
1300
1301 if( drcEngine->IsErrorLimitExceeded( ii ) )
1302 {
1303 if( severity == RPT_SEVERITY_ERROR )
1304 errorsOverflowed = true;
1305 else if( severity == RPT_SEVERITY_WARNING )
1306 warningsOverflowed = true;
1307
1308 if( ii == DRCE_UNCONNECTED_ITEMS )
1309 {
1310 if( showWarnings && severity == RPT_SEVERITY_WARNING )
1311 unconnectedOverflowed = true;
1312 else if( showErrors && severity == RPT_SEVERITY_ERROR )
1313 unconnectedOverflowed = true;
1314 }
1315 else if( ii == DRCE_MISSING_FOOTPRINT
1317 || ii == DRCE_EXTRA_FOOTPRINT
1318 || ii == DRCE_NET_CONFLICT
1319 || ii == DRCE_SCHEMATIC_PARITY
1320 || ii == DRCE_FOOTPRINT_FILTERS )
1321 {
1322 if( showWarnings && severity == RPT_SEVERITY_WARNING )
1323 footprintsOverflowed = true;
1324 else if( showErrors && severity == RPT_SEVERITY_ERROR )
1325 footprintsOverflowed = true;
1326 }
1327 else
1328 {
1329 if( showWarnings && severity == RPT_SEVERITY_WARNING )
1330 markersOverflowed = true;
1331 else if( showErrors && severity == RPT_SEVERITY_ERROR )
1332 markersOverflowed = true;
1333 }
1334 }
1335 }
1336
1337 wxString msg;
1338 wxString num;
1339
1340 // Update tab headers:
1341
1342 if( m_drcRun )
1343 {
1344 num.Printf( markersOverflowed ? wxT( "%d+" ) : wxT( "%d" ), numMarkers );
1345 msg.Printf( m_markersTitleTemplate, num );
1346 }
1347 else
1348 {
1350 msg.Replace( wxT( "(%s)" ), wxEmptyString );
1351 }
1352
1353 m_Notebook->SetPageText( 0, msg );
1354
1355 if( m_drcRun )
1356 {
1357 num.Printf( unconnectedOverflowed ? wxT( "%d+" ) : wxT( "%d" ), numUnconnected );
1358 msg.sprintf( m_unconnectedTitleTemplate, num );
1359 }
1360 else
1361 {
1363 msg.Replace( wxT( "(%s)" ), wxEmptyString );
1364 }
1365
1366 m_Notebook->SetPageText( 1, msg );
1367
1369 {
1370 num.Printf( footprintsOverflowed ? wxT( "%d+" ) : wxT( "%d" ), numFootprints );
1371 msg.sprintf( m_footprintsTitleTemplate, num );
1372 }
1373 else if( m_drcRun )
1374 {
1376 msg.Replace( wxT( "%s" ), _( "not run" ) );
1377 }
1378 else
1379 {
1381 msg.Replace( wxT( "(%s)" ), wxEmptyString );
1382 }
1383
1384 m_Notebook->SetPageText( 2, msg );
1385
1386 if( m_drcRun )
1387 {
1388 num.Printf( wxT( "%d" ), m_ignoredList->GetItemCount() );
1389 msg.sprintf( m_ignoredTitleTemplate, num );
1390 }
1391 else
1392 {
1394 msg.Replace( wxT( "(%s)" ), wxEmptyString );
1395 }
1396
1397 m_Notebook->SetPageText( 3, msg );
1398
1399 // Update badges:
1400
1401 if( !m_drcRun && numErrors == 0 )
1402 numErrors = -1;
1403
1404 if( !m_drcRun && numWarnings == 0 )
1405 numWarnings = -1;
1406
1407 m_errorsBadge->SetMaximumNumber( numErrors );
1408 m_errorsBadge->UpdateNumber( errorsOverflowed ? numErrors + 1 : numErrors,
1410
1411 m_warningsBadge->SetMaximumNumber( numWarnings );
1412 m_warningsBadge->UpdateNumber( warningsOverflowed ? numWarnings + 1 : numWarnings,
1414
1415 m_exclusionsBadge->SetMaximumNumber( numExcluded );
1417}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
void SetLayerVisible(int aLayer, bool isVisible)
BASE_SET & set(size_t pos)
Definition: base_set.h:115
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
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:79
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:290
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:789
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:1408
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: board.cpp:327
const MARKERS & Markers() const
Definition: board.h:339
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:1132
void UpdateRatsnestExclusions()
Update the visibility flags on the current unconnected ratsnest lines.
Definition: board.cpp:296
void DeleteMARKERs()
Delete all MARKERS from the board.
Definition: board.cpp:1357
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: board.cpp:1138
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:475
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:475
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:973
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:979
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:946
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
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:130
int ShowModal() override
Design Rule Checker object that performs all the DRC tests.
Definition: drc_engine.h:89
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition: drc_item.h:130
DRC_RULE * GetViolatingRule() const
Definition: drc_item.h:149
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:115
wxString m_Name
Definition: drc_rule.h:117
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:101
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:130
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:91
virtual void Remove(VIEW_ITEM *aItem) override
Remove a VIEW_ITEM from the view.
Definition: pcb_view.cpp:74
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: lset.h:36
static LSET AllLayersMask()
Definition: lset.cpp:701
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:410
@ MARKER_DRAWING_SHEET
Definition: marker_base.h:56
void SetExcluded(bool aExcluded, const wxString &aComment=wxEmptyString)
Definition: marker_base.h:99
enum MARKER_T GetMarkerType() const
Definition: marker_base.h:96
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:54
DISPLAY_OPTIONS m_Display
DIALOG_DRC m_DrcDialog
static TOOL_ACTION showRatsnest
Definition: pcb_actions.h:335
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
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:281
wxString SerializeToString() const
Definition: pcb_marker.cpp:97
virtual wxApp & App()
Returns a bare naked wxApp which may come from wxPython, SINGLE_TOP, or kicad.exe.
Definition: pgm_base.cpp:182
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:170
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_FOOTPRINT_FILTERS
Definition: drc_item.h:79
@ DRCE_UNCONNECTED_ITEMS
Definition: drc_item.h:39
@ DRCE_INVALID_OUTLINE
Definition: drc_item.h:72
@ DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG
Definition: drc_item.h:107
@ DRCE_MALFORMED_COURTYARD
Definition: drc_item.h:67
@ DRCE_FIRST
Definition: drc_item.h:38
@ DRCE_UNRESOLVED_VARIABLE
Definition: drc_item.h:87
@ DRCE_DUPLICATE_FOOTPRINT
Definition: drc_item.h:75
@ DRCE_EXTRA_FOOTPRINT
Definition: drc_item.h:76
@ DRCE_LAST
Definition: drc_item.h:109
@ DRCE_NET_CONFLICT
Definition: drc_item.h:77
@ DRCE_MISSING_FOOTPRINT
Definition: drc_item.h:74
@ DRCE_SCHEMATIC_PARITY
Definition: drc_item.h:78
#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:116
@ Edge_Cuts
Definition: layer_ids.h:112
@ B_CrtYd
Definition: layer_ids.h:115
@ 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: wxgtk/ui.cpp:338
void ForceFocus(wxWindow *aWindow)
Pass the current focus to the window.
Definition: wxgtk/ui.cpp:67
STL namespace.
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1060
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.
Definition of file extensions used in Kicad.
static int RPT_SEVERITY_ALL