KiCad PCB EDA Suite
libedit.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 (C) 2004-2019 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 
31 #include <fctsys.h>
32 #include <kiway.h>
33 #include <gr_basic.h>
34 #include <macros.h>
35 #include <pgm_base.h>
36 #include <sch_draw_panel.h>
37 #include <confirm.h>
38 #include <gestfich.h>
39 
40 #include <eeschema_id.h>
41 #include <general.h>
42 #include <lib_edit_frame.h>
43 #include <class_library.h>
44 #include <template_fieldnames.h>
46 #include <sch_edit_frame.h>
47 #include <symbol_lib_table.h>
48 #include <lib_manager.h>
49 #include <symbol_tree_pane.h>
50 #include <widgets/lib_tree.h>
51 
54 
56 #include <dialog_helpers.h>
57 
59 {
60  wxString lib = GetCurLib();
61  wxString title = _( "Symbol Editor" );
62 
63  if( GetCurPart() )
64  title += wxT( " \u2014 " ) + GetCurPart()->GetLibId().Format();
65 
66  SetTitle( title );
67 }
68 
69 
70 void LIB_EDIT_FRAME::SelectActiveLibrary( const wxString& aLibrary )
71 {
72  wxString selectedLib = aLibrary;
73 
74  if( selectedLib.empty() )
75  selectedLib = SelectLibraryFromList();
76 
77  if( !selectedLib.empty() )
78  SetCurLib( selectedLib );
79 
80  updateTitle();
81 }
82 
83 
85 {
86  if( GetCurPart() )
87  {
88  LIB_ID libId = GetCurPart()->GetLibId();
89  const wxString& libName = libId.GetLibNickname();
90  const wxString& partName = libId.GetLibItemName();
91 
92  if( m_libMgr->FlushPart( partName, libName ) )
93  {
94  m_libMgr->ClearPartModified( partName, libName );
95  return true;
96  }
97  }
98 
99  return false;
100 }
101 
102 
103 bool LIB_EDIT_FRAME::LoadComponentAndSelectLib( const LIB_ID& aLibId, int aUnit, int aConvert )
104 {
105  if( GetScreen()->IsModify() && GetCurPart() )
106  {
107  if( !HandleUnsavedChanges( this, _( "The current symbol has been modified. Save changes?" ),
108  [&]()->bool { return saveCurrentPart(); } ) )
109  {
110  return false;
111  }
112  }
113 
115  return LoadComponentFromCurrentLib( aLibId.GetLibItemName(), aUnit, aConvert );
116 }
117 
118 
119 bool LIB_EDIT_FRAME::LoadComponentFromCurrentLib( const wxString& aAliasName, int aUnit,
120  int aConvert )
121 {
122  LIB_ALIAS* alias = nullptr;
123 
124  try
125  {
126  alias = Prj().SchSymbolLibTable()->LoadSymbol( GetCurLib(), aAliasName );
127  }
128  catch( const IO_ERROR& ioe )
129  {
130  wxString msg;
131 
132  msg.Printf( _( "Error occurred loading symbol \"%s\" from library \"%s\"." ),
133  aAliasName, GetCurLib() );
134  DisplayErrorMessage( this, msg, ioe.What() );
135  return false;
136  }
137 
138  if( !alias || !LoadOneLibraryPartAux( alias, GetCurLib(), aUnit, aConvert ) )
139  return false;
140 
141  // Enable synchronized pin edit mode for symbols with interchangeable units
143 
145  Zoom_Automatique( false );
146  SetShowDeMorgan( GetCurPart()->HasConversion() );
147 
148  if( aUnit > 0 )
150 
151  return true;
152 }
153 
165  const SCH_SCREEN& aCurrentScreen, SCH_SCREEN& aIncomingScreen )
166 {
167  aIncomingScreen.SetGrid( aCurrentScreen.GetGridSize() );
168 }
169 
170 
171 bool LIB_EDIT_FRAME::LoadOneLibraryPartAux( LIB_ALIAS* aEntry, const wxString& aLibrary,
172  int aUnit, int aConvert )
173 {
174  wxString msg, rootName;
175 
176  if( !aEntry || aLibrary.empty() )
177  return false;
178 
179  if( aEntry->GetName().IsEmpty() )
180  {
181  wxLogWarning( "Symbol in library \"%s\" has empty name field.", aLibrary );
182  return false;
183  }
184 
185  LIB_PART* lib_part = m_libMgr->GetBufferedPart( aEntry->GetName(), aLibrary );
186  wxASSERT( lib_part );
187 
188  m_unit = aUnit > 0 ? aUnit : 1;
189  m_convert = aConvert > 0 ? aConvert : 1;
190 
191  // The buffered screen for the part
192  SCH_SCREEN* part_screen = m_libMgr->GetScreen( lib_part->GetName(), aLibrary );
193 
194  const SCH_SCREEN* curr_screen = GetScreen();
195 
196  // Before we set the frame screen, transfer any settings from the current
197  // screen that we want to keep to the incoming (buffered) part's screen
198  // which could be out of date relative to the current screen.
199  if( curr_screen )
200  synchronizeLibEditScreenSettings( *curr_screen, *part_screen );
201 
202  SetScreen( part_screen );
203  SetCurPart( new LIB_PART( *lib_part ) );
204  SetCurLib( aLibrary );
205 
206  Zoom_Automatique( false );
207  updateTitle();
209 
210  // Display the document information based on the entry selected just in
211  // case the entry is an alias.
212  DisplayCmpDoc();
213  Refresh();
214 
215  return true;
216 }
217 
218 
219 void LIB_EDIT_FRAME::RedrawComponent( wxDC* aDC, wxPoint aOffset )
220 {
221  LIB_PART* part = GetCurPart();
222 
223  if( part )
224  {
225  // display reference like in schematic (a reference U is shown U? or U?A)
226  // although it is stored without ? and part id.
227  // So temporary change the reference by a schematic like reference
228  LIB_FIELD* field = part->GetField( REFERENCE );
229  wxString fieldText = field->GetText();
230  wxString fieldfullText = field->GetFullText( m_unit );
231 
232  field->EDA_TEXT::SetText( fieldfullText ); // change the field text string only
233  auto opts = PART_DRAW_OPTIONS::Default();
234  opts.show_elec_type = GetShowElectricalType();
235  part->Draw( m_canvas, aDC, aOffset, m_unit, m_convert, opts );
236  field->EDA_TEXT::SetText( fieldText ); // restore the field text string
237  }
238 }
239 
240 
241 void LIB_EDIT_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg )
242 {
243  if( GetScreen() == NULL )
244  return;
245 
246  m_canvas->DrawBackGround( DC );
247 
248  RedrawComponent( DC, wxPoint( 0, 0 ) );
249 
250 #ifdef USE_WX_OVERLAY
251  if( IsShown() )
252  {
253  m_overlay.Reset();
254  wxDCOverlay overlaydc( m_overlay, (wxWindowDC*)DC );
255  overlaydc.Clear();
256  }
257 #endif
258 
259  if( m_canvas->IsMouseCaptured() )
260  m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
261 
262  m_canvas->DrawCrossHair( DC );
263 
264  updateTitle();
265  UpdateStatusBar();
266 }
267 
268 
269 void LIB_EDIT_FRAME::OnSaveAll( wxCommandEvent& event )
270 {
271  saveAllLibraries( false );
272  m_treePane->Refresh();
274 }
275 
276 
277 void LIB_EDIT_FRAME::OnCreateNewPart( wxCommandEvent& event )
278 {
279  m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, GetGalCanvas()->GetDefaultCursor() );
280  SetDrawItem( NULL );
281  wxString lib = getTargetLib();
282 
283  if( !m_libMgr->LibraryExists( lib ) )
284  {
285  lib = SelectLibraryFromList();
286 
287  if( !m_libMgr->LibraryExists( lib ) )
288  return;
289  }
290 
291  DIALOG_LIB_NEW_COMPONENT dlg( this );
292  dlg.SetMinSize( dlg.GetSize() );
293 
294  if( dlg.ShowModal() == wxID_CANCEL )
295  return;
296 
297  if( dlg.GetName().IsEmpty() )
298  {
299  wxMessageBox( _( "This new symbol has no name and cannot be created." ) );
300  return;
301  }
302 
303  wxString name = dlg.GetName();
304  // Currently, symbol names cannot include a space, that breaks libraries:
305  name.Replace( " ", "_" );
306 
307  // Test if there is a component with this name already.
308  if( !lib.empty() && m_libMgr->PartExists( name, lib ) )
309  {
310  wxString msg = wxString::Format( _( "Symbol \"%s\" already exists in library \"%s\"" ),
311  name, lib );
312  DisplayError( this, msg );
313  return;
314  }
315 
316  LIB_PART new_part( name ); // do not create part on the heap, it will be buffered soon
317  new_part.GetReferenceField().SetText( dlg.GetReference() );
318  new_part.SetUnitCount( dlg.GetUnitCount() );
319 
320  // Initialize new_part.m_TextInside member:
321  // if 0, pin text is outside the body (on the pin)
322  // if > 0, pin text is inside the body
323 
324  if( dlg.GetPinNameInside() )
325  {
326  new_part.SetPinNameOffset( dlg.GetPinTextPosition() );
327 
328  if( new_part.GetPinNameOffset() == 0 )
329  new_part.SetPinNameOffset( 1 );
330  }
331  else
332  {
333  new_part.SetPinNameOffset( 0 );
334  }
335 
336  ( dlg.GetPowerSymbol() ) ? new_part.SetPower() : new_part.SetNormal();
337  new_part.SetShowPinNumbers( dlg.GetShowPinNumber() );
338  new_part.SetShowPinNames( dlg.GetShowPinName() );
339  new_part.LockUnits( dlg.GetLockItems() );
340 
341  if( dlg.GetUnitCount() < 2 )
342  new_part.LockUnits( false );
343 
344  m_libMgr->UpdatePart( &new_part, lib );
345  SyncLibraries( false );
346  loadPart( name, lib, 1 );
347 
348  new_part.SetConversion( dlg.GetAlternateBodyStyle() );
349  // must be called after loadPart, that calls SetShowDeMorgan, but
350  // because the symbol is empty,it looks like it has no alternate body
352 
353 }
354 
355 
356 void LIB_EDIT_FRAME::OnEditPart( wxCommandEvent& aEvent )
357 {
358  int unit = 0;
359  LIB_ID partId = m_treePane->GetLibTree()->GetSelectedLibId( &unit );
360  loadPart( partId.GetLibItemName(), partId.GetLibNickname(), unit );
361 }
362 
363 
364 void LIB_EDIT_FRAME::OnSave( wxCommandEvent& aEvent )
365 {
366  LIB_ID libId = getTargetLibId();
367  const wxString& libName = libId.GetLibNickname();
368  const wxString& partName = libId.GetLibItemName();
369 
370  if( partName.IsEmpty() )
371  {
372  saveLibrary( libName, false );
373  }
374  else
375  {
376  // Save Part
377  if( m_libMgr->FlushPart( partName, libName ) )
378  m_libMgr->ClearPartModified( partName, libName );
379  }
380 
381  m_treePane->Refresh();
383 }
384 
385 
386 void LIB_EDIT_FRAME::OnSaveAs( wxCommandEvent& aEvent )
387 {
388  LIB_ID libId = getTargetLibId();
389  const wxString& libName = libId.GetLibNickname();
390  const wxString& partName = libId.GetLibItemName();
391 
392  if( partName.IsEmpty() )
393  saveLibrary( libName, true );
394  else
395  savePartAs();
396 
397  m_treePane->Refresh();
399 }
400 
401 
403 {
404  LIB_ID old_lib_id = getTargetLibId();
405  wxString old_name = old_lib_id.GetLibItemName();
406  wxString old_lib = old_lib_id.GetLibNickname();
407  LIB_PART* part = m_libMgr->GetBufferedPart( old_name, old_lib );
408 
409  if( part )
410  {
411  SYMBOL_LIB_TABLE* tbl = Prj().SchSymbolLibTable();
412  wxArrayString headers;
413  std::vector< wxArrayString > itemsToDisplay;
414  std::vector< wxString > libNicknames = tbl->GetLogicalLibs();
415 
416  headers.Add( _( "Nickname" ) );
417  headers.Add( _( "Description" ) );
418 
419  for( const auto& name : libNicknames )
420  {
421  wxArrayString item;
422  item.Add( name );
423  item.Add( tbl->GetDescription( name ) );
424  itemsToDisplay.push_back( item );
425  }
426 
427  EDA_LIST_DIALOG dlg( this, _( "Save Copy of Symbol" ), headers, itemsToDisplay, old_lib,
428  nullptr, nullptr, /* sort */ false, /* show headers */ false );
429  dlg.SetListLabel( _( "Save in library:" ) );
430  dlg.SetOKLabel( _( "Save" ) );
431 
432  wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
433 
434  wxStaticText* label = new wxStaticText( &dlg, wxID_ANY, _( "Name:" ),
435  wxDefaultPosition, wxDefaultSize, 0 );
436  bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
437 
438  wxTextCtrl* nameTextCtrl = new wxTextCtrl( &dlg, wxID_ANY, old_name,
439  wxDefaultPosition, wxDefaultSize, 0 );
440  bNameSizer->Add( nameTextCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
441 
442  wxSizer* mainSizer = dlg.GetSizer();
443  mainSizer->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
444 
445  // Move nameTextCtrl to the head of the tab-order
446  if( dlg.GetChildren().DeleteObject( nameTextCtrl ) )
447  dlg.GetChildren().Insert( nameTextCtrl );
448 
449  dlg.SetInitialFocus( nameTextCtrl );
450 
451  dlg.Layout();
452  mainSizer->Fit( &dlg );
453 
454  if( dlg.ShowModal() != wxID_OK )
455  return; // canceled by user
456 
457  wxString new_lib = dlg.GetTextSelection();
458 
459  if( new_lib.IsEmpty() )
460  {
461  DisplayError( NULL, _( "No library specified. Symbol could not be saved." ) );
462  return;
463  }
464 
465  wxString new_name = nameTextCtrl->GetValue();
466  new_name.Trim( true );
467  new_name.Trim( false );
468  new_name.Replace( " ", "_" );
469 
470  if( new_name.IsEmpty() )
471  {
472  DisplayError( NULL, _( "No symbol name specified. Symbol could not be saved." ) );
473  return;
474  }
475 
476  // Test if there is a component with this name already.
477  if( m_libMgr->PartExists( new_name, new_lib ) )
478  {
479  wxString msg = wxString::Format( _( "Symbol \"%s\" already exists in library \"%s\"" ),
480  new_name, new_lib );
481  DisplayError( this, msg );
482  return;
483  }
484 
485  LIB_PART new_part( *part );
486  new_part.SetName( new_name );
487 
488  fixDuplicateAliases( &new_part, new_lib );
489  m_libMgr->UpdatePart( &new_part, new_lib );
490  SyncLibraries( false );
491  m_treePane->GetLibTree()->SelectLibId( LIB_ID( new_lib, new_part.GetName() ) );
492 
493  if( isCurrentPart( old_lib_id ) )
494  loadPart( new_name, new_lib, m_unit );
495  }
496 }
497 
498 
499 void LIB_EDIT_FRAME::OnRemovePart( wxCommandEvent& aEvent )
500 {
501  LIB_ID libId = getTargetLibId();
502 
503  if( m_libMgr->IsPartModified( libId.GetLibItemName(), libId.GetLibNickname() )
504  && !IsOK( this, _( wxString::Format( "Component %s has been modified\n"
505  "Do you want to remove it from the library?",
506  libId.GetUniStringLibItemName() ) ) ) )
507  {
508  return;
509  }
510 
511  if( isCurrentPart( libId ) )
512  emptyScreen();
513 
514  m_libMgr->RemovePart( libId.GetLibItemName(), libId.GetLibNickname() );
515 
517 }
518 
519 
520 void LIB_EDIT_FRAME::OnCopyCutPart( wxCommandEvent& aEvent )
521 {
522  int dummyUnit;
523  LIB_ID libId = m_treePane->GetLibTree()->GetSelectedLibId( &dummyUnit );
524  LIB_PART* part = m_libMgr->GetBufferedPart( libId.GetLibItemName(), libId.GetLibNickname() );
525 
526  if( !part )
527  return;
528 
529  m_copiedPart.reset( new LIB_PART( *part ) );
530 
531  if( aEvent.GetId() == ID_LIBEDIT_CUT_PART )
532  OnRemovePart( aEvent );
533 }
534 
535 
536 void LIB_EDIT_FRAME::OnPasteDuplicatePart( wxCommandEvent& aEvent )
537 {
538  int dummyUnit;
539  LIB_ID libId = m_treePane->GetLibTree()->GetSelectedLibId( &dummyUnit );
540  wxString lib = libId.GetLibNickname();
541 
542  if( !m_libMgr->LibraryExists( lib ) )
543  return;
544 
545  LIB_PART* srcPart = nullptr;
546 
547  if( aEvent.GetId() == ID_LIBEDIT_DUPLICATE_PART )
548  srcPart = m_libMgr->GetBufferedPart( libId.GetLibItemName(), lib );
549  else if( aEvent.GetId() == ID_LIBEDIT_PASTE_PART )
550  srcPart = m_copiedPart.get();
551  else
552  wxFAIL;
553 
554  if( !srcPart )
555  return;
556 
557  LIB_PART newPart( *srcPart );
558  fixDuplicateAliases( &newPart, lib );
559  m_libMgr->UpdatePart( &newPart, lib );
560  SyncLibraries( false );
561  m_treePane->GetLibTree()->SelectLibId( LIB_ID( lib, newPart.GetName() ) );
562 }
563 
564 
565 void LIB_EDIT_FRAME::fixDuplicateAliases( LIB_PART* aPart, const wxString& aLibrary )
566 {
567  wxString newName;
568 
569  for( unsigned int i = 0; i < aPart->GetAliasCount(); ++i )
570  {
571  LIB_ALIAS* alias = aPart->GetAlias( i );
572  int sfx = 0;
573  newName = alias->GetName();
574 
575  while( m_libMgr->PartExists( newName, aLibrary ) )
576  {
577  if( sfx == 0 )
578  newName = wxString::Format( "%s_copy", alias->GetName() );
579  else
580  newName = wxString::Format( "%s_copy%d", alias->GetName(), sfx );
581  ++sfx;
582  }
583 
584  if( i == 0 )
585  aPart->SetName( newName );
586  else
587  alias->SetName( newName );
588  }
589 }
590 
591 
592 void LIB_EDIT_FRAME::OnRevert( wxCommandEvent& aEvent )
593 {
594  LIB_ID libId = getTargetLibId();
595  const wxString& libName = libId.GetLibNickname();
596  const wxString& partName = libId.GetLibItemName(); // Empty if this is the library itself that is selected
597 
598  wxString msg = wxString::Format( _( "Revert \"%s\" to last version saved?" ),
599  partName.IsEmpty() ? libName : partName );
600 
601  if( !ConfirmRevertDialog( this, msg ) )
602  return;
603 
604  bool reload_currentPart = false;
605  wxString curr_partName = partName;
606 
607  if( GetCurPart() )
608  {
609  // the library itself is reverted: the current part will be reloaded only if it is
610  // owned by this library
611  if( partName.IsEmpty() )
612  {
613  LIB_ID curr_libId = GetCurPart()->GetLibId();
614  reload_currentPart = libName == curr_libId.GetLibNickname();
615 
616  if( reload_currentPart )
617  curr_partName = curr_libId.GetLibItemName();
618  }
619  else
620  reload_currentPart = isCurrentPart( libId );
621  }
622 
623  int unit = m_unit;
624 
625  if( reload_currentPart )
626  emptyScreen();
627 
628  if( partName.IsEmpty() )
629  {
630  m_libMgr->RevertLibrary( libName );
631  }
632  else
633  {
634  libId = m_libMgr->RevertPart( libId.GetLibItemName(), libId.GetLibNickname() );
635 
636  m_treePane->GetLibTree()->SelectLibId( libId );
638  }
639 
640  if( reload_currentPart && m_libMgr->PartExists( curr_partName, libName ) )
641  loadPart( curr_partName, libName, unit );
642 
643  m_treePane->Refresh();
645 }
646 
647 
648 void LIB_EDIT_FRAME::loadPart( const wxString& aAlias, const wxString& aLibrary, int aUnit )
649 {
650  wxCHECK( m_libMgr->PartExists( aAlias, aLibrary ), /* void */ );
651  LIB_PART* part = m_libMgr->GetBufferedPart( aAlias, aLibrary );
652  LIB_ALIAS* alias = part ? part->GetAlias( aAlias ) : nullptr;
653 
654  if( !alias )
655  {
656  wxString msg = wxString::Format( _( "Symbol name \"%s\" not found in library \"%s\"" ),
657  GetChars( aAlias ),
658  GetChars( aLibrary ) );
659  DisplayError( this, msg );
660  return;
661  }
662 
663  m_lastDrawItem = nullptr;
664  SetDrawItem( NULL );
665 
666  // Optimize default edit options for this symbol
667  // Usually if units are locked, graphic items are specific to each unit
668  // and if units are interchangeable, graphic items are common to units
669  m_drawSpecificUnit = part->UnitsLocked() ? true : false;
670 
671  LoadOneLibraryPartAux( alias, aLibrary, aUnit, 0 );
672 }
673 
674 
675 bool LIB_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
676 {
677  wxFileName fn;
678  wxString msg;
679  PROJECT& prj = Prj();
680 
681  m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, GetGalCanvas()->GetDefaultCursor() );
682 
683  if( !aNewFile && ( aLibrary.empty() || !prj.SchSymbolLibTable()->HasLibrary( aLibrary ) ) )
684  {
685  DisplayError( this, _( "No library specified." ) );
686  return false;
687  }
688 
689  if( aNewFile )
690  {
691  SEARCH_STACK* search = prj.SchSearchS();
692 
693  // Get a new name for the library
694  wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH );
695 
696  if( !default_path )
697  default_path = search->LastVisitedPath();
698 
699  fn.SetName( aLibrary );
700  fn.SetExt( SchematicLibraryFileExtension );
701 
702  wxFileDialog dlg( this, wxString::Format( _( "Save Library \"%s\" As..." ), aLibrary ),
703  default_path, fn.GetFullName(), SchematicLibraryFileWildcard(),
704  wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
705 
706  if( dlg.ShowModal() == wxID_CANCEL )
707  return false;
708 
709  fn = dlg.GetPath();
710 
711  // The GTK file chooser doesn't return the file extension added to
712  // file name so add it here.
713  if( fn.GetExt().IsEmpty() )
714  fn.SetExt( SchematicLibraryFileExtension );
715  }
716  else
717  {
718  fn = prj.SchSymbolLibTable()->GetFullURI( aLibrary );
719  }
720 
721  // Verify the user has write privileges before attempting to save the library file.
722  if( !IsWritable( fn ) )
723  return false;
724 
725  ClearMsgPanel();
726 
727  // Copy .lib file to .bak.
728  if( !backupFile( fn, "bak" ) )
729  return false;
730 
731  wxFileName docFileName = fn;
732  docFileName.SetExt( DOC_EXT );
733 
734  // Copy .dcm file to .bck.
735  if( !backupFile( docFileName, "bck" ) )
736  return false;
737 
738  if( !m_libMgr->SaveLibrary( aLibrary, fn.GetFullPath() ) )
739  {
740  msg.Printf( _( "Failed to save changes to symbol library file \"%s\"" ),
741  fn.GetFullPath() );
742  DisplayErrorMessage( this, _( "Error saving library" ), msg );
743  return false;
744  }
745 
746  if( !aNewFile )
747  m_libMgr->ClearLibraryModified( aLibrary );
748 
749  msg.Printf( _( "Symbol library file \"%s\" saved" ), fn.GetFullPath() );
750  wxString msg1;
751  msg1.Printf( _( "Symbol library documentation file \"%s\" saved" ), docFileName.GetFullPath() );
752  AppendMsgPanel( msg, msg1, BLUE );
754 
755  return true;
756 }
757 
758 
759 bool LIB_EDIT_FRAME::saveAllLibraries( bool aRequireConfirmation )
760 {
761  bool doSave = true;
762  int dirtyCount = 0;
763  bool applyToAll = false;
764 
765  for( const auto& libNickname : m_libMgr->GetLibraryNames() )
766  {
767  if( m_libMgr->IsLibraryModified( libNickname ) )
768  dirtyCount++;
769  }
770 
771  for( const auto& libNickname : m_libMgr->GetLibraryNames() )
772  {
773  if( m_libMgr->IsLibraryModified( libNickname ) )
774  {
775  if( aRequireConfirmation && !applyToAll )
776  {
777  wxString msg = wxString::Format( _( "Save changes to \"%s\" before closing?" ),
778  libNickname );
779 
780  switch( UnsavedChangesDialog( this, msg, dirtyCount > 1 ? &applyToAll : nullptr ) )
781  {
782  case wxID_YES: doSave = true; break;
783  case wxID_NO: doSave = false; break;
784  default:
785  case wxID_CANCEL: return false;
786  }
787  }
788 
789  if( doSave )
790  {
791  // If saving under existing name fails then do a Save As..., and if that
792  // fails then cancel close action.
793  if( !saveLibrary( libNickname, false ) && !saveLibrary( libNickname, true ) )
794  return false;
795  }
796  }
797  }
798 
799  return true;
800 }
801 
802 
804 {
805  LIB_PART* part = GetCurPart();
806 
807  ClearMsgPanel();
808 
809  if( !part )
810  return;
811 
812  LIB_ALIAS* alias = part->GetAlias( part->GetName() );
813  wxString msg = part->GetName();
814 
815  AppendMsgPanel( _( "Name" ), msg, BLUE, 8 );
816 
817  static wxChar UnitLetter[] = wxT( "?ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
818  msg = UnitLetter[m_unit];
819 
820  AppendMsgPanel( _( "Unit" ), msg, BROWN, 8 );
821 
822  if( m_convert > 1 )
823  msg = _( "Convert" );
824  else
825  msg = _( "Normal" );
826 
827  AppendMsgPanel( _( "Body" ), msg, GREEN, 8 );
828 
829  if( part->IsPower() )
830  msg = _( "Power Symbol" );
831  else
832  msg = _( "Symbol" );
833 
834  AppendMsgPanel( _( "Type" ), msg, MAGENTA, 8 );
835  AppendMsgPanel( _( "Description" ), alias->GetDescription(), CYAN, 8 );
836  AppendMsgPanel( _( "Key words" ), alias->GetKeyWords(), DARKDARKGRAY );
837  AppendMsgPanel( _( "Datasheet" ), alias->GetDocFileName(), DARKDARKGRAY );
838 }
Definition: colors.h:57
LIB_PART * GetCurPart() const
Return the current part being edited or NULL if none selected.
void OnSaveAll(wxCommandEvent &aEvent)
Saves all modified parts and libraries.
Definition: libedit.cpp:269
LIB_FIELD * GetField(int aId)
Return pointer to the requested field.
const wxRealPoint & GetGridSize() const
Return the grid size of the currently selected grid.
Definition: base_screen.h:410
static void synchronizeLibEditScreenSettings(const SCH_SCREEN &aCurrentScreen, SCH_SCREEN &aIncomingScreen)
Synchronise screen settings from a current screen into another screen.
Definition: libedit.cpp:164
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Function HandleUnsavedChanges displays a dialog with Save, Cancel and Discard Changes buttons.
Definition: confirm.cpp:211
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDc, const wxPoint &aOffset, int aMulti, int aConvert, const PART_DRAW_OPTIONS &aOpts)
Draw part.
Part library alias object definition.
virtual void Zoom_Automatique(bool aWarpPointer) override
Redraw the screen with best zoom level and the best centering that shows all the page or the board.
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
std::unique_ptr< LIB_PART > m_copiedPart
bool ConfirmRevertDialog(wxWindow *parent, const wxString &aMessage)
Function ConfirmRevertDialog displays a confirmation for a revert action.
Definition: confirm.cpp:198
void SetConversion(bool aSetConvert)
Set or clear the alternate body style (DeMorgan) for the part.
void SetPower()
wxString GetTextSelection(int aColumn=0)
Function GetTextSelection return the selected text from aColumn in the wxListCtrl in the dialog.
Definition: displlst.cpp:156
bool LoadComponentFromCurrentLib(const wxString &aAliasName, int aUnit=0, int aConvert=0)
Loads a symbol from the current active library, optionally setting the selected unit and convert.
Definition: libedit.cpp:119
Class PROJECT holds project specific data.
Definition: project.h:57
int GetPinNameOffset()
static int m_convert
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Function DisplayErrorMessage displays an error message with aMessage.
Definition: confirm.cpp:257
This file is part of the common library TODO brief description.
LIB_ALIAS * GetAlias(size_t aIndex)
wxString SelectLibraryFromList()
Dispaly a list of loaded libraries in the symbol library and allows the user to select a library.
Definition: selpart.cpp:76
void OnCreateNewPart(wxCommandEvent &aEvent)
Creates a new part in the selected library.
Definition: libedit.cpp:277
This file is part of the common library.
bool RemovePart(const wxString &aName, const wxString &aLibrary)
Removes the part from the part buffer.
void SetOKLabel(const wxString &aLabel)
Definition: displlst.cpp:126
void savePartAs()
Definition: libedit.cpp:402
bool m_syncPinEdit
Set to true to not synchronize pins at the same position when editing symbols with multiple units or ...
Definition: colors.h:61
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:935
Field object used in symbol libraries.
Definition: lib_field.h:59
LIB_MANAGER * m_libMgr
manager taking care of temporary modificatoins
void SelectActiveLibrary(const wxString &aLibrary=wxEmptyString)
Set the current active library to aLibrary.
Definition: libedit.cpp:70
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
wxString SchematicLibraryFileWildcard()
virtual void EndMouseCapture(int aId=-1, int aCursorId=-1, const wxString &aTitle=wxEmptyString, bool aCallEndFunc=true)
Function EndMouseCapture ends mouse a capture.
class EDA_LIST_DIALOG
Class SEARCH_STACK looks for files in a number of places.
Definition: search_stack.h:41
bool isCurrentPart(const LIB_ID &aLibId) const
Returns true if aLibId is an alias for the editor screen part.
bool IsWritable(const wxFileName &aFileName)
Function IsWritable checks if aFileName can be written.
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
void fixDuplicateAliases(LIB_PART *aPart, const wxString &aLibrary)
Renames LIB_PART aliases to avoid conflicts before adding a component to a library
Definition: libedit.cpp:565
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:116
Field Reference of part, i.e. "IC21".
const wxString & GetDocFileName() const
wxString GetCurLib() const
The nickname of the current library being edited and empty string if none.
void SetShowDeMorgan(bool show)
This file contains miscellaneous commonly used macros and functions.
void OnSave(wxCommandEvent &aEvent)
Saves the selected part or library.
Definition: libedit.cpp:364
void SetName(const wxString &aName)
Subclass of DIALOG_LIB_NEW_COMPONENT, which is generated by wxFormBuilder.
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
bool saveLibrary(const wxString &aLibrary, bool aNewFile)
Saves the changes to the current library.
Definition: libedit.cpp:675
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
void SetText(const wxString &aText) override
Sets the field text to aText.
Definition: lib_field.cpp:518
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
void SetDrawItem(LIB_ITEM *drawItem)
LIB_ID RevertPart(const wxString &aAlias, const wxString &aLibrary)
Reverts unsaved changes for a particular part.
void SetUnitCount(int count)
Set the units per part count.
void OnPasteDuplicatePart(wxCommandEvent &aEvent)
Definition: libedit.cpp:536
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:143
const std::string SchematicLibraryFileExtension
bool IsPartModified(const wxString &aAlias, const wxString &aLibrary) const
Returns true if part has unsaved modifications.
const wxString GetDescription(const wxString &aNickname)
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
const wxString & GetKeyWords() const
SCH_SCREEN * GetScreen(const wxString &aAlias, const wxString &aLibrary)
Returns the screen used to edit a specific part.
LIB_ID GetSelectedLibId(int *aUnit=nullptr) const
For multi-unit components, if the user selects the component itself rather than picking an individual...
Definition: lib_tree.cpp:147
const LIB_ID & GetLibId() const
virtual void ClearUndoRedoList()
Function ClearUndoRedoList clear undo and redo list, using ClearUndoORRedoList() picked items are del...
Definition: colors.h:59
int UnsavedChangesDialog(wxWindow *parent, const wxString &aMessage, bool *aApplyToAll)
Function UnsavedChangesDialog a specialized version of HandleUnsavedChanges which handles an apply-to...
Definition: confirm.cpp:180
virtual void CallMouseCapture(wxDC *aDC, const wxPoint &aPosition, bool aErase)
Function CallMouseCapture calls the mouse capture callback.
void OnRemovePart(wxCommandEvent &aEvent)
Removes a part from the working copy of a library.
Definition: libedit.cpp:499
Define a library symbol object.
Definition of file extensions used in Kicad.
#define DOC_EXT
Definition: class_library.h:50
Helper dialog and control classes.
virtual void DrawCrossHair(wxDC *aDC=nullptr, COLOR4D aColor=COLOR4D::WHITE)
Function DrawCrossHair draws the user cross hair.
wxArrayString GetLibraryNames() const
Returns the array of library names.
Definition: lib_manager.cpp:84
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
bool LoadOneLibraryPartAux(LIB_ALIAS *aLibEntry, const wxString &aLibrary, int aUnit, int aConvert)
Create a copy of aLibEntry into memory.
Definition: libedit.cpp:171
wxString GetName(void) const override
static LIB_ITEM * m_lastDrawItem
bool FlushPart(const wxString &aAlias, const wxString &aLibrary)
Saves part changes to the library copy used by the schematic editor.
static PART_DRAW_OPTIONS Default()
bool PartExists(const wxString &aAlias, const wxString &aLibrary) const
Returns true if part with a specific alias exists in library (either original one or buffered).
bool ClearLibraryModified(const wxString &aLibrary) const
Clears the modified flag for all parts in a library.
bool LoadComponentAndSelectLib(const LIB_ID &aLibId, int aUnit, int aConvert)
Selects the currently active library and loads the symbol from aLibId.
Definition: libedit.cpp:103
bool SaveLibrary(const wxString &aLibrary, const wxString &aFileName)
Saves library to a file, including unsaved changes.
UTF8 Format() const
Definition: lib_id.cpp:237
void emptyScreen()
Restores the empty editor screen, without any part or library selected.
bool UpdatePart(LIB_PART *aPart, const wxString &aLibrary)
Updates the part buffer with a new version of the part.
void DisplayCmpDoc()
Display the documentation of the selected component.
Definition: libedit.cpp:803
void updateTitle()
Updates the main window title bar with the current library name and read only status of the library.
Definition: libedit.cpp:58
const wxString & GetDescription() override
void UpdateStatusBar() override
Update the status bar information.
void OnSaveAs(wxCommandEvent &aEvent)
Saves the selected part or library to a new name and/or location.
Definition: libedit.cpp:386
bool backupFile(const wxFileName &aOriginalFile, const wxString &aBackupExt)
Creates a backup copy of a file with requested extension
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:126
void AppendMsgPanel(const wxString &textUpper, const wxString &textLower, COLOR4D color, int pad=6)
Append a message to the message panel.
void SyncLibraries(bool aShowProgress)
Synchronize the library manager to the symbol library table, and then the symbol tree to the library ...
VTBL_ENTRY const wxString & GetRString(RSTRING_T aStringId)
Function GetRString returns a "retained string", which is any session and project specific string ide...
Definition: project.cpp:186
LIB_PART * GetBufferedPart(const wxString &aAlias, const wxString &aLibrary)
Returns the part copy from the buffer.
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
bool IsPower() const
Definition: colors.h:58
see class PGM_BASE
const wxString & GetName() const override
static int m_unit
bool saveCurrentPart()
Saves the current part.
Definition: libedit.cpp:84
const char * name
Definition: DXF_plotter.cpp:61
bool saveAllLibraries(bool aRequireConfirmation)
Definition: libedit.cpp:759
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
void OnRevert(wxCommandEvent &aEvent)
Reverts unsaved changes in a part, restoring to the last saved state.
Definition: libedit.cpp:592
void OnEditPart(wxCommandEvent &aEvent)
Opens the selected part for editing.
Definition: libedit.cpp:356
void OnCopyCutPart(wxCommandEvent &aEvent)
Definition: libedit.cpp:520
void SetCurPart(LIB_PART *aPart)
Take ownership of aPart and notes that it is the one currently being edited.
const wxString & GetName() const
void RedrawComponent(wxDC *aDC, wxPoint aOffset)
Redraw the current component loaded in library editor Display reference like in schematic (a referenc...
Definition: libedit.cpp:219
bool LibraryExists(const wxString &aLibrary, bool aCheckEnabled=false) const
Returns true if library exists.
const wxString LastVisitedPath(const wxString &aSubPathToSearch=wxEmptyString)
Function LastVisitedPath is a quirky function inherited from old code that seems to serve particular ...
virtual void SetScreen(BASE_SCREEN *aScreen) override
size_t i
Definition: json11.cpp:597
wxString GetFullText(int unit=1) const
Return the text of a field.
Definition: lib_field.cpp:371
LIB_ID getTargetLibId() const
Returns either the part selected in the component tree, if context menu is active or the currently mo...
bool IsLibraryModified(const wxString &aLibrary) const
Returns true if library has unsaved modifications.
virtual void SetName(const wxString &aName)
Definition of class LIB_EDIT_FRAME.
Implementing DIALOG_LIB_NEW_COMPONENT.
wxString SetCurLib(const wxString &aLibNickname)
Sets the current library nickname and returns the old library nickname.
virtual void DrawBackGround(wxDC *DC)
Function DrawBackGround.
size_t GetAliasCount() const
Definition for part library class.
int SetGrid(const wxRealPoint &size)
set the current grid size m_Grid.
LIB_TREE * GetLibTree() const
SYMBOL_TREE_PANE * m_treePane
component search tree widget
bool m_drawSpecificUnit
Specify which component parts the current draw item applies to.
void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
void SetPinNameOffset(int aOffset)
Set the offset in mils of the pin name text from the pin symbol.
void RedrawActiveWindow(wxDC *DC, bool EraseBg) override
Redraw the current component loaded in library editor, an axes Display reference like in schematic (a...
Definition: libedit.cpp:241
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:243
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:293
void UpdatePartSelectList()
void ClearMsgPanel(void)
Clear all messages from the message panel.
bool UnitsLocked() const
Check whether part units are interchangeable.
const wxString GetUniStringLibItemName() const
Definition: lib_id.h:121
bool GetShowElectricalType()
void loadPart(const wxString &aLibrary, const wxString &aPart, int Unit)
Definition: libedit.cpp:648
wxString getTargetLib() const
Returns either the library selected in the component tree, if context menu is active or the library t...
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
void LockUnits(bool aLockUnits)
Set interchangeable the property for part units.
bool ClearPartModified(const wxString &aAlias, const wxString &aLibrary) const
Clears the modified flag for a part.
void SelectLibId(const LIB_ID &aLibId)
Select an item in the tree widget.
Definition: lib_tree.cpp:165
bool RevertLibrary(const wxString &aLibrary)
Reverts unsaved changes for a particular library.
void SetNormal()
void SetListLabel(const wxString &aLabel)
Definition: displlst.cpp:120
Definition: colors.h:62