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.

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