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  * @author Maciej Suminski <maciej.suminski@cern.ch>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * https://www.gnu.org/licenses/gpl-3.0.html
20  * or you may search the http://www.gnu.org website for the version 3 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <lib_manager.h>
26 #include <class_libentry.h>
27 #include <class_library.h>
28 #include <lib_edit_frame.h>
29 #include <confirm.h>
30 #include <env_paths.h>
31 #include <pgm_base.h>
32 #include <kiway.h>
33 #include <profile.h>
34 #include <symbol_lib_table.h>
35 #include <sch_legacy_plugin.h>
36 #include <list>
37 
38 
40  : m_frame( aFrame ), m_syncHash( 0 )
41 {
43  m_adapter->ShowUnits( false );
44 }
45 
46 
47 void LIB_MANAGER::Sync( bool aForce, std::function<void(int, int, const wxString&)> aProgressCallback )
48 {
49  int libTableHash = symTable()->GetModifyHash();
50 
51  if( aForce || m_syncHash != libTableHash )
52  {
53  getAdapter()->Sync( aForce, aProgressCallback );
54  m_syncHash = libTableHash;
55  }
56 }
57 
58 
60 {
61  int hash = symTable()->GetModifyHash();
62 
63  for( const auto& libBuf : m_libs )
64  hash += libBuf.second.GetHash();
65 
66  return hash;
67 }
68 
69 
70 int LIB_MANAGER::GetLibraryHash( const wxString& aLibrary ) const
71 {
72  const auto libBufIt = m_libs.find( aLibrary );
73 
74  if( libBufIt != m_libs.end() )
75  return libBufIt->second.GetHash();
76 
77  auto row = GetLibrary( aLibrary );
78 
79  // return -1 if library does not exist or 0 if not modified
80  return row ? std::hash<std::string>{}( aLibrary.ToStdString() + row->GetFullURI( true ).ToStdString() ) : -1;
81 }
82 
83 
84 wxArrayString LIB_MANAGER::GetLibraryNames() const
85 {
86  wxArrayString res;
87 
88  for( const auto& libName : symTable()->GetLogicalLibs() )
89  res.Add( libName );
90 
91  return res;
92 }
93 
94 
95 SYMBOL_LIB_TABLE_ROW* LIB_MANAGER::GetLibrary( const wxString& aLibrary ) const
96 {
97  SYMBOL_LIB_TABLE_ROW* row = nullptr;
98 
99  try
100  {
101  row = symTable()->FindRow( aLibrary );
102  }
103  catch( const IO_ERROR& e )
104  {
105  DisplayErrorMessage( &m_frame, wxString::Format( _( "Cannot find library \"%s\" in "
106  "the Symbol Library Table" ), aLibrary ), e.What() );
107  }
108 
109  return row;
110 }
111 
112 
114 {
115  bool result = true;
116 
117  for( auto& libBuf : m_libs )
118  result &= FlushLibrary( libBuf.first );
119 
120  return result;
121 }
122 
123 
124 bool LIB_MANAGER::FlushLibrary( const wxString& aLibrary )
125 {
126  auto it = m_libs.find( aLibrary );
127 
128  if( it == m_libs.end() ) // no changes to flush
129  return true;
130 
131  LIB_BUFFER& libBuf = it->second;
132  wxArrayString aliases;
133 
134  try
135  {
136  symTable()->EnumerateSymbolLib( aLibrary, aliases );
137 
138  // TODO probably this could be implemented more efficiently
139  for( const auto& alias : aliases )
140  symTable()->DeleteAlias( aLibrary, alias );
141  }
142  catch( const IO_ERROR& e )
143  {
144  DisplayErrorMessage( &m_frame, wxString::Format( _( "Cannot flush "
145  "library changes (\"%s\")" ), aLibrary ), e.What() );
146  }
147 
148  // Assume all libraries are successfully saved
149  bool res = true;
150 
151  for( const auto& partBuf : libBuf.GetBuffers() )
152  {
153  if( !libBuf.SaveBuffer( partBuf, symTable() ) )
154  {
155  // Something went wrong but try to save other libraries
156  res = false;
157  }
158  }
159 
160  if( res )
161  libBuf.ClearDeletedBuffer();
162 
163  return res;
164 }
165 
166 
167 bool LIB_MANAGER::SaveLibrary( const wxString& aLibrary, const wxString& aFileName )
168 {
169  wxCHECK( LibraryExists( aLibrary ), false );
170  wxFileName fn( aFileName );
171  wxCHECK( !fn.FileExists() || fn.IsFileWritable(), false );
172  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
173  bool res = true; // assume all libraries are successfully saved
174 
175  auto it = m_libs.find( aLibrary );
176 
177  if( it != m_libs.end() )
178  {
179  // Handle buffered library
180  LIB_BUFFER& libBuf = it->second;
181 
182  const auto& partBuffers = libBuf.GetBuffers();
183 
184  for( const auto& partBuf : partBuffers )
185  {
186  if( !libBuf.SaveBuffer( partBuf, &*pi, true ) )
187  {
188  // Something went wrong, but try to save other libraries
189  res = false;
190  }
191  }
192 
193  // clear the deleted parts buffer only if data is saved to the original file
194  wxFileName original, destination( aFileName );
195  auto row = GetLibrary( aLibrary );
196 
197  if( row )
198  {
199  original = row->GetFullURI( true );
200  original.Normalize();
201  }
202 
203  destination.Normalize();
204 
205  if( res && original == destination )
206  libBuf.ClearDeletedBuffer();
207  }
208  else
209  {
210  // Handle original library
211  PROPERTIES properties;
212  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
213 
214  for( auto part : getOriginalParts( aLibrary ) )
215  pi->SaveSymbol( aLibrary, new LIB_PART( *part ), &properties );
216  }
217 
218  pi->SaveLibrary( aFileName );
219  return res;
220 }
221 
222 
223 bool LIB_MANAGER::IsLibraryModified( const wxString& aLibrary ) const
224 {
225  auto it = m_libs.find( aLibrary );
226  return it != m_libs.end() ? it->second.IsModified() : false;
227 }
228 
229 
230 bool LIB_MANAGER::IsPartModified( const wxString& aAlias, const wxString& aLibrary ) const
231 {
232  auto libIt = m_libs.find( aLibrary );
233 
234  if( libIt == m_libs.end() )
235  return false;
236 
237  const LIB_BUFFER& buf = libIt->second;
238  auto partBuf = buf.GetBuffer( aAlias );
239  return partBuf ? partBuf->IsModified() : false;
240 }
241 
242 
243 bool LIB_MANAGER::ClearLibraryModified( const wxString& aLibrary ) const
244 {
245  auto libIt = m_libs.find( aLibrary );
246 
247  if( libIt == m_libs.end() )
248  return false;
249 
250  for( auto& partBuf : libIt->second.GetBuffers() )
251  {
252  SCH_SCREEN* screen = partBuf->GetScreen();
253 
254  if( screen )
255  screen->ClrModify();
256  }
257 
258  return true;
259 }
260 
261 
262 bool LIB_MANAGER::ClearPartModified( const wxString& aAlias, const wxString& aLibrary ) const
263 {
264  auto libI = m_libs.find( aLibrary );
265 
266  if( libI == m_libs.end() )
267  return false;
268 
269  auto partBuf = libI->second.GetBuffer( aAlias );
270  wxCHECK( partBuf, false );
271 
272  partBuf->GetScreen()->ClrModify();
273  return true;
274 }
275 
276 
277 bool LIB_MANAGER::IsLibraryReadOnly( const wxString& aLibrary ) const
278 {
279  wxCHECK( LibraryExists( aLibrary ), true );
280  wxFileName fn( symTable()->GetFullURI( aLibrary ) );
281  return ( fn.FileExists() && !fn.IsFileWritable() ) || !fn.IsDirWritable();
282 }
283 
284 
285 wxArrayString LIB_MANAGER::GetAliasNames( const wxString& aLibrary ) const
286 {
287  wxArrayString names;
288  wxCHECK( LibraryExists( aLibrary ), names );
289 
290  auto it = m_libs.find( aLibrary );
291 
292  if( it == m_libs.end() )
293  {
294  try
295  {
296  symTable()->EnumerateSymbolLib( aLibrary, names );
297  }
298  catch( const IO_ERROR& e )
299  {
300  DisplayErrorMessage( &m_frame, wxString::Format( _( "Cannot enumerate "
301  "library \"%s\"" ), aLibrary ), e.What() );
302  }
303  }
304  else
305  {
306  names = it->second.GetAliasNames();
307  }
308 
309  return names;
310 }
311 
312 
313 std::list<LIB_ALIAS*> LIB_MANAGER::GetAliases( const wxString& aLibrary ) const
314 {
315  std::list<LIB_ALIAS*> ret;
316  wxCHECK( LibraryExists( aLibrary ), ret );
317 
318  auto libIt = m_libs.find( aLibrary );
319 
320  if( libIt != m_libs.end() )
321  {
322  for( auto& partBuf : libIt->second.GetBuffers() )
323  {
324  for( unsigned int i = 0; i < partBuf->GetPart()->GetAliasCount(); ++i )
325  ret.push_back( partBuf->GetPart()->GetAlias( i ) );
326  }
327  }
328  else
329  {
330  std::vector<LIB_ALIAS*> aliases;
331 
332  try
333  {
334  symTable()->LoadSymbolLib( aliases, aLibrary );
335  }
336  catch( const IO_ERROR& e )
337  {
338  DisplayErrorMessage( &m_frame, wxString::Format( _( "Cannot load "
339  "aliases from library \"%s\"" ), aLibrary ), e.What() );
340  }
341 
342  std::copy( aliases.begin(), aliases.end(), std::back_inserter( ret ) );
343  }
344 
345  return ret;
346 }
347 
348 
349 LIB_PART* LIB_MANAGER::GetBufferedPart( const wxString& aAlias, const wxString& aLibrary )
350 {
351  wxCHECK( LibraryExists( aLibrary ), nullptr );
352 
353  // try the library buffers first
354  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
355  LIB_PART* bufferedPart = libBuf.GetPart( aAlias );
356 
357  if( !bufferedPart ) // no buffer part found
358  {
359  // create a copy of the part
360  try
361  {
362  LIB_ALIAS* alias = symTable()->LoadSymbol( aLibrary, aAlias );
363 
364  if( alias == nullptr )
365  THROW_IO_ERROR( _( "Symbol not found." ) );
366 
367  bufferedPart = new LIB_PART( *alias->GetPart(), nullptr );
368  libBuf.CreateBuffer( bufferedPart, new SCH_SCREEN( &m_frame.Kiway() ) );
369  }
370  catch( const IO_ERROR& e )
371  {
372  wxString msg = wxString::Format( _( "Error loading symbol \"%s\" from library \"%s\"." ),
373  aAlias,
374  aLibrary);
375  DisplayErrorMessage( &m_frame, msg, e.What() );
376 
377  bufferedPart = nullptr;
378  }
379  }
380 
381  return bufferedPart;
382 }
383 
384 
385 SCH_SCREEN* LIB_MANAGER::GetScreen( const wxString& aAlias, const wxString& aLibrary )
386 {
387  wxCHECK( LibraryExists( aLibrary ), nullptr );
388  wxCHECK( !aAlias.IsEmpty(), nullptr );
389  auto it = m_libs.find( aLibrary );
390  wxCHECK( it != m_libs.end(), nullptr );
391 
392  LIB_BUFFER& buf = it->second;
393  auto partBuf = buf.GetBuffer( aAlias );
394  return partBuf ? partBuf->GetScreen() : nullptr;
395 }
396 
397 
398 bool LIB_MANAGER::UpdatePart( LIB_PART* aPart, const wxString& aLibrary )
399 {
400  wxCHECK( LibraryExists( aLibrary ), false );
401  wxCHECK( aPart, false );
402  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
403  auto partBuf = libBuf.GetBuffer( aPart->GetName() );
404  LIB_PART* partCopy = new LIB_PART( *aPart, nullptr );
405 
406  partCopy->SetLibId( LIB_ID( aLibrary, aPart->GetLibId().GetLibItemName() ) );
407 
408  if( partBuf )
409  {
410  libBuf.UpdateBuffer( partBuf, partCopy );
411  }
412  else // New entry
413  {
414  SCH_SCREEN* screen = new SCH_SCREEN( &m_frame.Kiway() );
415  libBuf.CreateBuffer( partCopy, screen );
416  screen->SetModify();
417  }
418 
419  return true;
420 }
421 
422 
423 bool LIB_MANAGER::UpdatePartAfterRename( LIB_PART* aPart, const wxString& oldAlias,
424  const wxString& aLibrary )
425 {
426  // This is essentially a delete/update.
427 
428  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
429  auto partBuf = libBuf.GetBuffer( oldAlias );
430  wxCHECK( partBuf, false );
431 
432  // Save the original record so it is transferred to the new buffer
433  std::unique_ptr<LIB_PART> original( new LIB_PART( *partBuf->GetOriginal() ) );
434 
435  // Save the screen object, so it is transferred to the new buffer
436  std::unique_ptr<SCH_SCREEN> screen = partBuf->RemoveScreen();
437 
438  if( !libBuf.DeleteBuffer( partBuf ) )
439  return false;
440 
441  if( !UpdatePart( aPart, aLibrary ) )
442  return false;
443 
444  partBuf = libBuf.GetBuffer( aPart->GetName() );
445  partBuf->SetScreen( std::move( screen ) );
446  wxCHECK( partBuf, false );
447  partBuf->SetOriginal( original.release() ); // part buffer takes ownership of pointer
448 
449  m_frame.SyncLibraries( false );
450 
451  return true;
452 }
453 
454 
455 bool LIB_MANAGER::FlushPart( const wxString& aAlias, const wxString& aLibrary )
456 {
457  auto it = m_libs.find( aLibrary );
458 
459  if( it == m_libs.end() ) // no items to flush
460  return true;
461 
462  auto partBuf = it->second.GetBuffer( aAlias );
463  wxCHECK( partBuf, false );
464 
465  return it->second.SaveBuffer( partBuf, symTable() );
466 }
467 
468 
469 LIB_ID LIB_MANAGER::RevertPart( const wxString& aAlias, const wxString& aLibrary )
470 {
471  auto it = m_libs.find( aLibrary );
472 
473  if( it == m_libs.end() ) // no items to flush
474  return LIB_ID( aLibrary, aAlias );
475 
476  auto partBuf = it->second.GetBuffer( aAlias );
477  wxCHECK( partBuf, LIB_ID( aLibrary, aAlias ) );
478  LIB_PART original( *partBuf->GetOriginal() );
479 
480  if( original.GetName() != aAlias )
481  {
482  UpdatePartAfterRename( &original, aAlias, aLibrary );
483  }
484  else
485  {
486  partBuf->SetPart( new LIB_PART( original ) );
487  m_frame.SyncLibraries( false );
488  }
489 
490  return LIB_ID( aLibrary, original.GetName() );
491 }
492 
493 
494 bool LIB_MANAGER::RevertLibrary( const wxString& aLibrary )
495 {
496  auto it = m_libs.find( aLibrary );
497 
498  if( it == m_libs.end() ) // nothing to reverse
499  return false;
500 
501  m_libs.erase( it );
502  m_frame.SyncLibraries( false );
503 
504  return true;
505 }
506 
507 
508 bool LIB_MANAGER::RemovePart( const wxString& aAlias, const wxString& aLibrary )
509 {
510  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
511  auto partBuf = libBuf.GetBuffer( aAlias );
512  wxCHECK( partBuf, false );
513 
514  bool res = libBuf.DeleteBuffer( partBuf );
515  m_frame.SyncLibraries( false );
516 
517  return res;
518 }
519 
520 
521 LIB_ALIAS* LIB_MANAGER::GetAlias( const wxString& aAlias, const wxString& aLibrary ) const
522 {
523  // Try the library buffers first
524  auto libIt = m_libs.find( aLibrary );
525 
526  if( libIt != m_libs.end() )
527  {
528  LIB_PART* part = libIt->second.GetPart( aAlias );
529 
530  if( part )
531  return part->GetAlias( aAlias );
532  }
533 
534  // Get the original part
535  LIB_ALIAS* alias = nullptr;
536 
537  try
538  {
539  alias = symTable()->LoadSymbol( aLibrary, aAlias );
540  }
541  catch( const IO_ERROR& e )
542  {
543  DisplayErrorMessage( &m_frame, wxString::Format( _( "Cannot load "
544  "symbol \"%s\" from library \"%s\"" ), aAlias, aLibrary ), e.What() );
545  }
546 
547  return alias;
548 }
549 
550 
551 bool LIB_MANAGER::PartExists( const wxString& aAlias, const wxString& aLibrary ) const
552 {
553  auto libBufIt = m_libs.find( aLibrary );
554  LIB_ALIAS* alias = nullptr;
555 
556  if( libBufIt != m_libs.end() )
557  return !!libBufIt->second.GetBuffer( aAlias );
558 
559  try
560  {
561  alias = symTable()->LoadSymbol( aLibrary, aAlias );
562  } catch( IO_ERROR& )
563  {
564  // checking if certain symbol exists, so its absence is perfectly fine
565  }
566 
567  return alias != nullptr;
568 }
569 
570 
571 bool LIB_MANAGER::LibraryExists( const wxString& aLibrary, bool aCheckEnabled ) const
572 {
573  if( aLibrary.IsEmpty() )
574  return false;
575 
576  if( m_libs.count( aLibrary ) > 0 )
577  return true;
578 
579  return symTable()->HasLibrary( aLibrary, aCheckEnabled );
580 }
581 
583 {
584  wxString name = "New_Library";
585 
586  if( !LibraryExists( name ) )
587  return name;
588 
589  name += "_";
590 
591  for( unsigned int i = 0; i < std::numeric_limits<unsigned int>::max(); ++i )
592  {
593  if( !LibraryExists( name + wxString::Format( "%u", i ) ) )
594  return name + wxString::Format( "%u", i );
595  }
596 
597  wxFAIL;
598  return wxEmptyString;
599 }
600 
601 
602 wxString LIB_MANAGER::GetUniqueComponentName( const wxString& aLibrary ) const
603 {
604  wxString name = "New_Component";
605 
606  if( !PartExists( name, aLibrary ) )
607  return name;
608 
609  name += "_";
610 
611  for( unsigned int i = 0; i < std::numeric_limits<unsigned int>::max(); ++i )
612  {
613  if( !PartExists( name + wxString::Format( "%u", i ), aLibrary ) )
614  return name + wxString::Format( "%u", i );
615  }
616 
617  wxFAIL;
618  return wxEmptyString;
619 }
620 
621 
622 wxString LIB_MANAGER::getLibraryName( const wxString& aFilePath )
623 {
624  wxFileName fn( aFilePath );
625  return fn.GetName();
626 }
627 
628 
629 bool LIB_MANAGER::addLibrary( const wxString& aFilePath, bool aCreate, SYMBOL_LIB_TABLE* aTable )
630 {
631  wxCHECK( aTable, false );
632  wxString libName = getLibraryName( aFilePath );
633  wxCHECK( !LibraryExists( libName ), false ); // either create or add an existing one
634 
635  // try to use path normalized to an environmental variable or project path
636  wxString relPath = NormalizePath( aFilePath, &Pgm().GetLocalEnvVariables(), &m_frame.Prj() );
637 
638  if( relPath.IsEmpty() )
639  relPath = aFilePath;
640 
641  SYMBOL_LIB_TABLE_ROW* libRow = new SYMBOL_LIB_TABLE_ROW( libName, relPath,
642  SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY ) );
643  aTable->InsertRow( libRow );
644 
645  if( aCreate )
646  {
647  // CreateSymbolLib() fails if the file exists
648  if( wxFileName::Exists( aFilePath ) )
649  {
650  if( !wxRemoveFile( aFilePath ) )
651  return false;
652  }
653 
654  aTable->CreateSymbolLib( libName );
655  }
656 
657  m_frame.SyncLibraries( false );
658 
659  return true;
660 }
661 
662 
664 {
665  return m_frame.Prj().SchSymbolLibTable();
666 }
667 
668 
669 std::set<LIB_PART*> LIB_MANAGER::getOriginalParts( const wxString& aLibrary )
670 {
671  std::set<LIB_PART*> parts;
672  wxCHECK( LibraryExists( aLibrary ), parts );
673 
674  try
675  {
676  wxArrayString aliases;
677  symTable()->EnumerateSymbolLib( aLibrary, aliases );
678 
679  for( const auto& aliasName : aliases )
680  {
681  LIB_ALIAS* alias = symTable()->LoadSymbol( aLibrary, aliasName );
682  parts.insert( alias->GetPart() );
683  }
684  } catch( const IO_ERROR& e )
685  {
686  DisplayErrorMessage( &m_frame, wxString::Format( _( "Cannot enumerate "
687  "library \"%s\"" ), aLibrary ), e.What() );
688  }
689 
690  return parts;
691 }
692 
693 
695 {
696  auto it = m_libs.find( aLibrary );
697 
698  if( it != m_libs.end() )
699  return it->second;
700 
701  // The requested buffer does not exist yet, so create one
702  auto ret = m_libs.emplace( aLibrary, LIB_BUFFER( aLibrary ) );
703  LIB_BUFFER& buf = ret.first->second;
704 
705  for( auto part : getOriginalParts( aLibrary ) )
706  buf.CreateBuffer( new LIB_PART( *part, nullptr ), new SCH_SCREEN( &m_frame.Kiway() ) );
707 
708  return buf;
709 }
710 
711 
712 LIB_MANAGER::PART_BUFFER::PART_BUFFER( LIB_PART* aPart, std::unique_ptr<SCH_SCREEN> aScreen )
713  : m_screen( std::move( aScreen ) ), m_part( aPart )
714 {
715  m_original = new LIB_PART( *aPart );
716 }
717 
718 
720 {
721  delete m_part;
722  delete m_original;
723 }
724 
725 
727 {
728  wxCHECK( m_part != aPart, /* void */ );
729  wxASSERT( aPart );
730  delete m_part;
731  m_part = aPart;
732 
733  // If the part moves libraries then the original moves with it
735  {
738  }
739 }
740 
741 
743 {
744  wxCHECK( m_original != aPart, /* void */ );
745  wxASSERT( aPart );
746  delete m_original;
747  m_original = aPart;
748 
749  // The original is not allowed to have a different library than its part
751  {
754  }
755 }
756 
757 
759 {
760  return m_screen && m_screen->IsModify();
761 }
762 
763 
765 {
766  wxArrayString ret;
767 
768  for( const auto& alias : m_aliases )
769  ret.push_back( alias.first );
770 
771  return ret;
772 }
773 
774 
776 {
777  wxASSERT( m_aliases.count( aCopy->GetName() ) == 0 ); // only for new parts
778  wxASSERT( aCopy->GetLib() == nullptr );
779  std::unique_ptr<SCH_SCREEN> screen( aScreen );
780  auto partBuf = std::make_shared<PART_BUFFER>( aCopy, std::move( screen ) );
781  m_parts.push_back( partBuf );
782  addAliases( partBuf );
783 
784  // Set the parent library name,
785  // otherwise it is empty as no library has been given as the owner during object construction
786  LIB_ID& libId = (LIB_ID&) aCopy->GetLibId();
787  libId.SetLibNickname( m_libName );
788  ++m_hash;
789 
790  return true;
791 }
792 
793 
795 {
796  bool ret = true;
797 
798  ret &= removeAliases( aPartBuf );
799  aPartBuf->SetPart( aCopy );
800  ret &= addAliases( aPartBuf );
801  ++m_hash;
802 
803  return ret;
804 }
805 
806 
808 {
809  auto partBufIt = std::find( m_parts.begin(), m_parts.end(), aPartBuf );
810  wxCHECK( partBufIt != m_parts.end(), false );
811  m_deleted.emplace_back( *partBufIt );
812  m_parts.erase( partBufIt );
813  ++m_hash;
814 
815  return removeAliases( aPartBuf );
816 }
817 
818 
820  SYMBOL_LIB_TABLE* aLibTable )
821 {
822  wxCHECK( aPartBuf, false );
823  LIB_PART* part = aPartBuf->GetPart();
824  wxCHECK( part, false );
825  wxCHECK( aLibTable->SaveSymbol( m_libName, new LIB_PART( *part ) ) == SYMBOL_LIB_TABLE::SAVE_OK, false );
826 
827  aPartBuf->SetOriginal( new LIB_PART( *part ) );
828  ++m_hash;
829  return true;
830 }
831 
832 
834  SCH_PLUGIN* aPlugin, bool aBuffer )
835 {
836  wxCHECK( aPartBuf, false );
837  LIB_PART* part = aPartBuf->GetPart();
838  wxCHECK( part, false );
839 
840  // set properties to prevent save file on every symbol save
841  PROPERTIES properties;
842  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
843 
844  // TODO there is no way to check if symbol has been successfully saved
845  aPlugin->SaveSymbol( m_libName, new LIB_PART( *part ), aBuffer ? &properties : nullptr );
846  aPartBuf->SetOriginal( new LIB_PART( *part ) );
847  ++m_hash;
848  return true;
849 }
850 
851 
853 {
854  LIB_PART* part = aPartBuf->GetPart();
855  wxCHECK( part, false );
856  bool ret = true; // Assume everything is ok
857 
858  for( unsigned int i = 0; i < part->GetAliasCount(); ++i )
859  {
860  bool newAlias;
861  std::tie( std::ignore, newAlias ) = m_aliases.emplace( part->GetAlias( i )->GetName(), aPartBuf );
862 
863  if( !newAlias ) // Overwrite check
864  {
865  wxFAIL;
866  ret = false;
867  }
868  }
869 
870  return ret;
871 }
872 
873 
875 {
876  LIB_PART* part = aPartBuf->GetPart();
877  wxCHECK( part, false );
878  bool ret = true; // Assume everything is ok
879 
880  for( unsigned int i = 0; i < part->GetAliasCount(); ++i )
881  {
882  auto aliasIt = m_aliases.find( part->GetAlias( i )->GetName() );
883 
884  if( aliasIt == m_aliases.end() )
885  {
886  wxFAIL;
887  ret = false;
888  continue;
889  }
890 
891  // Be sure the alias belongs to the assigned owner
892  wxASSERT( aliasIt->second.lock() == aPartBuf );
893 
894  m_aliases.erase( aliasIt );
895  }
896 
897  return ret;
898 }
std::unique_ptr< SCH_SCREEN > m_screen
Definition: lib_manager.h:323
LIB_ALIAS * LoadSymbol(const wxString &aNickname, const wxString &aAliasName)
Load a LIB_ALIAS having aAliasName from the library given by aNickname.
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:47
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...
Part library alias object definition.
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_player.h:60
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Function DisplayErrorMessage displays an error message with aMessage.
Definition: confirm.cpp:259
LIB_ALIAS * GetAlias(size_t aIndex)
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.
This file is part of the common library.
bool RemovePart(const wxString &aName, const wxString &aLibrary)
Removes the part from the part buffer.
LIB_PART * m_part
Working copy
Definition: lib_manager.h:326
static const wxString ShowType(SCH_FILE_T aFileType)
Return a brief name for a plugin, given aFileType enum.
Definition: sch_io_mgr.cpp:76
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)
bool ClearLibraryModified(const wxString &aLibrary) const
Clears the modified flag for all parts in a library.
const LIB_ID & GetLibId() const
int GetHash() const
Definition: lib_manager.cpp:59
const std::deque< PART_BUFFER::PTR > & GetBuffers() const
Returns all buffered parts
Definition: lib_manager.h:400
void LoadSymbolLib(std::vector< LIB_ALIAS * > &aAliasList, const wxString &aNickname, bool aPowerSymbolsOnly=false)
Template specialization to enable wxStrings for certain containers (e.g. unordered_map) ...
Definition: bitmap.cpp:55
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:66
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
size_t GetAliasCount() const
Class PROPERTIES is a name/value tuple with unique names and optional values.
Definition: properties.h:34
wxString GetUniqueComponentName(const wxString &aLibrary) const
Returns a component name that is not stored in a library.
LIB_PART * GetPart(const wxString &aAlias) const
Returns the working copy of a LIB_PART object with specified alias
Definition: lib_manager.h:365
bool DeleteBuffer(PART_BUFFER::PTR aPartBuf)
PART_BUFFER::PTR GetBuffer(const wxString &aAlias) const
Returns a part buffer with LIB_PART holding a particular alias
Definition: lib_manager.h:393
std::list< LIB_ALIAS * > GetAliases(const wxString &aLibrary) const
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
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:188
bool UpdateBuffer(PART_BUFFER::PTR aPartBuf, LIB_PART *aCopy)
Updates the stored part. LIB_BUFFER takes ownership of aCopy.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
LIB_ID RevertPart(const wxString &aAlias, const wxString &aLibrary)
Reverts unsaved changes for a particular part.
bool FlushLibrary(const wxString &aLibrary)
Saves changes to the library copy used by the schematic editor.
bool FlushAll()
Saves all changes to libraries.
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
bool ClearPartModified(const wxString &aAlias, const wxString &aLibrary) const
Clears the modified flag for a part.
SYMBOL_LIB_TABLE_ROW * GetLibrary(const wxString &aLibrary) const
Finds a single library within the (aggregate) library table.
Definition: lib_manager.cpp:95
Class LIB_ITEM definition.
SCH_SCREEN * GetScreen(const wxString &aAlias, const wxString &aLibrary)
Returns the screen used to edit a specific part.
LIB_EDIT_FRAME & m_frame
Parent frame
Definition: lib_manager.h:279
Define a library symbol object.
SYMBOL_TREE_SYNCHRONIZING_ADAPTER::PTR m_adapter
Definition: lib_manager.h:451
bool IsLibraryModified(const wxString &aLibrary) const
Returns true if library has unsaved modifications.
wxArrayString GetAliasNames(const wxString &aLibrary) const
Returns a set containing all part names for a specific library.
#define THROW_IO_ERROR(msg)
Class to store a working copy of a library
Definition: lib_manager.h:334
bool FlushPart(const wxString &aAlias, const wxString &aLibrary)
Saves part changes to the library copy used by the schematic editor.
bool SaveLibrary(const wxString &aLibrary, const wxString &aFileName)
Saves library to a file, including unsaved changes.
bool addAliases(PART_BUFFER::PTR aPartBuf)
Creates alias entries for a particular part buffer
bool IsLibraryReadOnly(const wxString &aLibrary) const
Returns true if the library is stored in a read-only file.
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.
LIB_PART * GetPart() const
Get the shared LIB_PART.
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:193
int GetLibraryHash(const wxString &aLibrary) const
Retruns a library hash value to determine if it has changed.
Definition: lib_manager.cpp:70
Helper object to release a SCH_PLUGIN in the context of a potential thrown exception through its dest...
Definition: sch_io_mgr.h:523
SYMBOL_LIB_TABLE * symTable() const
Returns the current Symbol Library Table
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.
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
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)...
bool removeAliases(PART_BUFFER::PTR aPartBuf)
Removes alias entries for a particular part buffer
wxArrayString GetLibraryNames() const
Returns the array of library names.
Definition: lib_manager.cpp:84
The symbol library editor main window.
see class PGM_BASE
LIB_MANAGER(LIB_EDIT_FRAME &aFrame)
Definition: lib_manager.cpp:39
const wxString & GetName() const override
const char * name
Definition: DXF_plotter.cpp:61
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
LIB_PART * m_original
Initial state of the part
Definition: lib_manager.h:329
wxArrayString GetAliasNames() const
Returns all alias names for stored parts
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 max(a, b)
Definition: auxiliary.h:86
size_t i
Definition: json11.cpp:597
bool LibraryExists(const wxString &aLibrary, bool aCheckEnabled=false) const
Returns true if library exists.
void ClrModify()
Definition: base_screen.h:325
LIB_ALIAS * 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...
static const char * PropBuffering
const char* PropBuffering
wxString GetUniqueLibraryName() const
Returns a library name that is not currently in use.
const wxString & GetName() const
Definition of class LIB_EDIT_FRAME.
bool IsPartModified(const wxString &aAlias, const wxString &aLibrary) const
Returns true if part has unsaved modifications.
std::shared_ptr< PART_BUFFER > PTR
Definition: lib_manager.h:319
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:102
void SetOriginal(LIB_PART *aPart)
int m_syncHash
Symbol Lib Table hash value returned during the last synchronization
Definition: lib_manager.h:443
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:440
Definition for part library class.
void SetModify()
Definition: base_screen.h:324
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
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
void DeleteAlias(const wxString &aNickname, const wxString &aAliasName)
Delete aAliasName from the library at aLibraryPath.
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:67
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:452