KiCad PCB EDA Suite
pcbnew.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) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 1992-2019 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 
32 #include <pgm_base.h>
33 #include <kiface_i.h>
34 #include <kiface_ids.h>
35 #include <confirm.h>
36 #include <pcb_edit_frame.h>
37 #include <eda_dde.h>
38 #include <macros.h>
39 #include <wx/file.h>
40 #include <wx/log.h>
41 #include <wx/snglinst.h>
42 #include <gestfich.h>
43 #include <paths.h>
44 #include <pcbnew.h>
45 #include <pcbnew_settings.h>
47 #include <class_draw_panel_gal.h>
48 #include <fp_lib_table.h>
49 #include <footprint_edit_frame.h>
50 #include <footprint_viewer_frame.h>
51 #include <footprint_wizard_frame.h>
53 #include <footprint_info_impl.h>
55 #include <paths.h>
56 #include <python_scripting.h>
57 
58 #include "invoke_pcb_dialog.h"
61 
62 
63 /* init functions defined by swig */
64 
65 extern "C" PyObject* PyInit__pcbnew( void );
66 
67 namespace PCB {
68 
69 static struct IFACE : public KIFACE_I
70 {
71  // Of course all are virtual overloads, implementations of the KIFACE.
72 
73  IFACE( const char* aName, KIWAY::FACE_T aType ) :
74  KIFACE_I( aName, aType )
75  {}
76 
77  bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) override;
78 
79  void OnKifaceEnd() override;
80 
81  wxWindow* CreateWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway, int aCtlBits = 0 ) override
82  {
83  switch( aClassId )
84  {
85  case FRAME_PCB_EDITOR:
86  {
87  auto frame = new PCB_EDIT_FRAME( aKiway, aParent );
88 
89  // give the scripting helpers access to our frame
90  ScriptingSetPcbEditFrame( frame );
91 
92  if( Kiface().IsSingle() )
93  {
94  // only run this under single_top, not under a project manager.
95  frame->CreateServer( KICAD_PCB_PORT_SERVICE_NUMBER );
96  }
97 
98  return frame;
99  }
100 
102  return new FOOTPRINT_EDIT_FRAME( aKiway, aParent,
104 
107  return new FOOTPRINT_VIEWER_FRAME( aKiway, aParent, FRAME_T( aClassId ) );
108 
110  return new FOOTPRINT_WIZARD_FRAME( aKiway, aParent, FRAME_T( aClassId ) );
111 
113  return dynamic_cast< wxWindow* >( FOOTPRINT_PREVIEW_PANEL::New( aKiway, aParent ) );
114 
116  {
117  DIALOG_CONFIGURE_PATHS dlg( aParent, aKiway->Prj().Get3DFilenameResolver() );
118 
119  // The dialog's constructor probably failed to set its Kiway because the
120  // dynamic_cast fails when aParent was allocated by a separate compilation
121  // module. So set it directly.
122  dlg.SetKiway( &dlg, aKiway );
123 
124  // Use QuasiModal so that HTML help window will work
125  if( dlg.ShowQuasiModal() == wxID_OK )
126  aKiway->CommonSettingsChanged( true, false );
127 
128  // Dialog has completed; nothing to return.
129  return nullptr;
130  }
131 
133  InvokePcbLibTableEditor( aKiway, aParent );
134  // Dialog has completed; nothing to return.
135  return nullptr;
136 
137  default:
138  return nullptr;
139  }
140  }
141 
150  void* IfaceOrAddress( int aDataId ) override
151  {
152  switch( aDataId )
153  {
154  // Return a pointer to the global instance of the footprint list.
156  return (void*) &GFootprintList;
157 
158  // Return a new FP_LIB_TABLE with the global table installed as a fallback.
160  return (void*) new FP_LIB_TABLE( &GFootprintTable );
161 
162  // Return a pointer to the global instance of the global footprint table.
164  return (void*) &GFootprintTable;
165 
167  return reinterpret_cast<void*>( PyInit__pcbnew );
168 
169  default:
170  return nullptr;
171  }
172  }
173 
180  void SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcProjectName,
181  const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
182  const wxString& aSrcFilePath, wxString& aErrors ) override;
183 
184 } kiface( "pcbnew", KIWAY::FACE_PCB );
185 
186 } // namespace
187 
188 using namespace PCB;
189 
190 
192 
193 
194 KIFACE_I& Kiface() { return kiface; }
195 
196 
197 // KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h.
198 // KIFACE_GETTER will not have name mangling due to declaration in kiway.h.
199 MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram )
200 {
201  process = aProgram;
202  return &kiface;
203 }
204 
205 #if defined( BUILD_KIWAY_DLL )
206 PGM_BASE& Pgm()
207 {
208  wxASSERT( process ); // KIFACE_GETTER has already been called.
209  return *process;
210 }
211 
212 // Similar to PGM_BASE& Pgm(), but return nullptr when a *.ki_face is run from a python script.
214 {
215  return process;
216 }
217 #endif
218 
223 
228 
229 
230 
231 bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
232 {
233  // This is process-level-initialization, not project-level-initialization of the DSO.
234  // Do nothing in here pertinent to a project!
237 
238  start_common( aCtlBits );
239 
240  wxFileName fn = FP_LIB_TABLE::GetGlobalTableFileName();
241 
242  if( !fn.FileExists() )
243  {
245 
246  fpDialog.ShowModal();
247  }
248  else
249  {
250  try
251  {
252  // The global table is not related to a specific project. All projects
253  // will use the same global table. So the KIFACE::OnKifaceStart() contract
254  // of avoiding anything project specific is not violated here.
256  return false;
257  }
258  catch( const IO_ERROR& ioe )
259  {
260  // if we are here, a incorrect global footprint library table was found.
261  // Incorrect global symbol library table is not a fatal error:
262  // the user just has to edit the (partially) loaded table.
263  wxString msg = _(
264  "An error occurred attempting to load the global footprint library table.\n"
265  "Please edit this global footprint library table in Preferences menu."
266  );
267 
268  DisplayErrorMessage( NULL, msg, ioe.What() );
269  }
270  }
271 
272  return true;
273 }
274 
275 
277 {
278  end_common();
279 }
280 
281 
282 void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcProjectName,
283  const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
284  const wxString& aSrcFilePath, wxString& aErrors )
285 {
286  wxFileName destFile( aSrcFilePath );
287  wxString destPath = destFile.GetPathWithSep();
288  wxUniChar pathSep = wxFileName::GetPathSeparator();
289  wxString ext = destFile.GetExt();
290 
291  if( destPath.StartsWith( aProjectBasePath + pathSep ) )
292  destPath.Replace( aProjectBasePath, aNewProjectBasePath, false );
294  wxString srcProjectFootprintLib = pathSep + aSrcProjectName + ".pretty" + pathSep;
295  wxString newProjectFootprintLib = pathSep + aNewProjectName + ".pretty" + pathSep;
296 
297  destPath.Replace( srcProjectFootprintLib, newProjectFootprintLib, true );
298 
299  destFile.SetPath( destPath );
300 
302  {
303  if( destFile.GetName() == aSrcProjectName )
304  destFile.SetName( aNewProjectName );
305 
306  KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
307  }
308  else if( ext == LegacyPcbFileExtension )
309  {
310  if( destFile.GetName() == aSrcProjectName )
311  destFile.SetName( aNewProjectName );
312 
313  KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
314  }
316  {
317  // Footprints are not project-specific. Keep their source names.
318  KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
319  }
320  else if( ext == FootprintAssignmentFileExtension )
321  {
322  // JEY TODO
323  }
324  else if( ext == "rpt" )
325  {
326  // DRC must be the "gold standard". Since we can't guarantee that there aren't
327  // any non-deterministic cases in the save-as algorithm, we don't want to certify
328  // the result with the source's DRC report. Therefore copy it under the old
329  // name.
330  KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
331  }
332  else if( destFile.GetName() == "fp-lib-table" )
333  {
334  try
335  {
336  FP_LIB_TABLE fpLibTable;
337  fpLibTable.Load( aSrcFilePath );
338 
339  for( unsigned i = 0; i < fpLibTable.GetCount(); i++ )
340  {
341  LIB_TABLE_ROW& row = fpLibTable.At( i );
342  wxString uri = row.GetFullURI();
343 
344  uri.Replace( "/" + aSrcProjectName + ".pretty", "/" + aNewProjectName + ".pretty" );
345 
346  row.SetFullURI( uri );
347  }
348 
349  fpLibTable.Save( destFile.GetFullPath() );
350  }
351  catch( ... )
352  {
353  wxString msg;
354 
355  if( !aErrors.empty() )
356  aErrors += "\n";
357 
358  msg.Printf( _( "Cannot copy file '%s'." ), destFile.GetFullPath() );
359  aErrors += msg;
360  }
361  }
362  else
363  {
364  wxFAIL_MSG( "Unexpected filetype for Pcbnew::SaveFileAs()" );
365  }
366 }
367 
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:129
A KIFACE (I)mplementation.
Definition: kiface_i.h:37
void SetKiway(wxWindow *aDest, KIWAY *aKiway)
It is only used for debugging, since "this" is not a wxWindow*.
#define KICAD_PCB_PORT_SERVICE_NUMBER
< Pcbnew listens on this port for commands from Eeschema
Definition: eda_dde.h:40
const std::string LegacyFootprintLibPathExtension
void SaveFileAs(const wxString &aProjectBasePath, const wxString &aSrcProjectName, const wxString &aNewProjectBasePath, const wxString &aNewProjectName, const wxString &aSrcFilePath, wxString &aErrors) override
Function SaveFileAs Saving a file under a different name is delegated to the various KIFACEs because ...
Definition: pcbnew.cpp:282
DDE server & client.
bool start_common(int aCtlBits)
Common things to do for a top program module, during OnKifaceStart().
Definition: kiface_i.cpp:84
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:265
This file is part of the common library TODO brief description.
bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits) override
Typically start_common() is called from here.
Definition: pcbnew.cpp:231
This file is part of the common library.
const std::string KiCadFootprintFileExtension
Container for data for KiCad programs.
Definition: pgm_base.h:93
const std::string LegacyPcbFileExtension
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition: frame_type.h:32
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition: kiway.cpp:186
const std::string BackupFileSuffix
unsigned GetCount() const
Get the number of rows contained in the table.
static PGM_BASE * process
Definition: pcbnew.cpp:191
Component library viewer main window.
MY_API(KIFACE *) KIFACE_GETTER(int *aKIFACEversion
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition: gestfich.cpp:363
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_i.h:92
const std::string KiCadPcbFileExtension
Return the global FP_LIB_TABLE.
Definition: kiface_ids.h:53
void ScriptingSetPcbEditFrame(PCB_EDIT_FRAME *aPcbEditFrame)
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
not specified: a GAL engine must be set by the client
FP_LIB_TABLE GFootprintTable
The global footprint library table.
Definition: pcbnew.cpp:222
This file contains miscellaneous commonly used macros and functions.
IFACE(const char *aName, KIWAY::FACE_T aType)
Definition: pcbnew.cpp:73
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
void InvokePcbLibTableEditor(KIWAY *aKiway, wxWindow *aCaller)
Function InvokePcbLibTableEditor shows the modal DIALOG_FP_LIB_TABLE for purposes of editing the glob...
void OnKifaceEnd() override
Called just once just before the DSO is to be unloaded.
Definition: pcbnew.cpp:276
const std::string FootprintAssignmentFileExtension
wxWindow * CreateWindow(wxWindow *aParent, int aClassId, KIWAY *aKiway, int aCtlBits=0) override
Create a wxWindow for the current project.
Definition: pcbnew.cpp:81
#define NULL
bool IsSingle() const
Is this KIFACE_I running under single_top?
Definition: kiface_i.h:104
int aKiwayVersion
Definition: pcbnew.cpp:199
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
static bool LoadGlobalTable(FP_LIB_TABLE &aTable)
Load the global footprint library table into aTable.
void end_common()
Common things to do for a top program module, during OnKifaceEnd();.
Definition: kiface_i.cpp:94
PGM_BASE * PgmOrNull()
similar to PGM_BASE& Pgm(), but return a reference that can be nullptr when running a shared lib from...
Definition: cvpcb.cpp:112
Definition of file extensions used in Kicad.
static FOOTPRINT_PREVIEW_PANEL * New(KIWAY *aKiway, wxWindow *aParent)
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:258
#define _(s)
PyObject * PyInit__pcbnew(void)
pcbnew DSO
Definition: kiway.h:267
Return a new FP_LIB_TABLE with the global table installed as a fallback.
Definition: kiface_ids.h:46
#define KIFACE_GETTER
Definition: kiway.h:108
void Load(const wxString &aFileName)
Load the library table using the path defined by aFileName aFallBackTable.
void * IfaceOrAddress(int aDataId) override
Function IfaceOrAddress return a pointer to the requested object.
Definition: pcbnew.cpp:150
PCB::IFACE KIFACE_I kiface("pcbnew", KIWAY::FACE_PCB)
FACE_T
Known KIFACE implementations.
Definition: kiway.h:264
JSON_SETTINGS * RegisterSettings(JSON_SETTINGS *aSettings, bool aLoadNow=true)
Takes ownership of the pointer passed in.
void SetFullURI(const wxString &aFullURI)
Change the full URI for the library.
see class PGM_BASE
LIB_TABLE_ROW & At(unsigned aIndex)
Get the 'n'th LIB_TABLE_ROW object.
Implement a participant in the KIWAY alchemy.
Definition: kiway.h:146
The main frame for Pcbnew.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
virtual void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition: kiway.cpp:543
void InitSettings(APP_SETTINGS_BASE *aSettings)
Definition: kiface_i.h:94
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: pcbnew.cpp:194
FOOTPRINT_LIST_IMPL GFootprintList
The global footprint info table.
Definition: pcbnew.cpp:227
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
static wxString GetGlobalTableFileName()
int PGM_BASE * aProgram
Definition: pcbnew.cpp:200
Return a pointer to the global instance of FOOTPRINT_LIST from pcbnew.
Definition: kiface_ids.h:39