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"
54
55
57{
58 wxString title;
59
61 {
63 title = wxT( "*" );
64
65 title += m_reference;
66 title += wxS( " " ) + _( "[from schematic]" );
67 }
68 else if( GetCurSymbol() )
69 {
71 title = wxT( "*" );
72
73 title += UnescapeString( GetCurSymbol()->GetLibId().Format() );
74
76 title += wxS( " " ) + _( "[Read Only Library]" );
77 }
78 else
79 {
80 title = _( "[no symbol loaded]" );
81 }
82
83 title += wxT( " \u2014 " ) + _( "Symbol Editor" );
84 SetTitle( title );
85}
86
87
88void SYMBOL_EDIT_FRAME::SelectActiveLibrary( const wxString& aLibrary )
89{
90 wxString selectedLib = aLibrary;
91
92 if( selectedLib.empty() )
93 selectedLib = SelectLibrary( _( "Select Symbol Library" ), _( "Library:" ) );
94
95 if( !selectedLib.empty() )
96 SetCurLib( selectedLib );
97
99}
100
101
103{
104 if( GetCurSymbol() )
105 {
107 {
108 SCH_EDIT_FRAME* schframe = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, false );
109
110 if( !schframe ) // happens when the schematic editor has been closed
111 {
112 DisplayErrorMessage( this, _( "No schematic currently open." ) );
113 return false;
114 }
115 else
116 {
118 GetScreen()->SetContentModified( false );
119 return true;
120 }
121 }
122 else
123 {
124 const wxString& libName = GetCurSymbol()->GetLibId().GetLibNickname();
125
126 if( m_libMgr->IsLibraryReadOnly( libName ) )
127 {
128 wxString msg = wxString::Format( _( "Symbol library '%s' is not writable." ),
129 libName );
130 wxString msg2 = _( "You must save to a different location." );
131
132 if( OKOrCancelDialog( this, _( "Warning" ), msg, msg2 ) == wxID_OK )
133 return saveLibrary( libName, true );
134 }
135 else
136 {
137 return saveLibrary( libName, false );
138 }
139 }
140 }
141
142 return false;
143}
144
145
146bool SYMBOL_EDIT_FRAME::LoadSymbol( const LIB_ID& aLibId, int aUnit, int aBodyStyle )
147{
148 LIB_ID libId = aLibId;
149
150 // Some libraries can't be edited, so load the underlying chosen symbol
152 {
153 if( lib->SchLibType() == SCH_IO_MGR::SCH_DATABASE
154 || lib->SchLibType() == SCH_IO_MGR::SCH_CADSTAR_ARCHIVE
155 || lib->SchLibType() == SCH_IO_MGR::SCH_HTTP )
156
157 {
158 try
159 {
160 LIB_SYMBOL* readOnlySym = PROJECT_SCH::SchSymbolLibTable( &Prj() )->LoadSymbol( aLibId );
161
162 if( readOnlySym && readOnlySym->GetSourceLibId().IsValid() )
163 libId = readOnlySym->GetSourceLibId();
164 }
165 catch( const IO_ERROR& ioe )
166 {
167 wxString msg;
168
169 msg.Printf( _( "Error loading symbol %s from library '%s'." ),
170 aLibId.GetUniStringLibId(), aLibId.GetUniStringLibItemName() );
171 DisplayErrorMessage( this, msg, ioe.What() );
172 return false;
173 }
174 }
175 }
176
178 && GetCurSymbol()->GetLibId() == libId
179 && GetUnit() == aUnit
180 && GetBodyStyle() == aBodyStyle )
181 {
182 return true;
183 }
184
186 {
187 if( !HandleUnsavedChanges( this, _( "The current symbol has been modified. Save changes?" ),
188 [&]() -> bool
189 {
190 return saveCurrentSymbol();
191 } ) )
192 {
193 return false;
194 }
195 }
196
198
199 if( LoadSymbolFromCurrentLib( libId.GetLibItemName(), aUnit, aBodyStyle ) )
200 {
201 m_treePane->GetLibTree()->SelectLibId( libId );
202 m_treePane->GetLibTree()->ExpandLibId( libId );
203
204 m_centerItemOnIdle = libId;
205 Bind( wxEVT_IDLE, &SYMBOL_EDIT_FRAME::centerItemIdleHandler, this );
206 setSymWatcher( &libId );
207
208 return true;
209 }
210
211 return false;
212}
213
214
216{
218 Unbind( wxEVT_IDLE, &SYMBOL_EDIT_FRAME::centerItemIdleHandler, this );
219}
220
221
222bool SYMBOL_EDIT_FRAME::LoadSymbolFromCurrentLib( const wxString& aSymbolName, int aUnit,
223 int aBodyStyle )
224{
225 LIB_SYMBOL* symbol = nullptr;
226
227 try
228 {
229 symbol = PROJECT_SCH::SchSymbolLibTable( &Prj() )->LoadSymbol( GetCurLib(), aSymbolName );
230 }
231 catch( const IO_ERROR& ioe )
232 {
233 wxString msg;
234
235 msg.Printf( _( "Error loading symbol %s from library '%s'." ),
236 aSymbolName,
237 GetCurLib() );
238 DisplayErrorMessage( this, msg, ioe.What() );
239 return false;
240 }
241
242 if( !symbol || !LoadOneLibrarySymbolAux( symbol, GetCurLib(), aUnit, aBodyStyle ) )
243 return false;
244
245 // Enable synchronized pin edit mode for symbols with interchangeable units
247
250 SetShowDeMorgan( GetCurSymbol()->Flatten()->HasAlternateBodyStyle() );
251
252 if( aUnit > 0 )
254
255 return true;
256}
257
258
259bool SYMBOL_EDIT_FRAME::LoadOneLibrarySymbolAux( LIB_SYMBOL* aEntry, const wxString& aLibrary,
260 int aUnit, int aBodyStyle )
261{
262 bool rebuildMenuAndToolbar = false;
263
264 if( !aEntry || aLibrary.empty() )
265 return false;
266
267 if( aEntry->GetName().IsEmpty() )
268 {
269 wxLogWarning( "Symbol in library '%s' has empty name field.", aLibrary );
270 return false;
271 }
272
274
275 // Symbols from the schematic are edited in place and not managed by the library manager.
277 {
278 delete m_symbol;
279 m_symbol = nullptr;
280
281 SCH_SCREEN* screen = GetScreen();
282 delete screen;
285 rebuildMenuAndToolbar = true;
286 }
287
288 LIB_SYMBOL* lib_symbol = m_libMgr->GetBufferedSymbol( aEntry->GetName(), aLibrary );
289 wxCHECK( lib_symbol, false );
290
291 m_unit = aUnit > 0 ? aUnit : 1;
292 m_bodyStyle = aBodyStyle > 0 ? aBodyStyle : 1;
293
294 // The buffered screen for the symbol
295 SCH_SCREEN* symbol_screen = m_libMgr->GetScreen( lib_symbol->GetName(), aLibrary );
296
297 SetScreen( symbol_screen );
298 SetCurSymbol( new LIB_SYMBOL( *lib_symbol ), true );
299 SetCurLib( aLibrary );
300
301 if( rebuildMenuAndToolbar )
302 {
305 GetInfoBar()->Dismiss();
306 }
307
308 UpdateTitle();
310 SetShowDeMorgan( GetCurSymbol()->HasAlternateBodyStyle() );
311
313
314 if( !IsSymbolFromSchematic() )
315 {
316 LIB_ID libId = GetCurSymbol()->GetLibId();
317 setSymWatcher( &libId );
318 }
319
320 // Let tools add things to the view if necessary
321 if( m_toolManager )
323
325
326 // Display the document information based on the entry selected just in
327 // case the entry is an alias.
329 Refresh();
330
331 return true;
332}
333
334
336{
337 saveAllLibraries( false );
339}
340
341
342void SYMBOL_EDIT_FRAME::CreateNewSymbol( const wxString& aInheritFrom )
343{
345
346 wxString lib = getTargetLib();
347
348 if( !m_libMgr->LibraryExists( lib ) )
349 {
350 lib = SelectLibrary( _( "New Symbol" ), _( "Create symbol in library:" ) );
351
352 if( !m_libMgr->LibraryExists( lib ) )
353 return;
354 }
355
356 const auto validator =
357 [&]( wxString newName ) -> bool
358 {
359 if( newName.IsEmpty() )
360 {
361 wxMessageBox( _( "Symbol must have a name." ) );
362 return false;
363 }
364
365 if( !lib.empty() && m_libMgr->SymbolNameInUse( newName, lib ) )
366 {
367 wxString msg;
368
369 msg.Printf( _( "Symbol '%s' already exists in library '%s'." ),
370 UnescapeString( newName ),
371 lib );
372
373 KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
374 wxOK | wxCANCEL | wxICON_WARNING );
375
376 errorDlg.SetOKLabel( _( "Overwrite" ) );
377
378 return errorDlg.ShowModal() == wxID_OK;
379 }
380
381 return true;
382 };
383
384 wxArrayString symbolNamesInLib;
385 m_libMgr->GetSymbolNames( lib, symbolNamesInLib );
386
387 DIALOG_LIB_NEW_SYMBOL dlg( this, symbolNamesInLib, aInheritFrom, validator );
388
389 dlg.SetMinSize( dlg.GetSize() );
390
391 if( dlg.ShowModal() == wxID_CANCEL )
392 return;
393
394 wxString name = dlg.GetName();
395
396 LIB_SYMBOL new_symbol( name ); // do not create symbol on the heap, it will be buffered soon
397
398 wxString parentSymbolName = dlg.GetParentSymbolName();
399
400 if( parentSymbolName.IsEmpty() )
401 {
402 new_symbol.GetReferenceField().SetText( dlg.GetReference() );
403 new_symbol.SetUnitCount( dlg.GetUnitCount() );
404
405 // Initialize new_symbol.m_TextInside member:
406 // if 0, pin text is outside the body (on the pin)
407 // if > 0, pin text is inside the body
408 if( dlg.GetPinNameInside() )
409 {
410 new_symbol.SetPinNameOffset( dlg.GetPinTextPosition() );
411
412 if( new_symbol.GetPinNameOffset() == 0 )
413 new_symbol.SetPinNameOffset( 1 );
414 }
415 else
416 {
417 new_symbol.SetPinNameOffset( 0 );
418 }
419
420 ( dlg.GetPowerSymbol() ) ? new_symbol.SetGlobalPower() : new_symbol.SetNormal();
421 new_symbol.SetShowPinNumbers( dlg.GetShowPinNumber() );
422 new_symbol.SetShowPinNames( dlg.GetShowPinName() );
423 new_symbol.LockUnits( !dlg.GetUnitsInterchangeable() );
424 new_symbol.SetExcludedFromBOM( !dlg.GetIncludeInBom() );
425 new_symbol.SetExcludedFromBoard( !dlg.GetIncludeOnBoard() );
426
427 if( dlg.GetUnitCount() < 2 )
428 new_symbol.LockUnits( false );
429
431 }
432 else
433 {
434 LIB_SYMBOL* parent = m_libMgr->GetSymbol( parentSymbolName, lib );
435 wxCHECK( parent, /* void */ );
436 new_symbol.SetParent( parent );
437
438 // Inherit the parent mandatory field attributes.
439 for( FIELD_T fieldId : MANDATORY_FIELDS )
440 {
441 SCH_FIELD* field = new_symbol.GetField( fieldId );
442 SCH_FIELD* parentField = parent->GetField( fieldId );
443
444 *field = *parentField;
445
446 switch( fieldId )
447 {
448 case FIELD_T::REFERENCE:
449 // parent's reference already copied
450 break;
451
452 case FIELD_T::VALUE:
453 if( parent->IsPower() )
454 field->SetText( name );
455 break;
456
457 case FIELD_T::FOOTPRINT:
458 if( !dlg.GetKeepFootprint() )
459 field->SetText( wxEmptyString );
460 break;
461
462 case FIELD_T::DATASHEET:
463 // - footprint might be the same as parent, but might not
464 // - datasheet is most likely different
465 // - probably best to play it safe and copy neither
466 if( !dlg.GetKeepDatasheet() )
467 field->SetText( wxEmptyString );
468 break;
469
470 default:
471 break;
472 }
473
474 field->SetParent( &new_symbol );
475 }
476
477 if( dlg.GetTransferUserFields() )
478 {
479 std::vector<SCH_FIELD*> listFields;
480 parent->GetFields( listFields );
481
482 for( SCH_FIELD* field : listFields )
483 {
484 if( field->GetId() == FIELD_T::USER )
485 {
486 SCH_FIELD* new_field = new SCH_FIELD( *field );
487
488 if( !dlg.GetKeepContentUserFields() )
489 new_field->SetText( wxEmptyString );
490
491 new_field->SetParent( &new_symbol );
492 new_symbol.AddField( new_field );
493 }
494 }
495 }
496 }
497
498 m_libMgr->UpdateSymbol( &new_symbol, lib );
499 SyncLibraries( false );
500 LoadSymbol( name, lib, 1 );
501
502 // must be called after loadSymbol, that calls SetShowDeMorgan, but
503 // because the symbol is empty,it looks like it has no alternate body
504 // and a derived symbol inherits its parent body.
505 if( !new_symbol.GetParent().lock() )
507 else
509}
510
511
513{
514 wxString libName;
515
516 if( IsLibraryTreeShown() )
518
519 if( libName.empty() )
520 {
522 }
523 else if( m_libMgr->IsLibraryReadOnly( libName ) )
524 {
525 wxString msg = wxString::Format( _( "Symbol library '%s' is not writable." ),
526 libName );
527 wxString msg2 = _( "You must save to a different location." );
528
529 if( OKOrCancelDialog( this, _( "Warning" ), msg, msg2 ) == wxID_OK )
530 saveLibrary( libName, true );
531 }
532 else
533 {
534 saveLibrary( libName, false );
535 }
536
537 if( IsLibraryTreeShown() )
539
540 UpdateTitle();
541}
542
543
545{
546 const wxString& libName = GetTargetLibId().GetLibNickname();
547
548 if( !libName.IsEmpty() )
549 {
550 saveLibrary( libName, true );
552 }
553}
554
555
557{
558 saveSymbolCopyAs( aOpenCopy );
559
561}
562
563
570static std::vector<LIB_SYMBOL_SPTR> GetParentChain( const LIB_SYMBOL& aSymbol )
571{
572 std::vector<LIB_SYMBOL_SPTR> chain( { aSymbol.SharedPtr() } );
573
574 while( chain.back()->IsDerived() )
575 {
576 LIB_SYMBOL_SPTR parent = chain.back()->GetParent().lock();
577 chain.push_back( parent );
578 }
579
580 return chain;
581}
582
583
593static std::pair<bool, bool> CheckSavingIntoOwnInheritance( LIB_SYMBOL_LIBRARY_MANAGER& aLibMgr,
594 LIB_SYMBOL& aSymbol,
595 const wxString& aNewSymbolName,
596 const wxString& aNewLibraryName )
597{
598 const wxString& oldLibraryName = aSymbol.GetLibId().GetLibNickname();
599
600 // Cannot be intersecting if in different libs
601 if( aNewLibraryName != oldLibraryName )
602 return { false, false };
603
604 // Or if the target symbol doesn't exist
605 if( !aLibMgr.SymbolNameInUse( aNewSymbolName, aNewLibraryName ) )
606 return { false, false };
607
608 bool inAncestry = false;
609 bool inDescendents = false;
610
611 {
612 const std::vector<LIB_SYMBOL_SPTR> parentChainFromUs = GetParentChain( aSymbol );
613
614 // Ignore the leaf symbol (0) - that must match
615 for( size_t i = 1; i < parentChainFromUs.size(); ++i )
616 {
617 // Attempting to overwrite a symbol in the parental chain
618 if( parentChainFromUs[i]->GetName() == aNewSymbolName )
619 {
620 inAncestry = true;
621 break;
622 }
623 }
624 }
625
626 {
627 LIB_SYMBOL* targetSymbol = aLibMgr.GetSymbol( aNewSymbolName, aNewLibraryName );
628 const std::vector<LIB_SYMBOL_SPTR> parentChainFromTarget = GetParentChain( *targetSymbol );
629 const wxString oldSymbolName = aSymbol.GetName();
630
631 // Ignore the leaf symbol - it'll match if we're saving the symbol
632 // to the same name, and that would be OK
633 for( size_t i = 1; i < parentChainFromTarget.size(); ++i )
634 {
635 if( parentChainFromTarget[i]->GetName() == oldSymbolName )
636 {
637 inDescendents = true;
638 break;
639 }
640 }
641 }
642
643 return { inAncestry, inDescendents };
644}
645
646
654static std::vector<wxString> CheckForParentalChainConflicts( LIB_SYMBOL_LIBRARY_MANAGER& aLibMgr,
655 LIB_SYMBOL& aSymbol,
656 const wxString& newSymbolName,
657 const wxString& newLibraryName )
658{
659 std::vector<wxString> conflicts;
660 const wxString& oldLibraryName = aSymbol.GetLibId().GetLibNickname();
661
662 if( newLibraryName == oldLibraryName )
663 {
664 // Saving into the same library - the only conflict could be the symbol itself
665 if( aLibMgr.SymbolNameInUse( newSymbolName, newLibraryName ) )
666 conflicts.push_back( newSymbolName );
667 }
668 else
669 {
670 // In a different library, check the whole chain
671 const std::vector<LIB_SYMBOL_SPTR> parentChain = GetParentChain( aSymbol );
672
673 for( size_t i = 0; i < parentChain.size(); ++i )
674 {
675 if( i == 0 )
676 {
677 // This is the leaf symbol which the user actually named
678 if( aLibMgr.SymbolNameInUse( newSymbolName, newLibraryName ) )
679 conflicts.push_back( newSymbolName );
680 }
681 else
682 {
683 LIB_SYMBOL_SPTR chainSymbol = parentChain[i];
684
685 if( aLibMgr.SymbolNameInUse( chainSymbol->GetName(), newLibraryName ) )
686 conflicts.push_back( chainSymbol->GetName() );
687 }
688 }
689 }
690
691 return conflicts;
692}
693
694
702{
703public:
705 {
706 // Just overwrite any existing symbols in the target library
707 OVERWRITE,
708 // Add a suffix until we find a name that doesn't conflict
709 RENAME,
710 // Could have a mode that asks for every one, be then we'll need a fancier
711 // SAVE_SYMBOL_AS_DIALOG subdialog with Overwrite/Rename/Prompt/Cancel
712 // PROMPT
713 };
714
716 bool aValueFollowsName ) :
717 m_libMgr( aLibMgr ),
718 m_strategy( aStrategy ),
719 m_valueFollowsName( aValueFollowsName )
720 {
721 }
722
723 bool DoSave( LIB_SYMBOL& symbol, const wxString& aNewSymName, const wxString& aNewLibName )
724 {
725 std::vector<LIB_SYMBOL_SPTR> parentChain;
726 // If we're saving into the same library, we don't need to check the parental chain
727 // because we can just keep the same parent symbol
728 if( aNewLibName == symbol.GetLibId().GetLibNickname().wx_str() )
729 parentChain.push_back( symbol.SharedPtr() );
730 else
731 parentChain = GetParentChain( symbol );
732
733 std::vector<wxString> newNames;
734
735 // Iterate backwards (i.e. from the root down)
736 for( int i = (int) parentChain.size() - 1; i >= 0; --i )
737 {
738 LIB_SYMBOL_SPTR& oldSymbol = parentChain[i];
739
740 LIB_SYMBOL new_symbol( *oldSymbol );
741
742 wxString newName;
743 if( i == 0 )
744 {
745 // This is the leaf symbol which the user actually named
746 newName = aNewSymName;
747 }
748 else
749 {
750 // Somewhere in the inheritance chain, use the conflict resolution strategy
751 newName = oldSymbol->GetName();
752 }
753
754 newName = resolveConflict( newName, aNewLibName );
755 new_symbol.SetName( newName );
756
758 new_symbol.GetValueField().SetText( newName );
759
760 if( i == (int) parentChain.size() - 1 )
761 {
762 // This is the root symbol
763 // Nothing extra to do, it's just a simple symbol with no parents
764 }
765 else
766 {
767 // Get the buffered new copy in the new library (with the name we gave it)
768 LIB_SYMBOL* newParent = m_libMgr.GetSymbol( newNames.back(), aNewLibName );
769
770 // We should have stored this already, why didn't we get it back?
771 wxASSERT( newParent );
772 new_symbol.SetParent( newParent );
773 }
774
775 newNames.push_back( newName );
776 m_libMgr.UpdateSymbol( &new_symbol, aNewLibName );
777 }
778
779 return true;
780 }
781
782private:
783 wxString resolveConflict( const wxString& proposed, const wxString& aNewLibName ) const
784 {
785 switch( m_strategy )
786 {
788 {
789 // In an overwrite strategy, we don't care about conflicts
790 return proposed;
791 }
793 {
794 // In a rename strategy, we need to find a name that doesn't conflict
795 int suffix = 1;
796
797 while( true )
798 {
799 wxString newName = wxString::Format( "%s_%d", proposed, suffix );
800
801 if( !m_libMgr.SymbolNameInUse( newName, aNewLibName ) )
802 return newName;
803
804 ++suffix;
805 }
806 break;
807 }
808 // No default
809 }
810
811 wxFAIL_MSG( "Invalid conflict strategy" );
812 return "";
813 }
814
818};
819
820
822{
823 ID_MAKE_NEW_LIBRARY = wxID_HIGHEST + 1,
826};
827
828
830{
831public:
832 using SymLibNameValidator = std::function<int( const wxString& libName, const wxString& symbolName )>;
833
834 SAVE_SYMBOL_AS_DIALOG( SYMBOL_EDIT_FRAME* aParent, const wxString& aSymbolName,
835 const wxString& aLibraryPreselect, SymLibNameValidator aValidator,
836 SYMBOL_SAVE_AS_HANDLER::CONFLICT_STRATEGY& aConflictStrategy ) :
837 EDA_LIST_DIALOG( aParent, _( "Save Symbol As" ), false ),
838 m_validator( std::move( aValidator ) ),
839 m_conflictStrategy( aConflictStrategy )
840 {
842 std::vector<wxString> libNicknames = tbl->GetLogicalLibs();
843 wxArrayString headers;
844 std::vector<wxArrayString> itemsToDisplay;
845
846 aParent->GetLibraryItemsForListDialog( headers, itemsToDisplay );
847 initDialog( headers, itemsToDisplay, aLibraryPreselect );
848
849 SetListLabel( _( "Save in library:" ) );
850 SetOKLabel( _( "Save" ) );
851
852 wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
853
854 wxStaticText* label = new wxStaticText( this, wxID_ANY, _( "Name:" ) );
855 bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
856
857 m_symbolNameCtrl = new wxTextCtrl( this, wxID_ANY, UnescapeString( aSymbolName ) );
858 bNameSizer->Add( m_symbolNameCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
859
860 wxButton* newLibraryButton = new wxButton( this, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
861 m_ButtonsSizer->Prepend( 80, 20 );
862 m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
863
864 GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
865
866 Bind( wxEVT_BUTTON,
867 [this]( wxCommandEvent& )
868 {
869 EndModal( ID_MAKE_NEW_LIBRARY );
871
872 // Move nameTextCtrl to the head of the tab-order
873 if( GetChildren().DeleteObject( m_symbolNameCtrl ) )
874 GetChildren().Insert( m_symbolNameCtrl );
875
877
879
880 Layout();
881 GetSizer()->Fit( this );
882
883 Centre();
884 }
885
886 wxString GetSymbolName()
887 {
888 wxString symbolName = m_symbolNameCtrl->GetValue();
889 symbolName.Trim( true );
890 symbolName.Trim( false );
891 symbolName.Replace( " ", "_" );
892 return EscapeString( symbolName, CTX_LIBID );
893 }
894
895protected:
897 {
899
900 if( ret == wxID_CANCEL )
901 return false;
902
903 if( ret == ID_OVERWRITE_CONFLICTS )
905 else if( ret == ID_RENAME_CONFLICTS )
907
908 return true;
909 }
910
911private:
912 wxTextCtrl* m_symbolNameCtrl;
915};
916
917
919{
920 LIB_SYMBOL* symbol = getTargetSymbol();
921
922 if( !symbol )
923 return;
924
925 LIB_ID old_lib_id = symbol->GetLibId();
926 wxString symbolName = old_lib_id.GetLibItemName();
927 wxString libraryName = old_lib_id.GetLibNickname();
928 bool valueFollowsName = symbol->GetValueField().GetText() == symbolName;
929 wxString msg;
930 bool done = false;
931
932 // This is the function that will be called when the user clicks OK in the dialog and checks
933 // if the proposed name has problems, and asks for clarification.
934 const auto dialogValidatorFunc =
935 [&]( const wxString& newLib, const wxString& newName ) -> int
936 {
937 if( newLib.IsEmpty() )
938 {
939 wxMessageBox( _( "A library must be specified." ) );
940 return wxID_CANCEL;
941 }
942
943 if( newName.IsEmpty() )
944 {
945 wxMessageBox( _( "Symbol must have a name." ) );
946 return wxID_CANCEL;
947 }
948
949 if( m_libMgr->IsLibraryReadOnly( newLib ) )
950 {
951 msg = wxString::Format( _( "Library '%s' is read-only. Choose a "
952 "different library to save the symbol '%s' to." ),
953 newLib,
954 UnescapeString( newName ) );
955 wxMessageBox( msg );
956 return wxID_CANCEL;
957 }
958
963 const auto& [inAncestry, inDescendents] = CheckSavingIntoOwnInheritance( *m_libMgr, *symbol,
964 newName, newLib );
965
966 if( inAncestry )
967 {
968 msg = wxString::Format( _( "Symbol '%s' cannot replace another symbol '%s' "
969 "that it descends from" ),
970 symbolName,
971 UnescapeString( newName ) );
972 wxMessageBox( msg );
973 return wxID_CANCEL;
974 }
975
976 if( inDescendents )
977 {
978 msg = wxString::Format( _( "Symbol '%s' cannot replace another symbol '%s' "
979 "that is a descendent of it." ),
980 symbolName,
981 UnescapeString( newName ) );
982 wxMessageBox( msg );
983 return wxID_CANCEL;
984 }
985
986 const std::vector<wxString> conflicts = CheckForParentalChainConflicts( *m_libMgr, *symbol,
987 newName, newLib );
988
989 if( conflicts.size() == 1 && conflicts.front() == newName )
990 {
991 // The simplest case is when the symbol itself has a conflict
992 msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'. "
993 "Do you want to overwrite it?" ),
994 UnescapeString( newName ),
995 newLib );
996
997 KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
998 errorDlg.SetOKLabel( _( "Overwrite" ) );
999
1000 return errorDlg.ShowModal() == wxID_OK ? ID_OVERWRITE_CONFLICTS : (int) wxID_CANCEL;
1001 }
1002 else if( !conflicts.empty() )
1003 {
1004 // If there are conflicts in the parental chain, we need to ask the user
1005 // if they want to overwrite all of them.
1006 // A more complex UI might allow the user to re-parent the symbol to an
1007 // existing symbol in the target lib, or rename all the parents somehow.
1008 msg = wxString::Format( _( "The following symbols in the inheritance chain of "
1009 "'%s' already exist in library '%s':\n" ),
1010 UnescapeString( symbolName ),
1011 newLib );
1012
1013 for( const wxString& conflict : conflicts )
1014 msg += wxString::Format( " %s\n", conflict );
1015
1016 msg += _( "\nDo you want to overwrite all of them, or rename the new symbols?" );
1017
1018 KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxYES_NO | wxCANCEL | wxICON_WARNING );
1019 errorDlg.SetYesNoCancelLabels( _( "Overwrite All" ), _( "Rename All" ), _( "Cancel" ) );
1020
1021 switch( errorDlg.ShowModal() )
1022 {
1023 case wxID_YES: return ID_OVERWRITE_CONFLICTS;
1024 case wxID_NO: return ID_RENAME_CONFLICTS;
1025 default: return wxID_CANCEL;
1026 }
1027 }
1028
1029 return wxID_OK;
1030 };
1031
1033
1034 // Keep asking the user for a new name until they give a valid one or cancel the operation
1035 while( !done )
1036 {
1037 SAVE_SYMBOL_AS_DIALOG dlg( this, symbolName, libraryName, dialogValidatorFunc, strategy );
1038
1039 int ret = dlg.ShowModal();
1040
1041 switch( ret )
1042 {
1043 case wxID_CANCEL:
1044 return;
1045
1046 case wxID_OK: // No conflicts
1049 symbolName = dlg.GetSymbolName();
1050 libraryName = dlg.GetTextSelection();
1051
1052 if( ret == ID_RENAME_CONFLICTS )
1054
1055 done = true;
1056 break;
1057
1059 {
1060 wxFileName newLibrary( AddLibraryFile( true ) );
1061 libraryName = newLibrary.GetName();
1062 break;
1063 }
1064
1065 default:
1066 break;
1067 }
1068 }
1069
1070 SYMBOL_SAVE_AS_HANDLER saver( *m_libMgr, strategy, valueFollowsName );
1071
1072 saver.DoSave( *symbol, symbolName, libraryName );
1073
1074 SyncLibraries( false );
1075
1076 if( aOpenCopy )
1077 LoadSymbol( symbolName, libraryName, 1 );
1078}
1079
1080
1082{
1083 wxString msg;
1084 LIB_SYMBOL* symbol = getTargetSymbol();
1085
1086 if( !symbol )
1087 {
1088 ShowInfoBarError( _( "There is no symbol selected to save." ) );
1089 return;
1090 }
1091
1092 wxFileName fn;
1093
1094 fn.SetName( symbol->GetName().Lower() );
1096
1097 wxFileDialog dlg( this, _( "Export Symbol" ), m_mruPath, fn.GetFullName(),
1099
1100 if( dlg.ShowModal() == wxID_CANCEL )
1101 return;
1102
1104
1105 fn = dlg.GetPath();
1106 fn.MakeAbsolute();
1107
1108 wxString libraryName;
1109 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = symbol->Flatten();
1110
1111 for( const wxString& candidate : m_libMgr->GetLibraryNames() )
1112 {
1113 if( m_libMgr->GetLibrary( candidate )->GetFullURI( true ) == fn.GetFullPath() )
1114 libraryName = candidate;
1115 }
1116
1117 if( !libraryName.IsEmpty() )
1118 {
1119 SYMBOL_SAVE_AS_HANDLER saver( *m_libMgr, strategy, false );
1120
1121 if( m_libMgr->IsLibraryReadOnly( libraryName ) )
1122 {
1123 msg = wxString::Format( _( "Library '%s' is read-only." ), libraryName );
1124 DisplayError( this, msg );
1125 return;
1126 }
1127
1128 if( m_libMgr->SymbolNameInUse( symbol->GetName(), libraryName ) )
1129 {
1130 msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'." ),
1131 symbol->GetName(), libraryName );
1132
1133 KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1134 errorDlg.SetOKLabel( _( "Overwrite" ) );
1135 errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1136
1137 if( errorDlg.ShowModal() == wxID_CANCEL )
1138 return;
1139 }
1140
1141 saver.DoSave( *flattenedSymbol, symbol->GetName(), libraryName );
1142
1143 SyncLibraries( false );
1144 return;
1145 }
1146
1147 LIB_SYMBOL* old_symbol = nullptr;
1148 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( fn.GetFullPath() );
1149
1150 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
1151 pluginType = SCH_IO_MGR::SCH_KICAD;
1152
1153 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pluginType ) );
1154
1155 if( fn.FileExists() )
1156 {
1157 try
1158 {
1159 old_symbol = pi->LoadSymbol( fn.GetFullPath(), symbol->GetName() );
1160 }
1161 catch( const IO_ERROR& ioe )
1162 {
1163 msg.Printf( _( "Error occurred attempting to load symbol library file '%s'." ),
1164 fn.GetFullPath() );
1165 DisplayErrorMessage( this, msg, ioe.What() );
1166 return;
1167 }
1168
1169 if( old_symbol )
1170 {
1171 msg.Printf( _( "Symbol %s already exists in library '%s'." ),
1172 UnescapeString( symbol->GetName() ),
1173 fn.GetFullName() );
1174
1175 KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1176 errorDlg.SetOKLabel( _( "Overwrite" ) );
1177 errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1178
1179 if( errorDlg.ShowModal() == wxID_CANCEL )
1180 return;
1181 }
1182 }
1183
1184 if( !fn.IsDirWritable() )
1185 {
1186 msg.Printf( _( "Insufficient permissions to save library '%s'." ), fn.GetFullPath() );
1187 DisplayError( this, msg );
1188 return;
1189 }
1190
1191 try
1192 {
1193 if( !fn.FileExists() )
1194 pi->CreateLibrary( fn.GetFullPath() );
1195
1196 // The flattened symbol is most likely what the user would want. As some point in
1197 // the future as more of the symbol library inheritance is implemented, this may have
1198 // to be changes to save symbols of inherited symbols.
1199 pi->SaveSymbol( fn.GetFullPath(), flattenedSymbol.release() );
1200 }
1201 catch( const IO_ERROR& ioe )
1202 {
1203 msg.Printf( _( "Failed to create symbol library file '%s'." ), fn.GetFullPath() );
1204 DisplayErrorMessage( this, msg, ioe.What() );
1205 msg.Printf( _( "Error creating symbol library '%s'." ), fn.GetFullName() );
1206 SetStatusText( msg );
1207 return;
1208 }
1209
1210 m_mruPath = fn.GetPath();
1211
1212 msg.Printf( _( "Symbol %s saved to library '%s'." ),
1213 UnescapeString( symbol->GetName() ),
1214 fn.GetFullPath() );
1215 SetStatusText( msg );
1216}
1217
1218
1220{
1221 wxCHECK( m_symbol, /* void */ );
1222
1223 wxString lib = GetCurLib();
1224
1225 if( !lib.IsEmpty() && aOldName && *aOldName != m_symbol->GetName() )
1226 {
1227 // Test the current library for name conflicts
1228 if( m_libMgr->SymbolNameInUse( m_symbol->GetName(), lib ) )
1229 {
1230 wxString msg = wxString::Format( _( "Symbol name '%s' already in use." ),
1232
1233 DisplayErrorMessage( this, msg );
1234 m_symbol->SetName( *aOldName );
1235 }
1236 else
1237 {
1238 m_libMgr->UpdateSymbolAfterRename( m_symbol, *aOldName, lib );
1239 }
1240
1241 // Reselect the renamed symbol
1243 }
1244
1246 SetShowDeMorgan( GetCurSymbol()->Flatten()->HasAlternateBodyStyle() );
1247 UpdateTitle();
1248
1249 // N.B. The view needs to be rebuilt first as the Symbol Properties change may invalidate
1250 // the view pointers by rebuilting the field table
1251 RebuildView();
1253
1254 OnModify();
1255}
1256
1257
1259{
1260 std::vector<LIB_ID> toDelete = GetSelectedLibIds();
1261
1262 if( toDelete.empty() )
1263 toDelete.emplace_back( GetTargetLibId() );
1264
1265 for( LIB_ID& libId : toDelete )
1266 {
1267 if( m_libMgr->IsSymbolModified( libId.GetLibItemName(), libId.GetLibNickname() )
1268 && !IsOK( this, wxString::Format( _( "The symbol '%s' has been modified.\n"
1269 "Do you want to remove it from the library?" ),
1270 libId.GetUniStringLibItemName() ) ) )
1271 {
1272 continue;
1273 }
1274
1275 if( m_libMgr->HasDerivedSymbols( libId.GetLibItemName(), libId.GetLibNickname() ) )
1276 {
1277 wxString msg;
1278
1279 msg.Printf(
1280 _( "The symbol %s is used to derive other symbols.\n"
1281 "Deleting this symbol will delete all of the symbols derived from it.\n\n"
1282 "Do you wish to delete this symbol and all of its derivatives?" ),
1283 libId.GetLibItemName().wx_str() );
1284
1285 wxMessageDialog::ButtonLabel yesButtonLabel( _( "Delete Symbol" ) );
1286 wxMessageDialog::ButtonLabel noButtonLabel( _( "Keep Symbol" ) );
1287
1288 wxMessageDialog dlg( this, msg, _( "Warning" ),
1289 wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION | wxCENTER );
1290 dlg.SetYesNoLabels( yesButtonLabel, noButtonLabel );
1291
1292 if( dlg.ShowModal() == wxID_NO )
1293 continue;
1294 }
1295
1296 if( IsCurrentSymbol( libId ) )
1297 emptyScreen();
1298
1299 m_libMgr->RemoveSymbol( libId.GetLibItemName(), libId.GetLibNickname() );
1300 }
1301
1303}
1304
1305
1307{
1308 std::vector<LIB_ID> symbols;
1309
1310 if( GetTreeLIBIDs( symbols ) == 0 )
1311 return;
1312
1313 STRING_FORMATTER formatter;
1314
1315 for( LIB_ID& libId : symbols )
1316 {
1317 LIB_SYMBOL* symbol = m_libMgr->GetBufferedSymbol( libId.GetLibItemName(),
1318 libId.GetLibNickname() );
1319
1320 if( !symbol )
1321 continue;
1322
1323 std::unique_ptr<LIB_SYMBOL> tmp = symbol->Flatten();
1324 SCH_IO_KICAD_SEXPR::FormatLibSymbol( tmp.get(), formatter );
1325 }
1326
1327 std::string prettyData = formatter.GetString();
1328 KICAD_FORMAT::Prettify( prettyData, true );
1329
1330 wxLogNull doNotLog; // disable logging of failed clipboard actions
1331
1332 auto clipboard = wxTheClipboard;
1333 wxClipboardLocker clipboardLock( clipboard );
1334
1335 if( !clipboardLock || !clipboard->IsOpened() )
1336 return;
1337
1338 auto data = new wxTextDataObject( wxString( prettyData.c_str(), wxConvUTF8 ) );
1339 clipboard->SetData( data );
1340
1341 clipboard->Flush();
1342}
1343
1344
1345void SYMBOL_EDIT_FRAME::DuplicateSymbol( bool aFromClipboard )
1346{
1347 LIB_ID libId = GetTargetLibId();
1348 wxString lib = libId.GetLibNickname();
1349
1350 if( !m_libMgr->LibraryExists( lib ) )
1351 return;
1352
1353 std::vector<LIB_SYMBOL*> newSymbols;
1354
1355 if( aFromClipboard )
1356 {
1357 std::string clipboardData = GetClipboardUTF8();
1358
1359 try
1360 {
1361 newSymbols = SCH_IO_KICAD_SEXPR::ParseLibSymbols( clipboardData, "Clipboard" );
1362 }
1363 catch( IO_ERROR& e )
1364 {
1365 wxLogMessage( wxS( "Can not paste: %s" ), e.Problem() );
1366 }
1367 }
1368 else if( LIB_SYMBOL* srcSymbol = m_libMgr->GetBufferedSymbol( libId.GetLibItemName(), lib ) )
1369 {
1370 newSymbols.emplace_back( new LIB_SYMBOL( *srcSymbol ) );
1371
1372 // Derive from same parent.
1373 if( srcSymbol->IsDerived() )
1374 {
1375 if( std::shared_ptr<LIB_SYMBOL> srcParent = srcSymbol->GetParent().lock() )
1376 newSymbols.back()->SetParent( srcParent.get() );
1377 }
1378 }
1379
1380 if( newSymbols.empty() )
1381 return;
1382
1383 for( LIB_SYMBOL* symbol : newSymbols )
1384 {
1385 ensureUniqueName( symbol, lib );
1386 m_libMgr->UpdateSymbol( symbol, lib );
1387
1388 LoadOneLibrarySymbolAux( symbol, lib, GetUnit(), GetBodyStyle() );
1389 }
1390
1391 SyncLibraries( false );
1392 m_treePane->GetLibTree()->SelectLibId( LIB_ID( lib, newSymbols[0]->GetName() ) );
1393
1394 for( LIB_SYMBOL* symbol : newSymbols )
1395 delete symbol;
1396}
1397
1398
1399void SYMBOL_EDIT_FRAME::ensureUniqueName( LIB_SYMBOL* aSymbol, const wxString& aLibrary )
1400{
1401 if( aSymbol )
1402 {
1403 int i = 1;
1404 wxString newName = aSymbol->GetName();
1405
1406 // Append a number to the name until the name is unique in the library.
1407 while( m_libMgr->SymbolNameInUse( newName, aLibrary ) )
1408 newName.Printf( "%s_%d", aSymbol->GetName(), i++ );
1409
1410 aSymbol->SetName( newName );
1411 }
1412}
1413
1414
1415void SYMBOL_EDIT_FRAME::Revert( bool aConfirm )
1416{
1417 LIB_ID libId = GetTargetLibId();
1418 const wxString& libName = libId.GetLibNickname();
1419
1420 // Empty if this is the library itself that is selected.
1421 const wxString& symbolName = libId.GetLibItemName();
1422
1423 wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1424 symbolName.IsEmpty() ? libName : symbolName );
1425
1426 if( aConfirm && !ConfirmRevertDialog( this, msg ) )
1427 return;
1428
1429 bool reload_currentSymbol = false;
1430 wxString curr_symbolName = symbolName;
1431
1432 if( GetCurSymbol() )
1433 {
1434 // the library itself is reverted: the current symbol will be reloaded only if it is
1435 // owned by this library
1436 if( symbolName.IsEmpty() )
1437 {
1438 LIB_ID curr_libId = GetCurSymbol()->GetLibId();
1439 reload_currentSymbol = libName == curr_libId.GetLibNickname().wx_str();
1440
1441 if( reload_currentSymbol )
1442 curr_symbolName = curr_libId.GetUniStringLibItemName();
1443 }
1444 else
1445 {
1446 reload_currentSymbol = IsCurrentSymbol( libId );
1447 }
1448 }
1449
1450 int unit = m_unit;
1451
1452 if( reload_currentSymbol )
1453 emptyScreen();
1454
1455 if( symbolName.IsEmpty() )
1456 {
1457 m_libMgr->RevertLibrary( libName );
1458 }
1459 else
1460 {
1461 libId = m_libMgr->RevertSymbol( libId.GetLibItemName(), libId.GetLibNickname() );
1462
1463 m_treePane->GetLibTree()->SelectLibId( libId );
1465 }
1466
1467 if( reload_currentSymbol && m_libMgr->SymbolExists( curr_symbolName, libName ) )
1468 LoadSymbol( curr_symbolName, libName, unit );
1469
1470 m_treePane->Refresh();
1471}
1472
1473
1475{
1476 wxCHECK_RET( m_libMgr, "Library manager object not created." );
1477
1478 Revert( false );
1480}
1481
1482
1483void SYMBOL_EDIT_FRAME::LoadSymbol( const wxString& aAlias, const wxString& aLibrary, int aUnit )
1484{
1486 {
1487 if( !HandleUnsavedChanges( this, _( "The current symbol has been modified. Save changes?" ),
1488 [&]() -> bool
1489 {
1490 return saveCurrentSymbol();
1491 } ) )
1492 {
1493 return;
1494 }
1495 }
1496
1497 LIB_SYMBOL* symbol = m_libMgr->GetBufferedSymbol( aAlias, aLibrary );
1498
1499 if( !symbol )
1500 {
1501 DisplayError( this, wxString::Format( _( "Symbol %s not found in library '%s'." ),
1502 aAlias,
1503 aLibrary ) );
1505 return;
1506 }
1507
1508 // Optimize default edit options for this symbol
1509 // Usually if units are locked, graphic items are specific to each unit
1510 // and if units are interchangeable, graphic items are common to units
1512 tools->SetDrawSpecificUnit( symbol->UnitsLocked() );
1513
1514 LoadOneLibrarySymbolAux( symbol, aLibrary, aUnit, 0 );
1515}
1516
1517
1518bool SYMBOL_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
1519{
1520 wxFileName fn;
1521 wxString msg;
1522 SYMBOL_SAVEAS_TYPE type = SYMBOL_SAVEAS_TYPE::NORMAL_SAVE_AS;
1523 SCH_IO_MGR::SCH_FILE_T fileType = SCH_IO_MGR::SCH_FILE_T::SCH_KICAD;
1524 PROJECT& prj = Prj();
1525
1527
1528 if( !aNewFile && ( aLibrary.empty() || !PROJECT_SCH::SchSymbolLibTable( &prj )->HasLibrary( aLibrary ) ) )
1529 {
1530 ShowInfoBarError( _( "No library specified." ) );
1531 return false;
1532 }
1533
1534 if( aNewFile )
1535 {
1536 SEARCH_STACK* search = PROJECT_SCH::SchSearchS( &prj );
1537
1538 // Get a new name for the library
1539 wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH );
1540
1541 if( !default_path )
1542 default_path = search->LastVisitedPath();
1543
1544 fn.SetName( aLibrary );
1546
1547 wxString wildcards = FILEEXT::KiCadSymbolLibFileWildcard();
1548
1549 wxFileDialog dlg( this, wxString::Format( _( "Save Library '%s' As..." ), aLibrary ), default_path,
1550 fn.GetFullName(), wildcards, wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1551
1552 SYMBOL_LIBRARY_SAVE_AS_FILEDLG_HOOK saveAsHook( type );
1553 dlg.SetCustomizeHook( saveAsHook );
1554
1555 if( dlg.ShowModal() == wxID_CANCEL )
1556 return false;
1557
1558 fn = dlg.GetPath();
1559
1560 prj.SetRString( PROJECT::SCH_LIB_PATH, fn.GetPath() );
1561
1562 if( fn.GetExt().IsEmpty() )
1564
1565 type = saveAsHook.GetOption();
1566 }
1567 else
1568 {
1569 fn = PROJECT_SCH::SchSymbolLibTable( &prj )->GetFullURI( aLibrary );
1571
1572 if( fileType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
1573 fileType = SCH_IO_MGR::SCH_KICAD;
1574 }
1575
1576 // Verify the user has write privileges before attempting to save the library file.
1577 if( !aNewFile && m_libMgr->IsLibraryReadOnly( aLibrary ) )
1578 return false;
1579
1580 ClearMsgPanel();
1581
1582 // Copy .kicad_symb file to .bak.
1583 if( !backupFile( fn, "bak" ) )
1584 return false;
1585
1586 if( !m_libMgr->SaveLibrary( aLibrary, fn.GetFullPath(), fileType ) )
1587 {
1588 msg.Printf( _( "Failed to save changes to symbol library file '%s'." ),
1589 fn.GetFullPath() );
1590 DisplayErrorMessage( this, _( "Error Saving Library" ), msg );
1591 return false;
1592 }
1593
1594 if( !aNewFile )
1595 {
1596 m_libMgr->ClearLibraryModified( aLibrary );
1597
1598 // Update the library modification time so that we don't reload based on the watcher
1599 if( aLibrary == getTargetLib() )
1600 SetSymModificationTime( fn.GetModificationTime() );
1601 }
1602 else
1603 {
1604 bool resyncLibTree = false;
1605 wxString originalLibNickname = getTargetLib();
1606 wxString forceRefresh;
1607
1608 switch( type )
1609 {
1610 case SYMBOL_SAVEAS_TYPE::REPLACE_TABLE_ENTRY:
1611 resyncLibTree = replaceLibTableEntry( originalLibNickname, fn.GetFullPath() );
1612 forceRefresh = originalLibNickname;
1613 break;
1614
1615 case SYMBOL_SAVEAS_TYPE::ADD_GLOBAL_TABLE_ENTRY:
1616 resyncLibTree = addLibTableEntry( fn.GetFullPath() );
1617 break;
1618
1619 case SYMBOL_SAVEAS_TYPE::ADD_PROJECT_TABLE_ENTRY:
1620 resyncLibTree = addLibTableEntry( fn.GetFullPath(), PROJECT_LIB_TABLE );
1621 break;
1622
1623 default:
1624 break;
1625 }
1626
1627 if( resyncLibTree )
1628 {
1630 SyncLibraries( true, false, forceRefresh );
1632 }
1633 }
1634
1635 ClearMsgPanel();
1636 msg.Printf( _( "Symbol library file '%s' saved." ), fn.GetFullPath() );
1638
1639 return true;
1640}
1641
1642
1643bool SYMBOL_EDIT_FRAME::saveAllLibraries( bool aRequireConfirmation )
1644{
1645 wxString msg, msg2;
1646 bool doSave = true;
1647 int dirtyCount = 0;
1648 bool applyToAll = false;
1649 bool retv = true;
1650
1651 for( const wxString& libNickname : m_libMgr->GetLibraryNames() )
1652 {
1653 if( m_libMgr->IsLibraryModified( libNickname ) )
1654 dirtyCount++;
1655 }
1656
1657 for( const wxString& libNickname : m_libMgr->GetLibraryNames() )
1658 {
1659 if( m_libMgr->IsLibraryModified( libNickname ) )
1660 {
1661 if( aRequireConfirmation && !applyToAll )
1662 {
1663 msg.Printf( _( "Save changes to '%s' before closing?" ), libNickname );
1664
1665 switch( UnsavedChangesDialog( this, msg, dirtyCount > 1 ? &applyToAll : nullptr ) )
1666 {
1667 case wxID_YES: doSave = true; break;
1668 case wxID_NO: doSave = false; break;
1669 default:
1670 case wxID_CANCEL: return false;
1671 }
1672 }
1673
1674 if( doSave )
1675 {
1676 // If saving under existing name fails then do a Save As..., and if that
1677 // fails then cancel close action.
1678 if( m_libMgr->IsLibraryReadOnly( libNickname ) )
1679 {
1680 msg.Printf( _( "Symbol library '%s' is not writable." ), libNickname );
1681 msg2 = _( "You must save to a different location." );
1682
1683 if( dirtyCount == 1 )
1684 {
1685 if( OKOrCancelDialog( this, _( "Warning" ), msg, msg2 ) != wxID_OK )
1686 {
1687 retv = false;
1688 continue;
1689 }
1690 }
1691 else
1692 {
1693 m_infoBar->Dismiss();
1694 m_infoBar->ShowMessageFor( msg + wxS( " " ) + msg2,
1695 2000, wxICON_EXCLAMATION );
1696
1697 while( m_infoBar->IsShownOnScreen() )
1698 wxSafeYield();
1699
1700 retv = false;
1701 continue;
1702 }
1703 }
1704 else if( saveLibrary( libNickname, false ) )
1705 {
1706 continue;
1707 }
1708
1709 if( !saveLibrary( libNickname, true ) )
1710 retv = false;
1711 }
1712 }
1713 }
1714
1715 UpdateTitle();
1716 return retv;
1717}
1718
1719
1721{
1723
1724 if( !m_symbol )
1725 return;
1726
1727 wxString msg = m_symbol->GetName();
1728
1729 AppendMsgPanel( _( "Name" ), UnescapeString( msg ), 8 );
1730
1731 if( m_symbol->IsDerived() )
1732 {
1733 LIB_SYMBOL_SPTR parent = m_symbol->GetParent().lock();
1734
1735 msg = parent ? parent->GetName() : _( "Undefined!" );
1736 AppendMsgPanel( _( "Parent" ), UnescapeString( msg ), 8 );
1737 }
1738
1739 if( m_symbol->IsGlobalPower() )
1740 msg = _( "Power Symbol" );
1741 else if( m_symbol->IsLocalPower() )
1742 msg = _( "Power Symbol (Local)" );
1743 else
1744 msg = _( "Symbol" );
1745
1746 AppendMsgPanel( _( "Type" ), msg, 8 );
1747 AppendMsgPanel( _( "Description" ), m_symbol->GetDescription(), 8 );
1748 AppendMsgPanel( _( "Keywords" ), m_symbol->GetKeyWords() );
1749 AppendMsgPanel( _( "Datasheet" ), m_symbol->GetDatasheetField().GetText() );
1750}
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:75
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:113
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:1561
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:475
bool IsMulti() const override
Definition: lib_symbol.h:589
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:469
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:335
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:423
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:453
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:344
void AddField(SCH_FIELD *aField)
Add a field.
Definition: lib_symbol.cpp:993
LIB_SYMBOL_REF & GetParent()
Definition: lib_symbol.h:118
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:328
void SetNormal()
Definition: lib_symbol.cpp:503
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...
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.
void RefreshLibTree()
Refresh the tree (mainly to update highlighting and asterisking)
Definition: lib_tree.cpp:472
void CenterLibId(const LIB_ID &aLibId)
Ensure that an item is visible (preferably centered).
Definition: lib_tree.cpp:381
void SelectLibId(const LIB_ID &aLibId)
Select an item in the tree widget.
Definition: lib_tree.cpp:375
void ExpandLibId(const LIB_ID &aLibId)
Expand and item i the tree widget.
Definition: lib_tree.cpp:395
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 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:321
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:332
bool TransferDataFromWindow() override
SYMBOL_SAVE_AS_HANDLER::CONFLICT_STRATEGY & m_conflictStrategy
std::function< int(const wxString &libName, const wxString &symbolName)> SymLibNameValidator
SAVE_SYMBOL_AS_DIALOG(SYMBOL_EDIT_FRAME *aParent, const wxString &aSymbolName, const wxString &aLibraryPreselect, SymLibNameValidator aValidator, SYMBOL_SAVE_AS_HANDLER::CONFLICT_STRATEGY &aConflictStrategy)
SymLibNameValidator m_validator
wxTextCtrl * m_symbolNameCtrl
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.
void GetLibraryItemsForListDialog(wxArrayString &aHeaders, std::vector< wxArrayString > &aItemsToDisplay)
wxString SelectLibrary(const wxString &aDialogTitle, const wxString &aListLabel, const std::vector< std::pair< wxString, bool * > > &aExtraCheckboxes={})
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:1089
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 ...
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:142
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:192
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:142
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:251
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:129
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:64
bool ConfirmRevertDialog(wxWindow *parent, const wxString &aMessage)
Display a confirmation dialog for a revert action.
Definition: confirm.cpp:118
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:169
This file is part of the common library.
#define _(s)
@ 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:608
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
STL namespace.
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
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
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.