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 The 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#include <advanced_config.h>
59
60// wxWidgets spends *far* too long calcuating column widths (most of it, believe it or
61// not, in repeatedly creating/destroying a wxDC to do the measurement in).
62// Use default column widths instead.
63static int DEFAULT_SINGLE_COL_WIDTH = 660;
64
65static BOARD* g_lastDRCBoard = nullptr;
66static bool g_lastDRCRun = false;
67static bool g_lastFootprintTestsRun = false;
68
69static std::vector<std::pair<wxString, int>> g_lastIgnored;
70
71
72DIALOG_DRC::DIALOG_DRC( PCB_EDIT_FRAME* aEditorFrame, wxWindow* aParent ) :
73 DIALOG_DRC_BASE( aParent ),
75 m_running( false ),
76 m_drcRun( false ),
77 m_footprintTestsRun( false ),
78 m_markersTreeModel( nullptr ),
79 m_unconnectedTreeModel( nullptr ),
80 m_fpWarningsTreeModel( nullptr ),
82 m_lastUpdateUi( std::chrono::steady_clock::now() )
83{
84 SetName( DIALOG_DRC_WINDOW_NAME ); // Set a window name to be able to find it
86
87 m_frame = aEditorFrame;
89
91
93 {
94 m_severities = cfg->m_DrcDialog.severities;
95
96 m_cbRefillZones->SetValue( cfg->m_DrcDialog.refill_zones );
97 m_cbReportAllTrackErrors->SetValue( cfg->m_DrcDialog.test_all_track_errors );
98
99 if( !Kiface().IsSingle() )
100 m_cbTestFootprints->SetValue( cfg->m_DrcDialog.test_footprints );
101 }
102
103 m_markersProvider = std::make_shared<DRC_ITEMS_PROVIDER>( m_currentBoard,
106
107 m_ratsnestProvider = std::make_shared<DRC_ITEMS_PROVIDER>( m_currentBoard,
109
110 m_fpWarningsProvider = std::make_shared<DRC_ITEMS_PROVIDER>( m_currentBoard,
112
114 m_markerDataView->AssociateModel( m_markersTreeModel );
116
120
124
125 m_ignoredList->InsertColumn( 0, wxEmptyString, wxLIST_FORMAT_LEFT, DEFAULT_SINGLE_COL_WIDTH );
126
128 {
131
132 for( const auto& [ str, code ] : g_lastIgnored )
133 {
134 wxListItem listItem;
135 listItem.SetId( m_ignoredList->GetItemCount() );
136 listItem.SetText( str );
137 listItem.SetData( code );
138
139 m_ignoredList->InsertItem( listItem );
140 }
141 }
142
143 m_Notebook->SetSelection( 0 );
144
145 if( Kiface().IsSingle() )
146 m_cbTestFootprints->Hide();
147
148 SetupStandardButtons( { { wxID_OK, _( "Run DRC" ) },
149 { wxID_CANCEL, _( "Close" ) } } );
150
151 m_markersTitleTemplate = m_Notebook->GetPageText( 0 );
152 m_unconnectedTitleTemplate = m_Notebook->GetPageText( 1 );
153 m_footprintsTitleTemplate = m_Notebook->GetPageText( 2 );
154 m_ignoredTitleTemplate = m_Notebook->GetPageText( 3 );
155
156 Layout(); // adding the units above expanded Clearance text, now resize.
157
158 SetFocus();
159
161
163}
164
165
167{
169
173
174 g_lastIgnored.clear();
175
176 for( int ii = 0; ii < m_ignoredList->GetItemCount(); ++ii )
177 {
178 g_lastIgnored.push_back( { m_ignoredList->GetItemText( ii ),
179 m_ignoredList->GetItemData( ii ) } );
180 }
181
183 {
184 cfg->m_DrcDialog.refill_zones = m_cbRefillZones->GetValue();
185 cfg->m_DrcDialog.test_all_track_errors = m_cbReportAllTrackErrors->GetValue();
186
187 if( !Kiface().IsSingle() )
188 cfg->m_DrcDialog.test_footprints = m_cbTestFootprints->GetValue();
189
190 cfg->m_DrcDialog.severities = m_severities;
191 }
192
193 m_markersTreeModel->DecRef();
194 m_unconnectedTreeModel->DecRef();
195 m_fpWarningsTreeModel->DecRef();
196}
197
198
199void DIALOG_DRC::OnActivateDlg( wxActivateEvent& aEvent )
200{
202 {
203 // If m_currentBoard is not the current board, (for instance because a new board
204 // was loaded), close the dialog, because many pointers are now invalid in lists
205 SetReturnCode( wxID_CANCEL );
206 Close();
207
209 drcTool->DestroyDRCDialog();
210 }
211}
212
213
214// PROGRESS_REPORTER calls
215
217{
218 double cur = std::clamp( (double) m_progress.load() / m_maxProgress, 0.0, 1.0 );
219
220 int newValue = KiROUND( cur * 1000.0 );
221 m_gauge->SetValue( newValue );
222
223 // There is significant overhead on at least Windows when updateUi is called constantly thousands of times
224 // in the drc process and safeyieldfor is called each time.
225 // Gate the yield to a limited rate which still allows the UI to function without slowing down the main thread
226 // which is also running DRC
227 std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
228 if( std::chrono::duration_cast<std::chrono::milliseconds>( now - m_lastUpdateUi ).count()
229 > 100 )
230 {
231 Pgm().App().SafeYieldFor( this, wxEVT_CATEGORY_NATIVE_EVENTS );
232 m_lastUpdateUi = now;
233 }
234
235 return !m_cancelled;
236}
237
238
239void DIALOG_DRC::AdvancePhase( const wxString& aMessage )
240{
242 SetCurrentProgress( 0.0 );
243
244 m_messages->Report( aMessage );
245}
246
247
248// Don't globally define this; different facilities use different definitions of "ALL"
250
251
253{
258}
259
260
261void DIALOG_DRC::OnErrorLinkClicked( wxHtmlLinkEvent& event )
262{
263 m_frame->ShowBoardSetupDialog( _( "Custom Rules" ) );
264}
265
266
267void DIALOG_DRC::OnRunDRCClick( wxCommandEvent& aEvent )
268{
269 TOOL_MANAGER* toolMgr = m_frame->GetToolManager();
270 DRC_TOOL* drcTool = toolMgr->GetTool<DRC_TOOL>();
271 ZONE_FILLER_TOOL* zoneFillerTool = toolMgr->GetTool<ZONE_FILLER_TOOL>();
272 bool refillZones = m_cbRefillZones->GetValue();
273 bool reportAllTrackErrors = m_cbReportAllTrackErrors->GetValue();
274 bool testFootprints = m_cbTestFootprints->GetValue();
275
276 if( zoneFillerTool->IsBusy() )
277 {
278 wxBell();
279 return;
280 }
281
282 // This is not the time to have stale or buggy rules. Ensure they're up-to-date
283 // and that they at least parse.
284 try
285 {
286 drcTool->GetDRCEngine()->InitEngine( m_frame->GetDesignRulesPath() );
287 }
288 catch( PARSE_ERROR& )
289 {
290 m_runningResultsBook->ChangeSelection( 0 ); // Display the "Tests Running..." tab
291 m_DeleteCurrentMarkerButton->Enable( false );
292 m_DeleteAllMarkersButton->Enable( false );
293 m_saveReport->Enable( false );
294
295 m_messages->Clear();
296 m_messages->Report( _( "DRC incomplete: could not compile custom design rules." )
297 + wxS( "&nbsp;&nbsp;" )
298 + wxS( "<a href='$CUSTOM_RULES'>" ) + _( "Show design rules." ) + wxT( "</a>" ) );
299 m_messages->Flush();
300
301 Raise();
302
303 // set float level again, it can be lost due to window events during test run
305 return;
306 }
307
308 m_footprintTestsRun = false;
309 m_cancelled = false;
310
312 deleteAllMarkers( true );
313
314 std::vector<std::reference_wrapper<RC_ITEM>> violations = DRC_ITEM::GetItemsWithSeverities();
315 m_ignoredList->DeleteAllItems();
316
317 for( std::reference_wrapper<RC_ITEM>& item : violations )
318 {
319 if( bds().GetSeverity( item.get().GetErrorCode() ) == RPT_SEVERITY_IGNORE )
320 {
321 wxListItem listItem;
322 listItem.SetId( m_ignoredList->GetItemCount() );
323 listItem.SetText( wxT( " • " ) + item.get().GetErrorText() );
324 listItem.SetData( item.get().GetErrorCode() );
325
326 m_ignoredList->InsertItem( listItem );
327 }
328 }
329
330 m_ignoredList->SetColumnWidth( 0, m_ignoredList->GetParent()->GetClientSize().x - 20 );
331
332 Raise();
333
334 m_runningResultsBook->ChangeSelection( 0 ); // Display the "Tests Running..." tab
335 m_messages->Clear();
336 wxYield(); // Allow time slice to refresh Messages
337
338 m_running = true;
339 m_sdbSizerCancel->SetLabel( _( "Cancel" ) );
340 m_sdbSizerOK->Enable( false );
341 m_DeleteCurrentMarkerButton->Enable( false );
342 m_DeleteAllMarkersButton->Enable( false );
343 m_saveReport->Enable( false );
344
345 {
346 wxBusyCursor dummy;
347 drcTool->RunTests( this, refillZones, reportAllTrackErrors, testFootprints );
348 }
349
350 if( m_cancelled )
351 m_messages->Report( _( "-------- DRC canceled by user.<br><br>" ) );
352 else
353 m_messages->Report( _( "Done.<br><br>" ) );
354
355 Raise();
356 wxYield(); // Allow time slice to refresh Messages
357
358 m_running = false;
359 m_sdbSizerCancel->SetLabel( _( "Close" ) );
360 m_sdbSizerOK->Enable( true );
361 m_DeleteCurrentMarkerButton->Enable( true );
362 m_DeleteAllMarkersButton->Enable( true );
363 m_saveReport->Enable( true );
364
365 if( !m_cancelled )
366 {
367 m_sdbSizerCancel->SetDefault();
368 // wxWidgets has a tendency to keep both buttons highlighted without the following:
369 m_sdbSizerOK->Enable( false );
370
371 wxMilliSleep( 500 );
372 m_runningResultsBook->ChangeSelection( 1 );
374
375 // now re-enable m_sdbSizerOK button
376 m_sdbSizerOK->Enable( true );
377 }
378
379 // set float level again, it can be lost due to window events during test run
382}
383
384
386{
390
392}
393
394
395void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
396{
397 BOARD* board = m_frame->GetBoard();
398 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
399
400 auto getActiveLayers =
401 []( BOARD_ITEM* aItem ) -> LSET
402 {
403 if( aItem->Type() == PCB_PAD_T )
404 {
405 PAD* pad = static_cast<PAD*>( aItem );
406 LSET layers;
407
408 for( int layer : aItem->GetLayerSet().Seq() )
409 {
410 if( pad->FlashLayer( layer ) )
411 layers.set( layer );
412 }
413
414 return layers;
415 }
416 else
417 {
418 return aItem->GetLayerSet();
419 }
420 };
421
422 auto isOverlapping =
423 []( BOARD_ITEM* aSelectedMarkerItem, BOARD_ITEM* aUnSelectedMarkerItem ) -> bool
424 {
425 VECTOR2D selectedItemPos = aSelectedMarkerItem->GetPosition() / PCB_IU_PER_MM;
426 VECTOR2D unSelectedItemPos = aUnSelectedMarkerItem->GetPosition() / PCB_IU_PER_MM;
427
428 double dist = selectedItemPos.Distance( unSelectedItemPos );
429
430 double minimumMarkerSeparationDistance =
432
433 return dist <= minimumMarkerSeparationDistance;
434 };
435
436 if( !node )
437 {
438 // list is being freed; don't do anything with null ptrs
439
440 aEvent.Skip();
441 return;
442 }
443
444 std::shared_ptr<RC_ITEM> rc_item = node->m_RcItem;
445
446 if( rc_item->GetErrorCode() == DRCE_UNRESOLVED_VARIABLE
447 && rc_item->GetParent()->GetMarkerType() == MARKER_BASE::MARKER_DRAWING_SHEET )
448 {
449 m_frame->FocusOnLocation( node->m_RcItem->GetParent()->GetPos() );
450
451 aEvent.Skip();
452 return;
453 }
454
455 const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
456 BOARD_ITEM* item = board->ResolveItem( itemID, true );
457
458 if( !item )
459 {
460 // nothing to highlight / focus on
461 aEvent.Skip();
462 return;
463 }
464
465 PCB_LAYER_ID principalLayer;
466 LSET violationLayers;
467 BOARD_ITEM* a = board->ResolveItem( rc_item->GetMainItemID(), true );
468 BOARD_ITEM* b = board->ResolveItem( rc_item->GetAuxItemID(), true );
469 BOARD_ITEM* c = board->ResolveItem( rc_item->GetAuxItem2ID(), true );
470 BOARD_ITEM* d = board->ResolveItem( rc_item->GetAuxItem3ID(), true );
471
472 if( rc_item->GetErrorCode() == DRCE_MALFORMED_COURTYARD )
473 {
474 if( a && ( a->GetFlags() & MALFORMED_B_COURTYARD ) > 0
475 && ( a->GetFlags() & MALFORMED_F_COURTYARD ) == 0 )
476 {
477 principalLayer = B_CrtYd;
478 }
479 else
480 {
481 principalLayer = F_CrtYd;
482 }
483 }
484 else if( rc_item->GetErrorCode() == DRCE_INVALID_OUTLINE )
485 {
486 principalLayer = Edge_Cuts;
487 }
488 else
489 {
490 principalLayer = UNDEFINED_LAYER;
491
492 if( a || b || c || d )
493 violationLayers = LSET::AllLayersMask();
494
495 // Try to initialize principalLayer to a valid layer. Note that some markers have
496 // a layer set to UNDEFINED_LAYER, so we may need to keep looking.
497
498 for( BOARD_ITEM* it: { a, b, c, d } )
499 {
500 if( !it )
501 continue;
502
503 LSET layersList = getActiveLayers( it );
504 violationLayers &= layersList;
505
506 if( principalLayer <= UNDEFINED_LAYER && layersList.count() )
507 principalLayer = layersList.Seq().front();
508 }
509 }
510
511 if( violationLayers.count() )
512 principalLayer = violationLayers.Seq().front();
513 else if( principalLayer >= 0 )
514 violationLayers.set( principalLayer );
515
516 WINDOW_THAWER thawer( m_frame );
517
518 if( principalLayer > UNDEFINED_LAYER && ( violationLayers & board->GetVisibleLayers() ).none() )
519 m_frame->GetAppearancePanel()->SetLayerVisible( principalLayer, true );
520
521 if( principalLayer > UNDEFINED_LAYER && board->GetVisibleLayers().test( principalLayer ) )
522 m_frame->SetActiveLayer( principalLayer );
523
524 if( rc_item->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
525 {
528
529 if( item->Type() == PCB_ZONE_T )
530 {
531 m_frame->FocusOnItem( item, principalLayer );
532
533 m_frame->GetBoard()->GetConnectivity()->RunOnUnconnectedEdges(
534 [&]( CN_EDGE& edge )
535 {
536 // Connectivity was valid when DRC was run, but this is a modeless dialog
537 // so it might not be now.
538 if( !edge.GetSourceNode() || edge.GetSourceNode()->Dirty() )
539 return true;
540
541 if( !edge.GetTargetNode() || edge.GetTargetNode()->Dirty() )
542 return true;
543
544 if( edge.GetSourceNode()->Parent() == a
545 && edge.GetTargetNode()->Parent() == b )
546 {
547 VECTOR2I focusPos;
548
549 if( item == a && item == b )
550 {
551 focusPos = ( node->m_Type == RC_TREE_NODE::MAIN_ITEM )
552 ? edge.GetSourcePos()
553 : edge.GetTargetPos();
554 }
555 else
556 {
557 focusPos = ( item == edge.GetSourceNode()->Parent() )
558 ? edge.GetSourcePos()
559 : edge.GetTargetPos();
560 }
561
562 m_frame->FocusOnLocation( focusPos );
564
565 return false;
566 }
567
568 return true;
569 } );
570 }
571 else
572 {
573 m_frame->FocusOnItem( item, principalLayer );
574 }
575 }
576 else if( rc_item->GetErrorCode() == DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG )
577 {
578 BOARD_CONNECTED_ITEM* track = dynamic_cast<PCB_TRACK*>( item );
579 std::vector<BOARD_ITEM*> items;
580
581 if( track )
582 {
583 int net = track->GetNetCode();
584
585 wxASSERT( net > 0 ); // Without a net how can it be a diff-pair?
586
587 for( const KIID& id : rc_item->GetIDs() )
588 {
589 auto* candidate = dynamic_cast<BOARD_CONNECTED_ITEM*>( board->ResolveItem( id, true ) );
590
591 if( candidate && candidate->GetNetCode() == net )
592 items.push_back( candidate );
593 }
594 }
595 else
596 {
597 items.push_back( item );
598 }
599
600 m_frame->FocusOnItems( items, principalLayer );
601 }
602 else
603 {
604 if( item->Type() == PCB_MARKER_T )
605 {
606 std::vector<BOARD_ITEM*> items;
607
608 for( BOARD_ITEM* boardMarkerItem : board->Markers() )
609 {
610 if( item->m_Uuid != boardMarkerItem->m_Uuid && isOverlapping( item, boardMarkerItem ) )
611 {
612 items.push_back( boardMarkerItem );
613 }
614 }
615
616 items.push_back( item );
617 m_frame->FocusOnItems( items, principalLayer );
618 }
619 else
620 {
621 m_frame->FocusOnItem( item, principalLayer );
622 }
623 }
624
625 aEvent.Skip();
626}
627
628
629void DIALOG_DRC::OnDRCItemDClick( wxDataViewEvent& aEvent )
630{
631 if( aEvent.GetItem().IsOk() )
632 {
633 // turn control over to m_frame, hide this DIALOG_DRC window,
634 // no destruction so we can preserve listbox cursor
635 if( !IsModal() )
636 Show( false );
637 }
638
639 // Do not skip aEvent here: this is not useful, and Pcbnew crashes
640 // if skipped (at least on Windows)
641}
642
643
644void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
645{
646 TOOL_MANAGER* toolMgr = m_frame->GetToolManager();
647 BOARD_INSPECTION_TOOL* inspectionTool = toolMgr->GetTool<BOARD_INSPECTION_TOOL>();
648 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
649
650 if( !node )
651 return;
652
653 std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
654 DRC_ITEM* drcItem = static_cast<DRC_ITEM*>( rcItem.get() );
655 std::shared_ptr<CONNECTIVITY_DATA> conn = m_currentBoard->GetConnectivity();
656 wxString listName;
657 wxMenu menu;
658
659 switch( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] )
660 {
661 case RPT_SEVERITY_ERROR: listName = _( "errors" ); break;
662 case RPT_SEVERITY_WARNING: listName = _( "warnings" ); break;
663 default: listName = _( "appropriate" ); break;
664 }
665
666 enum MENU_IDS
667 {
668 ID_EDIT_EXCLUSION_COMMENT = 4467,
669 ID_REMOVE_EXCLUSION,
670 ID_REMOVE_EXCLUSION_ALL,
671 ID_ADD_EXCLUSION,
672 ID_ADD_EXCLUSION_WITH_COMMENT,
673 ID_ADD_EXCLUSION_ALL,
674 ID_INSPECT_VIOLATION,
675 ID_SET_SEVERITY_TO_ERROR,
676 ID_SET_SEVERITY_TO_WARNING,
677 ID_SET_SEVERITY_TO_IGNORE,
678 ID_EDIT_SEVERITIES
679 };
680
681 if( rcItem->GetParent()->IsExcluded() )
682 {
683 menu.Append( ID_REMOVE_EXCLUSION,
684 _( "Remove exclusion for this violation" ),
685 wxString::Format( _( "It will be placed back in the %s list" ), listName ) );
686
687 menu.Append( ID_EDIT_EXCLUSION_COMMENT,
688 _( "Edit exclusion comment..." ) );
689
690 if( drcItem->GetViolatingRule() && !drcItem->GetViolatingRule()->m_Implicit )
691 {
692 menu.Append( ID_REMOVE_EXCLUSION_ALL,
693 wxString::Format( _( "Remove all exclusions for violations of rule '%s'" ),
694 drcItem->GetViolatingRule()->m_Name ),
695 wxString::Format( _( "They will be placed back in the %s list" ), listName ) );
696 }
697 }
698 else
699 {
700 menu.Append( ID_ADD_EXCLUSION,
701 _( "Exclude this violation" ),
702 wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
703
704 menu.Append( ID_ADD_EXCLUSION_WITH_COMMENT,
705 _( "Exclude with comment..." ),
706 wxString::Format( _( "It will be excluded from the %s list" ), listName ) );
707
708 if( drcItem->GetViolatingRule() && !drcItem->GetViolatingRule()->m_Implicit )
709 {
710 menu.Append( ID_ADD_EXCLUSION_ALL,
711 wxString::Format( _( "Exclude all violations of rule '%s'..." ),
712 drcItem->GetViolatingRule()->m_Name ),
713 wxString::Format( _( "They will be excluded from the %s list" ), listName ) );
714 }
715 }
716
717 wxString inspectDRCErrorMenuText = inspectionTool->InspectDRCErrorMenuText( rcItem );
718
719 if( !inspectDRCErrorMenuText.IsEmpty() )
720 menu.Append( ID_INSPECT_VIOLATION, inspectDRCErrorMenuText );
721
722 menu.AppendSeparator();
723
724 if( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] == RPT_SEVERITY_WARNING )
725 {
726 menu.Append( ID_SET_SEVERITY_TO_ERROR,
727 wxString::Format( _( "Change severity to Error for all '%s' violations" ),
728 rcItem->GetErrorText() ),
729 _( "Violation severities can also be edited in the Board Setup... dialog" ) );
730 }
731 else
732 {
733 menu.Append( ID_SET_SEVERITY_TO_WARNING,
734 wxString::Format( _( "Change severity to Warning for all '%s' violations" ),
735 rcItem->GetErrorText() ),
736 _( "Violation severities can also be edited in the Board Setup... dialog" ) );
737 }
738
739 menu.Append( ID_SET_SEVERITY_TO_IGNORE,
740 wxString::Format( _( "Ignore all '%s' violations" ), rcItem->GetErrorText() ),
741 _( "Violations will not be checked or reported" ) );
742
743 menu.AppendSeparator();
744
745 menu.Append( ID_EDIT_SEVERITIES,
746 _( "Edit violation severities..." ),
747 _( "Open the Board Setup... dialog" ) );
748
749 bool modified = false;
750 int command = GetPopupMenuSelectionFromUser( menu );
751
752 switch( command )
753 {
754 case ID_EDIT_EXCLUSION_COMMENT:
755 if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() ) )
756 {
757 WX_TEXT_ENTRY_DIALOG dlg( this, wxEmptyString, _( "Exclusion Comment" ),
758 marker->GetComment(), true );
759
760 if( dlg.ShowModal() == wxID_CANCEL )
761 break;
762
763 marker->SetExcluded( true, dlg.GetValue() );
764
765 wxString serialized = marker->SerializeToString();
766 bds().m_DrcExclusions.insert( serialized );
767 bds().m_DrcExclusionComments[serialized] = dlg.GetValue();
768
769 // Update view
770 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
771 modified = true;
772 }
773
774 break;
775
776 case ID_REMOVE_EXCLUSION:
777 if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( rcItem->GetParent() ) )
778 {
779 marker->SetExcluded( false );
780
781 wxString serialized = marker->SerializeToString();
782 bds().m_DrcExclusions.erase( serialized );
783 bds().m_DrcExclusionComments.erase( serialized );
784
785 if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
786 {
789 }
790 else
791 {
792 m_frame->GetCanvas()->GetView()->Update( marker );
793 }
794
795 // Update view
796 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
797 modified = true;
798 }
799
800 break;
801
802 case ID_ADD_EXCLUSION:
803 case ID_ADD_EXCLUSION_WITH_COMMENT:
804 if( PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( rcItem->GetParent() ) )
805 {
806 wxString comment;
807
808 if( command == ID_ADD_EXCLUSION_WITH_COMMENT )
809 {
810 WX_TEXT_ENTRY_DIALOG dlg( this, wxEmptyString, _( "Exclusion Comment" ),
811 wxEmptyString, true );
812
813 if( dlg.ShowModal() == wxID_CANCEL )
814 break;
815
816 comment = dlg.GetValue();
817 }
818
819 marker->SetExcluded( true, comment );
820
821 wxString serialized = marker->SerializeToString();
822 bds().m_DrcExclusions.insert( serialized );
823 bds().m_DrcExclusionComments[serialized] = comment;
824
825 if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
826 {
829 }
830 else
831 {
832 m_frame->GetCanvas()->GetView()->Update( marker );
833 }
834
835 // Update view
837 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
838 else
839 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->DeleteCurrentItem( false );
840
841 modified = true;
842 }
843
844 break;
845
846 case ID_REMOVE_EXCLUSION_ALL:
847 for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
848 {
849 DRC_ITEM* candidateDrcItem = static_cast<DRC_ITEM*>( marker->GetRCItem().get() );
850
851 if( candidateDrcItem->GetViolatingRule() == drcItem->GetViolatingRule() )
852 {
853 marker->SetExcluded( false );
854
855 wxString serialized = marker->SerializeToString();
856 bds().m_DrcExclusions.erase( serialized );
857 bds().m_DrcExclusionComments.erase( serialized );
858 }
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_ADD_EXCLUSION_ALL:
867 for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
868 {
869 DRC_ITEM* candidateDrcItem = static_cast<DRC_ITEM*>( marker->GetRCItem().get() );
870
871 if( candidateDrcItem->GetViolatingRule() == drcItem->GetViolatingRule() )
872 {
873 marker->SetExcluded( true );
874
875 wxString serialized = marker->SerializeToString();
876 bds().m_DrcExclusions.insert( serialized );
877 }
878 }
879
880 // Rebuild model and view
881 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markersProvider, m_severities );
882 modified = true;
883 break;
884
885 case ID_INSPECT_VIOLATION:
886 inspectionTool->InspectDRCError( node->m_RcItem );
887 break;
888
889 case ID_SET_SEVERITY_TO_ERROR:
890 bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_ERROR;
891
892 for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
893 {
894 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
895 m_frame->GetCanvas()->GetView()->Update( marker );
896 }
897
898 // Rebuild model and view
899 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markersProvider, m_severities );
900 modified = true;
901 break;
902
903 case ID_SET_SEVERITY_TO_WARNING:
904 bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_WARNING;
905
906 for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
907 {
908 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
909 m_frame->GetCanvas()->GetView()->Update( marker );
910 }
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 case ID_SET_SEVERITY_TO_IGNORE:
918 {
919 bds().m_DRCSeverities[ rcItem->GetErrorCode() ] = RPT_SEVERITY_IGNORE;
920
921 wxListItem listItem;
922 listItem.SetId( m_ignoredList->GetItemCount() );
923 listItem.SetText( wxT( " • " ) + rcItem->GetErrorText() );
924 listItem.SetData( rcItem->GetErrorCode() );
925
926 m_ignoredList->InsertItem( listItem );
927
928 BOARD* board = m_frame->GetBoard();
929
930 std::vector<BOARD_ITEM*> toRemove;
931
932 for( PCB_MARKER* marker : board->Markers() )
933 {
934 if( marker->GetRCItem()->GetErrorCode() == rcItem->GetErrorCode() )
935 {
936 m_frame->GetCanvas()->GetView()->Remove( marker );
937 toRemove.emplace_back( marker );
938 }
939 }
940
941 for( BOARD_ITEM* marker : toRemove )
942 board->Remove( marker, REMOVE_MODE::BULK );
943
944 board->FinalizeBulkRemove( toRemove );
945
946 if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
948
949 // Rebuild model and view
950 static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markersProvider, m_severities );
951 modified = true;
952 break;
953 }
954
955 case ID_EDIT_SEVERITIES:
956 m_frame->ShowBoardSetupDialog( _( "Violation Severity" ) );
957 break;
958 }
959
960 if( modified )
961 {
964 m_frame->OnModify();
965 }
966}
967
968
969void DIALOG_DRC::OnIgnoredItemRClick( wxListEvent& event )
970{
971 int errorCode = (int) event.m_item.GetData();
972 wxMenu menu;
973
974 menu.Append( RPT_SEVERITY_ERROR, _( "Error" ), wxEmptyString, wxITEM_CHECK );
975 menu.Append( RPT_SEVERITY_WARNING, _( "Warning" ), wxEmptyString, wxITEM_CHECK );
976 menu.Append( RPT_SEVERITY_IGNORE, _( "Ignore" ), wxEmptyString, wxITEM_CHECK );
977
978 menu.Check( bds().GetSeverity( errorCode ), true );
979
980 int severity = GetPopupMenuSelectionFromUser( menu );
981
982 if( severity > 0 )
983 {
984 if( bds().m_DRCSeverities[ errorCode ] != severity )
985 {
986 bds().m_DRCSeverities[ errorCode ] = (SEVERITY) severity;
987
990 m_frame->OnModify();
991 }
992 }
993}
994
995
996void DIALOG_DRC::OnEditViolationSeverities( wxHyperlinkEvent& aEvent )
997{
998 m_frame->ShowBoardSetupDialog( _( "Violation Severity" ) );
999}
1000
1001
1002void DIALOG_DRC::OnSeverity( wxCommandEvent& aEvent )
1003{
1004 int flag = 0;
1005
1006 if( aEvent.GetEventObject() == m_showAll )
1008 else if( aEvent.GetEventObject() == m_showErrors )
1010 else if( aEvent.GetEventObject() == m_showWarnings )
1012 else if( aEvent.GetEventObject() == m_showExclusions )
1014
1015 if( aEvent.IsChecked() )
1016 m_severities |= flag;
1017 else if( aEvent.GetEventObject() == m_showAll )
1019 else
1020 m_severities &= ~flag;
1021
1023 UpdateData();
1024}
1025
1026
1027void DIALOG_DRC::OnSaveReport( wxCommandEvent& aEvent )
1028{
1029 wxFileName fn( "DRC." + FILEEXT::ReportFileExtension );
1030
1031 wxFileDialog dlg( this, _( "Save Report File" ), Prj().GetProjectPath(), fn.GetFullName(),
1033 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1034
1035 if( dlg.ShowModal() != wxID_OK )
1036 return;
1037
1038 fn = dlg.GetPath();
1039
1040 if( fn.GetExt().IsEmpty() )
1041 fn.SetExt( FILEEXT::ReportFileExtension );
1042
1043 if( !fn.IsAbsolute() )
1044 {
1045 wxString prj_path = Prj().GetProjectPath();
1046 fn.MakeAbsolute( prj_path );
1047 }
1048
1051
1052 bool success = false;
1053 if( fn.GetExt() == FILEEXT::JsonFileExtension )
1054 success = reportWriter.WriteJsonReport( fn.GetFullPath() );
1055 else
1056 success = reportWriter.WriteTextReport( fn.GetFullPath() );
1057
1058 if( success )
1059 {
1060 m_messages->Report( wxString::Format( _( "Report file '%s' created<br>" ),
1061 fn.GetFullPath() ) );
1062 }
1063 else
1064 {
1065 DisplayError( this, wxString::Format( _( "Failed to create file '%s'." ),
1066 fn.GetFullPath() ) );
1067 }
1068}
1069
1070
1071void DIALOG_DRC::OnClose( wxCloseEvent& aEvent )
1072{
1073 if( m_running )
1074 aEvent.Veto();
1075
1076 wxCommandEvent dummy;
1077
1079}
1080
1081
1082void DIALOG_DRC::OnCancelClick( wxCommandEvent& aEvent )
1083{
1084 if( m_running )
1085 {
1086 m_cancelled = true;
1087 return;
1088 }
1089
1091
1092 SetReturnCode( wxID_CANCEL );
1093
1094 // The dialog can be modal or not modal.
1095 // Leave the DRC caller destroy (or not) the dialog
1097 drcTool->DestroyDRCDialog();
1098}
1099
1100
1101void DIALOG_DRC::OnChangingNotebookPage( wxNotebookEvent& aEvent )
1102{
1103 m_markerDataView->UnselectAll();
1104 m_unconnectedDataView->UnselectAll();
1105 m_footprintsDataView->UnselectAll();
1106
1107 aEvent.Skip();
1108}
1109
1110
1112{
1113 WINDOW_THAWER thawer( m_frame );
1114
1116}
1117
1118
1120{
1121 if( m_Notebook->IsShown() )
1122 {
1123 switch( m_Notebook->GetSelection() )
1124 {
1125 case 0: m_markersTreeModel->PrevMarker(); break;
1126 case 1: m_unconnectedTreeModel->PrevMarker(); break;
1127 case 2: m_fpWarningsTreeModel->PrevMarker(); break;
1128 case 3: break;
1129 }
1130 }
1131}
1132
1133
1135{
1136 if( m_Notebook->IsShown() )
1137 {
1138 switch( m_Notebook->GetSelection() )
1139 {
1140 case 0: m_markersTreeModel->NextMarker(); break;
1141 case 1: m_unconnectedTreeModel->NextMarker(); break;
1142 case 2: m_fpWarningsTreeModel->NextMarker(); break;
1143 case 3: break;
1144 }
1145 }
1146}
1147
1148
1150{
1151 if( m_Notebook->IsShown() )
1152 {
1153 enum MARKER_BASE::MARKER_T markerType = aMarker->GetMarkerType();
1154
1155 if( markerType == MARKER_BASE::MARKER_DRC )
1156 m_Notebook->SetSelection( 0 );
1157 else if( markerType == MARKER_BASE::MARKER_PARITY )
1158 m_Notebook->SetSelection( 2 );
1159
1160 m_markersTreeModel->SelectMarker( aMarker );
1161
1162 CallAfter(
1163 [this, aMarker]
1164 {
1165 m_markersTreeModel->CenterMarker( aMarker );
1166 } );
1167 }
1168}
1169
1170
1172{
1173 if( !m_Notebook->IsShown() || m_Notebook->GetSelection() != 0 )
1174 return;
1175
1176 RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( m_markerDataView->GetCurrentItem() );
1177 PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
1178
1179 if( marker && marker->GetSeverity() != RPT_SEVERITY_EXCLUSION )
1180 {
1181 marker->SetExcluded( true );
1182 bds().m_DrcExclusions.insert( marker->SerializeToString() );
1183 m_frame->GetCanvas()->GetView()->Update( marker );
1184
1185 // Update view
1188 else
1190
1192 refreshEditor();
1193 m_frame->OnModify();
1194 }
1195}
1196
1197
1198void DIALOG_DRC::deleteAllMarkers( bool aIncludeExclusions )
1199{
1200 // Clear current selection list to avoid selection of deleted items
1201 Freeze();
1203
1204 m_markersTreeModel->DeleteItems( false, aIncludeExclusions, false );
1205 m_unconnectedTreeModel->DeleteItems( false, aIncludeExclusions, false );
1206 m_fpWarningsTreeModel->DeleteItems( false, aIncludeExclusions, false );
1207
1208 m_frame->GetBoard()->DeleteMARKERs( true, aIncludeExclusions );
1209 Thaw();
1210}
1211
1212
1213void DIALOG_DRC::OnDeleteOneClick( wxCommandEvent& aEvent )
1214{
1215 if( m_Notebook->GetSelection() == 0 )
1216 {
1217 // Clear the selection. It may be the selected DRC marker.
1219
1221
1222 // redraw the pcb
1223 refreshEditor();
1224 }
1225 else if( m_Notebook->GetSelection() == 1 )
1226 {
1228 }
1229 else if( m_Notebook->GetSelection() == 2 )
1230 {
1232 }
1233
1235}
1236
1237
1238void DIALOG_DRC::OnDeleteAllClick( wxCommandEvent& aEvent )
1239{
1240 static bool s_includeExclusions = false;
1241
1242 int numExcluded = 0;
1243
1244 if( m_markersProvider )
1245 numExcluded += m_markersProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1246
1247 if( m_ratsnestProvider )
1248 numExcluded += m_ratsnestProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1249
1251 numExcluded += m_fpWarningsProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1252
1253 if( numExcluded > 0 )
1254 {
1255 wxMessageDialog dlg( this, _( "Delete exclusions too?" ), _( "Delete All Markers" ),
1256 wxYES_NO | wxCANCEL | wxCENTER | wxICON_QUESTION );
1257 dlg.SetYesNoLabels( _( "Errors and Warnings Only" ),
1258 _( "Errors, Warnings and Exclusions" ) );
1259
1260 int ret = dlg.ShowModal();
1261
1262 if( ret == wxID_CANCEL )
1263 return;
1264 else if( ret == wxID_NO )
1265 s_includeExclusions = true;
1266 }
1267
1268 deleteAllMarkers( s_includeExclusions );
1269 m_drcRun = false;
1270
1271 refreshEditor();
1273}
1274
1275
1277{
1279 DRC_ENGINE* drcEngine = drcTool->GetDRCEngine().get();
1280
1281 // Collect counts:
1282
1283 int numMarkers = 0;
1284 int numUnconnected = 0;
1285 int numFootprints = 0;
1286
1287 int numErrors = 0;
1288 int numWarnings = 0;
1289 int numExcluded = 0;
1290
1291 if( m_markersProvider )
1292 {
1293 numMarkers += m_markersProvider->GetCount();
1294 numErrors += m_markersProvider->GetCount( RPT_SEVERITY_ERROR );
1295 numWarnings += m_markersProvider->GetCount( RPT_SEVERITY_WARNING );
1296 numExcluded += m_markersProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1297 }
1298
1299 if( m_ratsnestProvider )
1300 {
1301 numUnconnected += m_ratsnestProvider->GetCount();
1302 numErrors += m_ratsnestProvider->GetCount( RPT_SEVERITY_ERROR );
1303 numWarnings += m_ratsnestProvider->GetCount( RPT_SEVERITY_WARNING );
1304 numExcluded += m_ratsnestProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1305 }
1306
1308 {
1309 numFootprints += m_fpWarningsProvider->GetCount();
1310 numErrors += m_fpWarningsProvider->GetCount( RPT_SEVERITY_ERROR );
1311 numWarnings += m_fpWarningsProvider->GetCount( RPT_SEVERITY_WARNING );
1312 numExcluded += m_fpWarningsProvider->GetCount( RPT_SEVERITY_EXCLUSION );
1313 }
1314
1315 bool showErrors = m_showErrors->GetValue();
1316 bool showWarnings = m_showWarnings->GetValue();
1317 bool errorsOverflowed = false;
1318 bool warningsOverflowed = false;
1319 bool markersOverflowed = false;
1320 bool unconnectedOverflowed = false;
1321 bool footprintsOverflowed = false;
1322
1323 for( int ii = DRCE_FIRST; ii <= DRCE_LAST; ++ii )
1324 {
1325 const SEVERITY severity = bds().GetSeverity( ii );
1326
1327 if( drcEngine->IsErrorLimitExceeded( ii ) )
1328 {
1329 if( severity == RPT_SEVERITY_ERROR )
1330 errorsOverflowed = true;
1331 else if( severity == RPT_SEVERITY_WARNING )
1332 warningsOverflowed = true;
1333
1334 if( ii == DRCE_UNCONNECTED_ITEMS )
1335 {
1336 if( showWarnings && severity == RPT_SEVERITY_WARNING )
1337 unconnectedOverflowed = true;
1338 else if( showErrors && severity == RPT_SEVERITY_ERROR )
1339 unconnectedOverflowed = true;
1340 }
1341 else if( ii == DRCE_MISSING_FOOTPRINT
1343 || ii == DRCE_EXTRA_FOOTPRINT
1344 || ii == DRCE_NET_CONFLICT
1345 || ii == DRCE_SCHEMATIC_PARITY
1346 || ii == DRCE_FOOTPRINT_FILTERS )
1347 {
1348 if( showWarnings && severity == RPT_SEVERITY_WARNING )
1349 footprintsOverflowed = true;
1350 else if( showErrors && severity == RPT_SEVERITY_ERROR )
1351 footprintsOverflowed = true;
1352 }
1353 else
1354 {
1355 if( showWarnings && severity == RPT_SEVERITY_WARNING )
1356 markersOverflowed = true;
1357 else if( showErrors && severity == RPT_SEVERITY_ERROR )
1358 markersOverflowed = true;
1359 }
1360 }
1361 }
1362
1363 wxString msg;
1364 wxString num;
1365
1366 // Update tab headers:
1367
1368 if( m_drcRun )
1369 {
1370 num.Printf( markersOverflowed ? wxT( "%d+" ) : wxT( "%d" ), numMarkers );
1371 msg.Printf( m_markersTitleTemplate, num );
1372 }
1373 else
1374 {
1376 msg.Replace( wxT( "(%s)" ), wxEmptyString );
1377 }
1378
1379 m_Notebook->SetPageText( 0, msg );
1380
1381 if( m_drcRun )
1382 {
1383 num.Printf( unconnectedOverflowed ? wxT( "%d+" ) : wxT( "%d" ), numUnconnected );
1384 msg.sprintf( m_unconnectedTitleTemplate, num );
1385 }
1386 else
1387 {
1389 msg.Replace( wxT( "(%s)" ), wxEmptyString );
1390 }
1391
1392 m_Notebook->SetPageText( 1, msg );
1393
1395 {
1396 num.Printf( footprintsOverflowed ? wxT( "%d+" ) : wxT( "%d" ), numFootprints );
1397 msg.sprintf( m_footprintsTitleTemplate, num );
1398 }
1399 else if( m_drcRun )
1400 {
1402 msg.Replace( wxT( "%s" ), _( "not run" ) );
1403 }
1404 else
1405 {
1407 msg.Replace( wxT( "(%s)" ), wxEmptyString );
1408 }
1409
1410 m_Notebook->SetPageText( 2, msg );
1411
1412 if( m_drcRun )
1413 {
1414 num.Printf( wxT( "%d" ), m_ignoredList->GetItemCount() );
1415 msg.sprintf( m_ignoredTitleTemplate, num );
1416 }
1417 else
1418 {
1420 msg.Replace( wxT( "(%s)" ), wxEmptyString );
1421 }
1422
1423 m_Notebook->SetPageText( 3, msg );
1424
1425 // Update badges:
1426
1427 if( !m_drcRun && numErrors == 0 )
1428 numErrors = -1;
1429
1430 if( !m_drcRun && numWarnings == 0 )
1431 numWarnings = -1;
1432
1433 m_errorsBadge->SetMaximumNumber( numErrors );
1434 m_errorsBadge->UpdateNumber( errorsOverflowed ? numErrors + 1 : numErrors,
1436
1437 m_warningsBadge->SetMaximumNumber( numWarnings );
1438 m_warningsBadge->UpdateNumber( warningsOverflowed ? numWarnings + 1 : numWarnings,
1440
1441 m_exclusionsBadge->SetMaximumNumber( numExcluded );
1443}
constexpr double PCB_IU_PER_MM
Pcbnew IU is 1 nanometer.
Definition: base_units.h:70
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: actions.h:217
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
void SetLayerVisible(int aLayer, bool isVisible)
BASE_SET & set(size_t pos)
Definition: base_set.h:116
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:317
const LSET & GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:908
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: board.cpp:328
const MARKERS & Markers() const
Definition: board.h:370
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:1258
void UpdateRatsnestExclusions()
Update the visibility flags on the current unconnected ratsnest lines.
Definition: board.cpp:297
void DeleteMARKERs()
Delete all MARKERS from the board.
Definition: board.cpp:1501
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: board.cpp:1281
BOARD_ITEM * ResolveItem(const KIID &aID, bool aAllowNullptrReturn=false) const
Definition: board.cpp:1554
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:520
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
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:216
void OnDRCItemSelected(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:395
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:385
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:72
void OnEditViolationSeverities(wxHyperlinkEvent &aEvent) override
Definition: dialog_drc.cpp:996
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:261
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:252
BOARD * m_currentBoard
Definition: dialog_drc.h:112
void OnDRCItemRClick(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:644
void PrevMarker()
void OnRunDRCClick(wxCommandEvent &aEvent) override
Definition: dialog_drc.cpp:267
wxString m_ignoredTitleTemplate
Definition: dialog_drc.h:121
void OnDRCItemDClick(wxDataViewEvent &aEvent) override
Definition: dialog_drc.cpp:629
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
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:969
void OnCancelClick(wxCommandEvent &aEvent) override
void NextMarker()
void OnActivateDlg(wxActivateEvent &aEvent) override
Definition: dialog_drc.cpp:199
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:102
int ShowModal() override
Design Rule Checker object that performs all the DRC tests.
Definition: drc_engine.h:85
DRC_RULE * GetViolatingRule() const
Definition: drc_item.h:164
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities(bool aIncludeDeprecated=false)
Definition: drc_item.h:133
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:118
wxString m_Name
Definition: drc_rule.h:120
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 ClearFocus()
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:259
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:109
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:144
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:37
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:296
static const LSET & AllLayersMask()
Definition: lset.cpp:626
@ MARKER_DRAWING_SHEET
Definition: marker_base.h:56
void SetExcluded(bool aExcluded, const wxString &aComment=wxEmptyString)
Definition: marker_base.h:94
enum MARKER_T GetMarkerType() const
Definition: marker_base.h:91
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
static TOOL_ACTION showRatsnest
Definition: pcb_actions.h:314
wxString GetDesignRulesPath()
Return the absolute path to the design rules file for the currently-loaded board.
APPEARANCE_CONTROLS * GetAppearancePanel()
void FocusOnItem(EDA_ITEM *aItem) override
Focus on a particular canvas item.
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 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:300
wxString SerializeToString() const
Definition: pcb_marker.cpp:98
virtual wxApp & App()
Return a bare naked wxApp which may come from wxPython, SINGLE_TOP, or kicad.exe.
Definition: pgm_base.cpp:174
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:148
void PrevMarker()
Definition: rc_item.cpp:690
void SelectMarker(const MARKER_BASE *aMarker)
Definition: rc_item.cpp:739
static RC_TREE_NODE * ToNode(wxDataViewItem aItem)
Definition: rc_item.h:238
void ValueChanged(RC_TREE_NODE *aNode)
Definition: rc_item.cpp:518
void Update(std::shared_ptr< RC_ITEMS_PROVIDER > aProvider, int aSeverities)
Definition: rc_item.cpp:361
void DeleteItems(bool aCurrentOnly, bool aIncludeExclusions, bool aDeep)
Delete the current item or all items.
Definition: rc_item.cpp:573
void DeleteCurrentItem(bool aDeep)
Definition: rc_item.cpp:567
void CenterMarker(const MARKER_BASE *aMarker)
Definition: rc_item.cpp:754
static KIID ToUUID(wxDataViewItem aItem)
Definition: rc_item.cpp:217
void NextMarker()
Definition: rc_item.cpp:711
std::shared_ptr< RC_ITEM > m_RcItem
Definition: rc_item.h:223
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
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
Definition: vector2d.h:561
void Clear() override
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)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:169
This file is part of the common library.
static bool g_lastDRCRun
Definition: dialog_drc.cpp:66
static int RPT_SEVERITY_ALL
Definition: dialog_drc.cpp:249
static int DEFAULT_SINGLE_COL_WIDTH
Definition: dialog_drc.cpp:63
static BOARD * g_lastDRCBoard
Definition: dialog_drc.cpp:65
static bool g_lastFootprintTestsRun
Definition: dialog_drc.cpp:67
static std::vector< std::pair< wxString, int > > g_lastIgnored
Definition: dialog_drc.cpp:69
#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:112
@ 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
double m_MinimumMarkerSeparationDistance
When finding overlapped marker a minium distance (in mm) between two DRC markers required to mark it ...
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:395
void ForceFocus(wxWindow *aWindow)
Pass the current focus to the window.
Definition: wxgtk/ui.cpp:124
STL namespace.
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:893
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_MARKER_T
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:99
@ 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