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.

455 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 <symbol_tree_synchronizing_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. If \a aCheckEnabled is set, then the library must
  127. * also be enabled in the library table.
  128. */
  129. bool LibraryExists( const wxString& aLibrary, bool aCheckEnabled = false ) const;
  130. /**
  131. * Returns true if library has unsaved modifications.
  132. */
  133. bool IsLibraryModified( const wxString& aLibrary ) const;
  134. /**
  135. * Returns true if part has unsaved modifications.
  136. */
  137. bool IsPartModified( const wxString& aAlias, const wxString& aLibrary ) const;
  138. /**
  139. * Clears the modified flag for all parts in a library.
  140. */
  141. bool ClearLibraryModified( const wxString& aLibrary ) const;
  142. /**
  143. * Clears the modified flag for a part.
  144. */
  145. bool ClearPartModified( const wxString& aAlias, const wxString& aLibrary ) const;
  146. /**
  147. * Returns true if the library is stored in a read-only file.
  148. * @return True on success, false otherwise.
  149. */
  150. bool IsLibraryReadOnly( const wxString& aLibrary ) const;
  151. /**
  152. * Saves part changes to the library copy used by the schematic editor. Not it is not
  153. * necessarily saved to the file.
  154. * @return True on success, false otherwise.
  155. */
  156. bool FlushPart( const wxString& aAlias, const wxString& aLibrary );
  157. /**
  158. * Saves changes to the library copy used by the schematic editor. Note it is not
  159. * necessarily saved to the file.
  160. * @param aLibrary is the library name.
  161. * @return True on success, false otherwise.
  162. */
  163. bool FlushLibrary( const wxString& aLibrary );
  164. /**
  165. * Saves library to a file, including unsaved changes.
  166. * @param aLibrary is the library name.
  167. * @param aFileName is the target file name.
  168. * @return True on success, false otherwise.
  169. */
  170. bool SaveLibrary( const wxString& aLibrary, const wxString& aFileName );
  171. /**
  172. * Saves all changes to libraries.
  173. * @return True if all changes have been flushed successfully, false otherwise.
  174. */
  175. bool FlushAll();
  176. /**
  177. * Reverts unsaved changes for a particular part.
  178. * @return The LIB_ID of the reverted part (which may be different in the case
  179. * of a rename)
  180. */
  181. LIB_ID RevertPart( const wxString& aAlias, const wxString& aLibrary );
  182. /**
  183. * Reverts unsaved changes for a particular library.
  184. * @return True on success, false otherwise.
  185. */
  186. bool RevertLibrary( const wxString& aLibrary );
  187. /**
  188. * Returns a library name that is not currently in use.
  189. * Used for generating names for new libraries.
  190. */
  191. wxString GetUniqueLibraryName() const;
  192. /**
  193. * Returns a component name that is not stored in a library.
  194. * Used for generating names for new components.
  195. */
  196. wxString GetUniqueComponentName( const wxString& aLibrary ) const;
  197. /**
  198. * Returns the adapter object that provides the stored data.
  199. */
  200. LIB_TREE_MODEL_ADAPTER::PTR& GetAdapter() { return m_adapter; }
  201. /**
  202. * Returns the currently modified library name.
  203. */
  204. const wxString& GetCurrentLib() const
  205. {
  206. return m_currentLib;
  207. }
  208. /**
  209. * Sets the currently modified library name.
  210. */
  211. void SetCurrentLib( const wxString& aLibrary )
  212. {
  213. m_currentLib = aLibrary;
  214. }
  215. /**
  216. * Returns the currently modified part name.
  217. */
  218. const wxString& GetCurrentPart() const
  219. {
  220. return m_currentPart;
  221. }
  222. /**
  223. * Sets the currently modified part name.
  224. */
  225. void SetCurrentPart( const wxString& aPart )
  226. {
  227. m_currentPart = aPart;
  228. }
  229. /**
  230. * Returns the current library and part name as LIB_ID.
  231. */
  232. LIB_ID GetCurrentLibId() const
  233. {
  234. return LIB_ID( m_currentLib, m_currentPart );
  235. }
  236. private:
  237. ///> Parent frame
  238. LIB_EDIT_FRAME& m_frame;
  239. ///> Extracts library name basing on the file name
  240. static wxString getLibraryName( const wxString& aFilePath );
  241. ///> Helper function to add either existing or create new library
  242. bool addLibrary( const wxString& aFilePath, bool aCreate, SYMBOL_LIB_TABLE* aTable );
  243. ///> Returns the current Symbol Library Table
  244. SYMBOL_LIB_TABLE* symTable() const;
  245. ///> Class to store a working copy of a LIB_PART object and editor context.
  246. class PART_BUFFER
  247. {
  248. public:
  249. PART_BUFFER( LIB_PART* aPart = nullptr, std::unique_ptr<SCH_SCREEN> aScreen = nullptr );
  250. ~PART_BUFFER();
  251. LIB_PART* GetPart() const { return m_part; }
  252. void SetPart( LIB_PART* aPart );
  253. LIB_PART* GetOriginal() const { return m_original; }
  254. void SetOriginal( LIB_PART* aPart );
  255. bool IsModified() const;
  256. SCH_SCREEN* GetScreen() const { return m_screen.get(); }
  257. ///> Transfer the screen ownership
  258. std::unique_ptr<SCH_SCREEN> RemoveScreen()
  259. {
  260. return std::move( m_screen );
  261. }
  262. bool SetScreen( std::unique_ptr<SCH_SCREEN> aScreen )
  263. {
  264. bool ret = !!m_screen;
  265. m_screen = std::move( aScreen );
  266. return ret;
  267. }
  268. typedef std::shared_ptr<PART_BUFFER> PTR;
  269. typedef std::weak_ptr<PART_BUFFER> WEAK_PTR;
  270. private:
  271. std::unique_ptr<SCH_SCREEN> m_screen;
  272. ///> Working copy
  273. LIB_PART* m_part;
  274. ///> Initial state of the part
  275. LIB_PART* m_original;
  276. };
  277. ///> Class to store a working copy of a library
  278. class LIB_BUFFER
  279. {
  280. public:
  281. LIB_BUFFER( const wxString& aLibrary )
  282. : m_libName( aLibrary ), m_hash( 1 )
  283. {
  284. }
  285. bool IsModified() const
  286. {
  287. if( !m_deleted.empty() )
  288. return true;
  289. for( const auto& partBuf : m_parts )
  290. {
  291. if( partBuf->IsModified() )
  292. return true;
  293. }
  294. return false;
  295. }
  296. int GetHash() const
  297. {
  298. return m_hash;
  299. }
  300. ///> Returns all alias names for stored parts
  301. wxArrayString GetAliasNames() const;
  302. ///> Returns the working copy of a LIB_PART object with specified alias
  303. LIB_PART* GetPart( const wxString& aAlias ) const
  304. {
  305. auto buf = GetBuffer( aAlias );
  306. return buf ? buf->GetPart() : nullptr;
  307. }
  308. ///> Creates a new buffer to store a part. LIB_BUFFER takes ownership of aCopy.
  309. bool CreateBuffer( LIB_PART* aCopy, SCH_SCREEN* aScreen );
  310. ///> Updates the stored part. LIB_BUFFER takes ownership of aCopy.
  311. bool UpdateBuffer( PART_BUFFER::PTR aPartBuf, LIB_PART* aCopy );
  312. bool DeleteBuffer( PART_BUFFER::PTR aPartBuf );
  313. void ClearDeletedBuffer()
  314. {
  315. m_deleted.clear();
  316. }
  317. ///> Saves stored modifications to Symbol Lib Table. It may result in saving the symbol
  318. ///> to disk as well, depending on the row properties.
  319. bool SaveBuffer( PART_BUFFER::PTR aPartBuf, SYMBOL_LIB_TABLE* aLibTable );
  320. ///> Saves stored modificatiosn using a plugin. aBuffer decides whether the changes
  321. ///> should be cached or stored directly to the disk (for SCH_LEGACY_PLUGIN).
  322. bool SaveBuffer( PART_BUFFER::PTR aPartBuf, SCH_PLUGIN* aPlugin, bool aBuffer );
  323. ///> Returns a part buffer with LIB_PART holding a particular alias
  324. PART_BUFFER::PTR GetBuffer( const wxString& aAlias ) const
  325. {
  326. auto it = m_aliases.find( aAlias );
  327. return it != m_aliases.end() ? it->second.lock() : PART_BUFFER::PTR( nullptr );
  328. }
  329. ///> Returns all buffered parts
  330. const std::deque<PART_BUFFER::PTR>& GetBuffers() const
  331. {
  332. return m_parts;
  333. }
  334. ///> Returns all aliases of buffered parts
  335. const std::map<wxString, PART_BUFFER::WEAK_PTR>& GetAliases() const
  336. {
  337. return m_aliases;
  338. }
  339. private:
  340. ///> Creates alias entries for a particular part buffer
  341. bool addAliases( PART_BUFFER::PTR aPartBuf );
  342. ///> Removes alias entries for a particular part buffer
  343. bool removeAliases( PART_BUFFER::PTR aPartBuf );
  344. std::map<wxString, PART_BUFFER::WEAK_PTR> m_aliases;
  345. std::deque<PART_BUFFER::PTR> m_parts;
  346. ///> Buffer to keep deleted parts until the library is saved
  347. std::deque<PART_BUFFER::PTR> m_deleted;
  348. /// Buffered library name
  349. const wxString m_libName;
  350. int m_hash;
  351. friend class PART_BUFFER;
  352. };
  353. ///> Returns a set of LIB_PART objects belonging to the original library
  354. std::set<LIB_PART*> getOriginalParts( const wxString& aLibrary );
  355. ///> Returns an existing library buffer or creates one to using
  356. ///> Symbol Library Table to get the original data.
  357. LIB_BUFFER& getLibraryBuffer( const wxString& aLibrary );
  358. ///> The library buffers
  359. std::map<wxString, LIB_BUFFER> m_libs;
  360. ///> Symbol Lib Table hash value returned during the last synchronization
  361. int m_syncHash;
  362. ///> Currently modified part
  363. wxString m_currentLib;
  364. ///> Currently modified library
  365. wxString m_currentPart;
  366. SYMBOL_TREE_SYNCHRONIZING_ADAPTER::PTR m_adapter;
  367. SYMBOL_TREE_SYNCHRONIZING_ADAPTER* getAdapter() { return static_cast<SYMBOL_TREE_SYNCHRONIZING_ADAPTER*>( m_adapter.get() ); }
  368. };
  369. #endif /* LIB_MANAGER_H */