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 <board.h>
35 #include <pcb_marker.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( KiCadPcbFileExtension ) )
83  return LoadBoard( aFileName, IO_MGR::KICAD_SEXP );
84  else if( aFileName.EndsWith( LegacyPcbFileExtension ) )
85  return LoadBoard( aFileName, IO_MGR::LEGACY );
86 
87  // as fall back for any other kind use the legacy format
88  return LoadBoard( aFileName, IO_MGR::LEGACY );
89 }
90 
91 
93 {
94  if( !s_SettingsManager )
95  {
96  // Ensure wx system settings stuff is available
97  GetApp();
98  s_SettingsManager = new SETTINGS_MANAGER( true );
99  }
100 
101  return s_SettingsManager;
102 }
103 
104 
106 {
107  PROJECT* project = GetSettingsManager()->GetProject( "" );
108 
109  if( !project )
110  {
112  project = GetSettingsManager()->GetProject( "" );
113  }
114 
115  return project;
116 }
117 
118 
119 BOARD* LoadBoard( wxString& aFileName, IO_MGR::PCB_FILE_T aFormat )
120 {
121  wxFileName pro = aFileName;
122  pro.SetExt( ProjectFileExtension );
123  pro.MakeAbsolute();
124  wxString projectPath = pro.GetFullPath();
125 
126  PROJECT* project = GetSettingsManager()->GetProject( projectPath );
127 
128  if( !project )
129  {
130  GetSettingsManager()->LoadProject( projectPath );
131  project = GetSettingsManager()->GetProject( projectPath );
132  }
133 
134  // Board cannot be loaded without a project, so create the default project
135  if( !project )
136  project = GetDefaultProject();
137 
138  BOARD* brd = IO_MGR::Load( aFormat, aFileName );
139 
140  if( brd )
141  {
142  brd->SetProject( project );
143 
144  // Move legacy view settings to local project settings
145  if( !brd->m_LegacyVisibleLayers.test( Rescue ) )
147 
150 
152  bds.m_DRCEngine = std::make_shared<DRC_ENGINE>( brd, &bds );
153 
154  try
155  {
156  wxFileName rules = pro;
157  rules.SetExt( DesignRulesFileExtension );
158  bds.m_DRCEngine->InitEngine( rules );
159  }
160  catch( ... )
161  {
162  // Best efforts...
163  }
164 
165  for( PCB_MARKER* marker : brd->ResolveDRCExclusions() )
166  brd->Add( marker );
167 
168  brd->BuildConnectivity();
169  brd->BuildListOfNets();
171  }
172 
173  return brd;
174 }
175 
176 
178 {
179  BOARD* brd = new BOARD();
180 
181  brd->SetProject( GetDefaultProject() );
182 
183  return brd;
184 }
185 
186 
187 bool SaveBoard( wxString& aFileName, BOARD* aBoard, IO_MGR::PCB_FILE_T aFormat )
188 {
189  aBoard->BuildConnectivity();
191 
192  IO_MGR::Save( aFormat, aFileName, aBoard, NULL );
193 
194  wxFileName pro = aFileName;
195  pro.SetExt( ProjectFileExtension );
196  pro.MakeAbsolute();
197  wxString projectPath = pro.GetFullPath();
198 
199  GetSettingsManager()->SaveProject( pro.GetFullPath() );
200 
201  return true;
202 }
203 
204 
205 bool SaveBoard( wxString& aFileName, BOARD* aBoard )
206 {
207  return SaveBoard( aFileName, aBoard, IO_MGR::KICAD_SEXP );
208 }
209 
210 
212 {
213  BOARD* board = GetBoard();
214 
215  if( !board )
216  return nullptr;
217 
218  PROJECT* project = board->GetProject();
219 
220  if( !project )
221  return nullptr;
222 
223  return project->PcbFootprintLibs();
224 }
225 
226 
227 wxArrayString GetFootprintLibraries()
228 {
229  wxArrayString footprintLibraryNames;
230 
232 
233  if( !tbl )
234  return footprintLibraryNames;
235 
236  for( const wxString& name : tbl->GetLogicalLibs() )
237  footprintLibraryNames.Add( name );
238 
239  return footprintLibraryNames;
240 }
241 
242 
243 wxArrayString GetFootprints( const wxString& aNickName )
244 {
245  wxArrayString footprintNames;
246 
248 
249  if( !tbl )
250  return footprintNames;
251 
252  tbl->FootprintEnumerate( footprintNames, aNickName, true );
253 
254  return footprintNames;
255 }
256 
257 
258 bool ExportSpecctraDSN( wxString& aFullFilename )
259 {
260  if( s_PcbEditFrame )
261  {
262  bool ok = s_PcbEditFrame->ExportSpecctraFile( aFullFilename );
263  return ok;
264  }
265  else
266  {
267  return false;
268  }
269 }
270 
271 bool ExportVRML( const wxString& aFullFileName, double aMMtoWRMLunit,
272  bool aExport3DFiles, bool aUseRelativePaths,
273  bool aUsePlainPCB, const wxString& a3D_Subdir,
274  double aXRef, double aYRef )
275 {
276  if( s_PcbEditFrame )
277  {
278  bool ok = s_PcbEditFrame->ExportVRML_File( aFullFileName, aMMtoWRMLunit,
279  aExport3DFiles, aUseRelativePaths,
280  aUsePlainPCB, a3D_Subdir, aXRef, aYRef );
281  return ok;
282  }
283  else
284  {
285  return false;
286  }
287 }
288 
289 bool ImportSpecctraSES( wxString& aFullFilename )
290 {
291  if( s_PcbEditFrame )
292  {
293  bool ok = s_PcbEditFrame->ImportSpecctraSession( aFullFilename );
294  return ok;
295  }
296  else
297  {
298  return false;
299  }
300 }
301 
302 
303 bool ExportFootprintsToLibrary( bool aStoreInNewLib, const wxString& aLibName, wxString* aLibPath )
304 {
305  if( s_PcbEditFrame )
306  {
307  s_PcbEditFrame->ExportFootprintsToLibrary( aStoreInNewLib, aLibName, aLibPath );
308  return true;
309  }
310  else
311  {
312  return false;
313  }
314 }
315 
316 void Refresh()
317 {
318  if( s_PcbEditFrame )
319  {
320  auto board = s_PcbEditFrame->GetBoard();
321  board->BuildConnectivity();
322 
323  // Re-init everything: this is the easy way to do that
326  }
327 }
328 
329 
331 {
332  if( s_PcbEditFrame )
334 }
335 
336 
338 {
339  if( s_PcbEditFrame )
340  return static_cast<int>( s_PcbEditFrame->GetUserUnits() );
341 
342  return -1;
343 }
344 
345 
347 {
349 }
350 
351 
352 bool WriteDRCReport( BOARD* aBoard, const wxString& aFileName, EDA_UNITS aUnits,
353  bool aReportAllTrackErrors )
354 {
355  wxCHECK( aBoard, false );
356 
357  BOARD_DESIGN_SETTINGS& bds = aBoard->GetDesignSettings();
358  std::shared_ptr<DRC_ENGINE> engine = bds.m_DRCEngine;
359 
360  if( !engine )
361  {
362  bds.m_DRCEngine = std::make_shared<DRC_ENGINE>( aBoard, &bds );
363  engine = bds.m_DRCEngine;
364  }
365 
366  wxCHECK( engine, false );
367 
368  wxFileName fn = aBoard->GetFileName();
369  fn.SetExt( DesignRulesFileExtension );
370  wxString drcRulesPath = s_SettingsManager->Prj().AbsolutePath( fn.GetFullName() );
371 
372  try
373  {
374  engine->InitEngine( drcRulesPath );
375  }
376  catch( PARSE_ERROR& )
377  {
378  return false;
379  }
380 
381  std::vector<std::shared_ptr<DRC_ITEM>> footprints;
382  std::vector<std::shared_ptr<DRC_ITEM>> unconnected;
383  std::vector<std::shared_ptr<DRC_ITEM>> violations;
384 
385  engine->SetProgressReporter( nullptr );
386 
387  engine->SetViolationHandler(
388  [&]( const std::shared_ptr<DRC_ITEM>& aItem, wxPoint aPos )
389  {
390  if( aItem->GetErrorCode() == DRCE_MISSING_FOOTPRINT
391  || aItem->GetErrorCode() == DRCE_DUPLICATE_FOOTPRINT
392  || aItem->GetErrorCode() == DRCE_EXTRA_FOOTPRINT
393  || aItem->GetErrorCode() == DRCE_NET_CONFLICT )
394  {
395  footprints.push_back( aItem );
396  }
397  else if( aItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
398  {
399  unconnected.push_back( aItem );
400  }
401  else
402  {
403  violations.push_back( aItem );
404  }
405  } );
406 
407  engine->RunTests( aUnits, aReportAllTrackErrors, false );
408  engine->ClearViolationHandler();
409 
410  // TODO: Unify this with DIALOG_DRC::writeReport
411 
412  FILE* fp = wxFopen( aFileName, wxT( "w" ) );
413 
414  if( fp == nullptr )
415  return false;
416 
417  std::map<KIID, EDA_ITEM*> itemMap;
418  aBoard->FillItemMap( itemMap );
419 
420  fprintf( fp, "** Drc report for %s **\n", TO_UTF8( aBoard->GetFileName() ) );
421 
422  wxDateTime now = wxDateTime::Now();
423 
424  fprintf( fp, "** Created on %s **\n", TO_UTF8( now.Format( wxT( "%F %T" ) ) ) );
425 
426  fprintf( fp, "\n** Found %d DRC violations **\n", static_cast<int>( violations.size() ) );
427 
428  for( const std::shared_ptr<DRC_ITEM>& item : violations )
429  {
430  SEVERITY severity = bds.GetSeverity( item->GetErrorCode() );
431  fprintf( fp, "%s", TO_UTF8( item->ShowReport( aUnits, severity, itemMap ) ) );
432  }
433 
434  fprintf( fp, "\n** Found %d unconnected pads **\n", static_cast<int>( unconnected.size() ) );
435 
436  for( const std::shared_ptr<DRC_ITEM>& item : unconnected )
437  {
438  SEVERITY severity = bds.GetSeverity( item->GetErrorCode() );
439  fprintf( fp, "%s", TO_UTF8( item->ShowReport( aUnits, severity, itemMap ) ) );
440  }
441 
442  fprintf( fp, "\n** Found %d Footprint errors **\n", static_cast<int>( footprints.size() ) );
443 
444  for( const std::shared_ptr<DRC_ITEM>& item : footprints )
445  {
446  SEVERITY severity = bds.GetSeverity( item->GetErrorCode() );
447  fprintf( fp, "%s", TO_UTF8( item->ShowReport( aUnits, severity, itemMap ) ) );
448  }
449 
450  fprintf( fp, "\n** End of Report **\n" );
451  fclose( fp );
452 
453  return true;
454 }
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)
bool WriteDRCReport(BOARD *aBoard, const wxString &aFileName, EDA_UNITS aUnits, bool aReportAllTrackErrors)
Runs the DRC check on the given board and writes the results to a report file.
void BuildListOfNets()
Definition: board.h:733
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
static bool IsActionRunning()
Function IsActionRunning.
Container for project specific data.
Definition: project.h:62
int GetUserUnits()
Returns the currently selected user unit value for the interface.
const std::string ProjectFileExtension
const std::string LegacyPcbFileExtension
SEVERITY
Definition: ui_common.h:83
void ActivateGalCanvas() override
Set the #m_Pcb member in such as way as to ensure deleting any previous BOARD.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
const std::string DesignRulesFileExtension
bool ExportFootprintsToLibrary(bool aStoreInNewLib, const wxString &aLibName, wxString *aLibPath)
Function ExportFootprintsToLibrary Save footprints in a library:
wxArrayString GetFootprints(const wxString &aNickName)
will get the names of all of the footprints available in a footprint library
PROJECT * GetProject() const
Definition: board.h:430
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:591
This is the end of the layers used for visibility bit masks in Pcbnew.
const std::string KiCadPcbFileExtension
void ScriptingSetPcbEditFrame(PCB_EDIT_FRAME *aPcbEditFrame)
const wxString & GetFileName() const
Definition: board.h:298
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:151
void ExportFootprintsToLibrary(bool aStoreInNewLib, const wxString &aLibName=wxEmptyString, wxString *aLibPath=NULL)
Save footprints in a library:
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)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
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.
Definition: board.cpp:1413
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: board.cpp:563
std::vector< PCB_MARKER * > ResolveDRCExclusions()
Rebuild DRC markers from the serialized data in BOARD_DESIGN_SETTINGS.
Definition: board.cpp:188
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
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()
SEVERITY GetSeverity(int aDRCErrorCode)
void BuildConnectivity()
Builds or rebuilds the board connectivity database for the board, especially the list of connected it...
Definition: board.cpp:133
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...
static BOARD * Load(PCB_FILE_T aFileType, const wxString &aFileName, BOARD *aAppendToMe=nullptr, const PROPERTIES *aProperties=nullptr, PROJECT *aProject=nullptr)
Find the requested PLUGIN and if found, calls the PLUGIN::Load() function on it using the arguments p...
Definition: io_mgr.cpp:158
BOARD * GetBoard()
virtual FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
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.
Definition: board.cpp:139
bool ImportSpecctraSession(const wxString &aFullFilename)
Import a specctra *.ses file and use it to relocate MODULEs and to replace all vias and tracks in an ...
bool SaveBoard(wxString &aFileName, BOARD *aBoard, IO_MGR::PCB_FILE_T aFormat)
A filename or source description, a problem input line, a line number, a byte offset,...
Definition: ki_exception.h:118
Class PCBNEW_ACTION_PLUGINS.
Legacy Pcbnew file formats prior to s-expression.
Definition: io_mgr.h:54
bool ExportVRML_File(const wxString &aFullFileName, double aMMtoWRMLunit, bool aExport3DFiles, bool aUseRelativePaths, bool aUsePlainPCB, const wxString &a3D_Subdir, double aXRef, double aYRef)
Creates the file(s) exporting current BOARD to a VRML file.
const char * name
Definition: DXF_plotter.cpp:59
static void Save(PCB_FILE_T aFileType, const wxString &aFileName, BOARD *aBoard, const PROPERTIES *aProperties=nullptr)
Write either a full aBoard to a storage file in a format that this implementation knows about,...
Definition: io_mgr.cpp:173
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
bool SaveProject(const wxString &aFullPath=wxEmptyString)
Saves a loaded project.
The main frame for Pcbnew.
BOARD * CreateEmptyBoard()
Constructs a default BOARD with a tempoary (no filename) project.
BOARD * GetBoard() const
PCB_FILE_T
The set of file types that the IO_MGR knows about, and for which there has been a plugin written.
Definition: io_mgr.h:52
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Definition: board.cpp:871
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: board.h:334
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)
Export the current BOARD to a specctra dsn file.
S-expression Pcbnew file format.
Definition: io_mgr.h:55
Container for design settings for a BOARD object.
GAL_SET m_LegacyVisibleItems
Definition: board.h:335