1 /* 2 * This program source code file is symbol of KiCad, a free EDA CAD application. 3 * 4 * Copyright (C) 2017 CERN 5 * Copyright (C) 2019-2021 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 27 #ifndef SYMBOL_LIBRARY_MANAGER_H 28 #define SYMBOL_LIBRARY_MANAGER_H 29 30 #include <map> 31 #include <list> 32 #include <deque> 33 #include <set> 34 #include <memory> 35 #include <wx/arrstr.h> 36 #include <symbol_tree_synchronizing_adapter.h> 37 #include <sch_io_mgr.h> 38 #include <sch_screen.h> 39 40 class LIB_SYMBOL; 41 class SYMBOL_LIB; 42 class PROGRESS_REPORTER; 43 class SCH_PLUGIN; 44 class SYMBOL_EDIT_FRAME; 45 class SYMBOL_LIB_TABLE; 46 class SYMBOL_LIB_TABLE_ROW; 47 class LIB_LOGGER; 48 49 50 /** 51 * Class to handle modifications to the symbol libraries. 52 */ 53 class SYMBOL_LIBRARY_MANAGER 54 { 55 public: 56 SYMBOL_LIBRARY_MANAGER( SYMBOL_EDIT_FRAME& aFrame ); 57 ~SYMBOL_LIBRARY_MANAGER(); 58 59 /** 60 * Updates the #SYMBOL_LIBRARY_MANAGER data to synchronize with Symbol Library Table. 61 */ 62 void Sync( const wxString& aForceRefresh, 63 std::function<void( int, int, const wxString& )> aProgressCallback ); 64 65 /** 66 * Preloads all symbol libraries in the symbol library table using SYMBOL_ASYNC_LOADER. 67 * Call before the first call to Sync() to get better performance. 68 * @param aReporter is used to report progress of the load 69 */ 70 void Preload( PROGRESS_REPORTER& aReporter ); 71 72 int GetHash() const; 73 74 bool HasModifications() const; 75 76 /** 77 * Return a library hash value to determine if it has changed. 78 * 79 * For buffered libraries, it returns a number corresponding to the number of modifications. 80 * For original libraries, hash is computed basing on the library URI. Returns -1 when the 81 * requested library does not exist. 82 */ 83 int GetLibraryHash( const wxString& aLibrary ) const; 84 85 /** 86 * Return the array of library names. 87 */ 88 wxArrayString GetLibraryNames() const; 89 90 /** 91 * Find a single library within the (aggregate) library table. 92 */ 93 SYMBOL_LIB_TABLE_ROW* GetLibrary( const wxString& aLibrary ) const; 94 95 std::list<LIB_SYMBOL*> GetAliases( const wxString& aLibrary ) const; 96 97 /** 98 * Create an empty library and adds it to the library table. The library file is created. 99 */ CreateLibrary(const wxString & aFilePath,SYMBOL_LIB_TABLE * aTable)100 bool CreateLibrary( const wxString& aFilePath, SYMBOL_LIB_TABLE* aTable ) 101 { 102 return addLibrary( aFilePath, true, aTable ); 103 } 104 105 /** 106 * Add an existing library. The library is added to the library table as well. 107 */ AddLibrary(const wxString & aFilePath,SYMBOL_LIB_TABLE * aTable)108 bool AddLibrary( const wxString& aFilePath, SYMBOL_LIB_TABLE* aTable ) 109 { 110 return addLibrary( aFilePath, false, aTable ); 111 } 112 113 /** 114 * Update the symbol buffer with a new version of the symbol. 115 * The library buffer creates a copy of the symbol. 116 * It is required to save the library to use the updated symbol in the schematic editor. 117 */ 118 bool UpdateSymbol( LIB_SYMBOL* aSymbol, const wxString& aLibrary ); 119 120 /** 121 * Update the symbol buffer with a new version of the symbol when the name has changed. 122 * The old library buffer will be deleted and a new one created with the new name. 123 */ 124 bool UpdateSymbolAfterRename( LIB_SYMBOL* aSymbol, const wxString& oldAlias, 125 const wxString& aLibrary ); 126 127 /** 128 * Remove the symbol from the symbol buffer. 129 * It is required to save the library to have the symbol removed in the schematic editor. 130 */ 131 bool RemoveSymbol( const wxString& aName, const wxString& aLibrary ); 132 133 /** 134 * Return either an alias of a working LIB_SYMBOL copy, or alias of the original symbol if there 135 * is no working copy. 136 */ 137 LIB_SYMBOL* GetAlias( const wxString& aAlias, const wxString& aLibrary ) const; 138 139 /** 140 * Return the symbol copy from the buffer. In case it does not exist yet, the copy is created. 141 * #SYMBOL_LIBRARY_MANAGER retains the ownership. 142 */ 143 LIB_SYMBOL* GetBufferedSymbol( const wxString& aAlias, const wxString& aLibrary ); 144 145 /** 146 * Return the screen used to edit a specific symbol. #SYMBOL_LIBRARY_MANAGER retains the 147 * ownership. 148 */ 149 SCH_SCREEN* GetScreen( const wxString& aAlias, const wxString& aLibrary ); 150 151 /** 152 * Return true if symbol with a specific alias exists in library (either original one or 153 * buffered). 154 */ 155 bool SymbolExists( const wxString& aAlias, const wxString& aLibrary ) const; 156 157 /** 158 * Return true if library exists. If \a aCheckEnabled is set, then the library must 159 * also be enabled in the library table. 160 */ 161 bool LibraryExists( const wxString& aLibrary, bool aCheckEnabled = false ) const; 162 163 /** 164 * Return true if the library was successfully loaded. 165 */ 166 bool IsLibraryLoaded( const wxString& aLibrary ) const; 167 168 /** 169 * Return true if library has unsaved modifications. 170 */ 171 bool IsLibraryModified( const wxString& aLibrary ) const; 172 173 /** 174 * Return true if symbol has unsaved modifications. 175 */ 176 bool IsSymbolModified( const wxString& aAlias, const wxString& aLibrary ) const; 177 178 /** 179 * Clear the modified flag for all symbols in a library. 180 */ 181 bool ClearLibraryModified( const wxString& aLibrary ) const; 182 183 /** 184 * Clear the modified flag for a symbol. 185 */ 186 bool ClearSymbolModified( const wxString& aAlias, const wxString& aLibrary ) const; 187 188 /** 189 * Return true if the library is stored in a read-only file. 190 * 191 * @return True on success, false otherwise. 192 */ 193 bool IsLibraryReadOnly( const wxString& aLibrary ) const; 194 195 /** 196 * Save symbol changes to the library copy used by the schematic editor. Not it is not 197 * necessarily saved to the file. 198 * 199 * @return True on success, false otherwise. 200 */ 201 bool FlushSymbol( const wxString& aAlias, const wxString& aLibrary ); 202 203 /** 204 * Save library to a file, including unsaved changes. 205 * 206 * @param aLibrary is the library name. 207 * @param aFileName is the target file name. 208 * @return True on success, false otherwise. 209 */ 210 bool SaveLibrary( const wxString& aLibrary, const wxString& aFileName, 211 SCH_IO_MGR::SCH_FILE_T aFileType = SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY ); 212 213 /** 214 * Revert unsaved changes for a symbolicular symbol. 215 * 216 * @return The LIB_ID of the reverted symbol (which may be different in the case 217 * of a rename) 218 */ 219 LIB_ID RevertSymbol( const wxString& aAlias, const wxString& aLibrary ); 220 221 /** 222 * Revert unsaved changes for a symbolicular library. 223 * 224 * @return True on success, false otherwise. 225 */ 226 bool RevertLibrary( const wxString& aLibrary ); 227 228 /** 229 * Revert all pending changes. 230 * 231 * @return True if all changes successfully reverted. 232 */ 233 bool RevertAll(); 234 235 /** 236 * Return a library name that is not currently in use. 237 * Used for generating names for new libraries. 238 */ 239 wxString GetUniqueLibraryName() const; 240 241 /** 242 * Return the adapter object that provides the stored data. 243 */ GetAdapter()244 wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>& GetAdapter() { return m_adapter; } 245 246 void GetRootSymbolNames( const wxString& aLibName, wxArrayString& aRootSymbolNames ); 247 248 /** 249 * Check if symbol \a aSymbolName in library \a aLibraryName is a root symbol that 250 * has derived symbols. 251 * 252 * @return true if \aSymbolName in \a aLibraryName has derived symbols. 253 */ 254 bool HasDerivedSymbols( const wxString& aSymbolName, const wxString& aLibraryName ); 255 256 size_t GetLibraryCount() const; 257 258 private: 259 ///< Extract library name basing on the file name. 260 static wxString getLibraryName( const wxString& aFilePath ); 261 262 ///< Helper function to add either existing or create new library 263 bool addLibrary( const wxString& aFilePath, bool aCreate, SYMBOL_LIB_TABLE* aTable ); 264 265 ///< Return the current Symbol Library Table. 266 SYMBOL_LIB_TABLE* symTable() const; 267 getAdapter()268 SYMBOL_TREE_SYNCHRONIZING_ADAPTER* getAdapter() 269 { 270 return static_cast<SYMBOL_TREE_SYNCHRONIZING_ADAPTER*>( m_adapter.get() ); 271 } 272 273 ///< Class to store a working copy of a LIB_SYMBOL object and editor context. 274 class SYMBOL_BUFFER 275 { 276 public: 277 SYMBOL_BUFFER( LIB_SYMBOL* aSymbol = nullptr, 278 std::unique_ptr<SCH_SCREEN> aScreen = nullptr ); 279 ~SYMBOL_BUFFER(); 280 GetSymbol()281 LIB_SYMBOL* GetSymbol() const { return m_symbol; } 282 void SetSymbol( LIB_SYMBOL* aSymbol ); 283 GetOriginal()284 LIB_SYMBOL* GetOriginal() const { return m_original; } 285 void SetOriginal( LIB_SYMBOL* aSymbol ); 286 287 bool IsModified() const; GetScreen()288 SCH_SCREEN* GetScreen() const { return m_screen.get(); } 289 290 ///< Transfer the screen ownership RemoveScreen()291 std::unique_ptr<SCH_SCREEN> RemoveScreen() 292 { 293 return std::move( m_screen ); 294 } 295 SetScreen(std::unique_ptr<SCH_SCREEN> aScreen)296 bool SetScreen( std::unique_ptr<SCH_SCREEN> aScreen ) 297 { 298 bool ret = !!m_screen; 299 m_screen = std::move( aScreen ); 300 return ret; 301 } 302 303 private: 304 std::unique_ptr<SCH_SCREEN> m_screen; 305 306 LIB_SYMBOL* m_symbol; // Working copy 307 LIB_SYMBOL* m_original; // Initial state of the symbol 308 }; 309 310 311 ///< Store a working copy of a library. 312 class LIB_BUFFER 313 { 314 public: LIB_BUFFER(const wxString & aLibrary)315 LIB_BUFFER( const wxString& aLibrary ) : 316 m_libName( aLibrary ), 317 m_hash( 1 ) 318 { } 319 IsModified()320 bool IsModified() const 321 { 322 if( !m_deleted.empty() ) 323 return true; 324 325 for( const std::shared_ptr<SYMBOL_BUFFER>& symbolBuf : m_symbols ) 326 { 327 if( symbolBuf->IsModified() ) 328 return true; 329 } 330 331 return false; 332 } 333 GetHash()334 int GetHash() const { return m_hash; } 335 336 ///< Return the working copy of a LIB_SYMBOL root object with specified alias. 337 LIB_SYMBOL* GetSymbol( const wxString& aAlias ) const; 338 339 ///< Create a new buffer to store a symbol. LIB_BUFFER takes ownership of aCopy. 340 bool CreateBuffer( LIB_SYMBOL* aCopy, SCH_SCREEN* aScreen ); 341 342 ///< Update the buffered symbol with the contents of \a aCopy. 343 bool UpdateBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf, LIB_SYMBOL* aCopy ); 344 345 bool DeleteBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf ); 346 ClearDeletedBuffer()347 void ClearDeletedBuffer() 348 { 349 m_deleted.clear(); 350 } 351 352 ///< Save stored modifications to Symbol Lib Table. It may result in saving the symbol 353 ///< to disk as well, depending on the row properties. 354 bool SaveBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf, SYMBOL_LIB_TABLE* aLibTable ); 355 356 ///< Save stored modifications using a plugin. aBuffer decides whether the changes 357 ///< should be cached or stored directly to the disk (for SCH_LEGACY_PLUGIN). 358 bool SaveBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf, const wxString& aFileName, 359 SCH_PLUGIN* aPlugin, bool aBuffer ); 360 361 ///< Return a symbol buffer with LIB_SYMBOL holding a symbolicular alias 362 std::shared_ptr<SYMBOL_BUFFER> GetBuffer( const wxString& aAlias ) const; 363 364 ///< Return all buffered symbols GetBuffers()365 const std::deque< std::shared_ptr<SYMBOL_BUFFER> >& GetBuffers() const { return m_symbols; } 366 367 /** 368 * Check to see any symbols in the buffer are derived from a parent named \a aParentName. 369 * 370 * @param aParentName is the name of the parent to test. 371 * @return true if any symbols are found derived from a symbol named \a aParent, otherwise 372 * false. 373 */ 374 bool HasDerivedSymbols( const wxString& aParentName ) const; 375 376 /** 377 * Fetch a list of root symbols names from the library buffer. 378 * 379 * @param aRootSymbolNames is a reference to a list to populate with root symbol names. 380 */ 381 void GetRootSymbolNames( wxArrayString& aRootSymbolNames ); 382 383 /** 384 * Fetch all of the symbols derived from a \a aSymbolName into \a aList. 385 * 386 * @param aSymbolName is the name of the symbol to search for derived symbols in this 387 * buffer. 388 * @param aList is the list of symbols names derived from \a aSymbolName. 389 * @return a size_t count of the number of symbols derived from \a aSymbolName. 390 */ 391 size_t GetDerivedSymbolNames( const wxString& aSymbolName, wxArrayString& aList ); 392 393 private: 394 /** 395 * Remove all symbols derived from \a aParent from the library buffer. 396 * 397 * @param aParent is the #SYMBOL_BUFFER to check against. 398 * @return the count of #SYMBOL_BUFFER objects removed from the library. 399 */ 400 int removeChildSymbols( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf ); 401 402 std::deque< std::shared_ptr<SYMBOL_BUFFER> > m_symbols; 403 404 ///< Buffer for deleted symbols until library is saved. 405 std::deque< std::shared_ptr<SYMBOL_BUFFER> > m_deleted; 406 const wxString m_libName; // Buffered library name 407 int m_hash; 408 }; 409 410 /** 411 * Return a set of #LIB_SYMBOL objects belonging to the original library. 412 */ 413 std::set<LIB_SYMBOL*> getOriginalSymbols( const wxString& aLibrary ); 414 415 /** 416 * Return an existing library buffer or creates one to using Symbol Library Table to get 417 * the original data. 418 */ 419 LIB_BUFFER& getLibraryBuffer( const wxString& aLibrary ); 420 421 ///< The library buffers 422 std::map<wxString, LIB_BUFFER> m_libs; 423 424 SYMBOL_EDIT_FRAME& m_frame; ///< Parent frame 425 LIB_LOGGER* m_logger; 426 int m_syncHash; ///< Symbol lib table hash value from last synchronization 427 428 wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> m_adapter; 429 }; 430 431 #endif /* SYMBOL_LIBRARY_MANAGER_H */ 432