You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

688 lines
29 KiB

++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
  1. #ifndef IO_MGR_H_
  2. #define IO_MGR_H_
  3. /*
  4. * This program source code file is part of KICAD, a free EDA CAD application.
  5. *
  6. * Copyright (C) 2011-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  7. * Copyright (C) 2016-2023 Kicad Developers, see AUTHORS.txt for contributors.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, you may find one here:
  21. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  22. * or you may search the http://www.gnu.org website for the version 2 license,
  23. * or you may write to the Free Software Foundation, Inc.,
  24. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  25. */
  26. #include <cstdint>
  27. #include <config.h>
  28. #include <vector>
  29. #include <wx/arrstr.h>
  30. #include <i18n_utility.h>
  31. class BOARD;
  32. class PLUGIN;
  33. class FOOTPRINT;
  34. class STRING_UTF8_MAP;
  35. class PROJECT;
  36. class PROGRESS_REPORTER;
  37. /**
  38. * A factory which returns an instance of a #PLUGIN.
  39. */
  40. class IO_MGR
  41. {
  42. public:
  43. /**
  44. * The set of file types that the IO_MGR knows about, and for which there has been a
  45. * plugin written, in alphabetical order.
  46. */
  47. enum PCB_FILE_T
  48. {
  49. KICAD_SEXP, ///< S-expression Pcbnew file format.
  50. LEGACY, ///< Legacy Pcbnew file formats prior to s-expression.
  51. ALTIUM_CIRCUIT_MAKER,
  52. ALTIUM_CIRCUIT_STUDIO,
  53. ALTIUM_DESIGNER,
  54. CADSTAR_PCB_ARCHIVE,
  55. EAGLE,
  56. FABMASTER,
  57. GEDA_PCB, ///< Geda PCB file formats.
  58. PCAD,
  59. SOLIDWORKS_PCB,
  60. // add your type here.
  61. // etc.
  62. FILE_TYPE_NONE
  63. };
  64. /**
  65. * Hold a list of available plugins, created using a singleton REGISTER_PLUGIN object.
  66. * This way, plugins can be added link-time.
  67. */
  68. class PLUGIN_REGISTRY
  69. {
  70. public:
  71. struct ENTRY
  72. {
  73. PCB_FILE_T m_type;
  74. std::function<PLUGIN*(void)> m_createFunc;
  75. wxString m_name;
  76. };
  77. static PLUGIN_REGISTRY *Instance()
  78. {
  79. static PLUGIN_REGISTRY *self = nullptr;
  80. if( !self )
  81. {
  82. self = new PLUGIN_REGISTRY;
  83. }
  84. return self;
  85. }
  86. void Register( PCB_FILE_T aType, const wxString& aName,
  87. std::function<PLUGIN*(void)> aCreateFunc )
  88. {
  89. ENTRY ent;
  90. ent.m_type = aType;
  91. ent.m_createFunc = aCreateFunc;
  92. ent.m_name = aName;
  93. m_plugins.push_back( ent );
  94. }
  95. PLUGIN* Create( PCB_FILE_T aFileType ) const
  96. {
  97. for( auto& ent : m_plugins )
  98. {
  99. if ( ent.m_type == aFileType )
  100. {
  101. return ent.m_createFunc();
  102. }
  103. }
  104. return nullptr;
  105. }
  106. const std::vector<ENTRY>& AllPlugins() const
  107. {
  108. return m_plugins;
  109. }
  110. private:
  111. std::vector<ENTRY> m_plugins;
  112. };
  113. /**
  114. * Register a plugin.
  115. *
  116. * Declare as a static variable in an anonymous namespace.
  117. *
  118. * @param aType type of the plugin
  119. * @param aName name of the file format
  120. * @param aCreateFunc function that creates a new object for the plugin.
  121. */
  122. struct REGISTER_PLUGIN
  123. {
  124. REGISTER_PLUGIN( PCB_FILE_T aType, const wxString& aName,
  125. std::function<PLUGIN*(void)> aCreateFunc )
  126. {
  127. PLUGIN_REGISTRY::Instance()->Register( aType, aName, aCreateFunc );
  128. }
  129. };
  130. /**
  131. * Return a #PLUGIN which the caller can use to import, export, save, or load
  132. * design documents.
  133. *
  134. * The returned #PLUGIN, may be reference counted, so please call PluginRelease() when you
  135. * are done using the returned #PLUGIN. It may or may not be code running from a DLL/DSO.
  136. *
  137. * @note The caller owns the returned object and must call PluginRelease when done using it.
  138. *
  139. * @param aFileType is from #PCB_FILE_T and tells which plugin to find.
  140. * @return the plug in corresponding to \a aFileType or NULL if not found.
  141. */
  142. static PLUGIN* PluginFind( PCB_FILE_T aFileType );
  143. /**
  144. * Release a #PLUGIN back to the system and may cause it to be unloaded from memory.
  145. *
  146. * @param aPlugin is the one to be released, and which is no longer usable
  147. * after calling this.
  148. */
  149. static void PluginRelease( PLUGIN* aPlugin );
  150. /**
  151. * Return a brief name for a plugin given \a aFileType enum.
  152. */
  153. static const wxString ShowType( PCB_FILE_T aFileType );
  154. /**
  155. * Return the #PCB_FILE_T from the corresponding plugin type name: "kicad", "legacy", etc.
  156. */
  157. static PCB_FILE_T EnumFromStr( const wxString& aFileType );
  158. /**
  159. * Return a plugin type given a path for a board file. FILE_TYPE_NONE if the file is not known.
  160. */
  161. static PCB_FILE_T FindPluginTypeFromBoardPath( const wxString& aFileName, int aCtl = 0 );
  162. /**
  163. * Return a plugin type given a footprint library's libPath.
  164. */
  165. static PCB_FILE_T GuessPluginTypeFromLibPath( const wxString& aLibPath );
  166. /**
  167. * Find the requested #PLUGIN and if found, calls the #PLUGIN::LoadBoard() function
  168. * on it using the arguments passed to this function. After the #PLUGIN::LoadBoard()
  169. * function returns, the #PLUGIN is Released() as part of this call.
  170. *
  171. * @param aFileType is the #PCB_FILE_T of file to load.
  172. * @param aFileName is the name of the file to load.
  173. * @param aAppendToMe is an existing BOARD to append to, use NULL if fresh
  174. * board load is wanted.
  175. * @param aProperties is an associative array that allows the caller to
  176. * pass additional tuning parameters to the PLUGIN.
  177. * @param aProject is the optional #PROJECT object primarily used by third party
  178. * importers.
  179. * @return the loaded #BOARD object. The caller owns it an it will never NULL because
  180. * exception thrown if error.
  181. *
  182. * @throw IO_ERROR if the #PLUGIN cannot be found, file cannot be found, or file cannot
  183. * be loaded.
  184. */
  185. static BOARD* Load( PCB_FILE_T aFileType, const wxString& aFileName,
  186. BOARD* aAppendToMe = nullptr, const STRING_UTF8_MAP* aProperties = nullptr,
  187. PROJECT* aProject = nullptr,
  188. PROGRESS_REPORTER* aProgressReporter = nullptr );
  189. /**
  190. * Write either a full \a aBoard to a storage file in a format that this implementation
  191. * knows about, or it can be used to write a portion of\a aBoard to a special kind of
  192. * export file.
  193. *
  194. * @param aFileType is the #PCB_FILE_T of file to save.
  195. * @param aFileName is the name of a file to save to on disk.
  196. * @param aBoard is the #BOARD document (data tree) to save or export to disk.
  197. * @param aBoard is the in memory document tree from which to extract information when
  198. * writing to \a aFileName. The caller continues to own the #BOARD, and
  199. * the plugin should refrain from modifying the #BOARD if possible.
  200. * @param aProperties is an associative array that can be used to tell the saver how to
  201. * save the file, because it can take any number of additional named
  202. * tuning arguments that the plugin is known to support. The caller
  203. * continues to own this object (plugin may not delete it), and plugins
  204. * should expect it to be optionally NULL.
  205. *
  206. * @throw IO_ERROR if there is a problem saving or exporting.
  207. */
  208. static void Save( PCB_FILE_T aFileType, const wxString& aFileName, BOARD* aBoard,
  209. const STRING_UTF8_MAP* aProperties = nullptr );
  210. };
  211. /**
  212. * Container that describes file type info
  213. */
  214. struct PLUGIN_FILE_DESC
  215. {
  216. wxString m_Description; ///< Description shown in the file picker dialog
  217. std::vector<std::string> m_FileExtensions; ///< Filter used for file pickers if m_IsFile is true
  218. std::vector<std::string> m_ExtensionsInDir; ///< In case of folders: extensions of files inside
  219. bool m_IsFile; ///< Whether the library is a folder or a file
  220. PLUGIN_FILE_DESC( const wxString& aDescription, const std::vector<std::string>& aFileExtensions,
  221. const std::vector<std::string>& aExtsInFolder = {}, bool aIsFile = true ) :
  222. m_Description( aDescription ),
  223. m_FileExtensions( aFileExtensions ), m_ExtensionsInDir( aExtsInFolder ),
  224. m_IsFile( aIsFile )
  225. {
  226. }
  227. /**
  228. * @return translated description + wildcards string for file dialogs.
  229. */
  230. wxString FileFilter() const;
  231. operator bool() const { return !m_Description.empty(); }
  232. };
  233. /**
  234. * A base class that #BOARD loading and saving plugins should derive from.
  235. *
  236. * Implementations can provide either Load() or Save() functions, or both. PLUGINs throw
  237. * exceptions, so it is best that you wrap your calls to these functions in a try catch block.
  238. * Plugins throw exceptions because it is illegal for them to have any user interface calls in
  239. * them whatsoever, i.e. no windowing or screen printing at all.
  240. *
  241. *The compiler writes the "zero argument" constructor for a PLUGIN automatically if you do
  242. * not provide one. If you decide you need to provide a zero argument constructor of your
  243. * own design, that is allowed. It must be public, and it is what the #IO_MGR uses. Parameters
  244. * may be passed into a PLUGIN via the #PROPERTIES variable for any of the public API functions
  245. * which take one.
  246. *
  247. *
  248. * <pre>
  249. * try
  250. * {
  251. * IO_MGR::Load(...);
  252. * or
  253. * IO_MGR::Save(...);
  254. * }
  255. * catch( const IO_ERROR& ioe )
  256. * {
  257. * // grab text from ioe, show in error window.
  258. * }
  259. * </pre>
  260. */
  261. class PLUGIN
  262. {
  263. public:
  264. /**
  265. * Return a brief hard coded name for this PLUGIN.
  266. */
  267. virtual const wxString PluginName() const = 0;
  268. /**
  269. * Returns board file description for the PLUGIN.
  270. */
  271. virtual PLUGIN_FILE_DESC GetBoardFileDesc() const;
  272. /**
  273. * Returns footprint file description for the PLUGIN.
  274. */
  275. virtual PLUGIN_FILE_DESC GetFootprintFileDesc() const;
  276. /**
  277. * Returns footprint library description for the PLUGIN.
  278. */
  279. virtual PLUGIN_FILE_DESC GetFootprintLibDesc() const;
  280. /**
  281. * Checks if this PLUGIN can read the specified board file.
  282. * If not overriden, extension check is used.
  283. */
  284. virtual bool CanReadBoard( const wxString& aFileName ) const;
  285. /**
  286. * Checks if this PLUGIN can read a footprint from specified file or directory.
  287. * If not overriden, extension check is used.
  288. */
  289. virtual bool CanReadFootprint( const wxString& aFileName ) const;
  290. /**
  291. * Checks if this PLUGIN can read footprint library from specified file or directory.
  292. * If not overriden, extension check is used.
  293. */
  294. virtual bool CanReadFootprintLib( const wxString& aFileName ) const;
  295. /**
  296. * Registers a KIDIALOG callback for collecting info from the user.
  297. */
  298. virtual void SetQueryUserCallback( std::function<bool( wxString aTitle, int aIcon,
  299. wxString aMessage,
  300. wxString aAction )> aCallback )
  301. { }
  302. /**
  303. * Load information from some input file format that this PLUGIN implementation
  304. * knows about into either a new #BOARD or an existing one.
  305. *
  306. * This may be used to load an entire new #BOARD, or to augment an existing one if
  307. * @a aAppendToMe is not NULL.
  308. *
  309. * @param aFileName is the name of the file to use as input and may be foreign in
  310. * nature or native in nature.
  311. * @param aAppendToMe is an existing BOARD to append to, but if NULL then this means
  312. * "do not append, rather load anew".
  313. * @param aProperties is an associative array that can be used to tell the loader how to
  314. * load the file, because it can take any number of additional named
  315. * arguments that the plugin is known to support. These are tuning
  316. * parameters for the import or load. The caller continues to own
  317. * this object (plugin may not delete it), and plugins should expect
  318. * it to be optionally NULL.
  319. * @param aProject is the optional #PROJECT object primarily used by third party
  320. * importers.
  321. * @param aProgressReporter an optional progress reporter
  322. * @param aLineCount a line count (necessary if a progress reporter is supplied)
  323. * @return the successfully loaded board, or the same one as \a aAppendToMe if aAppendToMe
  324. * was not NULL, and caller owns it.
  325. *
  326. * @throw IO_ERROR if there is a problem loading, and its contents should say what went
  327. * wrong, using line number and character offsets of the input file if
  328. * possible.
  329. */
  330. virtual BOARD* LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
  331. const STRING_UTF8_MAP* aProperties = nullptr, PROJECT* aProject = nullptr,
  332. PROGRESS_REPORTER* aProgressReporter = nullptr );
  333. /**
  334. * Return a container with the cached library footprints generated in the last call to
  335. * #Load. This function is intended to be used ONLY by the non-KiCad board importers for the
  336. * purpose of obtaining the footprint library of the design and creating a project-specific
  337. * library.
  338. *
  339. * @return Footprints (caller owns the objects)
  340. */
  341. virtual std::vector<FOOTPRINT*> GetImportedCachedLibraryFootprints();
  342. /**
  343. * Write @a aBoard to a storage file in a format that this PLUGIN implementation knows
  344. * about or it can be used to write a portion of \a aBoard to a special kind of export
  345. * file.
  346. *
  347. * @param aFileName is the name of a file to save to on disk.
  348. * @param aBoard is the class #BOARD in memory document tree from which to extract
  349. * information when writing to \a aFileName. The caller continues to
  350. * own the BOARD, and the plugin should refrain from modifying the BOARD
  351. * if possible.
  352. * @param aProperties is an associative array that can be used to tell the saver how to
  353. * save the file, because it can take any number of additional named
  354. * tuning arguments that the plugin is known to support. The caller
  355. * continues to own this object (plugin may not delete it) and plugins
  356. * should expect it to be optionally NULL.
  357. *
  358. * @throw IO_ERROR if there is a problem saving or exporting.
  359. */
  360. virtual void SaveBoard( const wxString& aFileName, BOARD* aBoard,
  361. const STRING_UTF8_MAP* aProperties = nullptr );
  362. /**
  363. * Return a list of footprint names contained within the library at @a aLibraryPath.
  364. *
  365. * @param aLibraryPath is a locator for the "library", usually a directory, file,
  366. * or URL containing several footprints.
  367. * @param aProperties is an associative array that can be used to tell the plugin
  368. * anything needed about how to perform with respect to @a aLibraryPath.
  369. * The caller continues to own this object (plugin may not delete it),
  370. * and plugins should expect it to be optionally NULL.
  371. * @param aFootprintNames is the array of available footprint names inside a library.
  372. * @param aBestEfforts if true, don't throw on errors, just return an empty list.
  373. *
  374. * @throw IO_ERROR if the library cannot be found, or footprint cannot be loaded.
  375. */
  376. virtual void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
  377. bool aBestEfforts, const STRING_UTF8_MAP* aProperties = nullptr );
  378. /**
  379. * Generate a timestamp representing all the files in the library (including the library
  380. * directory).
  381. *
  382. * Timestamps should not be considered ordered, they either match or they don't.
  383. */
  384. virtual long long GetLibraryTimestamp( const wxString& aLibraryPath ) const = 0;
  385. /**
  386. * If possible, prefetches the specified library (e.g. performing downloads). Does not parse.
  387. * Threadsafe.
  388. *
  389. * This is a no-op for libraries that cannot be prefetched. Plugins that cannot prefetch
  390. * need not override this; a default no-op is provided.
  391. *
  392. * @param aLibraryPath is a locator for the "library", usually a directory, file, or URL
  393. * containing several footprints.
  394. *
  395. * @param aProperties is an associative array that can be used to tell the plugin anything
  396. * needed about how to perform with respect to @a aLibraryPath. The
  397. * caller continues to own this object (plugin may not delete it), and
  398. * plugins should expect it to be optionally NULL.
  399. *
  400. * @throw IO_ERROR if there is an error prefetching the library.
  401. */
  402. virtual void PrefetchLib( const wxString& aLibraryPath,
  403. const STRING_UTF8_MAP* aProperties = nullptr );
  404. /**
  405. * Load a single footprint from @a aFootprintPath and put its name in @a aFootprintNameOut.
  406. * If this is a footprint library, the first footprint should be loaded.
  407. * The default implementation uses FootprintEnumerate and FootprintLoad to load first footprint.
  408. *
  409. * @param aLibraryPath is a path of the footprint file.
  410. * @param aFootprintNameOut is the name output of the loaded footprint.
  411. * @param aProperties is an associative array that can be used to tell the loader
  412. * implementation to do something special, because it can take
  413. * any number of additional named tuning arguments that the plugin
  414. * is known to support. The caller continues to own this object
  415. * (plugin may not delete it), and plugins should expect it to be
  416. * optionally NULL.
  417. * @return the #FOOTPRINT object if found, caller owns it, else NULL if not found.
  418. *
  419. * @throw IO_ERROR if the footprint cannot be found or read.
  420. */
  421. virtual FOOTPRINT* ImportFootprint( const wxString& aFootprintPath, wxString& aFootprintNameOut,
  422. const STRING_UTF8_MAP* aProperties = nullptr );
  423. /**
  424. * Load a footprint having @a aFootprintName from the @a aLibraryPath containing a library
  425. * format that this PLUGIN knows about.
  426. *
  427. * @param aLibraryPath is a locator for the "library", usually a directory, file, or URL
  428. * containing several footprints.
  429. * @param aFootprintName is the name of the footprint to load.
  430. * @param aProperties is an associative array that can be used to tell the loader
  431. * implementation to do something special, because it can take
  432. * any number of additional named tuning arguments that the plugin
  433. * is known to support. The caller continues to own this object
  434. * (plugin may not delete it), and plugins should expect it to be
  435. * optionally NULL.
  436. * @param aKeepUUID = true to keep initial items UUID, false to set new UUID
  437. * normally true if loaded in the footprint editor, false
  438. * if loaded in the board editor. Make sense only in kicad_plugin
  439. * @return the #FOOTPRINT object if found, caller owns it, else NULL if not found.
  440. *
  441. * @throw IO_ERROR if the library cannot be found or read. No exception is thrown in
  442. * the case where \a aFootprintName cannot be found.
  443. */
  444. virtual FOOTPRINT* FootprintLoad( const wxString& aLibraryPath,
  445. const wxString& aFootprintName,
  446. bool aKeepUUID = false,
  447. const STRING_UTF8_MAP* aProperties = nullptr );
  448. /**
  449. * A version of FootprintLoad() for use after FootprintEnumerate() for more efficient
  450. * cache management.
  451. */
  452. virtual const FOOTPRINT* GetEnumeratedFootprint( const wxString& aLibraryPath,
  453. const wxString& aFootprintName,
  454. const STRING_UTF8_MAP* aProperties = nullptr );
  455. /**
  456. * Check for the existence of a footprint.
  457. */
  458. virtual bool FootprintExists( const wxString& aLibraryPath, const wxString& aFootprintName,
  459. const STRING_UTF8_MAP* aProperties = nullptr );
  460. /**
  461. * Write @a aFootprint to an existing library located at @a aLibraryPath.
  462. * If a footprint by the same name already exists, it is replaced.
  463. *
  464. * @param aLibraryPath is a locator for the "library", usually a directory, file, or URL
  465. * containing several footprints.
  466. * @param aFootprint is what to store in the library. The caller continues to own the
  467. * footprint after this call.
  468. * @param aProperties is an associative array that can be used to tell the saver how to
  469. * save the footprint, because it can take any number of additional
  470. * named tuning arguments that the plugin is known to support. The
  471. * caller continues to own this object (plugin may not delete it), and
  472. * plugins should expect it to be optionally NULL.
  473. *
  474. * @throw IO_ERROR if there is a problem saving.
  475. */
  476. virtual void FootprintSave( const wxString& aLibraryPath, const FOOTPRINT* aFootprint,
  477. const STRING_UTF8_MAP* aProperties = nullptr );
  478. /**
  479. * Delete @a aFootprintName from the library at @a aLibraryPath.
  480. *
  481. * @param aLibraryPath is a locator for the "library", usually a directory, file, or URL
  482. * containing several footprints.
  483. * @param aFootprintName is the name of a footprint to delete from the specified library.
  484. * @param aProperties is an associative array that can be used to tell the library delete
  485. * function anything special, because it can take any number of additional
  486. * named tuning arguments that the plugin is known to support. The caller
  487. * continues to own this object (plugin may not delete it), and plugins
  488. * should expect it to be optionally NULL.
  489. *
  490. * @throw IO_ERROR if there is a problem finding the footprint or the library, or deleting it.
  491. */
  492. virtual void FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName,
  493. const STRING_UTF8_MAP* aProperties = nullptr );
  494. /**
  495. * Create a new empty footprint library at @a aLibraryPath empty.
  496. *
  497. * It is an error to attempt to create an existing library or to attempt to create
  498. * on a "read only" location.
  499. *
  500. * @param aLibraryPath is a locator for the "library", usually a directory, file, or URL
  501. * containing several footprints.
  502. * @param aProperties is an associative array that can be used to tell the library create
  503. * function anything special, because it can take any number of additional
  504. * named tuning arguments that the plugin is known to support. The caller
  505. * continues to own this object (plugin may not delete it), and plugins
  506. * should expect it to be optionally NULL.
  507. *
  508. * @throw IO_ERROR if there is a problem finding the library, or creating it.
  509. */
  510. virtual void FootprintLibCreate( const wxString& aLibraryPath,
  511. const STRING_UTF8_MAP* aProperties = nullptr );
  512. /**
  513. * Delete an existing footprint library and returns true, or if library does not
  514. * exist returns false, or throws an exception if library exists but is read only or
  515. * cannot be deleted for some other reason.
  516. *
  517. * @param aLibraryPath is a locator for the "library", usually a directory or file which
  518. * will contain footprints.
  519. * @param aProperties is an associative array that can be used to tell the library delete
  520. * implementation function anything special, because it can take any
  521. * number of additional named tuning arguments that the plugin is known
  522. * to support. The caller continues to own this object (plugin may not
  523. * delete it), and plugins should expect it to be optionally NULL.
  524. * @return true if library deleted, false if library did not exist.
  525. *
  526. * @throw IO_ERROR if there is a problem deleting an existing library.
  527. */
  528. virtual bool FootprintLibDelete( const wxString& aLibraryPath,
  529. const STRING_UTF8_MAP* aProperties = nullptr );
  530. /**
  531. * Return true if the library at @a aLibraryPath is writable.
  532. *
  533. * The system libraries are typically read only because of where they are installed..
  534. *
  535. * @param aLibraryPath is a locator for the "library", usually a directory, file, or URL
  536. * containing several footprints.
  537. *
  538. * @throw IO_ERROR if no library at aLibraryPath exists.
  539. */
  540. virtual bool IsFootprintLibWritable( const wxString& aLibraryPath );
  541. /**
  542. * Append supported PLUGIN options to @a aListToAppenTo along with internationalized
  543. * descriptions.
  544. *
  545. * Options are typically appended so that a derived #PLUGIN can call its base class
  546. * function by the same name first, thus inheriting options declared there. Some base
  547. * class options could pertain to all Footprint*() functions in all derived PLUGINs.
  548. *
  549. * @note Since aListToAppendTo is a #PROPERTIES object, all options will be unique and
  550. * last guy wins.
  551. *
  552. * @param aListToAppendTo holds a tuple of
  553. * <dl>
  554. * <dt>option</dt>
  555. * <dd>This eventually is what shows up into the fp-lib-table "options"
  556. * field, possibly combined with others.</dd>
  557. * <dt>internationalized description</dt>
  558. * <dd>The internationalized description is displayed in DIALOG_PLUGIN_OPTIONS.
  559. * It may be multi-line and be quite explanatory of the option.</dd>
  560. * </dl>
  561. * <br>
  562. * In the future perhaps @a aListToAppendTo evolves to something capable of also
  563. * holding a wxValidator for the cells in said dialog:
  564. * http://forums.wxwidgets.org/viewtopic.php?t=23277&p=104180.
  565. * This would require a 3 column list, and introducing wx GUI knowledge to
  566. * PLUGIN, which has been avoided to date.
  567. */
  568. virtual void FootprintLibOptions( STRING_UTF8_MAP* aListToAppendTo ) const;
  569. virtual ~PLUGIN()
  570. {};
  571. #ifndef SWIG
  572. /**
  573. * Releases a PLUGIN in the context of a potential thrown exception through its destructor.
  574. */
  575. class RELEASER
  576. {
  577. PLUGIN* plugin;
  578. // private assignment operator so it's illegal
  579. RELEASER& operator=( RELEASER& aOther ) { return *this; }
  580. // private copy constructor so it's illegal
  581. RELEASER( const RELEASER& aOther ) : plugin( nullptr ) {}
  582. public:
  583. RELEASER( PLUGIN* aPlugin = nullptr ) :
  584. plugin( aPlugin )
  585. {
  586. }
  587. ~RELEASER()
  588. {
  589. if( plugin )
  590. release();
  591. }
  592. void release()
  593. {
  594. IO_MGR::PluginRelease( plugin );
  595. plugin = nullptr;
  596. }
  597. void set( PLUGIN* aPlugin )
  598. {
  599. if( plugin )
  600. release();
  601. plugin = aPlugin;
  602. }
  603. operator PLUGIN* () const
  604. {
  605. return plugin;
  606. }
  607. PLUGIN* operator -> () const
  608. {
  609. return plugin;
  610. }
  611. };
  612. #endif
  613. protected:
  614. static bool fileStartsWithPrefix( const wxString& aFilePath, const wxString& aPrefix,
  615. bool aIgnoreWhitespace );
  616. static bool fileStartsWithBinaryHeader( const wxString& aFilePath,
  617. const std::vector<uint8_t>& aHeader );
  618. };
  619. #endif // IO_MGR_H_