KiCad PCB EDA Suite
symbol_library_manager.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part 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  * @author Maciej Suminski <maciej.suminski@cern.ch>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 3
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * https://www.gnu.org/licenses/gpl-3.0.html
21  * or you may search the http://www.gnu.org website for the version 3 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <symbol_library_manager.h>
27 #include <symbol_library.h>
29 #include <symbol_edit_frame.h>
30 #include <env_paths.h>
31 #include <pgm_base.h>
32 #include <kiway.h>
33 #include <profile.h>
34 #include <sch_io_mgr.h>
36 #include <symbol_lib_table.h>
37 #include <symbol_async_loader.h>
38 #include <progress_reporter.h>
39 #include <list>
40 #include <locale_io.h>
41 #include <wx/log.h>
42 #include <string_utils.h>
43 #include "lib_logger.h"
44 
45 
47  m_frame( aFrame ),
48  m_syncHash( 0 )
49 {
51  m_adapter->ShowUnits( false );
52  m_logger = new LIB_LOGGER();
53 }
54 
55 
57 {
58  delete m_logger;
59 }
60 
61 
62 void SYMBOL_LIBRARY_MANAGER::Sync( const wxString& aForceRefresh,
63  std::function<void( int, int,
64  const wxString& )> aProgressCallback )
65 {
66  m_logger->Activate();
67  {
68  getAdapter()->Sync( aForceRefresh, aProgressCallback );
70  }
72 }
73 
74 
76 {
77  const int progressIntervalMillis = 60;
78 
79  SYMBOL_ASYNC_LOADER loader( symTable()->GetLogicalLibs(), symTable(), false, nullptr,
80  &aReporter );
81 
82  LOCALE_IO toggle;
83 
84  loader.Start();
85 
86  while( !loader.Done() )
87  {
88  aReporter.KeepRefreshing();
89 
90  wxMilliSleep( progressIntervalMillis );
91  }
92 
93  if( aReporter.IsCancelled() )
94  {
95  loader.Abort();
96  }
97  else
98  {
99  loader.Join();
100  }
101 
102  if( !loader.GetErrors().IsEmpty() )
103  {
104  HTML_MESSAGE_BOX dlg( &m_frame, _( "Load Error" ) );
105 
106  dlg.MessageSet( _( "Errors loading symbols:" ) );
107 
108  wxString msg = loader.GetErrors();
109  msg.Replace( "\n", "<BR>" );
110 
111  dlg.AddHTML_Text( msg );
112  dlg.ShowModal();
113  }
114 }
115 
116 
118 {
119  for( const auto& lib : m_libs )
120  {
121  if( lib.second.IsModified() )
122  return true;
123  }
124 
125  return false;
126 }
127 
128 
130 {
131  int hash = symTable()->GetModifyHash();
132 
133  for( const auto& lib : m_libs )
134  hash += lib.second.GetHash();
135 
136  return hash;
137 }
138 
139 
140 int SYMBOL_LIBRARY_MANAGER::GetLibraryHash( const wxString& aLibrary ) const
141 {
142  const auto libBufIt = m_libs.find( aLibrary );
143 
144  if( libBufIt != m_libs.end() )
145  return libBufIt->second.GetHash();
146 
147  auto row = GetLibrary( aLibrary );
148 
149  // return -1 if library does not exist or 0 if not modified
150  return row ? std::hash<std::string>{}( aLibrary.ToStdString() +
151  row->GetFullURI( true ).ToStdString() ) : -1;
152 }
153 
154 
156 {
157  wxArrayString res;
158 
159  for( const auto& libName : symTable()->GetLogicalLibs() )
160  res.Add( libName );
161 
162  return res;
163 }
164 
165 
167 {
168  SYMBOL_LIB_TABLE_ROW* row = nullptr;
169 
170  try
171  {
172  row = symTable()->FindRow( aLibrary, true );
173  }
174  catch( const IO_ERROR& e )
175  {
176  wxLogMessage( _( "Library '%s' not found in the Symbol Library Table." ) + e.What(),
177  aLibrary );
178  }
179 
180  return row;
181 }
182 
183 
184 bool SYMBOL_LIBRARY_MANAGER::SaveLibrary( const wxString& aLibrary, const wxString& aFileName,
185  SCH_IO_MGR::SCH_FILE_T aFileType )
186 {
187  wxCHECK( aFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY && LibraryExists( aLibrary ), false );
188  wxFileName fn( aFileName );
189  wxCHECK( !fn.FileExists() || fn.IsFileWritable(), false );
190  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( aFileType ) );
191  bool res = true; // assume all libraries are successfully saved
192 
193  PROPERTIES properties;
194  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
195 
196  auto it = m_libs.find( aLibrary );
197 
198  if( it != m_libs.end() )
199  {
200  // Handle buffered library
201  LIB_BUFFER& libBuf = it->second;
202 
203  const auto& symbolBuffers = libBuf.GetBuffers();
204 
205  for( const auto& symbolBuf : symbolBuffers )
206  {
207  if( !libBuf.SaveBuffer( symbolBuf, aFileName, &*pi, true ) )
208  {
209  // Something went wrong, but try to save other libraries
210  res = false;
211  }
212  }
213 
214  // clear the deleted symbols buffer only if data is saved to the original file
215  wxFileName original, destination( aFileName );
216  auto row = GetLibrary( aLibrary );
217 
218  if( row )
219  {
220  original = row->GetFullURI( true );
221  original.Normalize();
222  }
223 
224  destination.Normalize();
225 
226  if( res && original == destination )
227  libBuf.ClearDeletedBuffer();
228  }
229  else
230  {
231  // Handle original library
232  for( LIB_SYMBOL* symbol : getOriginalSymbols( aLibrary ) )
233  {
234  LIB_SYMBOL* newSymbol;
235 
236  if( symbol->IsAlias() )
237  {
238  std::shared_ptr< LIB_SYMBOL > oldParent = symbol->GetParent().lock();
239 
240  wxCHECK_MSG( oldParent, false,
241  wxString::Format( "Derived symbol '%s' found with undefined parent.",
242  symbol->GetName() ) );
243 
244  LIB_SYMBOL* libParent = pi->LoadSymbol( aLibrary, oldParent->GetName(),
245  &properties );
246 
247  if( !libParent )
248  {
249  libParent = new LIB_SYMBOL( *oldParent.get() );
250  pi->SaveSymbol( aLibrary, libParent, &properties );
251  }
252 
253  newSymbol = new LIB_SYMBOL( *symbol );
254  newSymbol->SetParent( libParent );
255  pi->SaveSymbol( aLibrary, newSymbol, &properties );
256  }
257  else if( !pi->LoadSymbol( aLibrary, symbol->GetName(), &properties ) )
258  {
259  pi->SaveSymbol( aLibrary, new LIB_SYMBOL( *symbol ), &properties );
260  }
261  }
262  }
263 
264  try
265  {
266  pi->SaveLibrary( aFileName );
267  }
268  catch( ... )
269  {
270  // return false because something happens.
271  // The library is not successfully saved
272  res = false;
273  }
274 
275  return res;
276 }
277 
278 
279 bool SYMBOL_LIBRARY_MANAGER::IsLibraryModified( const wxString& aLibrary ) const
280 {
281  auto it = m_libs.find( aLibrary );
282  return it != m_libs.end() ? it->second.IsModified() : false;
283 }
284 
285 
286 bool SYMBOL_LIBRARY_MANAGER::IsSymbolModified( const wxString& aAlias,
287  const wxString& aLibrary ) const
288 {
289  auto libIt = m_libs.find( aLibrary );
290 
291  if( libIt == m_libs.end() )
292  return false;
293 
294  const LIB_BUFFER& buf = libIt->second;
295  auto symbolBuf = buf.GetBuffer( aAlias );
296  return symbolBuf ? symbolBuf->IsModified() : false;
297 }
298 
299 
300 bool SYMBOL_LIBRARY_MANAGER::ClearLibraryModified( const wxString& aLibrary ) const
301 {
302  auto libIt = m_libs.find( aLibrary );
303 
304  if( libIt == m_libs.end() )
305  return false;
306 
307  for( auto& symbolBuf : libIt->second.GetBuffers() )
308  {
309  SCH_SCREEN* screen = symbolBuf->GetScreen();
310 
311  if( screen )
312  screen->SetContentModified( false );
313  }
314 
315  return true;
316 }
317 
318 
319 bool SYMBOL_LIBRARY_MANAGER::ClearSymbolModified( const wxString& aAlias,
320  const wxString& aLibrary ) const
321 {
322  auto libI = m_libs.find( aLibrary );
323 
324  if( libI == m_libs.end() )
325  return false;
326 
327  auto symbolBuf = libI->second.GetBuffer( aAlias );
328  wxCHECK( symbolBuf, false );
329 
330  symbolBuf->GetScreen()->SetContentModified( false );
331  return true;
332 }
333 
334 
335 bool SYMBOL_LIBRARY_MANAGER::IsLibraryReadOnly( const wxString& aLibrary ) const
336 {
337  wxCHECK( LibraryExists( aLibrary ), true );
338 
339  return !symTable()->IsSymbolLibWritable( aLibrary );
340 }
341 
342 
343 bool SYMBOL_LIBRARY_MANAGER::IsLibraryLoaded( const wxString& aLibrary ) const
344 {
345  wxCHECK( LibraryExists( aLibrary ), false );
346 
347  return symTable()->IsSymbolLibLoaded( aLibrary );
348 }
349 
350 
351 std::list<LIB_SYMBOL*> SYMBOL_LIBRARY_MANAGER::GetAliases( const wxString& aLibrary ) const
352 {
353  std::list<LIB_SYMBOL*> ret;
354  wxCHECK( LibraryExists( aLibrary ), ret );
355 
356  auto libIt = m_libs.find( aLibrary );
357 
358  if( libIt != m_libs.end() )
359  {
360  for( auto& symbolBuf : libIt->second.GetBuffers() )
361  {
362  ret.push_back( symbolBuf->GetSymbol() );
363  }
364  }
365  else
366  {
367  std::vector<LIB_SYMBOL*> aliases;
368 
369  try
370  {
371  symTable()->LoadSymbolLib( aliases, aLibrary );
372  }
373  catch( const IO_ERROR& e )
374  {
375  wxLogWarning( e.Problem() );
376  }
377 
378  std::copy( aliases.begin(), aliases.end(), std::back_inserter( ret ) );
379  }
380 
381  return ret;
382 }
383 
384 
386  const wxString& aLibrary )
387 {
388  wxCHECK( LibraryExists( aLibrary ), nullptr );
389 
390  // try the library buffers first
391  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
392  LIB_SYMBOL* bufferedSymbol = libBuf.GetSymbol( aAlias );
393 
394  if( !bufferedSymbol ) // no buffer symbol found
395  {
396  // create a copy of the symbol
397  try
398  {
399  LIB_SYMBOL* symbol = symTable()->LoadSymbol( aLibrary, aAlias );
400 
401  if( symbol == nullptr )
402  THROW_IO_ERROR( _( "Symbol not found." ) );
403 
404  LIB_SYMBOL* bufferedParent = nullptr;
405 
406  // Create parent symbols on demand so parent symbol can be set.
407  if( symbol->IsAlias() )
408  {
409  std::shared_ptr< LIB_SYMBOL > parent = symbol->GetParent().lock();
410  wxCHECK_MSG( parent, nullptr,
411  wxString::Format( "Derived symbol '%s' found with undefined parent.",
412  symbol->GetName() ) );
413 
414  // Check if the parent symbol buffer has already be created.
415  bufferedParent = libBuf.GetSymbol( parent->GetName() );
416 
417  if( !bufferedParent )
418  {
419  bufferedParent = new LIB_SYMBOL( *parent.get() );
420  libBuf.CreateBuffer( bufferedParent, new SCH_SCREEN );
421  }
422  }
423 
424  bufferedSymbol = new LIB_SYMBOL( *symbol );
425 
426  if( bufferedParent )
427  bufferedSymbol->SetParent( bufferedParent );
428 
429  libBuf.CreateBuffer( bufferedSymbol, new SCH_SCREEN );
430  }
431  catch( const IO_ERROR& e )
432  {
433  wxLogMessage( _( "Error loading symbol %s from library '%s'. (%s)" ),
434  aAlias, aLibrary, e.What() );
435  bufferedSymbol = nullptr;
436  }
437  }
438 
439  return bufferedSymbol;
440 }
441 
442 
443 SCH_SCREEN* SYMBOL_LIBRARY_MANAGER::GetScreen( const wxString& aAlias, const wxString& aLibrary )
444 {
445  wxCHECK( LibraryExists( aLibrary ), nullptr );
446  wxCHECK( !aAlias.IsEmpty(), nullptr );
447  auto it = m_libs.find( aLibrary );
448  wxCHECK( it != m_libs.end(), nullptr );
449 
450  LIB_BUFFER& buf = it->second;
451  auto symbolBuf = buf.GetBuffer( aAlias );
452  return symbolBuf ? symbolBuf->GetScreen() : nullptr;
453 }
454 
455 
456 bool SYMBOL_LIBRARY_MANAGER::UpdateSymbol( LIB_SYMBOL* aSymbol, const wxString& aLibrary )
457 {
458  wxCHECK( LibraryExists( aLibrary ), false );
459  wxCHECK( aSymbol, false );
460  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
461  auto symbolBuf = libBuf.GetBuffer( aSymbol->GetName() );
462 
463  if( symbolBuf ) // Existing symbol.
464  {
465  LIB_SYMBOL* bufferedSymbol = const_cast< LIB_SYMBOL* >( symbolBuf->GetSymbol() );
466 
467  wxCHECK( bufferedSymbol, false );
468 
469  *bufferedSymbol = *aSymbol;
470  symbolBuf->GetScreen()->SetContentModified();
471  }
472  else // New symbol
473  {
474  LIB_SYMBOL* symbolCopy = new LIB_SYMBOL( *aSymbol, nullptr );
475 
476  symbolCopy->SetLibId( LIB_ID( aLibrary, aSymbol->GetLibId().GetLibItemName() ) );
477 
478  SCH_SCREEN* screen = new SCH_SCREEN;
479  libBuf.CreateBuffer( symbolCopy, screen );
480  screen->SetContentModified();
481  }
482 
483  return true;
484 }
485 
486 
487 bool SYMBOL_LIBRARY_MANAGER::UpdateSymbolAfterRename( LIB_SYMBOL* aSymbol, const wxString& aOldName,
488  const wxString& aLibrary )
489 {
490  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
491  auto symbolBuf = libBuf.GetBuffer( aOldName );
492 
493  wxCHECK( symbolBuf, false );
494 
495  libBuf.UpdateBuffer( symbolBuf, aSymbol );
496  m_frame.SyncLibraries( false );
497 
498  return true;
499 }
500 
501 
502 bool SYMBOL_LIBRARY_MANAGER::FlushSymbol( const wxString& aAlias, const wxString& aLibrary )
503 {
504  auto it = m_libs.find( aLibrary );
505 
506  if( it == m_libs.end() ) // no items to flush
507  return true;
508 
509  auto symbolBuf = it->second.GetBuffer( aAlias );
510  wxCHECK( symbolBuf, false );
511 
512  return it->second.SaveBuffer( symbolBuf, symTable() );
513 }
514 
515 
516 LIB_ID SYMBOL_LIBRARY_MANAGER::RevertSymbol( const wxString& aAlias, const wxString& aLibrary )
517 {
518  auto it = m_libs.find( aLibrary );
519 
520  if( it == m_libs.end() ) // no items to flush
521  return LIB_ID( aLibrary, aAlias );
522 
523  auto symbolBuf = it->second.GetBuffer( aAlias );
524  wxCHECK( symbolBuf, LIB_ID( aLibrary, aAlias ) );
525  LIB_SYMBOL original( *symbolBuf->GetOriginal() );
526 
527  if( original.GetName() != aAlias )
528  {
529  UpdateSymbolAfterRename( &original, aAlias, aLibrary );
530  }
531  else
532  {
533  symbolBuf->SetSymbol( new LIB_SYMBOL( original ) );
534  m_frame.SyncLibraries( false );
535  }
536 
537  return LIB_ID( aLibrary, original.GetName() );
538 }
539 
540 
541 bool SYMBOL_LIBRARY_MANAGER::RevertLibrary( const wxString& aLibrary )
542 {
543  auto it = m_libs.find( aLibrary );
544 
545  if( it == m_libs.end() ) // nothing to reverse
546  return false;
547 
548  m_libs.erase( it );
549  m_frame.SyncLibraries( false );
550 
551  return true;
552 }
553 
554 
556 {
557  bool retv = true;
558 
559  // Nothing to revert.
560  if( GetHash() == 0 )
561  return true;
562 
563  for( const auto& lib : m_libs )
564  {
565  if( !lib.second.IsModified() )
566  continue;
567 
568  for( const auto& buffer : lib.second.GetBuffers() )
569  {
570  if( !buffer->IsModified() )
571  continue;
572 
573  RevertSymbol( lib.first, buffer->GetOriginal()->GetName() );
574  }
575  }
576 
577  return retv;
578 }
579 
580 
581 bool SYMBOL_LIBRARY_MANAGER::RemoveSymbol( const wxString& aAlias, const wxString& aLibrary )
582 {
583  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
584  auto symbolBuf = libBuf.GetBuffer( aAlias );
585  wxCHECK( symbolBuf, false );
586 
587  bool retv = true;
588 
589  retv &= libBuf.DeleteBuffer( symbolBuf );
590  m_frame.SyncLibraries( false );
591 
592  return retv;
593 }
594 
595 
597  const wxString& aLibrary ) const
598 {
599  // Try the library buffers first
600  auto libIt = m_libs.find( aLibrary );
601 
602  if( libIt != m_libs.end() )
603  {
604  LIB_SYMBOL* symbol = libIt->second.GetSymbol( aAlias );
605 
606  if( symbol )
607  return symbol;
608  }
609 
610  // Get the original symbol
611  LIB_SYMBOL* alias = nullptr;
612 
613  try
614  {
615  alias = symTable()->LoadSymbol( aLibrary, aAlias );
616  }
617  catch( const IO_ERROR& e )
618  {
619  wxLogMessage( _( "Cannot load symbol '%s' from library '%s'." ) + e.What(),
620  aAlias,
621  aLibrary );
622  }
623 
624  return alias;
625 }
626 
627 
628 bool SYMBOL_LIBRARY_MANAGER::SymbolExists( const wxString& aAlias, const wxString& aLibrary ) const
629 {
630  auto libBufIt = m_libs.find( aLibrary );
631  LIB_SYMBOL* alias = nullptr;
632 
633  if( libBufIt != m_libs.end() )
634  return !!libBufIt->second.GetBuffer( aAlias );
635 
636  try
637  {
638  alias = symTable()->LoadSymbol( aLibrary, aAlias );
639  }
640  catch( IO_ERROR& )
641  {
642  // checking if certain symbol exists, so its absence is perfectly fine
643  }
644 
645  return alias != nullptr;
646 }
647 
648 
649 bool SYMBOL_LIBRARY_MANAGER::LibraryExists( const wxString& aLibrary, bool aCheckEnabled ) const
650 {
651  if( aLibrary.IsEmpty() )
652  return false;
653 
654  if( m_libs.count( aLibrary ) > 0 )
655  return true;
656 
657  return symTable()->HasLibrary( aLibrary, aCheckEnabled );
658 }
659 
660 
662 {
663  wxString name = "New_Library";
664 
665  if( !LibraryExists( name ) )
666  return name;
667 
668  name += "_";
669 
670  for( unsigned int i = 0; i < std::numeric_limits<unsigned int>::max(); ++i )
671  {
672  if( !LibraryExists( name + wxString::Format( "%u", i ) ) )
673  return name + wxString::Format( "%u", i );
674  }
675 
676  wxFAIL;
677  return wxEmptyString;
678 }
679 
680 
681 void SYMBOL_LIBRARY_MANAGER::GetRootSymbolNames( const wxString& aLibraryName,
682  wxArrayString& aRootSymbolNames )
683 {
684  LIB_BUFFER& libBuf = getLibraryBuffer( aLibraryName );
685 
686  libBuf.GetRootSymbolNames( aRootSymbolNames );
687 }
688 
689 
690 bool SYMBOL_LIBRARY_MANAGER:: HasDerivedSymbols( const wxString& aSymbolName,
691  const wxString& aLibraryName )
692 {
693  LIB_BUFFER& libBuf = getLibraryBuffer( aLibraryName );
694 
695  return libBuf.HasDerivedSymbols( aSymbolName );
696 }
697 
698 
700 {
701  return symTable()->GetLogicalLibs().size();
702 }
703 
704 
705 wxString SYMBOL_LIBRARY_MANAGER::getLibraryName( const wxString& aFilePath )
706 {
707  wxFileName fn( aFilePath );
708  return fn.GetName();
709 }
710 
711 
712 bool SYMBOL_LIBRARY_MANAGER::addLibrary( const wxString& aFilePath, bool aCreate,
713  SYMBOL_LIB_TABLE* aTable )
714 {
715  wxCHECK( aTable, false );
716  wxString libName = getLibraryName( aFilePath );
717  wxCHECK( !LibraryExists( libName ), false ); // either create or add an existing one
718 
719  // try to use path normalized to an environmental variable or project path
720  wxString relPath = NormalizePath( aFilePath, &Pgm().GetLocalEnvVariables(), &m_frame.Prj() );
721 
722  if( relPath.IsEmpty() )
723  relPath = aFilePath;
724 
725  SCH_IO_MGR::SCH_FILE_T schFileType = SCH_IO_MGR::GuessPluginTypeFromLibPath( aFilePath );
726  wxString typeName = SCH_IO_MGR::ShowType( schFileType );
727  SYMBOL_LIB_TABLE_ROW* libRow = new SYMBOL_LIB_TABLE_ROW( libName, relPath, typeName );
728  aTable->InsertRow( libRow );
729 
730  if( aCreate )
731  {
732  wxCHECK( schFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY, false );
733 
734  try
735  {
736  aTable->CreateSymbolLib( libName );
737  }
738  catch( const IO_ERROR& )
739  {
740  aTable->RemoveRow( libRow );
741  return false;
742  }
743  }
744 
745  m_frame.SyncLibraries( false );
746 
747  return true;
748 }
749 
750 
752 {
753  return m_frame.Prj().SchSymbolLibTable();
754 }
755 
756 
757 std::set<LIB_SYMBOL*> SYMBOL_LIBRARY_MANAGER::getOriginalSymbols( const wxString& aLibrary )
758 {
759  std::set<LIB_SYMBOL*> symbols;
760  wxCHECK( LibraryExists( aLibrary ), symbols );
761 
762  try
763  {
764  wxArrayString aliases;
765  symTable()->EnumerateSymbolLib( aLibrary, aliases );
766 
767  for( const auto& aliasName : aliases )
768  {
769  LIB_SYMBOL* alias = symTable()->LoadSymbol( aLibrary, aliasName );
770  symbols.insert( alias );
771  }
772  }
773  catch( const IO_ERROR& e )
774  {
775  wxLogMessage( _( "Cannot enumerate library '%s'." ) + e.What(), aLibrary );
776  }
777 
778  return symbols;
779 }
780 
781 
783  const wxString& aLibrary )
784 {
785  auto it = m_libs.find( aLibrary );
786 
787  if( it != m_libs.end() )
788  return it->second;
789 
790  // The requested buffer does not exist yet, so create one
791  auto ret = m_libs.emplace( aLibrary, LIB_BUFFER( aLibrary ) );
792  LIB_BUFFER& buf = ret.first->second;
793 
794  for( auto symbol : getOriginalSymbols( aLibrary ) )
795  {
796  LIB_SYMBOL* newSymbol;
797 
798  if( symbol->IsAlias() )
799  {
800  std::shared_ptr< LIB_SYMBOL > oldParent = symbol->GetParent().lock();
801 
802  wxCHECK_MSG( oldParent, buf,
803  wxString::Format( "Derived symbol '%s' found with undefined parent.",
804  symbol->GetName() ) );
805 
806  LIB_SYMBOL* libParent = buf.GetSymbol( oldParent->GetName() );
807 
808  if( !libParent )
809  {
810  libParent = new LIB_SYMBOL( *oldParent.get() );
811  buf.CreateBuffer( libParent, new SCH_SCREEN );
812  }
813 
814  newSymbol = new LIB_SYMBOL( *symbol );
815  newSymbol->SetParent( libParent );
816  buf.CreateBuffer( newSymbol, new SCH_SCREEN );
817  }
818  else if( !buf.GetSymbol( symbol->GetName() ) )
819  {
820  buf.CreateBuffer( new LIB_SYMBOL( *symbol ), new SCH_SCREEN );
821  }
822  }
823 
824  return buf;
825 }
826 
827 
829  std::unique_ptr<SCH_SCREEN> aScreen ) :
830  m_screen( std::move( aScreen ) ),
831  m_symbol( aSymbol )
832 {
833  m_original = new LIB_SYMBOL( *aSymbol );
834 }
835 
836 
838 {
839  delete m_symbol;
840  delete m_original;
841 }
842 
843 
845 {
846  wxCHECK( m_symbol != aSymbol, /* void */ );
847  wxASSERT( aSymbol );
848  delete m_symbol;
849  m_symbol = aSymbol;
850 
851  // If the symbol moves libraries then the original moves with it
852  if( m_original->GetLibId().GetLibNickname() != m_symbol->GetLibId().GetLibNickname() )
853  {
854  m_original->SetLibId( LIB_ID( m_symbol->GetLibId().GetLibNickname(),
855  m_original->GetLibId().GetLibItemName() ) );
856  }
857 }
858 
859 
861 {
862  wxCHECK( m_original != aSymbol, /* void */ );
863  wxASSERT( aSymbol );
864  delete m_original;
865  m_original = aSymbol;
866 
867  // The original is not allowed to have a different library than its symbol
868  if( m_original->GetLibId().GetLibNickname() != m_symbol->GetLibId().GetLibNickname() )
869  {
870  m_original->SetLibId( LIB_ID( m_symbol->GetLibId().GetLibNickname(),
871  m_original->GetLibId().GetLibItemName() ) );
872  }
873 }
874 
875 
877 {
878  return m_screen && m_screen->IsContentModified();
879 }
880 
881 
883 {
884  auto buf = GetBuffer( aAlias );
885 
886  if( !buf )
887  return nullptr;
888 
889  LIB_SYMBOL* symbol = buf->GetSymbol();
890 
891  wxCHECK( symbol, nullptr );
892 
893  return symbol;
894 }
895 
896 
898 {
899  wxASSERT( aCopy );
900  wxASSERT( aCopy->GetLib() == nullptr );
901  std::unique_ptr<SCH_SCREEN> screen( aScreen );
902  auto symbolBuf = std::make_shared<SYMBOL_BUFFER>( aCopy, std::move( screen ) );
903  m_symbols.push_back( symbolBuf );
904 
905  // Set the parent library name,
906  // otherwise it is empty as no library has been given as the owner during object construction
907  LIB_ID libId = aCopy->GetLibId();
908  libId.SetLibNickname( m_libName );
909  aCopy->SetLibId( libId );
910  ++m_hash;
911 
912  return true;
913 }
914 
915 
916 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::UpdateBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf,
917  LIB_SYMBOL* aCopy )
918 {
919  wxCHECK( aCopy && aSymbolBuf, false );
920 
921  LIB_SYMBOL* bufferedSymbol = aSymbolBuf->GetSymbol();
922 
923  wxCHECK( bufferedSymbol, false );
924 
925  *bufferedSymbol = *aCopy;
926  ++m_hash;
927 
928  return true;
929 }
930 
931 
932 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::DeleteBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf )
933 {
934  auto symbolBufIt = std::find( m_symbols.begin(), m_symbols.end(), aSymbolBuf );
935  wxCHECK( symbolBufIt != m_symbols.end(), false );
936 
937  bool retv = true;
938 
939  // Remove all derived symbols to prevent broken inheritance.
940  if( aSymbolBuf->GetSymbol()->IsRoot() && HasDerivedSymbols( aSymbolBuf->GetSymbol()->GetName() )
941  && removeChildSymbols( aSymbolBuf ) == 0 )
942  {
943  retv = false;
944  }
945 
946  m_deleted.emplace_back( *symbolBufIt );
947  m_symbols.erase( symbolBufIt );
948  ++m_hash;
949 
950  return retv;
951 }
952 
953 
954 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::SaveBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf,
955  SYMBOL_LIB_TABLE* aLibTable )
956 {
957  wxCHECK( aSymbolBuf, false );
958  LIB_SYMBOL* libSymbol = aSymbolBuf->GetSymbol();
959  LIB_SYMBOL* originalSymbol = aSymbolBuf->GetOriginal();
960  wxCHECK( libSymbol && originalSymbol, false );
962  PROPERTIES properties;
963  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
964 
965  // Delete the original symbol if the symbol name has been changed.
966  if( libSymbol->GetName() != originalSymbol->GetName() )
967  {
968  if( aLibTable->LoadSymbol( m_libName, originalSymbol->GetName() ) )
969  aLibTable->DeleteSymbol( m_libName, originalSymbol->GetName() );
970  }
971 
972  if( libSymbol->IsAlias() )
973  {
974  LIB_SYMBOL* newCachedSymbol = new LIB_SYMBOL( *libSymbol );
975  std::shared_ptr< LIB_SYMBOL > bufferedParent = libSymbol->GetParent().lock();
976 
977  wxCHECK( bufferedParent, false );
978 
979  LIB_SYMBOL* cachedParent = aLibTable->LoadSymbol( m_libName, bufferedParent->GetName() );
980 
981  if( !cachedParent )
982  {
983  cachedParent = new LIB_SYMBOL( *bufferedParent.get() );
984  newCachedSymbol->SetParent( cachedParent );
985  result = aLibTable->SaveSymbol( m_libName, cachedParent );
986  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
987  result = aLibTable->SaveSymbol( m_libName, newCachedSymbol );
988  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
989 
990  LIB_SYMBOL* originalParent = new LIB_SYMBOL( *bufferedParent.get() );
991  aSymbolBuf->SetOriginal( originalParent );
992  originalSymbol = new LIB_SYMBOL( *libSymbol );
993  originalSymbol->SetParent( originalParent );
994  aSymbolBuf->SetOriginal( originalSymbol );
995  }
996  else
997  {
998  newCachedSymbol->SetParent( cachedParent );
999  result = aLibTable->SaveSymbol( m_libName, newCachedSymbol );
1000  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1001 
1002  auto originalBufferedParent = GetBuffer( bufferedParent->GetName() );
1003  wxCHECK( originalBufferedParent, false );
1004  originalSymbol = new LIB_SYMBOL( *libSymbol );
1005  originalSymbol->SetParent( originalBufferedParent->GetSymbol() );
1006  aSymbolBuf->SetOriginal( originalSymbol );
1007  }
1008  }
1009  else
1010  {
1011  wxArrayString derivedSymbols;
1012 
1013  if( GetDerivedSymbolNames( libSymbol->GetName(), derivedSymbols ) == 0 )
1014  {
1015  result = aLibTable->SaveSymbol( m_libName, new LIB_SYMBOL( *libSymbol ) );
1016  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1017  aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1018  }
1019  else
1020  {
1021  LIB_SYMBOL* parentSymbol = new LIB_SYMBOL( *libSymbol );
1022 
1023  aLibTable->SaveSymbol( m_libName, parentSymbol );
1024 
1025  for( auto entry : derivedSymbols )
1026  {
1027  std::shared_ptr<SYMBOL_BUFFER> symbol = GetBuffer( entry );
1028  LIB_SYMBOL* derivedSymbol = new LIB_SYMBOL( *symbol->GetSymbol() );
1029  derivedSymbol->SetParent( parentSymbol );
1030  result = aLibTable->SaveSymbol( m_libName, derivedSymbol );
1031  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1032  }
1033  }
1034  }
1035 
1036  ++m_hash;
1037  return true;
1038 }
1039 
1040 
1041 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::SaveBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf,
1042  const wxString& aFileName,
1043  SCH_PLUGIN* aPlugin, bool aBuffer )
1044 {
1045  wxCHECK( aSymbolBuf, false );
1046  LIB_SYMBOL* libSymbol = aSymbolBuf->GetSymbol();
1047  LIB_SYMBOL* originalSymbol = aSymbolBuf->GetOriginal();
1048  wxCHECK( libSymbol && originalSymbol, false );
1049  wxCHECK( !aFileName.IsEmpty(), false );
1050 
1051  wxString errorMsg = _( "Error saving symbol %s to library '%s'." ) + wxS( "\n%s" );
1052 
1053  // set properties to prevent save file on every symbol save
1054  PROPERTIES properties;
1055  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
1056 
1057  // Delete the original symbol if the symbol name has been changed.
1058  if( libSymbol->GetName() != originalSymbol->GetName() )
1059  {
1060  if( aPlugin->LoadSymbol( aFileName, originalSymbol->GetName() ) )
1061  aPlugin->DeleteSymbol( aFileName, originalSymbol->GetName(), &properties );
1062  }
1063 
1064  if( libSymbol->IsAlias() )
1065  {
1066  LIB_SYMBOL* newCachedSymbol = new LIB_SYMBOL( *libSymbol );
1067  std::shared_ptr< LIB_SYMBOL > bufferedParent = libSymbol->GetParent().lock();
1068 
1069  wxCHECK( bufferedParent, false );
1070 
1071  LIB_SYMBOL* cachedParent = nullptr;
1072 
1073  try
1074  {
1075  cachedParent = aPlugin->LoadSymbol( aFileName, bufferedParent->GetName() );
1076  }
1077  catch( const IO_ERROR& )
1078  {
1079  return false;
1080  }
1081 
1082  if( !cachedParent )
1083  {
1084  cachedParent = new LIB_SYMBOL( *bufferedParent.get() );
1085  newCachedSymbol->SetParent( cachedParent );
1086 
1087  try
1088  {
1089  aPlugin->SaveSymbol( aFileName, cachedParent, aBuffer ? &properties : nullptr );
1090  }
1091  catch( const IO_ERROR& ioe )
1092  {
1093  wxLogError( errorMsg, UnescapeString( cachedParent->GetName() ), aFileName,
1094  ioe.What() );
1095  return false;
1096  }
1097 
1098  try
1099  {
1100  aPlugin->SaveSymbol( aFileName, newCachedSymbol, aBuffer ? &properties : nullptr );
1101  }
1102  catch( const IO_ERROR& ioe )
1103  {
1104  wxLogError( errorMsg, UnescapeString( newCachedSymbol->GetName() ), aFileName,
1105  ioe.What() );
1106  return false;
1107  }
1108 
1109  LIB_SYMBOL* originalParent = new LIB_SYMBOL( *bufferedParent.get() );
1110  aSymbolBuf->SetOriginal( originalParent );
1111  originalSymbol = new LIB_SYMBOL( *libSymbol );
1112  originalSymbol->SetParent( originalParent );
1113  aSymbolBuf->SetOriginal( originalSymbol );
1114  }
1115  else
1116  {
1117  newCachedSymbol->SetParent( cachedParent );
1118 
1119  try
1120  {
1121  aPlugin->SaveSymbol( aFileName, newCachedSymbol, aBuffer ? &properties : nullptr );
1122  }
1123  catch( const IO_ERROR& ioe )
1124  {
1125  wxLogError( errorMsg, UnescapeString( newCachedSymbol->GetName() ), aFileName,
1126  ioe.What() );
1127  return false;
1128  }
1129 
1130  auto originalBufferedParent = GetBuffer( bufferedParent->GetName() );
1131  wxCHECK( originalBufferedParent, false );
1132  originalSymbol = new LIB_SYMBOL( *libSymbol );
1133  originalSymbol->SetParent( originalBufferedParent->GetSymbol() );
1134  aSymbolBuf->SetOriginal( originalSymbol );
1135  }
1136  }
1137  else
1138  {
1139  wxArrayString derivedSymbols;
1140 
1141  if( GetDerivedSymbolNames( libSymbol->GetName(), derivedSymbols ) == 0 )
1142  {
1143  try
1144  {
1145  aPlugin->SaveSymbol( aFileName, new LIB_SYMBOL( *libSymbol ),
1146  aBuffer ? &properties : nullptr );
1147  }
1148  catch( const IO_ERROR& ioe )
1149  {
1150  wxLogError( errorMsg, UnescapeString( libSymbol->GetName() ), aFileName,
1151  ioe.What() );
1152  return false;
1153  }
1154 
1155  aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1156  }
1157  else
1158  {
1159  LIB_SYMBOL* parentSymbol = new LIB_SYMBOL( *libSymbol );
1160 
1161  // Save the modified root symbol.
1162  try
1163  {
1164  aPlugin->SaveSymbol( aFileName, parentSymbol, aBuffer ? &properties : nullptr );
1165  }
1166  catch( const IO_ERROR& ioe )
1167  {
1168  wxLogError( errorMsg, UnescapeString( libSymbol->GetName() ), aFileName,
1169  ioe.What() );
1170  return false;
1171  }
1172 
1173  aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1174 
1175  // Save the derived symbols.
1176  for( auto entry : derivedSymbols )
1177  {
1178  std::shared_ptr<SYMBOL_BUFFER> symbol = GetBuffer( entry );
1179  LIB_SYMBOL* derivedSymbol = new LIB_SYMBOL( *symbol->GetSymbol() );
1180  derivedSymbol->SetParent( parentSymbol );
1181 
1182  try
1183  {
1184  aPlugin->SaveSymbol( aFileName, new LIB_SYMBOL( *derivedSymbol ),
1185  aBuffer ? &properties : nullptr );
1186  }
1187  catch( const IO_ERROR& ioe )
1188  {
1189  wxLogError( errorMsg, UnescapeString( derivedSymbol->GetName() ), aFileName,
1190  ioe.What() );
1191  return false;
1192  }
1193  }
1194  }
1195  }
1196 
1197  ++m_hash;
1198  return true;
1199 }
1200 
1201 
1202 std::shared_ptr<SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER>
1203 SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::GetBuffer( const wxString& aAlias ) const
1204 {
1205  for( auto entry : m_symbols )
1206  {
1207  if( entry->GetSymbol()->GetName() == aAlias )
1208  return entry;
1209  }
1210 
1211  return std::shared_ptr<SYMBOL_BUFFER>( nullptr );
1212 }
1213 
1214 
1215 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::HasDerivedSymbols( const wxString& aParentName ) const
1216 {
1217  for( auto entry : m_symbols )
1218  {
1219  if( entry->GetSymbol()->IsAlias() )
1220  {
1221  LIB_SYMBOL_SPTR parent = entry->GetSymbol()->GetParent().lock();
1222 
1223  // Check for inherited symbol without a valid parent.
1224  wxCHECK( parent, false );
1225 
1226  if( parent->GetName() == aParentName )
1227  return true;
1228  }
1229  }
1230 
1231  return false;
1232 }
1233 
1234 
1235 void SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::GetRootSymbolNames( wxArrayString& aRootSymbolNames )
1236 {
1237  for( auto entry : m_symbols )
1238  {
1239  if( entry->GetSymbol()->IsAlias() )
1240  continue;
1241 
1242  aRootSymbolNames.Add( UnescapeString( entry->GetSymbol()->GetName() ) );
1243  }
1244 }
1245 
1246 
1248  wxArrayString& aList )
1249 {
1250  wxCHECK( !aSymbolName.IsEmpty(), 0 );
1251 
1252  for( auto entry : m_symbols )
1253  {
1254  if( entry->GetSymbol()->IsAlias() )
1255  {
1256  LIB_SYMBOL_SPTR parent = entry->GetSymbol()->GetParent().lock();
1257 
1258  // Check for inherited symbol without a valid parent.
1259  wxCHECK( parent, false );
1260 
1261  if( parent->GetName() == aSymbolName )
1262  aList.Add( entry->GetSymbol()->GetName() );
1263  }
1264  }
1265 
1266  return aList.GetCount();
1267 }
1268 
1269 
1270 int SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::removeChildSymbols( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf )
1271 {
1272  wxCHECK( aSymbolBuf && aSymbolBuf->GetSymbol()->IsRoot(), 0 );
1273 
1274  int cnt = 0;
1275  std::deque< std::shared_ptr<SYMBOL_BUFFER> >::iterator it = m_symbols.begin();
1276 
1277  while( it != m_symbols.end() )
1278  {
1279 
1280  if( (*it)->GetSymbol()->IsRoot() )
1281  {
1282  ++it;
1283  }
1284  else
1285  {
1286  LIB_SYMBOL_SPTR parent = (*it)->GetSymbol()->GetParent().lock();
1287 
1288  wxCHECK2( parent, ++it; continue );
1289 
1290  if( parent->GetName() == aSymbolBuf->GetSymbol()->GetName() )
1291  {
1292  wxCHECK2( parent == aSymbolBuf->GetSymbol()->SharedPtr(), ++it; continue );
1293 
1294  m_deleted.emplace_back( *it );
1295  it = m_symbols.erase( it );
1296  cnt++;
1297  }
1298  else
1299  {
1300  ++it;
1301  }
1302  }
1303  }
1304 
1305  return cnt;
1306 }
static SCH_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath)
Return a plugin type given a symbol library using the file extension of aLibPath.
Definition: sch_io_mgr.cpp:151
virtual void DeleteSymbol(const wxString &aLibraryPath, const wxString &aSymbolName, const PROPERTIES *aProperties=nullptr)
Delete the entire LIB_SYMBOL associated with aAliasName from the library aLibraryPath.
Definition: sch_plugin.cpp:102
LIB_SYMBOL_REF & GetParent()
Definition: lib_symbol.h:124
bool UpdateBuffer(std::shared_ptr< SYMBOL_BUFFER > aSymbolBuf, LIB_SYMBOL *aCopy)
void EnumerateSymbolLib(const wxString &aNickname, wxArrayString &aAliasNames, bool aPowerSymbolsOnly=false)
Return a list of symbol alias names contained within the library given by aNickname.
const UTF8 & GetLibItemName() const
Definition: lib_id.h:104
const std::deque< std::shared_ptr< SYMBOL_BUFFER > > & GetBuffers() const
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_PLUGIN obje...
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
void GetRootSymbolNames(const wxString &aLibName, wxArrayString &aRootSymbolNames)
void Start()
Spins up threads to load all the libraries in m_nicknames.
static wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > Create(SYMBOL_EDIT_FRAME *aParent, SYMBOL_LIBRARY_MANAGER *aLibs)
bool SaveBuffer(std::shared_ptr< SYMBOL_BUFFER > aSymbolBuf, SYMBOL_LIB_TABLE *aLibTable)
Save stored modifications using a plugin.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:40
bool Join()
Finalizes the threads and combines the output into the target output map.
void CreateSymbolLib(const wxString &aNickname)
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
wxString GetName() const override
Definition: lib_symbol.h:133
bool ClearLibraryModified(const wxString &aLibrary) const
Clear the modified flag for all symbols in a library.
SAVE_T SaveSymbol(const wxString &aNickname, const LIB_SYMBOL *aSymbol, bool aOverwrite=true)
Write aSymbol to an existing library given by aNickname.
A progress reporter interface for use in multi-threaded environments.
SYMBOL_LIBRARY_MANAGER(SYMBOL_EDIT_FRAME &aFrame)
void Abort()
Cancels a load in-progress.
LIB_SYMBOL * GetBufferedSymbol(const wxString &aAlias, const wxString &aLibrary)
Return the symbol copy from the buffer.
static const wxString ShowType(SCH_FILE_T aFileType)
Return a brief name for a plugin, given aFileType enum.
Definition: sch_io_mgr.cpp:79
bool SaveLibrary(const wxString &aLibrary, const wxString &aFileName, SCH_IO_MGR::SCH_FILE_T aFileType=SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY)
Save library to a file, including unsaved changes.
bool IsAlias() const
Definition: lib_symbol.h:172
std::shared_ptr< LIB_SYMBOL > LIB_SYMBOL_SPTR
shared pointer to LIB_SYMBOL
Definition: lib_symbol.h:42
static wxString getLibraryName(const wxString &aFilePath)
< Extract library name basing on the file name.
SYMBOL_LIB_TABLE * symTable() const
bool RemoveSymbol(const wxString &aName, const wxString &aLibrary)
Remove the symbol from the symbol buffer.
Definition: bitmap.cpp:64
virtual void SaveSymbol(const wxString &aLibraryPath, const LIB_SYMBOL *aSymbol, const PROPERTIES *aProperties=nullptr)
Write aSymbol to an existing library located at aLibraryPath.
Definition: sch_plugin.cpp:94
LIB_SYMBOL * GetSymbol(const wxString &aAlias) const
Create a new buffer to store a symbol. LIB_BUFFER takes ownership of aCopy.
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
SYMBOL_EDIT_FRAME & m_frame
Parent frame.
A name/value tuple with unique names and optional values.
Definition: properties.h:33
bool IsSymbolLibWritable(const wxString &aNickname)
Return true if the library given by aNickname is writable.
Define a library symbol object.
Definition: lib_symbol.h:96
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
LIB_ID RevertSymbol(const wxString &aAlias, const wxString &aLibrary)
Revert unsaved changes for a symbolicular symbol.
bool RevertLibrary(const wxString &aLibrary)
Revert unsaved changes for a symbolicular library.
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:46
bool Done()
Returns a string containing any errors generated during the load.
LIB_BUFFER & getLibraryBuffer(const wxString &aLibrary)
Return an existing library buffer or creates one to using Symbol Library Table to get the original da...
SYMBOL_LIB * GetLib() const
Definition: lib_symbol.h:176
const wxString & GetErrors() const
Represents a pair of <nickname, loaded parts list>
bool IsSymbolLibLoaded(const wxString &aNickname)
Return true if the library given by aNickname was successfully loaded.
bool addLibrary(const wxString &aFilePath, bool aCreate, SYMBOL_LIB_TABLE *aTable)
Return the current Symbol Library Table.
bool FlushSymbol(const wxString &aAlias, const wxString &aLibrary)
Save symbol changes to the library copy used by the schematic editor.
bool SymbolExists(const wxString &aAlias, const wxString &aLibrary) const
Return true if symbol with a specific alias exists in library (either original one or buffered).
void Sync(const wxString &aForceRefresh, std::function< void(int, int, const wxString &)> aProgressCallback)
Base class that schematic file and library loading and saving plugins should derive from.
Definition: sch_io_mgr.h:152
wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > m_adapter
bool RevertAll()
Revert all pending changes.
wxString GetUniqueLibraryName() const
Return a library name that is not currently in use.
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
SYMBOL_LIB_TABLE_ROW * GetLibrary(const wxString &aLibrary) const
Find a single library within the (aggregate) library table.
int GetLibraryHash(const wxString &aLibrary) const
Return a library hash value to determine if it has changed.
LIB_ID GetLibId() const override
Definition: lib_symbol.h:135
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
void ClearDeletedBuffer()
Save stored modifications to Symbol Lib Table.
bool IsLibraryReadOnly(const wxString &aLibrary) const
Return true if the library is stored in a read-only file.
bool IsSymbolModified(const wxString &aAlias, const wxString &aLibrary) const
Return true if symbol has unsaved modifications.
Definition for symbol library class.
std::map< wxString, LIB_BUFFER > m_libs
#define _(s)
void SetParent(LIB_SYMBOL *aParent=nullptr)
Definition: lib_symbol.cpp:323
SYMBOL_TREE_SYNCHRONIZING_ADAPTER * getAdapter()
Class to store a working copy of a LIB_SYMBOL object and editor context.
bool HasDerivedSymbols(const wxString &aSymbolName, const wxString &aLibraryName)
Check if symbol aSymbolName in library aLibraryName is a root symbol that has derived symbols.
void Sync(const wxString &aForceRefresh, std::function< void(int, int, const wxString &)> aProgressCallback)
Updates the SYMBOL_LIBRARY_MANAGER data to synchronize with Symbol Library Table.
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:136
void Preload(PROGRESS_REPORTER &aReporter)
Preloads all symbol libraries in the symbol library table using SYMBOL_ASYNC_LOADER.
SYMBOL_BUFFER(LIB_SYMBOL *aSymbol=nullptr, std::unique_ptr< SCH_SCREEN > aScreen=nullptr)
void GetRootSymbolNames(wxArrayString &aRootSymbolNames)
Fetch a list of root symbols names from the library buffer.
void MessageSet(const wxString &message)
Add a message (in bold) to message list.
wxString UnescapeString(const wxString &aSource)
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:97
bool RemoveRow(LIB_TABLE_ROW *aRow)
Removes a row from the table.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
wxArrayString GetLibraryNames() const
Return the array of library names.
Helper object to release a SCH_PLUGIN in the context of a potential thrown exception through its dest...
Definition: sch_io_mgr.h:479
bool ClearSymbolModified(const wxString &aAlias, const wxString &aLibrary) const
Clear the modified flag for a symbol.
void LoadSymbolLib(std::vector< LIB_SYMBOL * > &aAliasList, const wxString &aNickname, bool aPowerSymbolsOnly=false)
bool IsLibraryModified(const wxString &aLibrary) const
Return true if library has unsaved modifications.
bool LibraryExists(const wxString &aLibrary, bool aCheckEnabled=false) const
Return true if library exists.
void Activate()
Definition: lib_logger.cpp:39
void Deactivate()
Definition: lib_logger.cpp:49
see class PGM_BASE
std::set< LIB_SYMBOL * > getOriginalSymbols(const wxString &aLibrary)
Return a set of LIB_SYMBOL objects belonging to the original library.
std::shared_ptr< SYMBOL_BUFFER > GetBuffer(const wxString &aAlias) const
Return all buffered symbols.
const char * name
Definition: DXF_plotter.cpp:56
void DeleteSymbol(const wxString &aNickname, const wxString &aSymbolName)
Deletes the aSymbolName from the library given by aNickname.
void AddHTML_Text(const wxString &message)
Add HTML text (without any change) to message list.
bool IsLibraryLoaded(const wxString &aLibrary) const
Return true if the library was successfully loaded.
size_t GetDerivedSymbolNames(const wxString &aSymbolName, wxArrayString &aList)
Fetch all of the symbols derived from a aSymbolName into aList.
int m_syncHash
Symbol lib table hash value from last synchronization.
static const char * PropBuffering
The property used internally by the plugin to enable cache buffering which prevents the library file ...
LIB_SYMBOL * GetAlias(const wxString &aAlias, const wxString &aLibrary) const
Return either an alias of a working LIB_SYMBOL copy, or alias of the original symbol if there is no w...
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
bool UpdateSymbol(LIB_SYMBOL *aSymbol, const wxString &aLibrary)
Update the symbol buffer with a new version of the symbol.
SCH_SCREEN * GetScreen(const wxString &aAlias, const wxString &aLibrary)
Return the screen used to edit a specific symbol.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
SAVE_T
The set of return values from SaveSymbol() below.
virtual bool IsCancelled() const =0
virtual LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aPartName, const PROPERTIES *aProperties=nullptr)
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
Definition: sch_plugin.cpp:85
SYMBOL_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an SYMBOL_LIB_TABLE_ROW if aNickName is found in this table or in any chained fallBack table f...
bool HasDerivedSymbols(const wxString &aParentName) const
Check to see any symbols in the buffer are derived from a parent named aParentName.
void SyncLibraries(bool aShowProgress, const wxString &aForceRefresh=wxEmptyString)
Synchronize the library manager to the symbol library table, and then the symbol tree to the library ...
bool CreateBuffer(LIB_SYMBOL *aCopy, SCH_SCREEN *aScreen)
Update the buffered symbol with the contents of aCopy.
bool DeleteBuffer(std::shared_ptr< SYMBOL_BUFFER > aSymbolBuf)
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
wxString NormalizePath(const wxFileName &aFilePath, const ENV_VAR_MAP *aEnvVars, const wxString &aProjectPath)
Normalize a file path to an environmental variable, if possible.
Definition: env_paths.cpp:69
int removeChildSymbols(std::shared_ptr< SYMBOL_BUFFER > aSymbolBuf)
Remove all symbols derived from aParent from the library buffer.
std::list< LIB_SYMBOL * > GetAliases(const wxString &aLibrary) const
bool UpdateSymbolAfterRename(LIB_SYMBOL *aSymbol, const wxString &oldAlias, const wxString &aLibrary)
Update the symbol buffer with a new version of the symbol when the name has changed.
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
The symbol library editor main window.