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>
39 #include <list>
40 #include <locale_io.h>
41 #include <wx/log.h>
42 #include "lib_logger.h"
43 
44 
46  m_frame( aFrame ),
47  m_syncHash( 0 )
48 {
50  m_adapter->ShowUnits( false );
51  m_logger = new LIB_LOGGER();
52 }
53 
54 
56 {
57  delete m_logger;
58 }
59 
60 
61 void SYMBOL_LIBRARY_MANAGER::Sync( const wxString& aForceRefresh,
62  std::function<void( int, int,
63  const wxString& )> aProgressCallback )
64 {
65  m_logger->Activate();
66  {
67  getAdapter()->Sync( aForceRefresh, aProgressCallback );
69  }
71 }
72 
73 
75 {
76  const int progressIntervalMillis = 60;
77 
78  SYMBOL_ASYNC_LOADER loader( symTable()->GetLogicalLibs(), symTable(), false, nullptr,
79  &aReporter );
80 
81  LOCALE_IO toggle;
82 
83  loader.Start();
84 
85  while( !loader.Done() )
86  {
87  aReporter.KeepRefreshing();
88 
89  wxMilliSleep( progressIntervalMillis );
90  }
91 
92  if( aReporter.IsCancelled() )
93  {
94  loader.Abort();
95  }
96  else
97  {
98  loader.Join();
99  }
100 
101  if( !loader.GetErrors().IsEmpty() )
102  {
103  HTML_MESSAGE_BOX dlg( &m_frame, _( "Load Error" ) );
104 
105  dlg.MessageSet( _( "Errors were encountered loading symbols:" ) );
106 
107  wxString msg = loader.GetErrors();
108  msg.Replace( "\n", "<BR>" );
109 
110  dlg.AddHTML_Text( msg );
111  dlg.ShowModal();
112  }
113 }
114 
115 
117 {
118  for( const auto& lib : m_libs )
119  {
120  if( lib.second.IsModified() )
121  return true;
122  }
123 
124  return false;
125 }
126 
127 
129 {
130  int hash = symTable()->GetModifyHash();
131 
132  for( const auto& lib : m_libs )
133  hash += lib.second.GetHash();
134 
135  return hash;
136 }
137 
138 
139 int SYMBOL_LIBRARY_MANAGER::GetLibraryHash( const wxString& aLibrary ) const
140 {
141  const auto libBufIt = m_libs.find( aLibrary );
142 
143  if( libBufIt != m_libs.end() )
144  return libBufIt->second.GetHash();
145 
146  auto row = GetLibrary( aLibrary );
147 
148  // return -1 if library does not exist or 0 if not modified
149  return row ? std::hash<std::string>{}( aLibrary.ToStdString() +
150  row->GetFullURI( true ).ToStdString() ) : -1;
151 }
152 
153 
155 {
156  wxArrayString res;
157 
158  for( const auto& libName : symTable()->GetLogicalLibs() )
159  res.Add( libName );
160 
161  return res;
162 }
163 
164 
166 {
167  SYMBOL_LIB_TABLE_ROW* row = nullptr;
168 
169  try
170  {
171  row = symTable()->FindRow( aLibrary, true );
172  }
173  catch( const IO_ERROR& e )
174  {
175  wxLogMessage( _( "Cannot find library \"%s\" in the Symbol Library Table (%s)" ),
176  aLibrary, e.What() );
177  }
178 
179  return row;
180 }
181 
182 
183 bool SYMBOL_LIBRARY_MANAGER::SaveLibrary( const wxString& aLibrary, const wxString& aFileName,
184  SCH_IO_MGR::SCH_FILE_T aFileType )
185 {
186  wxCHECK( aFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY && LibraryExists( aLibrary ), false );
187  wxFileName fn( aFileName );
188  wxCHECK( !fn.FileExists() || fn.IsFileWritable(), false );
189  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( aFileType ) );
190  bool res = true; // assume all libraries are successfully saved
191 
192  PROPERTIES properties;
193  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
194 
195  auto it = m_libs.find( aLibrary );
196 
197  if( it != m_libs.end() )
198  {
199  // Handle buffered library
200  LIB_BUFFER& libBuf = it->second;
201 
202  const auto& symbolBuffers = libBuf.GetBuffers();
203 
204  for( const auto& symbolBuf : symbolBuffers )
205  {
206  if( !libBuf.SaveBuffer( symbolBuf, aFileName, &*pi, true ) )
207  {
208  // Something went wrong, but try to save other libraries
209  res = false;
210  }
211  }
212 
213  // clear the deleted symbols buffer only if data is saved to the original file
214  wxFileName original, destination( aFileName );
215  auto row = GetLibrary( aLibrary );
216 
217  if( row )
218  {
219  original = row->GetFullURI( true );
220  original.Normalize();
221  }
222 
223  destination.Normalize();
224 
225  if( res && original == destination )
226  libBuf.ClearDeletedBuffer();
227  }
228  else
229  {
230  // Handle original library
231  for( LIB_SYMBOL* symbol : getOriginalSymbols( aLibrary ) )
232  {
233  LIB_SYMBOL* newSymbol;
234 
235  if( symbol->IsAlias() )
236  {
237  std::shared_ptr< LIB_SYMBOL > oldParent = symbol->GetParent().lock();
238 
239  wxCHECK_MSG( oldParent, false,
240  wxString::Format( "Derived symbol '%s' found with undefined parent.",
241  symbol->GetName() ) );
242 
243  LIB_SYMBOL* libParent = pi->LoadSymbol( aLibrary, oldParent->GetName(),
244  &properties );
245 
246  if( !libParent )
247  {
248  libParent = new LIB_SYMBOL( *oldParent.get() );
249  pi->SaveSymbol( aLibrary, libParent, &properties );
250  }
251 
252  newSymbol = new LIB_SYMBOL( *symbol );
253  newSymbol->SetParent( libParent );
254  pi->SaveSymbol( aLibrary, newSymbol, &properties );
255  }
256  else if( !pi->LoadSymbol( aLibrary, symbol->GetName(), &properties ) )
257  {
258  pi->SaveSymbol( aLibrary, new LIB_SYMBOL( *symbol ), &properties );
259  }
260  }
261  }
262 
263  try
264  {
265  pi->SaveLibrary( aFileName );
266  }
267  catch( ... )
268  {
269  // return false because something happens.
270  // The library is not successfully saved
271  res = false;
272  }
273 
274  return res;
275 }
276 
277 
278 bool SYMBOL_LIBRARY_MANAGER::IsLibraryModified( const wxString& aLibrary ) const
279 {
280  auto it = m_libs.find( aLibrary );
281  return it != m_libs.end() ? it->second.IsModified() : false;
282 }
283 
284 
285 bool SYMBOL_LIBRARY_MANAGER::IsSymbolModified( const wxString& aAlias,
286  const wxString& aLibrary ) const
287 {
288  auto libIt = m_libs.find( aLibrary );
289 
290  if( libIt == m_libs.end() )
291  return false;
292 
293  const LIB_BUFFER& buf = libIt->second;
294  auto symbolBuf = buf.GetBuffer( aAlias );
295  return symbolBuf ? symbolBuf->IsModified() : false;
296 }
297 
298 
299 bool SYMBOL_LIBRARY_MANAGER::ClearLibraryModified( const wxString& aLibrary ) const
300 {
301  auto libIt = m_libs.find( aLibrary );
302 
303  if( libIt == m_libs.end() )
304  return false;
305 
306  for( auto& symbolBuf : libIt->second.GetBuffers() )
307  {
308  SCH_SCREEN* screen = symbolBuf->GetScreen();
309 
310  if( screen )
311  screen->SetContentModified( false );
312  }
313 
314  return true;
315 }
316 
317 
318 bool SYMBOL_LIBRARY_MANAGER::ClearSymbolModified( const wxString& aAlias,
319  const wxString& aLibrary ) const
320 {
321  auto libI = m_libs.find( aLibrary );
322 
323  if( libI == m_libs.end() )
324  return false;
325 
326  auto symbolBuf = libI->second.GetBuffer( aAlias );
327  wxCHECK( symbolBuf, false );
328 
329  symbolBuf->GetScreen()->SetContentModified( false );
330  return true;
331 }
332 
333 
334 bool SYMBOL_LIBRARY_MANAGER::IsLibraryReadOnly( const wxString& aLibrary ) const
335 {
336  wxCHECK( LibraryExists( aLibrary ), true );
337 
338  return !symTable()->IsSymbolLibWritable( aLibrary );
339 }
340 
341 
342 bool SYMBOL_LIBRARY_MANAGER::IsLibraryLoaded( const wxString& aLibrary ) const
343 {
344  wxCHECK( LibraryExists( aLibrary ), false );
345 
346  return symTable()->IsSymbolLibLoaded( aLibrary );
347 }
348 
349 
350 std::list<LIB_SYMBOL*> SYMBOL_LIBRARY_MANAGER::GetAliases( const wxString& aLibrary ) const
351 {
352  std::list<LIB_SYMBOL*> ret;
353  wxCHECK( LibraryExists( aLibrary ), ret );
354 
355  auto libIt = m_libs.find( aLibrary );
356 
357  if( libIt != m_libs.end() )
358  {
359  for( auto& symbolBuf : libIt->second.GetBuffers() )
360  {
361  ret.push_back( symbolBuf->GetSymbol() );
362  }
363  }
364  else
365  {
366  std::vector<LIB_SYMBOL*> aliases;
367 
368  try
369  {
370  symTable()->LoadSymbolLib( aliases, aLibrary );
371  }
372  catch( const IO_ERROR& e )
373  {
374  wxLogWarning( e.Problem() );
375  }
376 
377  std::copy( aliases.begin(), aliases.end(), std::back_inserter( ret ) );
378  }
379 
380  return ret;
381 }
382 
383 
385  const wxString& aLibrary )
386 {
387  wxCHECK( LibraryExists( aLibrary ), nullptr );
388 
389  // try the library buffers first
390  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
391  LIB_SYMBOL* bufferedSymbol = libBuf.GetSymbol( aAlias );
392 
393  if( !bufferedSymbol ) // no buffer symbol found
394  {
395  // create a copy of the symbol
396  try
397  {
398  LIB_SYMBOL* symbol = symTable()->LoadSymbol( aLibrary, aAlias );
399 
400  if( symbol == nullptr )
401  THROW_IO_ERROR( _( "Symbol not found." ) );
402 
403  LIB_SYMBOL* bufferedParent = nullptr;
404 
405  // Create parent symbols on demand so parent symbol can be set.
406  if( symbol->IsAlias() )
407  {
408  std::shared_ptr< LIB_SYMBOL > parent = symbol->GetParent().lock();
409  wxCHECK_MSG( parent, nullptr,
410  wxString::Format( "Derived symbol '%s' found with undefined parent.",
411  symbol->GetName() ) );
412 
413  // Check if the parent symbol buffer has already be created.
414  bufferedParent = libBuf.GetSymbol( parent->GetName() );
415 
416  if( !bufferedParent )
417  {
418  bufferedParent = new LIB_SYMBOL( *parent.get() );
419  libBuf.CreateBuffer( bufferedParent, new SCH_SCREEN );
420  }
421  }
422 
423  bufferedSymbol = new LIB_SYMBOL( *symbol );
424 
425  if( bufferedParent )
426  bufferedSymbol->SetParent( bufferedParent );
427 
428  libBuf.CreateBuffer( bufferedSymbol, new SCH_SCREEN );
429  }
430  catch( const IO_ERROR& e )
431  {
432  wxLogMessage( _( "Error loading symbol \"%s\" from library \"%s\". (%s)" ),
433  aAlias, aLibrary, e.What() );
434  bufferedSymbol = nullptr;
435  }
436  }
437 
438  return bufferedSymbol;
439 }
440 
441 
442 SCH_SCREEN* SYMBOL_LIBRARY_MANAGER::GetScreen( const wxString& aAlias, const wxString& aLibrary )
443 {
444  wxCHECK( LibraryExists( aLibrary ), nullptr );
445  wxCHECK( !aAlias.IsEmpty(), nullptr );
446  auto it = m_libs.find( aLibrary );
447  wxCHECK( it != m_libs.end(), nullptr );
448 
449  LIB_BUFFER& buf = it->second;
450  auto symbolBuf = buf.GetBuffer( aAlias );
451  return symbolBuf ? symbolBuf->GetScreen() : nullptr;
452 }
453 
454 
455 bool SYMBOL_LIBRARY_MANAGER::UpdateSymbol( LIB_SYMBOL* aSymbol, const wxString& aLibrary )
456 {
457  wxCHECK( LibraryExists( aLibrary ), false );
458  wxCHECK( aSymbol, false );
459  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
460  auto symbolBuf = libBuf.GetBuffer( aSymbol->GetName() );
461 
462  if( symbolBuf ) // Existing symbol.
463  {
464  LIB_SYMBOL* bufferedSymbol = const_cast< LIB_SYMBOL* >( symbolBuf->GetSymbol() );
465 
466  wxCHECK( bufferedSymbol, false );
467 
468  *bufferedSymbol = *aSymbol;
469  symbolBuf->GetScreen()->SetContentModified();
470  }
471  else // New symbol
472  {
473  LIB_SYMBOL* symbolCopy = new LIB_SYMBOL( *aSymbol, nullptr );
474 
475  symbolCopy->SetLibId( LIB_ID( aLibrary, aSymbol->GetLibId().GetLibItemName() ) );
476 
477  SCH_SCREEN* screen = new SCH_SCREEN;
478  libBuf.CreateBuffer( symbolCopy, screen );
479  screen->SetContentModified();
480  }
481 
482  return true;
483 }
484 
485 
486 bool SYMBOL_LIBRARY_MANAGER::UpdateSymbolAfterRename( LIB_SYMBOL* aSymbol, const wxString& aOldName,
487  const wxString& aLibrary )
488 {
489  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
490  auto symbolBuf = libBuf.GetBuffer( aOldName );
491 
492  wxCHECK( symbolBuf, false );
493 
494  libBuf.UpdateBuffer( symbolBuf, aSymbol );
495  m_frame.SyncLibraries( false );
496 
497  return true;
498 }
499 
500 
501 bool SYMBOL_LIBRARY_MANAGER::FlushSymbol( const wxString& aAlias, const wxString& aLibrary )
502 {
503  auto it = m_libs.find( aLibrary );
504 
505  if( it == m_libs.end() ) // no items to flush
506  return true;
507 
508  auto symbolBuf = it->second.GetBuffer( aAlias );
509  wxCHECK( symbolBuf, false );
510 
511  return it->second.SaveBuffer( symbolBuf, symTable() );
512 }
513 
514 
515 LIB_ID SYMBOL_LIBRARY_MANAGER::RevertSymbol( const wxString& aAlias, const wxString& aLibrary )
516 {
517  auto it = m_libs.find( aLibrary );
518 
519  if( it == m_libs.end() ) // no items to flush
520  return LIB_ID( aLibrary, aAlias );
521 
522  auto symbolBuf = it->second.GetBuffer( aAlias );
523  wxCHECK( symbolBuf, LIB_ID( aLibrary, aAlias ) );
524  LIB_SYMBOL original( *symbolBuf->GetOriginal() );
525 
526  if( original.GetName() != aAlias )
527  {
528  UpdateSymbolAfterRename( &original, aAlias, aLibrary );
529  }
530  else
531  {
532  symbolBuf->SetSymbol( new LIB_SYMBOL( original ) );
533  m_frame.SyncLibraries( false );
534  }
535 
536  return LIB_ID( aLibrary, original.GetName() );
537 }
538 
539 
540 bool SYMBOL_LIBRARY_MANAGER::RevertLibrary( const wxString& aLibrary )
541 {
542  auto it = m_libs.find( aLibrary );
543 
544  if( it == m_libs.end() ) // nothing to reverse
545  return false;
546 
547  m_libs.erase( it );
548  m_frame.SyncLibraries( false );
549 
550  return true;
551 }
552 
553 
555 {
556  bool retv = true;
557 
558  // Nothing to revert.
559  if( GetHash() == 0 )
560  return true;
561 
562  for( const auto& lib : m_libs )
563  {
564  if( !lib.second.IsModified() )
565  continue;
566 
567  for( const auto& buffer : lib.second.GetBuffers() )
568  {
569  if( !buffer->IsModified() )
570  continue;
571 
572  RevertSymbol( lib.first, buffer->GetOriginal()->GetName() );
573  }
574  }
575 
576  return retv;
577 }
578 
579 
580 bool SYMBOL_LIBRARY_MANAGER::RemoveSymbol( const wxString& aAlias, const wxString& aLibrary )
581 {
582  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
583  auto symbolBuf = libBuf.GetBuffer( aAlias );
584  wxCHECK( symbolBuf, false );
585 
586  bool retv = true;
587 
588  retv &= libBuf.DeleteBuffer( symbolBuf );
589  m_frame.SyncLibraries( false );
590 
591  return retv;
592 }
593 
594 
596  const wxString& aLibrary ) const
597 {
598  // Try the library buffers first
599  auto libIt = m_libs.find( aLibrary );
600 
601  if( libIt != m_libs.end() )
602  {
603  LIB_SYMBOL* symbol = libIt->second.GetSymbol( aAlias );
604 
605  if( symbol )
606  return symbol;
607  }
608 
609  // Get the original symbol
610  LIB_SYMBOL* alias = nullptr;
611 
612  try
613  {
614  alias = symTable()->LoadSymbol( aLibrary, aAlias );
615  }
616  catch( const IO_ERROR& e )
617  {
618  wxLogMessage( _( "Cannot load symbol \"%s\" from library \"%s\" (%s)" ),
619  aAlias, aLibrary, e.What() );
620  }
621 
622  return alias;
623 }
624 
625 
626 bool SYMBOL_LIBRARY_MANAGER::SymbolExists( const wxString& aAlias, const wxString& aLibrary ) const
627 {
628  auto libBufIt = m_libs.find( aLibrary );
629  LIB_SYMBOL* alias = nullptr;
630 
631  if( libBufIt != m_libs.end() )
632  return !!libBufIt->second.GetBuffer( aAlias );
633 
634  try
635  {
636  alias = symTable()->LoadSymbol( aLibrary, aAlias );
637  }
638  catch( IO_ERROR& )
639  {
640  // checking if certain symbol exists, so its absence is perfectly fine
641  }
642 
643  return alias != nullptr;
644 }
645 
646 
647 bool SYMBOL_LIBRARY_MANAGER::LibraryExists( const wxString& aLibrary, bool aCheckEnabled ) const
648 {
649  if( aLibrary.IsEmpty() )
650  return false;
651 
652  if( m_libs.count( aLibrary ) > 0 )
653  return true;
654 
655  return symTable()->HasLibrary( aLibrary, aCheckEnabled );
656 }
657 
658 
660 {
661  wxString name = "New_Library";
662 
663  if( !LibraryExists( name ) )
664  return name;
665 
666  name += "_";
667 
668  for( unsigned int i = 0; i < std::numeric_limits<unsigned int>::max(); ++i )
669  {
670  if( !LibraryExists( name + wxString::Format( "%u", i ) ) )
671  return name + wxString::Format( "%u", i );
672  }
673 
674  wxFAIL;
675  return wxEmptyString;
676 }
677 
678 
679 void SYMBOL_LIBRARY_MANAGER::GetRootSymbolNames( const wxString& aLibraryName,
680  wxArrayString& aRootSymbolNames )
681 {
682  LIB_BUFFER& libBuf = getLibraryBuffer( aLibraryName );
683 
684  libBuf.GetRootSymbolNames( aRootSymbolNames );
685 }
686 
687 
688 bool SYMBOL_LIBRARY_MANAGER:: HasDerivedSymbols( const wxString& aSymbolName,
689  const wxString& aLibraryName )
690 {
691  LIB_BUFFER& libBuf = getLibraryBuffer( aLibraryName );
692 
693  return libBuf.HasDerivedSymbols( aSymbolName );
694 }
695 
696 
698 {
699  return symTable()->GetLogicalLibs().size();
700 }
701 
702 
703 wxString SYMBOL_LIBRARY_MANAGER::getLibraryName( const wxString& aFilePath )
704 {
705  wxFileName fn( aFilePath );
706  return fn.GetName();
707 }
708 
709 
710 bool SYMBOL_LIBRARY_MANAGER::addLibrary( const wxString& aFilePath, bool aCreate,
711  SYMBOL_LIB_TABLE* aTable )
712 {
713  wxCHECK( aTable, false );
714  wxString libName = getLibraryName( aFilePath );
715  wxCHECK( !LibraryExists( libName ), false ); // either create or add an existing one
716 
717  // try to use path normalized to an environmental variable or project path
718  wxString relPath = NormalizePath( aFilePath, &Pgm().GetLocalEnvVariables(), &m_frame.Prj() );
719 
720  if( relPath.IsEmpty() )
721  relPath = aFilePath;
722 
723  SCH_IO_MGR::SCH_FILE_T schFileType = SCH_IO_MGR::GuessPluginTypeFromLibPath( aFilePath );
724  wxString typeName = SCH_IO_MGR::ShowType( schFileType );
725  SYMBOL_LIB_TABLE_ROW* libRow = new SYMBOL_LIB_TABLE_ROW( libName, relPath, typeName );
726  aTable->InsertRow( libRow );
727 
728  if( aCreate )
729  {
730  wxCHECK( schFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY, false );
731 
732  try
733  {
734  aTable->CreateSymbolLib( libName );
735  }
736  catch( const IO_ERROR& )
737  {
738  aTable->RemoveRow( libRow );
739  return false;
740  }
741  }
742 
743  m_frame.SyncLibraries( false );
744 
745  return true;
746 }
747 
748 
750 {
751  return m_frame.Prj().SchSymbolLibTable();
752 }
753 
754 
755 std::set<LIB_SYMBOL*> SYMBOL_LIBRARY_MANAGER::getOriginalSymbols( const wxString& aLibrary )
756 {
757  std::set<LIB_SYMBOL*> symbols;
758  wxCHECK( LibraryExists( aLibrary ), symbols );
759 
760  try
761  {
762  wxArrayString aliases;
763  symTable()->EnumerateSymbolLib( aLibrary, aliases );
764 
765  for( const auto& aliasName : aliases )
766  {
767  LIB_SYMBOL* alias = symTable()->LoadSymbol( aLibrary, aliasName );
768  symbols.insert( alias );
769  }
770  }
771  catch( const IO_ERROR& e )
772  {
773  wxLogMessage( _( "Cannot enumerate library \"%s\" (%s)" ), aLibrary, e.What() );
774  }
775 
776  return symbols;
777 }
778 
779 
781  const wxString& aLibrary )
782 {
783  auto it = m_libs.find( aLibrary );
784 
785  if( it != m_libs.end() )
786  return it->second;
787 
788  // The requested buffer does not exist yet, so create one
789  auto ret = m_libs.emplace( aLibrary, LIB_BUFFER( aLibrary ) );
790  LIB_BUFFER& buf = ret.first->second;
791 
792  for( auto symbol : getOriginalSymbols( aLibrary ) )
793  {
794  LIB_SYMBOL* newSymbol;
795 
796  if( symbol->IsAlias() )
797  {
798  std::shared_ptr< LIB_SYMBOL > oldParent = symbol->GetParent().lock();
799 
800  wxCHECK_MSG( oldParent, buf,
801  wxString::Format( "Derived symbol '%s' found with undefined parent.",
802  symbol->GetName() ) );
803 
804  LIB_SYMBOL* libParent = buf.GetSymbol( oldParent->GetName() );
805 
806  if( !libParent )
807  {
808  libParent = new LIB_SYMBOL( *oldParent.get() );
809  buf.CreateBuffer( libParent, new SCH_SCREEN );
810  }
811 
812  newSymbol = new LIB_SYMBOL( *symbol );
813  newSymbol->SetParent( libParent );
814  buf.CreateBuffer( newSymbol, new SCH_SCREEN );
815  }
816  else if( !buf.GetSymbol( symbol->GetName() ) )
817  {
818  buf.CreateBuffer( new LIB_SYMBOL( *symbol ), new SCH_SCREEN );
819  }
820  }
821 
822  return buf;
823 }
824 
825 
827  std::unique_ptr<SCH_SCREEN> aScreen ) :
828  m_screen( std::move( aScreen ) ),
829  m_symbol( aSymbol )
830 {
831  m_original = new LIB_SYMBOL( *aSymbol );
832 }
833 
834 
836 {
837  delete m_symbol;
838  delete m_original;
839 }
840 
841 
843 {
844  wxCHECK( m_symbol != aSymbol, /* void */ );
845  wxASSERT( aSymbol );
846  delete m_symbol;
847  m_symbol = aSymbol;
848 
849  // If the symbol moves libraries then the original moves with it
850  if( m_original->GetLibId().GetLibNickname() != m_symbol->GetLibId().GetLibNickname() )
851  {
852  m_original->SetLibId( LIB_ID( m_symbol->GetLibId().GetLibNickname(),
853  m_original->GetLibId().GetLibItemName() ) );
854  }
855 }
856 
857 
859 {
860  wxCHECK( m_original != aSymbol, /* void */ );
861  wxASSERT( aSymbol );
862  delete m_original;
863  m_original = aSymbol;
864 
865  // The original is not allowed to have a different library than its symbol
866  if( m_original->GetLibId().GetLibNickname() != m_symbol->GetLibId().GetLibNickname() )
867  {
868  m_original->SetLibId( LIB_ID( m_symbol->GetLibId().GetLibNickname(),
869  m_original->GetLibId().GetLibItemName() ) );
870  }
871 }
872 
873 
875 {
876  return m_screen && m_screen->IsContentModified();
877 }
878 
879 
881 {
882  auto buf = GetBuffer( aAlias );
883 
884  if( !buf )
885  return nullptr;
886 
887  LIB_SYMBOL* symbol = buf->GetSymbol();
888 
889  wxCHECK( symbol, nullptr );
890 
891  return symbol;
892 }
893 
894 
896 {
897  wxASSERT( aCopy );
898  wxASSERT( aCopy->GetLib() == nullptr );
899  std::unique_ptr<SCH_SCREEN> screen( aScreen );
900  auto symbolBuf = std::make_shared<SYMBOL_BUFFER>( aCopy, std::move( screen ) );
901  m_symbols.push_back( symbolBuf );
902 
903  // Set the parent library name,
904  // otherwise it is empty as no library has been given as the owner during object construction
905  LIB_ID libId = aCopy->GetLibId();
906  libId.SetLibNickname( m_libName );
907  aCopy->SetLibId( libId );
908  ++m_hash;
909 
910  return true;
911 }
912 
913 
916 {
917  wxCHECK( aCopy && aSymbolBuf, false );
918 
919  LIB_SYMBOL* bufferedSymbol = aSymbolBuf->GetSymbol();
920 
921  wxCHECK( bufferedSymbol, false );
922 
923  *bufferedSymbol = *aCopy;
924  ++m_hash;
925 
926  return true;
927 }
928 
929 
932 {
933  auto symbolBufIt = std::find( m_symbols.begin(), m_symbols.end(), aSymbolBuf );
934  wxCHECK( symbolBufIt != m_symbols.end(), false );
935 
936  bool retv = true;
937 
938  // Remove all derived symbols to prevent broken inheritance.
939  if( aSymbolBuf->GetSymbol()->IsRoot() && HasDerivedSymbols( aSymbolBuf->GetSymbol()->GetName() )
940  && removeChildSymbols( aSymbolBuf ) == 0 )
941  {
942  retv = false;
943  }
944 
945  m_deleted.emplace_back( *symbolBufIt );
946  m_symbols.erase( symbolBufIt );
947  ++m_hash;
948 
949  return retv;
950 }
951 
952 
955 {
956  wxCHECK( aSymbolBuf, false );
957  LIB_SYMBOL* libSymbol = aSymbolBuf->GetSymbol();
958  LIB_SYMBOL* originalSymbol = aSymbolBuf->GetOriginal();
959  wxCHECK( libSymbol && originalSymbol, false );
961  PROPERTIES properties;
962  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
963 
964  // Delete the original symbol if the symbol name has been changed.
965  if( libSymbol->GetName() != originalSymbol->GetName() )
966  {
967  if( aLibTable->LoadSymbol( m_libName, originalSymbol->GetName() ) )
968  aLibTable->DeleteSymbol( m_libName, originalSymbol->GetName() );
969  }
970 
971  if( libSymbol->IsAlias() )
972  {
973  LIB_SYMBOL* newCachedSymbol = new LIB_SYMBOL( *libSymbol );
974  std::shared_ptr< LIB_SYMBOL > bufferedParent = libSymbol->GetParent().lock();
975 
976  wxCHECK( bufferedParent, false );
977 
978  LIB_SYMBOL* cachedParent = aLibTable->LoadSymbol( m_libName, bufferedParent->GetName() );
979 
980  if( !cachedParent )
981  {
982  cachedParent = new LIB_SYMBOL( *bufferedParent.get() );
983  newCachedSymbol->SetParent( cachedParent );
984  result = aLibTable->SaveSymbol( m_libName, cachedParent );
985  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
986  result = aLibTable->SaveSymbol( m_libName, newCachedSymbol );
987  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
988 
989  LIB_SYMBOL* originalParent = new LIB_SYMBOL( *bufferedParent.get() );
990  aSymbolBuf->SetOriginal( originalParent );
991  originalSymbol = new LIB_SYMBOL( *libSymbol );
992  originalSymbol->SetParent( originalParent );
993  aSymbolBuf->SetOriginal( originalSymbol );
994  }
995  else
996  {
997  newCachedSymbol->SetParent( cachedParent );
998  result = aLibTable->SaveSymbol( m_libName, newCachedSymbol );
999  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1000 
1001  SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER::PTR originalBufferedParent =
1002  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  SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER::PTR 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 
1042  SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER::PTR aSymbolBuf, 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 = _( "An error \"%s\" occurred saving symbol \"%s\" to library \"%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, ioe.What(), cachedParent->GetName() );
1094  return false;
1095  }
1096 
1097  try
1098  {
1099  aPlugin->SaveSymbol( aFileName, newCachedSymbol, aBuffer ? &properties : nullptr );
1100  }
1101  catch( const IO_ERROR& ioe )
1102  {
1103  wxLogError( errorMsg, ioe.What(), newCachedSymbol->GetName() );
1104  return false;
1105  }
1106 
1107  LIB_SYMBOL* originalParent = new LIB_SYMBOL( *bufferedParent.get() );
1108  aSymbolBuf->SetOriginal( originalParent );
1109  originalSymbol = new LIB_SYMBOL( *libSymbol );
1110  originalSymbol->SetParent( originalParent );
1111  aSymbolBuf->SetOriginal( originalSymbol );
1112  }
1113  else
1114  {
1115  newCachedSymbol->SetParent( cachedParent );
1116 
1117  try
1118  {
1119  aPlugin->SaveSymbol( aFileName, newCachedSymbol, aBuffer ? &properties : nullptr );
1120  }
1121  catch( const IO_ERROR& ioe )
1122  {
1123  wxLogError( errorMsg, ioe.What(), newCachedSymbol->GetName() );
1124  return false;
1125  }
1126 
1127  SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER::PTR originalBufferedParent =
1128  GetBuffer( bufferedParent->GetName() );
1129  wxCHECK( originalBufferedParent, false );
1130  originalSymbol = new LIB_SYMBOL( *libSymbol );
1131  originalSymbol->SetParent( originalBufferedParent->GetSymbol() );
1132  aSymbolBuf->SetOriginal( originalSymbol );
1133  }
1134  }
1135  else
1136  {
1137  wxArrayString derivedSymbols;
1138 
1139  if( GetDerivedSymbolNames( libSymbol->GetName(), derivedSymbols ) == 0 )
1140  {
1141  try
1142  {
1143  aPlugin->SaveSymbol( aFileName, new LIB_SYMBOL( *libSymbol ),
1144  aBuffer ? &properties : nullptr );
1145  }
1146  catch( const IO_ERROR& ioe )
1147  {
1148  wxLogError( errorMsg, ioe.What(), libSymbol->GetName() );
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, ioe.What(), libSymbol->GetName() );
1166  return false;
1167  }
1168 
1169  aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1170 
1171  // Save the derived symbols.
1172  for( auto entry : derivedSymbols )
1173  {
1174  SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER::PTR symbol = GetBuffer( entry );
1175  LIB_SYMBOL* derivedSymbol = new LIB_SYMBOL( *symbol->GetSymbol() );
1176  derivedSymbol->SetParent( parentSymbol );
1177 
1178  try
1179  {
1180  aPlugin->SaveSymbol( aFileName, new LIB_SYMBOL( *derivedSymbol ),
1181  aBuffer ? &properties : nullptr );
1182  }
1183  catch( const IO_ERROR& ioe )
1184  {
1185  wxLogError( errorMsg, ioe.What(), derivedSymbol->GetName() );
1186  return false;
1187  }
1188  }
1189  }
1190  }
1191 
1192  ++m_hash;
1193  return true;
1194 }
1195 
1196 
1198 SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::GetBuffer( const wxString& aAlias ) const
1199 {
1200  for( auto entry : m_symbols )
1201  {
1202  if( entry->GetSymbol()->GetName() == aAlias )
1203  return entry;
1204  }
1205 
1206  return SYMBOL_BUFFER::PTR( nullptr );
1207 }
1208 
1209 
1210 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::HasDerivedSymbols( const wxString& aParentName ) const
1211 {
1212  for( auto entry : m_symbols )
1213  {
1214  if( entry->GetSymbol()->IsAlias() )
1215  {
1216  LIB_SYMBOL_SPTR parent = entry->GetSymbol()->GetParent().lock();
1217 
1218  // Check for inherited symbol without a valid parent.
1219  wxCHECK( parent, false );
1220 
1221  if( parent->GetName() == aParentName )
1222  return true;
1223  }
1224  }
1225 
1226  return false;
1227 }
1228 
1229 
1230 void SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::GetRootSymbolNames( wxArrayString& aRootSymbolNames )
1231 {
1232  for( auto entry : m_symbols )
1233  {
1234  if( entry->GetSymbol()->IsAlias() )
1235  continue;
1236 
1237  aRootSymbolNames.Add( entry->GetSymbol()->GetName() );
1238  }
1239 }
1240 
1241 
1243  wxArrayString& aList )
1244 {
1245  wxCHECK( !aSymbolName.IsEmpty(), 0 );
1246 
1247  for( auto entry : m_symbols )
1248  {
1249  if( entry->GetSymbol()->IsAlias() )
1250  {
1251  LIB_SYMBOL_SPTR parent = entry->GetSymbol()->GetParent().lock();
1252 
1253  // Check for inherited symbol without a valid parent.
1254  wxCHECK( parent, false );
1255 
1256  if( parent->GetName() == aSymbolName )
1257  aList.Add( entry->GetSymbol()->GetName() );
1258  }
1259  }
1260 
1261  return aList.GetCount();
1262 }
1263 
1264 
1267 {
1268  wxCHECK( aSymbolBuf && aSymbolBuf->GetSymbol()->IsRoot(), 0 );
1269 
1270  int cnt = 0;
1271  std::deque< SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER::PTR >::iterator it = m_symbols.begin();
1272 
1273  while( it != m_symbols.end() )
1274  {
1275 
1276  if( (*it)->GetSymbol()->IsRoot() )
1277  {
1278  ++it;
1279  }
1280  else
1281  {
1282  LIB_SYMBOL_SPTR parent = (*it)->GetSymbol()->GetParent().lock();
1283 
1284  wxCHECK2( parent, ++it; continue );
1285 
1286  if( parent->GetName() == aSymbolBuf->GetSymbol()->GetName() )
1287  {
1288  wxCHECK2( parent == aSymbolBuf->GetSymbol()->SharedPtr(), ++it; continue );
1289 
1290  m_deleted.emplace_back( *it );
1291  it = m_symbols.erase( it );
1292  cnt++;
1293  }
1294  else
1295  {
1296  ++it;
1297  }
1298  }
1299  }
1300 
1301  return cnt;
1302 }
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
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:106
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)
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.
bool SaveBuffer(SYMBOL_BUFFER::PTR aSymbolBuf, SYMBOL_LIB_TABLE *aLibTable)
Save stored modifications using a plugin.
A progress reporter 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
bool DeleteBuffer(SYMBOL_BUFFER::PTR aSymbolBuf)
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
int removeChildSymbols(SYMBOL_BUFFER::PTR aSymbolBuf)
Remove all symbols derived from aParent from the library buffer.
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:151
bool IsCancelled() const
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
SYMBOL_BUFFER::PTR GetBuffer(const wxString &aAlias) const
Return all buffered symbols.
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
void ClearDeletedBuffer()
Save stored modifications to Symbol Lib Table.
std::shared_ptr< SYMBOL_BUFFER > PTR
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:325
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
HTML_MESSAGE_BOX.
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)
bool UpdateBuffer(SYMBOL_BUFFER::PTR aSymbolBuf, LIB_SYMBOL *aCopy)
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.
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:193
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:473
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.
const char * name
Definition: DXF_plotter.cpp:59
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 KeepRefreshing(bool aWait=false)
Update the UI dialog.
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.
SAVE_T
The set of return values from SaveSymbol() below.
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.
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
const std::deque< SYMBOL_BUFFER::PTR > & GetBuffers() const
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
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.