KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_io_mgr.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) 2011-2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
5 * Copyright The 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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <wx/filename.h>
22#include <wx/uri.h>
23
24#include <config.h>
25#include <board.h>
26#include <footprint.h>
27#include <kiway_player.h>
30#include <pcb_io/pcb_io_mgr.h>
31
56#include <reporter.h>
58
59
60#define FMT_UNIMPLEMENTED _( "Plugin '%s' does not implement the '%s' function." )
61#define FMT_NOTFOUND _( "Plugin type '%s' is not found." )
62
63
64// Some day plugins might be in separate DLL/DSOs, simply because of numbers of them
65// and code size. Until then, use the simplest method:
66
67// This implementation is one of two which could be done.
68// The other one would cater to DLL/DSO's. But since it would be nearly
69// impossible to link a KICAD type DLL/DSO right now without pulling in all
70// ::Draw() functions, I forgo that option temporarily.
71
72// Some day it may be possible to have some built in AND some DLL/DSO
73// plugins coexisting.
74
75
77{
78 // This implementation is subject to change, any magic is allowed here.
79 // The public IO_MGR API is the only pertinent public information.
80
81 return PLUGIN_REGISTRY::Instance()->Create( aFileType );
82}
83
84
85const wxString PCB_IO_MGR::ShowType( PCB_FILE_T aType )
86{
87 if( aType == PCB_IO_MGR::NESTED_TABLE )
89
90 const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
91
92 for( const auto& plugin : plugins )
93 {
94 if ( plugin.m_type == aType )
95 return plugin.m_name;
96 }
97
98 return wxString::Format( _( "UNKNOWN (%d)" ), aType );
99}
100
101
103{
106
107 const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
108
109 for( const auto& plugin : plugins )
110 {
111 if( plugin.m_name.CmpNoCase( aType ) == 0 )
112 return plugin.m_type;
113 }
114
116}
117
118
120{
121 switch( aFileType )
122 {
123 case ALLEGRO:
124 return true;
125
126 default:
127 return false;
128 }
129}
130
131
133{
134 switch( aFileType )
135 {
137 case EAGLE:
138 case EASYEDA:
139 case EASYEDAPRO:
140 case EASYEDAPRO_V3:
141 case GEDA_PCB:
142 case ALTIUM_DESIGNER:
145 case ALLEGRO:
146 case TARGET3001:
147 return true;
148
149 default:
150 return false;
151 }
152}
153
154
155// The KIWAY_PLAYER::OpenProjectFiles() API knows nothing about plugins, so
156// determine how to load the BOARD here
158{
159 const auto& plugins = PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins();
160
161 for( const auto& plugin : plugins )
162 {
163 bool isKiCad = plugin.m_type == PCB_IO_MGR::KICAD_SEXP || plugin.m_type == PCB_IO_MGR::LEGACY;
164
165 if( ( aCtl & KICTL_KICAD_ONLY ) && !isKiCad )
166 continue;
167
168 if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
169 continue;
170
171 IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
172
173 if( pi->CanReadBoard( aFileName ) )
174 return plugin.m_type;
175 }
176
178}
179
180
182{
184
185 if( parser.Parse( aLibPath.ToStdString() ).has_value() )
186 return NESTED_TABLE;
187
188 const auto& plugins = PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins();
189
190 for( const auto& plugin : plugins )
191 {
192 bool isKiCad = plugin.m_type == PCB_IO_MGR::KICAD_SEXP || plugin.m_type == PCB_IO_MGR::LEGACY;
193
194 if( ( aCtl & KICTL_KICAD_ONLY ) && !isKiCad )
195 continue;
196
197 if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
198 continue;
199
200 IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
201
202 if( pi->CanReadLibrary( aLibPath ) )
203 return plugin.m_type;
204 }
205
207}
208
209
210std::unique_ptr<BOARD> PCB_IO_MGR::Load( PCB_FILE_T aFileType, const wxString& aFileName,
211 const std::map<std::string, UTF8>* aProperties, PROJECT* aProject,
212 PROGRESS_REPORTER* aProgressReporter )
213{
214 IO_RELEASER<PCB_IO> pi( FindPlugin( aFileType ) );
215
216 if( pi ) // test pi->plugin
217 {
218 pi->SetProgressReporter( aProgressReporter );
219 return pi->LoadBoard( aFileName, aProperties, aProject );
220 }
221
222 THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );
223}
224
225
226void PCB_IO_MGR::Save( PCB_FILE_T aFileType, const wxString& aFileName, BOARD& aBoard,
227 const std::map<std::string, UTF8>* aProperties )
228{
229 IO_RELEASER<PCB_IO> pi( FindPlugin( aFileType ) );
230
231 if( pi )
232 {
233 pi->SaveBoard( aFileName, aBoard, aProperties ); // virtual
234 return;
235 }
236
237 THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );
238}
239
240
241bool PCB_IO_MGR::ConvertLibrary( const std::map<std::string, UTF8>& aOldFileProps, const wxString& aOldFilePath,
242 const wxString& aNewFilePath, REPORTER* aReporter )
243{
245
246 if( oldFileType == PCB_IO_MGR::FILE_TYPE_NONE )
247 return false;
248
249 // A nested library table has no plugin to enumerate it; reject it before dereferencing
250 // the null plugin below.
251 if( oldFileType == PCB_IO_MGR::NESTED_TABLE )
252 return false;
253
254 IO_RELEASER<PCB_IO> oldFilePI( PCB_IO_MGR::FindPlugin( oldFileType ) );
256
257 if( !oldFilePI || !kicadPI )
258 return false;
259
260 wxArrayString fpNames;
261 wxFileName newFileName( aNewFilePath );
262
263 if( newFileName.HasExt() )
264 {
265 wxString extraDir = newFileName.GetFullName();
266 newFileName.ClearExt();
267 newFileName.SetName( "" );
268 newFileName.AppendDir( extraDir );
269 }
270
271 if( !newFileName.DirExists() && !wxFileName::Mkdir( aNewFilePath, wxS_DIR_DEFAULT ) )
272 return false;
273
274 try
275 {
276 bool bestEfforts = false; // throw on first error
277 oldFilePI->FootprintEnumerate( fpNames, aOldFilePath, bestEfforts, &aOldFileProps );
278 std::map<std::string, UTF8> props { { "skip_cache_validation", "" } };
279
280 for ( const wxString& fpName : fpNames )
281 {
282 std::unique_ptr<const FOOTPRINT> fp( oldFilePI->GetEnumeratedFootprint( aOldFilePath, fpName,
283 &aOldFileProps ) );
284
285 try
286 {
287 kicadPI->FootprintSave( aNewFilePath, fp.get(), &props );
288 }
289 catch( ... )
290 {
291 // Footprints that cannot be saved are just skipped. This is not see
292 // as a fatal error.
293 // this can be just a illegal filename used for the footprint
294 if( aReporter )
295 {
296 aReporter->Report( wxString::Format( "Footprint \"%s\" can't be saved. Skipped",
297 fpName ),
299 }
300 }
301 }
302 }
303 catch( IO_ERROR& io_err )
304 {
305 if( aReporter )
306 {
307 aReporter->Report( wxString::Format( "Library '%s' Convert err: \"%s\"",
308 aOldFilePath,
309 io_err.What() ),
311 }
312
313 return false;
314 }
315 catch( ... )
316 {
317 return false;
318 }
319
320 return true;
321}
322
323
324// These text strings are "truth" for identifying the plugins. If you change the spellings,
325// you will obsolete library tables, so don't do it. Additions are OK.
326
327// clang-format off
330 wxT( "KiCad" ),
331 []() -> PCB_IO* { return new PCB_IO_KICAD_SEXPR; } );
332
335 wxT( "Legacy" ),
336 []() -> PCB_IO* { return new PCB_IO_KICAD_LEGACY; } );
337
338// Keep non-KiCad plugins in alphabetical order
339
342 wxT( "Allegro" ),
343 []() -> PCB_IO* { return new PCB_IO_ALLEGRO; } );
344
347 wxT( "Altium Circuit Maker" ),
348 []() -> PCB_IO* { return new PCB_IO_ALTIUM_CIRCUIT_MAKER; } );
349
352 wxT( "Altium Circuit Studio" ),
353 []() -> PCB_IO* { return new PCB_IO_ALTIUM_CIRCUIT_STUDIO; } );
354
357 wxT( "Altium Designer" ),
358 []() -> PCB_IO* { return new PCB_IO_ALTIUM_DESIGNER; } );
359
362 wxT( "CADSTAR PCB Archive" ),
363 []() -> PCB_IO* { return new PCB_IO_CADSTAR_ARCHIVE; } );
364
367 wxT( "Eagle" ),
368 []() -> PCB_IO* { return new PCB_IO_EAGLE; } );
369
372 wxT( "EasyEDA / JLCEDA Std" ),
373 []() -> PCB_IO* { return new PCB_IO_EASYEDA; });
374
377 wxT( "EasyEDA / JLCEDA Pro" ),
378 []() -> PCB_IO* { return new PCB_IO_EASYEDAPRO; });
379
382 wxT( "EasyEDA / JLCEDA Pro v3" ),
383 []() -> PCB_IO* { return new PCB_IO_EASYEDAPRO_V3; });
384
387 wxT( "Fabmaster" ),
388 []() -> PCB_IO* { return new PCB_IO_FABMASTER; } );
389
392 wxT( "gEDA / Lepton EDA" ),
393 []() -> PCB_IO* { return new PCB_IO_GEDA; } );
394
397 wxT( "P-Cad" ),
398 []() -> PCB_IO* { return new PCB_IO_PCAD; } );
399
402 wxT( "Solidworks PCB" ),
403 []() -> PCB_IO* { return new PCB_IO_SOLIDWORKS; } );
404
407 wxT( "IPC-2581" ),
408 []() -> PCB_IO* { return new PCB_IO_IPC2581; } );
409
412 wxT( "ODB++" ),
413 []() -> PCB_IO* { return new PCB_IO_ODBPP; } );
414
417 wxT( "PADS" ),
418 []() -> PCB_IO* { return new PCB_IO_PADS(); } );
419
422 wxT( "Sprint Layout" ),
423 []() -> PCB_IO* { return new PCB_IO_SPRINT_LAYOUT; } );
424
427 wxT( "DipTrace" ),
428 []() -> PCB_IO* { return new PCB_IO_DIPTRACE; } );
429
432 wxT( "Easy-PC" ),
433 []() -> PCB_IO* { return new PCB_IO_EASYPC; } );
434
437 wxT( "TARGET 3001!" ),
438 []() -> PCB_IO* { return new PCB_IO_TARGET3001; } );
439
442 wxT( "Protel Autotrax" ),
443 []() -> PCB_IO* { return new PCB_IO_AUTOTRAX; } );
444
447 wxT( "PADS Binary" ),
448 []() -> PCB_IO* { return new PCB_IO_PADS_BINARY(); } );
449// clang-format on
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:411
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
tl::expected< LIBRARY_TABLE_IR, LIBRARY_PARSE_ERROR > Parse(const std::filesystem::path &aPath)
static const wxString TABLE_TYPE_NAME
Read-only importer for Protel Autotrax (.PCB, "PCB FILE 4") and Easytrax (.PCB, "PCB FILE 5") layout ...
Works with Eagle 6.x XML board files and footprints to implement the Pcbnew PCB_IO API or a portion o...
A PCB_IO derivation for saving and loading Geda PCB files.
Definition pcb_io_geda.h:59
A PCB_IO derivation which could possibly be put into a DLL/DSO.
A PCB_IO derivation for saving and loading Pcbnew s-expression formatted files.
PCB_IO * Create(PCB_FILE_T aFileType) const
Definition pcb_io_mgr.h:121
const std::vector< ENTRY > & AllPlugins() const
Definition pcb_io_mgr.h:134
static PLUGIN_REGISTRY * Instance()
Definition pcb_io_mgr.h:100
static bool ConvertLibrary(const std::map< std::string, UTF8 > &aOldFileProps, const wxString &aOldFilePath, const wxString &aNewFilePath, REPORTER *aReporter)
Convert a schematic symbol library to the latest KiCad format.
static bool ImportPopulatesProjectSettings(PCB_FILE_T aFileType)
Return true when importing aFileType writes netclasses, rules or other settings that belong to the pr...
static PCB_FILE_T EnumFromStr(const wxString &aFileType)
Return the PCB_FILE_T from the corresponding plugin type name: "kicad", "legacy", etc.
PCB_FILE_T
The set of file types that the PCB_IO_MGR knows about, and for which there has been a plugin written,...
Definition pcb_io_mgr.h:52
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:54
@ EASYPC
Easy-PC / DesignSpark PCB.
Definition pcb_io_mgr.h:76
@ TARGET3001
TARGET 3001! project.
Definition pcb_io_mgr.h:77
@ GEDA_PCB
Geda PCB file formats.
Definition pcb_io_mgr.h:66
@ ALTIUM_DESIGNER
Definition pcb_io_mgr.h:59
@ LEGACY
Legacy Pcbnew file formats prior to s-expression.
Definition pcb_io_mgr.h:55
@ ALTIUM_CIRCUIT_MAKER
Definition pcb_io_mgr.h:57
@ ALTIUM_CIRCUIT_STUDIO
Definition pcb_io_mgr.h:58
@ CADSTAR_PCB_ARCHIVE
Definition pcb_io_mgr.h:60
@ PCB_FILE_UNKNOWN
0 is not a legal menu id on Mac
Definition pcb_io_mgr.h:53
static void Save(PCB_FILE_T aFileType, const wxString &aFileName, BOARD &aBoard, const std::map< std::string, UTF8 > *aProperties=nullptr)
Write either a full aBoard to a storage file in a format that this implementation knows about,...
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a PCB_IO which the caller can use to import, export, save, or load design documents.
static PCB_FILE_T FindPluginTypeFromBoardPath(const wxString &aFileName, int aCtl=0)
Return a plugin type given a path for a board file.
static std::unique_ptr< BOARD > Load(PCB_FILE_T aFileType, const wxString &aFileName, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Find the requested PCB_IO and if found, calls the PCB_IO::LoadBoard() function on it using the argume...
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a footprint library's libPath.
static bool ImportGeneratesProjectLibrary(PCB_FILE_T aFileType)
Return true when importing aFileType should materialize a project footprint library.
static const wxString ShowType(PCB_FILE_T aFileType)
Return a brief name for a plugin given aFileType enum.
PCB I/O plugin for importing the native PADS Layout binary .pcb format, distinct from the ASCII forma...
Imports TARGET 3001!
A base class that BOARD loading and saving plugins should derive from.
Definition pcb_io.h:78
A progress reporter interface for use in multi-threaded environments.
Container for project specific data.
Definition project.h:63
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition reporter.h:102
#define _(s)
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
#define KICTL_KICAD_ONLY
chosen file is from KiCad according to user
#define KICTL_NONKICAD_ONLY
chosen file is non-KiCad according to user
Reader for TARGET 3001!
Pcbnew PCB_IO for DipTrace binary .dip board files.
PCB_IO for Number One Systems Easy-PC and RS DesignSpark PCB boards and symbol libraries (....
Geda PCB file plugin definition file.
static PCB_IO_MGR::REGISTER_PLUGIN registerODBPPPlugin(PCB_IO_MGR::ODBPP, wxT("ODB++"), []() -> PCB_IO *{ return new PCB_IO_ODBPP;})
static PCB_IO_MGR::REGISTER_PLUGIN registerEasyEDAProV3Plugin(PCB_IO_MGR::EASYEDAPRO_V3, wxT("EasyEDA / JLCEDA Pro v3"), []() -> PCB_IO *{ return new PCB_IO_EASYEDAPRO_V3;})
static PCB_IO_MGR::REGISTER_PLUGIN registerSolidworksPCBPlugin(PCB_IO_MGR::SOLIDWORKS_PCB, wxT("Solidworks PCB"), []() -> PCB_IO *{ return new PCB_IO_SOLIDWORKS;})
static PCB_IO_MGR::REGISTER_PLUGIN registerEasyEDAProPlugin(PCB_IO_MGR::EASYEDAPRO, wxT("EasyEDA / JLCEDA Pro"), []() -> PCB_IO *{ return new PCB_IO_EASYEDAPRO;})
static PCB_IO_MGR::REGISTER_PLUGIN registerPadsBinaryPlugin(PCB_IO_MGR::PADS_BINARY, wxT("PADS Binary"), []() -> PCB_IO *{ return new PCB_IO_PADS_BINARY();})
static PCB_IO_MGR::REGISTER_PLUGIN registerTarget3001Plugin(PCB_IO_MGR::TARGET3001, wxT("TARGET 3001!"), []() -> PCB_IO *{ return new PCB_IO_TARGET3001;})
static PCB_IO_MGR::REGISTER_PLUGIN registerPadsPlugin(PCB_IO_MGR::PADS, wxT("PADS"), []() -> PCB_IO *{ return new PCB_IO_PADS();})
static PCB_IO_MGR::REGISTER_PLUGIN registerEasyEDAPlugin(PCB_IO_MGR::EASYEDA, wxT("EasyEDA / JLCEDA Std"), []() -> PCB_IO *{ return new PCB_IO_EASYEDA;})
static PCB_IO_MGR::REGISTER_PLUGIN registerGPCBPlugin(PCB_IO_MGR::GEDA_PCB, wxT("gEDA / Lepton EDA"), []() -> PCB_IO *{ return new PCB_IO_GEDA;})
static PCB_IO_MGR::REGISTER_PLUGIN registerKicadPlugin(PCB_IO_MGR::KICAD_SEXP, wxT("KiCad"), []() -> PCB_IO *{ return new PCB_IO_KICAD_SEXPR;})
static PCB_IO_MGR::REGISTER_PLUGIN registerIPC2581Plugin(PCB_IO_MGR::IPC2581, wxT("IPC-2581"), []() -> PCB_IO *{ return new PCB_IO_IPC2581;})
static PCB_IO_MGR::REGISTER_PLUGIN registerPcadPlugin(PCB_IO_MGR::PCAD, wxT("P-Cad"), []() -> PCB_IO *{ return new PCB_IO_PCAD;})
static PCB_IO_MGR::REGISTER_PLUGIN registerEaglePlugin(PCB_IO_MGR::EAGLE, wxT("Eagle"), []() -> PCB_IO *{ return new PCB_IO_EAGLE;})
static PCB_IO_MGR::REGISTER_PLUGIN registerEasyPcPlugin(PCB_IO_MGR::EASYPC, wxT("Easy-PC"), []() -> PCB_IO *{ return new PCB_IO_EASYPC;})
static PCB_IO_MGR::REGISTER_PLUGIN registerAltiumCircuitStudioPlugin(PCB_IO_MGR::ALTIUM_CIRCUIT_STUDIO, wxT("Altium Circuit Studio"), []() -> PCB_IO *{ return new PCB_IO_ALTIUM_CIRCUIT_STUDIO;})
static PCB_IO_MGR::REGISTER_PLUGIN registerAltiumDesignerPlugin(PCB_IO_MGR::ALTIUM_DESIGNER, wxT("Altium Designer"), []() -> PCB_IO *{ return new PCB_IO_ALTIUM_DESIGNER;})
static PCB_IO_MGR::REGISTER_PLUGIN registerCadstarArchivePlugin(PCB_IO_MGR::CADSTAR_PCB_ARCHIVE, wxT("CADSTAR PCB Archive"), []() -> PCB_IO *{ return new PCB_IO_CADSTAR_ARCHIVE;})
static PCB_IO_MGR::REGISTER_PLUGIN registerDipTracePlugin(PCB_IO_MGR::DIPTRACE, wxT("DipTrace"), []() -> PCB_IO *{ return new PCB_IO_DIPTRACE;})
static PCB_IO_MGR::REGISTER_PLUGIN registerLegacyPlugin(PCB_IO_MGR::LEGACY, wxT("Legacy"), []() -> PCB_IO *{ return new PCB_IO_KICAD_LEGACY;})
static PCB_IO_MGR::REGISTER_PLUGIN registerFabmasterPlugin(PCB_IO_MGR::FABMASTER, wxT("Fabmaster"), []() -> PCB_IO *{ return new PCB_IO_FABMASTER;})
static PCB_IO_MGR::REGISTER_PLUGIN registerAltiumCircuitMakerPlugin(PCB_IO_MGR::ALTIUM_CIRCUIT_MAKER, wxT("Altium Circuit Maker"), []() -> PCB_IO *{ return new PCB_IO_ALTIUM_CIRCUIT_MAKER;})
static PCB_IO_MGR::REGISTER_PLUGIN registerAutotraxPlugin(PCB_IO_MGR::AUTOTRAX, wxT("Protel Autotrax"), []() -> PCB_IO *{ return new PCB_IO_AUTOTRAX;})
static PCB_IO_MGR::REGISTER_PLUGIN registerSprintLayoutPlugin(PCB_IO_MGR::SPRINT_LAYOUT, wxT("Sprint Layout"), []() -> PCB_IO *{ return new PCB_IO_SPRINT_LAYOUT;})
static PCB_IO_MGR::REGISTER_PLUGIN registerAllegroPlugin(PCB_IO_MGR::ALLEGRO, wxT("Allegro"), []() -> PCB_IO *{ return new PCB_IO_ALLEGRO;})
Pcbnew PLUGIN for P-Cad 200x ASCII *.pcb format.
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
#define FMT_NOTFOUND
Register a plugin.
Definition pcb_io_mgr.h:153
Definition of file extensions used in Kicad.