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 <[email protected]>
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  SCH_IO_MGR::SCH_FILE_T schFileType = SCH_IO_MGR::GuessPluginTypeFromLibPath( aFilePath );
723  wxString typeName = SCH_IO_MGR::ShowType( schFileType );
724  SYMBOL_LIB_TABLE_ROW* libRow = new SYMBOL_LIB_TABLE_ROW( libName, relPath, typeName );
725  aTable->InsertRow( libRow );
726 
727  if( aCreate )
728  {
729  wxCHECK( schFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY, false );
730 
731  try
732  {
733  aTable->CreateSymbolLib( libName );
734  }
735  catch( const IO_ERROR& )
736  {
737  aTable->RemoveRow( libRow );
738  return false;
739  }
740  }
741 
742  m_frame.SyncLibraries( false );
743 
744  return true;
745 }
746 
747 
749 {
750  return m_frame.Prj().SchSymbolLibTable();
751 }
752 
753 
754 std::set<LIB_SYMBOL*> SYMBOL_LIBRARY_MANAGER::getOriginalSymbols( const wxString& aLibrary )
755 {
756  std::set<LIB_SYMBOL*> symbols;
757  wxCHECK( LibraryExists( aLibrary ), symbols );
758 
759  try
760  {
761  wxArrayString aliases;
762  symTable()->EnumerateSymbolLib( aLibrary, aliases );
763 
764  for( const auto& aliasName : aliases )
765  {
766  LIB_SYMBOL* alias = symTable()->LoadSymbol( aLibrary, aliasName );
767  symbols.insert( alias );
768  }
769  }
770  catch( const IO_ERROR& e )
771  {
772  wxLogMessage( _( "Cannot enumerate library '%s'." ) + e.What(), aLibrary );
773  }
774 
775  return symbols;
776 }
777 
778 
780  const wxString& aLibrary )
781 {
782  auto it = m_libs.find( aLibrary );
783 
784  if( it != m_libs.end() )
785  return it->second;
786 
787  // The requested buffer does not exist yet, so create one
788  auto ret = m_libs.emplace( aLibrary, LIB_BUFFER( aLibrary ) );
789  LIB_BUFFER& buf = ret.first->second;
790 
791  for( auto symbol : getOriginalSymbols( aLibrary ) )
792  {
793  LIB_SYMBOL* newSymbol;
794 
795  if( symbol->IsAlias() )
796  {
797  std::shared_ptr< LIB_SYMBOL > oldParent = symbol->GetParent().lock();
798 
799  wxCHECK_MSG( oldParent, buf,
800  wxString::Format( "Derived symbol '%s' found with undefined parent.",
801  symbol->GetName() ) );
802 
803  LIB_SYMBOL* libParent = buf.GetSymbol( oldParent->GetName() );
804 
805  if( !libParent )
806  {
807  libParent = new LIB_SYMBOL( *oldParent.get() );
808  buf.CreateBuffer( libParent, new SCH_SCREEN );
809  }
810 
811  newSymbol = new LIB_SYMBOL( *symbol );
812  newSymbol->SetParent( libParent );
813  buf.CreateBuffer( newSymbol, new SCH_SCREEN );
814  }
815  else if( !buf.GetSymbol( symbol->GetName() ) )
816  {
817  buf.CreateBuffer( new LIB_SYMBOL( *symbol ), new SCH_SCREEN );
818  }
819  }
820 
821  return buf;
822 }
823 
824 
826  std::unique_ptr<SCH_SCREEN> aScreen ) :
827  m_screen( std::move( aScreen ) ),
828  m_symbol( aSymbol )
829 {
830  m_original = new LIB_SYMBOL( *aSymbol );
831 }
832 
833 
835 {
836  delete m_symbol;
837  delete m_original;
838 }
839 
840 
842 {
843  wxCHECK( m_symbol != aSymbol, /* void */ );
844  wxASSERT( aSymbol );
845  delete m_symbol;
846  m_symbol = aSymbol;
847 
848  // If the symbol moves libraries then the original moves with it
849  if( m_original->GetLibId().GetLibNickname() != m_symbol->GetLibId().GetLibNickname() )
850  {
851  m_original->SetLibId( LIB_ID( m_symbol->GetLibId().GetLibNickname(),
852  m_original->GetLibId().GetLibItemName() ) );
853  }
854 }
855 
856 
858 {
859  wxCHECK( m_original != aSymbol, /* void */ );
860  wxASSERT( aSymbol );
861  delete m_original;
862  m_original = aSymbol;
863 
864  // The original is not allowed to have a different library than its symbol
865  if( m_original->GetLibId().GetLibNickname() != m_symbol->GetLibId().GetLibNickname() )
866  {
867  m_original->SetLibId( LIB_ID( m_symbol->GetLibId().GetLibNickname(),
868  m_original->GetLibId().GetLibItemName() ) );
869  }
870 }
871 
872 
874 {
875  return m_screen && m_screen->IsContentModified();
876 }
877 
878 
880 {
881  auto buf = GetBuffer( aAlias );
882 
883  if( !buf )
884  return nullptr;
885 
886  LIB_SYMBOL* symbol = buf->GetSymbol();
887 
888  wxCHECK( symbol, nullptr );
889 
890  return symbol;
891 }
892 
893 
895 {
896  wxASSERT( aCopy );
897  wxASSERT( aCopy->GetLib() == nullptr );
898  std::unique_ptr<SCH_SCREEN> screen( aScreen );
899  auto symbolBuf = std::make_shared<SYMBOL_BUFFER>( aCopy, std::move( screen ) );
900  m_symbols.push_back( symbolBuf );
901 
902  // Set the parent library name,
903  // otherwise it is empty as no library has been given as the owner during object construction
904  LIB_ID libId = aCopy->GetLibId();
905  libId.SetLibNickname( m_libName );
906  aCopy->SetLibId( libId );
907  ++m_hash;
908 
909  return true;
910 }
911 
912 
913 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::UpdateBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf,
914  LIB_SYMBOL* aCopy )
915 {
916  wxCHECK( aCopy && aSymbolBuf, false );
917 
918  LIB_SYMBOL* bufferedSymbol = aSymbolBuf->GetSymbol();
919 
920  wxCHECK( bufferedSymbol, false );
921 
922  *bufferedSymbol = *aCopy;
923  ++m_hash;
924 
925  return true;
926 }
927 
928 
929 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::DeleteBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf )
930 {
931  auto symbolBufIt = std::find( m_symbols.begin(), m_symbols.end(), aSymbolBuf );
932  wxCHECK( symbolBufIt != m_symbols.end(), false );
933 
934  bool retv = true;
935 
936  // Remove all derived symbols to prevent broken inheritance.
937  if( aSymbolBuf->GetSymbol()->IsRoot() && HasDerivedSymbols( aSymbolBuf->GetSymbol()->GetName() )
938  && removeChildSymbols( aSymbolBuf ) == 0 )
939  {
940  retv = false;
941  }
942 
943  m_deleted.emplace_back( *symbolBufIt );
944  m_symbols.erase( symbolBufIt );
945  ++m_hash;
946 
947  return retv;
948 }
949 
950 
951 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::SaveBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf,
952  SYMBOL_LIB_TABLE* aLibTable )
953 {
954  wxCHECK( aSymbolBuf, false );
955  LIB_SYMBOL* libSymbol = aSymbolBuf->GetSymbol();
956  LIB_SYMBOL* originalSymbol = aSymbolBuf->GetOriginal();
957  wxCHECK( libSymbol && originalSymbol, false );
959  PROPERTIES properties;
960  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
961 
962  // Delete the original symbol if the symbol name has been changed.
963  if( libSymbol->GetName() != originalSymbol->GetName() )
964  {
965  if( aLibTable->LoadSymbol( m_libName, originalSymbol->GetName() ) )
966  aLibTable->DeleteSymbol( m_libName, originalSymbol->GetName() );
967  }
968 
969  if( libSymbol->IsAlias() )
970  {
971  LIB_SYMBOL* newCachedSymbol = new LIB_SYMBOL( *libSymbol );
972  std::shared_ptr< LIB_SYMBOL > bufferedParent = libSymbol->GetParent().lock();
973 
974  wxCHECK( bufferedParent, false );
975 
976  LIB_SYMBOL* cachedParent = aLibTable->LoadSymbol( m_libName, bufferedParent->GetName() );
977 
978  if( !cachedParent )
979  {
980  cachedParent = new LIB_SYMBOL( *bufferedParent.get() );
981  newCachedSymbol->SetParent( cachedParent );
982  result = aLibTable->SaveSymbol( m_libName, cachedParent );
983  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
984  result = aLibTable->SaveSymbol( m_libName, newCachedSymbol );
985  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
986 
987  LIB_SYMBOL* originalParent = new LIB_SYMBOL( *bufferedParent.get() );
988  aSymbolBuf->SetOriginal( originalParent );
989  originalSymbol = new LIB_SYMBOL( *libSymbol );
990  originalSymbol->SetParent( originalParent );
991  aSymbolBuf->SetOriginal( originalSymbol );
992  }
993  else
994  {
995  newCachedSymbol->SetParent( cachedParent );
996  result = aLibTable->SaveSymbol( m_libName, newCachedSymbol );
997  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
998 
999  auto originalBufferedParent = GetBuffer( bufferedParent->GetName() );
1000  wxCHECK( originalBufferedParent, false );
1001  originalSymbol = new LIB_SYMBOL( *libSymbol );
1002  originalSymbol->SetParent( originalBufferedParent->GetSymbol() );
1003  aSymbolBuf->SetOriginal( originalSymbol );
1004  }
1005  }
1006  else
1007  {
1008  wxArrayString derivedSymbols;
1009 
1010  if( GetDerivedSymbolNames( libSymbol->GetName(), derivedSymbols ) == 0 )
1011  {
1012  result = aLibTable->SaveSymbol( m_libName, new LIB_SYMBOL( *libSymbol ) );
1013  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1014  aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1015  }
1016  else
1017  {
1018  LIB_SYMBOL* parentSymbol = new LIB_SYMBOL( *libSymbol );
1019 
1020  aLibTable->SaveSymbol( m_libName, parentSymbol );
1021 
1022  for( auto entry : derivedSymbols )
1023  {
1024  std::shared_ptr<SYMBOL_BUFFER> symbol = GetBuffer( entry );
1025  LIB_SYMBOL* derivedSymbol = new LIB_SYMBOL( *symbol->GetSymbol() );
1026  derivedSymbol->SetParent( parentSymbol );
1027  result = aLibTable->SaveSymbol( m_libName, derivedSymbol );
1028  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1029  }
1030  }
1031  }
1032 
1033  ++m_hash;
1034  return true;
1035 }
1036 
1037 
1038 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::SaveBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf,
1039  const wxString& aFileName,
1040  SCH_PLUGIN* aPlugin, bool aBuffer )
1041 {
1042  wxCHECK( aSymbolBuf, false );
1043  LIB_SYMBOL* libSymbol = aSymbolBuf->GetSymbol();
1044  LIB_SYMBOL* originalSymbol = aSymbolBuf->GetOriginal();
1045  wxCHECK( libSymbol && originalSymbol, false );
1046  wxCHECK( !aFileName.IsEmpty(), false );
1047 
1048  wxString errorMsg = _( "Error saving symbol %s to library '%s'." ) + wxS( "\n%s" );
1049 
1050  // set properties to prevent save file on every symbol save
1051  PROPERTIES properties;
1052  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
1053 
1054  // Delete the original symbol if the symbol name has been changed.
1055  if( libSymbol->GetName() != originalSymbol->GetName() )
1056  {
1057  if( aPlugin->LoadSymbol( aFileName, originalSymbol->GetName() ) )
1058  aPlugin->DeleteSymbol( aFileName, originalSymbol->GetName(), &properties );
1059  }
1060 
1061  if( libSymbol->IsAlias() )
1062  {
1063  LIB_SYMBOL* newCachedSymbol = new LIB_SYMBOL( *libSymbol );
1064  std::shared_ptr< LIB_SYMBOL > bufferedParent = libSymbol->GetParent().lock();
1065 
1066  wxCHECK( bufferedParent, false );
1067 
1068  LIB_SYMBOL* cachedParent = nullptr;
1069 
1070  try
1071  {
1072  cachedParent = aPlugin->LoadSymbol( aFileName, bufferedParent->GetName() );
1073  }
1074  catch( const IO_ERROR& )
1075  {
1076  return false;
1077  }
1078 
1079  if( !cachedParent )
1080  {
1081  cachedParent = new LIB_SYMBOL( *bufferedParent.get() );
1082  newCachedSymbol->SetParent( cachedParent );
1083 
1084  try
1085  {
1086  aPlugin->SaveSymbol( aFileName, cachedParent, aBuffer ? &properties : nullptr );
1087  }
1088  catch( const IO_ERROR& ioe )
1089  {
1090  wxLogError( errorMsg, UnescapeString( cachedParent->GetName() ), aFileName,
1091  ioe.What() );
1092  return false;
1093  }
1094 
1095  try
1096  {
1097  aPlugin->SaveSymbol( aFileName, newCachedSymbol, aBuffer ? &properties : nullptr );
1098  }
1099  catch( const IO_ERROR& ioe )
1100  {
1101  wxLogError( errorMsg, UnescapeString( newCachedSymbol->GetName() ), aFileName,
1102  ioe.What() );
1103  return false;
1104  }
1105 
1106  LIB_SYMBOL* originalParent = new LIB_SYMBOL( *bufferedParent.get() );
1107  aSymbolBuf->SetOriginal( originalParent );
1108  originalSymbol = new LIB_SYMBOL( *libSymbol );
1109  originalSymbol->SetParent( originalParent );
1110  aSymbolBuf->SetOriginal( originalSymbol );
1111  }
1112  else
1113  {
1114  newCachedSymbol->SetParent( cachedParent );
1115 
1116  try
1117  {
1118  aPlugin->SaveSymbol( aFileName, newCachedSymbol, aBuffer ? &properties : nullptr );
1119  }
1120  catch( const IO_ERROR& ioe )
1121  {
1122  wxLogError( errorMsg, UnescapeString( newCachedSymbol->GetName() ), aFileName,
1123  ioe.What() );
1124  return false;
1125  }
1126 
1127  auto originalBufferedParent = GetBuffer( bufferedParent->GetName() );
1128  wxCHECK( originalBufferedParent, false );
1129  originalSymbol = new LIB_SYMBOL( *libSymbol );
1130  originalSymbol->SetParent( originalBufferedParent->GetSymbol() );
1131  aSymbolBuf->SetOriginal( originalSymbol );
1132  }
1133  }
1134  else
1135  {
1136  wxArrayString derivedSymbols;
1137 
1138  if( GetDerivedSymbolNames( libSymbol->GetName(), derivedSymbols ) == 0 )
1139  {
1140  try
1141  {
1142  aPlugin->SaveSymbol( aFileName, new LIB_SYMBOL( *libSymbol ),
1143  aBuffer ? &properties : nullptr );
1144  }
1145  catch( const IO_ERROR& ioe )
1146  {
1147  wxLogError( errorMsg, UnescapeString( libSymbol->GetName() ), aFileName,
1148  ioe.What() );
1149  return false;
1150  }
1151 
1152  aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1153  }
1154  else
1155  {
1156  LIB_SYMBOL* parentSymbol = new LIB_SYMBOL( *libSymbol );
1157 
1158  // Save the modified root symbol.
1159  try
1160  {
1161  aPlugin->SaveSymbol( aFileName, parentSymbol, aBuffer ? &properties : nullptr );
1162  }
1163  catch( const IO_ERROR& ioe )
1164  {
1165  wxLogError( errorMsg, UnescapeString( libSymbol->GetName() ), aFileName,
1166  ioe.What() );
1167  return false;
1168  }
1169 
1170  aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1171 
1172  // Save the derived symbols.
1173  for( auto entry : derivedSymbols )
1174  {
1175  std::shared_ptr<SYMBOL_BUFFER> symbol = GetBuffer( entry );
1176  LIB_SYMBOL* derivedSymbol = new LIB_SYMBOL( *symbol->GetSymbol() );
1177  derivedSymbol->SetParent( parentSymbol );
1178 
1179  try
1180  {
1181  aPlugin->SaveSymbol( aFileName, new LIB_SYMBOL( *derivedSymbol ),
1182  aBuffer ? &properties : nullptr );
1183  }
1184  catch( const IO_ERROR& ioe )
1185  {
1186  wxLogError( errorMsg, UnescapeString( derivedSymbol->GetName() ), aFileName,
1187  ioe.What() );
1188  return false;
1189  }
1190  }
1191  }
1192  }
1193 
1194  ++m_hash;
1195  return true;
1196 }
1197 
1198 
1199 std::shared_ptr<SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER>
1200 SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::GetBuffer( const wxString& aAlias ) const
1201 {
1202  for( auto entry : m_symbols )
1203  {
1204  if( entry->GetSymbol()->GetName() == aAlias )
1205  return entry;
1206  }
1207 
1208  return std::shared_ptr<SYMBOL_BUFFER>( nullptr );
1209 }
1210 
1211 
1212 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::HasDerivedSymbols( const wxString& aParentName ) const
1213 {
1214  for( auto entry : m_symbols )
1215  {
1216  if( entry->GetSymbol()->IsAlias() )
1217  {
1218  LIB_SYMBOL_SPTR parent = entry->GetSymbol()->GetParent().lock();
1219 
1220  // Check for inherited symbol without a valid parent.
1221  wxCHECK( parent, false );
1222 
1223  if( parent->GetName() == aParentName )
1224  return true;
1225  }
1226  }
1227 
1228  return false;
1229 }
1230 
1231 
1232 void SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::GetRootSymbolNames( wxArrayString& aRootSymbolNames )
1233 {
1234  for( auto entry : m_symbols )
1235  {
1236  if( entry->GetSymbol()->IsAlias() )
1237  continue;
1238 
1239  aRootSymbolNames.Add( UnescapeString( entry->GetSymbol()->GetName() ) );
1240  }
1241 }
1242 
1243 
1245  wxArrayString& aList )
1246 {
1247  wxCHECK( !aSymbolName.IsEmpty(), 0 );
1248 
1249  for( auto entry : m_symbols )
1250  {
1251  if( entry->GetSymbol()->IsAlias() )
1252  {
1253  LIB_SYMBOL_SPTR parent = entry->GetSymbol()->GetParent().lock();
1254 
1255  // Check for inherited symbol without a valid parent.
1256  wxCHECK( parent, false );
1257 
1258  if( parent->GetName() == aSymbolName )
1259  aList.Add( entry->GetSymbol()->GetName() );
1260  }
1261  }
1262 
1263  return aList.GetCount();
1264 }
1265 
1266 
1267 int SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::removeChildSymbols( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf )
1268 {
1269  wxCHECK( aSymbolBuf && aSymbolBuf->GetSymbol()->IsRoot(), 0 );
1270 
1271  int cnt = 0;
1272  std::deque< std::shared_ptr<SYMBOL_BUFFER> >::iterator it = m_symbols.begin();
1273 
1274  while( it != m_symbols.end() )
1275  {
1276 
1277  if( (*it)->GetSymbol()->IsRoot() )
1278  {
1279  ++it;
1280  }
1281  else
1282  {
1283  LIB_SYMBOL_SPTR parent = (*it)->GetSymbol()->GetParent().lock();
1284 
1285  wxCHECK2( parent, ++it; continue );
1286 
1287  if( parent->GetName() == aSymbolBuf->GetSymbol()->GetName() )
1288  {
1289  wxCHECK2( parent == aSymbolBuf->GetSymbol()->SharedPtr(), ++it; continue );
1290 
1291  m_deleted.emplace_back( *it );
1292  it = m_symbols.erase( it );
1293  cnt++;
1294  }
1295  else
1296  {
1297  ++it;
1298  }
1299  }
1300  }
1301 
1302  return cnt;
1303 }
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:356
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.