KiCad PCB EDA Suite
Loading...
Searching...
No Matches
symbol_editor.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) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2008 Wayne Stambaugh <[email protected]>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
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 2
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 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <pgm_base.h>
27#include <clipboard.h>
28#include <confirm.h>
29#include <kidialog.h>
30#include <kiway.h>
31#include <widgets/wx_infobar.h>
33#include <symbol_edit_frame.h>
34#include <symbol_library.h>
35#include <template_fieldnames.h>
37#include <symbol_lib_table.h>
39#include <symbol_tree_pane.h>
41#include <widgets/lib_tree.h>
45#include <eda_list_dialog.h>
46#include <wx/clipbrd.h>
47#include <wx/filedlg.h>
48#include <wx/log.h>
49#include <project_sch.h>
50#include <string_utils.h>
51#include "symbol_saveas_type.h"
52
55
56
58{
59 wxString title;
60
62 {
64 title = wxT( "*" );
65
66 title += m_reference;
67 title += wxS( " " ) + _( "[from schematic]" );
68 }
69 else if( GetCurSymbol() )
70 {
72 title = wxT( "*" );
73
74 title += UnescapeString( GetCurSymbol()->GetLibId().Format() );
75
77 title += wxS( " " ) + _( "[Read Only Library]" );
78 }
79 else
80 {
81 title = _( "[no symbol loaded]" );
82 }
83
84 title += wxT( " \u2014 " ) + _( "Symbol Editor" );
85 SetTitle( title );
86}
87
88
89void SYMBOL_EDIT_FRAME::SelectActiveLibrary( const wxString& aLibrary )
90{
91 wxString selectedLib = aLibrary;
92
93 if( selectedLib.empty() )
94 selectedLib = SelectLibraryFromList();
95
96 if( !selectedLib.empty() )
97 SetCurLib( selectedLib );
98
100}
101
102
104{
105 if( GetCurSymbol() )
106 {
108 {
109 SCH_EDIT_FRAME* schframe = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, false );
110
111 if( !schframe ) // happens when the schematic editor has been closed
112 {
113 DisplayErrorMessage( this, _( "No schematic currently open." ) );
114 return false;
115 }
116 else
117 {
119 GetScreen()->SetContentModified( false );
120 return true;
121 }
122 }
123 else
124 {
125 const wxString& libName = GetCurSymbol()->GetLibId().GetLibNickname();
126
127 if( m_libMgr->IsLibraryReadOnly( libName ) )
128 {
129 wxString msg = wxString::Format( _( "Symbol library '%s' is not writable." ),
130 libName );
131 wxString msg2 = _( "You must save to a different location." );
132
133 if( OKOrCancelDialog( this, _( "Warning" ), msg, msg2 ) == wxID_OK )
134 return saveLibrary( libName, true );
135 }
136 else
137 {
138 return saveLibrary( libName, false );
139 }
140 }
141 }
142
143 return false;
144}
145
146
147bool SYMBOL_EDIT_FRAME::LoadSymbol( const LIB_ID& aLibId, int aUnit, int aBodyStyle )
148{
149 LIB_ID libId = aLibId;
150
151 // Some libraries can't be edited, so load the underlying chosen symbol
153 {
154 if( lib->SchLibType() == SCH_IO_MGR::SCH_DATABASE
155 || lib->SchLibType() == SCH_IO_MGR::SCH_CADSTAR_ARCHIVE
156 || lib->SchLibType() == SCH_IO_MGR::SCH_HTTP )
157
158 {
159 try
160 {
161 LIB_SYMBOL* readOnlySym = PROJECT_SCH::SchSymbolLibTable( &Prj() )->LoadSymbol( aLibId );
162
163 if( readOnlySym && readOnlySym->GetSourceLibId().IsValid() )
164 libId = readOnlySym->GetSourceLibId();
165 }
166 catch( const IO_ERROR& ioe )
167 {
168 wxString msg;
169
170 msg.Printf( _( "Error loading symbol %s from library '%s'." ),
171 aLibId.GetUniStringLibId(), aLibId.GetUniStringLibItemName() );
172 DisplayErrorMessage( this, msg, ioe.What() );
173 return false;
174 }
175 }
176 }
177
179 && GetCurSymbol()->GetLibId() == libId
180 && GetUnit() == aUnit
181 && GetBodyStyle() == aBodyStyle )
182 {
183 return true;
184 }
185
187 {
188 if( !HandleUnsavedChanges( this, _( "The current symbol has been modified. Save changes?" ),
189 [&]() -> bool
190 {
191 return saveCurrentSymbol();
192 } ) )
193 {
194 return false;
195 }
196 }
197
199
200 if( LoadSymbolFromCurrentLib( libId.GetLibItemName(), aUnit, aBodyStyle ) )
201 {
202 m_treePane->GetLibTree()->SelectLibId( libId );
203 m_treePane->GetLibTree()->ExpandLibId( libId );
204
205 m_centerItemOnIdle = libId;
206 Bind( wxEVT_IDLE, &SYMBOL_EDIT_FRAME::centerItemIdleHandler, this );
207 setSymWatcher( &libId );
208
209 return true;
210 }
211
212 return false;
213}
214
215
217{
219 Unbind( wxEVT_IDLE, &SYMBOL_EDIT_FRAME::centerItemIdleHandler, this );
220}
221
222
223bool SYMBOL_EDIT_FRAME::LoadSymbolFromCurrentLib( const wxString& aSymbolName, int aUnit,
224 int aBodyStyle )
225{
226 LIB_SYMBOL* symbol = nullptr;
227
228 try
229 {
230 symbol = PROJECT_SCH::SchSymbolLibTable( &Prj() )->LoadSymbol( GetCurLib(), aSymbolName );
231 }
232 catch( const IO_ERROR& ioe )
233 {
234 wxString msg;
235
236 msg.Printf( _( "Error loading symbol %s from library '%s'." ),
237 aSymbolName,
238 GetCurLib() );
239 DisplayErrorMessage( this, msg, ioe.What() );
240 return false;
241 }
242
243 if( !symbol || !LoadOneLibrarySymbolAux( symbol, GetCurLib(), aUnit, aBodyStyle ) )
244 return false;
245
246 // Enable synchronized pin edit mode for symbols with interchangeable units
248
251 SetShowDeMorgan( GetCurSymbol()->Flatten()->HasAlternateBodyStyle() );
252
253 if( aUnit > 0 )
255
256 return true;
257}
258
259
260bool SYMBOL_EDIT_FRAME::LoadOneLibrarySymbolAux( LIB_SYMBOL* aEntry, const wxString& aLibrary,
261 int aUnit, int aBodyStyle )
262{
263 bool rebuildMenuAndToolbar = false;
264
265 if( !aEntry || aLibrary.empty() )
266 return false;
267
268 if( aEntry->GetName().IsEmpty() )
269 {
270 wxLogWarning( "Symbol in library '%s' has empty name field.", aLibrary );
271 return false;
272 }
273
275
276 // Symbols from the schematic are edited in place and not managed by the library manager.
278 {
279 delete m_symbol;
280 m_symbol = nullptr;
281
282 SCH_SCREEN* screen = GetScreen();
283 delete screen;
286 rebuildMenuAndToolbar = true;
287 }
288
289 LIB_SYMBOL* lib_symbol = m_libMgr->GetBufferedSymbol( aEntry->GetName(), aLibrary );
290 wxCHECK( lib_symbol, false );
291
292 m_unit = aUnit > 0 ? aUnit : 1;
293 m_bodyStyle = aBodyStyle > 0 ? aBodyStyle : 1;
294
295 // The buffered screen for the symbol
296 SCH_SCREEN* symbol_screen = m_libMgr->GetScreen( lib_symbol->GetName(), aLibrary );
297
298 SetScreen( symbol_screen );
299 SetCurSymbol( new LIB_SYMBOL( *lib_symbol ), true );
300 SetCurLib( aLibrary );
301
302 if( rebuildMenuAndToolbar )
303 {
306 GetInfoBar()->Dismiss();
307 }
308
309 UpdateTitle();
311 SetShowDeMorgan( GetCurSymbol()->HasAlternateBodyStyle() );
312
314
315 if( !IsSymbolFromSchematic() )
316 {
317 LIB_ID libId = GetCurSymbol()->GetLibId();
318 setSymWatcher( &libId );
319 }
320
321 // Let tools add things to the view if necessary
322 if( m_toolManager )
324
326
327 // Display the document information based on the entry selected just in
328 // case the entry is an alias.
330 Refresh();
331
332 return true;
333}
334
335
337{
338 saveAllLibraries( false );
340}
341
342
343void SYMBOL_EDIT_FRAME::CreateNewSymbol( const wxString& aInheritFrom )
344{
346
347 wxArrayString symbolNames;
348 wxString lib = getTargetLib();
349
350 if( !m_libMgr->LibraryExists( lib ) )
351 {
352 lib = SelectLibraryFromList();
353
354 if( !m_libMgr->LibraryExists( lib ) )
355 return;
356 }
357
358 const auto validator =
359 [&]( wxString newName ) -> bool
360 {
361 if( newName.IsEmpty() )
362 {
363 wxMessageBox( _( "Symbol must have a name." ) );
364 return false;
365 }
366
367 if( !lib.empty() && m_libMgr->SymbolNameInUse( newName, lib ) )
368 {
369 wxString msg;
370
371 msg.Printf( _( "Symbol '%s' already exists in library '%s'." ),
372 UnescapeString( newName ),
373 lib );
374
375 KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
376 wxOK | wxCANCEL | wxICON_WARNING );
377
378 errorDlg.SetOKLabel( _( "Overwrite" ) );
379
380 return errorDlg.ShowModal() == wxID_OK;
381 }
382
383 return true;
384 };
385
386 wxArrayString symbolNamesInLib;
387 m_libMgr->GetSymbolNames( lib, symbolNamesInLib );
388
389 DIALOG_LIB_NEW_SYMBOL dlg( this, symbolNamesInLib, aInheritFrom, validator );
390
391 dlg.SetMinSize( dlg.GetSize() );
392
393 if( dlg.ShowModal() == wxID_CANCEL )
394 return;
395
396 wxString name = dlg.GetName();
397
398 LIB_SYMBOL new_symbol( name ); // do not create symbol on the heap, it will be buffered soon
399
400 wxString parentSymbolName = dlg.GetParentSymbolName();
401
402 if( parentSymbolName.IsEmpty() )
403 {
404 new_symbol.GetReferenceField().SetText( dlg.GetReference() );
405 new_symbol.SetUnitCount( dlg.GetUnitCount() );
406
407 // Initialize new_symbol.m_TextInside member:
408 // if 0, pin text is outside the body (on the pin)
409 // if > 0, pin text is inside the body
410 if( dlg.GetPinNameInside() )
411 {
412 new_symbol.SetPinNameOffset( dlg.GetPinTextPosition() );
413
414 if( new_symbol.GetPinNameOffset() == 0 )
415 new_symbol.SetPinNameOffset( 1 );
416 }
417 else
418 {
419 new_symbol.SetPinNameOffset( 0 );
420 }
421
422 ( dlg.GetPowerSymbol() ) ? new_symbol.SetGlobalPower() : new_symbol.SetNormal();
423 new_symbol.SetShowPinNumbers( dlg.GetShowPinNumber() );
424 new_symbol.SetShowPinNames( dlg.GetShowPinName() );
425 new_symbol.LockUnits( !dlg.GetUnitsInterchangeable() );
426 new_symbol.SetExcludedFromBOM( !dlg.GetIncludeInBom() );
427 new_symbol.SetExcludedFromBoard( !dlg.GetIncludeOnBoard() );
428
429 if( dlg.GetUnitCount() < 2 )
430 new_symbol.LockUnits( false );
431
433 }
434 else
435 {
436 LIB_SYMBOL* parent = m_libMgr->GetSymbol( parentSymbolName, lib );
437 wxCHECK( parent, /* void */ );
438 new_symbol.SetParent( parent );
439
440 // Inherit the parent mandatory field attributes.
441 for( FIELD_T fieldId : MANDATORY_FIELDS )
442 {
443 SCH_FIELD* field = new_symbol.GetField( fieldId );
444 SCH_FIELD* parentField = parent->GetField( fieldId );
445
446 *field = *parentField;
447
448 switch( fieldId )
449 {
450 case FIELD_T::REFERENCE:
451 // parent's reference already copied
452 break;
453
454 case FIELD_T::VALUE:
455 if( parent->IsPower() )
456 field->SetText( name );
457 break;
458
459 case FIELD_T::FOOTPRINT:
460 if( !dlg.GetKeepFootprint() )
461 field->SetText( wxEmptyString );
462 break;
463
464 case FIELD_T::DATASHEET:
465 // - footprint might be the same as parent, but might not
466 // - datasheet is most likely different
467 // - probably best to play it safe and copy neither
468 if( !dlg.GetKeepDatasheet() )
469 field->SetText( wxEmptyString );
470 break;
471
472 default:
473 break;
474 }
475
476 field->SetParent( &new_symbol );
477 }
478
479 if( dlg.GetTransferUserFields() )
480 {
481 std::vector<SCH_FIELD*> listFields;
482 parent->GetFields( listFields );
483
484 for( SCH_FIELD* field : listFields )
485 {
486 if( field->GetId() == FIELD_T::USER )
487 {
488 SCH_FIELD* new_field = new SCH_FIELD( *field );
489
490 if( !dlg.GetKeepContentUserFields() )
491 new_field->SetText( wxEmptyString );
492
493 new_field->SetParent( &new_symbol );
494 new_symbol.AddField( new_field );
495 }
496 }
497 }
498 }
499
500 m_libMgr->UpdateSymbol( &new_symbol, lib );
501 SyncLibraries( false );
502 LoadSymbol( name, lib, 1 );
503
504 // must be called after loadSymbol, that calls SetShowDeMorgan, but
505 // because the symbol is empty,it looks like it has no alternate body
506 // and a derived symbol inherits its parent body.
507 if( !new_symbol.GetParent().lock() )
509 else
511}
512
513
515{
516 wxString libName;
517
518 if( IsLibraryTreeShown() )
520
521 if( libName.empty() )
522 {
524 }
525 else if( m_libMgr->IsLibraryReadOnly( libName ) )
526 {
527 wxString msg = wxString::Format( _( "Symbol library '%s' is not writable." ),
528 libName );
529 wxString msg2 = _( "You must save to a different location." );
530
531 if( OKOrCancelDialog( this, _( "Warning" ), msg, msg2 ) == wxID_OK )
532 saveLibrary( libName, true );
533 }
534 else
535 {
536 saveLibrary( libName, false );
537 }
538
539 if( IsLibraryTreeShown() )
541
542 UpdateTitle();
543}
544
545
547{
548 const wxString& libName = GetTargetLibId().GetLibNickname();
549
550 if( !libName.IsEmpty() )
551 {
552 saveLibrary( libName, true );
554 }
555}
556
557
559{
560 saveSymbolCopyAs( aOpenCopy );
561
563}
564
565
572static std::vector<LIB_SYMBOL_SPTR> GetParentChain( const LIB_SYMBOL& aSymbol )
573{
574 std::vector<LIB_SYMBOL_SPTR> chain( { aSymbol.SharedPtr() } );
575
576 while( chain.back()->IsDerived() )
577 {
578 LIB_SYMBOL_SPTR parent = chain.back()->GetParent().lock();
579 chain.push_back( parent );
580 }
581
582 return chain;
583}
584
585
595static std::pair<bool, bool> CheckSavingIntoOwnInheritance( LIB_SYMBOL_LIBRARY_MANAGER& aLibMgr,
596 LIB_SYMBOL& aSymbol,
597 const wxString& aNewSymbolName,
598 const wxString& aNewLibraryName )
599{
600 const wxString& oldLibraryName = aSymbol.GetLibId().GetLibNickname();
601
602 // Cannot be intersecting if in different libs
603 if( aNewLibraryName != oldLibraryName )
604 return { false, false };
605
606 // Or if the target symbol doesn't exist
607 if( !aLibMgr.SymbolNameInUse( aNewSymbolName, aNewLibraryName ) )
608 return { false, false };
609
610 bool inAncestry = false;
611 bool inDescendents = false;
612
613 {
614 const std::vector<LIB_SYMBOL_SPTR> parentChainFromUs = GetParentChain( aSymbol );
615
616 // Ignore the leaf symbol (0) - that must match
617 for( size_t i = 1; i < parentChainFromUs.size(); ++i )
618 {
619 // Attempting to overwrite a symbol in the parental chain
620 if( parentChainFromUs[i]->GetName() == aNewSymbolName )
621 {
622 inAncestry = true;
623 break;
624 }
625 }
626 }
627
628 {
629 LIB_SYMBOL* targetSymbol = aLibMgr.GetSymbol( aNewSymbolName, aNewLibraryName );
630 const std::vector<LIB_SYMBOL_SPTR> parentChainFromTarget = GetParentChain( *targetSymbol );
631 const wxString oldSymbolName = aSymbol.GetName();
632
633 // Ignore the leaf symbol - it'll match if we're saving the symbol
634 // to the same name, and that would be OK
635 for( size_t i = 1; i < parentChainFromTarget.size(); ++i )
636 {
637 if( parentChainFromTarget[i]->GetName() == oldSymbolName )
638 {
639 inDescendents = true;
640 break;
641 }
642 }
643 }
644
645 return { inAncestry, inDescendents };
646}
647
648
656static std::vector<wxString> CheckForParentalChainConflicts( LIB_SYMBOL_LIBRARY_MANAGER& aLibMgr,
657 LIB_SYMBOL& aSymbol,
658 const wxString& newSymbolName,
659 const wxString& newLibraryName )
660{
661 std::vector<wxString> conflicts;
662 const wxString& oldLibraryName = aSymbol.GetLibId().GetLibNickname();
663
664 if( newLibraryName == oldLibraryName )
665 {
666 // Saving into the same library - the only conflict could be the symbol itself
667 if( aLibMgr.SymbolNameInUse( newSymbolName, newLibraryName ) )
668 conflicts.push_back( newSymbolName );
669 }
670 else
671 {
672 // In a different library, check the whole chain
673 const std::vector<LIB_SYMBOL_SPTR> parentChain = GetParentChain( aSymbol );
674
675 for( size_t i = 0; i < parentChain.size(); ++i )
676 {
677 if( i == 0 )
678 {
679 // This is the leaf symbol which the user actually named
680 if( aLibMgr.SymbolNameInUse( newSymbolName, newLibraryName ) )
681 conflicts.push_back( newSymbolName );
682 }
683 else
684 {
685 LIB_SYMBOL_SPTR chainSymbol = parentChain[i];
686
687 if( aLibMgr.SymbolNameInUse( chainSymbol->GetName(), newLibraryName ) )
688 conflicts.push_back( chainSymbol->GetName() );
689 }
690 }
691 }
692
693 return conflicts;
694}
695
696
704{
705public:
707 {
708 // Just overwrite any existing symbols in the target library
709 OVERWRITE,
710 // Add a suffix until we find a name that doesn't conflict
711 RENAME,
712 // Could have a mode that asks for every one, be then we'll need a fancier
713 // SAVE_AS_DIALOG subdialog with Overwrite/Rename/Prompt/Cancel
714 // PROMPT
715 };
716
718 bool aValueFollowsName ) :
719 m_libMgr( aLibMgr ),
720 m_strategy( aStrategy ),
721 m_valueFollowsName( aValueFollowsName )
722 {
723 }
724
725 bool DoSave( LIB_SYMBOL& symbol, const wxString& aNewSymName, const wxString& aNewLibName )
726 {
727 std::vector<LIB_SYMBOL_SPTR> parentChain;
728 // If we're saving into the same library, we don't need to check the parental chain
729 // because we can just keep the same parent symbol
730 if( aNewLibName == symbol.GetLibId().GetLibNickname().wx_str() )
731 parentChain.push_back( symbol.SharedPtr() );
732 else
733 parentChain = GetParentChain( symbol );
734
735 std::vector<wxString> newNames;
736
737 // Iterate backwards (i.e. from the root down)
738 for( int i = (int) parentChain.size() - 1; i >= 0; --i )
739 {
740 LIB_SYMBOL_SPTR& oldSymbol = parentChain[i];
741
742 LIB_SYMBOL new_symbol( *oldSymbol );
743
744 wxString newName;
745 if( i == 0 )
746 {
747 // This is the leaf symbol which the user actually named
748 newName = aNewSymName;
749 }
750 else
751 {
752 // Somewhere in the inheritance chain, use the conflict resolution strategy
753 newName = oldSymbol->GetName();
754 }
755
756 newName = resolveConflict( newName, aNewLibName );
757 new_symbol.SetName( newName );
758
760 new_symbol.GetValueField().SetText( newName );
761
762 if( i == (int) parentChain.size() - 1 )
763 {
764 // This is the root symbol
765 // Nothing extra to do, it's just a simple symbol with no parents
766 }
767 else
768 {
769 // Get the buffered new copy in the new library (with the name we gave it)
770 LIB_SYMBOL* newParent = m_libMgr.GetSymbol( newNames.back(), aNewLibName );
771
772 // We should have stored this already, why didn't we get it back?
773 wxASSERT( newParent );
774 new_symbol.SetParent( newParent );
775 }
776
777 newNames.push_back( newName );
778 m_libMgr.UpdateSymbol( &new_symbol, aNewLibName );
779 }
780
781 return true;
782 }
783
784private:
785 wxString resolveConflict( const wxString& proposed, const wxString& aNewLibName ) const
786 {
787 switch( m_strategy )
788 {
790 {
791 // In an overwrite strategy, we don't care about conflicts
792 return proposed;
793 }
795 {
796 // In a rename strategy, we need to find a name that doesn't conflict
797 int suffix = 1;
798
799 while( true )
800 {
801 wxString newName = wxString::Format( "%s_%d", proposed, suffix );
802
803 if( !m_libMgr.SymbolNameInUse( newName, aNewLibName ) )
804 return newName;
805
806 ++suffix;
807 }
808 break;
809 }
810 // No default
811 }
812
813 wxFAIL_MSG( "Invalid conflict strategy" );
814 return "";
815 }
816
820};
821
822
824{
825 ID_MAKE_NEW_LIBRARY = wxID_HIGHEST + 1,
828};
829
830
832{
833public:
835 std::function<int( const wxString& libName, const wxString& symbolName )>;
836
837 SAVE_AS_DIALOG( SYMBOL_EDIT_FRAME* aParent, const wxString& aSymbolName,
838 const wxString& aLibraryPreselect, SymLibNameValidator aValidator,
839 SYMBOL_SAVE_AS_HANDLER::CONFLICT_STRATEGY& aConflictStrategy ) :
840 EDA_LIST_DIALOG( aParent, _( "Save Symbol As" ), false ),
841 m_validator( std::move( aValidator ) ), m_conflictStrategy( aConflictStrategy )
842 {
844 PROJECT_FILE& project = aParent->Prj().GetProjectFile();
846 std::vector<wxString> libNicknames = tbl->GetLogicalLibs();
847 wxArrayString headers;
848 std::vector<wxArrayString> itemsToDisplay;
849
850 headers.Add( _( "Nickname" ) );
851 headers.Add( _( "Description" ) );
852
853 for( const wxString& nickname : libNicknames )
854 {
855 if( alg::contains( project.m_PinnedSymbolLibs, nickname )
856 || alg::contains( cfg->m_Session.pinned_symbol_libs, nickname ) )
857 {
858 wxArrayString item;
859 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
860 item.Add( tbl->GetDescription( nickname ) );
861 itemsToDisplay.push_back( item );
862 }
863 }
864
865 for( const wxString& nickname : libNicknames )
866 {
867 if( !alg::contains( project.m_PinnedSymbolLibs, nickname )
868 && !alg::contains( cfg->m_Session.pinned_symbol_libs, nickname ) )
869 {
870 wxArrayString item;
871 item.Add( nickname );
872 item.Add( tbl->GetDescription( nickname ) );
873 itemsToDisplay.push_back( item );
874 }
875 }
876
877 initDialog( headers, itemsToDisplay, aLibraryPreselect );
878
879 SetListLabel( _( "Save in library:" ) );
880 SetOKLabel( _( "Save" ) );
881
882 wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
883
884 wxStaticText* label = new wxStaticText( this, wxID_ANY, _( "Name:" ) );
885 bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
886
887 m_symbolNameCtrl = new wxTextCtrl( this, wxID_ANY, UnescapeString( aSymbolName ) );
888 bNameSizer->Add( m_symbolNameCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
889
890 wxButton* newLibraryButton = new wxButton( this, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
891 m_ButtonsSizer->Prepend( 80, 20 );
892 m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
893
894 GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
895
896 Bind( wxEVT_BUTTON,
897 [this]( wxCommandEvent& )
898 {
899 EndModal( ID_MAKE_NEW_LIBRARY );
901
902 // Move nameTextCtrl to the head of the tab-order
903 if( GetChildren().DeleteObject( m_symbolNameCtrl ) )
904 GetChildren().Insert( m_symbolNameCtrl );
905
907
909
910 Layout();
911 GetSizer()->Fit( this );
912
913 Centre();
914 }
915
916 wxString GetSymbolName()
917 {
918 wxString symbolName = m_symbolNameCtrl->GetValue();
919 symbolName.Trim( true );
920 symbolName.Trim( false );
921 symbolName.Replace( " ", "_" );
922 return EscapeString( symbolName, CTX_LIBID );
923 }
924
925protected:
927 {
929
930 if( ret == wxID_CANCEL )
931 return false;
932
933 if( ret == ID_OVERWRITE_CONFLICTS )
935 else if( ret == ID_RENAME_CONFLICTS )
937
938 return true;
939 }
940
941private:
942 wxTextCtrl* m_symbolNameCtrl;
945};
946
947
949{
950 LIB_SYMBOL* symbol = getTargetSymbol();
951
952 if( !symbol )
953 return;
954
955 LIB_ID old_lib_id = symbol->GetLibId();
956 wxString symbolName = old_lib_id.GetLibItemName();
957 wxString libraryName = old_lib_id.GetLibNickname();
958 bool valueFollowsName = symbol->GetValueField().GetText() == symbolName;
959 wxString msg;
960 bool done = false;
961
962 // This is the function that will be called when the user clicks OK in the dialog and checks
963 // if the proposed name has problems, and asks for clarification.
964 const auto dialogValidatorFunc =
965 [&]( const wxString& newLib, const wxString& newName ) -> int
966 {
967 if( newLib.IsEmpty() )
968 {
969 wxMessageBox( _( "A library must be specified." ) );
970 return wxID_CANCEL;
971 }
972
973 if( newName.IsEmpty() )
974 {
975 wxMessageBox( _( "Symbol must have a name." ) );
976 return wxID_CANCEL;
977 }
978
979 if( m_libMgr->IsLibraryReadOnly( newLib ) )
980 {
981 msg = wxString::Format( _( "Library '%s' is read-only. Choose a "
982 "different library to save the symbol '%s' to." ),
983 newLib,
984 UnescapeString( newName ) );
985 wxMessageBox( msg );
986 return wxID_CANCEL;
987 }
988
993 const auto& [inAncestry, inDescendents] =
994 CheckSavingIntoOwnInheritance( *m_libMgr, *symbol, newName, newLib );
995
996 if( inAncestry )
997 {
998 msg = wxString::Format( _( "Symbol '%s' cannot replace another symbol '%s' "
999 "that it descends from" ),
1000 symbolName,
1001 UnescapeString( newName ) );
1002 wxMessageBox( msg );
1003 return wxID_CANCEL;
1004 }
1005
1006 if( inDescendents )
1007 {
1008 msg = wxString::Format( _( "Symbol '%s' cannot replace another symbol '%s' "
1009 "that is a descendent of it." ),
1010 symbolName,
1011 UnescapeString( newName ) );
1012 wxMessageBox( msg );
1013 return wxID_CANCEL;
1014 }
1015
1016 const std::vector<wxString> conflicts =
1017 CheckForParentalChainConflicts( *m_libMgr, *symbol, newName, newLib );
1018
1019 if( conflicts.size() == 1 && conflicts.front() == newName )
1020 {
1021 // The simplest case is when the symbol itself has a conflict
1022 msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'. "
1023 "Do you want to overwrite it?" ),
1024 UnescapeString( newName ),
1025 newLib );
1026
1027 KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
1028 wxOK | wxCANCEL | wxICON_WARNING );
1029 errorDlg.SetOKLabel( _( "Overwrite" ) );
1030
1031 return errorDlg.ShowModal() == wxID_OK ? ID_OVERWRITE_CONFLICTS
1032 : (int) wxID_CANCEL;
1033 }
1034 else if( !conflicts.empty() )
1035 {
1036 // If there are conflicts in the parental chain, we need to ask the user
1037 // if they want to overwrite all of them.
1038 // A more complex UI might allow the user to re-parent the symbol to an
1039 // existing symbol in the target lib, or rename all the parents somehow.
1040 msg = wxString::Format( _( "The following symbols in the inheritance chain of "
1041 "'%s' already exist in library '%s':\n" ),
1042 UnescapeString( symbolName ),
1043 newLib );
1044
1045 for( const wxString& conflict : conflicts )
1046 msg += wxString::Format( " %s\n", conflict );
1047
1048 msg += _( "\nDo you want to overwrite all of them, or rename the new symbols?" );
1049
1050 KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
1051 wxYES_NO | wxCANCEL | wxICON_WARNING );
1052 errorDlg.SetYesNoCancelLabels( _( "Overwrite All" ), _( "Rename All" ),
1053 _( "Cancel" ) );
1054
1055 switch( errorDlg.ShowModal() )
1056 {
1057 case wxID_YES: return ID_OVERWRITE_CONFLICTS;
1058 case wxID_NO: return ID_RENAME_CONFLICTS;
1059 default: return wxID_CANCEL;
1060 }
1061 }
1062
1063 return wxID_OK;
1064 };
1065
1067
1068 // Keep asking the user for a new name until they give a valid one or cancel the operation
1069 while( !done )
1070 {
1071 SAVE_AS_DIALOG dlg( this, symbolName, libraryName, dialogValidatorFunc, strategy );
1072
1073 int ret = dlg.ShowModal();
1074
1075 switch( ret )
1076 {
1077 case wxID_CANCEL:
1078 return;
1079
1080 case wxID_OK: // No conflicts
1083 symbolName = dlg.GetSymbolName();
1084 libraryName = dlg.GetTextSelection();
1085
1086 if( ret == ID_RENAME_CONFLICTS )
1088
1089 done = true;
1090 break;
1091
1093 {
1094 wxFileName newLibrary( AddLibraryFile( true ) );
1095 libraryName = newLibrary.GetName();
1096 break;
1097 }
1098
1099 default:
1100 break;
1101 }
1102 }
1103
1104 SYMBOL_SAVE_AS_HANDLER saver( *m_libMgr, strategy, valueFollowsName );
1105
1106 saver.DoSave( *symbol, symbolName, libraryName );
1107
1108 SyncLibraries( false );
1109
1110 if( aOpenCopy )
1111 LoadSymbol( symbolName, libraryName, 1 );
1112}
1113
1114
1116{
1117 wxString msg;
1118 LIB_SYMBOL* symbol = getTargetSymbol();
1119
1120 if( !symbol )
1121 {
1122 ShowInfoBarError( _( "There is no symbol selected to save." ) );
1123 return;
1124 }
1125
1126 wxFileName fn;
1127
1128 fn.SetName( symbol->GetName().Lower() );
1130
1131 wxFileDialog dlg( this, _( "Export Symbol" ), m_mruPath, fn.GetFullName(),
1133
1134 if( dlg.ShowModal() == wxID_CANCEL )
1135 return;
1136
1138
1139 fn = dlg.GetPath();
1140 fn.MakeAbsolute();
1141
1142 wxString libraryName;
1143 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = symbol->Flatten();
1144
1145 for( const wxString& candidate : m_libMgr->GetLibraryNames() )
1146 {
1147 if( m_libMgr->GetLibrary( candidate )->GetFullURI( true ) == fn.GetFullPath() )
1148 libraryName = candidate;
1149 }
1150
1151 if( !libraryName.IsEmpty() )
1152 {
1153 SYMBOL_SAVE_AS_HANDLER saver( *m_libMgr, strategy, false );
1154
1155 if( m_libMgr->IsLibraryReadOnly( libraryName ) )
1156 {
1157 msg = wxString::Format( _( "Library '%s' is read-only." ), libraryName );
1158 DisplayError( this, msg );
1159 return;
1160 }
1161
1162 if( m_libMgr->SymbolNameInUse( symbol->GetName(), libraryName ) )
1163 {
1164 msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'." ),
1165 symbol->GetName(), libraryName );
1166
1167 KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1168 errorDlg.SetOKLabel( _( "Overwrite" ) );
1169 errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1170
1171 if( errorDlg.ShowModal() == wxID_CANCEL )
1172 return;
1173 }
1174
1175 saver.DoSave( *flattenedSymbol, symbol->GetName(), libraryName );
1176
1177 SyncLibraries( false );
1178 return;
1179 }
1180
1181 LIB_SYMBOL* old_symbol = nullptr;
1182 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( fn.GetFullPath() );
1183
1184 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
1185 pluginType = SCH_IO_MGR::SCH_KICAD;
1186
1187 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pluginType ) );
1188
1189 if( fn.FileExists() )
1190 {
1191 try
1192 {
1193 old_symbol = pi->LoadSymbol( fn.GetFullPath(), symbol->GetName() );
1194 }
1195 catch( const IO_ERROR& ioe )
1196 {
1197 msg.Printf( _( "Error occurred attempting to load symbol library file '%s'." ),
1198 fn.GetFullPath() );
1199 DisplayErrorMessage( this, msg, ioe.What() );
1200 return;
1201 }
1202
1203 if( old_symbol )
1204 {
1205 msg.Printf( _( "Symbol %s already exists in library '%s'." ),
1206 UnescapeString( symbol->GetName() ),
1207 fn.GetFullName() );
1208
1209 KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1210 errorDlg.SetOKLabel( _( "Overwrite" ) );
1211 errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1212
1213 if( errorDlg.ShowModal() == wxID_CANCEL )
1214 return;
1215 }
1216 }
1217
1218 if( !fn.IsDirWritable() )
1219 {
1220 msg.Printf( _( "Insufficient permissions to save library '%s'." ), fn.GetFullPath() );
1221 DisplayError( this, msg );
1222 return;
1223 }
1224
1225 try
1226 {
1227 if( !fn.FileExists() )
1228 pi->CreateLibrary( fn.GetFullPath() );
1229
1230 // The flattened symbol is most likely what the user would want. As some point in
1231 // the future as more of the symbol library inheritance is implemented, this may have
1232 // to be changes to save symbols of inherited symbols.
1233 pi->SaveSymbol( fn.GetFullPath(), flattenedSymbol.release() );
1234 }
1235 catch( const IO_ERROR& ioe )
1236 {
1237 msg.Printf( _( "Failed to create symbol library file '%s'." ), fn.GetFullPath() );
1238 DisplayErrorMessage( this, msg, ioe.What() );
1239 msg.Printf( _( "Error creating symbol library '%s'." ), fn.GetFullName() );
1240 SetStatusText( msg );
1241 return;
1242 }
1243
1244 m_mruPath = fn.GetPath();
1245
1246 msg.Printf( _( "Symbol %s saved to library '%s'." ),
1247 UnescapeString( symbol->GetName() ),
1248 fn.GetFullPath() );
1249 SetStatusText( msg );
1250}
1251
1252
1254{
1255 wxCHECK( m_symbol, /* void */ );
1256
1257 wxString lib = GetCurLib();
1258
1259 if( !lib.IsEmpty() && aOldName && *aOldName != m_symbol->GetName() )
1260 {
1261 // Test the current library for name conflicts
1262 if( m_libMgr->SymbolNameInUse( m_symbol->GetName(), lib ) )
1263 {
1264 wxString msg = wxString::Format( _( "Symbol name '%s' already in use." ),
1266
1267 DisplayErrorMessage( this, msg );
1268 m_symbol->SetName( *aOldName );
1269 }
1270 else
1271 {
1272 m_libMgr->UpdateSymbolAfterRename( m_symbol, *aOldName, lib );
1273 }
1274
1275 // Reselect the renamed symbol
1277 }
1278
1280 SetShowDeMorgan( GetCurSymbol()->Flatten()->HasAlternateBodyStyle() );
1281 UpdateTitle();
1282
1283 // N.B. The view needs to be rebuilt first as the Symbol Properties change may invalidate
1284 // the view pointers by rebuilting the field table
1285 RebuildView();
1287
1288 OnModify();
1289}
1290
1291
1293{
1294 std::vector<LIB_ID> toDelete = GetSelectedLibIds();
1295
1296 if( toDelete.empty() )
1297 toDelete.emplace_back( GetTargetLibId() );
1298
1299 for( LIB_ID& libId : toDelete )
1300 {
1301 if( m_libMgr->IsSymbolModified( libId.GetLibItemName(), libId.GetLibNickname() )
1302 && !IsOK( this, wxString::Format( _( "The symbol '%s' has been modified.\n"
1303 "Do you want to remove it from the library?" ),
1304 libId.GetUniStringLibItemName() ) ) )
1305 {
1306 continue;
1307 }
1308
1309 if( m_libMgr->HasDerivedSymbols( libId.GetLibItemName(), libId.GetLibNickname() ) )
1310 {
1311 wxString msg;
1312
1313 msg.Printf(
1314 _( "The symbol %s is used to derive other symbols.\n"
1315 "Deleting this symbol will delete all of the symbols derived from it.\n\n"
1316 "Do you wish to delete this symbol and all of its derivatives?" ),
1317 libId.GetLibItemName().wx_str() );
1318
1319 wxMessageDialog::ButtonLabel yesButtonLabel( _( "Delete Symbol" ) );
1320 wxMessageDialog::ButtonLabel noButtonLabel( _( "Keep Symbol" ) );
1321
1322 wxMessageDialog dlg( this, msg, _( "Warning" ),
1323 wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION | wxCENTER );
1324 dlg.SetYesNoLabels( yesButtonLabel, noButtonLabel );
1325
1326 if( dlg.ShowModal() == wxID_NO )
1327 continue;
1328 }
1329
1330 if( IsCurrentSymbol( libId ) )
1331 emptyScreen();
1332
1333 m_libMgr->RemoveSymbol( libId.GetLibItemName(), libId.GetLibNickname() );
1334 }
1335
1337}
1338
1339
1341{
1342 std::vector<LIB_ID> symbols;
1343
1344 if( GetTreeLIBIDs( symbols ) == 0 )
1345 return;
1346
1347 STRING_FORMATTER formatter;
1348
1349 for( LIB_ID& libId : symbols )
1350 {
1351 LIB_SYMBOL* symbol = m_libMgr->GetBufferedSymbol( libId.GetLibItemName(),
1352 libId.GetLibNickname() );
1353
1354 if( !symbol )
1355 continue;
1356
1357 std::unique_ptr<LIB_SYMBOL> tmp = symbol->Flatten();
1358 SCH_IO_KICAD_SEXPR::FormatLibSymbol( tmp.get(), formatter );
1359 }
1360
1361 std::string prettyData = formatter.GetString();
1362 KICAD_FORMAT::Prettify( prettyData, true );
1363
1364 wxLogNull doNotLog; // disable logging of failed clipboard actions
1365
1366 auto clipboard = wxTheClipboard;
1367 wxClipboardLocker clipboardLock( clipboard );
1368
1369 if( !clipboardLock || !clipboard->IsOpened() )
1370 return;
1371
1372 auto data = new wxTextDataObject( wxString( prettyData.c_str(), wxConvUTF8 ) );
1373 clipboard->SetData( data );
1374
1375 clipboard->Flush();
1376}
1377
1378
1379void SYMBOL_EDIT_FRAME::DuplicateSymbol( bool aFromClipboard )
1380{
1381 LIB_ID libId = GetTargetLibId();
1382 wxString lib = libId.GetLibNickname();
1383
1384 if( !m_libMgr->LibraryExists( lib ) )
1385 return;
1386
1387 std::vector<LIB_SYMBOL*> newSymbols;
1388
1389 if( aFromClipboard )
1390 {
1391 std::string clipboardData = GetClipboardUTF8();
1392
1393 try
1394 {
1395 newSymbols = SCH_IO_KICAD_SEXPR::ParseLibSymbols( clipboardData, "Clipboard" );
1396 }
1397 catch( IO_ERROR& e )
1398 {
1399 wxLogMessage( wxS( "Can not paste: %s" ), e.Problem() );
1400 }
1401 }
1402 else if( LIB_SYMBOL* srcSymbol = m_libMgr->GetBufferedSymbol( libId.GetLibItemName(), lib ) )
1403 {
1404 newSymbols.emplace_back( new LIB_SYMBOL( *srcSymbol ) );
1405
1406 // Derive from same parent.
1407 if( srcSymbol->IsDerived() )
1408 {
1409 if( std::shared_ptr<LIB_SYMBOL> srcParent = srcSymbol->GetParent().lock() )
1410 newSymbols.back()->SetParent( srcParent.get() );
1411 }
1412 }
1413
1414 if( newSymbols.empty() )
1415 return;
1416
1417 for( LIB_SYMBOL* symbol : newSymbols )
1418 {
1419 ensureUniqueName( symbol, lib );
1420 m_libMgr->UpdateSymbol( symbol, lib );
1421
1422 LoadOneLibrarySymbolAux( symbol, lib, GetUnit(), GetBodyStyle() );
1423 }
1424
1425 SyncLibraries( false );
1426 m_treePane->GetLibTree()->SelectLibId( LIB_ID( lib, newSymbols[0]->GetName() ) );
1427
1428 for( LIB_SYMBOL* symbol : newSymbols )
1429 delete symbol;
1430}
1431
1432
1433void SYMBOL_EDIT_FRAME::ensureUniqueName( LIB_SYMBOL* aSymbol, const wxString& aLibrary )
1434{
1435 if( aSymbol )
1436 {
1437 int i = 1;
1438 wxString newName = aSymbol->GetName();
1439
1440 // Append a number to the name until the name is unique in the library.
1441 while( m_libMgr->SymbolNameInUse( newName, aLibrary ) )
1442 newName.Printf( "%s_%d", aSymbol->GetName(), i++ );
1443
1444 aSymbol->SetName( newName );
1445 }
1446}
1447
1448
1449void SYMBOL_EDIT_FRAME::Revert( bool aConfirm )
1450{
1451 LIB_ID libId = GetTargetLibId();
1452 const wxString& libName = libId.GetLibNickname();
1453
1454 // Empty if this is the library itself that is selected.
1455 const wxString& symbolName = libId.GetLibItemName();
1456
1457 wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1458 symbolName.IsEmpty() ? libName : symbolName );
1459
1460 if( aConfirm && !ConfirmRevertDialog( this, msg ) )
1461 return;
1462
1463 bool reload_currentSymbol = false;
1464 wxString curr_symbolName = symbolName;
1465
1466 if( GetCurSymbol() )
1467 {
1468 // the library itself is reverted: the current symbol will be reloaded only if it is
1469 // owned by this library
1470 if( symbolName.IsEmpty() )
1471 {
1472 LIB_ID curr_libId = GetCurSymbol()->GetLibId();
1473 reload_currentSymbol = libName == curr_libId.GetLibNickname().wx_str();
1474
1475 if( reload_currentSymbol )
1476 curr_symbolName = curr_libId.GetUniStringLibItemName();
1477 }
1478 else
1479 {
1480 reload_currentSymbol = IsCurrentSymbol( libId );
1481 }
1482 }
1483
1484 int unit = m_unit;
1485
1486 if( reload_currentSymbol )
1487 emptyScreen();
1488
1489 if( symbolName.IsEmpty() )
1490 {
1491 m_libMgr->RevertLibrary( libName );
1492 }
1493 else
1494 {
1495 libId = m_libMgr->RevertSymbol( libId.GetLibItemName(), libId.GetLibNickname() );
1496
1497 m_treePane->GetLibTree()->SelectLibId( libId );
1499 }
1500
1501 if( reload_currentSymbol && m_libMgr->SymbolExists( curr_symbolName, libName ) )
1502 LoadSymbol( curr_symbolName, libName, unit );
1503
1504 m_treePane->Refresh();
1505}
1506
1507
1509{
1510 wxCHECK_RET( m_libMgr, "Library manager object not created." );
1511
1512 Revert( false );
1514}
1515
1516
1517void SYMBOL_EDIT_FRAME::LoadSymbol( const wxString& aAlias, const wxString& aLibrary, int aUnit )
1518{
1520 {
1521 if( !HandleUnsavedChanges( this, _( "The current symbol has been modified. Save changes?" ),
1522 [&]() -> bool
1523 {
1524 return saveCurrentSymbol();
1525 } ) )
1526 {
1527 return;
1528 }
1529 }
1530
1531 LIB_SYMBOL* symbol = m_libMgr->GetBufferedSymbol( aAlias, aLibrary );
1532
1533 if( !symbol )
1534 {
1535 DisplayError( this, wxString::Format( _( "Symbol %s not found in library '%s'." ),
1536 aAlias,
1537 aLibrary ) );
1539 return;
1540 }
1541
1542 // Optimize default edit options for this symbol
1543 // Usually if units are locked, graphic items are specific to each unit
1544 // and if units are interchangeable, graphic items are common to units
1546 tools->SetDrawSpecificUnit( symbol->UnitsLocked() );
1547
1548 LoadOneLibrarySymbolAux( symbol, aLibrary, aUnit, 0 );
1549}
1550
1551
1552bool SYMBOL_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
1553{
1554 wxFileName fn;
1555 wxString msg;
1556 SYMBOL_SAVEAS_TYPE type = SYMBOL_SAVEAS_TYPE::NORMAL_SAVE_AS;
1557 SCH_IO_MGR::SCH_FILE_T fileType = SCH_IO_MGR::SCH_FILE_T::SCH_KICAD;
1558 PROJECT& prj = Prj();
1559
1561
1562 if( !aNewFile && ( aLibrary.empty() || !PROJECT_SCH::SchSymbolLibTable( &prj )->HasLibrary( aLibrary ) ) )
1563 {
1564 ShowInfoBarError( _( "No library specified." ) );
1565 return false;
1566 }
1567
1568 if( aNewFile )
1569 {
1570 SEARCH_STACK* search = PROJECT_SCH::SchSearchS( &prj );
1571
1572 // Get a new name for the library
1573 wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH );
1574
1575 if( !default_path )
1576 default_path = search->LastVisitedPath();
1577
1578 fn.SetName( aLibrary );
1580
1581 wxString wildcards = FILEEXT::KiCadSymbolLibFileWildcard();
1582
1583 wxFileDialog dlg( this, wxString::Format( _( "Save Library '%s' As..." ), aLibrary ),
1584 default_path, fn.GetFullName(), wildcards,
1585 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1586
1587 SYMBOL_FILEDLG_SAVE_AS saveAsHook( type );
1588 dlg.SetCustomizeHook( saveAsHook );
1589
1590 if( dlg.ShowModal() == wxID_CANCEL )
1591 return false;
1592
1593 fn = dlg.GetPath();
1594
1595 prj.SetRString( PROJECT::SCH_LIB_PATH, fn.GetPath() );
1596
1597 if( fn.GetExt().IsEmpty() )
1599
1600 type = saveAsHook.GetOption();
1601 }
1602 else
1603 {
1604 fn = PROJECT_SCH::SchSymbolLibTable( &prj )->GetFullURI( aLibrary );
1606
1607 if( fileType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
1608 fileType = SCH_IO_MGR::SCH_KICAD;
1609 }
1610
1611 // Verify the user has write privileges before attempting to save the library file.
1612 if( !aNewFile && m_libMgr->IsLibraryReadOnly( aLibrary ) )
1613 return false;
1614
1615 ClearMsgPanel();
1616
1617 // Copy .kicad_symb file to .bak.
1618 if( !backupFile( fn, "bak" ) )
1619 return false;
1620
1621 if( !m_libMgr->SaveLibrary( aLibrary, fn.GetFullPath(), fileType ) )
1622 {
1623 msg.Printf( _( "Failed to save changes to symbol library file '%s'." ),
1624 fn.GetFullPath() );
1625 DisplayErrorMessage( this, _( "Error Saving Library" ), msg );
1626 return false;
1627 }
1628
1629 if( !aNewFile )
1630 {
1631 m_libMgr->ClearLibraryModified( aLibrary );
1632
1633 // Update the library modification time so that we don't reload based on the watcher
1634 if( aLibrary == getTargetLib() )
1635 SetSymModificationTime( fn.GetModificationTime() );
1636 }
1637 else
1638 {
1639 bool resyncLibTree = false;
1640 wxString originalLibNickname = getTargetLib();
1641 wxString forceRefresh;
1642
1643 switch( type )
1644 {
1645 case SYMBOL_SAVEAS_TYPE::REPLACE_TABLE_ENTRY:
1646 resyncLibTree = replaceLibTableEntry( originalLibNickname, fn.GetFullPath() );
1647 forceRefresh = originalLibNickname;
1648 break;
1649
1650 case SYMBOL_SAVEAS_TYPE::ADD_GLOBAL_TABLE_ENTRY:
1651 resyncLibTree = addLibTableEntry( fn.GetFullPath() );
1652 break;
1653
1654 case SYMBOL_SAVEAS_TYPE::ADD_PROJECT_TABLE_ENTRY:
1655 resyncLibTree = addLibTableEntry( fn.GetFullPath(), PROJECT_LIB_TABLE );
1656 break;
1657
1658 default:
1659 break;
1660 }
1661
1662 if( resyncLibTree )
1663 {
1665 SyncLibraries( true, false, forceRefresh );
1667 }
1668 }
1669
1670 ClearMsgPanel();
1671 msg.Printf( _( "Symbol library file '%s' saved." ), fn.GetFullPath() );
1673
1674 return true;
1675}
1676
1677
1678bool SYMBOL_EDIT_FRAME::saveAllLibraries( bool aRequireConfirmation )
1679{
1680 wxString msg, msg2;
1681 bool doSave = true;
1682 int dirtyCount = 0;
1683 bool applyToAll = false;
1684 bool retv = true;
1685
1686 for( const wxString& libNickname : m_libMgr->GetLibraryNames() )
1687 {
1688 if( m_libMgr->IsLibraryModified( libNickname ) )
1689 dirtyCount++;
1690 }
1691
1692 for( const wxString& libNickname : m_libMgr->GetLibraryNames() )
1693 {
1694 if( m_libMgr->IsLibraryModified( libNickname ) )
1695 {
1696 if( aRequireConfirmation && !applyToAll )
1697 {
1698 msg.Printf( _( "Save changes to '%s' before closing?" ), libNickname );
1699
1700 switch( UnsavedChangesDialog( this, msg, dirtyCount > 1 ? &applyToAll : nullptr ) )
1701 {
1702 case wxID_YES: doSave = true; break;
1703 case wxID_NO: doSave = false; break;
1704 default:
1705 case wxID_CANCEL: return false;
1706 }
1707 }
1708
1709 if( doSave )
1710 {
1711 // If saving under existing name fails then do a Save As..., and if that
1712 // fails then cancel close action.
1713 if( m_libMgr->IsLibraryReadOnly( libNickname ) )
1714 {
1715 msg.Printf( _( "Symbol library '%s' is not writable." ), libNickname );
1716 msg2 = _( "You must save to a different location." );
1717
1718 if( dirtyCount == 1 )
1719 {
1720 if( OKOrCancelDialog( this, _( "Warning" ), msg, msg2 ) != wxID_OK )
1721 {
1722 retv = false;
1723 continue;
1724 }
1725 }
1726 else
1727 {
1728 m_infoBar->Dismiss();
1729 m_infoBar->ShowMessageFor( msg + wxS( " " ) + msg2,
1730 2000, wxICON_EXCLAMATION );
1731
1732 while( m_infoBar->IsShownOnScreen() )
1733 wxSafeYield();
1734
1735 retv = false;
1736 continue;
1737 }
1738 }
1739 else if( saveLibrary( libNickname, false ) )
1740 {
1741 continue;
1742 }
1743
1744 if( !saveLibrary( libNickname, true ) )
1745 retv = false;
1746 }
1747 }
1748 }
1749
1750 UpdateTitle();
1751 return retv;
1752}
1753
1754
1756{
1758
1759 if( !m_symbol )
1760 return;
1761
1762 wxString msg = m_symbol->GetName();
1763
1764 AppendMsgPanel( _( "Name" ), UnescapeString( msg ), 8 );
1765
1766 if( m_symbol->IsDerived() )
1767 {
1768 LIB_SYMBOL_SPTR parent = m_symbol->GetParent().lock();
1769
1770 msg = parent ? parent->GetName() : _( "Undefined!" );
1771 AppendMsgPanel( _( "Parent" ), UnescapeString( msg ), 8 );
1772 }
1773
1774 static wxChar UnitLetter[] = wxT( "?ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
1775 msg = UnitLetter[m_unit];
1776
1777 AppendMsgPanel( _( "Unit" ), msg, 8 );
1778
1779 if( m_bodyStyle == BODY_STYLE::DEMORGAN )
1780 msg = _( "Alternate" );
1781 else if( m_bodyStyle == BODY_STYLE::BASE )
1782 msg = _( "Standard" );
1783 else
1784 msg = wxT( "?" );
1785
1786 AppendMsgPanel( _( "Body" ), msg, 8 );
1787
1788 if( m_symbol->IsGlobalPower() )
1789 msg = _( "Power Symbol" );
1790 else if( m_symbol->IsLocalPower() )
1791 msg = _( "Power Symbol (Local)" );
1792 else
1793 msg = _( "Symbol" );
1794
1795 AppendMsgPanel( _( "Type" ), msg, 8 );
1796 AppendMsgPanel( _( "Description" ), m_symbol->GetDescription(), 8 );
1797 AppendMsgPanel( _( "Keywords" ), m_symbol->GetKeyWords() );
1798 AppendMsgPanel( _( "Datasheet" ), m_symbol->GetDatasheetField().GetText() );
1799}
const char * name
Definition: DXF_plotter.cpp:62
static TOOL_ACTION cancelInteractive
Definition: actions.h:72
static TOOL_ACTION zoomFitScreen
Definition: actions.h:141
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
wxString GetParentSymbolName() const
wxString GetName() const override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:66
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int ShowModal() override
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
WX_INFOBAR * m_infoBar
virtual void RecreateToolbars()
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
wxString m_mruPath
void ReCreateMenuBar()
Recreate the menu bar.
WX_INFOBAR * GetInfoBar()
virtual void ClearMsgPanel()
Clear all messages from the message panel.
void AppendMsgPanel(const wxString &aTextUpper, const wxString &aTextLower, int aPadding=6)
Append a message to the message panel.
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:112
A dialog which shows:
void SetOKLabel(const wxString &aLabel)
void initDialog(const wxArrayString &aItemHeaders, const std::vector< wxArrayString > &aItemList, const wxString &aPreselectText)
wxString GetTextSelection(int aColumn=0)
Return the selected text from aColumn in the wxListCtrl in the dialog.
void SetListLabel(const wxString &aLabel)
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:97
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
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
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:50
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition: kidialog.cpp:51
int ShowModal() override
Definition: kidialog.cpp:95
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition: view.cpp:1551
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:395
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:172
wxString GetUniStringLibId() const
Definition: lib_id.h:148
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
Definition: lib_id.h:112
const wxString GetUniStringLibNickname() const
Definition: lib_id.h:88
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
Symbol library management helper that is specific to the symbol library editor frame.
Define a library symbol object.
Definition: lib_symbol.h:85
wxString GetDescription() const override
Definition: lib_symbol.h:170
const LIB_ID & GetLibId() const override
Definition: lib_symbol.h:155
wxString GetKeyWords() const override
Definition: lib_symbol.h:183
void SetGlobalPower()
Definition: lib_symbol.cpp:476
bool IsMulti() const override
Definition: lib_symbol.h:587
void GetFields(std::vector< SCH_FIELD * > &aList, bool aVisibleOnly=false) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
bool IsPower() const override
Definition: lib_symbol.cpp:470
void SetUnitCount(int aCount, bool aDuplicateDrawItems=true)
Set the units per symbol count.
bool UnitsLocked() const
Check whether symbol units are interchangeable.
Definition: lib_symbol.h:289
SCH_FIELD & GetDatasheetField()
Return reference to the datasheet field.
Definition: lib_symbol.h:346
bool IsDerived() const
Definition: lib_symbol.h:207
LIB_ID GetSourceLibId() const
Definition: lib_symbol.h:158
SCH_FIELD * GetField(const wxString &aFieldName)
Find a field within this symbol matching aFieldName; return nullptr if not found.
bool HasAlternateBodyStyle() const override
Test if symbol has more than one body conversion type (DeMorgan).
void LockUnits(bool aLockUnits)
Set interchangeable the property for symbol units.
Definition: lib_symbol.h:283
void SetParent(LIB_SYMBOL *aParent=nullptr)
Definition: lib_symbol.cpp:336
wxString GetName() const override
Definition: lib_symbol.h:149
SCH_FIELD & GetValueField()
Return reference to the value field.
Definition: lib_symbol.h:334
bool IsLocalPower() const override
Definition: lib_symbol.cpp:424
LIB_SYMBOL_SPTR SharedPtr() const
http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared.
Definition: lib_symbol.h:96
void SetHasAlternateBodyStyle(bool aHasAlternate, bool aDuplicatePins=true)
Set or clear the alternate body style (DeMorgan) for the symbol.
bool IsGlobalPower() const override
Definition: lib_symbol.cpp:454
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:345
void AddField(SCH_FIELD *aField)
Add a field.
Definition: lib_symbol.cpp:994
LIB_SYMBOL_REF & GetParent()
Definition: lib_symbol.h:118
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:329
void SetNormal()
Definition: lib_symbol.cpp:504
SCH_FIELD & GetReferenceField()
Return reference to the reference designator field.
Definition: lib_symbol.h:338
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...
const wxString GetDescription(const wxString &aNickname)
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.
wxString GetFullURI(const wxString &aLibNickname, bool aExpandEnvVars=true) const
Return the full URI of the library mapped to aLibNickname.
static const wxString GetPinningSymbol()
void RefreshLibTree()
Refresh the tree (mainly to update highlighting and asterisking)
Definition: lib_tree.cpp:456
void CenterLibId(const LIB_ID &aLibId)
Ensure that an item is visible (preferably centered).
Definition: lib_tree.cpp:365
void SelectLibId(const LIB_ID &aLibId)
Select an item in the tree widget.
Definition: lib_tree.cpp:359
void ExpandLibId(const LIB_ID &aLibId)
Expand and item i the tree widget.
Definition: lib_tree.cpp:379
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:556
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:74
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
static SEARCH_STACK * SchSearchS(PROJECT *aProject)
Accessor for Eeschema search stack.
Definition: project_sch.cpp:41
Container for project specific data.
Definition: project.h:65
@ SCH_LIB_PATH
Definition: project.h:220
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:204
virtual void SetRString(RSTRING_T aStringId, const wxString &aString)
Store a "retained string", which is any session and project specific string identified in enum RSTRIN...
Definition: project.cpp:320
virtual const wxString & GetRString(RSTRING_T aStringId)
Return a "retained string", which is any session and project specific string identified in enum RSTRI...
Definition: project.cpp:331
wxString GetSymbolName()
bool TransferDataFromWindow() override
wxTextCtrl * m_symbolNameCtrl
SymLibNameValidator m_validator
SYMBOL_SAVE_AS_HANDLER::CONFLICT_STRATEGY & m_conflictStrategy
SAVE_AS_DIALOG(SYMBOL_EDIT_FRAME *aParent, const wxString &aSymbolName, const wxString &aLibraryPreselect, SymLibNameValidator aValidator, SYMBOL_SAVE_AS_HANDLER::CONFLICT_STRATEGY &aConflictStrategy)
std::function< int(const wxString &libName, const wxString &symbolName)> SymLibNameValidator
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
wxString SelectLibraryFromList()
Display a list of loaded libraries and allows the user to select a library.
void SetSymModificationTime(const wxDateTime &aTime)
Set the modification time of the symbol library table file.
void setSymWatcher(const LIB_ID *aSymbol)
Creates (or removes) a watcher on the specified symbol library.
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
Schematic editor (Eeschema) main window.
void SaveSymbolToSchematic(const LIB_SYMBOL &aSymbol, const KIID &aSchematicSymbolUUID)
Update a schematic symbol from a LIB_SYMBOL.
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1092
static void FormatLibSymbol(LIB_SYMBOL *aPart, OUTPUTFORMATTER &aFormatter)
static std::vector< LIB_SYMBOL * > ParseLibSymbols(std::string &aSymbolText, std::string aSource, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
static SCH_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a symbol library using the file extension of aLibPath.
Definition: sch_io_mgr.cpp:140
Look for files in a number of paths.
Definition: search_stack.h:43
const wxString LastVisitedPath(const wxString &aSubPathToSearch=wxEmptyString)
A quirky function inherited from old code that seems to serve particular needs in the UI.
Implement an OUTPUTFORMATTER to a memory buffer.
Definition: richio.h:449
const std::string & GetString()
Definition: richio.h:472
SYMBOL_EDITOR_DRAWING_TOOLS.
The symbol library editor main window.
void ClearMsgPanel() override
Clear all messages from the message panel.
void UpdateAfterSymbolProperties(wxString *aOldName=nullptr)
void SaveAll()
Save all modified symbols and libraries.
bool addLibTableEntry(const wxString &aLibFile, TABLE_SCOPE aScope=GLOBAL_LIB_TABLE)
Add aLibFile to the symbol library table defined by aScope.
bool IsLibraryTreeShown() const override
wxString getTargetLib() const
bool IsCurrentSymbol(const LIB_ID &aLibId) const
Restore the empty editor screen, without any symbol or library selected.
bool backupFile(const wxFileName &aOriginalFile, const wxString &aBackupExt)
Return currently edited symbol.
int GetTreeLIBIDs(std::vector< LIB_ID > &aSelection) const
LIB_ID GetTreeLIBID(int *aUnit=nullptr) const
Return the LIB_ID of the library or symbol selected in the symbol tree.
LIB_SYMBOL_LIBRARY_MANAGER * m_libMgr
wxString GetCurLib() const
The nickname of the current library being edited and empty string if none.
void Save()
Save the selected symbol or library.
void LoadSymbol(const wxString &aLibrary, const wxString &aSymbol, int Unit)
int GetBodyStyle() const
bool m_SyncPinEdit
Set to true to synchronize pins at the same position when editing symbols with multiple units or mult...
void Revert(bool aConfirm=true)
Revert unsaved changes in a symbol, restoring to the last saved state.
void centerItemIdleHandler(wxIdleEvent &aEvent)
bool replaceLibTableEntry(const wxString &aLibNickname, const wxString &aLibFile)
Replace the file path of the symbol library table entry aLibNickname with aLibFile.
bool IsSymbolFromSchematic() const
void SetScreen(BASE_SCREEN *aScreen) override
void DuplicateSymbol(bool aFromClipboard)
Insert a duplicate symbol.
SCH_SCREEN * m_dummyScreen
< Helper screen used when no symbol is loaded
void saveSymbolCopyAs(bool aOpenCopy)
void SetCurSymbol(LIB_SYMBOL *aSymbol, bool aUpdateZoom)
Take ownership of aSymbol and notes that it is the one currently being edited.
KIID m_schematicSymbolUUID
RefDes of the symbol (only valid if symbol was loaded from schematic)
std::vector< LIB_ID > GetSelectedLibIds() const
void SyncLibraries(bool aShowProgress, bool aPreloadCancelled=false, const wxString &aForceRefresh=wxEmptyString)
Synchronize the library manager to the symbol library table, and then the symbol tree to the library ...
LIB_SYMBOL * GetCurSymbol() const
Return the current symbol being edited or NULL if none selected.
void UpdateSymbolMsgPanelInfo()
Display the documentation of the selected symbol.
LIB_ID GetTargetLibId() const override
Return either the symbol selected in the symbol tree (if context menu is active) or the symbol on the...
bool saveLibrary(const wxString &aLibrary, bool aNewFile)
Save the changes to the current library.
void SelectActiveLibrary(const wxString &aLibrary=wxEmptyString)
Set the current active library to aLibrary.
int m_bodyStyle
Flag if the symbol being edited was loaded directly from a schematic.
bool saveAllLibraries(bool aRequireConfirmation)
Save the current symbol.
void UpdateMsgPanel() override
Redraw the message panel.
void CreateNewSymbol(const wxString &newName=wxEmptyString)
Create a new symbol in the selected library.
wxString SetCurLib(const wxString &aLibNickname)
Set the current library nickname and returns the old library nickname.
void UpdateTitle()
Update the main window title bar with the current library name and read only status of the library.
bool LoadSymbolFromCurrentLib(const wxString &aSymbolName, int aUnit=0, int aBodyStyle=0)
Load a symbol from the current active library, optionally setting the selected unit and convert.
SYMBOL_TREE_PANE * m_treePane
bool LoadOneLibrarySymbolAux(LIB_SYMBOL *aLibEntry, const wxString &aLibrary, int aUnit, int aBodyStyle)
Create a copy of aLibEntry into memory.
bool saveCurrentSymbol()
Store the currently modified symbol in the library manager buffer.
void SaveSymbolCopyAs(bool aOpenCopy)
Save the currently selected symbol to a new name and/or location.
wxString AddLibraryFile(bool aCreateNew)
Create or add an existing library to the symbol library table.
void ensureUniqueName(LIB_SYMBOL *aSymbol, const wxString &aLibrary)
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current symbol.
void SetShowDeMorgan(bool show)
void SaveLibraryAs()
Save the currently selected library to a new file.
bool IsContentModified() const override
Get if any symbols or libraries have been modified but not saved.
LIB_SYMBOL * getTargetSymbol() const
Return either the library selected in the symbol tree, if context menu is active or the library that ...
SYMBOL_SAVEAS_TYPE GetOption() const
bool IsLibraryReadOnly(const wxString &aLibrary) const
Return true if the library is stored in a read-only file.
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 * GetBufferedSymbol(const wxString &aSymbolName, const wxString &aLibrary)
Return the symbol copy from the buffer.
bool ClearSymbolModified(const wxString &aSymbolName, const wxString &aLibrary) const
Clear the modified flag for a symbol.
SCH_SCREEN * GetScreen(const wxString &aSymbolName, const wxString &aLibrary)
Return the screen used to edit a specific symbol.
bool SymbolNameInUse(const wxString &aName, const wxString &aLibrary)
Return true if the symbol name is already in use in the specified library.
bool IsLibraryModified(const wxString &aLibrary) const
Return true if library has unsaved modifications.
LIB_SYMBOL * GetSymbol(const wxString &aSymbolName, 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...
bool RemoveSymbol(const wxString &aSymbolName, const wxString &aLibrary)
Remove the symbol from the symbol buffer.
wxArrayString GetLibraryNames() const
Return the array of library names.
bool UpdateSymbolAfterRename(LIB_SYMBOL *aSymbol, const wxString &aOldSymbolName, const wxString &aLibrary)
Update the symbol buffer with a new version of the symbol when the name has changed.
bool IsSymbolModified(const wxString &aSymbolName, const wxString &aLibrary) const
Return true if symbol has unsaved modifications.
bool RevertLibrary(const wxString &aLibrary)
Revert unsaved changes for a symbol library.
LIB_ID RevertSymbol(const wxString &aSymbolName, const wxString &aLibrary)
Revert unsaved changes for a symbol.
void GetSymbolNames(const wxString &aLibName, wxArrayString &aSymbolNames, SYMBOL_NAME_FILTER aFilter=SYMBOL_NAME_FILTER::ALL)
bool RevertAll()
Revert all pending changes.
bool SymbolExists(const wxString &aSymbolName, const wxString &aLibrary) const
Return true if symbol with a specific alias exists in library (either original one or buffered).
SYMBOL_LIB_TABLE_ROW * GetLibrary(const wxString &aLibrary) const
Find a single library within the (aggregate) library table.
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.
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_IO object i...
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
This is a class that handles state involved in saving a symbol copy as a new symbol.
CONFLICT_STRATEGY m_strategy
wxString resolveConflict(const wxString &proposed, const wxString &aNewLibName) const
SYMBOL_SAVE_AS_HANDLER(LIB_SYMBOL_LIBRARY_MANAGER &aLibMgr, CONFLICT_STRATEGY aStrategy, bool aValueFollowsName)
LIB_SYMBOL_LIBRARY_MANAGER & m_libMgr
bool DoSave(LIB_SYMBOL &symbol, const wxString &aNewSymName, const wxString &aNewLibName)
LIB_TREE * GetLibTree() const
void SetExcludedFromBoard(bool aExcludeFromBoard) override
Set or clear exclude from board netlist flag.
Definition: symbol.h:186
virtual void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition: symbol.h:164
int GetPinNameOffset() const
Definition: symbol.h:153
virtual void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
Definition: symbol.h:158
void SetExcludedFromBOM(bool aExcludeFromBOM) override
Set or clear the exclude from schematic bill of materials flag.
Definition: symbol.h:180
void SetPinNameOffset(int aOffset)
Set the offset in mils of the pin name text from the pin symbol.
Definition: symbol.h:152
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:171
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition: tool_base.h:80
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
void ResetTools(TOOL_BASE::RESET_REASON aReason)
Reset all tools (i.e.
wxString wx_str() const
Definition: utf8.cpp:45
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION, MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the infobar with the provided message and icon for a specific period of time.
Definition: wx_infobar.cpp:140
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:190
std::string GetClipboardUTF8()
Return the information currently stored in the system clipboard.
Definition: clipboard.cpp:57
int OKOrCancelDialog(wxWindow *aParent, const wxString &aWarning, const wxString &aMessage, const wxString &aDetailedMessage, const wxString &aOKLabel, const wxString &aCancelLabel, bool *aApplyToAll)
Display a warning dialog with aMessage and returns the user response.
Definition: confirm.cpp:151
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:260
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition: confirm.cpp:138
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:203
int UnsavedChangesDialog(wxWindow *parent, const wxString &aMessage, bool *aApplyToAll)
A specialized version of HandleUnsavedChanges which handles an apply-to-all checkbox.
Definition: confirm.cpp:73
bool ConfirmRevertDialog(wxWindow *parent, const wxString &aMessage)
Display a confirmation dialog for a revert action.
Definition: confirm.cpp:127
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:178
This file is part of the common library.
#define _(s)
static int ID_MAKE_NEW_LIBRARY
@ FRAME_SCH
Definition: frame_type.h:34
static const std::string KiCadSymbolLibFileExtension
static wxString KiCadSymbolLibFileWildcard()
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition: io_mgr.h:33
PROJECT & Prj()
Definition: kicad.cpp:597
This file is part of the common library.
std::shared_ptr< LIB_SYMBOL > LIB_SYMBOL_SPTR
shared pointer to LIB_SYMBOL
Definition: lib_symbol.h:52
void Prettify(std::string &aSource, bool aCompactSave)
@ ALL
All except INITIAL_ADD.
Definition: view_item.h:59
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
STL namespace.
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:893
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:198
KIWAY Kiway(KFCTL_STANDALONE)
MODEL3D_FORMAT_TYPE fileType(const char *aFileName)
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_LIBID
Definition: string_utils.h:54
std::vector< wxString > pinned_symbol_libs
static std::vector< LIB_SYMBOL_SPTR > GetParentChain(const LIB_SYMBOL &aSymbol)
Get a list of all the symbols in the parental chain of a symbol, with the "leaf" symbol at the start ...
SAVE_AS_IDS
@ ID_OVERWRITE_CONFLICTS
@ ID_RENAME_CONFLICTS
@ ID_MAKE_NEW_LIBRARY
static std::vector< wxString > CheckForParentalChainConflicts(LIB_SYMBOL_LIBRARY_MANAGER &aLibMgr, LIB_SYMBOL &aSymbol, const wxString &newSymbolName, const wxString &newLibraryName)
Get a list of all the symbols in the parental chain of a symbol that have conflicts when transposed t...
static std::pair< bool, bool > CheckSavingIntoOwnInheritance(LIB_SYMBOL_LIBRARY_MANAGER &aLibMgr, LIB_SYMBOL &aSymbol, const wxString &aNewSymbolName, const wxString &aNewLibraryName)
Check if a planned overwrite would put a symbol into it's own inheritance chain.
Definition for symbol library class.
SYMBOL_SAVEAS_TYPE
#define MANDATORY_FIELDS
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
const SHAPE_LINE_CHAIN chain
Definition of file extensions used in Kicad.