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( aFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY && 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  try
213  {
214  pi->SaveLibrary( aFileName );
215  }
216  catch( ... )
217  {
218  // return false because something happens.
219  // The library is not successfully saved
220  res = false;
221  }
222 
223  return res;
224 }
225 
226 
227 bool LIB_MANAGER::IsLibraryModified( const wxString& aLibrary ) const
228 {
229  auto it = m_libs.find( aLibrary );
230  return it != m_libs.end() ? it->second.IsModified() : false;
231 }
232 
233 
234 bool LIB_MANAGER::IsPartModified( const wxString& aAlias, const wxString& aLibrary ) const
235 {
236  auto libIt = m_libs.find( aLibrary );
237 
238  if( libIt == m_libs.end() )
239  return false;
240 
241  const LIB_BUFFER& buf = libIt->second;
242  auto partBuf = buf.GetBuffer( aAlias );
243  return partBuf ? partBuf->IsModified() : false;
244 }
245 
246 
247 bool LIB_MANAGER::ClearLibraryModified( const wxString& aLibrary ) const
248 {
249  auto libIt = m_libs.find( aLibrary );
250 
251  if( libIt == m_libs.end() )
252  return false;
253 
254  for( auto& partBuf : libIt->second.GetBuffers() )
255  {
256  SCH_SCREEN* screen = partBuf->GetScreen();
257 
258  if( screen )
259  screen->ClrModify();
260  }
261 
262  return true;
263 }
264 
265 
266 bool LIB_MANAGER::ClearPartModified( const wxString& aAlias, const wxString& aLibrary ) const
267 {
268  auto libI = m_libs.find( aLibrary );
269 
270  if( libI == m_libs.end() )
271  return false;
272 
273  auto partBuf = libI->second.GetBuffer( aAlias );
274  wxCHECK( partBuf, false );
275 
276  partBuf->GetScreen()->ClrModify();
277  return true;
278 }
279 
280 
281 bool LIB_MANAGER::IsLibraryReadOnly( const wxString& aLibrary ) const
282 {
283  wxCHECK( LibraryExists( aLibrary ), true );
284 
285  return !symTable()->IsSymbolLibWritable( aLibrary );
286 }
287 
288 
289 bool LIB_MANAGER::IsLibraryLoaded( const wxString& aLibrary ) const
290 {
291  wxCHECK( LibraryExists( aLibrary ), false );
292 
293  return symTable()->IsSymbolLibLoaded( aLibrary );
294 }
295 
296 
297 std::list<LIB_PART*> LIB_MANAGER::GetAliases( const wxString& aLibrary ) const
298 {
299  std::list<LIB_PART*> ret;
300  wxCHECK( LibraryExists( aLibrary ), ret );
301 
302  auto libIt = m_libs.find( aLibrary );
303 
304  if( libIt != m_libs.end() )
305  {
306  for( auto& partBuf : libIt->second.GetBuffers() )
307  {
308  ret.push_back( partBuf->GetPart() );
309  }
310  }
311  else
312  {
313  std::vector<LIB_PART*> aliases;
314 
315  try
316  {
317  symTable()->LoadSymbolLib( aliases, aLibrary );
318  }
319  catch( const IO_ERROR& e )
320  {
321  wxLogWarning( e.Problem() );
322  }
323 
324  std::copy( aliases.begin(), aliases.end(), std::back_inserter( ret ) );
325  }
326 
327  return ret;
328 }
329 
330 
331 LIB_PART* LIB_MANAGER::GetBufferedPart( const wxString& aAlias, const wxString& aLibrary )
332 {
333  wxCHECK( LibraryExists( aLibrary ), nullptr );
334 
335  // try the library buffers first
336  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
337  LIB_PART* bufferedPart = libBuf.GetPart( aAlias );
338 
339  if( !bufferedPart ) // no buffer part found
340  {
341  // create a copy of the part
342  try
343  {
344  LIB_PART* part = symTable()->LoadSymbol( aLibrary, aAlias );
345 
346  if( part == nullptr )
347  THROW_IO_ERROR( _( "Symbol not found." ) );
348 
349  LIB_PART* bufferedParent = nullptr;
350 
351  // Create parent symbols on demand so parent symbol can be set.
352  if( part->IsAlias() )
353  {
354  std::shared_ptr< LIB_PART > parent = part->GetParent().lock();
355  wxCHECK_MSG( parent, nullptr,
356  wxString::Format( "Derived symbol '%s' found with undefined parent.",
357  part->GetName() ) );
358 
359  // Check if the parent symbol buffer has already be created.
360  bufferedParent = libBuf.GetPart( parent->GetName() );
361 
362  if( !bufferedParent )
363  {
364  bufferedParent = new LIB_PART( *parent.get() );
365  libBuf.CreateBuffer( bufferedParent, new SCH_SCREEN );
366  }
367  }
368 
369  bufferedPart = new LIB_PART( *part );
370 
371  if( bufferedParent )
372  bufferedPart->SetParent( bufferedParent );
373 
374  libBuf.CreateBuffer( bufferedPart, new SCH_SCREEN );
375  }
376  catch( const IO_ERROR& e )
377  {
378  wxLogMessage( _( "Error loading symbol \"%s\" from library \"%s\". (%s)" ),
379  aAlias, aLibrary, e.What() );
380  bufferedPart = nullptr;
381  }
382  }
383 
384  return bufferedPart;
385 }
386 
387 
388 SCH_SCREEN* LIB_MANAGER::GetScreen( const wxString& aAlias, const wxString& aLibrary )
389 {
390  wxCHECK( LibraryExists( aLibrary ), nullptr );
391  wxCHECK( !aAlias.IsEmpty(), nullptr );
392  auto it = m_libs.find( aLibrary );
393  wxCHECK( it != m_libs.end(), nullptr );
394 
395  LIB_BUFFER& buf = it->second;
396  auto partBuf = buf.GetBuffer( aAlias );
397  return partBuf ? partBuf->GetScreen() : nullptr;
398 }
399 
400 
401 bool LIB_MANAGER::UpdatePart( LIB_PART* aPart, const wxString& aLibrary )
402 {
403  wxCHECK( LibraryExists( aLibrary ), false );
404  wxCHECK( aPart, false );
405  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
406  auto partBuf = libBuf.GetBuffer( aPart->GetName() );
407 
408  if( partBuf ) // Existing symbol.
409  {
410  LIB_PART* bufferedPart = const_cast< LIB_PART* >( partBuf->GetPart() );
411 
412  wxCHECK( bufferedPart, false );
413 
414  *bufferedPart = *aPart;
415  partBuf->GetScreen()->SetModify();
416  }
417  else // New symbol
418  {
419  LIB_PART* partCopy = new LIB_PART( *aPart, nullptr );
420 
421  partCopy->SetLibId( LIB_ID( aLibrary, aPart->GetLibId().GetLibItemName() ) );
422 
423  SCH_SCREEN* screen = new SCH_SCREEN;
424  libBuf.CreateBuffer( partCopy, screen );
425  screen->SetModify();
426  }
427 
428  return true;
429 }
430 
431 
432 bool LIB_MANAGER::UpdatePartAfterRename( LIB_PART* aPart, const wxString& aOldName,
433  const wxString& aLibrary )
434 {
435  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
436  auto partBuf = libBuf.GetBuffer( aOldName );
437 
438  wxCHECK( partBuf, false );
439 
440  libBuf.UpdateBuffer( partBuf, aPart );
441  SetCurrentPart( aPart->GetName() );
442  m_frame.SyncLibraries( false );
443 
444  return true;
445 }
446 
447 
448 bool LIB_MANAGER::FlushPart( const wxString& aAlias, const wxString& aLibrary )
449 {
450  auto it = m_libs.find( aLibrary );
451 
452  if( it == m_libs.end() ) // no items to flush
453  return true;
454 
455  auto partBuf = it->second.GetBuffer( aAlias );
456  wxCHECK( partBuf, false );
457 
458  return it->second.SaveBuffer( partBuf, symTable() );
459 }
460 
461 
462 LIB_ID LIB_MANAGER::RevertPart( const wxString& aAlias, const wxString& aLibrary )
463 {
464  auto it = m_libs.find( aLibrary );
465 
466  if( it == m_libs.end() ) // no items to flush
467  return LIB_ID( aLibrary, aAlias );
468 
469  auto partBuf = it->second.GetBuffer( aAlias );
470  wxCHECK( partBuf, LIB_ID( aLibrary, aAlias ) );
471  LIB_PART original( *partBuf->GetOriginal() );
472 
473  if( original.GetName() != aAlias )
474  {
475  UpdatePartAfterRename( &original, aAlias, aLibrary );
476  }
477  else
478  {
479  partBuf->SetPart( new LIB_PART( original ) );
480  m_frame.SyncLibraries( false );
481  }
482 
483  return LIB_ID( aLibrary, original.GetName() );
484 }
485 
486 
487 bool LIB_MANAGER::RevertLibrary( const wxString& aLibrary )
488 {
489  auto it = m_libs.find( aLibrary );
490 
491  if( it == m_libs.end() ) // nothing to reverse
492  return false;
493 
494  m_libs.erase( it );
495  m_frame.SyncLibraries( false );
496 
497  return true;
498 }
499 
500 
502 {
503  bool retv = true;
504 
505  // Nothing to revert.
506  if( GetHash() == 0 )
507  return true;
508 
509  for( const auto& lib : m_libs )
510  {
511  if( !lib.second.IsModified() )
512  continue;
513 
514  for( const auto& buffer : lib.second.GetBuffers() )
515  {
516  if( !buffer->IsModified() )
517  continue;
518 
519  RevertPart( lib.first, buffer->GetOriginal()->GetName() );
520  }
521  }
522 
523  return retv;
524 }
525 
526 
527 bool LIB_MANAGER::RemovePart( const wxString& aAlias, const wxString& aLibrary )
528 {
529  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
530  auto partBuf = libBuf.GetBuffer( aAlias );
531  wxCHECK( partBuf, false );
532 
533  bool retv = true;
534 
535  retv &= libBuf.DeleteBuffer( partBuf );
536  m_frame.SyncLibraries( false );
537 
538  return retv;
539 }
540 
541 
542 LIB_PART* LIB_MANAGER::GetAlias( const wxString& aAlias, const wxString& aLibrary ) const
543 {
544  // Try the library buffers first
545  auto libIt = m_libs.find( aLibrary );
546 
547  if( libIt != m_libs.end() )
548  {
549  LIB_PART* part = libIt->second.GetPart( aAlias );
550 
551  if( part )
552  return part;
553  }
554 
555  // Get the original part
556  LIB_PART* alias = nullptr;
557 
558  try
559  {
560  alias = symTable()->LoadSymbol( aLibrary, aAlias );
561  }
562  catch( const IO_ERROR& e )
563  {
564  wxLogMessage( _( "Cannot load symbol \"%s\" from library \"%s\" (%s)" ),
565  aAlias, aLibrary, e.What() );
566  }
567 
568  return alias;
569 }
570 
571 
572 bool LIB_MANAGER::PartExists( const wxString& aAlias, const wxString& aLibrary ) const
573 {
574  auto libBufIt = m_libs.find( aLibrary );
575  LIB_PART* alias = nullptr;
576 
577  if( libBufIt != m_libs.end() )
578  return !!libBufIt->second.GetBuffer( aAlias );
579 
580  try
581  {
582  alias = symTable()->LoadSymbol( aLibrary, aAlias );
583  }
584  catch( IO_ERROR& )
585  {
586  // checking if certain symbol exists, so its absence is perfectly fine
587  }
588 
589  return alias != nullptr;
590 }
591 
592 
593 bool LIB_MANAGER::LibraryExists( const wxString& aLibrary, bool aCheckEnabled ) const
594 {
595  if( aLibrary.IsEmpty() )
596  return false;
597 
598  if( m_libs.count( aLibrary ) > 0 )
599  return true;
600 
601  return symTable()->HasLibrary( aLibrary, aCheckEnabled );
602 }
603 
604 
606 {
607  wxString name = "New_Library";
608 
609  if( !LibraryExists( name ) )
610  return name;
611 
612  name += "_";
613 
614  for( unsigned int i = 0; i < std::numeric_limits<unsigned int>::max(); ++i )
615  {
616  if( !LibraryExists( name + wxString::Format( "%u", i ) ) )
617  return name + wxString::Format( "%u", i );
618  }
619 
620  wxFAIL;
621  return wxEmptyString;
622 }
623 
624 
625 void LIB_MANAGER::GetRootSymbolNames( const wxString& aLibraryName,
626  wxArrayString& aRootSymbolNames )
627 {
628  LIB_BUFFER& libBuf = getLibraryBuffer( aLibraryName );
629 
630  libBuf.GetRootSymbolNames( aRootSymbolNames );
631 }
632 
633 
634 bool LIB_MANAGER:: HasDerivedSymbols( const wxString& aSymbolName,
635  const wxString& aLibraryName )
636 {
637  LIB_BUFFER& libBuf = getLibraryBuffer( aLibraryName );
638 
639  return libBuf.HasDerivedSymbols( aSymbolName );
640 }
641 
642 
643 wxString LIB_MANAGER::getLibraryName( const wxString& aFilePath )
644 {
645  wxFileName fn( aFilePath );
646  return fn.GetName();
647 }
648 
649 
650 bool LIB_MANAGER::addLibrary( const wxString& aFilePath, bool aCreate, SYMBOL_LIB_TABLE* aTable )
651 {
652  wxCHECK( aTable, false );
653  wxString libName = getLibraryName( aFilePath );
654  wxCHECK( !LibraryExists( libName ), false ); // either create or add an existing one
655 
656  // try to use path normalized to an environmental variable or project path
657  wxString relPath = NormalizePath( aFilePath, &Pgm().GetLocalEnvVariables(), &m_frame.Prj() );
658 
659  if( relPath.IsEmpty() )
660  relPath = aFilePath;
661 
662  SCH_IO_MGR::SCH_FILE_T schFileType = SCH_IO_MGR::GuessPluginTypeFromLibPath( aFilePath );
663  wxString typeName = SCH_IO_MGR::ShowType( schFileType );
664  SYMBOL_LIB_TABLE_ROW* libRow = new SYMBOL_LIB_TABLE_ROW( libName, relPath, typeName );
665  aTable->InsertRow( libRow );
666 
667  if( aCreate )
668  {
669  wxCHECK( schFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY, false );
670 
671  try
672  {
673  aTable->CreateSymbolLib( libName );
674  }
675  catch( const IO_ERROR& )
676  {
677  aTable->RemoveRow( libRow );
678  return false;
679  }
680  }
681 
682  m_frame.SyncLibraries( false );
683 
684  return true;
685 }
686 
687 
689 {
690  return m_frame.Prj().SchSymbolLibTable();
691 }
692 
693 
694 std::set<LIB_PART*> LIB_MANAGER::getOriginalParts( const wxString& aLibrary )
695 {
696  std::set<LIB_PART*> parts;
697  wxCHECK( LibraryExists( aLibrary ), parts );
698 
699  try
700  {
701  wxArrayString aliases;
702  symTable()->EnumerateSymbolLib( aLibrary, aliases );
703 
704  for( const auto& aliasName : aliases )
705  {
706  LIB_PART* alias = symTable()->LoadSymbol( aLibrary, aliasName );
707  parts.insert( alias );
708  }
709  }
710  catch( const IO_ERROR& e )
711  {
712  wxLogMessage( _( "Cannot enumerate library \"%s\" (%s)" ), aLibrary, e.What() );
713  }
714 
715  return parts;
716 }
717 
718 
720 {
721  auto it = m_libs.find( aLibrary );
722 
723  if( it != m_libs.end() )
724  return it->second;
725 
726  // The requested buffer does not exist yet, so create one
727  auto ret = m_libs.emplace( aLibrary, LIB_BUFFER( aLibrary ) );
728  LIB_BUFFER& buf = ret.first->second;
729 
730  for( auto part : getOriginalParts( aLibrary ) )
731  {
732  LIB_PART* newSymbol;
733 
734  if( part->IsAlias() )
735  {
736  std::shared_ptr< LIB_PART > oldParent = part->GetParent().lock();
737 
738  wxCHECK_MSG( oldParent, buf,
739  wxString::Format( "Derived symbol '%s' found with undefined parent.",
740  part->GetName() ) );
741 
742  LIB_PART* libParent = buf.GetPart( oldParent->GetName() );
743 
744  if( !libParent )
745  {
746  libParent = new LIB_PART( *oldParent.get() );
747  buf.CreateBuffer( libParent, new SCH_SCREEN );
748  }
749 
750  newSymbol = new LIB_PART( *part );
751  newSymbol->SetParent( libParent );
752  buf.CreateBuffer( newSymbol, new SCH_SCREEN );
753  }
754  else if( !buf.GetPart( part->GetName() ) )
755  {
756  buf.CreateBuffer( new LIB_PART( *part ), new SCH_SCREEN );
757  }
758  }
759 
760  return buf;
761 }
762 
763 
764 LIB_MANAGER::PART_BUFFER::PART_BUFFER( LIB_PART* aPart, std::unique_ptr<SCH_SCREEN> aScreen ) :
765  m_screen( std::move( aScreen ) ),
766  m_part( aPart )
767 {
768  m_original = new LIB_PART( *aPart );
769 }
770 
771 
773 {
774  delete m_part;
775  delete m_original;
776 }
777 
778 
780 {
781  wxCHECK( m_part != aPart, /* void */ );
782  wxASSERT( aPart );
783  delete m_part;
784  m_part = aPart;
785 
786  // If the part moves libraries then the original moves with it
787  if( m_original->GetLibId().GetLibNickname() != m_part->GetLibId().GetLibNickname() )
788  {
789  m_original->SetLibId( LIB_ID( m_part->GetLibId().GetLibNickname(),
790  m_original->GetLibId().GetLibItemName() ) );
791  }
792 }
793 
794 
796 {
797  wxCHECK( m_original != aPart, /* void */ );
798  wxASSERT( aPart );
799  delete m_original;
800  m_original = aPart;
801 
802  // The original is not allowed to have a different library than its part
803  if( m_original->GetLibId().GetLibNickname() != m_part->GetLibId().GetLibNickname() )
804  {
805  m_original->SetLibId( LIB_ID( m_part->GetLibId().GetLibNickname(),
806  m_original->GetLibId().GetLibItemName() ) );
807  }
808 }
809 
810 
812 {
813  return m_screen && m_screen->IsModify();
814 }
815 
816 
817 LIB_PART* LIB_MANAGER::LIB_BUFFER::GetPart( const wxString& aAlias ) const
818 {
819  auto buf = GetBuffer( aAlias );
820 
821  if( !buf )
822  return nullptr;
823 
824  LIB_PART* part = buf->GetPart();
825 
826  wxCHECK( part, nullptr );
827 
828  return part;
829 }
830 
831 
833 {
834  wxASSERT( aCopy );
835  wxASSERT( aCopy->GetLib() == nullptr );
836  std::unique_ptr<SCH_SCREEN> screen( aScreen );
837  auto partBuf = std::make_shared<PART_BUFFER>( aCopy, std::move( screen ) );
838  m_parts.push_back( partBuf );
839 
840  // Set the parent library name,
841  // otherwise it is empty as no library has been given as the owner during object construction
842  LIB_ID libId = aCopy->GetLibId();
843  libId.SetLibNickname( m_libName );
844  aCopy->SetLibId( libId );
845  ++m_hash;
846 
847  return true;
848 }
849 
850 
852  LIB_PART* aCopy )
853 {
854  wxCHECK( aCopy && aPartBuf, false );
855 
856  LIB_PART* bufferedPart = aPartBuf->GetPart();
857 
858  wxCHECK( bufferedPart, false );
859 
860  *bufferedPart = *aCopy;
861  ++m_hash;
862 
863  return true;
864 }
865 
866 
868 {
869  auto partBufIt = std::find( m_parts.begin(), m_parts.end(), aPartBuf );
870  wxCHECK( partBufIt != m_parts.end(), false );
871 
872  bool retv = true;
873 
874  // Remove all derived symbols to prevent broken inheritance.
875  if( aPartBuf->GetPart()->IsRoot() && HasDerivedSymbols( aPartBuf->GetPart()->GetName() )
876  && removeChildSymbols( aPartBuf ) == 0 )
877  retv = false;
878 
879  m_deleted.emplace_back( *partBufIt );
880  m_parts.erase( partBufIt );
881  ++m_hash;
882 
883  return retv;
884 }
885 
886 
888  SYMBOL_LIB_TABLE* aLibTable )
889 {
890  wxCHECK( aPartBuf, false );
891  LIB_PART* part = aPartBuf->GetPart();
892  wxCHECK( part, false );
894 
895  if( part->IsAlias() )
896  {
897  LIB_PART* originalPart;
898  LIB_PART* newCachedPart = new LIB_PART( *part );
899  std::shared_ptr< LIB_PART > bufferedParent = part->GetParent().lock();
900 
901  wxCHECK( bufferedParent, false );
902 
903  LIB_PART* cachedParent = aLibTable->LoadSymbol( m_libName, bufferedParent->GetName() );
904 
905  if( !cachedParent )
906  {
907  cachedParent = new LIB_PART( *bufferedParent.get() );
908  newCachedPart->SetParent( cachedParent );
909  result = aLibTable->SaveSymbol( m_libName, cachedParent );
910  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
911  result = aLibTable->SaveSymbol( m_libName, newCachedPart );
912  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
913 
914  LIB_PART* originalParent = new LIB_PART( *bufferedParent.get() );
915  aPartBuf->SetOriginal( originalParent );
916  originalPart = new LIB_PART( *part );
917  originalPart->SetParent( originalParent );
918  aPartBuf->SetOriginal( originalPart );
919  }
920  else
921  {
922  newCachedPart->SetParent( cachedParent );
923  result = aLibTable->SaveSymbol( m_libName, newCachedPart );
924  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
925 
926  LIB_MANAGER::PART_BUFFER::PTR originalBufferedParent =
927  GetBuffer( bufferedParent->GetName() );
928  wxCHECK( originalBufferedParent, false );
929  originalPart = new LIB_PART( *part );
930  originalPart->SetParent( originalBufferedParent->GetPart() );
931  aPartBuf->SetOriginal( originalPart );
932  }
933  }
934  else
935  {
936  wxArrayString derivedSymbols;
937 
938  if( GetDerivedSymbolNames( part->GetName(), derivedSymbols ) == 0 )
939  {
940  result = aLibTable->SaveSymbol( m_libName, new LIB_PART( *part ) );
941  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
942  aPartBuf->SetOriginal( new LIB_PART( *part ) );
943  }
944  else
945  {
946  LIB_PART* parentSymbol = new LIB_PART( *part );
947 
948  aLibTable->SaveSymbol( m_libName, parentSymbol );
949 
950  for( auto entry : derivedSymbols )
951  {
952  LIB_MANAGER::PART_BUFFER::PTR symbol = GetBuffer( entry );
953  LIB_PART* derivedSymbol = new LIB_PART( *symbol->GetPart() );
954  derivedSymbol->SetParent( parentSymbol );
955  result = aLibTable->SaveSymbol( m_libName, derivedSymbol );
956  wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
957  }
958  }
959  }
960 
961  ++m_hash;
962  return true;
963 }
964 
965 
967  SCH_PLUGIN* aPlugin, bool aBuffer )
968 {
969  wxCHECK( aPartBuf, false );
970  LIB_PART* part = aPartBuf->GetPart();
971  wxCHECK( part, false );
972 
973  wxString errorMsg = _( "An error \"%s\" occurred saving symbol \"%s\" to library \"%s\"" );
974 
975  // set properties to prevent save file on every symbol save
976  PROPERTIES properties;
977  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
978 
979  if( part->IsAlias() )
980  {
981  LIB_PART* originalPart;
982  LIB_PART* newCachedPart = new LIB_PART( *part );
983  std::shared_ptr< LIB_PART > bufferedParent = part->GetParent().lock();
984 
985  wxCHECK( bufferedParent, false );
986 
987  LIB_PART* cachedParent = nullptr;
988 
989  try
990  {
991  cachedParent = aPlugin->LoadSymbol( m_libName, bufferedParent->GetName() );
992  }
993  catch( const IO_ERROR& )
994  {
995  return false;
996  }
997 
998  if( !cachedParent )
999  {
1000  cachedParent = new LIB_PART( *bufferedParent.get() );
1001  newCachedPart->SetParent( cachedParent );
1002 
1003  try
1004  {
1005  aPlugin->SaveSymbol( m_libName, cachedParent, aBuffer ? &properties : nullptr );
1006  }
1007  catch( const IO_ERROR& ioe )
1008  {
1009  wxLogError( errorMsg, ioe.What(), cachedParent->GetName() );
1010  return false;
1011  }
1012 
1013  try
1014  {
1015  aPlugin->SaveSymbol( m_libName, newCachedPart, aBuffer ? &properties : nullptr );
1016  }
1017  catch( const IO_ERROR& ioe )
1018  {
1019  wxLogError( errorMsg, ioe.What(), newCachedPart->GetName() );
1020  return false;
1021  }
1022 
1023  LIB_PART* originalParent = new LIB_PART( *bufferedParent.get() );
1024  aPartBuf->SetOriginal( originalParent );
1025  originalPart = new LIB_PART( *part );
1026  originalPart->SetParent( originalParent );
1027  aPartBuf->SetOriginal( originalPart );
1028  }
1029  else
1030  {
1031  newCachedPart->SetParent( cachedParent );
1032 
1033  try
1034  {
1035  aPlugin->SaveSymbol( m_libName, newCachedPart, aBuffer ? &properties : nullptr );
1036  }
1037  catch( const IO_ERROR& ioe )
1038  {
1039  wxLogError( errorMsg, ioe.What(), newCachedPart->GetName() );
1040  return false;
1041  }
1042 
1043  LIB_MANAGER::PART_BUFFER::PTR originalBufferedParent =
1044  GetBuffer( bufferedParent->GetName() );
1045  wxCHECK( originalBufferedParent, false );
1046  originalPart = new LIB_PART( *part );
1047  originalPart->SetParent( originalBufferedParent->GetPart() );
1048  aPartBuf->SetOriginal( originalPart );
1049  }
1050  }
1051  else
1052  {
1053  wxArrayString derivedSymbols;
1054 
1055  if( GetDerivedSymbolNames( part->GetName(), derivedSymbols ) == 0 )
1056  {
1057  try
1058  {
1059  aPlugin->SaveSymbol( m_libName, new LIB_PART( *part ),
1060  aBuffer ? &properties : nullptr );
1061  }
1062  catch( const IO_ERROR& ioe )
1063  {
1064  wxLogError( errorMsg, ioe.What(), part->GetName() );
1065  return false;
1066  }
1067 
1068  aPartBuf->SetOriginal( new LIB_PART( *part ) );
1069  }
1070  else
1071  {
1072  LIB_PART* parentSymbol = new LIB_PART( *part );
1073 
1074  // Save the modified root symbol.
1075  try
1076  {
1077  aPlugin->SaveSymbol( m_libName, parentSymbol, aBuffer ? &properties : nullptr );
1078  }
1079  catch( const IO_ERROR& ioe )
1080  {
1081  wxLogError( errorMsg, ioe.What(), part->GetName() );
1082  return false;
1083  }
1084 
1085  aPartBuf->SetOriginal( new LIB_PART( *part ) );
1086 
1087  // Save the derived symbols.
1088  for( auto entry : derivedSymbols )
1089  {
1090  LIB_MANAGER::PART_BUFFER::PTR symbol = GetBuffer( entry );
1091  LIB_PART* derivedSymbol = new LIB_PART( *symbol->GetPart() );
1092  derivedSymbol->SetParent( parentSymbol );
1093 
1094  try
1095  {
1096  aPlugin->SaveSymbol( m_libName, new LIB_PART( *derivedSymbol ),
1097  aBuffer ? &properties : nullptr );
1098  }
1099  catch( const IO_ERROR& ioe )
1100  {
1101  wxLogError( errorMsg, ioe.What(), derivedSymbol->GetName() );
1102  return false;
1103  }
1104  }
1105  }
1106  }
1107 
1108  ++m_hash;
1109  return true;
1110 }
1111 
1112 
1114 {
1115  for( auto entry : m_parts )
1116  {
1117  if( entry->GetPart()->GetName() == aAlias )
1118  return entry;
1119  }
1120 
1121  return PART_BUFFER::PTR( nullptr );
1122 }
1123 
1124 
1125 bool LIB_MANAGER::LIB_BUFFER::HasDerivedSymbols( const wxString& aParentName ) const
1126 {
1127  for( auto entry : m_parts )
1128  {
1129  if( entry->GetPart()->IsAlias() )
1130  {
1131  PART_SPTR parent = entry->GetPart()->GetParent().lock();
1132 
1133  // Check for inherited part without a valid parent.
1134  wxCHECK( parent, false );
1135 
1136  if( parent->GetName() == aParentName )
1137  return true;
1138  }
1139  }
1140 
1141  return false;
1142 }
1143 
1144 
1145 void LIB_MANAGER::LIB_BUFFER::GetRootSymbolNames( wxArrayString& aRootSymbolNames )
1146 {
1147  for( auto entry : m_parts )
1148  {
1149  if( entry->GetPart()->IsAlias() )
1150  continue;
1151 
1152  aRootSymbolNames.Add( entry->GetPart()->GetName() );
1153  }
1154 }
1155 
1156 
1157 size_t LIB_MANAGER::LIB_BUFFER::GetDerivedSymbolNames( const wxString& aSymbolName,
1158  wxArrayString& aList )
1159 {
1160  wxCHECK( !aSymbolName.IsEmpty(), 0 );
1161 
1162  for( auto entry : m_parts )
1163  {
1164  if( entry->GetPart()->IsAlias() )
1165  {
1166  PART_SPTR parent = entry->GetPart()->GetParent().lock();
1167 
1168  // Check for inherited part without a valid parent.
1169  wxCHECK( parent, false );
1170 
1171  if( parent->GetName() == aSymbolName )
1172  aList.Add( entry->GetPart()->GetName() );
1173  }
1174  }
1175 
1176  return aList.GetCount();
1177 }
1178 
1179 
1181 {
1182  wxCHECK( aPartBuf && aPartBuf->GetPart()->IsRoot(), 0 );
1183 
1184  int cnt = 0;
1185  std::deque< LIB_MANAGER::PART_BUFFER::PTR >::iterator it = m_parts.begin();
1186 
1187  while( it != m_parts.end() )
1188  {
1189 
1190  if( (*it)->GetPart()->IsRoot() )
1191  {
1192  ++it;
1193  }
1194  else
1195  {
1196  PART_SPTR parent = (*it)->GetPart()->GetParent().lock();
1197 
1198  wxCHECK2( parent, ++it; continue );
1199 
1200  if( parent->GetName() == aPartBuf->GetPart()->GetName() )
1201  {
1202  wxCHECK2( parent == aPartBuf->GetPart()->SharedPtr(), ++it; continue );
1203 
1204  m_deleted.emplace_back( *it );
1205  it = m_parts.erase( it );
1206  cnt++;
1207  }
1208  else
1209  {
1210  ++it;
1211  }
1212  }
1213  }
1214 
1215  return cnt;
1216 }
PART_LIB * GetLib()
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:161
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...
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:104
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:84
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.
bool IsLibraryLoaded(const wxString &aLibrary) const
Returns true if the library was successfully loaded.
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:411
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
bool IsSymbolLibWritable(const wxString &aNickname)
Return true if the library given by aNickname is writable.
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:45
bool DeleteBuffer(PART_BUFFER::PTR aPartBuf)
bool IsSymbolLibLoaded(const wxString &aNickname)
Return true if the library given by aNickname was successfully loaded.
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:152
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:29
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.
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:467
LIB_LOGGER m_logger
Definition: lib_manager.h:468
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:474
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.
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:359
void SetCurrentPart(const wxString &aPart)
Definition: lib_manager.h:288
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:469
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:201
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:101
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:347
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:465
Definition for part library class.
void SetModify()
Definition: base_screen.h:100
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
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
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:475