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  SYMBOL_ASYNC_LOADER loader( symTable()->GetLogicalLibs(), symTable(), false, nullptr,
78  &aReporter );
79 
80  LOCALE_IO toggle;
81 
82  loader.Start();
83 
84  while( !loader.Done() )
85  {
86  if( !aReporter.KeepRefreshing() )
87  break;
88 
89  wxMilliSleep( 33 /* 30 FPS refresh rate */ );
90  }
91 
92  loader.Join();
93 
94  if( !loader.GetErrors().IsEmpty() )
95  {
96  HTML_MESSAGE_BOX dlg( &m_frame, _( "Load Error" ) );
97 
98  dlg.MessageSet( _( "Errors loading symbols:" ) );
99 
100  wxString msg = loader.GetErrors();
101  msg.Replace( wxT( "\n" ), wxT( "<BR>" ) );
102 
103  dlg.AddHTML_Text( msg );
104  dlg.ShowModal();
105  }
106 }
107 
108 
110 {
111  for( const std::pair<const wxString, LIB_BUFFER>& lib : m_libs )
112  {
113  if( lib.second.IsModified() )
114  return true;
115  }
116 
117  return false;
118 }
119 
120 
122 {
123  int hash = symTable()->GetModifyHash();
124 
125  for( const std::pair<const wxString, LIB_BUFFER>& lib : m_libs )
126  hash += lib.second.GetHash();
127 
128  return hash;
129 }
130 
131 
132 int SYMBOL_LIBRARY_MANAGER::GetLibraryHash( const wxString& aLibrary ) const
133 {
134  const auto libBufIt = m_libs.find( aLibrary );
135 
136  if( libBufIt != m_libs.end() )
137  return libBufIt->second.GetHash();
138 
139  SYMBOL_LIB_TABLE_ROW* row = GetLibrary( aLibrary );
140 
141  // return -1 if library does not exist or 0 if not modified
142  return row ? std::hash<std::string>{}( aLibrary.ToStdString() +
143  row->GetFullURI( true ).ToStdString() ) : -1;
144 }
145 
146 
148 {
149  wxArrayString res;
150 
151  for( const wxString& libName : symTable()->GetLogicalLibs() )
152  res.Add( libName );
153 
154  return res;
155 }
156 
157 
159 {
160  SYMBOL_LIB_TABLE_ROW* row = nullptr;
161 
162  try
163  {
164  row = symTable()->FindRow( aLibrary, true );
165  }
166  catch( const IO_ERROR& e )
167  {
168  wxLogMessage( _( "Library '%s' not found in the Symbol Library Table." ) + e.What(),
169  aLibrary );
170  }
171 
172  return row;
173 }
174 
175 
176 bool SYMBOL_LIBRARY_MANAGER::SaveLibrary( const wxString& aLibrary, const wxString& aFileName,
177  SCH_IO_MGR::SCH_FILE_T aFileType )
178 {
179  wxCHECK( aFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY && LibraryExists( aLibrary ), false );
180  wxFileName fn( aFileName );
181  wxCHECK( !fn.FileExists() || fn.IsFileWritable(), false );
182  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( aFileType ) );
183  bool res = true; // assume all libraries are successfully saved
184 
185  PROPERTIES properties;
186  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, wxEmptyString );
187 
188  auto it = m_libs.find( aLibrary );
189 
190  if( it != m_libs.end() )
191  {
192  // Handle buffered library
193  LIB_BUFFER& libBuf = it->second;
194 
195  const auto& symbolBuffers = libBuf.GetBuffers();
196 
197  for( const auto& symbolBuf : symbolBuffers )
198  {
199  if( !libBuf.SaveBuffer( symbolBuf, aFileName, &*pi, true ) )
200  {
201  // Something went wrong, but try to save other libraries
202  res = false;
203  }
204  }
205 
206  // clear the deleted symbols buffer only if data is saved to the original file
207  wxFileName original, destination( aFileName );
208  auto row = GetLibrary( aLibrary );
209 
210  if( row )
211  {
212  original = row->GetFullURI( true );
213  original.Normalize();
214  }
215 
216  destination.Normalize();
217 
218  if( res && original == destination )
219  libBuf.ClearDeletedBuffer();
220  }
221  else
222  {
223  // Handle original library
224  for( LIB_SYMBOL* symbol : getOriginalSymbols( aLibrary ) )
225  {
226  LIB_SYMBOL* newSymbol;
227 
228  try
229  {
230  if( symbol->IsAlias() )
231  {
232  std::shared_ptr< LIB_SYMBOL > oldParent = symbol->GetParent().lock();
233 
234  wxCHECK_MSG( oldParent, false,
235  wxString::Format( wxT( "Derived symbol '%s' found with undefined parent." ),
236  symbol->GetName() ) );
237 
238  LIB_SYMBOL* libParent = pi->LoadSymbol( aLibrary, oldParent->GetName(),
239  &properties );
240 
241  if( !libParent )
242  {
243  libParent = new LIB_SYMBOL( *oldParent.get() );
244  pi->SaveSymbol( aLibrary, libParent, &properties );
245  }
246 
247  newSymbol = new LIB_SYMBOL( *symbol );
248  newSymbol->SetParent( libParent );
249  pi->SaveSymbol( aLibrary, newSymbol, &properties );
250  }
251  else if( !pi->LoadSymbol( aLibrary, symbol->GetName(), &properties ) )
252  {
253  pi->SaveSymbol( aLibrary, new LIB_SYMBOL( *symbol ), &properties );
254  }
255  }
256  catch( ... )
257  {
258  res = false;
259  break;
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( wxT( "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 = wxT( "New_Library" );
664 
665  if( !LibraryExists( name ) )
666  return name;
667 
668  name += wxT( "_" );
669 
670  for( unsigned int i = 0; i < std::numeric_limits<unsigned int>::max(); ++i )
671  {
672  if( !LibraryExists( name + wxString::Format( wxT( "%u" ), i ) ) )
673  return name + wxString::Format( wxT( "%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( wxT( "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, wxEmptyString );
961 
962  wxString errorMsg = _( "Error saving symbol %s to library '%s'." ) + wxS( "\n%s" );
963 
964  // Delete the original symbol if the symbol name has been changed.
965  if( libSymbol->GetName() != originalSymbol->GetName() )
966  {
967  // DeleteSymbol may throw
968  try
969  {
970  if( aLibTable->LoadSymbol( m_libName, originalSymbol->GetName() ) )
971  aLibTable->DeleteSymbol( m_libName, originalSymbol->GetName() );
972  }
973  catch( const IO_ERROR& ioe )
974  {
975  wxLogError( errorMsg, UnescapeString( originalSymbol->GetName() ), m_libName,
976  ioe.What() );
977  return false;
978  }
979  }
980 
981  if( libSymbol->IsAlias() )
982  {
983  LIB_SYMBOL* newCachedSymbol = new LIB_SYMBOL( *libSymbol );
984  std::shared_ptr< LIB_SYMBOL > bufferedParent = libSymbol->GetParent().lock();
985 
986  wxCHECK( bufferedParent, false );
987 
988  LIB_SYMBOL* cachedParent = aLibTable->LoadSymbol( m_libName, bufferedParent->GetName() );
989 
990  if( !cachedParent )
991  {
992  cachedParent = new LIB_SYMBOL( *bufferedParent.get() );
993  newCachedSymbol->SetParent( cachedParent );
994  result = aLibTable->SaveSymbol( m_libName, cachedParent );
995  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
996  result = aLibTable->SaveSymbol( m_libName, newCachedSymbol );
997  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
998 
999  LIB_SYMBOL* originalParent = new LIB_SYMBOL( *bufferedParent.get() );
1000  aSymbolBuf->SetOriginal( originalParent );
1001  originalSymbol = new LIB_SYMBOL( *libSymbol );
1002  originalSymbol->SetParent( originalParent );
1003  aSymbolBuf->SetOriginal( originalSymbol );
1004  }
1005  else
1006  {
1007  newCachedSymbol->SetParent( cachedParent );
1008  result = aLibTable->SaveSymbol( m_libName, newCachedSymbol );
1009  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1010 
1011  auto originalBufferedParent = GetBuffer( bufferedParent->GetName() );
1012  wxCHECK( originalBufferedParent, false );
1013  originalSymbol = new LIB_SYMBOL( *libSymbol );
1014  originalSymbol->SetParent( originalBufferedParent->GetSymbol() );
1015  aSymbolBuf->SetOriginal( originalSymbol );
1016  }
1017  }
1018  else
1019  {
1020  wxArrayString derivedSymbols;
1021 
1022  if( GetDerivedSymbolNames( libSymbol->GetName(), derivedSymbols ) == 0 )
1023  {
1024  result = aLibTable->SaveSymbol( m_libName, new LIB_SYMBOL( *libSymbol ) );
1025  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1026  aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1027  }
1028  else
1029  {
1030  LIB_SYMBOL* parentSymbol = new LIB_SYMBOL( *libSymbol );
1031 
1032  aLibTable->SaveSymbol( m_libName, parentSymbol );
1033 
1034  for( auto entry : derivedSymbols )
1035  {
1036  std::shared_ptr<SYMBOL_BUFFER> symbol = GetBuffer( entry );
1037  LIB_SYMBOL* derivedSymbol = new LIB_SYMBOL( *symbol->GetSymbol() );
1038  derivedSymbol->SetParent( parentSymbol );
1039  result = aLibTable->SaveSymbol( m_libName, derivedSymbol );
1040  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1041  }
1042  }
1043  }
1044 
1045  ++m_hash;
1046  return true;
1047 }
1048 
1049 
1050 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::SaveBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf,
1051  const wxString& aFileName,
1052  SCH_PLUGIN* aPlugin, bool aBuffer )
1053 {
1054  wxCHECK( aSymbolBuf, false );
1055  LIB_SYMBOL* libSymbol = aSymbolBuf->GetSymbol();
1056  LIB_SYMBOL* originalSymbol = aSymbolBuf->GetOriginal();
1057  wxCHECK( libSymbol && originalSymbol, false );
1058  wxCHECK( !aFileName.IsEmpty(), false );
1059 
1060  wxString errorMsg = _( "Error saving symbol %s to library '%s'." ) + wxS( "\n%s" );
1061 
1062  // set properties to prevent save file on every symbol save
1063  PROPERTIES properties;
1064  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, wxEmptyString );
1065 
1066  // Delete the original symbol if the symbol name has been changed.
1067  if( libSymbol->GetName() != originalSymbol->GetName() )
1068  {
1069  try
1070  {
1071  if( aPlugin->LoadSymbol( aFileName, originalSymbol->GetName() ) )
1072  aPlugin->DeleteSymbol( aFileName, originalSymbol->GetName(), &properties );
1073  }
1074  catch( const IO_ERROR& ioe )
1075  {
1076  wxLogError( errorMsg, UnescapeString( originalSymbol->GetName() ), aFileName,
1077  ioe.What() );
1078  return false;
1079  }
1080  }
1081 
1082  if( libSymbol->IsAlias() )
1083  {
1084  LIB_SYMBOL* newCachedSymbol = new LIB_SYMBOL( *libSymbol );
1085  std::shared_ptr< LIB_SYMBOL > bufferedParent = libSymbol->GetParent().lock();
1086 
1087  wxCHECK( bufferedParent, false );
1088 
1089  LIB_SYMBOL* cachedParent = nullptr;
1090 
1091  try
1092  {
1093  cachedParent = aPlugin->LoadSymbol( aFileName, bufferedParent->GetName() );
1094  }
1095  catch( const IO_ERROR& )
1096  {
1097  return false;
1098  }
1099 
1100  if( !cachedParent )
1101  {
1102  cachedParent = new LIB_SYMBOL( *bufferedParent.get() );
1103  newCachedSymbol->SetParent( cachedParent );
1104 
1105  try
1106  {
1107  aPlugin->SaveSymbol( aFileName, cachedParent, aBuffer ? &properties : nullptr );
1108  }
1109  catch( const IO_ERROR& ioe )
1110  {
1111  wxLogError( errorMsg, UnescapeString( cachedParent->GetName() ), aFileName,
1112  ioe.What() );
1113  return false;
1114  }
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  LIB_SYMBOL* originalParent = new LIB_SYMBOL( *bufferedParent.get() );
1128  aSymbolBuf->SetOriginal( originalParent );
1129  originalSymbol = new LIB_SYMBOL( *libSymbol );
1130  originalSymbol->SetParent( originalParent );
1131  aSymbolBuf->SetOriginal( originalSymbol );
1132  }
1133  else
1134  {
1135  newCachedSymbol->SetParent( cachedParent );
1136 
1137  try
1138  {
1139  aPlugin->SaveSymbol( aFileName, newCachedSymbol, aBuffer ? &properties : nullptr );
1140  }
1141  catch( const IO_ERROR& ioe )
1142  {
1143  wxLogError( errorMsg, UnescapeString( newCachedSymbol->GetName() ), aFileName,
1144  ioe.What() );
1145  return false;
1146  }
1147 
1148  auto originalBufferedParent = GetBuffer( bufferedParent->GetName() );
1149  wxCHECK( originalBufferedParent, false );
1150  originalSymbol = new LIB_SYMBOL( *libSymbol );
1151  originalSymbol->SetParent( originalBufferedParent->GetSymbol() );
1152  aSymbolBuf->SetOriginal( originalSymbol );
1153  }
1154  }
1155  else
1156  {
1157  wxArrayString derivedSymbols;
1158 
1159  if( GetDerivedSymbolNames( libSymbol->GetName(), derivedSymbols ) == 0 )
1160  {
1161  try
1162  {
1163  aPlugin->SaveSymbol( aFileName, new LIB_SYMBOL( *libSymbol ),
1164  aBuffer ? &properties : nullptr );
1165  }
1166  catch( const IO_ERROR& ioe )
1167  {
1168  wxLogError( errorMsg, UnescapeString( libSymbol->GetName() ), aFileName,
1169  ioe.What() );
1170  return false;
1171  }
1172 
1173  aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1174  }
1175  else
1176  {
1177  LIB_SYMBOL* parentSymbol = new LIB_SYMBOL( *libSymbol );
1178 
1179  // Save the modified root symbol.
1180  try
1181  {
1182  aPlugin->SaveSymbol( aFileName, parentSymbol, aBuffer ? &properties : nullptr );
1183  }
1184  catch( const IO_ERROR& ioe )
1185  {
1186  wxLogError( errorMsg, UnescapeString( libSymbol->GetName() ), aFileName,
1187  ioe.What() );
1188  return false;
1189  }
1190 
1191  aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1192 
1193  // Save the derived symbols.
1194  for( auto entry : derivedSymbols )
1195  {
1196  std::shared_ptr<SYMBOL_BUFFER> symbol = GetBuffer( entry );
1197  LIB_SYMBOL* derivedSymbol = new LIB_SYMBOL( *symbol->GetSymbol() );
1198  derivedSymbol->SetParent( parentSymbol );
1199 
1200  try
1201  {
1202  aPlugin->SaveSymbol( aFileName, new LIB_SYMBOL( *derivedSymbol ),
1203  aBuffer ? &properties : nullptr );
1204  }
1205  catch( const IO_ERROR& ioe )
1206  {
1207  wxLogError( errorMsg, UnescapeString( derivedSymbol->GetName() ), aFileName,
1208  ioe.What() );
1209  return false;
1210  }
1211  }
1212  }
1213  }
1214 
1215  ++m_hash;
1216  return true;
1217 }
1218 
1219 
1220 std::shared_ptr<SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER>
1221 SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::GetBuffer( const wxString& aAlias ) const
1222 {
1223  for( auto entry : m_symbols )
1224  {
1225  if( entry->GetSymbol()->GetName() == aAlias )
1226  return entry;
1227  }
1228 
1229  return std::shared_ptr<SYMBOL_BUFFER>( nullptr );
1230 }
1231 
1232 
1233 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::HasDerivedSymbols( const wxString& aParentName ) const
1234 {
1235  for( auto entry : m_symbols )
1236  {
1237  if( entry->GetSymbol()->IsAlias() )
1238  {
1239  LIB_SYMBOL_SPTR parent = entry->GetSymbol()->GetParent().lock();
1240 
1241  // Check for inherited symbol without a valid parent.
1242  wxCHECK( parent, false );
1243 
1244  if( parent->GetName() == aParentName )
1245  return true;
1246  }
1247  }
1248 
1249  return false;
1250 }
1251 
1252 
1253 void SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::GetRootSymbolNames( wxArrayString& aRootSymbolNames )
1254 {
1255  for( auto entry : m_symbols )
1256  {
1257  if( entry->GetSymbol()->IsAlias() )
1258  continue;
1259 
1260  aRootSymbolNames.Add( UnescapeString( entry->GetSymbol()->GetName() ) );
1261  }
1262 }
1263 
1264 
1266  wxArrayString& aList )
1267 {
1268  wxCHECK( !aSymbolName.IsEmpty(), 0 );
1269 
1270  for( auto entry : m_symbols )
1271  {
1272  if( entry->GetSymbol()->IsAlias() )
1273  {
1274  LIB_SYMBOL_SPTR parent = entry->GetSymbol()->GetParent().lock();
1275 
1276  // Check for inherited symbol without a valid parent.
1277  wxCHECK( parent, false );
1278 
1279  if( parent->GetName() == aSymbolName )
1280  aList.Add( entry->GetSymbol()->GetName() );
1281  }
1282  }
1283 
1284  return aList.GetCount();
1285 }
1286 
1287 
1288 int SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::removeChildSymbols( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf )
1289 {
1290  wxCHECK( aSymbolBuf && aSymbolBuf->GetSymbol()->IsRoot(), 0 );
1291 
1292  int cnt = 0;
1293  std::deque< std::shared_ptr<SYMBOL_BUFFER> >::iterator it = m_symbols.begin();
1294 
1295  while( it != m_symbols.end() )
1296  {
1297 
1298  if( (*it)->GetSymbol()->IsRoot() )
1299  {
1300  ++it;
1301  }
1302  else
1303  {
1304  LIB_SYMBOL_SPTR parent = (*it)->GetSymbol()->GetParent().lock();
1305 
1306  wxCHECK2( parent, ++it; continue );
1307 
1308  if( parent->GetName() == aSymbolBuf->GetSymbol()->GetName() )
1309  {
1310  wxCHECK2( parent == aSymbolBuf->GetSymbol()->SharedPtr(), ++it; continue );
1311 
1312  m_deleted.emplace_back( *it );
1313  it = m_symbols.erase( it );
1314  cnt++;
1315  }
1316  else
1317  {
1318  ++it;
1319  }
1320  }
1321  }
1322 
1323  return cnt;
1324 }
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)
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.
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
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
void SyncLibraries(bool aShowProgress, bool aPreloadCancelled=false, const wxString &aForceRefresh=wxEmptyString)
Synchronize the library manager to the symbol library table, and then the symbol tree to the library ...
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:371
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 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.
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:71
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.