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  // keep this function in sync with EnumFromStr() relative to the
80  // text spellings. If you change the spellings, you will obsolete
81  // library tables, so don't do change, only additions are ok.
82 
83  const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
84 
85  for( const auto& plugin : plugins )
86  {
87  if ( plugin.m_type == aType )
88  {
89  return plugin.m_name;
90  }
91  }
92 
93  return wxString::Format( _( "Unknown PCB_FILE_T value: %d" ), aType );
94 }
95 
96 
97 IO_MGR::PCB_FILE_T IO_MGR::EnumFromStr( const wxString& aType )
98 {
99  // keep this function in sync with ShowType() relative to the
100  // text spellings. If you change the spellings, you will obsolete
101  // library tables, so don't do change, only additions are ok.
102 
103  const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
104 
105  for( const auto& plugin : plugins )
106  {
107  if ( plugin.m_name == aType )
108  {
109  return plugin.m_type;
110  }
111  }
112 
113  return PCB_FILE_T( -1 );
114 }
115 
116 
117 const wxString IO_MGR::GetFileExtension( PCB_FILE_T aFileType )
118 {
119  wxString ext = wxEmptyString;
120  PLUGIN* plugin = PluginFind( aFileType );
121 
122  if( plugin != NULL )
123  {
124  ext = plugin->GetFileExtension();
125  PluginRelease( plugin );
126  }
127 
128  return ext;
129 }
130 
131 
133 {
134  PCB_FILE_T ret = KICAD_SEXP; // default guess, unless detected otherwise.
135  wxFileName fn( aLibPath );
136 
137  if( fn.GetExt() == LegacyFootprintLibPathExtension )
138  {
139  ret = LEGACY;
140  }
141  else if( fn.GetExt() == GedaPcbFootprintLibFileExtension )
142  {
143  ret = GEDA_PCB;
144  }
145  else if( fn.GetExt() == EagleFootprintLibPathExtension )
146  {
147  ret = EAGLE;
148  }
149 
150  // Test this one anyways, even though it's the default guess, to avoid
151  // the wxURI instantiation below.
152  // We default ret to KICAD above, because somebody might have
153  // mistakenly put a pretty library into a directory other than
154  // *.pretty/ with *.kicad_mod in there., and I don't want to return -1,
155  // since we only claimed to be guessing.
156  //
157  // However libraries on GitHub have names ending by .pretty
158  // so test also this is not a name starting by http (including https).
159  else if( fn.GetExt() == KiCadFootprintLibPathExtension &&
160  !aLibPath.StartsWith( wxT( "http" ) ) )
161  {
162  ret = KICAD_SEXP;
163  }
164  else
165  {
166  // There is no extension for a remote repo, so test the server name.
167  wxURI uri( aLibPath );
168 
169  if( uri.HasServer() && uri.GetServer() == wxT( "github.com" ) )
170  {
171  ret = GITHUB;
172  }
173  }
174 
175  return ret;
176 }
177 
178 
179 BOARD* IO_MGR::Load( PCB_FILE_T aFileType, const wxString& aFileName,
180  BOARD* aAppendToMe, const PROPERTIES* aProperties )
181 {
182  // release the PLUGIN even if an exception is thrown.
183  PLUGIN::RELEASER pi( PluginFind( aFileType ) );
184 
185  if( (PLUGIN*) pi ) // test pi->plugin
186  {
187  return pi->Load( aFileName, aAppendToMe, aProperties ); // virtual
188  }
189 
190  THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );
191 }
192 
193 
194 void IO_MGR::Save( PCB_FILE_T aFileType, const wxString& aFileName, BOARD* aBoard, const PROPERTIES* aProperties )
195 {
196  // release the PLUGIN even if an exception is thrown.
197  PLUGIN::RELEASER pi( PluginFind( aFileType ) );
198 
199  if( (PLUGIN*) pi ) // test pi->plugin
200  {
201  pi->Save( aFileName, aBoard, aProperties ); // virtual
202  return;
203  }
204 
205  THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );
206 }
207 
208 static IO_MGR::REGISTER_PLUGIN registerEaglePlugin( IO_MGR::EAGLE, wxT("Eagle"), []() -> PLUGIN* { return new EAGLE_PLUGIN; } );
209 static IO_MGR::REGISTER_PLUGIN registerKicadPlugin( IO_MGR::KICAD_SEXP, wxT("KiCad"), []() -> PLUGIN* { return new PCB_IO; } );
210 static IO_MGR::REGISTER_PLUGIN registerPcadPlugin( IO_MGR::PCAD, wxT("P-Cad"), []() -> PLUGIN* { return new PCAD_PLUGIN; } );
211 #ifdef BUILD_GITHUB_PLUGIN
212 static IO_MGR::REGISTER_PLUGIN registerGithubPlugin( IO_MGR::GITHUB, wxT("Github"), []() -> PLUGIN* { return new GITHUB_PLUGIN; } );
213 #endif /* BUILD_GITHUB_PLUGIN */
214 static IO_MGR::REGISTER_PLUGIN registerLegacyPlugin( IO_MGR::LEGACY, wxT("Legacy"), []() -> PLUGIN* { return new LEGACY_PLUGIN; } );
215 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:115
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:57
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath)
Function GuessPluginTypeFromLibPath returns a plugin type given a footprint library's libPath...
Definition: io_mgr.cpp:132
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:546
Class EAGLE_PLUGIN works with Eagle 6.x XML board files and footprints to implement the Pcbnew PLUGIN...
Definition: eagle_plugin.h:83
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:97
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:179
const wxString KiCadFootprintLibPathExtension
The common library.
Class GITHUB_PLUGIN implements a portion of pcbnew'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:194
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:83
Legacy Pcbnew file formats prior to s-expression.
Definition: io_mgr.h:53
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:265
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:103
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:51
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
Read only http://github.com repo holding pretty footprints.
Definition: io_mgr.h:58
Class REGISTER_PLUGIN Registers a plugin.
Definition: io_mgr.h:131
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:54
static const wxString GetFileExtension(PCB_FILE_T aFileType)
Function GetFileExtension returns the file extension for aFileType.
Definition: io_mgr.cpp:117