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.

429 lines
14 KiB

6 years ago
  1. /*
  2. * This program source code file is symbol of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2017 CERN
  5. * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * @author Maciej Suminski <maciej.suminski@cern.ch>
  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 3
  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 SYMBOLICULAR 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. * https://www.gnu.org/licenses/gpl-3.0.html
  22. * or you may search the http://www.gnu.org website for the version 3 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. #ifndef SYMBOL_LIBRARY_MANAGER_H
  27. #define SYMBOL_LIBRARY_MANAGER_H
  28. #include <map>
  29. #include <list>
  30. #include <deque>
  31. #include <set>
  32. #include <memory>
  33. #include <wx/arrstr.h>
  34. #include <sch_io/sch_io_mgr.h>
  35. #include <sch_screen.h>
  36. class LIB_SYMBOL;
  37. class SYMBOL_LIB;
  38. class PROGRESS_REPORTER;
  39. class SCH_IO;
  40. class SCH_BASE_FRAME;
  41. class SYMBOL_LIB_TABLE;
  42. class SYMBOL_LIB_TABLE_ROW;
  43. class LIB_LOGGER;
  44. enum class SYMBOL_NAME_FILTER
  45. {
  46. ALL,
  47. ROOT_ONLY,
  48. DERIVED_ONLY
  49. };
  50. class SYMBOL_BUFFER
  51. {
  52. public:
  53. SYMBOL_BUFFER( std::unique_ptr<LIB_SYMBOL> aSymbol = nullptr,
  54. std::unique_ptr<SCH_SCREEN> aScreen = nullptr );
  55. ~SYMBOL_BUFFER();
  56. LIB_SYMBOL& GetSymbol() const { return *m_symbol; }
  57. void SetSymbol( std::unique_ptr<LIB_SYMBOL> aSymbol );
  58. LIB_SYMBOL& GetOriginal() const { return *m_original; }
  59. void SetOriginal( std::unique_ptr<LIB_SYMBOL> aSymbol );
  60. bool IsModified() const;
  61. SCH_SCREEN* GetScreen() const { return m_screen.get(); }
  62. private:
  63. std::unique_ptr<SCH_SCREEN> m_screen;
  64. std::unique_ptr<LIB_SYMBOL> m_symbol; // Working copy
  65. std::unique_ptr<LIB_SYMBOL> m_original; // Initial state of the symbol
  66. };
  67. /// Store a working copy of a library.
  68. class LIB_BUFFER
  69. {
  70. public:
  71. LIB_BUFFER( const wxString& aLibrary ) :
  72. m_libName( aLibrary ),
  73. m_hash( 1 )
  74. {}
  75. bool IsModified() const
  76. {
  77. if( !m_deleted.empty() )
  78. return true;
  79. for( const std::shared_ptr<SYMBOL_BUFFER>& symbolBuf : m_symbols )
  80. {
  81. if( symbolBuf->IsModified() )
  82. return true;
  83. }
  84. return false;
  85. }
  86. int GetHash() const { return m_hash; }
  87. /// Return the working copy of a #LIB_SYMBOL root object with specified alias.
  88. LIB_SYMBOL* GetSymbol( const wxString& aAlias ) const;
  89. /// Create a new buffer to store a symbol. #LIB_BUFFER takes ownership of \a aCopy.
  90. bool CreateBuffer( std::unique_ptr<LIB_SYMBOL> aCopy, std::unique_ptr<SCH_SCREEN> aScreen );
  91. /// Update the buffered symbol with the contents of \a aCopy.
  92. bool UpdateBuffer( SYMBOL_BUFFER& aSymbolBuf, const LIB_SYMBOL& aCopy );
  93. /**
  94. * Delete the given symbol buffer from the library buffer.
  95. */
  96. bool DeleteBuffer( const SYMBOL_BUFFER& aSymbolBuf );
  97. void ClearDeletedBuffer() { m_deleted.clear(); }
  98. /// Save stored modifications using a plugin. aBuffer decides whether the changes
  99. /// should be cached or stored directly to the disk (for #SCH_IO_KICAD_LEGACY).
  100. bool SaveBuffer( SYMBOL_BUFFER& aSymbolBuf, const wxString& aFileName, SCH_IO* aPlugin,
  101. bool aBuffer );
  102. /// Return a symbol buffer with #LIB_SYMBOL holding a symbolic alias.
  103. std::shared_ptr<SYMBOL_BUFFER> GetBuffer( const wxString& aAlias ) const;
  104. /// Return all buffered symbols.
  105. const std::deque<std::shared_ptr<SYMBOL_BUFFER>>& GetBuffers() const { return m_symbols; }
  106. /**
  107. * Check to see any symbols in the buffer are derived from a parent named \a aParentName.
  108. *
  109. * @param aParentName is the name of the parent to test.
  110. * @return true if any symbols are found derived from a symbol named \a aParent, otherwise
  111. * false.
  112. */
  113. bool HasDerivedSymbols( const wxString& aParentName ) const;
  114. /**
  115. * Fetch a list of root symbols names from the library buffer.
  116. *
  117. * @param aRootSymbolNames is a reference to a list to populate with root symbol names.
  118. * @param aFilter is the symbol derivation type.
  119. */
  120. void GetSymbolNames( wxArrayString& aSymbolNames,
  121. SYMBOL_NAME_FILTER aFilter = SYMBOL_NAME_FILTER::ALL );
  122. /**
  123. * Fetch all of the symbols derived from a \a aSymbolName into \a aList.
  124. *
  125. * @param aSymbolName is the name of the symbol to search for derived symbols in this
  126. * buffer.
  127. * @param aList is the list of symbols names derived from \a aSymbolName.
  128. * @return a size_t count of the number of symbols derived from \a aSymbolName.
  129. */
  130. size_t GetDerivedSymbolNames( const wxString& aSymbolName, wxArrayString& aList );
  131. private:
  132. /**
  133. * Remove all symbols derived from \a aParent from the library buffer.
  134. *
  135. * @param aParent is the #SYMBOL_BUFFER to check against.
  136. * @return the count of #SYMBOL_BUFFER objects removed from the library.
  137. */
  138. int removeChildSymbols( const SYMBOL_BUFFER& aSymbolBuf );
  139. private:
  140. std::deque<std::shared_ptr<SYMBOL_BUFFER>> m_symbols;
  141. std::deque<std::shared_ptr<SYMBOL_BUFFER>> m_deleted; ///< Buffer for deleted symbols until
  142. ///< library is saved.
  143. const wxString m_libName; ///< Buffered library name
  144. int m_hash;
  145. };
  146. /**
  147. * Class to handle modifications to the symbol libraries.
  148. */
  149. class SYMBOL_LIBRARY_MANAGER
  150. {
  151. public:
  152. SYMBOL_LIBRARY_MANAGER( SCH_BASE_FRAME& aFrame );
  153. virtual ~SYMBOL_LIBRARY_MANAGER();
  154. /**
  155. * Preload all symbol libraries in the symbol library table using #SYMBOL_ASYNC_LOADER.
  156. *
  157. * Call before the first call to Sync() to get better performance.
  158. *
  159. * @param aReporter is used to report progress of the load
  160. */
  161. void Preload( PROGRESS_REPORTER& aReporter );
  162. int GetHash() const;
  163. bool HasModifications() const;
  164. /**
  165. * Return a library hash value to determine if it has changed.
  166. *
  167. * For buffered libraries, it returns a number corresponding to the number of modifications.
  168. * For original libraries, hash is computed basing on the library URI. Returns -1 when the
  169. * requested library does not exist.
  170. */
  171. int GetLibraryHash( const wxString& aLibrary ) const;
  172. /**
  173. * Return the array of library names.
  174. */
  175. wxArrayString GetLibraryNames() const;
  176. /**
  177. * Find a single library within the (aggregate) library table.
  178. */
  179. SYMBOL_LIB_TABLE_ROW* GetLibrary( const wxString& aLibrary ) const;
  180. std::list<LIB_SYMBOL*> EnumerateSymbols( const wxString& aLibrary ) const;
  181. /**
  182. * Create an empty library and adds it to the library table.
  183. *
  184. * The library file is created.
  185. */
  186. bool CreateLibrary( const wxString& aFilePath, SYMBOL_LIB_TABLE& aTable )
  187. {
  188. return addLibrary( aFilePath, true, aTable );
  189. }
  190. /**
  191. * Add an existing library.
  192. *
  193. * The library is added to the library table as well.
  194. */
  195. bool AddLibrary( const wxString& aFilePath, SYMBOL_LIB_TABLE& aTable )
  196. {
  197. return addLibrary( aFilePath, false, aTable );
  198. }
  199. /**
  200. * Update the symbol buffer with a new version of the symbol.
  201. *
  202. * The library buffer creates a copy of the symbol.
  203. *
  204. * It is required to save the library to use the updated symbol in the schematic editor.
  205. */
  206. bool UpdateSymbol( LIB_SYMBOL* aSymbol, const wxString& aLibrary );
  207. /**
  208. * Update the symbol buffer with a new version of the symbol when the name has changed.
  209. *
  210. * The old library buffer will be deleted and a new one created with the new name.
  211. */
  212. bool UpdateSymbolAfterRename( LIB_SYMBOL* aSymbol, const wxString& aOldSymbolName,
  213. const wxString& aLibrary );
  214. /**
  215. * Update the library buffer with a new version of the library.
  216. */
  217. bool UpdateLibraryBuffer( const wxString& aLibrary );
  218. /**
  219. * Remove the symbol from the symbol buffer.
  220. *
  221. * It is required to save the library to have the symbol removed in the schematic editor.
  222. */
  223. bool RemoveSymbol( const wxString& aSymbolName, const wxString& aLibrary );
  224. /**
  225. * Return either an alias of a working LIB_SYMBOL copy, or alias of the original symbol if there
  226. * is no working copy.
  227. */
  228. LIB_SYMBOL* GetSymbol( const wxString& aSymbolName, const wxString& aLibrary ) const;
  229. /**
  230. * Return the symbol copy from the buffer.
  231. *
  232. * In case it does not exist yet, the copy is created. #SYMBOL_LIBRARY_MANAGER retains
  233. * the ownership.
  234. */
  235. LIB_SYMBOL* GetBufferedSymbol( const wxString& aSymbolName, const wxString& aLibrary );
  236. /**
  237. * Return the screen used to edit a specific symbol. #SYMBOL_LIBRARY_MANAGER retains the
  238. * ownership.
  239. */
  240. SCH_SCREEN* GetScreen( const wxString& aSymbolName, const wxString& aLibrary );
  241. /**
  242. * Return true if symbol with a specific alias exists in library (either original one or
  243. * buffered).
  244. */
  245. bool SymbolExists( const wxString& aSymbolName, const wxString& aLibrary ) const;
  246. /**
  247. * Return true if the symbol name is already in use in the specified library.
  248. */
  249. bool SymbolNameInUse( const wxString& aName, const wxString& aLibrary );
  250. /**
  251. * Return true if library exists.
  252. *
  253. * If \a aCheckEnabled is set, then the library must also be enabled in the library table.
  254. */
  255. bool LibraryExists( const wxString& aLibrary, bool aCheckEnabled = false ) const;
  256. /**
  257. * Return true if the library was successfully loaded.
  258. */
  259. bool IsLibraryLoaded( const wxString& aLibrary ) const;
  260. /**
  261. * Return true if library has unsaved modifications.
  262. */
  263. bool IsLibraryModified( const wxString& aLibrary ) const;
  264. /**
  265. * Return true if symbol has unsaved modifications.
  266. */
  267. bool IsSymbolModified( const wxString& aSymbolName, const wxString& aLibrary ) const;
  268. void SetSymbolModified( const wxString& aSymbolName, const wxString& aLibrary );
  269. /**
  270. * Clear the modified flag for all symbols in a library.
  271. */
  272. bool ClearLibraryModified( const wxString& aLibrary ) const;
  273. /**
  274. * Clear the modified flag for a symbol.
  275. */
  276. bool ClearSymbolModified( const wxString& aSymbolName, const wxString& aLibrary ) const;
  277. /**
  278. * Return true if the library is stored in a read-only file.
  279. *
  280. * @return True on success, false otherwise.
  281. */
  282. bool IsLibraryReadOnly( const wxString& aLibrary ) const;
  283. /**
  284. * Save library to a file, including unsaved changes.
  285. *
  286. * @param aLibrary is the library name.
  287. * @param aFileName is the target file name.
  288. * @return True on success, false otherwise.
  289. */
  290. bool SaveLibrary( const wxString& aLibrary, const wxString& aFileName,
  291. SCH_IO_MGR::SCH_FILE_T aFileType = SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY );
  292. /**
  293. * Revert unsaved changes for a symbol.
  294. *
  295. * @return The LIB_ID of the reverted symbol (which may be different in the case
  296. * of a rename)
  297. */
  298. LIB_ID RevertSymbol( const wxString& aSymbolName, const wxString& aLibrary );
  299. /**
  300. * Revert unsaved changes for a symbol library.
  301. *
  302. * @return True on success, false otherwise.
  303. */
  304. bool RevertLibrary( const wxString& aLibrary );
  305. /**
  306. * Revert all pending changes.
  307. *
  308. * @return True if all changes successfully reverted.
  309. */
  310. bool RevertAll();
  311. /**
  312. * Return a library name that is not currently in use.
  313. *
  314. * Used for generating names for new libraries.
  315. */
  316. wxString GetUniqueLibraryName() const;
  317. void GetSymbolNames( const wxString& aLibName, wxArrayString& aSymbolNames,
  318. SYMBOL_NAME_FILTER aFilter = SYMBOL_NAME_FILTER::ALL );
  319. /**
  320. * Check if symbol \a aSymbolName in library \a aLibraryName is a root symbol that
  321. * has derived symbols.
  322. *
  323. * @return true if \aSymbolName in \a aLibraryName has derived symbols.
  324. */
  325. bool HasDerivedSymbols( const wxString& aSymbolName, const wxString& aLibraryName );
  326. /**
  327. * Fetch all of the symbols derived from a \a aSymbolName into \a aList.
  328. */
  329. size_t GetDerivedSymbolNames( const wxString& aSymbolName, const wxString& aLibraryName, wxArrayString& aList );
  330. size_t GetLibraryCount() const;
  331. protected:
  332. virtual void OnDataChanged() const {}
  333. /// Extract library name basing on the file name.
  334. static wxString getLibraryName( const wxString& aFilePath );
  335. /// Helper function to add either existing or create new library.
  336. bool addLibrary( const wxString& aFilePath, bool aCreate, SYMBOL_LIB_TABLE& aTable );
  337. /// Return the current symbol library table.
  338. SYMBOL_LIB_TABLE* symTable() const;
  339. /**
  340. * Return a set of #LIB_SYMBOL objects belonging to the original library.
  341. */
  342. std::set<LIB_SYMBOL*> getOriginalSymbols( const wxString& aLibrary );
  343. /**
  344. * Return an existing library buffer or creates one to using symbol library table to get
  345. * the original data.
  346. */
  347. LIB_BUFFER& getLibraryBuffer( const wxString& aLibrary );
  348. protected:
  349. std::map<wxString, LIB_BUFFER> m_libs; ///< The library buffers
  350. SCH_BASE_FRAME& m_frame; ///< Parent frame
  351. LIB_LOGGER* m_logger;
  352. };
  353. #endif /* SYMBOL_LIBRARY_MANAGER_H */