KiCad PCB EDA Suite
dialog_footprint_checker.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 KiCad Developers, see AUTHORS.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 
26 #include <tool/tool_manager.h>
27 #include <tools/pcb_actions.h>
28 #include <pcb_marker.h>
30 #include <footprint_edit_frame.h>
33 
34 
37  m_frame( aParent ),
38  m_checksRun( false ),
39  m_markersProvider( nullptr ),
41 {
43  m_markersDataView->AssociateModel( m_markersTreeModel );
44 
46 
47  // We use a sdbSizer to get platform-dependent ordering of the action buttons, but
48  // that requires us to correct the button labels here.
49  m_sdbSizerOK->SetLabel( _( "Run Checks" ) );
50  m_sdbSizerCancel->SetLabel( _( "Close" ) );
51 
52  m_sdbSizerOK->SetDefault();
53 
55 
57 }
58 
59 
61 {
62  m_markersTreeModel->DecRef();
63 }
64 
65 
67 {
68  runChecks();
69 
70  return true;
71 }
72 
73 
75 {
76  return true;
77 }
78 
79 
80 // Don't globally define this; different facilities use different definitions of "ALL"
82 
83 
85 {
86  m_showAll->SetValue( m_severities == RPT_SEVERITY_ALL );
90 }
91 
92 
94 {
95  BOARD* board = m_frame->GetBoard();
96  FOOTPRINT* footprint = board->GetFirstFootprint();
97  wxString msg;
98 
100 
101  if( !footprint )
102  {
103  msg = _( "No footprint loaded." );
104  return;
105  }
106 
107  OUTLINE_ERROR_HANDLER errorHandler =
108  [&]( const wxString& aMsg, BOARD_ITEM* aItemA, BOARD_ITEM* aItemB, const wxPoint& aPt )
109  {
110  std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MALFORMED_COURTYARD );
111 
112  drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + aMsg );
113  drcItem->SetItems( aItemA, aItemB );
114 
115  PCB_MARKER* marker = new PCB_MARKER( drcItem, aPt );
116  board->Add( marker );
117  m_frame->GetCanvas()->GetView()->Add( marker );
118  };
119 
120  footprint->BuildPolyCourtyards( &errorHandler );
121 
122  m_checksRun = true;
123 
125 
126  refreshEditor();
127 }
128 
129 
131 {
132  m_markersTreeModel->SetProvider( aProvider );
134 }
135 
136 
137 void DIALOG_FOOTPRINT_CHECKER::OnRunChecksClick( wxCommandEvent& aEvent )
138 {
139  m_checksRun = false;
140 
141  runChecks();
142 }
143 
144 
145 void DIALOG_FOOTPRINT_CHECKER::OnSelectItem( wxDataViewEvent& aEvent )
146 {
147  BOARD* board = m_frame->GetBoard();
148  RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
149  const KIID& itemID = node ? RC_TREE_MODEL::ToUUID( aEvent.GetItem() ) : niluuid;
150  BOARD_ITEM* item = board->GetItem( itemID );
151 
152  if( node && item )
153  {
154  PCB_LAYER_ID principalLayer = item->GetLayer();
155  LSET violationLayers;
156  std::shared_ptr<RC_ITEM> rc_item = node->m_RcItem;
157 
158  if( rc_item->GetErrorCode() == DRCE_MALFORMED_COURTYARD )
159  {
160  BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
161 
162  if( a && ( a->GetFlags() & MALFORMED_B_COURTYARD ) > 0
163  && ( a->GetFlags() & MALFORMED_F_COURTYARD ) == 0 )
164  {
165  principalLayer = B_CrtYd;
166  }
167  else
168  {
169  principalLayer = F_CrtYd;
170  }
171  }
172  else if (rc_item->GetErrorCode() == DRCE_INVALID_OUTLINE )
173  {
174  principalLayer = Edge_Cuts;
175  }
176  else
177  {
178  BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
179  BOARD_ITEM* b = board->GetItem( rc_item->GetAuxItemID() );
180  BOARD_ITEM* c = board->GetItem( rc_item->GetAuxItem2ID() );
181  BOARD_ITEM* d = board->GetItem( rc_item->GetAuxItem3ID() );
182 
183  if( a || b || c || d )
184  violationLayers = LSET::AllLayersMask();
185 
186  if( a )
187  violationLayers &= a->GetLayerSet();
188 
189  if( b )
190  violationLayers &= b->GetLayerSet();
191 
192  if( c )
193  violationLayers &= c->GetLayerSet();
194 
195  if( d )
196  violationLayers &= d->GetLayerSet();
197  }
198 
199  if( violationLayers.count() )
200  principalLayer = violationLayers.Seq().front();
201  else
202  violationLayers.set( principalLayer );
203 
204  WINDOW_THAWER thawer( m_frame );
205 
206  m_frame->FocusOnItem( item );
207  m_frame->GetCanvas()->Refresh();
208 
209  if( ( violationLayers & board->GetVisibleLayers() ) == 0 )
210  {
211  m_frame->GetAppearancePanel()->SetLayerVisible( principalLayer, true );
212  m_frame->GetCanvas()->Refresh();
213  }
214 
215  if( board->GetVisibleLayers().test( principalLayer ) )
216  m_frame->SetActiveLayer( principalLayer );
217  }
218 
219  aEvent.Skip();
220 }
221 
222 
224 {
225  if( m_markersDataView->GetCurrentItem().IsOk() )
226  {
227  // turn control over to m_frame, hide this DIALOG_FOOTPRINT_CHECKER window,
228  // no destruction so we can preserve listbox cursor
229  if( !IsModal() )
230  Show( false );
231  }
232 
233  // Do not skip aVent here: tihs is not useful, and Pcbnew crashes
234  // if skipped (at least on Windows)
235 }
236 
237 
238 void DIALOG_FOOTPRINT_CHECKER::OnSeverity( wxCommandEvent& aEvent )
239 {
240  int flag = 0;
241 
242  if( aEvent.GetEventObject() == m_showAll )
244  else if( aEvent.GetEventObject() == m_showErrors )
246  else if( aEvent.GetEventObject() == m_showWarnings )
248  else if( aEvent.GetEventObject() == m_showExclusions )
250 
251  if( aEvent.IsChecked() )
252  m_severities |= flag;
253  else if( aEvent.GetEventObject() == m_showAll )
255  else
256  m_severities &= ~flag;
257 
258  syncCheckboxes();
259 
260  // Set the provider's severity levels through the TreeModel so that the old tree
261  // can be torn down before the severity changes.
262  //
263  // It's not clear this is required, but we've had a lot of issues with wxDataView
264  // being cranky on various platforms.
265 
267 
269 }
270 
271 
272 void DIALOG_FOOTPRINT_CHECKER::OnCancelClick( wxCommandEvent& aEvent )
273 {
274  m_frame->FocusOnItem( nullptr );
275 
276  SetReturnCode( wxID_CANCEL );
277 
278  // Leave the tool to destroy (or not) the dialog
280  tool->DestroyCheckerDialog();
281 }
282 
283 
284 void DIALOG_FOOTPRINT_CHECKER::OnClose( wxCloseEvent& aEvent )
285 {
286  wxCommandEvent dummy;
287  OnCancelClick( dummy );
288 }
289 
290 
292 {
293  WINDOW_THAWER thawer( m_frame );
294 
295  m_frame->GetCanvas()->Refresh();
296 }
297 
298 
299 void DIALOG_FOOTPRINT_CHECKER::OnDeleteOneClick( wxCommandEvent& aEvent )
300 {
301  // Clear the selection. It may be the selected DRC marker.
303 
305 
306  // redraw the pcb
307  refreshEditor();
308 
310 }
311 
312 
313 void DIALOG_FOOTPRINT_CHECKER::OnDeleteAllClick( wxCommandEvent& event )
314 {
316 
317  m_checksRun = false;
318  refreshEditor();
320 }
321 
322 
324 {
325  // Clear current selection list to avoid selection of deleted items
327 
328  m_markersTreeModel->DeleteItems( false, true, true );
329 }
330 
331 
333 {
334  // Collect counts:
335 
336  int numErrors = 0;
337  int numWarnings = 0;
338  int numExcluded = 0;
339 
340  if( m_markersProvider )
341  {
345  }
346 
347  // Update badges:
348 
349  if( !m_checksRun && numErrors == 0 )
350  numErrors = -1;
351 
352  if( !m_checksRun && numWarnings == 0 )
353  numWarnings = -1;
354 
355  m_errorsBadge->SetMaximumNumber( numErrors );
357 
358  m_warningsBadge->SetMaximumNumber( numWarnings );
360 
361  m_exclusionsBadge->SetMaximumNumber( numExcluded );
363 }
364 
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:63
void BuildPolyCourtyards(OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Build complex polygons of the courtyard areas from graphic items on the courtyard layers.
Definition: footprint.cpp:1931
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:815
void DeleteItems(bool aCurrentOnly, bool aIncludeExclusions, bool aDeep)
Deletes the current item or all items.
Definition: rc_item.cpp:438
Module editor specific tools.
KIID niluuid(0)
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition: drc_item.cpp:245
void OnDeleteAllClick(wxCommandEvent &event) override
void SetProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: rc_item.cpp:264
void SetActiveLayer(PCB_LAYER_ID aLayer) override
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
static int RPT_SEVERITY_ALL
void OnDeleteOneClick(wxCommandEvent &event) override
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void UpdateNumber(int aNumber, SEVERITY aSeverity)
Update the number displayed on the badge.
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings Returns a bit-mask of all t...
Definition: board.cpp:461
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:141
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
Definition: sch_symbol.cpp:69
functions to convert a shape built with DRAWSEGMENTS to a polygon.
static KIID ToUUID(wxDataViewItem aItem)
Definition: rc_item.cpp:119
FOOTPRINT_EDIT_FRAME * m_frame
virtual int GetCount(int aSeverity=-1) const =0
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:411
APPEARANCE_CONTROLS * GetAppearancePanel()
void OnClose(wxCloseEvent &event) override
void DeleteCurrentItem(bool aDeep)
Definition: rc_item.cpp:432
RC_ITEMS_PROVIDER * m_markersProvider
void SetSeverities(int aSeverities)
Definition: rc_item.cpp:270
Provide an abstract interface of a RC_ITEM* list manager.
Definition: rc_item.h:43
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: board.cpp:563
Definition: kiid.h:44
PCB_LAYER_ID
A quick note on layer IDs:
LSET is a set of PCB_LAYER_IDs.
std::shared_ptr< RC_ITEM > m_RcItem
Definition: rc_item.h:205
#define MALFORMED_B_COURTYARD
Definition: eda_item.h:125
FOOTPRINT * GetFirstFootprint() const
Gets the first footprint on the board or nullptr.
Definition: board.h:382
static RC_TREE_NODE * ToNode(wxDataViewItem aItem)
Definition: rc_item.h:220
BOARD_DRC_ITEMS_PROVIDER is an implementation of the RC_ITEMS_PROVIDER interface which uses a BOARD i...
void OnRunChecksClick(wxCommandEvent &aEvent) override
static LSET AllLayersMask()
Definition: lset.cpp:787
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
bool Show(bool show) override
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
#define MALFORMED_F_COURTYARD
Definition: eda_item.h:124
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
Class DIALOG_FOOTPRINT_CHECKER_BASE.
void OnSelectItem(wxDataViewEvent &event) override
void SetMarkersProvider(RC_ITEMS_PROVIDER *aProvider)
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
#define _(s)
Definition: 3d_actions.cpp:33
void OnCancelClick(wxCommandEvent &aEvent) override
DIALOG_FOOTPRINT_CHECKER(FOOTPRINT_EDIT_FRAME *aParent)
void OnSeverity(wxCommandEvent &aEvent) override
const std::function< void(const wxString &msg, BOARD_ITEM *itemA, BOARD_ITEM *itemB, const wxPoint &pt)> OUTLINE_ERROR_HANDLER
void SetLayerVisible(LAYER_NUM aLayer, bool isVisible)
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Add a VIEW_ITEM to the view.
Definition: pcb_view.cpp:58
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
BOARD * GetBoard() const
void OnLeftDClickItem(wxMouseEvent &event) override
STATUS_FLAGS GetFlags() const
Definition: eda_item.h:205
void SetMaximumNumber(int aMax)
Set the maximum number to be shown on the badge.
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:173
void FocusOnItem(BOARD_ITEM *aItem)
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:178