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
66/* init functions defined by swig */
67
68extern "C" PyObject* PyInit__pcbnew( void );
69
70namespace PCB {
71
72static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
73{
74 // Of course all are virtual overloads, implementations of the KIFACE.
75
76 IFACE( const char* aName, KIWAY::FACE_T aType ) :
77 KIFACE_BASE( aName, aType ),
79 {}
80
81 bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) override;
82
83 void OnKifaceEnd() override;
84
85 wxWindow* CreateKiWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway,
86 int aCtlBits = 0 ) override
87 {
88 switch( aClassId )
89 {
91 {
92 auto frame = new PCB_EDIT_FRAME( aKiway, aParent );
93
94 // give the scripting helpers access to our frame
96
97 if( Kiface().IsSingle() )
98 {
99 // only run this under single_top, not under a project manager.
100 frame->CreateServer( KICAD_PCB_PORT_SERVICE_NUMBER );
101 }
102
103 return frame;
104 }
105
107 return new FOOTPRINT_EDIT_FRAME( aKiway, aParent );
108
111 return new FOOTPRINT_VIEWER_FRAME( aKiway, aParent, FRAME_T( aClassId ) );
112
114 return new FOOTPRINT_WIZARD_FRAME( aKiway, aParent, FRAME_T( aClassId ) );
115
117 return dynamic_cast< wxWindow* >( FOOTPRINT_PREVIEW_PANEL::New( aKiway, aParent ) );
118
120 {
121 DIALOG_CONFIGURE_PATHS dlg( aParent );
122
123 // The dialog's constructor probably failed to set its Kiway because the
124 // dynamic_cast fails when aParent was allocated by a separate compilation
125 // module. So set it directly.
126 dlg.SetKiway( &dlg, aKiway );
127
128 // Use QuasiModal so that HTML help window will work
129 if( dlg.ShowQuasiModal() == wxID_OK )
130 aKiway->CommonSettingsChanged( true, false );
131
132 // Dialog has completed; nothing to return.
133 return nullptr;
134 }
135
137 InvokePcbLibTableEditor( aKiway, aParent );
138 // Dialog has completed; nothing to return.
139 return nullptr;
140
142 {
143 SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
145
146 return new PANEL_DISPLAY_OPTIONS( aParent, cfg );
147 }
148
150 {
151 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
152
153 if( !frame )
154 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
155
156 if( !frame )
157 frame = aKiway->Player( FRAME_PCB_EDITOR, false );
158
159 if( frame )
160 return new PANEL_EDIT_OPTIONS( aParent, frame, frame, true );
161 else
162 return new PANEL_EDIT_OPTIONS( aParent, this, nullptr, true );
163 }
164
166 {
167 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
168
169 if( !frame )
170 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
171
172 if( !frame )
173 frame = aKiway->Player( FRAME_PCB_EDITOR, false );
174
175 if( frame )
176 return new PANEL_FP_EDITOR_DEFAULTS( aParent, frame );
177 else
178 return new PANEL_FP_EDITOR_DEFAULTS( aParent, this );
179 }
180
181 case PANEL_FP_COLORS:
182 return new PANEL_FP_EDITOR_COLOR_SETTINGS( aParent );
183
185 {
186 SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
188
189 return new PANEL_DISPLAY_OPTIONS( aParent, cfg );
190 }
191
193 {
194 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_PCB_EDITOR, false );
195
196 if( !frame )
197 frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
198
199 if( !frame )
200 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
201
202 if( frame )
203 return new PANEL_EDIT_OPTIONS( aParent, frame, frame, false );
204 else
205 return new PANEL_EDIT_OPTIONS( aParent, this, nullptr, false );
206 }
208 case PANEL_PCB_COLORS:
209 {
210 BOARD* board = nullptr;
211 EDA_BASE_FRAME* boardProvider = aKiway->Player( FRAME_PCB_EDITOR, false );
212
213 if( boardProvider )
214 board = static_cast<PCB_EDIT_FRAME*>( boardProvider )->GetBoard();
215
216 return new PANEL_PCBNEW_COLOR_SETTINGS( aParent, board );
217 }
218
220 return new PANEL_PCBNEW_ACTION_PLUGINS( aParent );
221
223 return new PANEL_PCBNEW_DISPLAY_ORIGIN( aParent );
224
226 return new PANEL_3D_DISPLAY_OPTIONS( aParent );
227
228 case PANEL_3DV_OPENGL:
229 return new PANEL_3D_OPENGL_OPTIONS( aParent );
230
232 return new PANEL_3D_RAYTRACING_OPTIONS( aParent );
233
234 case PANEL_3DV_COLORS:
235 return new PANEL_3D_COLORS( aParent );
236
237 default:
238 return nullptr;
239 }
240 }
241
252 void* IfaceOrAddress( int aDataId ) override
253 {
254 switch( aDataId )
255 {
256 // Return a pointer to the global instance of the footprint list.
258 return (void*) &GFootprintList;
259
260 // Return a new FP_LIB_TABLE with the global table installed as a fallback.
262 return (void*) new FP_LIB_TABLE( &GFootprintTable );
263
264 // Return a pointer to the global instance of the global footprint table.
266 return (void*) &GFootprintTable;
267
269 return reinterpret_cast<void*>( PyInit__pcbnew );
270
271 default:
272 return nullptr;
273 }
274 }
275
281 void SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcProjectName,
282 const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
283 const wxString& aSrcFilePath, wxString& aErrors ) override;
284
285 int HandleJob( JOB* aJob ) override;
286
287private:
288 std::unique_ptr<PCBNEW_JOBS_HANDLER> m_jobHandler;
289
290} kiface( "pcbnew", KIWAY::FACE_PCB );
291
292} // namespace
293
294
295using namespace PCB;
296
297
299
300
302
303
304// KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h.
305// KIFACE_GETTER will not have name mangling due to declaration in kiway.h.
306MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram )
307{
309 return &kiface;
310}
311
312
313#if defined( BUILD_KIWAY_DLL )
314PGM_BASE& Pgm()
315{
316 wxASSERT( process ); // KIFACE_GETTER has already been called.
317 return *process;
318}
319
320
321// Similar to PGM_BASE& Pgm(), but return nullptr when a *.ki_face is run from a python script.
323{
324 return process;
325}
326#endif
327
328
333
338
339
341{
342 // This is process-level-initialization, not project-level-initialization of the DSO.
343 // Do nothing in here pertinent to a project!
346
347 start_common( aCtlBits );
348
349 wxFileName fn = FP_LIB_TABLE::GetGlobalTableFileName();
350
351 if( !fn.FileExists() )
352 {
353 DIALOG_GLOBAL_FP_LIB_TABLE_CONFIG fpDialog( nullptr );
354
355 fpDialog.ShowModal();
356 }
357 else
358 {
359 try
360 {
361 // The global table is not related to a specific project. All projects
362 // will use the same global table. So the KIFACE::OnKifaceStart() contract
363 // of avoiding anything project specific is not violated here.
365 return false;
366 }
367 catch( const IO_ERROR& ioe )
368 {
369 // if we are here, a incorrect global footprint library table was found.
370 // Incorrect global symbol library table is not a fatal error:
371 // the user just has to edit the (partially) loaded table.
372 wxString msg = _( "An error occurred attempting to load the global footprint library "
373 "table.\n"
374 "Please edit this global footprint library table in Preferences "
375 "menu." );
376
377 DisplayErrorMessage( nullptr, msg, ioe.What() );
378 }
379 }
380
381 m_jobHandler = std::make_unique<PCBNEW_JOBS_HANDLER>();
382
383 return true;
384}
385
386
388{
389 end_common();
390}
391
392
393void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcProjectName,
394 const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
395 const wxString& aSrcFilePath, wxString& aErrors )
396{
397 wxFileName destFile( aSrcFilePath );
398 wxString destPath = destFile.GetPathWithSep();
399 wxUniChar pathSep = wxFileName::GetPathSeparator();
400 wxString ext = destFile.GetExt();
401
402 if( destPath.StartsWith( aProjectBasePath + pathSep ) )
403 destPath.Replace( aProjectBasePath, aNewProjectBasePath, false );
404
405 wxString srcProjectFootprintLib = pathSep + aSrcProjectName + wxT( ".pretty" ) + pathSep;
406 wxString newProjectFootprintLib = pathSep + aNewProjectName + wxT( ".pretty" ) + pathSep;
407
408 destPath.Replace( srcProjectFootprintLib, newProjectFootprintLib, true );
409
410 destFile.SetPath( destPath );
411
413 {
414 if( destFile.GetName() == aSrcProjectName )
415 destFile.SetName( aNewProjectName );
416
417 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
418 }
419 else if( ext == LegacyPcbFileExtension )
420 {
421 if( destFile.GetName() == aSrcProjectName )
422 destFile.SetName( aNewProjectName );
423
424 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
425 }
427 {
428 // Footprints are not project-specific. Keep their source names.
429 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
430 }
431 else if( ext == FootprintAssignmentFileExtension )
432 {
433 // TODO
434 }
435 else if( ext == wxT( "rpt" ) )
436 {
437 // DRC must be the "gold standard". Since we can't guarantee that there aren't
438 // any non-deterministic cases in the save-as algorithm, we don't want to certify
439 // the result with the source's DRC report. Therefore copy it under the old
440 // name.
441 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
442 }
443 else if( destFile.GetName() == wxT( "fp-lib-table" ) )
444 {
445 try
446 {
447 FP_LIB_TABLE fpLibTable;
448 fpLibTable.Load( aSrcFilePath );
449
450 for( unsigned i = 0; i < fpLibTable.GetCount(); i++ )
451 {
452 LIB_TABLE_ROW& row = fpLibTable.At( i );
453 wxString uri = row.GetFullURI();
454
455 uri.Replace( wxT( "/" ) + aSrcProjectName + wxT( ".pretty" ),
456 wxT( "/" ) + aNewProjectName + wxT( ".pretty" ) );
457
458 row.SetFullURI( uri );
459 }
460
461 fpLibTable.Save( destFile.GetFullPath() );
462 }
463 catch( ... )
464 {
465 wxString msg;
466
467 if( !aErrors.empty() )
468 aErrors += wxT( "\n" );
469
470 msg.Printf( _( "Cannot copy file '%s'." ), destFile.GetFullPath() );
471 aErrors += msg;
472 }
473 }
474 else
475 {
476 wxFAIL_MSG( wxT( "Unexpected filetype for Pcbnew::SaveFileAs()" ) );
477 }
478}
479
480
482{
483 return m_jobHandler->RunJob( aJob );
484}
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:265
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:95
void end_common()
Common things to do for a top program module, during OnKifaceEnd();.
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:93
bool start_common(int aCtlBits)
Common things to do for a top program module, during OnKifaceStart().
Definition: kiface_base.cpp:97
bool IsSingle() const
Is this KIFACE running under single_top?
Definition: kiface_base.h:105
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:273
virtual void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition: kiway.cpp:572
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:279
@ FACE_PCB
pcbnew DSO
Definition: kiway.h:281
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:94
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:134
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:299
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 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:309
PyObject * PyInit__pcbnew(void)
MY_API(KIFACE *) KIFACE_GETTER(int *aKIFACEversion
int aKiwayVersion
Definition: pcbnew.cpp:306
static PGM_BASE * process
Definition: pcbnew.cpp:298
int PGM_BASE * aProgram
Definition: pcbnew.cpp:307
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
Definition: pcbnew.cpp:301
FP_LIB_TABLE GFootprintTable
The global footprint library table.
Definition: pcbnew.cpp:332
FOOTPRINT_LIST_IMPL GFootprintList
The global footprint info table.
Definition: pcbnew.cpp:337
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:340
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:393
void * IfaceOrAddress(int aDataId) override
Return a pointer to the requested object.
Definition: pcbnew.cpp:252
wxWindow * CreateKiWindow(wxWindow *aParent, int aClassId, KIWAY *aKiway, int aCtlBits=0) override
Create a wxWindow for the current project.
Definition: pcbnew.cpp:85
IFACE(const char *aName, KIWAY::FACE_T aType)
Definition: pcbnew.cpp:76
std::unique_ptr< PCBNEW_JOBS_HANDLER > m_jobHandler
Definition: pcbnew.cpp:288
void OnKifaceEnd() override
Called just once just before the DSO is to be unloaded.
Definition: pcbnew.cpp:387
int HandleJob(JOB *aJob) override
Definition: pcbnew.cpp:481
Definition of file extensions used in Kicad.