KiCad PCB EDA Suite
pcbnew_scripting_helpers.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) 2012 NBEE Embedded Systems, Miguel Angel Ajo <miguelangel@nbee.es>
5  * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
30 #include <Python.h>
31 #undef HAVE_CLOCK_GETTIME // macro is defined in Python.h and causes redefine warning
32 
33 #include <action_plugin.h>
34 #include <class_board.h>
35 #include <class_marker_pcb.h>
36 #include <cstdlib>
37 #include <drc/drc_engine.h>
38 #include <drc/drc_item.h>
39 #include <fp_lib_table.h>
40 #include <io_mgr.h>
41 #include <kicad_string.h>
43 #include <project.h>
47 
49 
51 
53 static wxApp* s_WxApp = nullptr;
54 
55 
56 wxApp* GetApp()
57 {
58  if( !s_WxApp )
59  s_WxApp = new wxApp();
60 
61  return s_WxApp;
62 }
63 
64 
66 {
67  if( s_PcbEditFrame )
68  return s_PcbEditFrame->GetBoard();
69  else
70  return NULL;
71 }
72 
73 
75 {
76  s_PcbEditFrame = aPcbEditFrame;
77 }
78 
79 
80 BOARD* LoadBoard( wxString& aFileName )
81 {
82  if( aFileName.EndsWith( wxT( ".kicad_pcb" ) ) )
83  return LoadBoard( aFileName, IO_MGR::KICAD_SEXP );
84 
85  else if( aFileName.EndsWith( wxT( ".brd" ) ) )
86  return LoadBoard( aFileName, IO_MGR::LEGACY );
87 
88  // as fall back for any other kind use the legacy format
89  return LoadBoard( aFileName, IO_MGR::LEGACY );
90 }
91 
92 
94 {
95  if( !s_SettingsManager )
96  {
97  // Ensure wx system settings stuff is available
98  GetApp();
99  s_SettingsManager = new SETTINGS_MANAGER( true );
100  }
101 
102  return s_SettingsManager;
103 }
104 
105 
107 {
108  PROJECT* project = GetSettingsManager()->GetProject( "" );
109 
110  if( !project )
111  {
113  project = GetSettingsManager()->GetProject( "" );
114  }
115 
116  return project;
117 }
118 
119 
120 BOARD* LoadBoard( wxString& aFileName, IO_MGR::PCB_FILE_T aFormat )
121 {
122  wxFileName pro = aFileName;
123  pro.SetExt( ProjectFileExtension );
124  pro.MakeAbsolute();
125  wxString projectPath = pro.GetFullPath();
126 
127  PROJECT* project = GetSettingsManager()->GetProject( projectPath );
128 
129  if( !project )
130  {
131  GetSettingsManager()->LoadProject( projectPath );
132  project = GetSettingsManager()->GetProject( projectPath );
133  }
134 
135  // Board cannot be loaded without a project, so create the default project
136  if( !project )
137  project = GetDefaultProject();
138 
139  BOARD* brd = IO_MGR::Load( aFormat, aFileName );
140 
141  if( brd )
142  {
143  brd->SetProject( project );
144 
145  // Move legacy view settings to local project settings
146  if( !brd->m_LegacyVisibleLayers.test( Rescue ) )
148 
151 
153  bds.m_DRCEngine = std::make_shared<DRC_ENGINE>( brd, &bds );
154 
155  try
156  {
157  wxFileName rules = pro;
158  rules.SetExt( DesignRulesFileExtension );
159  bds.m_DRCEngine->InitEngine( rules );
160  }
161  catch( ... )
162  {
163  // Best efforts...
164  }
165 
166  for( MARKER_PCB* marker : brd->ResolveDRCExclusions() )
167  brd->Add( marker );
168 
169  brd->BuildConnectivity();
170  brd->BuildListOfNets();
172  }
173 
174  return brd;
175 }
176 
177 
179 {
180  BOARD* brd = new BOARD();
181 
182  brd->SetProject( GetDefaultProject() );
183 
184  return brd;
185 }
186 
187 
188 bool SaveBoard( wxString& aFileName, BOARD* aBoard, IO_MGR::PCB_FILE_T aFormat )
189 {
190  aBoard->BuildConnectivity();
192 
193  IO_MGR::Save( aFormat, aFileName, aBoard, NULL );
194 
195  wxFileName pro = aFileName;
196  pro.SetExt( ProjectFileExtension );
197  pro.MakeAbsolute();
198  wxString projectPath = pro.GetFullPath();
199 
200  GetSettingsManager()->SaveProject( pro.GetFullPath() );
201 
202  return true;
203 }
204 
205 
206 bool SaveBoard( wxString& aFileName, BOARD* aBoard )
207 {
208  return SaveBoard( aFileName, aBoard, IO_MGR::KICAD_SEXP );
209 }
210 
211 
213 {
214  BOARD* board = GetBoard();
215 
216  if( !board )
217  return nullptr;
218 
219  PROJECT* project = board->GetProject();
220 
221  if( !project )
222  return nullptr;
223 
224  return project->PcbFootprintLibs();
225 }
226 
227 
228 wxArrayString GetFootprintLibraries()
229 {
230  wxArrayString footprintLibraryNames;
231 
233 
234  if( !tbl )
235  return footprintLibraryNames;
236 
237  for( const wxString& name : tbl->GetLogicalLibs() )
238  footprintLibraryNames.Add( name );
239 
240  return footprintLibraryNames;
241 }
242 
243 
244 wxArrayString GetFootprints( const wxString& aNickName )
245 {
246  wxArrayString footprintNames;
247 
249 
250  if( !tbl )
251  return footprintNames;
252 
253  tbl->FootprintEnumerate( footprintNames, aNickName, true );
254 
255  return footprintNames;
256 }
257 
258 
259 bool ExportSpecctraDSN( wxString& aFullFilename )
260 {
261  if( s_PcbEditFrame )
262  {
263  bool ok = s_PcbEditFrame->ExportSpecctraFile( aFullFilename );
264  return ok;
265  }
266  else
267  {
268  return false;
269  }
270 }
271 
272 bool ExportVRML( const wxString& aFullFileName, double aMMtoWRMLunit,
273  bool aExport3DFiles, bool aUseRelativePaths,
274  bool aUsePlainPCB, const wxString& a3D_Subdir,
275  double aXRef, double aYRef )
276 {
277  if( s_PcbEditFrame )
278  {
279  bool ok = s_PcbEditFrame->ExportVRML_File( aFullFileName, aMMtoWRMLunit,
280  aExport3DFiles, aUseRelativePaths,
281  aUsePlainPCB, a3D_Subdir, aXRef, aYRef );
282  return ok;
283  }
284  else
285  {
286  return false;
287  }
288 }
289 
290 bool ImportSpecctraSES( wxString& aFullFilename )
291 {
292  if( s_PcbEditFrame )
293  {
294  bool ok = s_PcbEditFrame->ImportSpecctraSession( aFullFilename );
295  return ok;
296  }
297  else
298  {
299  return false;
300  }
301 }
302 
303 
304 bool HarvestFootprintsToLibrary( bool aStoreInNewLib, const wxString& aLibName, wxString* aLibPath )
305 {
306  if( s_PcbEditFrame )
307  {
308  s_PcbEditFrame->HarvestFootprintsToLibrary( aStoreInNewLib, aLibName, aLibPath );
309  return true;
310  }
311  else
312  {
313  return false;
314  }
315 }
316 
317 void Refresh()
318 {
319  if( s_PcbEditFrame )
320  {
321  auto board = s_PcbEditFrame->GetBoard();
322  board->BuildConnectivity();
323 
324  // Re-init everything: this is the easy way to do that
327  }
328 }
329 
330 
332 {
333  if( s_PcbEditFrame )
335 }
336 
337 
339 {
340  if( s_PcbEditFrame )
341  return static_cast<int>( s_PcbEditFrame->GetUserUnits() );
342 
343  return -1;
344 }
345 
346 
348 {
350 }
351 
352 
353 bool WriteDRCReport( BOARD* aBoard, const wxString& aFileName, EDA_UNITS aUnits,
354  bool aTestTracksAgainstZones, bool aReportAllTrackErrors )
355 {
356  wxCHECK( aBoard, false );
357 
358  BOARD_DESIGN_SETTINGS& bds = aBoard->GetDesignSettings();
359  std::shared_ptr<DRC_ENGINE> engine = bds.m_DRCEngine;
360 
361  if( !engine )
362  {
363  bds.m_DRCEngine = std::make_shared<DRC_ENGINE>( aBoard, &bds );
364  engine = bds.m_DRCEngine;
365  }
366 
367  wxCHECK( engine, false );
368 
369  wxFileName fn = aBoard->GetFileName();
370  fn.SetExt( DesignRulesFileExtension );
371  wxString drcRulesPath = s_SettingsManager->Prj().AbsolutePath( fn.GetFullName() );
372 
373  try
374  {
375  engine->InitEngine( drcRulesPath );
376  }
377  catch( PARSE_ERROR& pe )
378  {
379  return false;
380  }
381 
382  std::vector<std::shared_ptr<DRC_ITEM>> footprints;
383  std::vector<std::shared_ptr<DRC_ITEM>> unconnected;
384  std::vector<std::shared_ptr<DRC_ITEM>> violations;
385 
386  engine->SetProgressReporter( nullptr );
387 
388  engine->SetViolationHandler(
389  [&]( const std::shared_ptr<DRC_ITEM>& aItem, wxPoint aPos )
390  {
391  if( aItem->GetErrorCode() == DRCE_MISSING_FOOTPRINT
392  || aItem->GetErrorCode() == DRCE_DUPLICATE_FOOTPRINT
393  || aItem->GetErrorCode() == DRCE_EXTRA_FOOTPRINT
394  || aItem->GetErrorCode() == DRCE_NET_CONFLICT )
395  {
396  footprints.push_back( aItem );
397  }
398  else if( aItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
399  {
400  unconnected.push_back( aItem );
401  }
402  else
403  {
404  violations.push_back( aItem );
405  }
406  } );
407 
408  engine->RunTests( aUnits, aTestTracksAgainstZones, aReportAllTrackErrors, false );
409  engine->ClearViolationHandler();
410 
411  // TODO: Unify this with DIALOG_DRC::writeReport
412 
413  FILE* fp = wxFopen( aFileName, wxT( "w" ) );
414 
415  if( fp == nullptr )
416  return false;
417 
418  std::map<KIID, EDA_ITEM*> itemMap;
419  aBoard->FillItemMap( itemMap );
420 
421  fprintf( fp, "** Drc report for %s **\n", TO_UTF8( aBoard->GetFileName() ) );
422 
423  wxDateTime now = wxDateTime::Now();
424 
425  fprintf( fp, "** Created on %s **\n", TO_UTF8( now.Format( wxT( "%F %T" ) ) ) );
426 
427  fprintf( fp, "\n** Found %d DRC violations **\n", static_cast<int>( violations.size() ) );
428 
429  for( const std::shared_ptr<DRC_ITEM>& item : violations )
430  {
431  SEVERITY severity = static_cast<SEVERITY>( bds.GetSeverity( item->GetErrorCode() ) );
432  fprintf( fp, "%s", TO_UTF8( item->ShowReport( aUnits, severity, itemMap ) ) );
433  }
434 
435  fprintf( fp, "\n** Found %d unconnected pads **\n", static_cast<int>( unconnected.size() ) );
436 
437  for( const std::shared_ptr<DRC_ITEM>& item : unconnected )
438  {
439  SEVERITY severity = static_cast<SEVERITY>( bds.GetSeverity( item->GetErrorCode() ) );
440  fprintf( fp, "%s", TO_UTF8( item->ShowReport( aUnits, severity, itemMap ) ) );
441  }
442 
443  fprintf( fp, "\n** Found %d Footprint errors **\n", static_cast<int>( footprints.size() ) );
444 
445  for( const std::shared_ptr<DRC_ITEM>& item : footprints )
446  {
447  SEVERITY severity = static_cast<SEVERITY>( bds.GetSeverity( item->GetErrorCode() ) );
448  fprintf( fp, "%s", TO_UTF8( item->ShowReport( aUnits, severity, itemMap ) ) );
449  }
450 
451  fprintf( fp, "\n** End of Report **\n" );
452  fclose( fp );
453 
454  return true;
455 }
void UpdateUserInterface()
Update the layer manager and other widgets from the board setup (layer and items visibility,...
LSET m_VisibleLayers
Board settings.
BOARD * LoadBoard(wxString &aFileName)
void BuildListOfNets()
Definition: class_board.h:705
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
static bool IsActionRunning()
Function IsActionRunning.
PROJECT holds project specific data.
Definition: project.h:63
void HarvestFootprintsToLibrary(bool aStoreInNewLib, const wxString &aLibName=wxEmptyString, wxString *aLibPath=NULL)
Function HarvestFootprintsToLibrary Save footprints in a library:
int GetUserUnits()
Returns the currently selected user unit value for the interface.
const std::string ProjectFileExtension
VTBL_ENTRY PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:149
SEVERITY
Definition: ui_common.h:76
void ActivateGalCanvas() override
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
const std::string DesignRulesFileExtension
bool WriteDRCReport(BOARD *aBoard, const wxString &aFileName, EDA_UNITS aUnits, bool aTestTracksAgainstZones, bool aReportAllTrackErrors)
Runs the DRC check on the given board and writes the results to a report file.
wxArrayString GetFootprints(const wxString &aNickName)
will get the names of all of the footprints available in a footprint library
PROJECT * GetProject() const
Definition: class_board.h:397
bool HarvestFootprintsToLibrary(bool aStoreInNewLib, const wxString &aLibName, wxString *aLibPath)
Function HarvestFootprintsToLibrary Save footprints in a library:
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:558
This is the end of the layers used for visibility bit masks in Pcbnew There can be at most 32 layers ...
void ScriptingSetPcbEditFrame(PCB_EDIT_FRAME *aPcbEditFrame)
std::vector< MARKER_PCB * > ResolveDRCExclusions()
Rebuild DRC markers from the serialized data in BOARD_DESIGN_SETTINGS.
const wxString & GetFileName() const
Definition: class_board.h:279
VTBL_ENTRY const wxString AbsolutePath(const wxString &aFileName) const
Function AbsolutePath fixes up aFileName if it is relative to the project's directory to be an absolu...
Definition: project.cpp:269
bool IsActionRunning()
Are we currently in an action plugin?
wxArrayString GetFootprintLibraries()
will get the nicknames of all of the footprint libraries configured in pcbnew in both the project and...
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:95
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aNickname, bool aBestEfforts)
Return a list of footprint names contained within the library given by aNickname.
void SynchronizeNetsAndNetClasses()
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Markers used to show a drc problem on boards.
static wxApp * s_WxApp
A valid app is needed for preventing some asserts when opening the settings manager.
GAL_SET m_VisibleItems
The GAL layers (aka items) that are turned on for viewing (.
#define NULL
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
#define GAL_LAYER_INDEX(x)
Use this macro to convert a GAL layer to a 0-indexed offset from LAYER_VIAS.
static SETTINGS_MANAGER * s_SettingsManager
static BOARD * Load(PCB_FILE_T aFileType, const wxString &aFileName, BOARD *aAppendToMe=NULL, const PROPERTIES *aProperties=NULL)
Function Load finds the requested PLUGIN and if found, calls the PLUGIN->Load(..) funtion on it using...
Definition: io_mgr.cpp:177
bool ImportSpecctraSES(wxString &aFullFilename)
will import a specctra *.ses file and use it to relocate MODULEs and to replace all vias and tracks i...
Definition of file extensions used in Kicad.
wxApp * GetApp()
void BuildConnectivity()
Builds or rebuilds the board connectivity database for the board, especially the list of connected it...
void UpdateUserInterface()
Update the layer manager and other widgets from the board setup (layer and items visibility,...
FP_LIB_TABLE * GetFootprintLibraryTable()
bool ExportSpecctraDSN(wxString &aFullFilename)
will export the current BOARD to a specctra dsn file.
SETTINGS_MANAGER * GetSettingsManager()
bool ExportVRML(const wxString &aFullFileName, double aMMtoWRMLunit, bool aExport3DFiles, bool aUseRelativePaths, bool aUsePlainPCB, const wxString &a3D_Subdir, double aXRef, double aYRef)
will export the current BOARD to a VRML (wrl) file.
PROJECT * GetDefaultProject()
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...
BOARD * GetBoard()
VTBL_ENTRY FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition: project.cpp:283
EDA_UNITS
Definition: eda_units.h:38
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Loads a project or sets up a new project with a specified path.
void SetProject(PROJECT *aProject)
Links a board to a given project.
static void Save(PCB_FILE_T aFileType, const wxString &aFileName, BOARD *aBoard, const PROPERTIES *aProperties=NULL)
Function Save will write either a full aBoard to a storage file in a format that this implementation ...
Definition: io_mgr.cpp:192
bool ImportSpecctraSession(const wxString &aFullFilename)
Function ImportSpecctraSession will import a specctra *.ses file and use it to relocate MODULEs and t...
bool SaveBoard(wxString &aFileName, BOARD *aBoard, IO_MGR::PCB_FILE_T aFormat)
Struct PARSE_ERROR contains a filename or source description, a problem input line,...
Definition: ki_exception.h:123
Class PCBNEW_ACTION_PLUGINS.
Legacy Pcbnew file formats prior to s-expression.
Definition: io_mgr.h:56
bool ExportVRML_File(const wxString &aFullFileName, double aMMtoWRMLunit, bool aExport3DFiles, bool aUseRelativePaths, bool aUsePlainPCB, const wxString &a3D_Subdir, double aXRef, double aYRef)
Function ExportVRML_File Creates the file(s) exporting current BOARD to a VRML file.
const char * name
Definition: DXF_plotter.cpp:59
Information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:186
bool SaveProject(const wxString &aFullPath=wxEmptyString)
Saves a loaded project.
PCB_EDIT_FRAME is the main frame for Pcbnew.
BOARD * CreateEmptyBoard()
Constructs a default BOARD with a tempoary (no filename) project.
BOARD * GetBoard() const
int GetSeverity(int aDRCErrorCode)
PCB_FILE_T
Enum PCB_FILE_T is a set of file types that the IO_MGR knows about, and for which there has been a pl...
Definition: io_mgr.h:54
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: class_board.h:313
std::shared_ptr< DRC_ENGINE > m_DRCEngine
PROJECT * GetProject(const wxString &aFullPath) const
Retrieves a loaded project by name.
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
static PCB_EDIT_FRAME * s_PcbEditFrame
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
bool ExportSpecctraFile(const wxString &aFullFilename)
Function ExportSpecctraFile will export the current BOARD to a specctra dsn file.
S-expression Pcbnew file format.
Definition: io_mgr.h:57
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
GAL_SET m_LegacyVisibleItems
Definition: class_board.h:314