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