KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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 <stambaughw@gmail.com>
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 case FIELD_T::DATASHEET:
461 // - footprint might be the same as parent, but might not
462 // - datasheet is most likely different
463 // - probably best to play it safe and copy neither
464 field->SetText( wxEmptyString );
465 break;
466
467 default:
468 break;
469 }
470
471 field->SetParent( &new_symbol );
472 }
473 }
474
475 m_libMgr->UpdateSymbol( &new_symbol, lib );
476 SyncLibraries( false );
477 LoadSymbol( name, lib, 1 );
478
479 // must be called after loadSymbol, that calls SetShowDeMorgan, but
480 // because the symbol is empty,it looks like it has no alternate body
481 // and a derived symbol inherits its parent body.
482 if( !new_symbol.GetParent().lock() )
484 else
486}
487
488
490{
491 wxString libName;
492
493 if( IsLibraryTreeShown() )
495
496 if( libName.empty() )
497 {
499 }
500 else if( m_libMgr->IsLibraryReadOnly( libName ) )
501 {
502 wxString msg = wxString::Format( _( "Symbol library '%s' is not writable." ),
503 libName );
504 wxString msg2 = _( "You must save to a different location." );
505
506 if( OKOrCancelDialog( this, _( "Warning" ), msg, msg2 ) == wxID_OK )
507 saveLibrary( libName, true );
508 }
509 else
510 {
511 saveLibrary( libName, false );
512 }
513
514 if( IsLibraryTreeShown() )
516
517 UpdateTitle();
518}
519
520
522{
523 const wxString& libName = GetTargetLibId().GetLibNickname();
524
525 if( !libName.IsEmpty() )
526 {
527 saveLibrary( libName, true );
529 }
530}
531
532
534{
535 saveSymbolCopyAs( aOpenCopy );
536
538}
539
540
547static std::vector<LIB_SYMBOL_SPTR> GetParentChain( const LIB_SYMBOL& aSymbol )
548{
549 std::vector<LIB_SYMBOL_SPTR> chain( { aSymbol.SharedPtr() } );
550
551 while( chain.back()->IsDerived() )
552 {
553 LIB_SYMBOL_SPTR parent = chain.back()->GetParent().lock();
554 chain.push_back( parent );
555 }
556
557 return chain;
558}
559
560
570static std::pair<bool, bool> CheckSavingIntoOwnInheritance( LIB_SYMBOL_LIBRARY_MANAGER& aLibMgr,
571 LIB_SYMBOL& aSymbol,
572 const wxString& aNewSymbolName,
573 const wxString& aNewLibraryName )
574{
575 const wxString& oldLibraryName = aSymbol.GetLibId().GetLibNickname();
576
577 // Cannot be intersecting if in different libs
578 if( aNewLibraryName != oldLibraryName )
579 return { false, false };
580
581 // Or if the target symbol doesn't exist
582 if( !aLibMgr.SymbolNameInUse( aNewSymbolName, aNewLibraryName ) )
583 return { false, false };
584
585 bool inAncestry = false;
586 bool inDescendents = false;
587
588 {
589 const std::vector<LIB_SYMBOL_SPTR> parentChainFromUs = GetParentChain( aSymbol );
590
591 // Ignore the leaf symbol (0) - that must match
592 for( size_t i = 1; i < parentChainFromUs.size(); ++i )
593 {
594 // Attempting to overwrite a symbol in the parental chain
595 if( parentChainFromUs[i]->GetName() == aNewSymbolName )
596 {
597 inAncestry = true;
598 break;
599 }
600 }
601 }
602
603 {
604 LIB_SYMBOL* targetSymbol = aLibMgr.GetSymbol( aNewSymbolName, aNewLibraryName );
605 const std::vector<LIB_SYMBOL_SPTR> parentChainFromTarget = GetParentChain( *targetSymbol );
606 const wxString oldSymbolName = aSymbol.GetName();
607
608 // Ignore the leaf symbol - it'll match if we're saving the symbol
609 // to the same name, and that would be OK
610 for( size_t i = 1; i < parentChainFromTarget.size(); ++i )
611 {
612 if( parentChainFromTarget[i]->GetName() == oldSymbolName )
613 {
614 inDescendents = true;
615 break;
616 }
617 }
618 }
619
620 return { inAncestry, inDescendents };
621}
622
623
631static std::vector<wxString> CheckForParentalChainConflicts( LIB_SYMBOL_LIBRARY_MANAGER& aLibMgr,
632 LIB_SYMBOL& aSymbol,
633 const wxString& newSymbolName,
634 const wxString& newLibraryName )
635{
636 std::vector<wxString> conflicts;
637 const wxString& oldLibraryName = aSymbol.GetLibId().GetLibNickname();
638
639 if( newLibraryName == oldLibraryName )
640 {
641 // Saving into the same library - the only conflict could be the symbol itself
642 if( aLibMgr.SymbolNameInUse( newSymbolName, newLibraryName ) )
643 conflicts.push_back( newSymbolName );
644 }
645 else
646 {
647 // In a different library, check the whole chain
648 const std::vector<LIB_SYMBOL_SPTR> parentChain = GetParentChain( aSymbol );
649
650 for( size_t i = 0; i < parentChain.size(); ++i )
651 {
652 if( i == 0 )
653 {
654 // This is the leaf symbol which the user actually named
655 if( aLibMgr.SymbolNameInUse( newSymbolName, newLibraryName ) )
656 conflicts.push_back( newSymbolName );
657 }
658 else
659 {
660 LIB_SYMBOL_SPTR chainSymbol = parentChain[i];
661
662 if( aLibMgr.SymbolNameInUse( chainSymbol->GetName(), newLibraryName ) )
663 conflicts.push_back( chainSymbol->GetName() );
664 }
665 }
666 }
667
668 return conflicts;
669}
670
671
679{
680public:
682 {
683 // Just overwrite any existing symbols in the target library
684 OVERWRITE,
685 // Add a suffix until we find a name that doesn't conflict
686 RENAME,
687 // Could have a mode that asks for every one, be then we'll need a fancier
688 // SAVE_AS_DIALOG subdialog with Overwrite/Rename/Prompt/Cancel
689 // PROMPT
690 };
691
693 bool aValueFollowsName ) :
694 m_libMgr( aLibMgr ),
695 m_strategy( aStrategy ),
696 m_valueFollowsName( aValueFollowsName )
697 {
698 }
699
700 bool DoSave( LIB_SYMBOL& symbol, const wxString& aNewSymName, const wxString& aNewLibName )
701 {
702 std::vector<LIB_SYMBOL_SPTR> parentChain;
703 // If we're saving into the same library, we don't need to check the parental chain
704 // because we can just keep the same parent symbol
705 if( aNewLibName == symbol.GetLibId().GetLibNickname().wx_str() )
706 parentChain.push_back( symbol.SharedPtr() );
707 else
708 parentChain = GetParentChain( symbol );
709
710 std::vector<wxString> newNames;
711
712 // Iterate backwards (i.e. from the root down)
713 for( int i = (int) parentChain.size() - 1; i >= 0; --i )
714 {
715 LIB_SYMBOL_SPTR& oldSymbol = parentChain[i];
716
717 LIB_SYMBOL new_symbol( *oldSymbol );
718
719 wxString newName;
720 if( i == 0 )
721 {
722 // This is the leaf symbol which the user actually named
723 newName = aNewSymName;
724 }
725 else
726 {
727 // Somewhere in the inheritance chain, use the conflict resolution strategy
728 newName = oldSymbol->GetName();
729 }
730
731 newName = resolveConflict( newName, aNewLibName );
732 new_symbol.SetName( newName );
733
735 new_symbol.GetValueField().SetText( newName );
736
737 if( i == (int) parentChain.size() - 1 )
738 {
739 // This is the root symbol
740 // Nothing extra to do, it's just a simple symbol with no parents
741 }
742 else
743 {
744 // Get the buffered new copy in the new library (with the name we gave it)
745 LIB_SYMBOL* newParent = m_libMgr.GetSymbol( newNames.back(), aNewLibName );
746
747 // We should have stored this already, why didn't we get it back?
748 wxASSERT( newParent );
749 new_symbol.SetParent( newParent );
750 }
751
752 newNames.push_back( newName );
753 m_libMgr.UpdateSymbol( &new_symbol, aNewLibName );
754 }
755
756 return true;
757 }
758
759private:
760 wxString resolveConflict( const wxString& proposed, const wxString& aNewLibName ) const
761 {
762 switch( m_strategy )
763 {
765 {
766 // In an overwrite strategy, we don't care about conflicts
767 return proposed;
768 }
770 {
771 // In a rename strategy, we need to find a name that doesn't conflict
772 int suffix = 1;
773
774 while( true )
775 {
776 wxString newName = wxString::Format( "%s_%d", proposed, suffix );
777
778 if( !m_libMgr.SymbolNameInUse( newName, aNewLibName ) )
779 return newName;
780
781 ++suffix;
782 }
783 break;
784 }
785 // No default
786 }
787
788 wxFAIL_MSG( "Invalid conflict strategy" );
789 return "";
790 }
791
795};
796
797
799{
800 ID_MAKE_NEW_LIBRARY = wxID_HIGHEST + 1,
803};
804
805
807{
808public:
810 std::function<int( const wxString& libName, const wxString& symbolName )>;
811
812 SAVE_AS_DIALOG( SYMBOL_EDIT_FRAME* aParent, const wxString& aSymbolName,
813 const wxString& aLibraryPreselect, SymLibNameValidator aValidator,
814 SYMBOL_SAVE_AS_HANDLER::CONFLICT_STRATEGY& aConflictStrategy ) :
815 EDA_LIST_DIALOG( aParent, _( "Save Symbol As" ), false ),
816 m_validator( std::move( aValidator ) ), m_conflictStrategy( aConflictStrategy )
817 {
819 PROJECT_FILE& project = aParent->Prj().GetProjectFile();
821 std::vector<wxString> libNicknames = tbl->GetLogicalLibs();
822 wxArrayString headers;
823 std::vector<wxArrayString> itemsToDisplay;
824
825 headers.Add( _( "Nickname" ) );
826 headers.Add( _( "Description" ) );
827
828 for( const wxString& nickname : libNicknames )
829 {
830 if( alg::contains( project.m_PinnedSymbolLibs, nickname )
831 || alg::contains( cfg->m_Session.pinned_symbol_libs, nickname ) )
832 {
833 wxArrayString item;
834 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
835 item.Add( tbl->GetDescription( nickname ) );
836 itemsToDisplay.push_back( item );
837 }
838 }
839
840 for( const wxString& nickname : libNicknames )
841 {
842 if( !alg::contains( project.m_PinnedSymbolLibs, nickname )
843 && !alg::contains( cfg->m_Session.pinned_symbol_libs, nickname ) )
844 {
845 wxArrayString item;
846 item.Add( nickname );
847 item.Add( tbl->GetDescription( nickname ) );
848 itemsToDisplay.push_back( item );
849 }
850 }
851
852 initDialog( headers, itemsToDisplay, aLibraryPreselect );
853
854 SetListLabel( _( "Save in library:" ) );
855 SetOKLabel( _( "Save" ) );
856
857 wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
858
859 wxStaticText* label = new wxStaticText( this, wxID_ANY, _( "Name:" ) );
860 bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
861
862 m_symbolNameCtrl = new wxTextCtrl( this, wxID_ANY, aSymbolName );
863 bNameSizer->Add( m_symbolNameCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
864
865 wxButton* newLibraryButton = new wxButton( this, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
866 m_ButtonsSizer->Prepend( 80, 20 );
867 m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
868
869 GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
870
871 Bind( wxEVT_BUTTON,
872 [this]( wxCommandEvent& )
873 {
874 EndModal( ID_MAKE_NEW_LIBRARY );
876
877 // Move nameTextCtrl to the head of the tab-order
878 if( GetChildren().DeleteObject( m_symbolNameCtrl ) )
879 GetChildren().Insert( m_symbolNameCtrl );
880
882
884
885 Layout();
886 GetSizer()->Fit( this );
887
888 Centre();
889 }
890
891 wxString GetSymbolName()
892 {
893 wxString symbolName = m_symbolNameCtrl->GetValue();
894 symbolName.Trim( true );
895 symbolName.Trim( false );
896 symbolName.Replace( " ", "_" );
897 return symbolName;
898 }
899
900protected:
902 {
904
905 if( ret == wxID_CANCEL )
906 return false;
907
908 if( ret == ID_OVERWRITE_CONFLICTS )
910 else if( ret == ID_RENAME_CONFLICTS )
912
913 return true;
914 }
915
916private:
917 wxTextCtrl* m_symbolNameCtrl;
920};
921
922
924{
925 LIB_SYMBOL* symbol = getTargetSymbol();
926
927 if( !symbol )
928 return;
929
930 LIB_ID old_lib_id = symbol->GetLibId();
931 wxString symbolName = old_lib_id.GetLibItemName();
932 wxString libraryName = old_lib_id.GetLibNickname();
933 bool valueFollowsName = symbol->GetValueField().GetText() == symbolName;
934 wxString msg;
935 bool done = false;
936
937 // This is the function that will be called when the user clicks OK in the dialog and checks
938 // if the proposed name has problems, and asks for clarification.
939 const auto dialogValidatorFunc =
940 [&]( const wxString& newLib, const wxString& newName ) -> int
941 {
942 if( newLib.IsEmpty() )
943 {
944 wxMessageBox( _( "A library must be specified." ) );
945 return wxID_CANCEL;
946 }
947
948 if( newName.IsEmpty() )
949 {
950 wxMessageBox( _( "Symbol must have a name." ) );
951 return wxID_CANCEL;
952 }
953
954 if( m_libMgr->IsLibraryReadOnly( newLib ) )
955 {
956 msg = wxString::Format( _( "Library '%s' is read-only. Choose a "
957 "different library to save the symbol '%s' to." ),
958 newLib, newName );
959 wxMessageBox( msg );
960 return wxID_CANCEL;
961 }
962
967 const auto& [inAncestry, inDescendents] =
968 CheckSavingIntoOwnInheritance( *m_libMgr, *symbol, newName, newLib );
969
970 if( inAncestry )
971 {
972 msg = wxString::Format( _( "Symbol '%s' cannot replace another symbol '%s' "
973 "that it descends from" ),
974 symbolName, newName );
975 wxMessageBox( msg );
976 return wxID_CANCEL;
977 }
978
979 if( inDescendents )
980 {
981 msg = wxString::Format( _( "Symbol '%s' cannot replace another symbol '%s' "
982 "that is a descendent of it." ),
983 symbolName, newName );
984 wxMessageBox( msg );
985 return wxID_CANCEL;
986 }
987
988 const std::vector<wxString> conflicts =
989 CheckForParentalChainConflicts( *m_libMgr, *symbol, newName, newLib );
990
991 if( conflicts.size() == 1 && conflicts.front() == newName )
992 {
993 // The simplest case is when the symbol itself has a conflict
994 msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'. "
995 "Do you want to overwrite it?" ),
996 newName, newLib );
997
998 KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
999 wxOK | wxCANCEL | wxICON_WARNING );
1000 errorDlg.SetOKLabel( _( "Overwrite" ) );
1001
1002 return errorDlg.ShowModal() == wxID_OK ? ID_OVERWRITE_CONFLICTS
1003 : (int) wxID_CANCEL;
1004 }
1005 else if( !conflicts.empty() )
1006 {
1007 // If there are conflicts in the parental chain, we need to ask the user
1008 // if they want to overwrite all of them.
1009 // A more complex UI might allow the user to re-parent the symbol to an
1010 // existing symbol in the target lib, or rename all the parents somehow.
1011 msg = wxString::Format( _( "The following symbols in the inheritance chain of "
1012 "'%s' already exist in library '%s':\n" ),
1013 symbolName, newLib );
1014
1015 for( const wxString& conflict : conflicts )
1016 msg += wxString::Format( " %s\n", conflict );
1017
1018 msg += _( "\nDo you want to overwrite all of them, or rename the new symbols?" );
1019
1020 KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
1021 wxYES_NO | wxCANCEL | wxICON_WARNING );
1022 errorDlg.SetYesNoCancelLabels( _( "Overwrite All" ), _( "Rename All" ),
1023 _( "Cancel" ) );
1024
1025 switch( errorDlg.ShowModal() )
1026 {
1027 case wxID_YES: return ID_OVERWRITE_CONFLICTS;
1028 case wxID_NO: return ID_RENAME_CONFLICTS;
1029 default: break;
1030 }
1031 return wxID_CANCEL;
1032 }
1033
1034 return wxID_OK;
1035 };
1036
1038
1039 // Keep asking the user for a new name until they give a valid one or cancel the operation
1040 while( !done )
1041 {
1042 SAVE_AS_DIALOG dlg( this, symbolName, libraryName, dialogValidatorFunc, strategy );
1043
1044 int ret = dlg.ShowModal();
1045
1046 switch( ret )
1047 {
1048 case wxID_CANCEL:
1049 return;
1050
1051 case wxID_OK: // No conflicts
1054 symbolName = dlg.GetSymbolName();
1055 libraryName = dlg.GetTextSelection();
1056
1057 if( ret == ID_RENAME_CONFLICTS )
1059
1060 done = true;
1061 break;
1062
1064 {
1065 wxFileName newLibrary( AddLibraryFile( true ) );
1066 libraryName = newLibrary.GetName();
1067 break;
1068 }
1069
1070 default:
1071 break;
1072 }
1073 }
1074
1075 SYMBOL_SAVE_AS_HANDLER saver( *m_libMgr, strategy, valueFollowsName );
1076
1077 saver.DoSave( *symbol, symbolName, libraryName );
1078
1079 SyncLibraries( false );
1080
1081 if( aOpenCopy )
1082 LoadSymbol( symbolName, libraryName, 1 );
1083}
1084
1085
1087{
1088 wxString msg;
1089 LIB_SYMBOL* symbol = getTargetSymbol();
1090
1091 if( !symbol )
1092 {
1093 ShowInfoBarError( _( "There is no symbol selected to save." ) );
1094 return;
1095 }
1096
1097 wxFileName fn;
1098
1099 fn.SetName( symbol->GetName().Lower() );
1101
1102 wxFileDialog dlg( this, _( "Export Symbol" ), m_mruPath, fn.GetFullName(),
1104
1105 if( dlg.ShowModal() == wxID_CANCEL )
1106 return;
1107
1109
1110 fn = dlg.GetPath();
1111 fn.MakeAbsolute();
1112
1113 wxString libraryName;
1114 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = symbol->Flatten();
1115
1116 for( const wxString& candidate : m_libMgr->GetLibraryNames() )
1117 {
1118 if( m_libMgr->GetLibrary( candidate )->GetFullURI( true ) == fn.GetFullPath() )
1119 libraryName = candidate;
1120 }
1121
1122 if( !libraryName.IsEmpty() )
1123 {
1124 SYMBOL_SAVE_AS_HANDLER saver( *m_libMgr, strategy, false );
1125
1126 if( m_libMgr->IsLibraryReadOnly( libraryName ) )
1127 {
1128 msg = wxString::Format( _( "Library '%s' is read-only." ), libraryName );
1129 DisplayError( this, msg );
1130 return;
1131 }
1132
1133 if( m_libMgr->SymbolNameInUse( symbol->GetName(), libraryName ) )
1134 {
1135 msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'." ),
1136 symbol->GetName(), libraryName );
1137
1138 KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1139 errorDlg.SetOKLabel( _( "Overwrite" ) );
1140 errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1141
1142 if( errorDlg.ShowModal() == wxID_CANCEL )
1143 return;
1144 }
1145
1146 saver.DoSave( *flattenedSymbol, symbol->GetName(), libraryName );
1147
1148 SyncLibraries( false );
1149 return;
1150 }
1151
1152 LIB_SYMBOL* old_symbol = nullptr;
1153 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( fn.GetFullPath() );
1154
1155 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
1156 pluginType = SCH_IO_MGR::SCH_KICAD;
1157
1158 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pluginType ) );
1159
1160 if( fn.FileExists() )
1161 {
1162 try
1163 {
1164 old_symbol = pi->LoadSymbol( fn.GetFullPath(), symbol->GetName() );
1165 }
1166 catch( const IO_ERROR& ioe )
1167 {
1168 msg.Printf( _( "Error occurred attempting to load symbol library file '%s'." ),
1169 fn.GetFullPath() );
1170 DisplayErrorMessage( this, msg, ioe.What() );
1171 return;
1172 }
1173
1174 if( old_symbol )
1175 {
1176 msg.Printf( _( "Symbol %s already exists in library '%s'." ),
1177 UnescapeString( symbol->GetName() ),
1178 fn.GetFullName() );
1179
1180 KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1181 errorDlg.SetOKLabel( _( "Overwrite" ) );
1182 errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1183
1184 if( errorDlg.ShowModal() == wxID_CANCEL )
1185 return;
1186 }
1187 }
1188
1189 if( !fn.IsDirWritable() )
1190 {
1191 msg.Printf( _( "Insufficient permissions to save library '%s'." ), fn.GetFullPath() );
1192 DisplayError( this, msg );
1193 return;
1194 }
1195
1196 try
1197 {
1198 if( !fn.FileExists() )
1199 pi->CreateLibrary( fn.GetFullPath() );
1200
1201 // The flattened symbol is most likely what the user would want. As some point in
1202 // the future as more of the symbol library inheritance is implemented, this may have
1203 // to be changes to save symbols of inherited symbols.
1204 pi->SaveSymbol( fn.GetFullPath(), flattenedSymbol.release() );
1205 }
1206 catch( const IO_ERROR& ioe )
1207 {
1208 msg.Printf( _( "Failed to create symbol library file '%s'." ), fn.GetFullPath() );
1209 DisplayErrorMessage( this, msg, ioe.What() );
1210 msg.Printf( _( "Error creating symbol library '%s'." ), fn.GetFullName() );
1211 SetStatusText( msg );
1212 return;
1213 }
1214
1215 m_mruPath = fn.GetPath();
1216
1217 msg.Printf( _( "Symbol %s saved to library '%s'." ),
1218 UnescapeString( symbol->GetName() ),
1219 fn.GetFullPath() );
1220 SetStatusText( msg );
1221}
1222
1223
1225{
1226 wxCHECK( m_symbol, /* void */ );
1227
1228 wxString lib = GetCurLib();
1229
1230 if( !lib.IsEmpty() && aOldName && *aOldName != m_symbol->GetName() )
1231 {
1232 // Test the current library for name conflicts
1233 if( m_libMgr->SymbolNameInUse( m_symbol->GetName(), lib ) )
1234 {
1235 wxString msg = wxString::Format( _( "Symbol name '%s' already in use." ),
1237
1238 DisplayErrorMessage( this, msg );
1239 m_symbol->SetName( *aOldName );
1240 }
1241 else
1242 {
1243 m_libMgr->UpdateSymbolAfterRename( m_symbol, *aOldName, lib );
1244 }
1245
1246 // Reselect the renamed symbol
1248 }
1249
1251 SetShowDeMorgan( GetCurSymbol()->Flatten()->HasAlternateBodyStyle() );
1252 UpdateTitle();
1253
1254 // N.B. The view needs to be rebuilt first as the Symbol Properties change may invalidate
1255 // the view pointers by rebuilting the field table
1256 RebuildView();
1258
1259 OnModify();
1260}
1261
1262
1264{
1265 std::vector<LIB_ID> toDelete = GetSelectedLibIds();
1266
1267 if( toDelete.empty() )
1268 toDelete.emplace_back( GetTargetLibId() );
1269
1270 for( LIB_ID& libId : toDelete )
1271 {
1272 if( m_libMgr->IsSymbolModified( libId.GetLibItemName(), libId.GetLibNickname() )
1273 && !IsOK( this, wxString::Format( _( "The symbol '%s' has been modified.\n"
1274 "Do you want to remove it from the library?" ),
1275 libId.GetUniStringLibItemName() ) ) )
1276 {
1277 continue;
1278 }
1279
1280 if( m_libMgr->HasDerivedSymbols( libId.GetLibItemName(), libId.GetLibNickname() ) )
1281 {
1282 wxString msg;
1283
1284 msg.Printf(
1285 _( "The symbol %s is used to derive other symbols.\n"
1286 "Deleting this symbol will delete all of the symbols derived from it.\n\n"
1287 "Do you wish to delete this symbol and all of its derivatives?" ),
1288 libId.GetLibItemName().wx_str() );
1289
1290 wxMessageDialog::ButtonLabel yesButtonLabel( _( "Delete Symbol" ) );
1291 wxMessageDialog::ButtonLabel noButtonLabel( _( "Keep Symbol" ) );
1292
1293 wxMessageDialog dlg( this, msg, _( "Warning" ),
1294 wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION | wxCENTER );
1295 dlg.SetYesNoLabels( yesButtonLabel, noButtonLabel );
1296
1297 if( dlg.ShowModal() == wxID_NO )
1298 continue;
1299 }
1300
1301 if( IsCurrentSymbol( libId ) )
1302 emptyScreen();
1303
1304 m_libMgr->RemoveSymbol( libId.GetLibItemName(), libId.GetLibNickname() );
1305 }
1306
1308}
1309
1310
1312{
1313 std::vector<LIB_ID> symbols;
1314
1315 if( GetTreeLIBIDs( symbols ) == 0 )
1316 return;
1317
1318 STRING_FORMATTER formatter;
1319
1320 for( LIB_ID& libId : symbols )
1321 {
1322 LIB_SYMBOL* symbol = m_libMgr->GetBufferedSymbol( libId.GetLibItemName(),
1323 libId.GetLibNickname() );
1324
1325 if( !symbol )
1326 continue;
1327
1328 std::unique_ptr<LIB_SYMBOL> tmp = symbol->Flatten();
1329 SCH_IO_KICAD_SEXPR::FormatLibSymbol( tmp.get(), formatter );
1330 }
1331
1332 std::string prettyData = formatter.GetString();
1333 KICAD_FORMAT::Prettify( prettyData, true );
1334
1335 wxLogNull doNotLog; // disable logging of failed clipboard actions
1336
1337 auto clipboard = wxTheClipboard;
1338 wxClipboardLocker clipboardLock( clipboard );
1339
1340 if( !clipboardLock || !clipboard->IsOpened() )
1341 return;
1342
1343 auto data = new wxTextDataObject( wxString( prettyData.c_str(), wxConvUTF8 ) );
1344 clipboard->SetData( data );
1345
1346 clipboard->Flush();
1347}
1348
1349
1350void SYMBOL_EDIT_FRAME::DuplicateSymbol( bool aFromClipboard )
1351{
1352 LIB_ID libId = GetTargetLibId();
1353 wxString lib = libId.GetLibNickname();
1354
1355 if( !m_libMgr->LibraryExists( lib ) )
1356 return;
1357
1358 std::vector<LIB_SYMBOL*> newSymbols;
1359
1360 if( aFromClipboard )
1361 {
1362 std::string clipboardData = GetClipboardUTF8();
1363
1364 try
1365 {
1366 newSymbols = SCH_IO_KICAD_SEXPR::ParseLibSymbols( clipboardData, "Clipboard" );
1367 }
1368 catch( IO_ERROR& e )
1369 {
1370 wxLogMessage( wxS( "Can not paste: %s" ), e.Problem() );
1371 }
1372 }
1373 else if( LIB_SYMBOL* srcSymbol = m_libMgr->GetBufferedSymbol( libId.GetLibItemName(), lib ) )
1374 {
1375 newSymbols.emplace_back( new LIB_SYMBOL( *srcSymbol ) );
1376
1377 // Derive from same parent.
1378 if( srcSymbol->IsDerived() )
1379 {
1380 if( std::shared_ptr<LIB_SYMBOL> srcParent = srcSymbol->GetParent().lock() )
1381 newSymbols.back()->SetParent( srcParent.get() );
1382 }
1383 }
1384
1385 if( newSymbols.empty() )
1386 return;
1387
1388 for( LIB_SYMBOL* symbol : newSymbols )
1389 {
1390 ensureUniqueName( symbol, lib );
1391 m_libMgr->UpdateSymbol( symbol, lib );
1392
1393 LoadOneLibrarySymbolAux( symbol, lib, GetUnit(), GetBodyStyle() );
1394 }
1395
1396 SyncLibraries( false );
1397 m_treePane->GetLibTree()->SelectLibId( LIB_ID( lib, newSymbols[0]->GetName() ) );
1398
1399 for( LIB_SYMBOL* symbol : newSymbols )
1400 delete symbol;
1401}
1402
1403
1404void SYMBOL_EDIT_FRAME::ensureUniqueName( LIB_SYMBOL* aSymbol, const wxString& aLibrary )
1405{
1406 if( aSymbol )
1407 {
1408 int i = 1;
1409 wxString newName = aSymbol->GetName();
1410
1411 // Append a number to the name until the name is unique in the library.
1412 while( m_libMgr->SymbolNameInUse( newName, aLibrary ) )
1413 newName.Printf( "%s_%d", aSymbol->GetName(), i++ );
1414
1415 aSymbol->SetName( newName );
1416 }
1417}
1418
1419
1420void SYMBOL_EDIT_FRAME::Revert( bool aConfirm )
1421{
1422 LIB_ID libId = GetTargetLibId();
1423 const wxString& libName = libId.GetLibNickname();
1424
1425 // Empty if this is the library itself that is selected.
1426 const wxString& symbolName = libId.GetLibItemName();
1427
1428 wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1429 symbolName.IsEmpty() ? libName : symbolName );
1430
1431 if( aConfirm && !ConfirmRevertDialog( this, msg ) )
1432 return;
1433
1434 bool reload_currentSymbol = false;
1435 wxString curr_symbolName = symbolName;
1436
1437 if( GetCurSymbol() )
1438 {
1439 // the library itself is reverted: the current symbol will be reloaded only if it is
1440 // owned by this library
1441 if( symbolName.IsEmpty() )
1442 {
1443 LIB_ID curr_libId = GetCurSymbol()->GetLibId();
1444 reload_currentSymbol = libName == curr_libId.GetLibNickname().wx_str();
1445
1446 if( reload_currentSymbol )
1447 curr_symbolName = curr_libId.GetUniStringLibItemName();
1448 }
1449 else
1450 {
1451 reload_currentSymbol = IsCurrentSymbol( libId );
1452 }
1453 }
1454
1455 int unit = m_unit;
1456
1457 if( reload_currentSymbol )
1458 emptyScreen();
1459
1460 if( symbolName.IsEmpty() )
1461 {
1462 m_libMgr->RevertLibrary( libName );
1463 }
1464 else
1465 {
1466 libId = m_libMgr->RevertSymbol( libId.GetLibItemName(), libId.GetLibNickname() );
1467
1468 m_treePane->GetLibTree()->SelectLibId( libId );
1470 }
1471
1472 if( reload_currentSymbol && m_libMgr->SymbolExists( curr_symbolName, libName ) )
1473 LoadSymbol( curr_symbolName, libName, unit );
1474
1475 m_treePane->Refresh();
1476}
1477
1478
1480{
1481 wxCHECK_RET( m_libMgr, "Library manager object not created." );
1482
1483 Revert( false );
1485}
1486
1487
1488void SYMBOL_EDIT_FRAME::LoadSymbol( const wxString& aAlias, const wxString& aLibrary, int aUnit )
1489{
1491 {
1492 if( !HandleUnsavedChanges( this, _( "The current symbol has been modified. Save changes?" ),
1493 [&]() -> bool
1494 {
1495 return saveCurrentSymbol();
1496 } ) )
1497 {
1498 return;
1499 }
1500 }
1501
1502 LIB_SYMBOL* symbol = m_libMgr->GetBufferedSymbol( aAlias, aLibrary );
1503
1504 if( !symbol )
1505 {
1506 DisplayError( this, wxString::Format( _( "Symbol %s not found in library '%s'." ),
1507 aAlias,
1508 aLibrary ) );
1510 return;
1511 }
1512
1513 // Optimize default edit options for this symbol
1514 // Usually if units are locked, graphic items are specific to each unit
1515 // and if units are interchangeable, graphic items are common to units
1517 tools->SetDrawSpecificUnit( symbol->UnitsLocked() );
1518
1519 LoadOneLibrarySymbolAux( symbol, aLibrary, aUnit, 0 );
1520}
1521
1522
1523bool SYMBOL_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
1524{
1525 wxFileName fn;
1526 wxString msg;
1527 SYMBOL_SAVEAS_TYPE type = SYMBOL_SAVEAS_TYPE::NORMAL_SAVE_AS;
1528 SCH_IO_MGR::SCH_FILE_T fileType = SCH_IO_MGR::SCH_FILE_T::SCH_KICAD;
1529 PROJECT& prj = Prj();
1530
1532
1533 if( !aNewFile && ( aLibrary.empty() || !PROJECT_SCH::SchSymbolLibTable( &prj )->HasLibrary( aLibrary ) ) )
1534 {
1535 ShowInfoBarError( _( "No library specified." ) );
1536 return false;
1537 }
1538
1539 if( aNewFile )
1540 {
1541 SEARCH_STACK* search = PROJECT_SCH::SchSearchS( &prj );
1542
1543 // Get a new name for the library
1544 wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH );
1545
1546 if( !default_path )
1547 default_path = search->LastVisitedPath();
1548
1549 fn.SetName( aLibrary );
1551
1552 wxString wildcards = FILEEXT::KiCadSymbolLibFileWildcard();
1553
1554 wxFileDialog dlg( this, wxString::Format( _( "Save Library '%s' As..." ), aLibrary ),
1555 default_path, fn.GetFullName(), wildcards,
1556 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1557
1558 SYMBOL_FILEDLG_SAVE_AS saveAsHook( type );
1559 dlg.SetCustomizeHook( saveAsHook );
1560
1561 if( dlg.ShowModal() == wxID_CANCEL )
1562 return false;
1563
1564 fn = dlg.GetPath();
1565
1566 prj.SetRString( PROJECT::SCH_LIB_PATH, fn.GetPath() );
1567
1568 if( fn.GetExt().IsEmpty() )
1570
1571 type = saveAsHook.GetOption();
1572 }
1573 else
1574 {
1575 fn = PROJECT_SCH::SchSymbolLibTable( &prj )->GetFullURI( aLibrary );
1577
1578 if( fileType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
1579 fileType = SCH_IO_MGR::SCH_KICAD;
1580 }
1581
1582 // Verify the user has write privileges before attempting to save the library file.
1583 if( !aNewFile && m_libMgr->IsLibraryReadOnly( aLibrary ) )
1584 return false;
1585
1586 ClearMsgPanel();
1587
1588 // Copy .kicad_symb file to .bak.
1589 if( !backupFile( fn, "bak" ) )
1590 return false;
1591
1592 if( !m_libMgr->SaveLibrary( aLibrary, fn.GetFullPath(), fileType ) )
1593 {
1594 msg.Printf( _( "Failed to save changes to symbol library file '%s'." ),
1595 fn.GetFullPath() );
1596 DisplayErrorMessage( this, _( "Error Saving Library" ), msg );
1597 return false;
1598 }
1599
1600 if( !aNewFile )
1601 {
1602 m_libMgr->ClearLibraryModified( aLibrary );
1603
1604 // Update the library modification time so that we don't reload based on the watcher
1605 if( aLibrary == getTargetLib() )
1606 SetSymModificationTime( fn.GetModificationTime() );
1607 }
1608 else
1609 {
1610 bool resyncLibTree = false;
1611 wxString originalLibNickname = getTargetLib();
1612 wxString forceRefresh;
1613
1614 switch( type )
1615 {
1616 case SYMBOL_SAVEAS_TYPE::REPLACE_TABLE_ENTRY:
1617 resyncLibTree = replaceLibTableEntry( originalLibNickname, fn.GetFullPath() );
1618 forceRefresh = originalLibNickname;
1619 break;
1620
1621 case SYMBOL_SAVEAS_TYPE::ADD_GLOBAL_TABLE_ENTRY:
1622 resyncLibTree = addLibTableEntry( fn.GetFullPath() );
1623 break;
1624
1625 case SYMBOL_SAVEAS_TYPE::ADD_PROJECT_TABLE_ENTRY:
1626 resyncLibTree = addLibTableEntry( fn.GetFullPath(), PROJECT_LIB_TABLE );
1627 break;
1628
1629 default:
1630 break;
1631 }
1632
1633 if( resyncLibTree )
1634 {
1636 SyncLibraries( true, false, forceRefresh );
1638 }
1639 }
1640
1641 ClearMsgPanel();
1642 msg.Printf( _( "Symbol library file '%s' saved." ), fn.GetFullPath() );
1644
1645 return true;
1646}
1647
1648
1649bool SYMBOL_EDIT_FRAME::saveAllLibraries( bool aRequireConfirmation )
1650{
1651 wxString msg, msg2;
1652 bool doSave = true;
1653 int dirtyCount = 0;
1654 bool applyToAll = false;
1655 bool retv = true;
1656
1657 for( const wxString& libNickname : m_libMgr->GetLibraryNames() )
1658 {
1659 if( m_libMgr->IsLibraryModified( libNickname ) )
1660 dirtyCount++;
1661 }
1662
1663 for( const wxString& libNickname : m_libMgr->GetLibraryNames() )
1664 {
1665 if( m_libMgr->IsLibraryModified( libNickname ) )
1666 {
1667 if( aRequireConfirmation && !applyToAll )
1668 {
1669 msg.Printf( _( "Save changes to '%s' before closing?" ), libNickname );
1670
1671 switch( UnsavedChangesDialog( this, msg, dirtyCount > 1 ? &applyToAll : nullptr ) )
1672 {
1673 case wxID_YES: doSave = true; break;
1674 case wxID_NO: doSave = false; break;
1675 default:
1676 case wxID_CANCEL: return false;
1677 }
1678 }
1679
1680 if( doSave )
1681 {
1682 // If saving under existing name fails then do a Save As..., and if that
1683 // fails then cancel close action.
1684 if( m_libMgr->IsLibraryReadOnly( libNickname ) )
1685 {
1686 msg.Printf( _( "Symbol library '%s' is not writable." ), libNickname );
1687 msg2 = _( "You must save to a different location." );
1688
1689 if( dirtyCount == 1 )
1690 {
1691 if( OKOrCancelDialog( this, _( "Warning" ), msg, msg2 ) != wxID_OK )
1692 {
1693 retv = false;
1694 continue;
1695 }
1696 }
1697 else
1698 {
1699 m_infoBar->Dismiss();
1700 m_infoBar->ShowMessageFor( msg + wxS( " " ) + msg2,
1701 2000, wxICON_EXCLAMATION );
1702
1703 while( m_infoBar->IsShownOnScreen() )
1704 wxSafeYield();
1705
1706 retv = false;
1707 continue;
1708 }
1709 }
1710 else if( saveLibrary( libNickname, false ) )
1711 {
1712 continue;
1713 }
1714
1715 if( !saveLibrary( libNickname, true ) )
1716 retv = false;
1717 }
1718 }
1719 }
1720
1721 UpdateTitle();
1722 return retv;
1723}
1724
1725
1727{
1729
1730 if( !m_symbol )
1731 return;
1732
1733 wxString msg = m_symbol->GetName();
1734
1735 AppendMsgPanel( _( "Name" ), UnescapeString( msg ), 8 );
1736
1737 if( m_symbol->IsDerived() )
1738 {
1739 LIB_SYMBOL_SPTR parent = m_symbol->GetParent().lock();
1740
1741 msg = parent ? parent->GetName() : _( "Undefined!" );
1742 AppendMsgPanel( _( "Parent" ), UnescapeString( msg ), 8 );
1743 }
1744
1745 static wxChar UnitLetter[] = wxT( "?ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
1746 msg = UnitLetter[m_unit];
1747
1748 AppendMsgPanel( _( "Unit" ), msg, 8 );
1749
1750 if( m_bodyStyle == BODY_STYLE::DEMORGAN )
1751 msg = _( "Alternate" );
1752 else if( m_bodyStyle == BODY_STYLE::BASE )
1753 msg = _( "Standard" );
1754 else
1755 msg = wxT( "?" );
1756
1757 AppendMsgPanel( _( "Body" ), msg, 8 );
1758
1759 if( m_symbol->IsGlobalPower() )
1760 msg = _( "Power Symbol" );
1761 else if( m_symbol->IsLocalPower() )
1762 msg = _( "Power Symbol (Local)" );
1763 else
1764 msg = _( "Symbol" );
1765
1766 AppendMsgPanel( _( "Type" ), msg, 8 );
1767 AppendMsgPanel( _( "Description" ), m_symbol->GetDescription(), 8 );
1768 AppendMsgPanel( _( "Keywords" ), m_symbol->GetKeyWords() );
1769 AppendMsgPanel( _( "Datasheet" ), m_symbol->GetDatasheetField().GetText() );
1770}
const char * name
Definition: DXF_plotter.cpp:59
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
static TOOL_ACTION zoomFitScreen
Definition: actions.h:134
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:110
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:98
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:43
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:1549
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:406
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:473
bool IsMulti() const override
Definition: lib_symbol.h:587
bool IsPower() const override
Definition: lib_symbol.cpp:467
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:333
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:421
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:451
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:342
LIB_SYMBOL_REF & GetParent()
Definition: lib_symbol.h:118
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:326
void SetNormal()
Definition: lib_symbol.cpp:501
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:459
void CenterLibId(const LIB_ID &aLibId)
Ensure that an item is visible (preferably centered).
Definition: lib_tree.cpp:368
void SelectLibId(const LIB_ID &aLibId)
Select an item in the tree widget.
Definition: lib_tree.cpp:362
void ExpandLibId(const LIB_ID &aLibId)
Expand and item i the tree widget.
Definition: lib_tree.cpp:382
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:687
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:73
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:64
@ SCH_LIB_PATH
Definition: project.h:219
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:203
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:318
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:329
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:1069
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
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)
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
void SetExcludedFromBoard(bool aExcludeFromBoard)
Set or clear exclude from board netlist flag.
Definition: symbol.h:186
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:51
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:143
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:249
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:130
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:194
int UnsavedChangesDialog(wxWindow *parent, const wxString &aMessage, bool *aApplyToAll)
A specialized version of HandleUnsavedChanges which handles an apply-to-all checkbox.
Definition: confirm.cpp:66
bool ConfirmRevertDialog(wxWindow *parent, const wxString &aMessage)
Display a confirmation dialog for a revert action.
Definition: confirm.cpp:119
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
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:1071
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)
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.