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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 2004-2017 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 
154 
155 bool LIB_EDIT_FRAME::LoadOneLibraryPartAux( LIB_ALIAS* aEntry, const wxString& aLibrary,
156  int aUnit, int aConvert )
157 {
158  wxString msg, rootName;
159 
160  if( !aEntry || aLibrary.empty() )
161  return false;
162 
163  if( aEntry->GetName().IsEmpty() )
164  {
165  wxLogWarning( "Symbol in library \"%s\" has empty name field.", aLibrary );
166  return false;
167  }
168 
169  LIB_PART* lib_part = m_libMgr->GetBufferedPart( aEntry->GetName(), aLibrary );
170  wxASSERT( lib_part );
171 
172  m_unit = aUnit > 0 ? aUnit : 1;
173  m_convert = aConvert > 0 ? aConvert : 1;
174 
175  auto s = m_libMgr->GetScreen( lib_part->GetName(), aLibrary );
176  SetScreen( s );
177  SetCurPart( new LIB_PART( *lib_part ) );
178  SetCurLib( aLibrary );
179 
180  Zoom_Automatique( false );
181  updateTitle();
183 
184  // Display the document information based on the entry selected just in
185  // case the entry is an alias.
186  DisplayCmpDoc();
187  Refresh();
188 
189  return true;
190 }
191 
192 
193 void LIB_EDIT_FRAME::RedrawComponent( wxDC* aDC, wxPoint aOffset )
194 {
195  LIB_PART* part = GetCurPart();
196 
197  if( part )
198  {
199  // display reference like in schematic (a reference U is shown U? or U?A)
200  // although it is stored without ? and part id.
201  // So temporary change the reference by a schematic like reference
202  LIB_FIELD* field = part->GetField( REFERENCE );
203  wxString fieldText = field->GetText();
204  wxString fieldfullText = field->GetFullText( m_unit );
205 
206  field->EDA_TEXT::SetText( fieldfullText ); // change the field text string only
207  auto opts = PART_DRAW_OPTIONS::Default();
208  opts.show_elec_type = GetShowElectricalType();
209  part->Draw( m_canvas, aDC, aOffset, m_unit, m_convert, opts );
210  field->EDA_TEXT::SetText( fieldText ); // restore the field text string
211  }
212 }
213 
214 
215 void LIB_EDIT_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg )
216 {
217  if( GetScreen() == NULL )
218  return;
219 
220  m_canvas->DrawBackGround( DC );
221 
222  RedrawComponent( DC, wxPoint( 0, 0 ) );
223 
224 #ifdef USE_WX_OVERLAY
225  if( IsShown() )
226  {
227  m_overlay.Reset();
228  wxDCOverlay overlaydc( m_overlay, (wxWindowDC*)DC );
229  overlaydc.Clear();
230  }
231 #endif
232 
233  if( m_canvas->IsMouseCaptured() )
234  m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
235 
236  m_canvas->DrawCrossHair( DC );
237 
238  updateTitle();
239  UpdateStatusBar();
240 }
241 
242 
243 void LIB_EDIT_FRAME::OnSaveAll( wxCommandEvent& event )
244 {
245  saveAllLibraries( false );
246  m_treePane->Refresh();
248 }
249 
250 
251 void LIB_EDIT_FRAME::OnCreateNewPart( wxCommandEvent& event )
252 {
253  m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, GetGalCanvas()->GetDefaultCursor() );
254  SetDrawItem( NULL );
255  wxString lib = getTargetLib();
256 
257  if( !m_libMgr->LibraryExists( lib ) )
258  {
259  lib = SelectLibraryFromList();
260 
261  if( !m_libMgr->LibraryExists( lib ) )
262  return;
263  }
264 
265  DIALOG_LIB_NEW_COMPONENT dlg( this );
266  dlg.SetMinSize( dlg.GetSize() );
267 
268  if( dlg.ShowModal() == wxID_CANCEL )
269  return;
270 
271  if( dlg.GetName().IsEmpty() )
272  {
273  wxMessageBox( _( "This new symbol has no name and cannot be created." ) );
274  return;
275  }
276 
277  wxString name = dlg.GetName();
278  // Currently, symbol names cannot include a space, that breaks libraries:
279  name.Replace( " ", "_" );
280 
281  // Test if there is a component with this name already.
282  if( !lib.empty() && m_libMgr->PartExists( name, lib ) )
283  {
284  wxString msg = wxString::Format( _( "Symbol \"%s\" already exists in library \"%s\"" ),
285  name, lib );
286  DisplayError( this, msg );
287  return;
288  }
289 
290  LIB_PART new_part( name ); // do not create part on the heap, it will be buffered soon
291  new_part.GetReferenceField().SetText( dlg.GetReference() );
292  new_part.SetUnitCount( dlg.GetUnitCount() );
293 
294  // Initialize new_part.m_TextInside member:
295  // if 0, pin text is outside the body (on the pin)
296  // if > 0, pin text is inside the body
297 
298  if( dlg.GetPinNameInside() )
299  {
300  new_part.SetPinNameOffset( dlg.GetPinTextPosition() );
301 
302  if( new_part.GetPinNameOffset() == 0 )
303  new_part.SetPinNameOffset( 1 );
304  }
305  else
306  {
307  new_part.SetPinNameOffset( 0 );
308  }
309 
310  ( dlg.GetPowerSymbol() ) ? new_part.SetPower() : new_part.SetNormal();
311  new_part.SetShowPinNumbers( dlg.GetShowPinNumber() );
312  new_part.SetShowPinNames( dlg.GetShowPinName() );
313  new_part.LockUnits( dlg.GetLockItems() );
314 
315  if( dlg.GetUnitCount() < 2 )
316  new_part.LockUnits( false );
317 
318  m_libMgr->UpdatePart( &new_part, lib );
319  SyncLibraries( false );
320  loadPart( name, lib, 1 );
321 
322  new_part.SetConversion( dlg.GetAlternateBodyStyle() );
323  // must be called after loadPart, that calls SetShowDeMorgan, but
324  // because the symbol is empty,it looks like it has no alternate body
326 
327 }
328 
329 
330 void LIB_EDIT_FRAME::OnEditPart( wxCommandEvent& aEvent )
331 {
332  int unit = 0;
333  LIB_ID partId = m_treePane->GetLibTree()->GetSelectedLibId( &unit );
334  loadPart( partId.GetLibItemName(), partId.GetLibNickname(), unit );
335 }
336 
337 
338 void LIB_EDIT_FRAME::OnSave( wxCommandEvent& aEvent )
339 {
340  LIB_ID libId = getTargetLibId();
341  const wxString& libName = libId.GetLibNickname();
342  const wxString& partName = libId.GetLibItemName();
343 
344  if( partName.IsEmpty() )
345  {
346  saveLibrary( libName, false );
347  }
348  else
349  {
350  // Save Part
351  if( m_libMgr->FlushPart( partName, libName ) )
352  m_libMgr->ClearPartModified( partName, libName );
353  }
354 
355  m_treePane->Refresh();
357 }
358 
359 
360 void LIB_EDIT_FRAME::OnSaveAs( wxCommandEvent& aEvent )
361 {
362  LIB_ID libId = getTargetLibId();
363  const wxString& libName = libId.GetLibNickname();
364  const wxString& partName = libId.GetLibItemName();
365 
366  if( partName.IsEmpty() )
367  saveLibrary( libName, true );
368  else
369  savePartAs();
370 
371  m_treePane->Refresh();
373 }
374 
375 
377 {
378  LIB_ID old_lib_id = getTargetLibId();
379  wxString old_name = old_lib_id.GetLibItemName();
380  wxString old_lib = old_lib_id.GetLibNickname();
381  LIB_PART* part = m_libMgr->GetBufferedPart( old_name, old_lib );
382 
383  if( part )
384  {
385  SYMBOL_LIB_TABLE* tbl = Prj().SchSymbolLibTable();
386  wxArrayString headers;
387  std::vector< wxArrayString > itemsToDisplay;
388  std::vector< wxString > libNicknames = tbl->GetLogicalLibs();
389 
390  headers.Add( _( "Nickname" ) );
391  headers.Add( _( "Description" ) );
392 
393  for( const auto& name : libNicknames )
394  {
395  wxArrayString item;
396  item.Add( name );
397  item.Add( tbl->GetDescription( name ) );
398  itemsToDisplay.push_back( item );
399  }
400 
401  EDA_LIST_DIALOG dlg( this, _( "Save Copy of Symbol" ), headers, itemsToDisplay, old_lib,
402  nullptr, nullptr, /* sort */ false, /* show headers */ false );
403  dlg.SetListLabel( _( "Save in library:" ) );
404  dlg.SetOKLabel( _( "Save" ) );
405 
406  wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
407 
408  wxStaticText* label = new wxStaticText( &dlg, wxID_ANY, _( "Name:" ),
409  wxDefaultPosition, wxDefaultSize, 0 );
410  bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
411 
412  wxTextCtrl* nameTextCtrl = new wxTextCtrl( &dlg, wxID_ANY, old_name,
413  wxDefaultPosition, wxDefaultSize, 0 );
414  bNameSizer->Add( nameTextCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
415 
416  wxSizer* mainSizer = dlg.GetSizer();
417  mainSizer->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
418 
419  // Move nameTextCtrl to the head of the tab-order
420  if( dlg.GetChildren().DeleteObject( nameTextCtrl ) )
421  dlg.GetChildren().Insert( nameTextCtrl );
422 
423  dlg.SetInitialFocus( nameTextCtrl );
424 
425  dlg.Layout();
426  mainSizer->Fit( &dlg );
427 
428  if( dlg.ShowModal() != wxID_OK )
429  return; // canceled by user
430 
431  wxString new_lib = dlg.GetTextSelection();
432 
433  if( new_lib.IsEmpty() )
434  {
435  DisplayError( NULL, _( "No library specified. Symbol could not be saved." ) );
436  return;
437  }
438 
439  wxString new_name = nameTextCtrl->GetValue();
440  new_name.Trim( true );
441  new_name.Trim( false );
442  new_name.Replace( " ", "_" );
443 
444  if( new_name.IsEmpty() )
445  {
446  DisplayError( NULL, _( "No symbol name specified. Symbol could not be saved." ) );
447  return;
448  }
449 
450  // Test if there is a component with this name already.
451  if( m_libMgr->PartExists( new_name, new_lib ) )
452  {
453  wxString msg = wxString::Format( _( "Symbol \"%s\" already exists in library \"%s\"" ),
454  new_name, new_lib );
455  DisplayError( this, msg );
456  return;
457  }
458 
459  LIB_PART new_part( *part );
460  new_part.SetName( new_name );
461 
462  fixDuplicateAliases( &new_part, new_lib );
463  m_libMgr->UpdatePart( &new_part, new_lib );
464  SyncLibraries( false );
465  m_treePane->GetLibTree()->SelectLibId( LIB_ID( new_lib, new_part.GetName() ) );
466 
467  if( isCurrentPart( old_lib_id ) )
468  loadPart( new_name, new_lib, m_unit );
469  }
470 }
471 
472 
473 void LIB_EDIT_FRAME::OnRemovePart( wxCommandEvent& aEvent )
474 {
475  LIB_ID libId = getTargetLibId();
476 
477  if( m_libMgr->IsPartModified( libId.GetLibItemName(), libId.GetLibNickname() )
478  && !IsOK( this, _( wxString::Format( "Component %s has been modified\n"
479  "Do you want to remove it from the library?",
480  libId.GetUniStringLibItemName() ) ) ) )
481  {
482  return;
483  }
484 
485  if( isCurrentPart( libId ) )
486  emptyScreen();
487 
488  m_libMgr->RemovePart( libId.GetLibItemName(), libId.GetLibNickname() );
489 
491 }
492 
493 
494 void LIB_EDIT_FRAME::OnCopyCutPart( wxCommandEvent& aEvent )
495 {
496  int dummyUnit;
497  LIB_ID libId = m_treePane->GetLibTree()->GetSelectedLibId( &dummyUnit );
498  LIB_PART* part = m_libMgr->GetBufferedPart( libId.GetLibItemName(), libId.GetLibNickname() );
499 
500  if( !part )
501  return;
502 
503  m_copiedPart.reset( new LIB_PART( *part ) );
504 
505  if( aEvent.GetId() == ID_LIBEDIT_CUT_PART )
506  OnRemovePart( aEvent );
507 }
508 
509 
510 void LIB_EDIT_FRAME::OnPasteDuplicatePart( wxCommandEvent& aEvent )
511 {
512  int dummyUnit;
513  LIB_ID libId = m_treePane->GetLibTree()->GetSelectedLibId( &dummyUnit );
514  wxString lib = libId.GetLibNickname();
515 
516  if( !m_libMgr->LibraryExists( lib ) )
517  return;
518 
519  LIB_PART* srcPart = nullptr;
520 
521  if( aEvent.GetId() == ID_LIBEDIT_DUPLICATE_PART )
522  srcPart = m_libMgr->GetBufferedPart( libId.GetLibItemName(), lib );
523  else if( aEvent.GetId() == ID_LIBEDIT_PASTE_PART )
524  srcPart = m_copiedPart.get();
525  else
526  wxFAIL;
527 
528  if( !srcPart )
529  return;
530 
531  LIB_PART newPart( *srcPart );
532  fixDuplicateAliases( &newPart, lib );
533  m_libMgr->UpdatePart( &newPart, lib );
534  SyncLibraries( false );
535  m_treePane->GetLibTree()->SelectLibId( LIB_ID( lib, newPart.GetName() ) );
536 }
537 
538 
539 void LIB_EDIT_FRAME::fixDuplicateAliases( LIB_PART* aPart, const wxString& aLibrary )
540 {
541  wxString newName;
542 
543  for( unsigned int i = 0; i < aPart->GetAliasCount(); ++i )
544  {
545  LIB_ALIAS* alias = aPart->GetAlias( i );
546  int sfx = 0;
547  newName = alias->GetName();
548 
549  while( m_libMgr->PartExists( newName, aLibrary ) )
550  {
551  if( sfx == 0 )
552  newName = wxString::Format( "%s_copy", alias->GetName() );
553  else
554  newName = wxString::Format( "%s_copy%d", alias->GetName(), sfx );
555  ++sfx;
556  }
557 
558  if( i == 0 )
559  aPart->SetName( newName );
560  else
561  alias->SetName( newName );
562  }
563 }
564 
565 
566 void LIB_EDIT_FRAME::OnRevert( wxCommandEvent& aEvent )
567 {
568  LIB_ID libId = getTargetLibId();
569  const wxString& libName = libId.GetLibNickname();
570  const wxString& partName = libId.GetLibItemName(); // Empty if this is the library itself that is selected
571 
572  wxString msg = wxString::Format( _( "Revert \"%s\" to last version saved?" ),
573  partName.IsEmpty() ? libName : partName );
574 
575  if( !ConfirmRevertDialog( this, msg ) )
576  return;
577 
578  bool reload_currentPart = false;
579  wxString curr_partName = partName;
580 
581  if( GetCurPart() )
582  {
583  // the library itself is reverted: the current part will be reloaded only if it is
584  // owned by this library
585  if( partName.IsEmpty() )
586  {
587  LIB_ID curr_libId = GetCurPart()->GetLibId();
588  reload_currentPart = libName == curr_libId.GetLibNickname();
589 
590  if( reload_currentPart )
591  curr_partName = curr_libId.GetLibItemName();
592  }
593  else
594  reload_currentPart = isCurrentPart( libId );
595  }
596 
597  int unit = m_unit;
598 
599  if( reload_currentPart )
600  emptyScreen();
601 
602  if( partName.IsEmpty() )
603  {
604  m_libMgr->RevertLibrary( libName );
605  }
606  else
607  {
608  libId = m_libMgr->RevertPart( libId.GetLibItemName(), libId.GetLibNickname() );
609 
610  m_treePane->GetLibTree()->SelectLibId( libId );
612  }
613 
614  if( reload_currentPart && m_libMgr->PartExists( curr_partName, libName ) )
615  loadPart( curr_partName, libName, unit );
616 
617  m_treePane->Refresh();
619 }
620 
621 
622 void LIB_EDIT_FRAME::loadPart( const wxString& aAlias, const wxString& aLibrary, int aUnit )
623 {
624  wxCHECK( m_libMgr->PartExists( aAlias, aLibrary ), /* void */ );
625  LIB_PART* part = m_libMgr->GetBufferedPart( aAlias, aLibrary );
626  LIB_ALIAS* alias = part ? part->GetAlias( aAlias ) : nullptr;
627 
628  if( !alias )
629  {
630  wxString msg = wxString::Format( _( "Symbol name \"%s\" not found in library \"%s\"" ),
631  GetChars( aAlias ),
632  GetChars( aLibrary ) );
633  DisplayError( this, msg );
634  return;
635  }
636 
637  m_lastDrawItem = nullptr;
638  SetDrawItem( NULL );
639 
640  // Optimize default edit options for this symbol
641  // Usually if units are locked, graphic items are specific to each unit
642  // and if units are interchangeable, graphic items are common to units
643  m_drawSpecificUnit = part->UnitsLocked() ? true : false;
644 
645  LoadOneLibraryPartAux( alias, aLibrary, m_unit, 0 );
646 }
647 
648 
649 bool LIB_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
650 {
651  wxFileName fn;
652  wxString msg;
653  PROJECT& prj = Prj();
654 
655  m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, GetGalCanvas()->GetDefaultCursor() );
656 
657  if( !aNewFile && ( aLibrary.empty() || !prj.SchSymbolLibTable()->HasLibrary( aLibrary ) ) )
658  {
659  DisplayError( this, _( "No library specified." ) );
660  return false;
661  }
662 
663  if( aNewFile )
664  {
665  SEARCH_STACK* search = prj.SchSearchS();
666 
667  // Get a new name for the library
668  wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH );
669 
670  if( !default_path )
671  default_path = search->LastVisitedPath();
672 
673  fn.SetName( aLibrary );
674  fn.SetExt( SchematicLibraryFileExtension );
675 
676  wxFileDialog dlg( this, wxString::Format( _( "Save Library \"%s\" As..." ), aLibrary ),
677  default_path, fn.GetFullName(), SchematicLibraryFileWildcard(),
678  wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
679 
680  if( dlg.ShowModal() == wxID_CANCEL )
681  return false;
682 
683  fn = dlg.GetPath();
684 
685  // The GTK file chooser doesn't return the file extension added to
686  // file name so add it here.
687  if( fn.GetExt().IsEmpty() )
688  fn.SetExt( SchematicLibraryFileExtension );
689  }
690  else
691  {
692  fn = prj.SchSymbolLibTable()->GetFullURI( aLibrary );
693  }
694 
695  // Verify the user has write privileges before attempting to save the library file.
696  if( !IsWritable( fn ) )
697  return false;
698 
699  ClearMsgPanel();
700 
701  // Copy .lib file to .bak.
702  if( !backupFile( fn, "bak" ) )
703  return false;
704 
705  wxFileName docFileName = fn;
706  docFileName.SetExt( DOC_EXT );
707 
708  // Copy .dcm file to .bck.
709  if( !backupFile( docFileName, "bck" ) )
710  return false;
711 
712  if( !m_libMgr->SaveLibrary( aLibrary, fn.GetFullPath() ) )
713  {
714  msg.Printf( _( "Failed to save changes to symbol library file \"%s\"" ),
715  fn.GetFullPath() );
716  DisplayErrorMessage( this, _( "Error saving library" ), msg );
717  return false;
718  }
719 
720  if( !aNewFile )
721  m_libMgr->ClearLibraryModified( aLibrary );
722 
723  msg.Printf( _( "Symbol library file \"%s\" saved" ), fn.GetFullPath() );
724  wxString msg1;
725  msg1.Printf( _( "Symbol library documentation file \"%s\" saved" ), docFileName.GetFullPath() );
726  AppendMsgPanel( msg, msg1, BLUE );
728 
729  return true;
730 }
731 
732 
733 bool LIB_EDIT_FRAME::saveAllLibraries( bool aRequireConfirmation )
734 {
735  bool doSave = true;
736  int dirtyCount = 0;
737  bool applyToAll = false;
738 
739  for( const auto& libNickname : m_libMgr->GetLibraryNames() )
740  {
741  if( m_libMgr->IsLibraryModified( libNickname ) )
742  dirtyCount++;
743  }
744 
745  for( const auto& libNickname : m_libMgr->GetLibraryNames() )
746  {
747  if( m_libMgr->IsLibraryModified( libNickname ) )
748  {
749  if( aRequireConfirmation && !applyToAll )
750  {
751  wxString msg = wxString::Format( _( "Save changes to \"%s\" before closing?" ),
752  libNickname );
753 
754  switch( UnsavedChangesDialog( this, msg, dirtyCount > 1 ? &applyToAll : nullptr ) )
755  {
756  case wxID_YES: doSave = true; break;
757  case wxID_NO: doSave = false; break;
758  default:
759  case wxID_CANCEL: return false;
760  }
761  }
762 
763  if( doSave )
764  {
765  // If saving under existing name fails then do a Save As..., and if that
766  // fails then cancel close action.
767  if( !saveLibrary( libNickname, false ) && !saveLibrary( libNickname, true ) )
768  return false;
769  }
770  }
771  }
772 
773  return true;
774 }
775 
776 
778 {
779  LIB_PART* part = GetCurPart();
780 
781  ClearMsgPanel();
782 
783  if( !part )
784  return;
785 
786  LIB_ALIAS* alias = part->GetAlias( part->GetName() );
787  wxString msg = part->GetName();
788 
789  AppendMsgPanel( _( "Name" ), msg, BLUE, 8 );
790 
791  static wxChar UnitLetter[] = wxT( "?ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
792  msg = UnitLetter[m_unit];
793 
794  AppendMsgPanel( _( "Unit" ), msg, BROWN, 8 );
795 
796  if( m_convert > 1 )
797  msg = _( "Convert" );
798  else
799  msg = _( "Normal" );
800 
801  AppendMsgPanel( _( "Body" ), msg, GREEN, 8 );
802 
803  if( part->IsPower() )
804  msg = _( "Power Symbol" );
805  else
806  msg = _( "Symbol" );
807 
808  AppendMsgPanel( _( "Type" ), msg, MAGENTA, 8 );
809  AppendMsgPanel( _( "Description" ), alias->GetDescription(), CYAN, 8 );
810  AppendMsgPanel( _( "Key words" ), alias->GetKeyWords(), DARKDARKGRAY );
811  AppendMsgPanel( _( "Datasheet" ), alias->GetDocFileName(), DARKDARKGRAY );
812 }
Definition: colors.h:57
void OnSaveAll(wxCommandEvent &aEvent)
Saves all modified parts and libraries.
Definition: libedit.cpp:243
bool UnitsLocked() const
Check whether part units are interchangeable.
LIB_FIELD * GetField(int aId)
Return pointer to the requested field.
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:213
const wxString GetUniStringLibItemName() const
Definition: lib_id.h:121
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...
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:200
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:259
This file is part of the common library TODO brief description.
bool IsPower() const
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:251
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:376
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
bool isCurrentPart(const LIB_ID &aLibId) const
Returns true if aLibId is an alias for the editor screen part.
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.
bool ClearLibraryModified(const wxString &aLibrary) const
Clears the modified flag for all parts in a library.
wxString SchematicLibraryFileWildcard()
virtual void EndMouseCapture(int aId=-1, int aCursorId=-1, const wxString &aTitle=wxEmptyString, bool aCallEndFunc=true)
Function EndMouseCapture ends mouse a capture.
const LIB_ID & GetLibId() const
LIB_ID getTargetLibId() const
Returns either the part selected in the component tree, if context menu is active or the currently mo...
class EDA_LIST_DIALOG
Class SEARCH_STACK looks for files in a number of places.
Definition: search_stack.h:41
wxString GetFullText(int unit=1) const
Return the text of a field.
Definition: lib_field.cpp:371
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
size_t GetAliasCount() const
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:539
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:115
Field Reference of part, i.e. "IC21".
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:338
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
void SetName(const wxString &aName)
Subclass of DIALOG_LIB_NEW_COMPONENT, which is generated by wxFormBuilder.
LIB_PART * GetCurPart() const
Return the current part being edited or NULL if none selected.
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:649
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.
const wxString & GetKeyWords() const
void SetUnitCount(int count)
Set the units per part count.
void OnPasteDuplicatePart(wxCommandEvent &aEvent)
Definition: libedit.cpp:510
const std::string SchematicLibraryFileExtension
const wxString GetDescription(const wxString &aNickname)
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
bool ClearPartModified(const wxString &aAlias, const wxString &aLibrary) const
Clears the modified flag for a 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:144
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:143
SCH_SCREEN * GetScreen(const wxString &aAlias, const wxString &aLibrary)
Returns the screen used to edit a specific part.
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:182
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:473
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.
bool IsLibraryModified(const wxString &aLibrary) const
Returns true if library has unsaved modifications.
wxString GetCurLib() const
The nickname of the current library being edited and empty string if none.
bool LoadOneLibraryPartAux(LIB_ALIAS *aLibEntry, const wxString &aLibrary, int aUnit, int aConvert)
Create a copy of aLibEntry into memory.
Definition: libedit.cpp:155
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 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.
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:777
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.
const wxString & GetDocFileName() const
void OnSaveAs(wxCommandEvent &aEvent)
Saves the selected part or library to a new name and/or location.
Definition: libedit.cpp:360
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:123
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 ...
wxString getTargetLib() const
Returns either the library selected in the component tree, if context menu is active or the library t...
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.
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
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)...
wxArrayString GetLibraryNames() const
Returns the array of library names.
Definition: lib_manager.cpp:84
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
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:733
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:566
void OnEditPart(wxCommandEvent &aEvent)
Opens the selected part for editing.
Definition: libedit.cpp:330
void OnCopyCutPart(wxCommandEvent &aEvent)
Definition: libedit.cpp:494
void SetCurPart(LIB_PART *aPart)
Take ownership of aPart and notes that it is the one currently being edited.
void RedrawComponent(wxDC *aDC, wxPoint aOffset)
Redraw the current component loaded in library editor Display reference like in schematic (a referenc...
Definition: libedit.cpp:193
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
LIB_TREE * GetLibTree() const
bool LibraryExists(const wxString &aLibrary, bool aCheckEnabled=false) const
Returns true if library exists.
UTF8 Format() const
Definition: lib_id.cpp:237
const wxString & GetName() const
virtual void SetName(const wxString &aName)
Definition of class LIB_EDIT_FRAME.
bool IsPartModified(const wxString &aAlias, const wxString &aLibrary) const
Returns true if part has unsaved modifications.
Implementing DIALOG_LIB_NEW_COMPONENT.
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:925
wxString SetCurLib(const wxString &aLibNickname)
Sets the current library nickname and returns the old library nickname.
virtual void DrawBackGround(wxDC *DC)
Function DrawBackGround.
Definition for part library class.
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
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:215
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:245
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:295
void UpdatePartSelectList()
void ClearMsgPanel(void)
Clear all messages from the message panel.
bool GetShowElectricalType()
void loadPart(const wxString &aLibrary, const wxString &aPart, int Unit)
Definition: libedit.cpp:622
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.
void SelectLibId(const LIB_ID &aLibId)
Select an item in the tree widget.
Definition: lib_tree.cpp:162
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