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  switch( aFileType )
64  {
65  case LEGACY:
66  return new LEGACY_PLUGIN();
67 
68  case KICAD:
69  return new PCB_IO();
70 
71  case EAGLE:
72  return new EAGLE_PLUGIN();
73 
74  case PCAD:
75  return new PCAD_PLUGIN();
76 
77  case GEDA_PCB:
78  return new GPCB_PLUGIN();
79 
80  case GITHUB:
81 #if defined(BUILD_GITHUB_PLUGIN)
82  return new GITHUB_PLUGIN();
83 #else
84  THROW_IO_ERROR( "BUILD_GITHUB_PLUGIN not enabled in cmake build environment" );
85 #endif
86 
87  case FILE_TYPE_NONE:
88  return NULL;
89  }
90 
91  return NULL;
92 }
93 
94 
95 void IO_MGR::PluginRelease( PLUGIN* aPlugin )
96 {
97  // This function is a place holder for a future point in time where
98  // the plugin is a DLL/DSO. It could do reference counting, and then
99  // unload the DLL/DSO when count goes to zero.
100 
101  delete aPlugin;
102 }
103 
104 
105 const wxString IO_MGR::ShowType( PCB_FILE_T aType )
106 {
107  // keep this function in sync with EnumFromStr() relative to the
108  // text spellings. If you change the spellings, you will obsolete
109  // library tables, so don't do change, only additions are ok.
110 
111  switch( aType )
112  {
113  default:
114  return wxString::Format( _( "Unknown PCB_FILE_T value: %d" ), aType );
115 
116  case LEGACY:
117  return wxString( wxT( "Legacy" ) );
118 
119  case KICAD:
120  return wxString( wxT( "KiCad" ) );
121 
122  case EAGLE:
123  return wxString( wxT( "Eagle" ) );
124 
125  case PCAD:
126  return wxString( wxT( "P-Cad" ) );
127 
128  case GEDA_PCB:
129  return wxString( wxT( "Geda-PCB" ) );
130 
131  case GITHUB:
132  return wxString( wxT( "Github" ) );
133  }
134 }
135 
136 
137 IO_MGR::PCB_FILE_T IO_MGR::EnumFromStr( const wxString& aType )
138 {
139  // keep this function in sync with ShowType() relative to the
140  // text spellings. If you change the spellings, you will obsolete
141  // library tables, so don't do change, only additions are ok.
142 
143  if( aType == wxT( "KiCad" ) )
144  return KICAD;
145 
146  if( aType == wxT( "Legacy" ) )
147  return LEGACY;
148 
149  if( aType == wxT( "Eagle" ) )
150  return EAGLE;
151 
152  if( aType == wxT( "P-Cad" ) )
153  return PCAD;
154 
155  if( aType == wxT( "Geda-PCB" ) )
156  return GEDA_PCB;
157 
158  if( aType == wxT( "Github" ) )
159  return GITHUB;
160 
161  // wxASSERT( blow up here )
162 
163  return PCB_FILE_T( -1 );
164 }
165 
166 
167 const wxString IO_MGR::GetFileExtension( PCB_FILE_T aFileType )
168 {
169  wxString ext = wxEmptyString;
170  PLUGIN* plugin = PluginFind( aFileType );
171 
172  if( plugin != NULL )
173  {
174  ext = plugin->GetFileExtension();
175  PluginRelease( plugin );
176  }
177 
178  return ext;
179 }
180 
181 
183 {
184  PCB_FILE_T ret = KICAD; // default guess, unless detected otherwise.
185  wxFileName fn( aLibPath );
186 
187  if( fn.GetExt() == LegacyFootprintLibPathExtension )
188  {
189  ret = LEGACY;
190  }
191  else if( fn.GetExt() == GedaPcbFootprintLibFileExtension )
192  {
193  ret = GEDA_PCB;
194  }
195  else if( fn.GetExt() == EagleFootprintLibPathExtension )
196  {
197  ret = EAGLE;
198  }
199 
200  // Test this one anyways, even though it's the default guess, to avoid
201  // the wxURI instantiation below.
202  // We default ret to KICAD above, because somebody might have
203  // mistakenly put a pretty library into a directory other than
204  // *.pretty/ with *.kicad_mod in there., and I don't want to return -1,
205  // since we only claimed to be guessing.
206  //
207  // However libraries on GitHub have names ending by .pretty
208  // so test also this is not a name starting by http (including https).
209  else if( fn.GetExt() == KiCadFootprintLibPathExtension &&
210  !aLibPath.StartsWith( wxT( "http" ) ) )
211  {
212  ret = KICAD;
213  }
214  else
215  {
216  // There is no extension for a remote repo, so test the server name.
217  wxURI uri( aLibPath );
218 
219  if( uri.HasServer() && uri.GetServer() == wxT( "github.com" ) )
220  {
221  ret = GITHUB;
222  }
223  }
224 
225  return ret;
226 }
227 
228 
229 BOARD* IO_MGR::Load( PCB_FILE_T aFileType, const wxString& aFileName,
230  BOARD* aAppendToMe, const PROPERTIES* aProperties )
231 {
232  // release the PLUGIN even if an exception is thrown.
233  PLUGIN::RELEASER pi( PluginFind( aFileType ) );
234 
235  if( (PLUGIN*) pi ) // test pi->plugin
236  {
237  return pi->Load( aFileName, aAppendToMe, aProperties ); // virtual
238  }
239 
240  THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );
241 }
242 
243 
244 void IO_MGR::Save( PCB_FILE_T aFileType, const wxString& aFileName, BOARD* aBoard, const PROPERTIES* aProperties )
245 {
246  // release the PLUGIN even if an exception is thrown.
247  PLUGIN::RELEASER pi( PluginFind( aFileType ) );
248 
249  if( (PLUGIN*) pi ) // test pi->plugin
250  {
251  pi->Save( aFileName, aBoard, aProperties ); // virtual
252  return;
253  }
254 
255  THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );
256 }
257 
const wxString KiCadFootprintLibPathExtension
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
static const wxString ShowType(PCB_FILE_T aFileType)
Function ShowType returns a brief name for a plugin, given aFileType enum.
Definition: io_mgr.cpp:105
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:182
Class RELEASER releases a PLUGIN in the context of a potential thrown exception, through its destruct...
Definition: io_mgr.h:474
Class EAGLE_PLUGIN works with Eagle 6.x XML board files and footprints to implement the Pcbnew PLUGIN...
Definition: eagle_plugin.h:83
const wxString GedaPcbFootprintLibFileExtension
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:137
S-expression Pcbnew file format.
Definition: io_mgr.h:54
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:229
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.
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:244
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:95
const wxString EagleFootprintLibPathExtension
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 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
const wxString LegacyFootprintLibPathExtension
Class PLUGIN is a base class that BOARD loading and saving plugins should derive from.
Definition: io_mgr.h:193
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
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
static const wxString GetFileExtension(PCB_FILE_T aFileType)
Function GetFileExtension returns the file extension for aFileType.
Definition: io_mgr.cpp:167