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.

432 lines
13 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2017 CERN
  5. * @author Maciej Suminski <maciej.suminski@cern.ch>
  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 3
  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. * https://www.gnu.org/licenses/gpl-3.0.html
  20. * or you may search the http://www.gnu.org website for the version 3 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. #ifndef LIB_MANAGER_H
  25. #define LIB_MANAGER_H
  26. #include <map>
  27. #include <list>
  28. #include <deque>
  29. #include <set>
  30. #include <memory>
  31. #include <wx/arrstr.h>
  32. #include <lib_manager_adapter.h>
  33. class LIB_ALIAS;
  34. class LIB_PART;
  35. class LIB_BUFFER;
  36. class PART_LIB;
  37. class SCH_SCREEN;
  38. class SCH_PLUGIN;
  39. class LIB_EDIT_FRAME;
  40. class SYMBOL_LIB_TABLE;
  41. /**
  42. * Class to handle modifications to the symbol libraries.
  43. */
  44. class LIB_MANAGER
  45. {
  46. public:
  47. LIB_MANAGER( LIB_EDIT_FRAME& aFrame );
  48. /**
  49. * Updates the LIB_MANAGER data to synchronize with Symbol Library Table.
  50. */
  51. void Sync( bool aForce = false, std::function<void(int, int, const wxString&)> aProgressCallback
  52. = [](int, int, const wxString&){} );
  53. int GetHash() const;
  54. /**
  55. * Retruns a library hash value to determine if it has changed.
  56. *
  57. * For buffered libraries, it returns a number corresponding to the number
  58. * of modifications. For original libraries, hash is computed basing on the
  59. * library URI. Returns -1 when the requested library does not exist.
  60. */
  61. int GetLibraryHash( const wxString& aLibrary ) const;
  62. /**
  63. * Returns the array of library names.
  64. */
  65. wxArrayString GetLibraryNames() const;
  66. /**
  67. * Returns a set containing all part names for a specific library.
  68. */
  69. wxArrayString GetAliasNames( const wxString& aLibrary ) const;
  70. std::list<LIB_ALIAS*> GetAliases( const wxString& aLibrary ) const;
  71. /**
  72. * Creates an empty library and adds it to the library table. The library file is created.
  73. */
  74. bool CreateLibrary( const wxString& aFilePath, SYMBOL_LIB_TABLE* aTable )
  75. {
  76. return addLibrary( aFilePath, true, aTable );
  77. }
  78. /**
  79. * Adds an existing library. The library is added to the library table as well.
  80. */
  81. bool AddLibrary( const wxString& aFilePath, SYMBOL_LIB_TABLE* aTable )
  82. {
  83. return addLibrary( aFilePath, false, aTable );
  84. }
  85. /**
  86. * Updates the part buffer with a new version of the part.
  87. * The library buffer creates a copy of the part.
  88. * It is required to save the library to use the updated part in the schematic editor.
  89. */
  90. bool UpdatePart( LIB_PART* aPart, const wxString& aLibrary );
  91. /**
  92. * Removes the part from the part buffer.
  93. * It is required to save the library to have the part removed in the schematic editor.
  94. */
  95. bool RemovePart( const wxString& aName, const wxString& aLibrary );
  96. /**
  97. * Returns either an alias of a working LIB_PART copy, or alias of the original part if there
  98. * is no working copy.
  99. */
  100. LIB_ALIAS* GetAlias( const wxString& aAlias, const wxString& aLibrary ) const;
  101. /**
  102. * Returns the part copy from the buffer. In case it does not exist yet, the copy is created.
  103. * LIB_MANAGER retains the ownership.
  104. */
  105. LIB_PART* GetBufferedPart( const wxString& aAlias, const wxString& aLibrary );
  106. /**
  107. * Returns the screen used to edit a specific part. LIB_MANAGER retains the ownership.
  108. */
  109. SCH_SCREEN* GetScreen( const wxString& aAlias, const wxString& aLibrary );
  110. /**
  111. * Returns true if part with a specific alias exists in library (either original one or buffered).
  112. */
  113. bool PartExists( const wxString& aAlias, const wxString& aLibrary ) const;
  114. /**
  115. * Returns true if library exists.
  116. */
  117. bool LibraryExists( const wxString& aLibrary ) const;
  118. /**
  119. * Returns true if library has unsaved modifications.
  120. */
  121. bool IsLibraryModified( const wxString& aLibrary ) const;
  122. /**
  123. * Returns true if part has unsaved modifications.
  124. */
  125. bool IsPartModified( const wxString& aAlias, const wxString& aLibrary ) const;
  126. /**
  127. * Clears the modified flag for all parts in a library.
  128. */
  129. bool ClearLibraryModified( const wxString& aLibrary ) const;
  130. /**
  131. * Clears the modified flag for a part.
  132. */
  133. bool ClearPartModified( const wxString& aAlias, const wxString& aLibrary ) const;
  134. /**
  135. * Returns true if the library is stored in a read-only file.
  136. * @return True on success, false otherwise.
  137. */
  138. bool IsLibraryReadOnly( const wxString& aLibrary ) const;
  139. /**
  140. * Saves part changes to the library copy used by the schematic editor. Not it is not
  141. * necessarily saved to the file.
  142. * @return True on success, false otherwise.
  143. */
  144. bool FlushPart( const wxString& aAlias, const wxString& aLibrary );
  145. /**
  146. * Saves changes to the library copy used by the schematic editor. Note it is not
  147. * necessarily saved to the file.
  148. * @param aLibrary is the library name.
  149. * @return True on success, false otherwise.
  150. */
  151. bool FlushLibrary( const wxString& aLibrary );
  152. /**
  153. * Saves library to a file, including unsaved changes.
  154. * @param aLibrary is the library name.
  155. * @param aFileName is the target file name.
  156. * @return True on success, false otherwise.
  157. */
  158. bool SaveLibrary( const wxString& aLibrary, const wxString& aFileName );
  159. /**
  160. * Saves all changes to libraries.
  161. * @return True if all changes have been flushed successfully, false otherwise.
  162. */
  163. bool FlushAll();
  164. /**
  165. * Reverts unsaved changes for a particular part.
  166. * @return True on success, false otherwise.
  167. */
  168. bool RevertPart( const wxString& aAlias, const wxString& aLibrary );
  169. /**
  170. * Reverts unsaved changes for a particular library.
  171. * @return True on success, false otherwise.
  172. */
  173. bool RevertLibrary( const wxString& aLibrary );
  174. /**
  175. * Replaces all characters considered illegal in library/part names with underscores.
  176. */
  177. static wxString ValidateName( const wxString& aName );
  178. /**
  179. * Returns a library name that is not currently in use.
  180. * Used for generating names for new libraries.
  181. */
  182. wxString GetUniqueLibraryName() const;
  183. /**
  184. * Returns a component name that is not stored in a library.
  185. * Used for generating names for new components.
  186. */
  187. wxString GetUniqueComponentName( const wxString& aLibrary ) const;
  188. /**
  189. * Returns the adapter object that provides the stored data.
  190. */
  191. CMP_TREE_MODEL_ADAPTER_BASE::PTR& GetAdapter() { return m_adapter; }
  192. /**
  193. * Returns the currently modified library name.
  194. */
  195. const wxString& GetCurrentLib() const
  196. {
  197. return m_currentLib;
  198. }
  199. /**
  200. * Sets the currently modified library name.
  201. */
  202. void SetCurrentLib( const wxString& aLibrary )
  203. {
  204. m_currentLib = aLibrary;
  205. }
  206. /**
  207. * Returns the currently modified part name.
  208. */
  209. const wxString& GetCurrentPart() const
  210. {
  211. return m_currentPart;
  212. }
  213. /**
  214. * Sets the currently modified part name.
  215. */
  216. void SetCurrentPart( const wxString& aPart )
  217. {
  218. m_currentPart = aPart;
  219. }
  220. /**
  221. * Returns the current library and part name as LIB_ID.
  222. */
  223. LIB_ID GetCurrentLibId() const
  224. {
  225. return LIB_ID( m_currentLib, m_currentPart );
  226. }
  227. private:
  228. ///> Parent frame
  229. LIB_EDIT_FRAME& m_frame;
  230. ///> Extracts library name basing on the file name
  231. static wxString getLibraryName( const wxString& aFilePath );
  232. ///> Helper function to add either existing or create new library
  233. bool addLibrary( const wxString& aFilePath, bool aCreate, SYMBOL_LIB_TABLE* aTable );
  234. ///> Returns the current Symbol Library Table
  235. SYMBOL_LIB_TABLE* symTable() const;
  236. ///> Class to store a working copy of a LIB_PART object and editor context.
  237. class PART_BUFFER
  238. {
  239. public:
  240. PART_BUFFER( LIB_PART* aPart = nullptr, SCH_SCREEN* aScreen = nullptr );
  241. ~PART_BUFFER();
  242. LIB_PART* GetPart() const { return m_part; }
  243. void SetPart( LIB_PART* aPart );
  244. LIB_PART* GetOriginal() const { return m_original; }
  245. void SetOriginal( LIB_PART* aPart );
  246. bool IsModified() const;
  247. SCH_SCREEN* GetScreen() const { return m_screen; }
  248. typedef std::shared_ptr<PART_BUFFER> PTR;
  249. typedef std::weak_ptr<PART_BUFFER> WEAK_PTR;
  250. private:
  251. SCH_SCREEN* m_screen;
  252. ///> Working copy
  253. LIB_PART* m_part;
  254. ///> Initial state of the part
  255. LIB_PART* m_original;
  256. };
  257. ///> Class to store a working copy of a library
  258. class LIB_BUFFER
  259. {
  260. public:
  261. LIB_BUFFER( const wxString& aLibrary )
  262. : m_libName( aLibrary ), m_hash( 1 )
  263. {
  264. }
  265. bool IsModified() const
  266. {
  267. if( !m_deleted.empty() )
  268. return true;
  269. for( const auto& partBuf : m_parts )
  270. {
  271. if( partBuf->IsModified() )
  272. return true;
  273. }
  274. return false;
  275. }
  276. int GetHash() const
  277. {
  278. return m_hash;
  279. }
  280. ///> Returns all alias names for stored parts
  281. wxArrayString GetAliasNames() const;
  282. ///> Returns the working copy of a LIB_PART object with specified alias
  283. LIB_PART* GetPart( const wxString& aAlias ) const
  284. {
  285. auto buf = GetBuffer( aAlias );
  286. return buf ? buf->GetPart() : nullptr;
  287. }
  288. ///> Creates a new buffer to store a part. LIB_BUFFER takes ownership of aCopy.
  289. bool CreateBuffer( LIB_PART* aCopy, SCH_SCREEN* aScreen );
  290. ///> Updates the stored part. LIB_BUFFER takes ownership of aCopy.
  291. bool UpdateBuffer( PART_BUFFER::PTR aPartBuf, LIB_PART* aCopy );
  292. bool DeleteBuffer( PART_BUFFER::PTR aPartBuf );
  293. void ClearDeletedBuffer()
  294. {
  295. m_deleted.clear();
  296. }
  297. ///> Saves stored modifications to Symbol Lib Table. It may result in saving the symbol
  298. ///> to disk as well, depending on the row properties.
  299. bool SaveBuffer( PART_BUFFER::PTR aPartBuf, SYMBOL_LIB_TABLE* aLibTable );
  300. ///> Saves stored modificatiosn using a plugin. aBuffer decides whether the changes
  301. ///> should be cached or stored directly to the disk (for SCH_LEGACY_PLUGIN).
  302. bool SaveBuffer( PART_BUFFER::PTR aPartBuf, SCH_PLUGIN* aPlugin, bool aBuffer );
  303. ///> Returns a part buffer with LIB_PART holding a particular alias
  304. PART_BUFFER::PTR GetBuffer( const wxString& aAlias ) const
  305. {
  306. auto it = m_aliases.find( aAlias );
  307. return it != m_aliases.end() ? it->second.lock() : PART_BUFFER::PTR( nullptr );
  308. }
  309. ///> Returns all buffered parts
  310. const std::deque<PART_BUFFER::PTR>& GetBuffers() const
  311. {
  312. return m_parts;
  313. }
  314. ///> Returns all aliases of buffered parts
  315. const std::map<wxString, PART_BUFFER::WEAK_PTR>& GetAliases() const
  316. {
  317. return m_aliases;
  318. }
  319. private:
  320. ///> Creates alias entries for a particular part buffer
  321. bool addAliases( PART_BUFFER::PTR aPartBuf );
  322. ///> Removes alias entries for a particular part buffer
  323. bool removeAliases( PART_BUFFER::PTR aPartBuf );
  324. std::map<wxString, PART_BUFFER::WEAK_PTR> m_aliases;
  325. std::deque<PART_BUFFER::PTR> m_parts;
  326. ///> Buffer to keep deleted parts until the library is saved
  327. std::deque<PART_BUFFER::PTR> m_deleted;
  328. /// Buffered library name
  329. const wxString m_libName;
  330. int m_hash;
  331. friend class PART_BUFFER;
  332. };
  333. ///> Returns a set of LIB_PART objects belonging to the original library
  334. std::set<LIB_PART*> getOriginalParts( const wxString& aLibrary );
  335. ///> Returns an existing library buffer or creates one to using
  336. ///> Symbol Library Table to get the original data.
  337. LIB_BUFFER& getLibraryBuffer( const wxString& aLibrary );
  338. ///> The library buffers
  339. std::map<wxString, LIB_BUFFER> m_libs;
  340. ///> Symbol Lib Table hash value returned during the last synchronization
  341. int m_syncHash;
  342. ///> Currently modified part
  343. wxString m_currentLib;
  344. ///> Currently modified library
  345. wxString m_currentPart;
  346. LIB_MANAGER_ADAPTER::PTR m_adapter;
  347. LIB_MANAGER_ADAPTER* getAdapter() { return static_cast<LIB_MANAGER_ADAPTER*>( m_adapter.get() ); }
  348. };
  349. #endif /* LIB_MANAGER_H */