KiCad PCB EDA Suite
drc_tool.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) 2020-2021 KiCad Developers, see change_log.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <pcb_edit_frame.h>
25 #include <bitmaps.h>
26 #include <tool/tool_manager.h>
27 #include <tools/pcb_actions.h>
28 #include <tools/pcb_tool_base.h>
29 #include <tools/zone_filler_tool.h>
31 #include <tools/drc_tool.h>
32 #include <kiface_base.h>
33 #include <dialog_drc.h>
34 #include <board_commit.h>
35 #include <board_design_settings.h>
36 #include <progress_reporter.h>
37 #include <drc/drc_engine.h>
40 
42  PCB_TOOL_BASE( "pcbnew.DRCTool" ),
43  m_editFrame( nullptr ),
44  m_pcb( nullptr ),
45  m_drcDialog( nullptr ),
46  m_drcRunning( false )
47 {
48 }
49 
50 
52 {
53 }
54 
55 
57 {
58  m_editFrame = getEditFrame<PCB_EDIT_FRAME>();
59 
60  if( m_pcb != m_editFrame->GetBoard() )
61  {
62  if( m_drcDialog )
64 
67  }
68 }
69 
70 
71 void DRC_TOOL::ShowDRCDialog( wxWindow* aParent )
72 {
73  bool show_dlg_modal = true;
74 
75  // the dialog needs a parent frame. if it is not specified, this is the PCB editor frame
76  // specified in DRC_TOOL class.
77  if( !aParent )
78  {
79  // if any parent is specified, the dialog is modal.
80  // if this is the default PCB editor frame, it is not modal
81  show_dlg_modal = false;
82  aParent = m_editFrame;
83  }
84 
85  Activate();
87 
88  if( !m_drcDialog )
89  {
90  m_drcDialog = new DIALOG_DRC( m_editFrame, aParent );
92 
93  if( show_dlg_modal )
94  m_drcDialog->ShowModal();
95  else
96  m_drcDialog->Show( true );
97  }
98  else // The dialog is just not visible (because the user has double clicked on an error item)
99  {
100  updatePointers();
101  m_drcDialog->Show( true );
102  }
103 }
104 
105 
107 {
108  ShowDRCDialog( nullptr );
109  return 0;
110 }
111 
112 
114 {
115  if( m_drcDialog )
116  return m_drcDialog->IsShown();
117 
118  return false;
119 }
120 
121 
123 {
124  if( m_drcDialog )
125  {
126  m_drcDialog->Destroy();
127  m_drcDialog = nullptr;
128  }
129 }
130 
131 
132 void DRC_TOOL::RunTests( PROGRESS_REPORTER* aProgressReporter, bool aRefillZones,
133  bool aReportAllTrackErrors, bool aTestFootprints )
134 {
135  // One at a time, please.
136  // Note that the main GUI entry points to get here are blocked, so this is really an
137  // insurance policy and as such we make no attempts to queue up the DRC run or anything.
138  if( m_drcRunning )
139  return;
140 
142  BOARD_COMMIT commit( m_editFrame );
144  bool netlistFetched = false;
145  wxWindowDisabler disabler( /* disable everything except: */ m_drcDialog );
146 
147  m_drcRunning = true;
148 
149  if( aRefillZones )
150  {
151  aProgressReporter->AdvancePhase( _( "Refilling all zones..." ) );
152 
153  zoneFiller->FillAllZones( m_drcDialog, aProgressReporter );
154  }
155 
156  m_drcEngine->SetDrawingSheet( m_editFrame->GetCanvas()->GetDrawingSheet());
157 
158  if( aTestFootprints && !Kiface().IsSingle() )
159  {
160  if( m_editFrame->FetchNetlistFromSchematic( netlist, _( "Schematic parity tests require a "
161  "fully annotated schematic." ) ) )
162  {
163  netlistFetched = true;
164  }
165 
166  if( m_drcDialog )
167  m_drcDialog->Raise();
168 
169  m_drcEngine->SetSchematicNetlist( &netlist );
170  }
171 
172  m_drcEngine->SetProgressReporter( aProgressReporter );
173 
174  m_drcEngine->SetViolationHandler(
175  [&]( const std::shared_ptr<DRC_ITEM>& aItem, wxPoint aPos )
176  {
177  if( aItem->GetErrorCode() == DRCE_MISSING_FOOTPRINT
178  || aItem->GetErrorCode() == DRCE_DUPLICATE_FOOTPRINT
179  || aItem->GetErrorCode() == DRCE_EXTRA_FOOTPRINT
180  || aItem->GetErrorCode() == DRCE_NET_CONFLICT )
181  {
182  m_footprints.push_back( aItem );
183  }
184  else if( aItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
185  {
186  m_unconnected.push_back( aItem );
187  }
188  else
189  {
190  PCB_MARKER* marker = new PCB_MARKER( aItem, aPos );
191  commit.Add( marker );
192  }
193  } );
194 
195  m_drcEngine->RunTests( m_editFrame->GetUserUnits(), aReportAllTrackErrors, aTestFootprints );
196 
197  m_drcEngine->SetProgressReporter( nullptr );
198  m_drcEngine->ClearViolationHandler();
199 
200  if( m_drcDialog )
201  {
203 
204  if( aTestFootprints && netlistFetched )
206  }
207 
208  commit.Push( _( "DRC" ), false, false );
209 
210  m_drcRunning = false;
211 
212  // update the m_drcDialog listboxes
213  updatePointers();
214 }
215 
216 
218 {
219  // update my pointers, m_editFrame is the only unchangeable one
221 
223 
224  if( m_drcDialog ) // Use diag list boxes only in DRC_TOOL dialog
225  {
228  &m_unconnected ) );
230  &m_footprints ) );
231  }
232 }
233 
234 
235 int DRC_TOOL::PrevMarker( const TOOL_EVENT& aEvent )
236 {
237  if( m_drcDialog )
238  {
239  m_drcDialog->Show( true );
240  m_drcDialog->Raise();
242  }
243  else
244  {
245  ShowDRCDialog( nullptr );
246  }
247 
248  return 0;
249 }
250 
251 
252 int DRC_TOOL::NextMarker( const TOOL_EVENT& aEvent )
253 {
254  if( m_drcDialog )
255  {
256  m_drcDialog->Show( true );
257  m_drcDialog->Raise();
259  }
260  else
261  {
262  ShowDRCDialog( nullptr );
263  }
264 
265  return 0;
266 }
267 
268 
269 int DRC_TOOL::CrossProbe( const TOOL_EVENT& aEvent )
270 {
271  if( m_drcDialog )
272  {
274  PCB_SELECTION& selection = selectionTool->GetSelection();
275 
276  if( selection.GetSize() == 1 && selection.Front()->Type() == PCB_MARKER_T )
277  {
278  if( !m_drcDialog->IsShown() )
279  m_drcDialog->Show( true );
280 
281  m_drcDialog->SelectMarker( static_cast<PCB_MARKER*>( selection.Front() ) );
282  }
283  }
284 
285  return 0;
286 }
287 
288 
289 void DRC_TOOL::CrossProbe( const PCB_MARKER* aMarker )
290 {
291  if( !IsDRCDialogShown() )
292  ShowDRCDialog( nullptr );
293 
294  m_drcDialog->SelectMarker( aMarker );
295 }
296 
297 
299 {
300  if( m_drcDialog )
302 
303  return 0;
304 }
305 
306 
308 {
314 }
315 
316 
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
int NextMarker(const TOOL_EVENT &aEvent)
Definition: drc_tool.cpp:252
void NextMarker()
Definition: dialog_drc.cpp:765
static const TOOL_EVENT SelectedEvent
Definition: actions.h:200
RATSNEST_DRC_ITEMS_PROVIDER.
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
A progress reporter interface for use in multi-threaded environments.
DRC_TOOL()
Definition: drc_tool.cpp:41
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void ResolveDRCExclusions()
Update markers to match recorded exclusions.
int ExcludeMarker(const TOOL_EVENT &aEvent)
Definition: drc_tool.cpp:298
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
PCB_EDIT_FRAME * m_editFrame
Definition: drc_tool.h:109
BOARD * m_pcb
Definition: drc_tool.h:110
void PrevMarker()
Definition: dialog_drc.cpp:751
static TOOL_ACTION nextMarker
Definition: actions.h:86
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
std::shared_ptr< DRC_ENGINE > m_drcEngine
Definition: drc_tool.h:114
bool m_drcRunning
Definition: drc_tool.h:112
void SetDrcRun()
Definition: dialog_drc.h:51
void ShowDRCDialog(wxWindow *aParent)
Opens the DRC dialog.
Definition: drc_tool.cpp:71
bool FetchNetlistFromSchematic(NETLIST &aNetlist, const wxString &aAnnotateMessage)
void ExcludeMarker()
Definition: dialog_drc.cpp:802
void SetFootprintTestsRun()
Definition: dialog_drc.h:52
static TOOL_ACTION excludeMarker
Definition: actions.h:87
void setTransitions() override
< Set up handlers for various events.
Definition: drc_tool.cpp:307
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
DS_PROXY_VIEW_ITEM * GetDrawingSheet() const
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
Definition: drc_tool.cpp:56
PCB_SELECTION & GetSelection()
Return the set of currently selected items.
void FillAllZones(wxWindow *aCaller, PROGRESS_REPORTER *aReporter=nullptr)
Handle actions specific to filling copper zones.
const PCB_SELECTION & selection() const
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
Definition: pcb_netlist.h:206
virtual void AdvancePhase()=0
Use the next available virtual zone of the dialog progress bar.
BOARD_DRC_ITEMS_PROVIDER is an implementation of the RC_ITEMS_PROVIDER interface which uses a BOARD i...
Generic, UI-independent tool event.
Definition: tool_event.h:152
void SetFootprintsProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: dialog_drc.cpp:302
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc_tool.cpp:217
#define _(s)
DIALOG_DRC * m_drcDialog
Definition: drc_tool.h:111
bool Show(bool show) override
void RunTests(PROGRESS_REPORTER *aProgressReporter, bool aRefillZones, bool aReportAllTrackErrors, bool aTestFootprints)
Run the DRC tests.
Definition: drc_tool.cpp:132
static TOOL_ACTION prevMarker
Definition: actions.h:85
bool IsDRCDialogShown()
Check to see if the DRC_TOOL dialog is currently shown.
Definition: drc_tool.cpp:113
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition: selection.h:88
void SetMarkersProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: dialog_drc.cpp:286
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:98
std::vector< std::shared_ptr< DRC_ITEM > > m_footprints
Definition: drc_tool.h:117
The selection tool: currently supports:
static TOOL_ACTION runDRC
Definition: pcb_actions.h:342
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:77
void SelectMarker(const PCB_MARKER *aMarker)
Definition: dialog_drc.cpp:779
void Activate()
Run the tool.
int CrossProbe(const TOOL_EVENT &aEvent)
Definition: drc_tool.cpp:269
int PrevMarker(const TOOL_EVENT &aEvent)
Definition: drc_tool.cpp:235
BOARD * GetBoard() const
void DestroyDRCDialog()
Close and free the DRC dialog.
Definition: drc_tool.cpp:122
std::vector< std::shared_ptr< DRC_ITEM > > m_unconnected
Definition: drc_tool.h:116
~DRC_TOOL()
Definition: drc_tool.cpp:51
VECTOR_DRC_ITEMS_PROVIDER is an implementation of the interface named DRC_ITEMS_PROVIDER which uses a...
void SetUnconnectedProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: dialog_drc.cpp:294
bool IsSingle() const
Is this KIFACE running under single_top?
Definition: kiface_base.h:104
std::shared_ptr< DRC_ENGINE > m_DRCEngine
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
EDA_ITEM * Front() const
Definition: selection.h:145
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:112