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