KiCad PCB EDA Suite
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 <dick@softplc.com>
5  * Copyright (C) 2016 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, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <wx/filename.h>
26 #include <wx/uri.h>
27 
28 #include <io_mgr.h>
29 #include <legacy_plugin.h>
30 #include <kicad_plugin.h>
31 #include <eagle_plugin.h>
33 #include <gpcb_plugin.h>
34 #include <config.h>
35 
36 #if defined(BUILD_GITHUB_PLUGIN)
37  #include <github/github_plugin.h>
38 #endif
39 
41 
42 #define FMT_UNIMPLEMENTED _( "Plugin \"%s\" does not implement the \"%s\" function." )
43 #define FMT_NOTFOUND _( "Plugin type \"%s\" is not found." )
44 
45 
46 // Some day plugins might be in separate DLL/DSOs, simply because of numbers of them
47 // and code size. Until then, use the simplest method:
48 
49 // This implementation is one of two which could be done.
50 // The other one would cater to DLL/DSO's. But since it would be nearly
51 // impossible to link a KICAD type DLL/DSO right now without pulling in all
52 // ::Draw() functions, I forgo that option temporarily.
53 
54 // Some day it may be possible to have some built in AND some DLL/DSO
55 // plugins coexisting.
56 
57 
59 {
60  // This implementation is subject to change, any magic is allowed here.
61  // The public IO_MGR API is the only pertinent public information.
62 
63  return PLUGIN_REGISTRY::Instance()->Create( aFileType );
64 }
65 
66 
67 void IO_MGR::PluginRelease( PLUGIN* aPlugin )
68 {
69  // This function is a place holder for a future point in time where
70  // the plugin is a DLL/DSO. It could do reference counting, and then
71  // unload the DLL/DSO when count goes to zero.
72 
73  delete aPlugin;
74 }
75 
76 
77 const wxString IO_MGR::ShowType( PCB_FILE_T aType )
78 {
79  const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
80 
81  for( const auto& plugin : plugins )
82  {
83  if ( plugin.m_type == aType )
84  {
85  return plugin.m_name;
86  }
87  }
88 
89  return wxString::Format( _( "UNKNOWN (%d)" ), aType );
90 }
91 
92 
93 IO_MGR::PCB_FILE_T IO_MGR::EnumFromStr( const wxString& aType )
94 {
95  const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
96 
97  for( const auto& plugin : plugins )
98  {
99  if ( plugin.m_name == aType )
100  {
101  return plugin.m_type;
102  }
103  }
104 
105  return PCB_FILE_T( -1 );
106 }
107 
108 
109 const wxString IO_MGR::GetFileExtension( PCB_FILE_T aFileType )
110 {
111  wxString ext = wxEmptyString;
112  PLUGIN* plugin = PluginFind( aFileType );
113 
114  if( plugin != NULL )
115  {
116  ext = plugin->GetFileExtension();
117  PluginRelease( plugin );
118  }
119 
120  return ext;
121 }
122 
123 
125 {
126  PCB_FILE_T ret = KICAD_SEXP; // default guess, unless detected otherwise.
127  wxFileName fn( aLibPath );
128 
129  if( fn.GetExt() == LegacyFootprintLibPathExtension )
130  {
131  ret = LEGACY;
132  }
133  else if( fn.GetExt() == GedaPcbFootprintLibFileExtension )
134  {
135  ret = GEDA_PCB;
136  }
137  else if( fn.GetExt() == EagleFootprintLibPathExtension )
138  {
139  ret = EAGLE;
140  }
141 
142  // Test this one anyways, even though it's the default guess, to avoid
143  // the wxURI instantiation below.
144  // We default ret to KICAD above, because somebody might have
145  // mistakenly put a pretty library into a directory other than
146  // *.pretty/ with *.kicad_mod in there., and I don't want to return -1,
147  // since we only claimed to be guessing.
148  //
149  // However libraries on GitHub have names ending by .pretty
150  // so test also this is not a name starting by http (including https).
151  else if( fn.GetExt() == KiCadFootprintLibPathExtension &&
152  !aLibPath.StartsWith( wxT( "http" ) ) )
153  {
154  ret = KICAD_SEXP;
155  }
156  else
157  {
158  // There is no extension for a remote repo, so test the server name.
159  wxURI uri( aLibPath );
160 
161  if( uri.HasServer() && uri.GetServer() == wxT( "github.com" ) )
162  {
163  ret = GITHUB;
164  }
165  }
166 
167  return ret;
168 }
169 
170 
171 BOARD* IO_MGR::Load( PCB_FILE_T aFileType, const wxString& aFileName,
172  BOARD* aAppendToMe, const PROPERTIES* aProperties )
173 {
174  // release the PLUGIN even if an exception is thrown.
175  PLUGIN::RELEASER pi( PluginFind( aFileType ) );
176 
177  if( (PLUGIN*) pi ) // test pi->plugin
178  {
179  return pi->Load( aFileName, aAppendToMe, aProperties ); // virtual
180  }
181 
182  THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );
183 }
184 
185 
186 void IO_MGR::Save( PCB_FILE_T aFileType, const wxString& aFileName, BOARD* aBoard, const PROPERTIES* aProperties )
187 {
188  // release the PLUGIN even if an exception is thrown.
189  PLUGIN::RELEASER pi( PluginFind( aFileType ) );
190 
191  if( (PLUGIN*) pi ) // test pi->plugin
192  {
193  pi->Save( aFileName, aBoard, aProperties ); // virtual
194  return;
195  }
196 
197  THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );
198 }
199 
200 // These text strings are "truth" for identifying the plugins. If you change the spellings,
201 // you will obsolete library tables, so don't do it. Additions are OK.
202 static IO_MGR::REGISTER_PLUGIN registerEaglePlugin( IO_MGR::EAGLE, wxT("Eagle"), []() -> PLUGIN* { return new EAGLE_PLUGIN; } );
203 static IO_MGR::REGISTER_PLUGIN registerKicadPlugin( IO_MGR::KICAD_SEXP, wxT("KiCad"), []() -> PLUGIN* { return new PCB_IO; } );
204 static IO_MGR::REGISTER_PLUGIN registerPcadPlugin( IO_MGR::PCAD, wxT("P-Cad"), []() -> PLUGIN* { return new PCAD_PLUGIN; } );
205 #ifdef BUILD_GITHUB_PLUGIN
206 static IO_MGR::REGISTER_PLUGIN registerGithubPlugin( IO_MGR::GITHUB, wxT("Github"), []() -> PLUGIN* { return new GITHUB_PLUGIN; } );
207 #endif /* BUILD_GITHUB_PLUGIN */
208 static IO_MGR::REGISTER_PLUGIN registerLegacyPlugin( IO_MGR::LEGACY, wxT("Legacy"), []() -> PLUGIN* { return new LEGACY_PLUGIN; } );
209 static IO_MGR::REGISTER_PLUGIN registerGPCBPlugin( IO_MGR::GEDA_PCB, wxT("GEDA/Pcb"), []() -> PLUGIN* { return new GPCB_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerGPCBPlugin(IO_MGR::GEDA_PCB, wxT("GEDA/Pcb"), []() -> PLUGIN *{return new GPCB_PLUGIN;})
Class PCB_IO is a PLUGIN derivation for saving and loading Pcbnew s-expression formatted files...
virtual void Save(const wxString &aFileName, BOARD *aBoard, const PROPERTIES *aProperties=NULL)
Function Save will write aBoard to a storage file in a format that this PLUGIN implementation knows a...
Definition: plugin.cpp:54
Class GPCB_PLUGIN is a PLUGIN derivation for saving and loading Geda PCB files.
Definition: gpcb_plugin.h:47
const std::vector< ENTRY > & AllPlugins() const
Definition: io_mgr.h:116
static const wxString ShowType(PCB_FILE_T aFileType)
Function ShowType returns a brief name for a plugin, given aFileType enum.
Definition: io_mgr.cpp:77
Class PROPERTIES is a name/value tuple with unique names and optional values.
Definition: properties.h:34
Geda PCB file formats.
Definition: io_mgr.h:58
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath)
Function GuessPluginTypeFromLibPath returns a plugin type given a footprint library&#39;s libPath...
Definition: io_mgr.cpp:124
static IO_MGR::REGISTER_PLUGIN registerPcadPlugin(IO_MGR::PCAD, wxT("P-Cad"), []() -> PLUGIN *{return new PCAD_PLUGIN;})
const wxString LegacyFootprintLibPathExtension
Class RELEASER releases a PLUGIN in the context of a potential thrown exception, through its destruct...
Definition: io_mgr.h:563
Class EAGLE_PLUGIN works with Eagle 6.x XML board files and footprints to implement the Pcbnew PLUGIN...
Definition: eagle_plugin.h:109
Class LEGACY_PLUGIN is a PLUGIN derivation which could possibly be put into a DLL/DSO.
Definition: legacy_plugin.h:66
static PCB_FILE_T EnumFromStr(const wxString &aFileType)
Function EnumFromStr returns the PCB_FILE_T from the corresponding plugin type name: "kicad"...
Definition: io_mgr.cpp:93
static BOARD * Load(PCB_FILE_T aFileType, const wxString &aFileName, BOARD *aAppendToMe=NULL, const PROPERTIES *aProperties=NULL)
Function Load finds the requested PLUGIN and if found, calls the PLUGIN->Load(..) funtion on it using...
Definition: io_mgr.cpp:171
const wxString KiCadFootprintLibPathExtension
The common library.
Class GITHUB_PLUGIN implements a portion of pcbnew&#39;s PLUGIN interface to provide read only access to ...
#define FMT_NOTFOUND
Definition: io_mgr.cpp:43
virtual const wxString GetFileExtension() const =0
Function GetFileExtension returns the file extension for the PLUGIN.
const wxString GedaPcbFootprintLibFileExtension
static void Save(PCB_FILE_T aFileType, const wxString &aFileName, BOARD *aBoard, const PROPERTIES *aProperties=NULL)
Function Save will write either a full aBoard to a storage file in a format that this implementation ...
Definition: io_mgr.cpp:186
static void PluginRelease(PLUGIN *aPlugin)
Function PluginRelease releases a PLUGIN back to the system, and may cause it to be unloaded from mem...
Definition: io_mgr.cpp:67
static PLUGIN_REGISTRY * Instance()
Definition: io_mgr.h:84
Legacy Pcbnew file formats prior to s-expression.
Definition: io_mgr.h:54
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
Pcbnew PLUGIN for P-Cad 200x ASCII *.pcb format.
static IO_MGR::REGISTER_PLUGIN registerLegacyPlugin(IO_MGR::LEGACY, wxT("Legacy"), []() -> PLUGIN *{return new LEGACY_PLUGIN;})
static PLUGIN * PluginFind(PCB_FILE_T aFileType)
Function PluginFind returns a PLUGIN which the caller can use to import, export, save, or load design documents.
Definition: io_mgr.cpp:58
Class PLUGIN is a base class that BOARD loading and saving plugins should derive from.
Definition: io_mgr.h:266
static IO_MGR::REGISTER_PLUGIN registerEaglePlugin(IO_MGR::EAGLE, wxT("Eagle"), []() -> PLUGIN *{return new EAGLE_PLUGIN;})
PLUGIN * Create(PCB_FILE_T aFileType) const
Definition: io_mgr.h:104
static IO_MGR::REGISTER_PLUGIN registerKicadPlugin(IO_MGR::KICAD_SEXP, wxT("KiCad"), []() -> PLUGIN *{return new PCB_IO;})
const wxString EagleFootprintLibPathExtension
PCB_FILE_T
Enum PCB_FILE_T is a set of file types that the IO_MGR knows about, and for which there has been a pl...
Definition: io_mgr.h:52
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
Read only http://github.com repo holding pretty footprints.
Definition: io_mgr.h:59
Class REGISTER_PLUGIN Registers a plugin.
Definition: io_mgr.h:132
virtual BOARD * Load(const wxString &aFileName, BOARD *aAppendToMe, const PROPERTIES *aProperties=NULL)
Function Load loads information from some input file format that this PLUGIN implementation knows abo...
Definition: plugin.cpp:47
S-expression Pcbnew file format.
Definition: io_mgr.h:55
static const wxString GetFileExtension(PCB_FILE_T aFileType)
Function GetFileExtension returns the file extension for aFileType.
Definition: io_mgr.cpp:109