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 <[email protected]>
6 * Copyright (C) 1992-2022 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
27#include <pgm_base.h>
28#include <kiface_base.h>
29#include <kiface_ids.h>
30#include <confirm.h>
31#include <pcb_edit_frame.h>
32#include <eda_dde.h>
33#include <macros.h>
34#include <wx/snglinst.h>
35#include <gestfich.h>
36#include <paths.h>
37#include <pcbnew_settings.h>
40#include <fp_lib_table.h>
45#include <footprint_info_impl.h>
49#include <panel_edit_options.h>
58#include <panel_3D_colors.h>
59#include <python_scripting.h>
60
61#include "invoke_pcb_dialog.h"
63#include "pcbnew_jobs_handler.h"
64
65#include <wx/crt.h>
66
67/* init functions defined by swig */
68
69extern "C" PyObject* PyInit__pcbnew( void );
70
71namespace PCB {
72
73static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
74{
75 // Of course all are virtual overloads, implementations of the KIFACE.
76
77 IFACE( const char* aName, KIWAY::FACE_T aType ) :
78 KIFACE_BASE( aName, aType ),
80 {}
81
82 bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) override;
83
84 void Reset() override;
85
86 void OnKifaceEnd() override;
87
88 wxWindow* CreateKiWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway,
89 int aCtlBits = 0 ) override
90 {
91 switch( aClassId )
92 {
94 {
95 auto frame = new PCB_EDIT_FRAME( aKiway, aParent );
96
97 // give the scripting helpers access to our frame
99
100 if( Kiface().IsSingle() )
101 {
102 // only run this under single_top, not under a project manager.
103 frame->CreateServer( KICAD_PCB_PORT_SERVICE_NUMBER );
104 }
105
106 return frame;
107 }
108
110 return new FOOTPRINT_EDIT_FRAME( aKiway, aParent );
111
114 return new FOOTPRINT_VIEWER_FRAME( aKiway, aParent, FRAME_T( aClassId ) );
115
117 return new FOOTPRINT_WIZARD_FRAME( aKiway, aParent, FRAME_T( aClassId ) );
118
120 return dynamic_cast< wxWindow* >( FOOTPRINT_PREVIEW_PANEL::New( aKiway, aParent ) );
121
123 {
124 DIALOG_CONFIGURE_PATHS dlg( aParent );
125
126 // The dialog's constructor probably failed to set its Kiway because the
127 // dynamic_cast fails when aParent was allocated by a separate compilation
128 // module. So set it directly.
129 dlg.SetKiway( &dlg, aKiway );
130
131 // Use QuasiModal so that HTML help window will work
132 if( dlg.ShowQuasiModal() == wxID_OK )
133 aKiway->CommonSettingsChanged( true, false );
134
135 // Dialog has completed; nothing to return.
136 return nullptr;
137 }
138
140 InvokePcbLibTableEditor( aKiway, aParent );
141 // Dialog has completed; nothing to return.
142 return nullptr;
143
145 {
146 SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
148
149 return new PANEL_DISPLAY_OPTIONS( aParent, cfg );
150 }
151
153 {
154 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
155
156 if( !frame )
157 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
158
159 if( !frame )
160 frame = aKiway->Player( FRAME_PCB_EDITOR, false );
161
162 if( frame )
163 return new PANEL_EDIT_OPTIONS( aParent, frame, frame, true );
164 else
165 return new PANEL_EDIT_OPTIONS( aParent, this, nullptr, true );
166 }
167
169 {
170 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
171
172 if( !frame )
173 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
174
175 if( !frame )
176 frame = aKiway->Player( FRAME_PCB_EDITOR, false );
177
178 if( frame )
179 return new PANEL_FP_EDITOR_DEFAULTS( aParent, frame );
180 else
181 return new PANEL_FP_EDITOR_DEFAULTS( aParent, this );
182 }
183
184 case PANEL_FP_COLORS:
185 return new PANEL_FP_EDITOR_COLOR_SETTINGS( aParent );
186
188 {
189 SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
191
192 return new PANEL_DISPLAY_OPTIONS( aParent, cfg );
193 }
194
196 {
197 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_PCB_EDITOR, false );
198
199 if( !frame )
200 frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
201
202 if( !frame )
203 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
204
205 if( frame )
206 return new PANEL_EDIT_OPTIONS( aParent, frame, frame, false );
207 else
208 return new PANEL_EDIT_OPTIONS( aParent, this, nullptr, false );
210
211 case PANEL_PCB_COLORS:
212 {
213 BOARD* board = nullptr;
214 EDA_BASE_FRAME* boardProvider = aKiway->Player( FRAME_PCB_EDITOR, false );
215
216 if( boardProvider )
217 board = static_cast<PCB_EDIT_FRAME*>( boardProvider )->GetBoard();
219 return new PANEL_PCBNEW_COLOR_SETTINGS( aParent, board );
220 }
221
223 return new PANEL_PCBNEW_ACTION_PLUGINS( aParent );
224
226 return new PANEL_PCBNEW_DISPLAY_ORIGIN( aParent );
227
229 return new PANEL_3D_DISPLAY_OPTIONS( aParent );
230
231 case PANEL_3DV_OPENGL:
232 return new PANEL_3D_OPENGL_OPTIONS( aParent );
233
235 return new PANEL_3D_RAYTRACING_OPTIONS( aParent );
236
237 case PANEL_3DV_COLORS:
238 return new PANEL_3D_COLORS( aParent );
239
240 default:
241 return nullptr;
242 }
243 }
244
255 void* IfaceOrAddress( int aDataId ) override
256 {
257 switch( aDataId )
258 {
259 // Return a pointer to the global instance of the footprint list.
261 return (void*) &GFootprintList;
262
263 // Return a new FP_LIB_TABLE with the global table installed as a fallback.
265 return (void*) new FP_LIB_TABLE( &GFootprintTable );
266
267 // Return a pointer to the global instance of the global footprint table.
269 return (void*) &GFootprintTable;
270
272 return reinterpret_cast<void*>( PyInit__pcbnew );
273
274 default:
275 return nullptr;
276 }
277 }
278
284 void SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcProjectName,
285 const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
286 const wxString& aSrcFilePath, wxString& aErrors ) override;
287
288 int HandleJob( JOB* aJob ) override;
289
290private:
291 bool loadGlobalLibTable();
292
293 std::unique_ptr<PCBNEW_JOBS_HANDLER> m_jobHandler;
294
295} kiface( "pcbnew", KIWAY::FACE_PCB );
296
297} // namespace
298
299
300using namespace PCB;
301
302
304
305
307
308
309// KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h.
310// KIFACE_GETTER will not have name mangling due to declaration in kiway.h.
311MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram )
312{
314 return &kiface;
315}
316
317
318#if defined( BUILD_KIWAY_DLL )
319PGM_BASE& Pgm()
320{
321 wxASSERT( process ); // KIFACE_GETTER has already been called.
322 return *process;
323}
324
325
326// Similar to PGM_BASE& Pgm(), but return nullptr when a *.ki_face is run from a python script.
328{
329 return process;
330}
331#endif
332
333
338
343
344
346{
347 // This is process-level-initialization, not project-level-initialization of the DSO.
348 // Do nothing in here pertinent to a project!
351
352 start_common( aCtlBits );
353
354 if( !loadGlobalLibTable() )
355 return false;
356
357 m_jobHandler = std::make_unique<PCBNEW_JOBS_HANDLER>();
358
359 return true;
360}
361
362
364{
366}
367
368
370{
371 wxFileName fn = FP_LIB_TABLE::GetGlobalTableFileName();
372
373 if( !fn.FileExists() )
374 {
375 if( !( m_start_flags & KFCTL_CLI ) )
376 {
377 DIALOG_GLOBAL_FP_LIB_TABLE_CONFIG fpDialog( nullptr );
378
379 fpDialog.ShowModal();
380 }
381 }
382 else
383 {
384 try
385 {
386 // The global table is not related to a specific project. All projects
387 // will use the same global table. So the KIFACE::OnKifaceStart() contract
388 // of avoiding anything project specific is not violated here.
390 return false;
391 }
392 catch( const IO_ERROR& ioe )
393 {
394 // if we are here, a incorrect global footprint library table was found.
395 // Incorrect global symbol library table is not a fatal error:
396 // the user just has to edit the (partially) loaded table.
397 wxString msg = _( "An error occurred attempting to load the global footprint library "
398 "table.\n"
399 "Please edit this global footprint library table in Preferences "
400 "menu." );
401
402 DisplayErrorMessage( nullptr, msg, ioe.What() );
403 }
404 }
405
406 return true;
407}
408
409
411{
412 end_common();
413}
414
415
416void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcProjectName,
417 const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
418 const wxString& aSrcFilePath, wxString& aErrors )
419{
420 wxFileName destFile( aSrcFilePath );
421 wxString destPath = destFile.GetPathWithSep();
422 wxUniChar pathSep = wxFileName::GetPathSeparator();
423 wxString ext = destFile.GetExt();
424
425 if( destPath.StartsWith( aProjectBasePath + pathSep ) )
426 destPath.Replace( aProjectBasePath, aNewProjectBasePath, false );
427
428 wxString srcProjectFootprintLib = pathSep + aSrcProjectName + wxT( ".pretty" ) + pathSep;
429 wxString newProjectFootprintLib = pathSep + aNewProjectName + wxT( ".pretty" ) + pathSep;
430
431 destPath.Replace( srcProjectFootprintLib, newProjectFootprintLib, true );
432
433 destFile.SetPath( destPath );
434
436 {
437 if( destFile.GetName() == aSrcProjectName )
438 destFile.SetName( aNewProjectName );
439
440 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
441 }
442 else if( ext == LegacyPcbFileExtension )
443 {
444 if( destFile.GetName() == aSrcProjectName )
445 destFile.SetName( aNewProjectName );
446
447 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
448 }
450 {
451 // Footprints are not project-specific. Keep their source names.
452 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
453 }
454 else if( ext == FootprintAssignmentFileExtension )
455 {
456 // TODO
457 }
458 else if( ext == wxT( "rpt" ) )
459 {
460 // DRC must be the "gold standard". Since we can't guarantee that there aren't
461 // any non-deterministic cases in the save-as algorithm, we don't want to certify
462 // the result with the source's DRC report. Therefore copy it under the old
463 // name.
464 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
465 }
466 else if( destFile.GetName() == wxT( "fp-lib-table" ) )
467 {
468 try
469 {
470 FP_LIB_TABLE fpLibTable;
471 fpLibTable.Load( aSrcFilePath );
472
473 for( unsigned i = 0; i < fpLibTable.GetCount(); i++ )
474 {
475 LIB_TABLE_ROW& row = fpLibTable.At( i );
476 wxString uri = row.GetFullURI();
477
478 uri.Replace( wxT( "/" ) + aSrcProjectName + wxT( ".pretty" ),
479 wxT( "/" ) + aNewProjectName + wxT( ".pretty" ) );
480
481 row.SetFullURI( uri );
482 }
483
484 fpLibTable.Save( destFile.GetFullPath() );
485 }
486 catch( ... )
487 {
488 wxString msg;
489
490 if( !aErrors.empty() )
491 aErrors += wxT( "\n" );
492
493 msg.Printf( _( "Cannot copy file '%s'." ), destFile.GetFullPath() );
494 aErrors += msg;
495 }
496 }
497 else
498 {
499 wxFAIL_MSG( wxT( "Unexpected filetype for Pcbnew::SaveFileAs()" ) );
500 }
501}
502
503
505{
506 return m_jobHandler->RunJob( aJob );
507}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:110
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:269
int ShowQuasiModal()
The base frame for deriving all KiCad main window classes.
static FOOTPRINT_PREVIEW_PANEL * New(KIWAY *aKiway, wxWindow *aParent)
Component library viewer main window.
static bool LoadGlobalTable(FP_LIB_TABLE &aTable)
Load the global footprint library table into aTable.
static wxString GetGlobalTableFileName()
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:76
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
An simple container class that lets us dispatch output jobs to kifaces.
Definition: job.h:28
A KIFACE implementation.
Definition: kiface_base.h:39
void InitSettings(APP_SETTINGS_BASE *aSettings)
Definition: kiface_base.h:97
void end_common()
Common things to do for a top program module, during OnKifaceEnd();.
Definition: kiface_base.cpp:42
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:95
bool start_common(int aCtlBits)
Common things to do for a top program module, during OnKifaceStart().
Definition: kiface_base.cpp:32
int m_start_flags
flags provided in OnKifaceStart()
Definition: kiface_base.h:125
bool IsSingle() const
Is this KIFACE running under single_top?
Definition: kiface_base.h:107
void SetKiway(wxWindow *aDest, KIWAY *aKiway)
It is only used for debugging, since "this" is not a wxWindow*.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:279
virtual void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition: kiway.cpp:575
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:394
FACE_T
Known KIFACE implementations.
Definition: kiway.h:285
@ FACE_PCB
pcbnew DSO
Definition: kiway.h:287
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
void SetFullURI(const wxString &aFullURI)
Change the full URI for the library.
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...
LIB_TABLE_ROW & At(unsigned aIndex)
Get the 'n'th LIB_TABLE_ROW object.
void Load(const wxString &aFileName)
Load the library table using the path defined by aFileName aFallBackTable.
unsigned GetCount() const
Get the number of rows contained in the table.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
The main frame for Pcbnew.
Container for data for KiCad programs.
Definition: pgm_base.h:95
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:135
T * GetAppSettings(bool aLoadNow=true)
Returns a handle to the a given settings by type If the settings have already been loaded,...
T * RegisterSettings(T *aSettings, bool aLoadNow=true)
Takes ownership of the pointer passed in.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:325
This file is part of the common library.
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
#define _(s)
DDE server & client.
#define KICAD_PCB_PORT_SERVICE_NUMBER
< Pcbnew listens on this port for commands from Eeschema
Definition: eda_dde.h:40
EDA_UNITS
Definition: eda_units.h:43
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition: frame_type.h:33
@ FRAME_PCB_EDITOR
Definition: frame_type.h:40
@ FRAME_FOOTPRINT_VIEWER_MODAL
Definition: frame_type.h:43
@ FRAME_FOOTPRINT_VIEWER
Definition: frame_type.h:42
@ PANEL_3DV_COLORS
Definition: frame_type.h:92
@ PANEL_3DV_OPENGL
Definition: frame_type.h:90
@ PANEL_PCB_ORIGINS_AXES
Definition: frame_type.h:87
@ FRAME_FOOTPRINT_WIZARD
Definition: frame_type.h:44
@ PANEL_PCB_EDIT_OPTIONS
Definition: frame_type.h:84
@ PANEL_FP_DISPLAY_OPTIONS
Definition: frame_type.h:78
@ PANEL_PCB_COLORS
Definition: frame_type.h:85
@ PANEL_3DV_RAYTRACING
Definition: frame_type.h:91
@ DIALOG_PCB_LIBRARY_TABLE
Definition: frame_type.h:105
@ FRAME_FOOTPRINT_PREVIEW
Definition: frame_type.h:46
@ DIALOG_CONFIGUREPATHS
Definition: frame_type.h:103
@ PANEL_FP_COLORS
Definition: frame_type.h:80
@ FRAME_FOOTPRINT_EDITOR
Definition: frame_type.h:41
@ PANEL_FP_EDIT_OPTIONS
Definition: frame_type.h:79
@ PANEL_PCB_ACTION_PLUGINS
Definition: frame_type.h:86
@ PANEL_FP_DEFAULT_VALUES
Definition: frame_type.h:81
@ PANEL_3DV_DISPLAY_OPTIONS
Definition: frame_type.h:89
@ PANEL_PCB_DISPLAY_OPTIONS
Definition: frame_type.h:83
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition: gestfich.cpp:214
const std::string LegacyPcbFileExtension
const std::string BackupFileSuffix
const std::string FootprintAssignmentFileExtension
const std::string KiCadFootprintFileExtension
const std::string KiCadPcbFileExtension
const std::string LegacyFootprintLibPathExtension
@ KIFACE_SCRIPTING_LEGACY
Definition: kiface_ids.h:57
@ KIFACE_FOOTPRINT_LIST
Return a pointer to the global instance of FOOTPRINT_LIST from pcbnew.
Definition: kiface_ids.h:39
@ KIFACE_GLOBAL_FOOTPRINT_TABLE
Return the global FP_LIB_TABLE.
Definition: kiface_ids.h:53
@ KIFACE_NEW_FOOTPRINT_TABLE
Return a new FP_LIB_TABLE with the global table installed as a fallback.
Definition: kiface_ids.h:46
#define KFCTL_CLI
Running as CLI app.
Definition: kiway.h:160
#define KIFACE_GETTER
Definition: kiway.h:111
This file contains miscellaneous commonly used macros and functions.
PCB::IFACE KIFACE_BASE, UNITS_PROVIDER kiface("pcbnew", KIWAY::FACE_PCB)
void InvokePcbLibTableEditor(KIWAY *aKiway, wxWindow *aCaller)
Function InvokePcbLibTableEditor shows the modal DIALOG_FP_LIB_TABLE for purposes of editing the glob...
return & kiface
Definition: pcbnew.cpp:314
PyObject * PyInit__pcbnew(void)
MY_API(KIFACE *) KIFACE_GETTER(int *aKIFACEversion
int aKiwayVersion
Definition: pcbnew.cpp:311
static PGM_BASE * process
Definition: pcbnew.cpp:303
int PGM_BASE * aProgram
Definition: pcbnew.cpp:312
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
Definition: pcbnew.cpp:306
FP_LIB_TABLE GFootprintTable
The global footprint library table.
Definition: pcbnew.cpp:337
FOOTPRINT_LIST_IMPL GFootprintList
The global footprint info table.
Definition: pcbnew.cpp:342
void ScriptingSetPcbEditFrame(PCB_EDIT_FRAME *aPcbEditFrame)
BOARD * GetBoard()
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits) override
Typically start_common() is called from here.
Implement a participant in the KIWAY alchemy.
Definition: kiway.h:151
bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits) override
Typically start_common() is called from here.
Definition: pcbnew.cpp:345
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:416
void * IfaceOrAddress(int aDataId) override
Return a pointer to the requested object.
Definition: pcbnew.cpp:255
void Reset() override
Reloads global state.
Definition: pcbnew.cpp:363
wxWindow * CreateKiWindow(wxWindow *aParent, int aClassId, KIWAY *aKiway, int aCtlBits=0) override
Create a wxWindow for the current project.
Definition: pcbnew.cpp:88
IFACE(const char *aName, KIWAY::FACE_T aType)
Definition: pcbnew.cpp:77
bool loadGlobalLibTable()
Definition: pcbnew.cpp:369
std::unique_ptr< PCBNEW_JOBS_HANDLER > m_jobHandler
Definition: pcbnew.cpp:293
void OnKifaceEnd() override
Called just once just before the DSO is to be unloaded.
Definition: pcbnew.cpp:410
int HandleJob(JOB *aJob) override
Definition: pcbnew.cpp:504
Definition of file extensions used in Kicad.