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  wxCHECK( alias, nullptr );
364  bufferedPart = new LIB_PART( *alias->GetPart(), nullptr );
365  libBuf.CreateBuffer( bufferedPart, new SCH_SCREEN( &m_frame.Kiway() ) );
366  }
367  catch( const IO_ERROR& e )
368  {
369  DisplayErrorMessage( &m_frame, wxString::Format( _( "Cannot load "
370  "symbol \"%s\" from library \"%s\"" ), aAlias, aLibrary ), e.What() );
371  bufferedPart = nullptr;
372  }
373  }
374 
375  return bufferedPart;
376 }
377 
378 
379 SCH_SCREEN* LIB_MANAGER::GetScreen( const wxString& aAlias, const wxString& aLibrary )
380 {
381  wxCHECK( LibraryExists( aLibrary ), nullptr );
382  wxCHECK( !aAlias.IsEmpty(), nullptr );
383  auto it = m_libs.find( aLibrary );
384  wxCHECK( it != m_libs.end(), nullptr );
385 
386  LIB_BUFFER& buf = it->second;
387  auto partBuf = buf.GetBuffer( aAlias );
388  return partBuf ? partBuf->GetScreen() : nullptr;
389 }
390 
391 
392 bool LIB_MANAGER::UpdatePart( LIB_PART* aPart, const wxString& aLibrary )
393 {
394  wxCHECK( LibraryExists( aLibrary ), false );
395  wxCHECK( aPart, false );
396  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
397  auto partBuf = libBuf.GetBuffer( aPart->GetName() );
398  LIB_PART* partCopy = new LIB_PART( *aPart, nullptr );
399 
400  if( partBuf )
401  {
402  libBuf.UpdateBuffer( partBuf, partCopy );
403  }
404  else // New entry
405  {
406  SCH_SCREEN* screen = new SCH_SCREEN( &m_frame.Kiway() );
407  libBuf.CreateBuffer( partCopy, screen );
408  screen->SetModify();
409  }
410 
411  return true;
412 }
413 
414 
415 bool LIB_MANAGER::UpdatePartAfterRename( LIB_PART* aPart, const wxString& oldAlias,
416  const wxString& aLibrary )
417 {
418  // This is essentially a delete/update, but we have to make a copy of the "original"
419  // LIB_PART from the old buffer to give to the new one.
420 
421  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
422  auto partBuf = libBuf.GetBuffer( oldAlias );
423  wxCHECK( partBuf, false );
424 
425  std::unique_ptr<LIB_PART> original( new LIB_PART( *partBuf->GetOriginal() ) );
426  // Save the screen object, so it is transferred to the new buffer
427  std::unique_ptr<SCH_SCREEN> screen = partBuf->RemoveScreen();
428 
429  if( !libBuf.DeleteBuffer( partBuf ) )
430  return false;
431 
432  if( !UpdatePart( aPart, aLibrary ) )
433  return false;
434 
435  partBuf = libBuf.GetBuffer( aPart->GetName() );
436  partBuf->SetScreen( std::move( screen ) );
437  wxCHECK( partBuf, false );
438  partBuf->SetOriginal( original.release() ); // part buffer takes ownership of pointer
439 
440  m_frame.SyncLibraries( false );
441 
442  return true;
443 }
444 
445 
446 bool LIB_MANAGER::FlushPart( const wxString& aAlias, const wxString& aLibrary )
447 {
448  auto it = m_libs.find( aLibrary );
449 
450  if( it == m_libs.end() ) // no items to flush
451  return true;
452 
453  auto partBuf = it->second.GetBuffer( aAlias );
454  wxCHECK( partBuf, false );
455 
456  return it->second.SaveBuffer( partBuf, symTable() );
457 }
458 
459 
460 LIB_ID LIB_MANAGER::RevertPart( const wxString& aAlias, const wxString& aLibrary )
461 {
462  auto it = m_libs.find( aLibrary );
463 
464  if( it == m_libs.end() ) // no items to flush
465  return LIB_ID( aLibrary, aAlias );
466 
467  auto partBuf = it->second.GetBuffer( aAlias );
468  wxCHECK( partBuf, LIB_ID( aLibrary, aAlias ) );
469  LIB_PART original( *partBuf->GetOriginal() );
470 
471  if( original.GetName() != aAlias )
472  {
473  UpdatePartAfterRename( &original, aAlias, aLibrary );
474  }
475  else
476  {
477  partBuf->SetPart( new LIB_PART( original ) );
478  m_frame.SyncLibraries( false );
479  }
480 
481  return LIB_ID( aLibrary, original.GetName() );
482 }
483 
484 
485 bool LIB_MANAGER::RevertLibrary( const wxString& aLibrary )
486 {
487  auto it = m_libs.find( aLibrary );
488 
489  if( it == m_libs.end() ) // nothing to reverse
490  return false;
491 
492  m_libs.erase( it );
493  m_frame.SyncLibraries( false );
494 
495  return true;
496 }
497 
498 
499 bool LIB_MANAGER::RemovePart( const wxString& aAlias, const wxString& aLibrary )
500 {
501  LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
502  auto partBuf = libBuf.GetBuffer( aAlias );
503  wxCHECK( partBuf, false );
504 
505  bool res = libBuf.DeleteBuffer( partBuf );
506  m_frame.SyncLibraries( false );
507 
508  return res;
509 }
510 
511 
512 LIB_ALIAS* LIB_MANAGER::GetAlias( const wxString& aAlias, const wxString& aLibrary ) const
513 {
514  // Try the library buffers first
515  auto libIt = m_libs.find( aLibrary );
516 
517  if( libIt != m_libs.end() )
518  {
519  LIB_PART* part = libIt->second.GetPart( aAlias );
520 
521  if( part )
522  return part->GetAlias( aAlias );
523  }
524 
525  // Get the original part
526  LIB_ALIAS* alias = nullptr;
527 
528  try
529  {
530  alias = symTable()->LoadSymbol( aLibrary, aAlias );
531  }
532  catch( const IO_ERROR& e )
533  {
534  DisplayErrorMessage( &m_frame, wxString::Format( _( "Cannot load "
535  "symbol \"%s\" from library \"%s\"" ), aAlias, aLibrary ), e.What() );
536  }
537 
538  return alias;
539 }
540 
541 
542 bool LIB_MANAGER::PartExists( const wxString& aAlias, const wxString& aLibrary ) const
543 {
544  auto libBufIt = m_libs.find( aLibrary );
545  LIB_ALIAS* alias = nullptr;
546 
547  if( libBufIt != m_libs.end() )
548  return !!libBufIt->second.GetBuffer( aAlias );
549 
550  try
551  {
552  alias = symTable()->LoadSymbol( aLibrary, aAlias );
553  } catch( IO_ERROR& )
554  {
555  // checking if certain symbol exists, so its absence is perfectly fine
556  }
557 
558  return alias != nullptr;
559 }
560 
561 
562 bool LIB_MANAGER::LibraryExists( const wxString& aLibrary, bool aCheckEnabled ) const
563 {
564  if( aLibrary.IsEmpty() )
565  return false;
566 
567  if( m_libs.count( aLibrary ) > 0 )
568  return true;
569 
570  return symTable()->HasLibrary( aLibrary, aCheckEnabled );
571 }
572 
574 {
575  wxString name = "New_Library";
576 
577  if( !LibraryExists( name ) )
578  return name;
579 
580  name += "_";
581 
582  for( unsigned int i = 0; i < std::numeric_limits<unsigned int>::max(); ++i )
583  {
584  if( !LibraryExists( name + wxString::Format( "%u", i ) ) )
585  return name + wxString::Format( "%u", i );
586  }
587 
588  wxFAIL;
589  return wxEmptyString;
590 }
591 
592 
593 wxString LIB_MANAGER::GetUniqueComponentName( const wxString& aLibrary ) const
594 {
595  wxString name = "New_Component";
596 
597  if( !PartExists( name, aLibrary ) )
598  return name;
599 
600  name += "_";
601 
602  for( unsigned int i = 0; i < std::numeric_limits<unsigned int>::max(); ++i )
603  {
604  if( !PartExists( name + wxString::Format( "%u", i ), aLibrary ) )
605  return name + wxString::Format( "%u", i );
606  }
607 
608  wxFAIL;
609  return wxEmptyString;
610 }
611 
612 
613 wxString LIB_MANAGER::getLibraryName( const wxString& aFilePath )
614 {
615  wxFileName fn( aFilePath );
616  return fn.GetName();
617 }
618 
619 
620 bool LIB_MANAGER::addLibrary( const wxString& aFilePath, bool aCreate, SYMBOL_LIB_TABLE* aTable )
621 {
622  wxCHECK( aTable, false );
623  wxString libName = getLibraryName( aFilePath );
624  wxCHECK( !LibraryExists( libName ), false ); // either create or add an existing one
625 
626  // try to use path normalized to an environmental variable or project path
627  wxString relPath = NormalizePath( aFilePath, &Pgm().GetLocalEnvVariables(), &m_frame.Prj() );
628 
629  if( relPath.IsEmpty() )
630  relPath = aFilePath;
631 
632  SYMBOL_LIB_TABLE_ROW* libRow = new SYMBOL_LIB_TABLE_ROW( libName, relPath,
633  SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY ) );
634  aTable->InsertRow( libRow );
635 
636  if( aCreate )
637  {
638  // CreateSymbolLib() fails if the file exists
639  if( wxFileName::Exists( aFilePath ) )
640  {
641  if( !wxRemoveFile( aFilePath ) )
642  return false;
643  }
644 
645  aTable->CreateSymbolLib( libName );
646  }
647 
648  m_frame.SyncLibraries( false );
649 
650  return true;
651 }
652 
653 
655 {
656  return m_frame.Prj().SchSymbolLibTable();
657 }
658 
659 
660 std::set<LIB_PART*> LIB_MANAGER::getOriginalParts( const wxString& aLibrary )
661 {
662  std::set<LIB_PART*> parts;
663  wxCHECK( LibraryExists( aLibrary ), parts );
664 
665  try
666  {
667  wxArrayString aliases;
668  symTable()->EnumerateSymbolLib( aLibrary, aliases );
669 
670  for( const auto& aliasName : aliases )
671  {
672  LIB_ALIAS* alias = symTable()->LoadSymbol( aLibrary, aliasName );
673  parts.insert( alias->GetPart() );
674  }
675  } catch( const IO_ERROR& e )
676  {
677  DisplayErrorMessage( &m_frame, wxString::Format( _( "Cannot enumerate "
678  "library \"%s\"" ), aLibrary ), e.What() );
679  }
680 
681  return parts;
682 }
683 
684 
686 {
687  auto it = m_libs.find( aLibrary );
688 
689  if( it != m_libs.end() )
690  return it->second;
691 
692  // The requested buffer does not exist yet, so create one
693  auto ret = m_libs.emplace( aLibrary, LIB_BUFFER( aLibrary ) );
694  LIB_BUFFER& buf = ret.first->second;
695 
696  for( auto part : getOriginalParts( aLibrary ) )
697  buf.CreateBuffer( new LIB_PART( *part, nullptr ), new SCH_SCREEN( &m_frame.Kiway() ) );
698 
699  return buf;
700 }
701 
702 
703 LIB_MANAGER::PART_BUFFER::PART_BUFFER( LIB_PART* aPart, std::unique_ptr<SCH_SCREEN> aScreen )
704  : m_screen( std::move( aScreen ) ), m_part( aPart )
705 {
706  m_original = new LIB_PART( *aPart );
707 }
708 
709 
711 {
712  delete m_part;
713  delete m_original;
714 }
715 
716 
718 {
719  wxCHECK( m_part != aPart, /* void */ );
720  wxASSERT( aPart );
721  delete m_part;
722  m_part = aPart;
723 }
724 
725 
727 {
728  wxCHECK( m_original != aPart, /* void */ );
729  wxASSERT( aPart );
730  delete m_original;
731  m_original = aPart;
732 }
733 
734 
736 {
737  return m_screen && m_screen->IsModify();
738 }
739 
740 
742 {
743  wxArrayString ret;
744 
745  for( const auto& alias : m_aliases )
746  ret.push_back( alias.first );
747 
748  return ret;
749 }
750 
751 
753 {
754  wxASSERT( m_aliases.count( aCopy->GetName() ) == 0 ); // only for new parts
755  wxASSERT( aCopy->GetLib() == nullptr );
756  std::unique_ptr<SCH_SCREEN> screen( aScreen );
757  auto partBuf = std::make_shared<PART_BUFFER>( aCopy, std::move( screen ) );
758  m_parts.push_back( partBuf );
759  addAliases( partBuf );
760 
761  // Set the parent library name,
762  // otherwise it is empty as no library has been given as the owner during object construction
763  LIB_ID& libId = (LIB_ID&) aCopy->GetLibId();
764  libId.SetLibNickname( m_libName );
765  ++m_hash;
766 
767  return true;
768 }
769 
770 
772 {
773  bool ret = true;
774 
775  ret &= removeAliases( aPartBuf );
776  aPartBuf->SetPart( aCopy );
777  ret &= addAliases( aPartBuf );
778  ++m_hash;
779 
780  return ret;
781 }
782 
783 
785 {
786  auto partBufIt = std::find( m_parts.begin(), m_parts.end(), aPartBuf );
787  wxCHECK( partBufIt != m_parts.end(), false );
788  m_deleted.emplace_back( *partBufIt );
789  m_parts.erase( partBufIt );
790  ++m_hash;
791 
792  return removeAliases( aPartBuf );
793 }
794 
795 
797  SYMBOL_LIB_TABLE* aLibTable )
798 {
799  wxCHECK( aPartBuf, false );
800  LIB_PART* part = aPartBuf->GetPart();
801  wxCHECK( part, false );
802  wxCHECK( aLibTable->SaveSymbol( m_libName, new LIB_PART( *part ) ) == SYMBOL_LIB_TABLE::SAVE_OK, false );
803 
804  aPartBuf->SetOriginal( new LIB_PART( *part ) );
805  ++m_hash;
806  return true;
807 }
808 
809 
811  SCH_PLUGIN* aPlugin, bool aBuffer )
812 {
813  wxCHECK( aPartBuf, false );
814  LIB_PART* part = aPartBuf->GetPart();
815  wxCHECK( part, false );
816 
817  // set properties to prevent save file on every symbol save
818  PROPERTIES properties;
819  properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
820 
821  // TODO there is no way to check if symbol has been successfully saved
822  aPlugin->SaveSymbol( m_libName, new LIB_PART( *part ), aBuffer ? &properties : nullptr );
823  aPartBuf->SetOriginal( new LIB_PART( *part ) );
824  ++m_hash;
825  return true;
826 }
827 
828 
830 {
831  LIB_PART* part = aPartBuf->GetPart();
832  wxCHECK( part, false );
833  bool ret = true; // Assume everything is ok
834 
835  for( unsigned int i = 0; i < part->GetAliasCount(); ++i )
836  {
837  bool newAlias;
838  std::tie( std::ignore, newAlias ) = m_aliases.emplace( part->GetAlias( i )->GetName(), aPartBuf );
839 
840  if( !newAlias ) // Overwrite check
841  {
842  wxFAIL;
843  ret = false;
844  }
845  }
846 
847  return ret;
848 }
849 
850 
852 {
853  LIB_PART* part = aPartBuf->GetPart();
854  wxCHECK( part, false );
855  bool ret = true; // Assume everything is ok
856 
857  for( unsigned int i = 0; i < part->GetAliasCount(); ++i )
858  {
859  auto aliasIt = m_aliases.find( part->GetAlias( i )->GetName() );
860 
861  if( aliasIt == m_aliases.end() )
862  {
863  wxFAIL;
864  ret = false;
865  continue;
866  }
867 
868  // Be sure the alias belongs to the assigned owner
869  wxASSERT( aliasIt->second.lock() == aPartBuf );
870 
871  m_aliases.erase( aliasIt );
872  }
873 
874  return ret;
875 }
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.
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.
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.
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
static wxString getLibraryName(const wxString &aFilePath)
Extracts library name basing on the file name
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