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