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-2021 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_base.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/snglinst.h>
40 #include <gestfich.h>
41 #include <paths.h>
42 #include <pcbnew_settings.h>
44 #include <class_draw_panel_gal.h>
45 #include <fp_lib_table.h>
46 #include <footprint_edit_frame.h>
47 #include <footprint_viewer_frame.h>
48 #include <footprint_wizard_frame.h>
50 #include <footprint_info_impl.h>
52 #include <python_scripting.h>
53 
54 #include "invoke_pcb_dialog.h"
57 
58 
59 /* init functions defined by swig */
60 
61 extern "C" PyObject* PyInit__pcbnew( void );
62 
63 namespace PCB {
64 
65 static struct IFACE : public KIFACE_BASE
66 {
67  // Of course all are virtual overloads, implementations of the KIFACE.
68 
69  IFACE( const char* aName, KIWAY::FACE_T aType ) :
70  KIFACE_BASE( aName, aType )
71  {}
72 
73  bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) override;
74 
75  void OnKifaceEnd() override;
76 
77  wxWindow* CreateWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway,
78  int aCtlBits = 0 ) override
79  {
80  switch( aClassId )
81  {
82  case FRAME_PCB_EDITOR:
83  {
84  auto frame = new PCB_EDIT_FRAME( aKiway, aParent );
85 
86  // give the scripting helpers access to our frame
87  ScriptingSetPcbEditFrame( frame );
88 
89  if( Kiface().IsSingle() )
90  {
91  // only run this under single_top, not under a project manager.
92  frame->CreateServer( KICAD_PCB_PORT_SERVICE_NUMBER );
93  }
94 
95  return frame;
96  }
97 
99  return new FOOTPRINT_EDIT_FRAME( aKiway, aParent,
101 
104  return new FOOTPRINT_VIEWER_FRAME( aKiway, aParent, FRAME_T( aClassId ) );
105 
107  return new FOOTPRINT_WIZARD_FRAME( aKiway, aParent, FRAME_T( aClassId ) );
108 
110  return dynamic_cast< wxWindow* >( FOOTPRINT_PREVIEW_PANEL::New( aKiway, aParent ) );
111 
113  {
114  DIALOG_CONFIGURE_PATHS dlg( aParent, aKiway->Prj().Get3DFilenameResolver() );
115 
116  // The dialog's constructor probably failed to set its Kiway because the
117  // dynamic_cast fails when aParent was allocated by a separate compilation
118  // module. So set it directly.
119  dlg.SetKiway( &dlg, aKiway );
120 
121  // Use QuasiModal so that HTML help window will work
122  if( dlg.ShowQuasiModal() == wxID_OK )
123  aKiway->CommonSettingsChanged( true, false );
124 
125  // Dialog has completed; nothing to return.
126  return nullptr;
127  }
128 
130  InvokePcbLibTableEditor( aKiway, aParent );
131  // Dialog has completed; nothing to return.
132  return nullptr;
133 
134  default:
135  return nullptr;
136  }
137  }
138 
149  void* IfaceOrAddress( int aDataId ) override
150  {
151  switch( aDataId )
152  {
153  // Return a pointer to the global instance of the footprint list.
155  return (void*) &GFootprintList;
156 
157  // Return a new FP_LIB_TABLE with the global table installed as a fallback.
159  return (void*) new FP_LIB_TABLE( &GFootprintTable );
160 
161  // Return a pointer to the global instance of the global footprint table.
163  return (void*) &GFootprintTable;
164 
166  return reinterpret_cast<void*>( PyInit__pcbnew );
167 
168  default:
169  return nullptr;
170  }
171  }
172 
178  void SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcProjectName,
179  const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
180  const wxString& aSrcFilePath, wxString& aErrors ) override;
181 
182 } kiface( "pcbnew", KIWAY::FACE_PCB );
183 
184 } // namespace
185 
186 
187 using namespace PCB;
188 
189 
191 
192 
193 KIFACE_BASE& Kiface() { return kiface; }
194 
195 
196 // KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h.
197 // KIFACE_GETTER will not have name mangling due to declaration in kiway.h.
198 MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram )
199 {
200  process = aProgram;
201  return &kiface;
202 }
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 
213 // Similar to PGM_BASE& Pgm(), but return nullptr when a *.ki_face is run from a python script.
215 {
216  return process;
217 }
218 #endif
219 
220 
225 
230 
231 
232 bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
233 {
234  // This is process-level-initialization, not project-level-initialization of the DSO.
235  // Do nothing in here pertinent to a project!
238 
239  start_common( aCtlBits );
240 
241  wxFileName fn = FP_LIB_TABLE::GetGlobalTableFileName();
242 
243  if( !fn.FileExists() )
244  {
245  DIALOG_GLOBAL_FP_LIB_TABLE_CONFIG fpDialog( nullptr );
246 
247  fpDialog.ShowModal();
248  }
249  else
250  {
251  try
252  {
253  // The global table is not related to a specific project. All projects
254  // will use the same global table. So the KIFACE::OnKifaceStart() contract
255  // of avoiding anything project specific is not violated here.
257  return false;
258  }
259  catch( const IO_ERROR& ioe )
260  {
261  // if we are here, a incorrect global footprint library table was found.
262  // Incorrect global symbol library table is not a fatal error:
263  // the user just has to edit the (partially) loaded table.
264  wxString msg = _(
265  "An error occurred attempting to load the global footprint library table.\n"
266  "Please edit this global footprint library table in Preferences menu."
267  );
268 
269  DisplayErrorMessage( nullptr, msg, ioe.What() );
270  }
271  }
272 
273  return true;
274 }
275 
276 
278 {
279  end_common();
280 }
281 
282 
283 void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcProjectName,
284  const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
285  const wxString& aSrcFilePath, wxString& aErrors )
286 {
287  wxFileName destFile( aSrcFilePath );
288  wxString destPath = destFile.GetPathWithSep();
289  wxUniChar pathSep = wxFileName::GetPathSeparator();
290  wxString ext = destFile.GetExt();
291 
292  if( destPath.StartsWith( aProjectBasePath + pathSep ) )
293  destPath.Replace( aProjectBasePath, aNewProjectBasePath, false );
295  wxString srcProjectFootprintLib = pathSep + aSrcProjectName + ".pretty" + pathSep;
296  wxString newProjectFootprintLib = pathSep + aNewProjectName + ".pretty" + pathSep;
297 
298  destPath.Replace( srcProjectFootprintLib, newProjectFootprintLib, true );
299 
300  destFile.SetPath( destPath );
301 
303  {
304  if( destFile.GetName() == aSrcProjectName )
305  destFile.SetName( aNewProjectName );
306 
307  KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
308  }
309  else if( ext == LegacyPcbFileExtension )
310  {
311  if( destFile.GetName() == aSrcProjectName )
312  destFile.SetName( aNewProjectName );
313 
314  KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
315  }
317  {
318  // Footprints are not project-specific. Keep their source names.
319  KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
320  }
321  else if( ext == FootprintAssignmentFileExtension )
322  {
323  // JEY TODO
324  }
325  else if( ext == "rpt" )
326  {
327  // DRC must be the "gold standard". Since we can't guarantee that there aren't
328  // any non-deterministic cases in the save-as algorithm, we don't want to certify
329  // the result with the source's DRC report. Therefore copy it under the old
330  // name.
331  KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
332  }
333  else if( destFile.GetName() == "fp-lib-table" )
334  {
335  try
336  {
337  FP_LIB_TABLE fpLibTable;
338  fpLibTable.Load( aSrcFilePath );
339 
340  for( unsigned i = 0; i < fpLibTable.GetCount(); i++ )
341  {
342  LIB_TABLE_ROW& row = fpLibTable.At( i );
343  wxString uri = row.GetFullURI();
344 
345  uri.Replace( "/" + aSrcProjectName + ".pretty", "/" + aNewProjectName + ".pretty" );
346 
347  row.SetFullURI( uri );
348  }
349 
350  fpLibTable.Save( destFile.GetFullPath() );
351  }
352  catch( ... )
353  {
354  wxString msg;
355 
356  if( !aErrors.empty() )
357  aErrors += "\n";
358 
359  msg.Printf( _( "Cannot copy file '%s'." ), destFile.GetFullPath() );
360  aErrors += msg;
361  }
362  }
363  else
364  {
365  wxFAIL_MSG( "Unexpected filetype for Pcbnew::SaveFileAs()" );
366  }
367 }
368 
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:129
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
Saving a file under a different name is delegated to the various KIFACEs because the project doesn't ...
Definition: pcbnew.cpp:283
DDE server & client.
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
A KIFACE implementation.
Definition: kiface_base.h:37
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:284
T * RegisterSettings(T *aSettings, bool aLoadNow=true)
Takes ownership of the pointer passed in.
bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits) override
Typically start_common() is called from here.
Definition: pcbnew.cpp:232
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:189
const std::string BackupFileSuffix
unsigned GetCount() const
Get the number of rows contained in the table.
static PGM_BASE * process
Definition: pcbnew.cpp:190
Component library viewer main window.
MY_API(KIFACE *) KIFACE_GETTER(int *aKIFACEversion
void end_common()
Common things to do for a top program module, during OnKifaceEnd();.
Definition: kiface_base.cpp:94
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition: gestfich.cpp:334
PCB::IFACE KIFACE_BASE kiface("pcbnew", KIWAY::FACE_PCB)
const std::string KiCadPcbFileExtension
Return the global FP_LIB_TABLE.
Definition: kiface_ids.h:53
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
Definition: pcbnew.cpp:193
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:224
This file contains miscellaneous commonly used macros and functions.
IFACE(const char *aName, KIWAY::FACE_T aType)
Definition: pcbnew.cpp:69
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 InitSettings(APP_SETTINGS_BASE *aSettings)
Definition: kiface_base.h:94
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:277
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:77
int aKiwayVersion
Definition: pcbnew.cpp:198
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.
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:125
bool start_common(int aCtlBits)
Common things to do for a top program module, during OnKifaceStart().
Definition: kiface_base.cpp:84
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:260
#define _(s)
PyObject * PyInit__pcbnew(void)
pcbnew DSO
Definition: kiway.h:269
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:110
void Load(const wxString &aFileName)
Load the library table using the path defined by aFileName aFallBackTable.
void * IfaceOrAddress(int aDataId) override
Return a pointer to the requested object.
Definition: pcbnew.cpp:149
FACE_T
Known KIFACE implementations.
Definition: kiway.h:266
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:148
The main frame for Pcbnew.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:92
virtual void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition: kiway.cpp:553
FOOTPRINT_LIST_IMPL GFootprintList
The global footprint info table.
Definition: pcbnew.cpp:229
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
bool IsSingle() const
Is this KIFACE running under single_top?
Definition: kiface_base.h:104
static wxString GetGlobalTableFileName()
int PGM_BASE * aProgram
Definition: pcbnew.cpp:199
Return a pointer to the global instance of FOOTPRINT_LIST from pcbnew.
Definition: kiface_ids.h:39