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 <class_library.h>
28 #include <symbol_edit_frame.h>
29 #include <env_paths.h>
30 #include <pgm_base.h>
31 #include <kiway.h>
32 #include <profile.h>
33 #include <sch_io_mgr.h>
35 #include <symbol_lib_table.h>
36 #include <list>
37 
38 
40  m_frame( aFrame ),
41  m_syncHash( 0 )
42 {
44  m_adapter->ShowUnits( false );
45 }
46 
47 
48 void SYMBOL_LIBRARY_MANAGER::Sync( const wxString& aForceRefresh,
49  std::function<void( int, int, const wxString& )> aProgressCallback )
50 {
52  {
53  getAdapter()->Sync( aForceRefresh, aProgressCallback );
55  }
57 }
58 
59 
61 {
62  for( const auto& lib : m_libs )
63  {
64  if( lib.second.IsModified() )
65  return true;
66  }
67 
68  return false;
69 }
70 
71 
73 {
74  int hash = symTable()->GetModifyHash();
75 
76  for( const auto& lib : m_libs )
77  hash += lib.second.GetHash();
78 
79  return hash;
80 }
81 
82 
83 int SYMBOL_LIBRARY_MANAGER::GetLibraryHash( const wxString& aLibrary ) const
84 {
85  const auto libBufIt = m_libs.find( aLibrary );
86 
87  if( libBufIt != m_libs.end() )
88  return libBufIt->second.GetHash();
89 
90  auto row = GetLibrary( aLibrary );
91 
92  // return -1 if library does not exist or 0 if not modified
93  return row ? std::hash<std::string>{}( aLibrary.ToStdString() +
94  row->GetFullURI( true ).ToStdString() ) : -1;
95 }
96 
97 
99 {
100  wxArrayString res;
101 
102  for( const auto& libName : symTable()->GetLogicalLibs() )
103  res.Add( libName );
104 
105  return res;
106 }
107 
108 
110 {
111  SYMBOL_LIB_TABLE_ROW* row = nullptr;
112 
113  try
114  {
115  row = symTable()->FindRow( aLibrary, true );
116  }
117  catch( const IO_ERROR& e )
118  {
119  wxLogMessage( _( "Cannot find library \"%s\" in the Symbol Library Table (%s)" ),
120  aLibrary, e.What() );
121  }
122 
123  return row;
124 }
125 
126 
127 bool SYMBOL_LIBRARY_MANAGER::SaveLibrary( const wxString& aLibrary, const wxString& aFileName,
128  SCH_IO_MGR::SCH_FILE_T aFileType )
129 {
130  wxCHECK( aFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY && LibraryExists( aLibrary ), false );
131  wxFileName fn( aFileName );
132  wxCHECK( !fn.FileExists() || fn.IsFileWritable(), false );
133  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( aFileType ) );
134  bool res = true; // assume all libraries are successfully saved
135 
136  PROPERTIES properties;
137  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
138 
139  auto it = m_libs.find( aLibrary );
140 
141  if( it != m_libs.end() )
142  {
143  // Handle buffered library
144  LIB_BUFFER& libBuf = it->second;
145 
146  const auto& partBuffers = libBuf.GetBuffers();
147 
148  for( const auto& partBuf : partBuffers )
149  {
150  if( !libBuf.SaveBuffer( partBuf, &*pi, true ) )
151  {
152  // Something went wrong, but try to save other libraries
153  res = false;
154  }
155  }
156 
157  // clear the deleted parts buffer only if data is saved to the original file
158  wxFileName original, destination( aFileName );
159  auto row = GetLibrary( aLibrary );
160 
161  if( row )
162  {
163  original = row->GetFullURI( true );
164  original.Normalize();
165  }
166 
167  destination.Normalize();
168 
169  if( res && original == destination )
170  libBuf.ClearDeletedBuffer();
171  }
172  else
173  {
174  // Handle original library
175  for( LIB_PART* part : getOriginalParts( aLibrary ) )
176  {
177  LIB_PART* newSymbol;
178 
179  if( part->IsAlias() )
180  {
181  std::shared_ptr< LIB_PART > oldParent = part->GetParent().lock();
182 
183  wxCHECK_MSG( oldParent, false,
184  wxString::Format( "Derived symbol '%s' found with undefined parent.",
185  part->GetName() ) );
186 
187  LIB_PART* libParent = pi->LoadSymbol( aLibrary, oldParent->GetName(), &properties );
188 
189  if( !libParent )
190  {
191  libParent = new LIB_PART( *oldParent.get() );
192  pi->SaveSymbol( aLibrary, libParent, &properties );
193  }
194 
195  newSymbol = new LIB_PART( *part );
196  newSymbol->SetParent( libParent );
197  pi->SaveSymbol( aLibrary, newSymbol, &properties );
198  }
199  else if( !pi->LoadSymbol( aLibrary, part->GetName(), &properties ) )
200  {
201  pi->SaveSymbol( aLibrary, new LIB_PART( *part ), &properties );
202  }
203  }
204  }
205 
206  try
207  {
208  pi->SaveLibrary( aFileName );
209  }
210  catch( ... )
211  {
212  // return false because something happens.
213  // The library is not successfully saved
214  res = false;
215  }
216 
217  return res;
218 }
219 
220 
221 bool SYMBOL_LIBRARY_MANAGER::IsLibraryModified( const wxString& aLibrary ) const
222 {
223  auto it = m_libs.find( aLibrary );
224  return it != m_libs.end() ? it->second.IsModified() : false;
225 }
226 
227 
228 bool SYMBOL_LIBRARY_MANAGER::IsPartModified( const wxString& aAlias, const wxString& aLibrary ) const
229 {
230  auto libIt = m_libs.find( aLibrary );
231 
232  if( libIt == m_libs.end() )
233  return false;
234 
235  const LIB_BUFFER& buf = libIt->second;
236  auto partBuf = buf.GetBuffer( aAlias );
237  return partBuf ? partBuf->IsModified() : false;
238 }
239 
240 
241 bool SYMBOL_LIBRARY_MANAGER::ClearLibraryModified( const wxString& aLibrary ) const
242 {
243  auto libIt = m_libs.find( aLibrary );
244 
245  if( libIt == m_libs.end() )
246  return false;
247 
248  for( auto& partBuf : libIt->second.GetBuffers() )
249  {
250  SCH_SCREEN* screen = partBuf->GetScreen();
251 
252  if( screen )
253  screen->ClrModify();
254  }
255 
256  return true;
257 }
258 
259 
260 bool SYMBOL_LIBRARY_MANAGER::ClearPartModified( const wxString& aAlias, const wxString& aLibrary ) const
261 {
262  auto libI = m_libs.find( aLibrary );
263 
264  if( libI == m_libs.end() )
265  return false;
266 
267  auto partBuf = libI->second.GetBuffer( aAlias );
268  wxCHECK( partBuf, false );
269 
270  partBuf->GetScreen()->ClrModify();
271  return true;
272 }
273 
274 
275 bool SYMBOL_LIBRARY_MANAGER::IsLibraryReadOnly( const wxString& aLibrary ) const
276 {
277  wxCHECK( LibraryExists( aLibrary ), true );
278 
279  return !symTable()->IsSymbolLibWritable( aLibrary );
280 }
281 
282 
283 bool SYMBOL_LIBRARY_MANAGER::IsLibraryLoaded( const wxString& aLibrary ) const
284 {
285  wxCHECK( LibraryExists( aLibrary ), false );
286 
287  return symTable()->IsSymbolLibLoaded( aLibrary );
288 }
289 
290 
291 std::list<LIB_PART*> SYMBOL_LIBRARY_MANAGER::GetAliases( const wxString& aLibrary ) const
292 {
293  std::list<LIB_PART*> ret;
294  wxCHECK( LibraryExists( aLibrary ), ret );
295 
296  auto libIt = m_libs.find( aLibrary );
297 
298  if( libIt != m_libs.end() )
299  {
300  for( auto& partBuf : libIt->second.GetBuffers() )
301  {
302  ret.push_back( partBuf->GetPart() );
303  }
304  }
305  else
306  {
307  std::vector<LIB_PART*> aliases;
308 
309  try
310  {
311  symTable()->LoadSymbolLib( aliases, aLibrary );
312  }
313  catch( const IO_ERROR& e )
314  {
315  wxLogWarning( e.Problem() );
316  }
317 
318  std::copy( aliases.begin(), aliases.end(), std::back_inserter( ret ) );
319  }
320 
321  return ret;
322 }
323 
324 
326  const wxString& aLibrary )
327 {
328  wxCHECK( LibraryExists( aLibrary ), nullptr );
329 
330  // try the library buffers first
331  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
332  LIB_PART* bufferedPart = libBuf.GetPart( aAlias );
333 
334  if( !bufferedPart ) // no buffer part found
335  {
336  // create a copy of the part
337  try
338  {
339  LIB_PART* part = symTable()->LoadSymbol( aLibrary, aAlias );
340 
341  if( part == nullptr )
342  THROW_IO_ERROR( _( "Symbol not found." ) );
343 
344  LIB_PART* bufferedParent = nullptr;
345 
346  // Create parent symbols on demand so parent symbol can be set.
347  if( part->IsAlias() )
348  {
349  std::shared_ptr< LIB_PART > parent = part->GetParent().lock();
350  wxCHECK_MSG( parent, nullptr,
351  wxString::Format( "Derived symbol '%s' found with undefined parent.",
352  part->GetName() ) );
353 
354  // Check if the parent symbol buffer has already be created.
355  bufferedParent = libBuf.GetPart( parent->GetName() );
356 
357  if( !bufferedParent )
358  {
359  bufferedParent = new LIB_PART( *parent.get() );
360  libBuf.CreateBuffer( bufferedParent, new SCH_SCREEN );
361  }
362  }
363 
364  bufferedPart = new LIB_PART( *part );
365 
366  if( bufferedParent )
367  bufferedPart->SetParent( bufferedParent );
368 
369  libBuf.CreateBuffer( bufferedPart, new SCH_SCREEN );
370  }
371  catch( const IO_ERROR& e )
372  {
373  wxLogMessage( _( "Error loading symbol \"%s\" from library \"%s\". (%s)" ),
374  aAlias, aLibrary, e.What() );
375  bufferedPart = nullptr;
376  }
377  }
378 
379  return bufferedPart;
380 }
381 
382 
383 SCH_SCREEN* SYMBOL_LIBRARY_MANAGER::GetScreen( const wxString& aAlias, const wxString& aLibrary )
384 {
385  wxCHECK( LibraryExists( aLibrary ), nullptr );
386  wxCHECK( !aAlias.IsEmpty(), nullptr );
387  auto it = m_libs.find( aLibrary );
388  wxCHECK( it != m_libs.end(), nullptr );
389 
390  LIB_BUFFER& buf = it->second;
391  auto partBuf = buf.GetBuffer( aAlias );
392  return partBuf ? partBuf->GetScreen() : nullptr;
393 }
394 
395 
396 bool SYMBOL_LIBRARY_MANAGER::UpdatePart( LIB_PART* aPart, const wxString& aLibrary )
397 {
398  wxCHECK( LibraryExists( aLibrary ), false );
399  wxCHECK( aPart, false );
400  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
401  auto partBuf = libBuf.GetBuffer( aPart->GetName() );
402 
403  if( partBuf ) // Existing symbol.
404  {
405  LIB_PART* bufferedPart = const_cast< LIB_PART* >( partBuf->GetPart() );
406 
407  wxCHECK( bufferedPart, false );
408 
409  *bufferedPart = *aPart;
410  partBuf->GetScreen()->SetModify();
411  }
412  else // New symbol
413  {
414  LIB_PART* partCopy = new LIB_PART( *aPart, nullptr );
415 
416  partCopy->SetLibId( LIB_ID( aLibrary, aPart->GetLibId().GetLibItemName() ) );
417 
418  SCH_SCREEN* screen = new SCH_SCREEN;
419  libBuf.CreateBuffer( partCopy, screen );
420  screen->SetModify();
421  }
422 
423  return true;
424 }
425 
426 
427 bool SYMBOL_LIBRARY_MANAGER::UpdatePartAfterRename( LIB_PART* aPart, const wxString& aOldName,
428  const wxString& aLibrary )
429 {
430  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
431  auto partBuf = libBuf.GetBuffer( aOldName );
432 
433  wxCHECK( partBuf, false );
434 
435  libBuf.UpdateBuffer( partBuf, aPart );
436  m_frame.SyncLibraries( false );
437 
438  return true;
439 }
440 
441 
442 bool SYMBOL_LIBRARY_MANAGER::FlushPart( const wxString& aAlias, const wxString& aLibrary )
443 {
444  auto it = m_libs.find( aLibrary );
445 
446  if( it == m_libs.end() ) // no items to flush
447  return true;
448 
449  auto partBuf = it->second.GetBuffer( aAlias );
450  wxCHECK( partBuf, false );
451 
452  return it->second.SaveBuffer( partBuf, symTable() );
453 }
454 
455 
456 LIB_ID SYMBOL_LIBRARY_MANAGER::RevertPart( const wxString& aAlias, const wxString& aLibrary )
457 {
458  auto it = m_libs.find( aLibrary );
459 
460  if( it == m_libs.end() ) // no items to flush
461  return LIB_ID( aLibrary, aAlias );
462 
463  auto partBuf = it->second.GetBuffer( aAlias );
464  wxCHECK( partBuf, LIB_ID( aLibrary, aAlias ) );
465  LIB_PART original( *partBuf->GetOriginal() );
466 
467  if( original.GetName() != aAlias )
468  {
469  UpdatePartAfterRename( &original, aAlias, aLibrary );
470  }
471  else
472  {
473  partBuf->SetPart( new LIB_PART( original ) );
474  m_frame.SyncLibraries( false );
475  }
476 
477  return LIB_ID( aLibrary, original.GetName() );
478 }
479 
480 
481 bool SYMBOL_LIBRARY_MANAGER::RevertLibrary( const wxString& aLibrary )
482 {
483  auto it = m_libs.find( aLibrary );
484 
485  if( it == m_libs.end() ) // nothing to reverse
486  return false;
487 
488  m_libs.erase( it );
489  m_frame.SyncLibraries( false );
490 
491  return true;
492 }
493 
494 
496 {
497  bool retv = true;
498 
499  // Nothing to revert.
500  if( GetHash() == 0 )
501  return true;
502 
503  for( const auto& lib : m_libs )
504  {
505  if( !lib.second.IsModified() )
506  continue;
507 
508  for( const auto& buffer : lib.second.GetBuffers() )
509  {
510  if( !buffer->IsModified() )
511  continue;
512 
513  RevertPart( lib.first, buffer->GetOriginal()->GetName() );
514  }
515  }
516 
517  return retv;
518 }
519 
520 
521 bool SYMBOL_LIBRARY_MANAGER::RemovePart( const wxString& aAlias, const wxString& aLibrary )
522 {
523  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
524  auto partBuf = libBuf.GetBuffer( aAlias );
525  wxCHECK( partBuf, false );
526 
527  bool retv = true;
528 
529  retv &= libBuf.DeleteBuffer( partBuf );
530  m_frame.SyncLibraries( false );
531 
532  return retv;
533 }
534 
535 
537  const wxString& aLibrary ) const
538 {
539  // Try the library buffers first
540  auto libIt = m_libs.find( aLibrary );
541 
542  if( libIt != m_libs.end() )
543  {
544  LIB_PART* part = libIt->second.GetPart( aAlias );
545 
546  if( part )
547  return part;
548  }
549 
550  // Get the original part
551  LIB_PART* alias = nullptr;
552 
553  try
554  {
555  alias = symTable()->LoadSymbol( aLibrary, aAlias );
556  }
557  catch( const IO_ERROR& e )
558  {
559  wxLogMessage( _( "Cannot load symbol \"%s\" from library \"%s\" (%s)" ),
560  aAlias, aLibrary, e.What() );
561  }
562 
563  return alias;
564 }
565 
566 
567 bool SYMBOL_LIBRARY_MANAGER::PartExists( const wxString& aAlias, const wxString& aLibrary ) const
568 {
569  auto libBufIt = m_libs.find( aLibrary );
570  LIB_PART* alias = nullptr;
571 
572  if( libBufIt != m_libs.end() )
573  return !!libBufIt->second.GetBuffer( aAlias );
574 
575  try
576  {
577  alias = symTable()->LoadSymbol( aLibrary, aAlias );
578  }
579  catch( IO_ERROR& )
580  {
581  // checking if certain symbol exists, so its absence is perfectly fine
582  }
583 
584  return alias != nullptr;
585 }
586 
587 
588 bool SYMBOL_LIBRARY_MANAGER::LibraryExists( const wxString& aLibrary, bool aCheckEnabled ) const
589 {
590  if( aLibrary.IsEmpty() )
591  return false;
592 
593  if( m_libs.count( aLibrary ) > 0 )
594  return true;
595 
596  return symTable()->HasLibrary( aLibrary, aCheckEnabled );
597 }
598 
599 
601 {
602  wxString name = "New_Library";
603 
604  if( !LibraryExists( name ) )
605  return name;
606 
607  name += "_";
608 
609  for( unsigned int i = 0; i < std::numeric_limits<unsigned int>::max(); ++i )
610  {
611  if( !LibraryExists( name + wxString::Format( "%u", i ) ) )
612  return name + wxString::Format( "%u", i );
613  }
614 
615  wxFAIL;
616  return wxEmptyString;
617 }
618 
619 
620 void SYMBOL_LIBRARY_MANAGER::GetRootSymbolNames( const wxString& aLibraryName,
621  wxArrayString& aRootSymbolNames )
622 {
623  LIB_BUFFER& libBuf = getLibraryBuffer( aLibraryName );
624 
625  libBuf.GetRootSymbolNames( aRootSymbolNames );
626 }
627 
628 
629 bool SYMBOL_LIBRARY_MANAGER:: HasDerivedSymbols( const wxString& aSymbolName,
630  const wxString& aLibraryName )
631 {
632  LIB_BUFFER& libBuf = getLibraryBuffer( aLibraryName );
633 
634  return libBuf.HasDerivedSymbols( aSymbolName );
635 }
636 
637 
638 wxString SYMBOL_LIBRARY_MANAGER::getLibraryName( const wxString& aFilePath )
639 {
640  wxFileName fn( aFilePath );
641  return fn.GetName();
642 }
643 
644 
645 bool SYMBOL_LIBRARY_MANAGER::addLibrary( const wxString& aFilePath, bool aCreate,
646  SYMBOL_LIB_TABLE* aTable )
647 {
648  wxCHECK( aTable, false );
649  wxString libName = getLibraryName( aFilePath );
650  wxCHECK( !LibraryExists( libName ), false ); // either create or add an existing one
651 
652  // try to use path normalized to an environmental variable or project path
653  wxString relPath = NormalizePath( aFilePath, &Pgm().GetLocalEnvVariables(), &m_frame.Prj() );
654 
655  if( relPath.IsEmpty() )
656  relPath = aFilePath;
657 
658  SCH_IO_MGR::SCH_FILE_T schFileType = SCH_IO_MGR::GuessPluginTypeFromLibPath( aFilePath );
659  wxString typeName = SCH_IO_MGR::ShowType( schFileType );
660  SYMBOL_LIB_TABLE_ROW* libRow = new SYMBOL_LIB_TABLE_ROW( libName, relPath, typeName );
661  aTable->InsertRow( libRow );
662 
663  if( aCreate )
664  {
665  wxCHECK( schFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY, false );
666 
667  try
668  {
669  aTable->CreateSymbolLib( libName );
670  }
671  catch( const IO_ERROR& )
672  {
673  aTable->RemoveRow( libRow );
674  return false;
675  }
676  }
677 
678  m_frame.SyncLibraries( false );
679 
680  return true;
681 }
682 
683 
685 {
686  return m_frame.Prj().SchSymbolLibTable();
687 }
688 
689 
690 std::set<LIB_PART*> SYMBOL_LIBRARY_MANAGER::getOriginalParts( const wxString& aLibrary )
691 {
692  std::set<LIB_PART*> parts;
693  wxCHECK( LibraryExists( aLibrary ), parts );
694 
695  try
696  {
697  wxArrayString aliases;
698  symTable()->EnumerateSymbolLib( aLibrary, aliases );
699 
700  for( const auto& aliasName : aliases )
701  {
702  LIB_PART* alias = symTable()->LoadSymbol( aLibrary, aliasName );
703  parts.insert( alias );
704  }
705  }
706  catch( const IO_ERROR& e )
707  {
708  wxLogMessage( _( "Cannot enumerate library \"%s\" (%s)" ), aLibrary, e.What() );
709  }
710 
711  return parts;
712 }
713 
714 
716 {
717  auto it = m_libs.find( aLibrary );
718 
719  if( it != m_libs.end() )
720  return it->second;
721 
722  // The requested buffer does not exist yet, so create one
723  auto ret = m_libs.emplace( aLibrary, LIB_BUFFER( aLibrary ) );
724  LIB_BUFFER& buf = ret.first->second;
725 
726  for( auto part : getOriginalParts( aLibrary ) )
727  {
728  LIB_PART* newSymbol;
729 
730  if( part->IsAlias() )
731  {
732  std::shared_ptr< LIB_PART > oldParent = part->GetParent().lock();
733 
734  wxCHECK_MSG( oldParent, buf,
735  wxString::Format( "Derived symbol '%s' found with undefined parent.",
736  part->GetName() ) );
737 
738  LIB_PART* libParent = buf.GetPart( oldParent->GetName() );
739 
740  if( !libParent )
741  {
742  libParent = new LIB_PART( *oldParent.get() );
743  buf.CreateBuffer( libParent, new SCH_SCREEN );
744  }
745 
746  newSymbol = new LIB_PART( *part );
747  newSymbol->SetParent( libParent );
748  buf.CreateBuffer( newSymbol, new SCH_SCREEN );
749  }
750  else if( !buf.GetPart( part->GetName() ) )
751  {
752  buf.CreateBuffer( new LIB_PART( *part ), new SCH_SCREEN );
753  }
754  }
755 
756  return buf;
757 }
758 
759 
761  std::unique_ptr<SCH_SCREEN> aScreen ) :
762  m_screen( std::move( aScreen ) ),
763  m_part( aPart )
764 {
765  m_original = new LIB_PART( *aPart );
766 }
767 
768 
770 {
771  delete m_part;
772  delete m_original;
773 }
774 
775 
777 {
778  wxCHECK( m_part != aPart, /* void */ );
779  wxASSERT( aPart );
780  delete m_part;
781  m_part = aPart;
782 
783  // If the part moves libraries then the original moves with it
784  if( m_original->GetLibId().GetLibNickname() != m_part->GetLibId().GetLibNickname() )
785  {
786  m_original->SetLibId( LIB_ID( m_part->GetLibId().GetLibNickname(),
787  m_original->GetLibId().GetLibItemName() ) );
788  }
789 }
790 
791 
793 {
794  wxCHECK( m_original != aPart, /* void */ );
795  wxASSERT( aPart );
796  delete m_original;
797  m_original = aPart;
798 
799  // The original is not allowed to have a different library than its part
800  if( m_original->GetLibId().GetLibNickname() != m_part->GetLibId().GetLibNickname() )
801  {
802  m_original->SetLibId( LIB_ID( m_part->GetLibId().GetLibNickname(),
803  m_original->GetLibId().GetLibItemName() ) );
804  }
805 }
806 
807 
809 {
810  return m_screen && m_screen->IsModify();
811 }
812 
813 
815 {
816  auto buf = GetBuffer( aAlias );
817 
818  if( !buf )
819  return nullptr;
820 
821  LIB_PART* part = buf->GetPart();
822 
823  wxCHECK( part, nullptr );
824 
825  return part;
826 }
827 
828 
830 {
831  wxASSERT( aCopy );
832  wxASSERT( aCopy->GetLib() == nullptr );
833  std::unique_ptr<SCH_SCREEN> screen( aScreen );
834  auto partBuf = std::make_shared<PART_BUFFER>( aCopy, std::move( screen ) );
835  m_parts.push_back( partBuf );
836 
837  // Set the parent library name,
838  // otherwise it is empty as no library has been given as the owner during object construction
839  LIB_ID libId = aCopy->GetLibId();
840  libId.SetLibNickname( m_libName );
841  aCopy->SetLibId( libId );
842  ++m_hash;
843 
844  return true;
845 }
846 
847 
849  LIB_PART* aCopy )
850 {
851  wxCHECK( aCopy && aPartBuf, false );
852 
853  LIB_PART* bufferedPart = aPartBuf->GetPart();
854 
855  wxCHECK( bufferedPart, false );
856 
857  *bufferedPart = *aCopy;
858  ++m_hash;
859 
860  return true;
861 }
862 
863 
865 {
866  auto partBufIt = std::find( m_parts.begin(), m_parts.end(), aPartBuf );
867  wxCHECK( partBufIt != m_parts.end(), false );
868 
869  bool retv = true;
870 
871  // Remove all derived symbols to prevent broken inheritance.
872  if( aPartBuf->GetPart()->IsRoot() && HasDerivedSymbols( aPartBuf->GetPart()->GetName() )
873  && removeChildSymbols( aPartBuf ) == 0 )
874  {
875  retv = false;
876  }
877 
878  m_deleted.emplace_back( *partBufIt );
879  m_parts.erase( partBufIt );
880  ++m_hash;
881 
882  return retv;
883 }
884 
885 
887  SYMBOL_LIB_TABLE* aLibTable )
888 {
889  wxCHECK( aPartBuf, false );
890  LIB_PART* part = aPartBuf->GetPart();
891  LIB_PART* originalPart = aPartBuf->GetOriginal();
892  wxCHECK( part && originalPart, false );
894  PROPERTIES properties;
895  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
896 
897  // Delete the original symbol if the symbol name has been changed.
898  if( part->GetName() != originalPart->GetName() )
899  {
900  aLibTable->DeleteSymbol( m_libName, originalPart->GetName() );
901  }
902 
903  if( part->IsAlias() )
904  {
905  LIB_PART* newCachedPart = new LIB_PART( *part );
906  std::shared_ptr< LIB_PART > bufferedParent = part->GetParent().lock();
907 
908  wxCHECK( bufferedParent, false );
909 
910  LIB_PART* cachedParent = aLibTable->LoadSymbol( m_libName, bufferedParent->GetName() );
911 
912  if( !cachedParent )
913  {
914  cachedParent = new LIB_PART( *bufferedParent.get() );
915  newCachedPart->SetParent( cachedParent );
916  result = aLibTable->SaveSymbol( m_libName, cachedParent );
917  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
918  result = aLibTable->SaveSymbol( m_libName, newCachedPart );
919  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
920 
921  LIB_PART* originalParent = new LIB_PART( *bufferedParent.get() );
922  aPartBuf->SetOriginal( originalParent );
923  originalPart = new LIB_PART( *part );
924  originalPart->SetParent( originalParent );
925  aPartBuf->SetOriginal( originalPart );
926  }
927  else
928  {
929  newCachedPart->SetParent( cachedParent );
930  result = aLibTable->SaveSymbol( m_libName, newCachedPart );
931  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
932 
933  SYMBOL_LIBRARY_MANAGER::PART_BUFFER::PTR originalBufferedParent =
934  GetBuffer( bufferedParent->GetName() );
935  wxCHECK( originalBufferedParent, false );
936  originalPart = new LIB_PART( *part );
937  originalPart->SetParent( originalBufferedParent->GetPart() );
938  aPartBuf->SetOriginal( originalPart );
939  }
940  }
941  else
942  {
943  wxArrayString derivedSymbols;
944 
945  if( GetDerivedSymbolNames( part->GetName(), derivedSymbols ) == 0 )
946  {
947  result = aLibTable->SaveSymbol( m_libName, new LIB_PART( *part ) );
948  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
949  aPartBuf->SetOriginal( new LIB_PART( *part ) );
950  }
951  else
952  {
953  LIB_PART* parentSymbol = new LIB_PART( *part );
954 
955  aLibTable->SaveSymbol( m_libName, parentSymbol );
956 
957  for( auto entry : derivedSymbols )
958  {
959  SYMBOL_LIBRARY_MANAGER::PART_BUFFER::PTR symbol = GetBuffer( entry );
960  LIB_PART* derivedSymbol = new LIB_PART( *symbol->GetPart() );
961  derivedSymbol->SetParent( parentSymbol );
962  result = aLibTable->SaveSymbol( m_libName, derivedSymbol );
963  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
964  }
965  }
966  }
967 
968  ++m_hash;
969  return true;
970 }
971 
972 
974  SCH_PLUGIN* aPlugin, bool aBuffer )
975 {
976  wxCHECK( aPartBuf, false );
977  LIB_PART* part = aPartBuf->GetPart();
978  LIB_PART* originalPart = aPartBuf->GetOriginal();
979  wxCHECK( part && originalPart, false );
980 
981  wxString errorMsg = _( "An error \"%s\" occurred saving symbol \"%s\" to library \"%s\"" );
982 
983  // set properties to prevent save file on every symbol save
984  PROPERTIES properties;
985  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
986 
987  // Delete the original symbol if the symbol name has been changed.
988  if( part->GetName() != originalPart->GetName() )
989  {
990  aPlugin->DeleteSymbol( m_libName, originalPart->GetName(), &properties );
991  }
992 
993  if( part->IsAlias() )
994  {
995  LIB_PART* newCachedPart = new LIB_PART( *part );
996  std::shared_ptr< LIB_PART > bufferedParent = part->GetParent().lock();
997 
998  wxCHECK( bufferedParent, false );
999 
1000  LIB_PART* cachedParent = nullptr;
1001 
1002  try
1003  {
1004  cachedParent = aPlugin->LoadSymbol( m_libName, bufferedParent->GetName() );
1005  }
1006  catch( const IO_ERROR& )
1007  {
1008  return false;
1009  }
1010 
1011  if( !cachedParent )
1012  {
1013  cachedParent = new LIB_PART( *bufferedParent.get() );
1014  newCachedPart->SetParent( cachedParent );
1015 
1016  try
1017  {
1018  aPlugin->SaveSymbol( m_libName, cachedParent, aBuffer ? &properties : nullptr );
1019  }
1020  catch( const IO_ERROR& ioe )
1021  {
1022  wxLogError( errorMsg, ioe.What(), cachedParent->GetName() );
1023  return false;
1024  }
1025 
1026  try
1027  {
1028  aPlugin->SaveSymbol( m_libName, newCachedPart, aBuffer ? &properties : nullptr );
1029  }
1030  catch( const IO_ERROR& ioe )
1031  {
1032  wxLogError( errorMsg, ioe.What(), newCachedPart->GetName() );
1033  return false;
1034  }
1035 
1036  LIB_PART* originalParent = new LIB_PART( *bufferedParent.get() );
1037  aPartBuf->SetOriginal( originalParent );
1038  originalPart = new LIB_PART( *part );
1039  originalPart->SetParent( originalParent );
1040  aPartBuf->SetOriginal( originalPart );
1041  }
1042  else
1043  {
1044  newCachedPart->SetParent( cachedParent );
1045 
1046  try
1047  {
1048  aPlugin->SaveSymbol( m_libName, newCachedPart, aBuffer ? &properties : nullptr );
1049  }
1050  catch( const IO_ERROR& ioe )
1051  {
1052  wxLogError( errorMsg, ioe.What(), newCachedPart->GetName() );
1053  return false;
1054  }
1055 
1056  SYMBOL_LIBRARY_MANAGER::PART_BUFFER::PTR originalBufferedParent =
1057  GetBuffer( bufferedParent->GetName() );
1058  wxCHECK( originalBufferedParent, false );
1059  originalPart = new LIB_PART( *part );
1060  originalPart->SetParent( originalBufferedParent->GetPart() );
1061  aPartBuf->SetOriginal( originalPart );
1062  }
1063  }
1064  else
1065  {
1066  wxArrayString derivedSymbols;
1067 
1068  if( GetDerivedSymbolNames( part->GetName(), derivedSymbols ) == 0 )
1069  {
1070  try
1071  {
1072  aPlugin->SaveSymbol( m_libName, new LIB_PART( *part ),
1073  aBuffer ? &properties : nullptr );
1074  }
1075  catch( const IO_ERROR& ioe )
1076  {
1077  wxLogError( errorMsg, ioe.What(), part->GetName() );
1078  return false;
1079  }
1080 
1081  aPartBuf->SetOriginal( new LIB_PART( *part ) );
1082  }
1083  else
1084  {
1085  LIB_PART* parentSymbol = new LIB_PART( *part );
1086 
1087  // Save the modified root symbol.
1088  try
1089  {
1090  aPlugin->SaveSymbol( m_libName, parentSymbol, aBuffer ? &properties : nullptr );
1091  }
1092  catch( const IO_ERROR& ioe )
1093  {
1094  wxLogError( errorMsg, ioe.What(), part->GetName() );
1095  return false;
1096  }
1097 
1098  aPartBuf->SetOriginal( new LIB_PART( *part ) );
1099 
1100  // Save the derived symbols.
1101  for( auto entry : derivedSymbols )
1102  {
1103  SYMBOL_LIBRARY_MANAGER::PART_BUFFER::PTR symbol = GetBuffer( entry );
1104  LIB_PART* derivedSymbol = new LIB_PART( *symbol->GetPart() );
1105  derivedSymbol->SetParent( parentSymbol );
1106 
1107  try
1108  {
1109  aPlugin->SaveSymbol( m_libName, new LIB_PART( *derivedSymbol ),
1110  aBuffer ? &properties : nullptr );
1111  }
1112  catch( const IO_ERROR& ioe )
1113  {
1114  wxLogError( errorMsg, ioe.What(), derivedSymbol->GetName() );
1115  return false;
1116  }
1117  }
1118  }
1119  }
1120 
1121  ++m_hash;
1122  return true;
1123 }
1124 
1125 
1127 SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::GetBuffer( const wxString& aAlias ) const
1128 {
1129  for( auto entry : m_parts )
1130  {
1131  if( entry->GetPart()->GetName() == aAlias )
1132  return entry;
1133  }
1134 
1135  return PART_BUFFER::PTR( nullptr );
1136 }
1137 
1138 
1139 bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::HasDerivedSymbols( const wxString& aParentName ) const
1140 {
1141  for( auto entry : m_parts )
1142  {
1143  if( entry->GetPart()->IsAlias() )
1144  {
1145  PART_SPTR parent = entry->GetPart()->GetParent().lock();
1146 
1147  // Check for inherited part without a valid parent.
1148  wxCHECK( parent, false );
1149 
1150  if( parent->GetName() == aParentName )
1151  return true;
1152  }
1153  }
1154 
1155  return false;
1156 }
1157 
1158 
1159 void SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::GetRootSymbolNames( wxArrayString& aRootSymbolNames )
1160 {
1161  for( auto entry : m_parts )
1162  {
1163  if( entry->GetPart()->IsAlias() )
1164  continue;
1165 
1166  aRootSymbolNames.Add( entry->GetPart()->GetName() );
1167  }
1168 }
1169 
1170 
1172  wxArrayString& aList )
1173 {
1174  wxCHECK( !aSymbolName.IsEmpty(), 0 );
1175 
1176  for( auto entry : m_parts )
1177  {
1178  if( entry->GetPart()->IsAlias() )
1179  {
1180  PART_SPTR parent = entry->GetPart()->GetParent().lock();
1181 
1182  // Check for inherited part without a valid parent.
1183  wxCHECK( parent, false );
1184 
1185  if( parent->GetName() == aSymbolName )
1186  aList.Add( entry->GetPart()->GetName() );
1187  }
1188  }
1189 
1190  return aList.GetCount();
1191 }
1192 
1193 
1195 {
1196  wxCHECK( aPartBuf && aPartBuf->GetPart()->IsRoot(), 0 );
1197 
1198  int cnt = 0;
1199  std::deque< SYMBOL_LIBRARY_MANAGER::PART_BUFFER::PTR >::iterator it = m_parts.begin();
1200 
1201  while( it != m_parts.end() )
1202  {
1203 
1204  if( (*it)->GetPart()->IsRoot() )
1205  {
1206  ++it;
1207  }
1208  else
1209  {
1210  PART_SPTR parent = (*it)->GetPart()->GetParent().lock();
1211 
1212  wxCHECK2( parent, ++it; continue );
1213 
1214  if( parent->GetName() == aPartBuf->GetPart()->GetName() )
1215  {
1216  wxCHECK2( parent == aPartBuf->GetPart()->SharedPtr(), ++it; continue );
1217 
1218  m_deleted.emplace_back( *it );
1219  it = m_parts.erase( it );
1220  cnt++;
1221  }
1222  else
1223  {
1224  ++it;
1225  }
1226  }
1227  }
1228 
1229  return cnt;
1230 }
PART_LIB * GetLib()
Definition: lib_symbol.h:172
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:169
bool ClearPartModified(const wxString &aAlias, const wxString &aLibrary) const
Clear the modified flag for a part.
SAVE_T SaveSymbol(const wxString &aNickname, const LIB_PART *aSymbol, bool aOverwrite=true)
Write aSymbol to an existing library given by aNickname.
bool UpdatePartAfterRename(LIB_PART *aPart, const wxString &oldAlias, const wxString &aLibrary)
Update the part buffer with a new version of the part when the name has changed.
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...
LIB_PART * GetAlias(const wxString &aAlias, const wxString &aLibrary) const
Return either an alias of a working LIB_PART copy, or alias of the original part if there is no worki...
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
LIB_ID GetLibId() const override
Definition: lib_symbol.h:131
void GetRootSymbolNames(const wxString &aLibName, wxArrayString &aRootSymbolNames)
bool RemovePart(const wxString &aName, const wxString &aLibrary)
Remove the part from the part buffer.
static wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > Create(SYMBOL_EDIT_FRAME *aParent, SYMBOL_LIBRARY_MANAGER *aLibs)
wxString GetName() const override
Definition: lib_symbol.h:129
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.
bool ClearLibraryModified(const wxString &aLibrary) const
Clear the modified flag for all parts in a library.
bool PartExists(const wxString &aAlias, const wxString &aLibrary) const
Return true if part with a specific alias exists in library (either original one or buffered).
SYMBOL_LIBRARY_MANAGER(SYMBOL_EDIT_FRAME &aFrame)
static const wxString ShowType(SCH_FILE_T aFileType)
Return a brief name for a plugin, given aFileType enum.
Definition: sch_io_mgr.cpp:87
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 CreateBuffer(LIB_PART *aCopy, SCH_SCREEN *aScreen)
Update the buffered part with the contents of aCopy.
static wxString getLibraryName(const wxString &aFilePath)
< Extract library name basing on the file name.
virtual void DeleteSymbol(const wxString &aLibraryPath, const wxString &aSymbolName, const PROPERTIES *aProperties=NULL)
Delete the entire LIB_PART associated with aAliasName from the library aLibraryPath.
Definition: sch_plugin.cpp:102
SYMBOL_LIB_TABLE * symTable() const
LIB_PART * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_PART having aName from the library given by aNickname.
Definition: bitmap.cpp:58
std::shared_ptr< LIB_PART > PART_SPTR
shared pointer to LIB_PART
Definition: lib_symbol.h:42
PART_BUFFER(LIB_PART *aPart=nullptr, std::unique_ptr< SCH_SCREEN > aScreen=nullptr)
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.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
bool UpdatePart(LIB_PART *aPart, const wxString &aLibrary)
Update the part buffer with a new version of the part.
bool RevertLibrary(const wxString &aLibrary)
Revert unsaved changes for a particular library.
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:45
LIB_BUFFER & getLibraryBuffer(const wxString &aLibrary)
Return an existing library buffer or creates one to using Symbol Library Table to get the original da...
LIB_PART * GetPart(const wxString &aAlias) const
Create a new buffer to store a part. LIB_BUFFER takes ownership of aCopy.
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.
void Sync(const wxString &aForceRefresh, std::function< void(int, int, const wxString &)> aProgressCallback)
bool FlushPart(const wxString &aAlias, const wxString &aLibrary)
Save part changes to the library copy used by the schematic editor.
LIB_PART * GetBufferedPart(const wxString &aAlias, const wxString &aLibrary)
Return the part copy from the buffer.
Base class that schematic file and library loading and saving plugins should derive from.
Definition: sch_io_mgr.h:153
wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > m_adapter
bool UpdateBuffer(PART_BUFFER::PTR aPartBuf, LIB_PART *aCopy)
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:29
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.
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.
virtual LIB_PART * LoadSymbol(const wxString &aLibraryPath, const wxString &aPartName, const PROPERTIES *aProperties=NULL)
Load a LIB_PART object having aPartName from the aLibraryPath containing a library format that this S...
Definition: sch_plugin.cpp:85
void SetParent(LIB_PART *aParent=nullptr)
Definition: lib_symbol.cpp:318
PART_REF & GetParent()
Definition: lib_symbol.h:120
void LoadSymbolLib(std::vector< LIB_PART * > &aAliasList, const wxString &aNickname, bool aPowerSymbolsOnly=false)
Define a library symbol object.
Definition: lib_symbol.h:93
std::map< wxString, LIB_BUFFER > m_libs
bool DeleteBuffer(PART_BUFFER::PTR aPartBuf)
SYMBOL_TREE_SYNCHRONIZING_ADAPTER * getAdapter()
Class to store a working copy of a LIB_PART 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.
const std::deque< PART_BUFFER::PTR > & GetBuffers() const
void GetRootSymbolNames(wxArrayString &aRootSymbolNames)
Fetch a list of root symbols names from the library buffer.
int removeChildSymbols(PART_BUFFER::PTR aPartBuf)
Remove all symbols derived from aParent from the library buffer.
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
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:470
std::set< LIB_PART * > getOriginalParts(const wxString &aLibrary)
Return a set of LIB_PART objects belonging to the original library.
LIB_ID RevertPart(const wxString &aAlias, const wxString &aLibrary)
Revert unsaved changes for a particular part.
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.
see class PGM_BASE
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.
#define _(s)
Definition: 3d_actions.cpp:33
bool IsAlias() const
Definition: lib_symbol.h:168
bool IsLibraryLoaded(const wxString &aLibrary) const
Return true if the library was successfully loaded.
void ClrModify()
Definition: base_screen.h:60
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 ...
PART_BUFFER::PTR GetBuffer(const wxString &aAlias) const
Return all buffered parts.
virtual void SaveSymbol(const wxString &aLibraryPath, const LIB_PART *aSymbol, const PROPERTIES *aProperties=NULL)
Write aSymbol to an existing library located at aLibraryPath.
Definition: sch_plugin.cpp:94
SCH_SCREEN * GetScreen(const wxString &aAlias, const wxString &aLibrary)
Return the screen used to edit a specific part.
SAVE_T
The set of return values from SaveSymbol() below.
std::list< LIB_PART * > GetAliases(const wxString &aLibrary) const
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...
Definition for part library class.
bool SaveBuffer(PART_BUFFER::PTR aPartBuf, SYMBOL_LIB_TABLE *aLibTable)
Save stored modifications using a plugin.
void SetModify()
Definition: base_screen.h:59
bool HasDerivedSymbols(const wxString &aParentName) const
Check to see any parts 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 ...
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:132
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
std::shared_ptr< PART_BUFFER > PTR
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:67
The symbol library editor main window.
bool IsPartModified(const wxString &aAlias, const wxString &aLibrary) const
Return true if part has unsaved modifications.