KiCad PCB EDA Suite
symbol_library_manager.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2017 CERN
5 * Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Maciej Suminski <[email protected]>
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
27#include <symbol_library.h>
29#include <symbol_edit_frame.h>
30#include <env_paths.h>
31#include <pgm_base.h>
32#include <kiway.h>
33#include <profile.h>
34#include <wx_filename.h>
35#include <sch_io_mgr.h>
37#include <symbol_lib_table.h>
38#include <symbol_async_loader.h>
39#include <progress_reporter.h>
40#include <list>
41#include <locale_io.h>
42#include <wx/log.h>
43#include <string_utils.h>
44#include "lib_logger.h"
45
46
48 m_frame( aFrame )
49{
50 m_logger = new LIB_LOGGER();
51}
52
53
55{
56 delete m_logger;
57}
58
59
61{
62 SYMBOL_ASYNC_LOADER loader( symTable()->GetLogicalLibs(), symTable(), false, nullptr,
63 &aReporter );
64
65 LOCALE_IO toggle;
66
67 loader.Start();
68
69 while( !loader.Done() )
70 {
71 if( !aReporter.KeepRefreshing() )
72 break;
73
74 wxMilliSleep( 33 /* 30 FPS refresh rate */ );
75 }
76
77 loader.Join();
78
79 if( !loader.GetErrors().IsEmpty() )
80 {
81 HTML_MESSAGE_BOX dlg( &m_frame, _( "Load Error" ) );
82
83 dlg.MessageSet( _( "Errors loading symbols:" ) );
84
85 wxString msg = loader.GetErrors();
86 msg.Replace( "\n", "<BR>" );
87
88 dlg.AddHTML_Text( msg );
89 dlg.ShowModal();
90 }
91}
92
93
95{
96 for( const std::pair<const wxString, LIB_BUFFER>& lib : m_libs )
97 {
98 if( lib.second.IsModified() )
99 return true;
100 }
101
102 return false;
103}
104
105
107{
108 int hash = symTable()->GetModifyHash();
109
110 for( const std::pair<const wxString, LIB_BUFFER>& lib : m_libs )
111 hash += lib.second.GetHash();
112
113 return hash;
114}
115
116
117int SYMBOL_LIBRARY_MANAGER::GetLibraryHash( const wxString& aLibrary ) const
118{
119 const auto libBufIt = m_libs.find( aLibrary );
120
121 if( libBufIt != m_libs.end() )
122 return libBufIt->second.GetHash();
123
124 SYMBOL_LIB_TABLE_ROW* row = GetLibrary( aLibrary );
125
126 // return -1 if library does not exist or 0 if not modified
127 return row ? std::hash<std::string>{}( aLibrary.ToStdString() +
128 row->GetFullURI( true ).ToStdString() ) : -1;
129}
130
131
133{
134 wxArrayString res;
135
136 for( const wxString& libName : symTable()->GetLogicalLibs() )
137 {
138 // Database libraries are hidden from the symbol editor at the moment
139 if( GetLibrary( libName )->SchLibType() == SCH_IO_MGR::SCH_DATABASE )
140 continue;
141
142 res.Add( libName );
143 }
144
145 return res;
146}
147
148
150{
151 SYMBOL_LIB_TABLE_ROW* row = nullptr;
152
153 try
154 {
155 row = symTable()->FindRow( aLibrary, true );
156 }
157 catch( const IO_ERROR& e )
158 {
159 wxLogMessage( _( "Library '%s' not found in the Symbol Library Table." ) + e.What(),
160 aLibrary );
161 }
162
163 return row;
164}
165
166
167bool SYMBOL_LIBRARY_MANAGER::SaveLibrary( const wxString& aLibrary, const wxString& aFileName,
168 SCH_IO_MGR::SCH_FILE_T aFileType )
169{
170 wxCHECK( aFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY && LibraryExists( aLibrary ), false );
171 wxFileName fn( aFileName );
172 wxCHECK( !fn.FileExists() || fn.IsFileWritable(), false );
173 SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( aFileType ) );
174 bool res = true; // assume all libraries are successfully saved
175
176 STRING_UTF8_MAP properties;
177 properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
178
179 auto it = m_libs.find( aLibrary );
180
181 if( it != m_libs.end() )
182 {
183 // Handle buffered library
184 LIB_BUFFER& libBuf = it->second;
185
186 const auto& symbolBuffers = libBuf.GetBuffers();
187
188 for( const auto& symbolBuf : symbolBuffers )
189 {
190 if( !libBuf.SaveBuffer( symbolBuf, aFileName, &*pi, true ) )
191 {
192 // Something went wrong, but try to save other libraries
193 res = false;
194 }
195 }
196
197 // clear the deleted symbols buffer only if data is saved to the original file
198 wxFileName original, destination( aFileName );
199 SYMBOL_LIB_TABLE_ROW* row = GetLibrary( aLibrary );
200
201 if( row )
202 {
203 original = row->GetFullURI();
204 original.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
205 }
206
207 destination.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
208
209 if( res && original == destination )
210 libBuf.ClearDeletedBuffer();
211 }
212 else
213 {
214 // Handle original library
215 for( LIB_SYMBOL* symbol : getOriginalSymbols( aLibrary ) )
216 {
217 LIB_SYMBOL* newSymbol;
218
219 try
220 {
221 if( symbol->IsAlias() )
222 {
223 std::shared_ptr< LIB_SYMBOL > oldParent = symbol->GetParent().lock();
224
225 wxCHECK_MSG( oldParent, false,
226 wxString::Format( wxT( "Derived symbol '%s' found with undefined parent." ),
227 symbol->GetName() ) );
228
229 LIB_SYMBOL* libParent = pi->LoadSymbol( aLibrary, oldParent->GetName(),
230 &properties );
231
232 if( !libParent )
233 {
234 libParent = new LIB_SYMBOL( *oldParent.get() );
235 pi->SaveSymbol( aLibrary, libParent, &properties );
236 }
237
238 newSymbol = new LIB_SYMBOL( *symbol );
239 newSymbol->SetParent( libParent );
240 pi->SaveSymbol( aLibrary, newSymbol, &properties );
241 }
242 else if( !pi->LoadSymbol( aLibrary, symbol->GetName(), &properties ) )
243 {
244 pi->SaveSymbol( aLibrary, new LIB_SYMBOL( *symbol ), &properties );
245 }
246 }
247 catch( ... )
248 {
249 res = false;
250 break;
251 }
252 }
253 }
254
255 try
256 {
257 pi->SaveLibrary( aFileName );
258 }
259 catch( ... )
260 {
261 // return false because something happens.
262 // The library is not successfully saved
263 res = false;
264 }
265
266 return res;
267}
268
269
270bool SYMBOL_LIBRARY_MANAGER::IsLibraryModified( const wxString& aLibrary ) const
271{
272 auto it = m_libs.find( aLibrary );
273 return it != m_libs.end() ? it->second.IsModified() : false;
274}
275
276
277bool SYMBOL_LIBRARY_MANAGER::IsSymbolModified( const wxString& aAlias,
278 const wxString& aLibrary ) const
279{
280 auto libIt = m_libs.find( aLibrary );
281
282 if( libIt == m_libs.end() )
283 return false;
284
285 const LIB_BUFFER& buf = libIt->second;
286 const std::shared_ptr<SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER> symbolBuf = buf.GetBuffer( aAlias );
287 return symbolBuf ? symbolBuf->IsModified() : false;
288}
289
290
291void SYMBOL_LIBRARY_MANAGER::SetSymbolModified( const wxString& aAlias,
292 const wxString& aLibrary )
293{
294 auto libIt = m_libs.find( aLibrary );
295
296 if( libIt == m_libs.end() )
297 return;
298
299 const LIB_BUFFER& buf = libIt->second;
300 std::shared_ptr<SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER> symbolBuf = buf.GetBuffer( aAlias );
301
302 wxCHECK( symbolBuf, /* void */ );
303
304 symbolBuf->GetScreen()->SetContentModified();
305}
306
307
308bool SYMBOL_LIBRARY_MANAGER::ClearLibraryModified( const wxString& aLibrary ) const
309{
310 auto libIt = m_libs.find( aLibrary );
311
312 if( libIt == m_libs.end() )
313 return false;
314
315 for( auto& symbolBuf : libIt->second.GetBuffers() )
316 {
317 SCH_SCREEN* screen = symbolBuf->GetScreen();
318
319 if( screen )
320 screen->SetContentModified( false );
321 }
322
323 return true;
324}
325
326
328 const wxString& aLibrary ) const
329{
330 auto libI = m_libs.find( aLibrary );
331
332 if( libI == m_libs.end() )
333 return false;
334
335 auto symbolBuf = libI->second.GetBuffer( aAlias );
336 wxCHECK( symbolBuf, false );
337
338 symbolBuf->GetScreen()->SetContentModified( false );
339 return true;
340}
341
342
343bool SYMBOL_LIBRARY_MANAGER::IsLibraryReadOnly( const wxString& aLibrary ) const
344{
345 wxCHECK( LibraryExists( aLibrary ), true );
346
347 return !symTable()->IsSymbolLibWritable( aLibrary );
348}
349
350
351bool SYMBOL_LIBRARY_MANAGER::IsLibraryLoaded( const wxString& aLibrary ) const
352{
353 wxCHECK( LibraryExists( aLibrary ), false );
354
355 return symTable()->IsSymbolLibLoaded( aLibrary );
356}
357
358
359std::list<LIB_SYMBOL*> SYMBOL_LIBRARY_MANAGER::GetAliases( const wxString& aLibrary ) const
360{
361 std::list<LIB_SYMBOL*> ret;
362 wxCHECK( LibraryExists( aLibrary ), ret );
363
364 auto libIt = m_libs.find( aLibrary );
365
366 if( libIt != m_libs.end() )
367 {
368 for( auto& symbolBuf : libIt->second.GetBuffers() )
369 {
370 ret.push_back( symbolBuf->GetSymbol() );
371 }
372 }
373 else
374 {
375 std::vector<LIB_SYMBOL*> aliases;
376
377 try
378 {
379 symTable()->LoadSymbolLib( aliases, aLibrary );
380 }
381 catch( const IO_ERROR& e )
382 {
383 wxLogWarning( e.Problem() );
384 }
385
386 std::copy( aliases.begin(), aliases.end(), std::back_inserter( ret ) );
387 }
388
389 return ret;
390}
391
392
394 const wxString& aLibrary )
395{
396 wxCHECK( LibraryExists( aLibrary ), nullptr );
397
398 // try the library buffers first
399 LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
400 LIB_SYMBOL* bufferedSymbol = libBuf.GetSymbol( aAlias );
401
402 if( !bufferedSymbol ) // no buffer symbol found
403 {
404 // create a copy of the symbol
405 try
406 {
407 LIB_SYMBOL* symbol = symTable()->LoadSymbol( aLibrary, aAlias );
408
409 if( symbol == nullptr )
410 THROW_IO_ERROR( _( "Symbol not found." ) );
411
412 LIB_SYMBOL* bufferedParent = nullptr;
413
414 // Create parent symbols on demand so parent symbol can be set.
415 if( symbol->IsAlias() )
416 {
417 std::shared_ptr< LIB_SYMBOL > parent = symbol->GetParent().lock();
418 wxCHECK_MSG( parent, nullptr,
419 wxString::Format( "Derived symbol '%s' found with undefined parent.",
420 symbol->GetName() ) );
421
422 // Check if the parent symbol buffer has already be created.
423 bufferedParent = libBuf.GetSymbol( parent->GetName() );
424
425 if( !bufferedParent )
426 {
427 bufferedParent = new LIB_SYMBOL( *parent.get() );
428 libBuf.CreateBuffer( bufferedParent, new SCH_SCREEN );
429 }
430 }
431
432 bufferedSymbol = new LIB_SYMBOL( *symbol );
433
434 if( bufferedParent )
435 bufferedSymbol->SetParent( bufferedParent );
436
437 libBuf.CreateBuffer( bufferedSymbol, new SCH_SCREEN );
438 }
439 catch( const IO_ERROR& e )
440 {
441 wxLogMessage( _( "Error loading symbol %s from library '%s'. (%s)" ),
442 aAlias, aLibrary, e.What() );
443 bufferedSymbol = nullptr;
444 }
445 }
446
447 return bufferedSymbol;
448}
449
450
451SCH_SCREEN* SYMBOL_LIBRARY_MANAGER::GetScreen( const wxString& aAlias, const wxString& aLibrary )
452{
453 wxCHECK( LibraryExists( aLibrary ), nullptr );
454 wxCHECK( !aAlias.IsEmpty(), nullptr );
455 auto it = m_libs.find( aLibrary );
456 wxCHECK( it != m_libs.end(), nullptr );
457
458 LIB_BUFFER& buf = it->second;
459 auto symbolBuf = buf.GetBuffer( aAlias );
460 return symbolBuf ? symbolBuf->GetScreen() : nullptr;
461}
462
463
464bool SYMBOL_LIBRARY_MANAGER::UpdateSymbol( LIB_SYMBOL* aSymbol, const wxString& aLibrary )
465{
466 wxCHECK( LibraryExists( aLibrary ), false );
467 wxCHECK( aSymbol, false );
468 LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
469 auto symbolBuf = libBuf.GetBuffer( aSymbol->GetName() );
470
471 if( symbolBuf ) // Existing symbol.
472 {
473 LIB_SYMBOL* bufferedSymbol = const_cast< LIB_SYMBOL* >( symbolBuf->GetSymbol() );
474
475 wxCHECK( bufferedSymbol, false );
476
477 *bufferedSymbol = *aSymbol;
478 symbolBuf->GetScreen()->SetContentModified();
479 }
480 else // New symbol
481 {
482 LIB_SYMBOL* symbolCopy = new LIB_SYMBOL( *aSymbol, nullptr );
483
484 symbolCopy->SetLibId( LIB_ID( aLibrary, aSymbol->GetLibId().GetLibItemName() ) );
485
486 SCH_SCREEN* screen = new SCH_SCREEN;
487 libBuf.CreateBuffer( symbolCopy, screen );
488 screen->SetContentModified();
489 }
490
491 return true;
492}
493
494
495bool SYMBOL_LIBRARY_MANAGER::UpdateSymbolAfterRename( LIB_SYMBOL* aSymbol, const wxString& aOldName,
496 const wxString& aLibrary )
497{
498 LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
499 auto symbolBuf = libBuf.GetBuffer( aOldName );
500
501 wxCHECK( symbolBuf, false );
502
503 libBuf.UpdateBuffer( symbolBuf, aSymbol );
505
506 return true;
507}
508
509
510bool SYMBOL_LIBRARY_MANAGER::FlushSymbol( const wxString& aAlias, const wxString& aLibrary )
511{
512 auto it = m_libs.find( aLibrary );
513
514 if( it == m_libs.end() ) // no items to flush
515 return true;
516
517 auto symbolBuf = it->second.GetBuffer( aAlias );
518 wxCHECK( symbolBuf, false );
519
520 return it->second.SaveBuffer( symbolBuf, symTable() );
521}
522
523
524LIB_ID SYMBOL_LIBRARY_MANAGER::RevertSymbol( const wxString& aAlias, const wxString& aLibrary )
525{
526 auto it = m_libs.find( aLibrary );
527
528 if( it == m_libs.end() ) // no items to flush
529 return LIB_ID( aLibrary, aAlias );
530
531 auto symbolBuf = it->second.GetBuffer( aAlias );
532 wxCHECK( symbolBuf, LIB_ID( aLibrary, aAlias ) );
533 LIB_SYMBOL original( *symbolBuf->GetOriginal() );
534
535 if( original.GetName() != aAlias )
536 {
537 UpdateSymbolAfterRename( &original, aAlias, aLibrary );
538 }
539 else
540 {
541 // copy the initial data to the current symbol to restore
542 *symbolBuf->GetSymbol() = original;
544 }
545
546 return LIB_ID( aLibrary, original.GetName() );
547}
548
549
550bool SYMBOL_LIBRARY_MANAGER::RevertLibrary( const wxString& aLibrary )
551{
552 auto it = m_libs.find( aLibrary );
553
554 if( it == m_libs.end() ) // nothing to reverse
555 return false;
556
557 m_libs.erase( it );
559
560 return true;
561}
562
563
565{
566 bool retv = true;
567
568 // Nothing to revert.
569 if( GetHash() == 0 )
570 return true;
571
572 for( const auto& lib : m_libs )
573 {
574 if( !lib.second.IsModified() )
575 continue;
576
577 for( const auto& buffer : lib.second.GetBuffers() )
578 {
579 if( !buffer->IsModified() )
580 continue;
581
582 RevertSymbol( lib.first, buffer->GetOriginal()->GetName() );
583 }
584 }
585
586 return retv;
587}
588
589
590bool SYMBOL_LIBRARY_MANAGER::RemoveSymbol( const wxString& aAlias, const wxString& aLibrary )
591{
592 LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary );
593 auto symbolBuf = libBuf.GetBuffer( aAlias );
594 wxCHECK( symbolBuf, false );
595
596 bool retv = true;
597
598 retv &= libBuf.DeleteBuffer( symbolBuf );
600
601 return retv;
602}
603
604
606 const wxString& aLibrary ) const
607{
608 // Try the library buffers first
609 auto libIt = m_libs.find( aLibrary );
610
611 if( libIt != m_libs.end() )
612 {
613 LIB_SYMBOL* symbol = libIt->second.GetSymbol( aAlias );
614
615 if( symbol )
616 return symbol;
617 }
618
619 // Get the original symbol
620 LIB_SYMBOL* alias = nullptr;
621
622 try
623 {
624 alias = symTable()->LoadSymbol( aLibrary, aAlias );
625 }
626 catch( const IO_ERROR& e )
627 {
628 wxLogMessage( _( "Cannot load symbol '%s' from library '%s'." ) + e.What(),
629 aAlias,
630 aLibrary );
631 }
632
633 return alias;
634}
635
636
637bool SYMBOL_LIBRARY_MANAGER::SymbolExists( const wxString& aAlias, const wxString& aLibrary ) const
638{
639 auto libBufIt = m_libs.find( aLibrary );
640 LIB_SYMBOL* alias = nullptr;
641
642 if( libBufIt != m_libs.end() )
643 return !!libBufIt->second.GetBuffer( aAlias );
644
645 try
646 {
647 alias = symTable()->LoadSymbol( aLibrary, aAlias );
648 }
649 catch( IO_ERROR& )
650 {
651 // checking if certain symbol exists, so its absence is perfectly fine
652 }
653
654 return alias != nullptr;
655}
656
657
658bool SYMBOL_LIBRARY_MANAGER::LibraryExists( const wxString& aLibrary, bool aCheckEnabled ) const
659{
660 if( aLibrary.IsEmpty() )
661 return false;
662
663 if( m_libs.count( aLibrary ) > 0 )
664 return true;
665
666 return symTable()->HasLibrary( aLibrary, aCheckEnabled );
667}
668
669
671{
672 wxString name = "New_Library";
673
674 if( !LibraryExists( name ) )
675 return name;
676
677 name += "_";
678
679 for( unsigned int i = 0; i < std::numeric_limits<unsigned int>::max(); ++i )
680 {
681 if( !LibraryExists( name + wxString::Format( "%u", i ) ) )
682 return name + wxString::Format( "%u", i );
683 }
684
685 wxFAIL;
686 return wxEmptyString;
687}
688
689
690void SYMBOL_LIBRARY_MANAGER::GetRootSymbolNames( const wxString& aLibraryName,
691 wxArrayString& aRootSymbolNames )
692{
693 LIB_BUFFER& libBuf = getLibraryBuffer( aLibraryName );
694
695 libBuf.GetRootSymbolNames( aRootSymbolNames );
696}
697
698
699bool SYMBOL_LIBRARY_MANAGER:: HasDerivedSymbols( const wxString& aSymbolName,
700 const wxString& aLibraryName )
701{
702 LIB_BUFFER& libBuf = getLibraryBuffer( aLibraryName );
703
704 return libBuf.HasDerivedSymbols( aSymbolName );
705}
706
707
709{
710 return symTable()->GetLogicalLibs().size();
711}
712
713
714wxString SYMBOL_LIBRARY_MANAGER::getLibraryName( const wxString& aFilePath )
715{
716 wxFileName fn( aFilePath );
717 return fn.GetName();
718}
719
720
721bool SYMBOL_LIBRARY_MANAGER::addLibrary( const wxString& aFilePath, bool aCreate,
722 SYMBOL_LIB_TABLE* aTable )
723{
724 wxCHECK( aTable, false );
725 wxString libName = getLibraryName( aFilePath );
726 wxCHECK( !LibraryExists( libName ), false ); // either create or add an existing one
727
728 // try to use path normalized to an environmental variable or project path
729 wxString relPath = NormalizePath( aFilePath, &Pgm().GetLocalEnvVariables(), &m_frame.Prj() );
730
731 SCH_IO_MGR::SCH_FILE_T schFileType = SCH_IO_MGR::GuessPluginTypeFromLibPath( aFilePath );
732 wxString typeName = SCH_IO_MGR::ShowType( schFileType );
733 SYMBOL_LIB_TABLE_ROW* libRow = new SYMBOL_LIB_TABLE_ROW( libName, relPath, typeName );
734 aTable->InsertRow( libRow );
735
736 if( aCreate )
737 {
738 wxCHECK( schFileType != SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY, false );
739
740 try
741 {
742 aTable->CreateSymbolLib( libName );
743 }
744 catch( const IO_ERROR& )
745 {
746 aTable->RemoveRow( libRow );
747 return false;
748 }
749 }
750
752
753 return true;
754}
755
756
758{
759 return m_frame.Prj().SchSymbolLibTable();
760}
761
762
763std::set<LIB_SYMBOL*> SYMBOL_LIBRARY_MANAGER::getOriginalSymbols( const wxString& aLibrary )
764{
765 std::set<LIB_SYMBOL*> symbols;
766 wxCHECK( LibraryExists( aLibrary ), symbols );
767
768 try
769 {
770 wxArrayString aliases;
771 symTable()->EnumerateSymbolLib( aLibrary, aliases );
772
773 for( const auto& aliasName : aliases )
774 {
775 LIB_SYMBOL* alias = symTable()->LoadSymbol( aLibrary, aliasName );
776 symbols.insert( alias );
777 }
778 }
779 catch( const IO_ERROR& e )
780 {
781 wxLogMessage( _( "Cannot enumerate library '%s'." ) + e.What(), aLibrary );
782 }
783
784 return symbols;
785}
786
787
789 const wxString& aLibrary )
790{
791 auto it = m_libs.find( aLibrary );
792
793 if( it != m_libs.end() )
794 return it->second;
795
796 // The requested buffer does not exist yet, so create one
797 auto ret = m_libs.emplace( aLibrary, LIB_BUFFER( aLibrary ) );
798 LIB_BUFFER& buf = ret.first->second;
799
800 for( auto symbol : getOriginalSymbols( aLibrary ) )
801 {
802 LIB_SYMBOL* newSymbol;
803
804 if( symbol->IsAlias() )
805 {
806 std::shared_ptr< LIB_SYMBOL > oldParent = symbol->GetParent().lock();
807
808 wxCHECK_MSG( oldParent, buf,
809 wxString::Format( "Derived symbol '%s' found with undefined parent.",
810 symbol->GetName() ) );
811
812 LIB_SYMBOL* libParent = buf.GetSymbol( oldParent->GetName() );
813
814 if( !libParent )
815 {
816 libParent = new LIB_SYMBOL( *oldParent.get() );
817 buf.CreateBuffer( libParent, new SCH_SCREEN );
818 }
819
820 newSymbol = new LIB_SYMBOL( *symbol );
821 newSymbol->SetParent( libParent );
822 buf.CreateBuffer( newSymbol, new SCH_SCREEN );
823 }
824 else if( !buf.GetSymbol( symbol->GetName() ) )
825 {
826 buf.CreateBuffer( new LIB_SYMBOL( *symbol ), new SCH_SCREEN );
827 }
828 }
829
830 return buf;
831}
832
833
835 std::unique_ptr<SCH_SCREEN> aScreen ) :
836 m_screen( std::move( aScreen ) ),
837 m_symbol( aSymbol )
838{
839 m_original = new LIB_SYMBOL( *aSymbol );
840}
841
842
844{
845 delete m_symbol;
846 delete m_original;
847}
848
849
851{
852 wxCHECK( m_symbol != aSymbol, /* void */ );
853 wxASSERT( aSymbol );
854 delete m_symbol;
855 m_symbol = aSymbol;
856
857 // If the symbol moves libraries then the original moves with it
858 if( m_original->GetLibId().GetLibNickname() != m_symbol->GetLibId().GetLibNickname() )
859 {
860 m_original->SetLibId( LIB_ID( m_symbol->GetLibId().GetLibNickname(),
861 m_original->GetLibId().GetLibItemName() ) );
862 }
863}
864
865
867{
868 wxCHECK( m_original != aSymbol, /* void */ );
869 wxASSERT( aSymbol );
870 delete m_original;
871 m_original = aSymbol;
872
873 // The original is not allowed to have a different library than its symbol
874 if( m_original->GetLibId().GetLibNickname() != m_symbol->GetLibId().GetLibNickname() )
875 {
876 m_original->SetLibId( LIB_ID( m_symbol->GetLibId().GetLibNickname(),
877 m_original->GetLibId().GetLibItemName() ) );
878 }
879}
880
881
883{
884 return m_screen && m_screen->IsContentModified();
885}
886
887
889{
890 auto buf = GetBuffer( aAlias );
891
892 if( !buf )
893 return nullptr;
894
895 LIB_SYMBOL* symbol = buf->GetSymbol();
896
897 wxCHECK( symbol, nullptr );
898
899 return symbol;
900}
901
902
904{
905 wxASSERT( aCopy );
906 wxASSERT( aCopy->GetLib() == nullptr );
907 std::unique_ptr<SCH_SCREEN> screen( aScreen );
908 auto symbolBuf = std::make_shared<SYMBOL_BUFFER>( aCopy, std::move( screen ) );
909 m_symbols.push_back( symbolBuf );
910
911 // Set the parent library name,
912 // otherwise it is empty as no library has been given as the owner during object construction
913 LIB_ID libId = aCopy->GetLibId();
914 libId.SetLibNickname( m_libName );
915 aCopy->SetLibId( libId );
916 ++m_hash;
917
918 return true;
919}
920
921
922bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::UpdateBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf,
923 LIB_SYMBOL* aCopy )
924{
925 wxCHECK( aCopy && aSymbolBuf, false );
926
927 LIB_SYMBOL* bufferedSymbol = aSymbolBuf->GetSymbol();
928
929 wxCHECK( bufferedSymbol, false );
930
931 *bufferedSymbol = *aCopy;
932 ++m_hash;
933
934 return true;
935}
936
937
938bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::DeleteBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf )
939{
940 auto symbolBufIt = std::find( m_symbols.begin(), m_symbols.end(), aSymbolBuf );
941 wxCHECK( symbolBufIt != m_symbols.end(), false );
942
943 bool retv = true;
944
945 // Remove all derived symbols to prevent broken inheritance.
946 if( aSymbolBuf->GetSymbol()->IsRoot() && HasDerivedSymbols( aSymbolBuf->GetSymbol()->GetName() )
947 && removeChildSymbols( aSymbolBuf ) == 0 )
948 {
949 retv = false;
950 }
951
952 m_deleted.emplace_back( *symbolBufIt );
953 m_symbols.erase( symbolBufIt );
954 ++m_hash;
955
956 return retv;
957}
958
959
960bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::SaveBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf,
961 SYMBOL_LIB_TABLE* aLibTable )
962{
963 wxCHECK( aSymbolBuf, false );
964 LIB_SYMBOL* libSymbol = aSymbolBuf->GetSymbol();
965 LIB_SYMBOL* originalSymbol = aSymbolBuf->GetOriginal();
966 wxCHECK( libSymbol && originalSymbol, false );
968 STRING_UTF8_MAP properties;
969 properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
970
971 wxString errorMsg = _( "Error saving symbol %s to library '%s'." ) + wxS( "\n%s" );
972
973 // Delete the original symbol if the symbol name has been changed.
974 if( libSymbol->GetName() != originalSymbol->GetName() )
975 {
976 // DeleteSymbol may throw
977 try
978 {
979 if( aLibTable->LoadSymbol( m_libName, originalSymbol->GetName() ) )
980 aLibTable->DeleteSymbol( m_libName, originalSymbol->GetName() );
981 }
982 catch( const IO_ERROR& ioe )
983 {
984 wxLogError( errorMsg, UnescapeString( originalSymbol->GetName() ), m_libName,
985 ioe.What() );
986 return false;
987 }
988 }
989
990 if( libSymbol->IsAlias() )
991 {
992 LIB_SYMBOL* newCachedSymbol = new LIB_SYMBOL( *libSymbol );
993 std::shared_ptr< LIB_SYMBOL > bufferedParent = libSymbol->GetParent().lock();
994
995 wxCHECK( bufferedParent, false );
996
997 LIB_SYMBOL* cachedParent = aLibTable->LoadSymbol( m_libName, bufferedParent->GetName() );
998
999 if( !cachedParent )
1000 {
1001 cachedParent = new LIB_SYMBOL( *bufferedParent.get() );
1002 newCachedSymbol->SetParent( cachedParent );
1003 result = aLibTable->SaveSymbol( m_libName, cachedParent );
1004 wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1005 result = aLibTable->SaveSymbol( m_libName, newCachedSymbol );
1006 wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1007
1008 LIB_SYMBOL* originalParent = new LIB_SYMBOL( *bufferedParent.get() );
1009 aSymbolBuf->SetOriginal( originalParent );
1010 originalSymbol = new LIB_SYMBOL( *libSymbol );
1011 originalSymbol->SetParent( originalParent );
1012 aSymbolBuf->SetOriginal( originalSymbol );
1013 }
1014 else
1015 {
1016 newCachedSymbol->SetParent( cachedParent );
1017 result = aLibTable->SaveSymbol( m_libName, newCachedSymbol );
1018 wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1019
1020 auto originalBufferedParent = GetBuffer( bufferedParent->GetName() );
1021 wxCHECK( originalBufferedParent, false );
1022 originalSymbol = new LIB_SYMBOL( *libSymbol );
1023 originalSymbol->SetParent( originalBufferedParent->GetSymbol() );
1024 aSymbolBuf->SetOriginal( originalSymbol );
1025 }
1026 }
1027 else
1028 {
1029 wxArrayString derivedSymbols;
1030
1031 if( GetDerivedSymbolNames( libSymbol->GetName(), derivedSymbols ) == 0 )
1032 {
1033 result = aLibTable->SaveSymbol( m_libName, new LIB_SYMBOL( *libSymbol ) );
1034 wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1035 aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1036 }
1037 else
1038 {
1039 LIB_SYMBOL* parentSymbol = new LIB_SYMBOL( *libSymbol );
1040
1041 aLibTable->SaveSymbol( m_libName, parentSymbol );
1042
1043 for( auto& entry : derivedSymbols )
1044 {
1045 std::shared_ptr<SYMBOL_BUFFER> symbol = GetBuffer( entry );
1046
1047 wxCHECK2( symbol, continue );
1048
1049 LIB_SYMBOL* derivedSymbol = new LIB_SYMBOL( *symbol->GetSymbol() );
1050 derivedSymbol->SetParent( parentSymbol );
1051 result = aLibTable->SaveSymbol( m_libName, derivedSymbol );
1052 wxCHECK( result == SYMBOL_LIB_TABLE::SAVE_OK, false );
1053 }
1054 }
1055 }
1056
1057 ++m_hash;
1058 return true;
1059}
1060
1061
1062bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::SaveBuffer( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf,
1063 const wxString& aFileName,
1064 SCH_PLUGIN* aPlugin, bool aBuffer )
1065{
1066 wxCHECK( aSymbolBuf, false );
1067 LIB_SYMBOL* libSymbol = aSymbolBuf->GetSymbol();
1068 LIB_SYMBOL* originalSymbol = aSymbolBuf->GetOriginal();
1069 wxCHECK( libSymbol && originalSymbol, false );
1070 wxCHECK( !aFileName.IsEmpty(), false );
1071
1072 wxString errorMsg = _( "Error saving symbol %s to library '%s'." ) + wxS( "\n%s" );
1073
1074 // set properties to prevent save file on every symbol save
1075 STRING_UTF8_MAP properties;
1076 properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
1077
1078 // Delete the original symbol if the symbol name has been changed.
1079 if( libSymbol->GetName() != originalSymbol->GetName() )
1080 {
1081 try
1082 {
1083 if( aPlugin->LoadSymbol( aFileName, originalSymbol->GetName() ) )
1084 aPlugin->DeleteSymbol( aFileName, originalSymbol->GetName(), &properties );
1085 }
1086 catch( const IO_ERROR& ioe )
1087 {
1088 wxLogError( errorMsg, UnescapeString( originalSymbol->GetName() ), aFileName,
1089 ioe.What() );
1090 return false;
1091 }
1092 }
1093
1094 if( libSymbol->IsAlias() )
1095 {
1096 LIB_SYMBOL* newCachedSymbol = new LIB_SYMBOL( *libSymbol );
1097 std::shared_ptr< LIB_SYMBOL > bufferedParent = libSymbol->GetParent().lock();
1098
1099 wxCHECK( bufferedParent, false );
1100
1101 LIB_SYMBOL* cachedParent = nullptr;
1102
1103 try
1104 {
1105 cachedParent = aPlugin->LoadSymbol( aFileName, bufferedParent->GetName() );
1106 }
1107 catch( const IO_ERROR& )
1108 {
1109 return false;
1110 }
1111
1112 if( !cachedParent )
1113 {
1114 cachedParent = new LIB_SYMBOL( *bufferedParent.get() );
1115 newCachedSymbol->SetParent( cachedParent );
1116
1117 try
1118 {
1119 aPlugin->SaveSymbol( aFileName, cachedParent, aBuffer ? &properties : nullptr );
1120 }
1121 catch( const IO_ERROR& ioe )
1122 {
1123 wxLogError( errorMsg, UnescapeString( cachedParent->GetName() ), aFileName,
1124 ioe.What() );
1125 return false;
1126 }
1127
1128 try
1129 {
1130 aPlugin->SaveSymbol( aFileName, newCachedSymbol, aBuffer ? &properties : nullptr );
1131 }
1132 catch( const IO_ERROR& ioe )
1133 {
1134 wxLogError( errorMsg, UnescapeString( newCachedSymbol->GetName() ), aFileName,
1135 ioe.What() );
1136 return false;
1137 }
1138
1139 LIB_SYMBOL* originalParent = new LIB_SYMBOL( *bufferedParent.get() );
1140 aSymbolBuf->SetOriginal( originalParent );
1141 originalSymbol = new LIB_SYMBOL( *libSymbol );
1142 originalSymbol->SetParent( originalParent );
1143 aSymbolBuf->SetOriginal( originalSymbol );
1144 }
1145 else
1146 {
1147 newCachedSymbol->SetParent( cachedParent );
1148
1149 try
1150 {
1151 aPlugin->SaveSymbol( aFileName, newCachedSymbol, aBuffer ? &properties : nullptr );
1152 }
1153 catch( const IO_ERROR& ioe )
1154 {
1155 wxLogError( errorMsg, UnescapeString( newCachedSymbol->GetName() ), aFileName,
1156 ioe.What() );
1157 return false;
1158 }
1159
1160 auto originalBufferedParent = GetBuffer( bufferedParent->GetName() );
1161 wxCHECK( originalBufferedParent, false );
1162 originalSymbol = new LIB_SYMBOL( *libSymbol );
1163 originalSymbol->SetParent( originalBufferedParent->GetSymbol() );
1164 aSymbolBuf->SetOriginal( originalSymbol );
1165 }
1166 }
1167 else
1168 {
1169 wxArrayString derivedSymbols;
1170
1171 if( GetDerivedSymbolNames( libSymbol->GetName(), derivedSymbols ) == 0 )
1172 {
1173 try
1174 {
1175 aPlugin->SaveSymbol( aFileName, new LIB_SYMBOL( *libSymbol ),
1176 aBuffer ? &properties : nullptr );
1177 }
1178 catch( const IO_ERROR& ioe )
1179 {
1180 wxLogError( errorMsg, UnescapeString( libSymbol->GetName() ), aFileName,
1181 ioe.What() );
1182 return false;
1183 }
1184
1185 aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1186 }
1187 else
1188 {
1189 LIB_SYMBOL* parentSymbol = new LIB_SYMBOL( *libSymbol );
1190
1191 // Save the modified root symbol.
1192 try
1193 {
1194 aPlugin->SaveSymbol( aFileName, parentSymbol, aBuffer ? &properties : nullptr );
1195 }
1196 catch( const IO_ERROR& ioe )
1197 {
1198 wxLogError( errorMsg, UnescapeString( libSymbol->GetName() ), aFileName,
1199 ioe.What() );
1200 return false;
1201 }
1202
1203 aSymbolBuf->SetOriginal( new LIB_SYMBOL( *libSymbol ) );
1204
1205 // Save the derived symbols.
1206 for( const wxString& entry : derivedSymbols )
1207 {
1208 std::shared_ptr<SYMBOL_BUFFER> symbol = GetBuffer( entry );
1209
1210 wxCHECK2( symbol, continue );
1211
1212 LIB_SYMBOL* derivedSymbol = new LIB_SYMBOL( *symbol->GetSymbol() );
1213 derivedSymbol->SetParent( parentSymbol );
1214
1215 try
1216 {
1217 aPlugin->SaveSymbol( aFileName, new LIB_SYMBOL( *derivedSymbol ),
1218 aBuffer ? &properties : nullptr );
1219 }
1220 catch( const IO_ERROR& ioe )
1221 {
1222 wxLogError( errorMsg, UnescapeString( derivedSymbol->GetName() ), aFileName,
1223 ioe.What() );
1224 return false;
1225 }
1226 }
1227 }
1228 }
1229
1230 ++m_hash;
1231 return true;
1232}
1233
1234
1235std::shared_ptr<SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER>
1237{
1238 for( std::shared_ptr<SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER> entry : m_symbols )
1239 {
1240 if( entry->GetSymbol()->GetName() == aAlias )
1241 return entry;
1242 }
1243
1244 return std::shared_ptr<SYMBOL_BUFFER>( nullptr );
1245}
1246
1247
1248bool SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::HasDerivedSymbols( const wxString& aParentName ) const
1249{
1250 for( auto& entry : m_symbols )
1251 {
1252 if( entry->GetSymbol()->IsAlias() )
1253 {
1254 LIB_SYMBOL_SPTR parent = entry->GetSymbol()->GetParent().lock();
1255
1256 // Check for inherited symbol without a valid parent.
1257 wxCHECK( parent, false );
1258
1259 if( parent->GetName() == aParentName )
1260 return true;
1261 }
1262 }
1263
1264 return false;
1265}
1266
1267
1268void SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::GetRootSymbolNames( wxArrayString& aRootSymbolNames )
1269{
1270 for( auto& entry : m_symbols )
1271 {
1272 if( entry->GetSymbol()->IsAlias() )
1273 continue;
1274
1275 aRootSymbolNames.Add( UnescapeString( entry->GetSymbol()->GetName() ) );
1276 }
1277}
1278
1279
1281 wxArrayString& aList )
1282{
1283 wxCHECK( !aSymbolName.IsEmpty(), 0 );
1284
1285 for( auto& entry : m_symbols )
1286 {
1287 if( entry->GetSymbol()->IsAlias() )
1288 {
1289 LIB_SYMBOL_SPTR parent = entry->GetSymbol()->GetParent().lock();
1290
1291 // Check for inherited symbol without a valid parent.
1292 wxCHECK( parent, false );
1293
1294 if( parent->GetName() == aSymbolName )
1295 aList.Add( entry->GetSymbol()->GetName() );
1296 }
1297 }
1298
1299 return aList.GetCount();
1300}
1301
1302
1303int SYMBOL_LIBRARY_MANAGER::LIB_BUFFER::removeChildSymbols( std::shared_ptr<SYMBOL_BUFFER> aSymbolBuf )
1304{
1305 wxCHECK( aSymbolBuf && aSymbolBuf->GetSymbol()->IsRoot(), 0 );
1306
1307 int cnt = 0;
1308 std::deque< std::shared_ptr<SYMBOL_BUFFER> >::iterator it = m_symbols.begin();
1309
1310 while( it != m_symbols.end() )
1311 {
1312
1313 if( (*it)->GetSymbol()->IsRoot() )
1314 {
1315 ++it;
1316 }
1317 else
1318 {
1319 LIB_SYMBOL_SPTR parent = (*it)->GetSymbol()->GetParent().lock();
1320
1321 wxCHECK2( parent, ++it; continue );
1322
1323 if( parent->GetName() == aSymbolBuf->GetSymbol()->GetName() )
1324 {
1325 wxCHECK2( parent == aSymbolBuf->GetSymbol()->SharedPtr(), ++it; continue );
1326
1327 m_deleted.emplace_back( *it );
1328 it = m_symbols.erase( it );
1329 cnt++;
1330 }
1331 else
1332 {
1333 ++it;
1334 }
1335 }
1336 }
1337
1338 return cnt;
1339}
const char * name
Definition: DXF_plotter.cpp:56
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
void MessageSet(const wxString &message)
Add a message (in bold) to message list.
void AddHTML_Text(const wxString &message)
Add HTML text (without any change) to message list.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:76
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:46
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:98
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
Define a library symbol object.
Definition: lib_symbol.h:99
bool IsAlias() const
Definition: lib_symbol.h:188
LIB_ID GetLibId() const override
Definition: lib_symbol.h:141
void SetParent(LIB_SYMBOL *aParent=nullptr)
Definition: lib_symbol.cpp:447
wxString GetName() const override
Definition: lib_symbol.h:138
SYMBOL_LIB * GetLib() const
Definition: lib_symbol.h:192
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:142
LIB_SYMBOL_REF & GetParent()
Definition: lib_symbol.h:127
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
bool RemoveRow(const LIB_TABLE_ROW *aRow)
Removes a row from the table.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:41
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
static const wxString ShowType(SCH_FILE_T aFileType)
Return a brief name for a plugin, given aFileType enum.
Definition: sch_io_mgr.cpp:81
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:156
static const char * PropBuffering
The property used internally by the plugin to enable cache buffering which prevents the library file ...
Helper object to release a SCH_PLUGIN in the context of a potential thrown exception through its dest...
Definition: sch_io_mgr.h:535
Base class that schematic file and library loading and saving plugins should derive from.
Definition: sch_io_mgr.h:155
virtual void SaveSymbol(const wxString &aLibraryPath, const LIB_SYMBOL *aSymbol, const STRING_UTF8_MAP *aProperties=nullptr)
Write aSymbol to an existing library located at aLibraryPath.
Definition: sch_plugin.cpp:94
virtual void DeleteSymbol(const wxString &aLibraryPath, const wxString &aSymbolName, const STRING_UTF8_MAP *aProperties=nullptr)
Delete the entire LIB_SYMBOL associated with aAliasName from the library aLibraryPath.
Definition: sch_plugin.cpp:102
virtual void SaveLibrary(const wxString &aFileName, const STRING_UTF8_MAP *aProperties=nullptr)
Definition: sch_plugin.cpp:45
virtual LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aPartName, const STRING_UTF8_MAP *aProperties=nullptr)
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
Definition: sch_plugin.cpp:85
A name/value tuple with unique names and optional values.
bool Done()
Returns a string containing any errors generated during the load.
const wxString & GetErrors() const
Represents a pair of <nickname, loaded parts list>
void Start()
Spins up threads to load all the libraries in m_nicknames.
bool Join()
Finalizes the threads and combines the output into the target output map.
LIB_SYMBOL * GetSymbol(const wxString &aAlias) const
Create a new buffer to store a symbol. LIB_BUFFER takes ownership of aCopy.
void ClearDeletedBuffer()
Save stored modifications to Symbol Lib Table.
bool HasDerivedSymbols(const wxString &aParentName) const
Check to see any symbols in the buffer are derived from a parent named aParentName.
bool SaveBuffer(std::shared_ptr< SYMBOL_BUFFER > aSymbolBuf, SYMBOL_LIB_TABLE *aLibTable)
Save stored modifications using a plugin.
void GetRootSymbolNames(wxArrayString &aRootSymbolNames)
Fetch a list of root symbols names from the library buffer.
const std::deque< std::shared_ptr< SYMBOL_BUFFER > > & GetBuffers() const
int removeChildSymbols(std::shared_ptr< SYMBOL_BUFFER > aSymbolBuf)
Remove all symbols derived from aParent from the library buffer.
std::shared_ptr< SYMBOL_BUFFER > GetBuffer(const wxString &aAlias) const
Return all buffered symbols.
bool UpdateBuffer(std::shared_ptr< SYMBOL_BUFFER > aSymbolBuf, LIB_SYMBOL *aCopy)
bool DeleteBuffer(std::shared_ptr< SYMBOL_BUFFER > aSymbolBuf)
bool CreateBuffer(LIB_SYMBOL *aCopy, SCH_SCREEN *aScreen)
Update the buffered symbol with the contents of aCopy.
size_t GetDerivedSymbolNames(const wxString &aSymbolName, wxArrayString &aList)
Fetch all of the symbols derived from a aSymbolName into aList.
SYMBOL_BUFFER(LIB_SYMBOL *aSymbol=nullptr, std::unique_ptr< SCH_SCREEN > aScreen=nullptr)
LIB_SYMBOL * GetBufferedSymbol(const wxString &aAlias, const wxString &aLibrary)
Return the symbol copy from the buffer.
bool UpdateSymbolAfterRename(LIB_SYMBOL *aSymbol, const wxString &oldAlias, const wxString &aLibrary)
Update the symbol buffer with a new version of the symbol when the name has changed.
bool IsLibraryReadOnly(const wxString &aLibrary) const
Return true if the library is stored in a read-only file.
bool addLibrary(const wxString &aFilePath, bool aCreate, SYMBOL_LIB_TABLE *aTable)
Return the current Symbol Library Table.
bool ClearSymbolModified(const wxString &aAlias, const wxString &aLibrary) const
Clear the modified flag for a symbol.
bool LibraryExists(const wxString &aLibrary, bool aCheckEnabled=false) const
Return true if library exists.
bool ClearLibraryModified(const wxString &aLibrary) const
Clear the modified flag for all symbols in a library.
LIB_SYMBOL * GetAlias(const wxString &aAlias, const wxString &aLibrary) const
Return either an alias of a working LIB_SYMBOL copy, or alias of the original symbol if there is no w...
SCH_SCREEN * GetScreen(const wxString &aAlias, const wxString &aLibrary)
Return the screen used to edit a specific symbol.
bool IsLibraryModified(const wxString &aLibrary) const
Return true if library has unsaved modifications.
wxArrayString GetLibraryNames() const
Return the array of library names.
void SetSymbolModified(const wxString &aAlias, const wxString &aLibrary)
void GetRootSymbolNames(const wxString &aLibName, wxArrayString &aRootSymbolNames)
bool SymbolExists(const wxString &aAlias, const wxString &aLibrary) const
Return true if symbol with a specific alias exists in library (either original one or buffered).
wxString GetUniqueLibraryName() const
Return a library name that is not currently in use.
bool RemoveSymbol(const wxString &aName, const wxString &aLibrary)
Remove the symbol from the symbol buffer.
static wxString getLibraryName(const wxString &aFilePath)
Helper function to add either existing or create new library.
LIB_BUFFER & getLibraryBuffer(const wxString &aLibrary)
Return an existing library buffer or creates one to using Symbol Library Table to get the original da...
virtual void OnDataChanged() const
Extract library name basing on the file name.
bool IsSymbolModified(const wxString &aAlias, const wxString &aLibrary) const
Return true if symbol has unsaved modifications.
bool IsLibraryLoaded(const wxString &aLibrary) const
Return true if the library was successfully loaded.
SYMBOL_LIB_TABLE * symTable() const
Class to store a working copy of a LIB_SYMBOL object and editor context.
bool RevertLibrary(const wxString &aLibrary)
Revert unsaved changes for a symbolicular library.
std::set< LIB_SYMBOL * > getOriginalSymbols(const wxString &aLibrary)
Return a set of LIB_SYMBOL objects belonging to the original library.
int GetLibraryHash(const wxString &aLibrary) const
Return a library hash value to determine if it has changed.
void Preload(PROGRESS_REPORTER &aReporter)
Preloads all symbol libraries in the symbol library table using SYMBOL_ASYNC_LOADER.
bool RevertAll()
Revert all pending changes.
SYMBOL_LIBRARY_MANAGER(SCH_BASE_FRAME &aFrame)
LIB_ID RevertSymbol(const wxString &aAlias, const wxString &aLibrary)
Revert unsaved changes for a symbolicular symbol.
SYMBOL_LIB_TABLE_ROW * GetLibrary(const wxString &aLibrary) const
Find a single library within the (aggregate) library table.
SCH_BASE_FRAME & m_frame
Parent frame.
std::list< LIB_SYMBOL * > GetAliases(const wxString &aLibrary) const
bool UpdateSymbol(LIB_SYMBOL *aSymbol, const wxString &aLibrary)
Update the symbol buffer with a new version of the symbol.
bool SaveLibrary(const wxString &aLibrary, const wxString &aFileName, SCH_IO_MGR::SCH_FILE_T aFileType=SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY)
Save library to a file, including unsaved changes.
bool HasDerivedSymbols(const wxString &aSymbolName, const wxString &aLibraryName)
Check if symbol aSymbolName in library aLibraryName is a root symbol that has derived symbols.
std::map< wxString, LIB_BUFFER > m_libs
bool FlushSymbol(const wxString &aAlias, const wxString &aLibrary)
Save symbol changes to the library copy used by the schematic editor.
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_PLUGIN obje...
void LoadSymbolLib(std::vector< LIB_SYMBOL * > &aAliasList, const wxString &aNickname, bool aPowerSymbolsOnly=false)
void DeleteSymbol(const wxString &aNickname, const wxString &aSymbolName)
Deletes the aSymbolName from the library given by aNickname.
bool IsSymbolLibWritable(const wxString &aNickname)
Return true if the library given by aNickname is writable.
bool IsSymbolLibLoaded(const wxString &aNickname)
Return true if the library given by aNickname was successfully loaded.
void CreateSymbolLib(const wxString &aNickname)
void EnumerateSymbolLib(const wxString &aNickname, wxArrayString &aAliasNames, bool aPowerSymbolsOnly=false)
Return a list of symbol alias names contained within the library given by aNickname.
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
SAVE_T SaveSymbol(const wxString &aNickname, const LIB_SYMBOL *aSymbol, bool aOverwrite=true)
Write aSymbol to an existing library given by aNickname.
SAVE_T
The set of return values from SaveSymbol() below.
SYMBOL_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an SYMBOL_LIB_TABLE_ROW if aNickName is found in this table or in any chained fallBack table f...
#define _(s)
wxString NormalizePath(const wxFileName &aFilePath, const ENV_VAR_MAP *aEnvVars, const wxString &aProjectPath)
Normalize a file path to an environmental variable, if possible.
Definition: env_paths.cpp:71
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
std::shared_ptr< LIB_SYMBOL > LIB_SYMBOL_SPTR
shared pointer to LIB_SYMBOL
Definition: lib_symbol.h:45
Definition: bitmap.cpp:64
see class PGM_BASE
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
wxString UnescapeString(const wxString &aSource)
Definition for symbol library class.
VECTOR3I res
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition: wx_filename.h:38