KiCad PCB EDA Suite
footprint_libraries_utils.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) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <wx/ffile.h>
25 #include <pgm_base.h>
26 #include <kiface_base.h>
27 #include <confirm.h>
28 #include <string_utils.h>
29 #include <macros.h>
30 #include <pcb_edit_frame.h>
31 #include <eda_list_dialog.h>
32 #include <filter_reader.h>
33 #include <fp_lib_table.h>
34 #include <validators.h>
36 #include <tool/tool_manager.h>
37 #include <tools/pcb_actions.h>
39 #include <board.h>
40 #include <footprint.h>
41 #include <board_commit.h>
42 #include <footprint_edit_frame.h>
46 #include <env_paths.h>
47 #include <paths.h>
50 #include "footprint_viewer_frame.h"
51 #include <wx/choicdlg.h>
52 #include <wx/filedlg.h>
53 
54 
55 // unique, "file local" translations:
56 
57 
58 static const wxString INFO_LEGACY_LIB_WARN_EDIT(
59  _( "Writing/modifying legacy libraries (.mod files) is not allowed\n"\
60  "Please save the current library to the new .pretty format\n"\
61  "and update your footprint lib table\n"\
62  "to save your footprint (a .kicad_mod file) in the .pretty library folder" ) );
63 
64 static const wxString INFO_LEGACY_LIB_WARN_DELETE(
65  _( "Modifying legacy libraries (.mod files) is not allowed\n"\
66  "Please save the current library under the new .pretty format\n"\
67  "and update your footprint lib table\n"\
68  "before deleting a footprint" ) );
69 
70 
76 static wxFileName getFootprintFilenameFromUser( wxWindow* aParent, const wxString& aLastPath )
77 {
78  static int lastFilterIndex = 0; // To store the last choice during a session.
79  wxString wildCard;
80 
81  wildCard << KiCadFootprintLibFileWildcard() << wxChar( '|' )
82  << ModLegacyExportFileWildcard() << wxChar( '|' )
83  << GedaPcbFootprintLibFileWildcard() << wxChar( '|' )
84  << AllFilesWildcard();
85 
86  wxFileDialog dlg( aParent, _( "Import Footprint" ), aLastPath, wxEmptyString, wildCard,
87  wxFD_OPEN | wxFD_FILE_MUST_EXIST );
88 
89  dlg.SetFilterIndex( lastFilterIndex );
90 
91  if( dlg.ShowModal() == wxID_CANCEL )
92  return wxFileName();
93 
94  lastFilterIndex = dlg.GetFilterIndex();
95 
96  return wxFileName( dlg.GetPath() );
97 }
98 
99 
106 static IO_MGR::PCB_FILE_T detect_file_type( FILE* aFile, const wxFileName& aFileName,
107  wxString* aName )
108 {
109  FILE_LINE_READER freader( aFile, aFileName.GetFullPath() );
110  WHITESPACE_FILTER_READER reader( freader );
111  IO_MGR::PCB_FILE_T file_type;
112 
113  wxASSERT( aName );
114 
115  reader.ReadLine();
116  char* line = reader.Line();
117 
118  if( !line )
119  {
120  return IO_MGR::FILE_TYPE_NONE;
121  }
122 
123  // first .kicad_mod file versions starts by "(module"
124  // recent .kicad_mod file versions starts by "(footprint"
125  if( strncasecmp( line, "(module", strlen( "(module" ) ) == 0
126  || strncasecmp( line, "(footprint", strlen( "(footprint" ) ) == 0 )
127  {
128  file_type = IO_MGR::KICAD_SEXP;
129  *aName = aFileName.GetName();
130  }
131  else if( !strncasecmp( line, FOOTPRINT_LIBRARY_HEADER, FOOTPRINT_LIBRARY_HEADER_CNT ) )
132  {
133  file_type = IO_MGR::LEGACY;
134 
135  while( reader.ReadLine() )
136  {
137  if( !strncasecmp( line, "$MODULE", strlen( "$MODULE" ) ) )
138  {
139  *aName = FROM_UTF8( StrPurge( line + strlen( "$MODULE" ) ) );
140  break;
141  }
142  }
143  }
144  else if( !strncasecmp( line, "Element", strlen( "Element" ) ) )
145  {
146  file_type = IO_MGR::GEDA_PCB;
147  *aName = aFileName.GetName();
148  }
149  else
150  {
151  file_type = IO_MGR::FILE_TYPE_NONE;
152  }
153 
154  return file_type;
155 }
156 
157 
164 static FOOTPRINT* parse_footprint_with_plugin( const wxFileName& aFileName,
165  IO_MGR::PCB_FILE_T aFileType,
166  const wxString& aName )
167 {
168  wxString path;
169 
170  switch( aFileType )
171  {
172  case IO_MGR::GEDA_PCB: path = aFileName.GetPath(); break;
173  case IO_MGR::LEGACY: path = aFileName.GetFullPath(); break;
174  default: wxFAIL_MSG( wxT( "unexpected IO_MGR::PCB_FILE_T" ) ); break;
175  }
176 
177  PLUGIN::RELEASER pi( IO_MGR::PluginFind( aFileType ) );
178 
179  return pi->FootprintLoad( path, aName );
180 }
181 
182 
187 static FOOTPRINT* parse_footprint_kicad( const wxFileName& aFileName )
188 {
189  wxString fcontents;
190  PCB_PLUGIN pcb_io;
191  wxFFile f( aFileName.GetFullPath() );
192 
193  if( !f.IsOpened() )
194  return nullptr;
195 
196  f.ReadAll( &fcontents );
197 
198  return dynamic_cast<FOOTPRINT*>( pcb_io.Parse( fcontents ) );
199 }
200 
201 
208 FOOTPRINT* try_load_footprint( const wxFileName& aFileName, IO_MGR::PCB_FILE_T aFileType,
209  const wxString& aName )
210 {
211  FOOTPRINT* footprint;
212 
213  switch( aFileType )
214  {
215  case IO_MGR::GEDA_PCB:
216  case IO_MGR::LEGACY:
217  footprint = parse_footprint_with_plugin( aFileName, aFileType, aName );
218  break;
219 
220  case IO_MGR::KICAD_SEXP:
221  footprint = parse_footprint_kicad( aFileName );
222  break;
223 
224  default:
225  wxFAIL_MSG( wxT( "unexpected IO_MGR::PCB_FILE_T" ) );
226  footprint = nullptr;
227  }
228 
229  return footprint;
230 }
231 
232 
234 {
235  wxString lastOpenedPathForLoading = m_mruPath;
237 
238  if( !cfg->m_LastImportExportPath.empty() )
239  lastOpenedPathForLoading = cfg->m_LastImportExportPath;
240 
241  wxFileName fn;
242 
243  if( aName != wxT("") )
244  fn = aName;
245  else
246  fn = getFootprintFilenameFromUser( this, lastOpenedPathForLoading );
247 
248  if( !fn.IsOk() )
249  return nullptr;
250 
251  FILE* fp = wxFopen( fn.GetFullPath(), wxT( "rt" ) );
252 
253  if( !fp )
254  {
255  wxString msg = wxString::Format( _( "File '%s' not found." ), fn.GetFullPath() );
256  DisplayError( this, msg );
257  return nullptr;
258  }
259 
260  m_mruPath = cfg->m_LastImportExportPath = fn.GetPath();
261 
262  wxString footprintName;
263  IO_MGR::PCB_FILE_T fileType = detect_file_type( fp, fn.GetFullPath(), &footprintName );
264 
266  {
267  DisplayError( this, _( "Not a footprint file." ) );
268  return nullptr;
269  }
270 
271  FOOTPRINT* footprint = nullptr;
272 
273  try
274  {
275  footprint = try_load_footprint( fn, fileType, footprintName );
276 
277  if( !footprint )
278  {
279  wxString msg = wxString::Format( _( "Unable to load footprint '%s' from '%s'" ),
280  footprintName,
281  fn.GetFullPath() );
282  DisplayError( this, msg );
283  return nullptr;
284  }
285  }
286  catch( const IO_ERROR& ioe )
287  {
288  DisplayError( this, ioe.What() );
289 
290  // if the footprint is not loaded, exit.
291  // However, even if an error happens, it can be loaded, because in KICAD and GPCB format,
292  // a fp library is a set of separate files, and the error(s) are not necessary when
293  // reading the selected file
294 
295  if( !footprint )
296  return nullptr;
297  }
298 
299  footprint->SetFPID( LIB_ID( wxEmptyString, footprintName ) );
300 
301  // Insert footprint in list
302  AddFootprintToBoard( footprint );
303 
304  // Display info :
305  SetMsgPanel( footprint );
306  PlaceFootprint( footprint );
307 
308  footprint->SetPosition( wxPoint( 0, 0 ) );
309 
311  UpdateView();
312 
313  return footprint;
314 }
315 
316 
318 {
319  wxFileName fn;
321 
322  if( !aFootprint )
323  return;
324 
325  fn.SetName( aFootprint->GetFPID().GetLibItemName() );
326 
327  wxString wildcard = KiCadFootprintLibFileWildcard();
328 
329  fn.SetExt( KiCadFootprintFileExtension );
330 
331  if( !cfg->m_LastImportExportPath.empty() )
332  fn.SetPath( cfg->m_LastImportExportPath );
333  else
334  fn.SetPath( m_mruPath );
335 
336  wxFileDialog dlg( this, _( "Export Footprint" ), fn.GetPath(), fn.GetFullName(),
337  wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
338 
339  if( dlg.ShowModal() == wxID_CANCEL )
340  return;
341 
342  fn = dlg.GetPath();
343  cfg->m_LastImportExportPath = fn.GetPath();
344 
345  try
346  {
347  // Export as *.kicad_pcb format, using a strategy which is specifically chosen
348  // as an example on how it could also be used to send it to the system clipboard.
349 
350  PCB_PLUGIN pcb_io(CTL_FOR_LIBRARY );
351 
352  /* This footprint should *already* be "normalized" in a way such that
353  orientation is zero, etc., since it came from the Footprint Editor.
354 
355  aFootprint->SetParent( 0 );
356  aFootprint->SetOrientation( 0 );
357  */
358 
359  pcb_io.Format( aFootprint );
360 
361  FILE* fp = wxFopen( dlg.GetPath(), wxT( "wt" ) );
362 
363  if( fp == nullptr )
364  {
365  wxMessageBox( wxString::Format( _( "Insufficient permissions to write file '%s'." ),
366  dlg.GetPath() ) );
367  return;
368  }
369 
370  fprintf( fp, "%s", pcb_io.GetStringOutput( false ).c_str() );
371  fclose( fp );
372  }
373  catch( const IO_ERROR& ioe )
374  {
375  DisplayError( this, ioe.What() );
376  return;
377  }
378 
379  wxString msg = wxString::Format( _( "Footprint exported to file '%s'." ), dlg.GetPath() );
380  DisplayInfoMessage( this, msg );
381 }
382 
383 
384 wxString PCB_BASE_EDIT_FRAME::CreateNewProjectLibrary( const wxString& aLibName,
385  const wxString& aProposedName )
386 {
387  return createNewLibrary( aLibName, aProposedName, Prj().PcbFootprintLibs() );
388 }
389 
390 
391 wxString PCB_BASE_EDIT_FRAME::CreateNewLibrary( const wxString& aLibName,
392  const wxString& aProposedName )
393 {
394  FP_LIB_TABLE* table = selectLibTable();
395 
396  return createNewLibrary( aLibName, aProposedName, table );
397 }
398 
399 
400 wxString PCB_BASE_EDIT_FRAME::createNewLibrary( const wxString& aLibName,
401  const wxString& aProposedName,
402  FP_LIB_TABLE* aTable )
403 {
404  // Kicad cannot write legacy format libraries, only .pretty new format because the legacy
405  // format cannot handle current features.
406  // The footprint library is actually a directory.
407 
408  if( aTable == nullptr )
409  return wxEmptyString;
410 
411  wxString initialPath = aProposedName.IsEmpty() ? Prj().GetProjectPath() : aProposedName;
412  wxFileName fn;
413  bool doAdd = false;
414  bool isGlobal = ( aTable == &GFootprintTable );
415 
416  if( aLibName.IsEmpty() )
417  {
418  fn = initialPath;
419 
421  KiCadFootprintLibPathExtension, false, isGlobal,
423  {
424  return wxEmptyString;
425  }
426 
427  doAdd = true;
428  }
429  else
430  {
431  fn = aLibName;
432 
433  if( !fn.IsAbsolute() )
434  {
435  fn.SetName( aLibName );
436  fn.MakeAbsolute( initialPath );
437  }
438 
439  // Enforce the .pretty extension:
440  fn.SetExt( KiCadFootprintLibPathExtension );
441  }
442 
443  // We can save fp libs only using IO_MGR::KICAD_SEXP format (.pretty libraries)
445  wxString libPath = fn.GetFullPath();
446 
447  try
448  {
449  PLUGIN::RELEASER pi( IO_MGR::PluginFind( piType ) );
450 
451  bool writable = false;
452  bool exists = false;
453 
454  try
455  {
456  writable = pi->IsFootprintLibWritable( libPath );
457  exists = true; // no exception was thrown, lib must exist.
458  }
459  catch( const IO_ERROR& )
460  {
461  // best efforts....
462  }
463 
464  if( exists )
465  {
466  if( !writable )
467  {
468  wxString msg = wxString::Format( _( "Library %s is read only." ), libPath );
469  ShowInfoBarError( msg );
470  return wxEmptyString;
471  }
472  else
473  {
474  wxString msg = wxString::Format( _( "Library %s already exists." ), libPath );
475  KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
476  dlg.SetOKLabel( _( "Overwrite" ) );
477  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
478 
479  if( dlg.ShowModal() == wxID_CANCEL )
480  return wxEmptyString;
481 
482  pi->FootprintLibDelete( libPath );
483  }
484  }
485 
486  pi->FootprintLibCreate( libPath );
487  }
488  catch( const IO_ERROR& ioe )
489  {
490  DisplayError( this, ioe.What() );
491  return wxEmptyString;
492  }
493 
494  if( doAdd )
495  AddLibrary( libPath, aTable );
496 
497  return libPath;
498 }
499 
500 
502 {
503  // If no project is loaded, always work with the global table
504  if( Prj().IsNullProject() )
505  {
507 
508  if( aOptional )
509  {
510  wxMessageDialog dlg( this, _( "Add the library to the global library table?" ),
511  _( "Add To Global Library Table" ), wxYES_NO );
512 
513  if( dlg.ShowModal() != wxID_OK )
514  ret = nullptr;
515  }
516 
517  return ret;
518  }
519 
520  wxArrayString libTableNames;
521  libTableNames.Add( _( "Global" ) );
522  libTableNames.Add( _( "Project" ) );
523 
524  wxSingleChoiceDialog dlg( this, _( "Choose the Library Table to add the library to:" ),
525  _( "Add To Library Table" ), libTableNames );
526 
527  if( aOptional )
528  {
529  dlg.FindWindow( wxID_CANCEL )->SetLabel( _( "Skip" ) );
530  dlg.FindWindow( wxID_OK )->SetLabel( _( "Add" ) );
531  }
532 
533  if( dlg.ShowModal() != wxID_OK )
534  return nullptr;
535 
536  switch( dlg.GetSelection() )
537  {
538  case 0: return &GFootprintTable;
539  case 1: return Prj().PcbFootprintLibs();
540  default: return nullptr;
541  }
542 }
543 
544 
545 bool PCB_BASE_EDIT_FRAME::AddLibrary( const wxString& aFilename, FP_LIB_TABLE* aTable )
546 {
547  if( aTable == nullptr )
548  aTable = selectLibTable();
549 
550  if( aTable == nullptr )
551  return wxEmptyString;
552 
553  bool isGlobal = ( aTable == &GFootprintTable );
554 
555  wxFileName fn( aFilename );
556 
557  if( aFilename.IsEmpty() )
558  {
560  KiCadFootprintLibPathExtension, true, isGlobal,
562  {
563  return false;
564  }
565  }
566 
567  wxString libPath = fn.GetFullPath();
568  wxString libName = fn.GetName();
569 
570  if( libName.IsEmpty() )
571  return false;
572 
573  wxString type = IO_MGR::ShowType( IO_MGR::GuessPluginTypeFromLibPath( libPath ) );
574 
575  // try to use path normalized to an environmental variable or project path
576  wxString normalizedPath = NormalizePath( libPath, &Pgm().GetLocalEnvVariables(), &Prj() );
577 
578  try
579  {
580  FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libName, normalizedPath, type, wxEmptyString );
581  aTable->InsertRow( row );
582 
583  if( isGlobal )
585  else
586  Prj().PcbFootprintLibs()->Save( Prj().FootprintLibTblName() );
587  }
588  catch( const IO_ERROR& ioe )
589  {
590  DisplayError( this, ioe.What() );
591  return false;
592  }
593 
595 
596  if( editor )
597  {
598  LIB_ID libID( libName, wxEmptyString );
599  editor->SyncLibraryTree( true );
600  editor->FocusOnLibID( libID );
601  }
602 
603  auto viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_VIEWER, false );
604 
605  if( viewer )
606  viewer->ReCreateLibraryList();
607 
608  return true;
609 }
610 
611 
612 bool FOOTPRINT_EDIT_FRAME::DeleteFootprintFromLibrary( const LIB_ID& aFPID, bool aConfirm )
613 {
614  if( !aFPID.IsValid() )
615  return false;
616 
617  wxString nickname = aFPID.GetLibNickname();
618  wxString fpname = aFPID.GetLibItemName();
619 
620  // Legacy libraries are readable, but modifying legacy format is not allowed
621  // So prompt the user if he try to delete a footprint from a legacy lib
622  wxString libfullname = Prj().PcbFootprintLibs()->FindRow( nickname )->GetFullURI();
623 
624  if( IO_MGR::GuessPluginTypeFromLibPath( libfullname ) == IO_MGR::LEGACY )
625  {
627  return false;
628  }
629 
630  if( !Prj().PcbFootprintLibs()->IsFootprintLibWritable( nickname ) )
631  {
632  wxString msg = wxString::Format( _( "Library '%s' is read only." ), nickname );
633  ShowInfoBarError( msg );
634  return false;
635  }
636 
637  // Confirmation
638  wxString msg = wxString::Format( _( "Delete footprint '%s' from library '%s'?" ),
639  fpname.GetData(),
640  nickname.GetData() );
641 
642  if( aConfirm && !IsOK( this, msg ) )
643  return false;
644 
645  try
646  {
647  Prj().PcbFootprintLibs()->FootprintDelete( nickname, fpname );
648  }
649  catch( const IO_ERROR& ioe )
650  {
651  DisplayError( this, ioe.What() );
652  return false;
653  }
654 
655  msg.Printf( _( "Footprint '%s' deleted from library '%s'" ),
656  fpname.GetData(),
657  nickname.GetData() );
658 
659  SetStatusText( msg );
660 
661  return true;
662 }
663 
664 
665 void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxString& aLibName,
666  wxString* aLibPath )
667 {
668  if( GetBoard()->GetFirstFootprint() == nullptr )
669  {
670  DisplayInfoMessage( this, _( "No footprints to export!" ) );
671  return;
672  }
673 
674  wxString footprintName;
675 
676  auto resetReference =
677  []( FOOTPRINT* aFootprint )
678  {
679  aFootprint->SetReference( "REF**" );
680  };
681 
682  if( !aStoreInNewLib )
683  {
684  // The footprints are saved in an existing .pretty library in the fp lib table
685  PROJECT& prj = Prj();
686  wxString last_nickname = prj.GetRString( PROJECT::PCB_LIB_NICKNAME );
687  wxString nickname = SelectLibrary( last_nickname );
688 
689  if( !nickname ) // Aborted
690  return;
691 
692  bool map = IsOK( this, wxString::Format( _( "Update footprints on board to refer to %s?" ),
693  nickname ) );
694 
695  prj.SetRString( PROJECT::PCB_LIB_NICKNAME, nickname );
696 
697  for( FOOTPRINT* footprint : GetBoard()->Footprints() )
698  {
699  try
700  {
701  FP_LIB_TABLE* tbl = prj.PcbFootprintLibs();
702 
703  if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
704  {
705  FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
706 
707  resetReference( fpCopy );
708  tbl->FootprintSave( nickname, fpCopy, true );
709 
710  delete fpCopy;
711  }
712  }
713  catch( const IO_ERROR& ioe )
714  {
715  DisplayError( this, ioe.What() );
716  }
717 
718  if( map )
719  {
720  LIB_ID id = footprint->GetFPID();
721  id.SetLibNickname( nickname );
722  footprint->SetFPID( id );
723  }
724  }
725  }
726  else
727  {
728  // The footprints are saved in a new .pretty library.
729  // If this library already exists, all previous footprints will be deleted
730  wxString libPath = CreateNewLibrary( aLibName );
731 
732  if( libPath.IsEmpty() ) // Aborted
733  return;
734 
735  if( aLibPath )
736  *aLibPath = libPath;
737 
738  wxString libNickname;
739  bool map = IsOK( this, _( "Update footprints on board to refer to new library?" ) );
740 
741  if( map )
742  {
743  const LIB_TABLE_ROW* row = Prj().PcbFootprintLibs()->FindRowByURI( libPath );
744 
745  if( row )
746  libNickname = row->GetNickName();
747  }
748 
750  PLUGIN::RELEASER pi( IO_MGR::PluginFind( piType ) );
751 
752  for( FOOTPRINT* footprint : GetBoard()->Footprints() )
753  {
754  try
755  {
756  if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
757  {
758  FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
759 
760  resetReference( fpCopy );
761  pi->FootprintSave( libPath, fpCopy );
762 
763  delete fpCopy;
764  }
765  }
766  catch( const IO_ERROR& ioe )
767  {
768  DisplayError( this, ioe.What() );
769  }
770 
771  if( map )
772  {
773  LIB_ID id = footprint->GetFPID();
774  id.SetLibNickname( libNickname );
775  footprint->SetFPID( id );
776  }
777  }
778  }
779 }
780 
781 
783 {
784  if( !aFootprint ) // Happen if no footprint loaded
785  return false;
786 
787  wxString libraryName = aFootprint->GetFPID().GetLibNickname();
788  wxString footprintName = aFootprint->GetFPID().GetLibItemName();
789  bool nameChanged = m_footprintNameWhenLoaded != footprintName;
790 
791  if( aFootprint->GetLink() != niluuid )
792  {
793  if( SaveFootprintToBoard( false ) )
794  {
795  m_footprintNameWhenLoaded = footprintName;
796  return true;
797  }
798  else
799  {
800  return false;
801  }
802  }
803  else if( libraryName.IsEmpty() || footprintName.IsEmpty() )
804  {
805  if( SaveFootprintAs( aFootprint ) )
806  {
807  m_footprintNameWhenLoaded = footprintName;
808  SyncLibraryTree( true );
809  return true;
810  }
811  else
812  {
813  return false;
814  }
815  }
816 
817  FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs();
818 
819  // Legacy libraries are readable, but modifying legacy format is not allowed
820  // So prompt the user if he try to add/replace a footprint in a legacy lib
821  wxString libfullname = tbl->FindRow( libraryName )->GetFullURI();
822 
823  if( IO_MGR::GuessPluginTypeFromLibPath( libfullname ) == IO_MGR::LEGACY )
824  {
826  return false;
827  }
828 
829  if( nameChanged )
830  {
831  LIB_ID oldFPID( libraryName, m_footprintNameWhenLoaded );
832  DeleteFootprintFromLibrary( oldFPID, false );
833  }
834 
835  if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
836  return false;
837 
838  if( nameChanged )
839  {
840  m_footprintNameWhenLoaded = footprintName;
841  SyncLibraryTree( true );
842  }
843 
844  return true;
845 }
846 
847 
849  const wxString& aLibraryName )
850 {
851  try
852  {
853  aFootprint->SetFPID( LIB_ID( wxEmptyString, aFootprint->GetFPID().GetLibItemName() ) );
854 
855  Prj().PcbFootprintLibs()->FootprintSave( aLibraryName, aFootprint );
856 
857  aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
858  return true;
859  }
860  catch( const IO_ERROR& ioe )
861  {
862  DisplayError( this, ioe.What() );
863 
864  aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
865  return false;
866  }
867 }
868 
869 
871 {
872  // update footprint in the current board,
873  // not just add it to the board with total disregard for the netlist...
874  PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB_EDITOR, false );
875 
876  if( pcbframe == nullptr ) // happens when the board editor is not active (or closed)
877  {
878  ShowInfoBarError( _( "No board currently open." ) );
879  return false;
880  }
881 
882  TOOL_MANAGER* toolMgr = pcbframe->GetToolManager();
883  BOARD* mainpcb = pcbframe->GetBoard();
884  FOOTPRINT* sourceFootprint = nullptr;
885  FOOTPRINT* editorFootprint = GetBoard()->GetFirstFootprint();
886 
887  // Search the old footprint (source) if exists
888  // Because this source could be deleted when editing the main board...
889  if( editorFootprint->GetLink() != niluuid ) // this is not a new footprint ...
890  {
891  sourceFootprint = nullptr;
892 
893  for( FOOTPRINT* candidate : mainpcb->Footprints() )
894  {
895  if( editorFootprint->GetLink() == candidate->m_Uuid )
896  {
897  sourceFootprint = candidate;
898  break;
899  }
900  }
901  }
902 
903  if( !aAddNew && sourceFootprint == nullptr ) // source not found
904  {
905  DisplayError( this, _( "Unable to find the footprint on the main board.\nCannot save." ) );
906  return false;
907  }
908 
909  if( aAddNew && toolMgr->GetTool<BOARD_EDITOR_CONTROL>()->PlacingFootprint() )
910  {
911  DisplayError( this, _( "Previous footprint placement still in progress." ) );
912  return false;
913  }
914 
916  toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
917  BOARD_COMMIT commit( pcbframe );
918 
919  // Create a copy for the board, first using Clone() to keep existing Uuids, and then either
920  // resetting the uuids to the board values or assigning new Uuids.
921  FOOTPRINT* newFootprint = static_cast<FOOTPRINT*>( editorFootprint->Clone() );
922  newFootprint->SetParent( mainpcb );
923  newFootprint->SetLink( niluuid );
924 
925  auto fixUuid =
926  [&]( KIID& aUuid )
927  {
928  if( editorFootprint->GetLink() != niluuid && m_boardFootprintUuids.count( aUuid ) )
929  aUuid = m_boardFootprintUuids[ aUuid ];
930  else
931  aUuid = KIID();
932  };
933 
934  fixUuid( const_cast<KIID&>( newFootprint->m_Uuid ) );
935  newFootprint->RunOnChildren(
936  [&]( BOARD_ITEM* aChild )
937  {
938  fixUuid( const_cast<KIID&>( aChild->m_Uuid ) );
939  } );
940 
941  if( sourceFootprint ) // this is an update command
942  {
943  // In the main board the new footprint replaces the old one (pos, orient, ref, value,
944  // connections and properties are kept) and the sourceFootprint (old footprint) is
945  // deleted
946  pcbframe->ExchangeFootprint( sourceFootprint, newFootprint, commit );
947  commit.Push( wxT( "Update footprint" ) );
948  }
949  else // This is an insert command
950  {
951  KIGFX::VIEW_CONTROLS* viewControls = pcbframe->GetCanvas()->GetViewControls();
952  VECTOR2D cursorPos = viewControls->GetCursorPosition();
953 
954  commit.Add( newFootprint );
955  viewControls->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
956  pcbframe->PlaceFootprint( newFootprint );
957  newFootprint->SetPosition( wxPoint( 0, 0 ) );
958  viewControls->SetCrossHairCursorPosition( cursorPos, false );
959  const_cast<KIID&>( newFootprint->m_Uuid ) = KIID();
960  commit.Push( wxT( "Insert footprint" ) );
961 
962  pcbframe->Raise();
963  toolMgr->RunAction( PCB_ACTIONS::placeFootprint, true, newFootprint );
964  }
965 
966  newFootprint->ClearFlags();
967 
968  return true;
969 }
970 
971 
973 {
974  if( aFootprint == nullptr )
975  return false;
976 
977  FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs();
978 
979  SetMsgPanel( aFootprint );
980 
981  wxString libraryName = aFootprint->GetFPID().GetLibNickname();
982  wxString footprintName = aFootprint->GetFPID().GetLibItemName();
983  bool updateValue = aFootprint->GetValue() == footprintName;
984 
985  wxArrayString headers;
986  std::vector<wxArrayString> itemsToDisplay;
987  std::vector<wxString> nicknames = tbl->GetLogicalLibs();
988 
989  headers.Add( _( "Nickname" ) );
990  headers.Add( _( "Description" ) );
991 
992  for( const wxString& nickname : nicknames )
993  {
994  wxArrayString item;
995  item.Add( nickname );
996  item.Add( tbl->GetDescription( nickname ) );
997  itemsToDisplay.push_back( item );
998  }
999 
1000  EDA_LIST_DIALOG dlg( this, _( "Save Footprint As" ), headers, itemsToDisplay, libraryName );
1001  dlg.SetListLabel( _( "Save in library:" ) );
1002  dlg.SetOKLabel( _( "Save" ) );
1003 
1004  wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
1005 
1006  wxStaticText* label = new wxStaticText( &dlg, wxID_ANY, _( "Name:" ),
1007  wxDefaultPosition, wxDefaultSize, 0 );
1008  bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
1009 
1010  wxTextCtrl* nameTextCtrl = new wxTextCtrl( &dlg, wxID_ANY, footprintName,
1011  wxDefaultPosition, wxDefaultSize, 0 );
1012  bNameSizer->Add( nameTextCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
1013 
1014  wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST );
1015  nameValidator.SetCharExcludes( FOOTPRINT::StringLibNameInvalidChars( false ) );
1016  nameTextCtrl->SetValidator( nameValidator );
1017 
1018  wxSizer* mainSizer = dlg.GetSizer();
1019  mainSizer->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
1020 
1021  // Move nameTextCtrl to the head of the tab-order
1022  if( dlg.GetChildren().DeleteObject( nameTextCtrl ) )
1023  dlg.GetChildren().Insert( nameTextCtrl );
1024 
1025  dlg.SetInitialFocus( nameTextCtrl );
1026 
1027  dlg.Layout();
1028  mainSizer->Fit( &dlg );
1029 
1030  if( dlg.ShowModal() != wxID_OK )
1031  return false; // canceled by user
1032 
1033  libraryName = dlg.GetTextSelection();
1034 
1035  if( libraryName.IsEmpty() )
1036  {
1037  DisplayError( this, _( "No library specified. Footprint could not be saved." ) );
1038  return false;
1039  }
1040 
1041  footprintName = nameTextCtrl->GetValue();
1042  footprintName.Trim( true );
1043  footprintName.Trim( false );
1044 
1045  if( footprintName.IsEmpty() )
1046  {
1047  DisplayError( this, _( "No footprint name specified. Footprint could not be saved." ) );
1048  return false;
1049  }
1050 
1051  aFootprint->SetFPID( LIB_ID( libraryName, footprintName ) );
1052 
1053  if( updateValue )
1054  aFootprint->SetValue( footprintName );
1055 
1056  // Legacy libraries are readable, but modifying legacy format is not allowed
1057  // So prompt the user if he try to add/replace a footprint in a legacy lib
1058  wxString libfullname = Prj().PcbFootprintLibs()->FindRow( libraryName )->GetFullURI();
1060 
1061  if( piType == IO_MGR::LEGACY )
1062  {
1064  return false;
1065  }
1066 
1067  bool footprintExists = tbl->FootprintExists( libraryName, footprintName );
1068 
1069  if( footprintExists )
1070  {
1071  wxString msg = wxString::Format( _( "Footprint %s already exists in %s." ),
1072  footprintName,
1073  libraryName );
1074  KIDIALOG chkdlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1075  chkdlg.SetOKLabel( _( "Overwrite" ) );
1076 
1077  if( chkdlg.ShowModal() == wxID_CANCEL )
1078  return false;
1079  }
1080 
1081  if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
1082  return false;
1083 
1084  // Once saved-as a board footprint is no longer a board footprint
1085  aFootprint->SetLink( niluuid );
1086 
1087  wxString fmt = footprintExists ? _( "Footprint '%s' replaced in '%s'" )
1088  : _( "Footprint '%s' added to '%s'" );
1089 
1090  wxString msg = wxString::Format( fmt, footprintName.GetData(), libraryName.GetData() );
1091  SetStatusText( msg );
1092  UpdateTitle();
1093  ReCreateHToolbar();
1094 
1095  return true;
1096 }
1097 
1098 
1100 {
1102  {
1103  wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1104  GetLoadedFPID().GetLibItemName().wx_str() );
1105 
1106  if( ConfirmRevertDialog( this, msg ) )
1107  {
1108  Clear_Pcb( false );
1109  AddFootprintToBoard( static_cast<FOOTPRINT*>( m_revertModule->Clone() ) );
1110 
1111  Zoom_Automatique( false );
1112 
1113  Update3DView( true, true );
1114 
1116  GetScreen()->SetContentModified( false );
1117 
1118  UpdateView();
1119  GetCanvas()->Refresh();
1120 
1121  return true;
1122  }
1123  }
1124 
1125  return false;
1126 }
1127 
1128 
1129 FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( const wxString& aFootprintName, bool aQuiet )
1130 {
1131  wxString footprintName = aFootprintName;
1132 
1133  // Static to store user preference for a session
1134  static int footprintType = 1;
1135  int footprintTranslated = FP_SMD;
1136 
1137  // Ask for the new footprint name
1138  if( footprintName.IsEmpty() && !aQuiet )
1139  {
1140  WX_TEXT_ENTRY_DIALOG dlg( this, _( "Enter footprint name:" ), _( "New Footprint" ),
1141  footprintName, _( "Footprint type:" ),
1142  { _( "Through hole" ), _( "SMD" ), _( "Other" ) },
1143  footprintType );
1144  dlg.SetTextValidator( FOOTPRINT_NAME_VALIDATOR( &footprintName ) );
1145 
1146  if( dlg.ShowModal() != wxID_OK )
1147  return nullptr; //Aborted by user
1148 
1149  footprintType = dlg.GetChoice();
1150 
1151  switch( footprintType )
1152  {
1153  case 0:
1154  footprintTranslated = FP_THROUGH_HOLE;
1155  break;
1156  case 1:
1157  footprintTranslated = FP_SMD;
1158  break;
1159  default:
1160  footprintTranslated = 0;
1161  }
1162  }
1163 
1164  footprintName.Trim( true );
1165  footprintName.Trim( false );
1166 
1167  if( footprintName.IsEmpty() )
1168  {
1169  if( !aQuiet )
1170  DisplayInfoMessage( this, _( "No footprint name defined." ) );
1171 
1172  return nullptr;
1173  }
1174 
1175  // Creates the new footprint and add it to the head of the linked list of footprints
1176  FOOTPRINT* footprint = new FOOTPRINT( GetBoard() );
1177 
1178  // Update parameters: timestamp ...
1179  footprint->SetLastEditTime();
1180 
1181  // Update its name in lib
1182  footprint->SetFPID( LIB_ID( wxEmptyString, footprintName ) );
1183 
1184  footprint->SetAttributes( footprintTranslated );
1185 
1186  PCB_LAYER_ID txt_layer;
1187  wxPoint default_pos;
1189 
1190  footprint->Reference().SetText( settings.m_DefaultFPTextItems[0].m_Text );
1191  footprint->Reference().SetVisible( settings.m_DefaultFPTextItems[0].m_Visible );
1192  txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[0].m_Layer;
1193  footprint->Reference().SetLayer( txt_layer );
1194  default_pos.y -= settings.GetTextSize( txt_layer ).y / 2;
1195  footprint->Reference().SetPosition( default_pos );
1196  default_pos.y += settings.GetTextSize( txt_layer ).y;
1197 
1198  footprint->Value().SetText( settings.m_DefaultFPTextItems[1].m_Text );
1199  footprint->Value().SetVisible( settings.m_DefaultFPTextItems[1].m_Visible );
1200  txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[1].m_Layer;
1201  footprint->Value().SetLayer( txt_layer );
1202  default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1203  footprint->Value().SetPosition( default_pos );
1204  default_pos.y += settings.GetTextSize( txt_layer ).y;
1205 
1206  for( size_t i = 2; i < settings.m_DefaultFPTextItems.size(); ++i )
1207  {
1208  FP_TEXT* textItem = new FP_TEXT( footprint );
1209  textItem->SetText( settings.m_DefaultFPTextItems[i].m_Text );
1210  textItem->SetVisible( settings.m_DefaultFPTextItems[i].m_Visible );
1211  txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[i].m_Layer;
1212  textItem->SetLayer( txt_layer );
1213  default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1214  textItem->SetPosition( default_pos );
1215  default_pos.y += settings.GetTextSize( txt_layer ).y;
1216  footprint->GraphicalItems().push_back( textItem );
1217  }
1218 
1219  if( footprint->GetReference().IsEmpty() )
1220  footprint->SetReference( footprintName );
1221 
1222  if( footprint->GetValue().IsEmpty() )
1223  footprint->SetValue( footprintName );
1224 
1225  footprint->RunOnChildren(
1226  [&] ( BOARD_ITEM* aChild )
1227  {
1228  if( aChild->Type() == PCB_FP_TEXT_T )
1229  {
1230  FP_TEXT* textItem = static_cast<FP_TEXT*>( aChild );
1231  PCB_LAYER_ID layer = textItem->GetLayer();
1232 
1233  textItem->SetTextThickness( settings.GetTextThickness( layer ) );
1234  textItem->SetTextSize( settings.GetTextSize( layer ) );
1235  textItem->SetItalic( settings.GetTextItalic( layer ) );
1236  textItem->SetKeepUpright( settings.GetTextUpright( layer ) );
1237  }
1238  } );
1239 
1240  SetMsgPanel( footprint );
1241  return footprint;
1242 }
1243 
1244 
1245 wxString PCB_BASE_FRAME::SelectLibrary( const wxString& aNicknameExisting )
1246 {
1247  wxArrayString headers;
1248 
1249  headers.Add( _( "Nickname" ) );
1250  headers.Add( _( "Description" ) );
1251 
1252  FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs();
1253 
1254  std::vector< wxArrayString > itemsToDisplay;
1255  std::vector< wxString > nicknames = fptbl->GetLogicalLibs();
1256 
1257  for( const wxString& nickname : nicknames )
1258  {
1259  wxArrayString item;
1260 
1261  item.Add( nickname );
1262  item.Add( fptbl->GetDescription( nickname ) );
1263 
1264  itemsToDisplay.push_back( item );
1265  }
1266 
1267  EDA_LIST_DIALOG dlg( this, _( "Select Library" ), headers, itemsToDisplay, aNicknameExisting );
1268 
1269  if( dlg.ShowModal() != wxID_OK )
1270  return wxEmptyString;
1271 
1272  return dlg.GetTextSelection();
1273 }
void SetReference(const wxString &aReference)
Definition: footprint.h:473
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:279
void BuildListOfNets()
Definition: board.h:659
std::map< KIID, KIID > m_boardFootprintUuids
const UTF8 & GetLibItemName() const
Definition: lib_id.h:104
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: confirm.cpp:55
bool ConfirmRevertDialog(wxWindow *parent, const wxString &aMessage)
Display a confirmation dialog for a revert action.
Definition: confirm.cpp:228
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:53
static const wxString INFO_LEGACY_LIB_WARN_EDIT(_("Writing/modifying legacy libraries (.mod files) is not allowed\n" "Please save the current library to the new .pretty format\n" "and update your footprint lib table\n" "to save your footprint (a .kicad_mod file) in the .pretty library folder"))
void ReCreateHToolbar() override
Create the main horizontal toolbar for the footprint editor.
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project.
std::vector< TEXT_ITEM_INFO > m_DefaultFPTextItems
KIID niluuid(0)
wxString GetTextSelection(int aColumn=0)
Return the selected text from aColumn in the wxListCtrl in the dialog.
KIGFX::VIEW_CONTROLS * GetViewControls() const
Return a pointer to the #VIEW_CONTROLS instance used in the panel.
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
wxString m_mruPath
virtual void SetPosition(const wxPoint &aPos) override
Definition: fp_text.h:93
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
FP_LIB_TABLE GFootprintTable
The global footprint library table.
Definition: cvpcb.cpp:134
Container for project specific data.
Definition: project.h:62
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:110
const wxString & GetValue() const
Definition: footprint.h:486
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:45
Hold a record identifying a library accessed by the appropriate footprint library PLUGIN object in th...
Definition: fp_lib_table.h:40
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:163
This file is part of the common library.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:49
const std::string KiCadFootprintFileExtension
static wxFileName getFootprintFilenameFromUser(wxWindow *aParent, const wxString &aLastPath)
Prompt the user for a footprint file to open.
void SetOKLabel(const wxString &aLabel)
COMMIT & Add(EDA_ITEM *aItem)
Notify observers that aItem has been added.
Definition: commit.h:78
static FOOTPRINT * parse_footprint_kicad(const wxFileName &aFileName)
Parse a KICAD footprint.
FOOTPRINT * CreateNewFootprint(const wxString &aFootprintName, bool aQuiet=false)
Creates a new footprint, at position 0,0.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void SetItalic(bool isItalic)
Definition: eda_text.h:200
A KICAD version of wxTextEntryDialog which supports the various improvements/work-arounds from DIALOG...
bool LibraryFileBrowser(bool doOpen, wxFileName &aFilename, const wxString &wildcard, const wxString &ext, bool isDirectory=false, bool aIsGlobal=false, const wxString &aGlobalPath=wxEmptyString)
Component library viewer main window.
void SetTextValidator(wxTextValidatorStyle style)
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
A PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
Definition: pcb_plugin.h:141
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:383
A dialog which shows:
void SaveFootprintToBoard(wxCommandEvent &event)
bool DeleteFootprintFromLibrary(const LIB_ID &aFPID, bool aConfirm)
Delete the given footprint from its library.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:258
static const wxString ShowType(PCB_FILE_T aFileType)
Return a brief name for a plugin given aFileType enum.
Definition: io_mgr.cpp:77
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
int GetTextThickness(PCB_LAYER_ID aLayer) const
Return the default text thickness from the layer class for the given layer.
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:159
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:122
wxString AllFilesWildcard()
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
Read lines of text from another LINE_READER but only returns non-comment lines and non-blank lines wi...
Definition: filter_reader.h:68
Geda PCB file formats.
Definition: io_mgr.h:64
BOARD_ITEM * Parse(const wxString &aClipboardSourceInput)
Definition: pcb_plugin.cpp:378
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath)
Return a plugin type given a footprint library's libPath.
Definition: io_mgr.cpp:124
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:115
void SetAttributes(int aAttributes)
Definition: footprint.h:237
void PlaceFootprint(FOOTPRINT *aFootprint, bool aRecreateRatsnest=true)
Places aFootprint at the current cursor position and updates footprint coordinates with the new posit...
This file contains miscellaneous commonly used macros and functions.
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:500
bool GetTextUpright(PCB_LAYER_ID aLayer) const
This class provides a custom wxValidator object for limiting the allowable characters when defining f...
Definition: validators.h:63
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...
FP_TEXT & Reference()
Definition: footprint.h:501
bool GetTextItalic(PCB_LAYER_ID aLayer) const
Releases a PLUGIN in the context of a potential thrown exception through its destructor.
Definition: io_mgr.h:555
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...
Master controller class:
Definition: tool_manager.h:54
virtual void Zoom_Automatique(bool aWarpPointer)
Redraw the screen with best zoom level and the best centering that shows all the page or the board.
virtual void SetVisible(bool aVisible)
Definition: eda_text.h:206
void ExportFootprint(FOOTPRINT *aFootprint)
Create a file containing only one footprint.
void SyncLibraryTree(bool aProgress)
Synchronize the footprint library tree to the current state of the footprint library table.
Definition: kiid.h:44
void ExchangeFootprint(FOOTPRINT *aExisting, FOOTPRINT *aNew, BOARD_COMMIT &aCommit, bool deleteExtraTexts=true, bool resetTextLayers=true, bool resetTextEffects=true, bool resetFabricationAttrs=true, bool reset3DModels=true)
Replace aExisting footprint by aNew footprint using the Existing footprint settings (position,...
const wxString & GetNickName() const
static FOOTPRINT * parse_footprint_with_plugin(const wxFileName &aFileName, IO_MGR::PCB_FILE_T aFileType, const wxString &aName)
Parse a footprint using a PLUGIN.
#define FOOTPRINT_LIBRARY_HEADER
Definition: legacy_plugin.h:38
bool Clear_Pcb(bool aQuery)
Delete all and reinitialize the current board.
Definition: initpcb.cpp:97
A LINE_READER that reads from an open file.
Definition: richio.h:172
wxString CreateNewProjectLibrary(const wxString &aLibName=wxEmptyString, const wxString &aProposedName=wxEmptyString)
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:318
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:124
VECTOR2< double > VECTOR2D
Definition: vector2d.h:621
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
const wxString GetDescription(const wxString &aNickname)
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
const LIB_TABLE_ROW * FindRowByURI(const wxString &aURI)
bool SaveFootprintInLibrary(FOOTPRINT *aFootprint, const wxString &aLibraryName)
wxString CreateNewLibrary(const wxString &aLibName=wxEmptyString, const wxString &aProposedName=wxEmptyString)
If a library name is given, creates a new footprint library in the project folder with the given name...
FOOTPRINTS & Footprints()
Definition: board.h:234
char * StrPurge(char *text)
Remove leading and training spaces, tabs and end of line chars in text.
wxString ModLegacyExportFileWildcard()
Handle actions specific to the board editor in PcbNew.
void ExportFootprintsToLibrary(bool aStoreInNewLib, const wxString &aLibName=wxEmptyString, wxString *aLibPath=nullptr)
Save footprints in a library:
Definition of file extensions used in Kicad.
An interface for classes handling user events controlling the view behavior such as zooming,...
const wxString & GetReference() const
Definition: footprint.h:464
#define _(s)
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:90
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:153
DRAWINGS & GraphicalItems()
Definition: footprint.h:172
const LIB_ID & GetFPID() const
Definition: footprint.h:195
static IO_MGR::PCB_FILE_T detect_file_type(FILE *aFile, const wxFileName &aFileName, wxString *aName)
Read a file to detect the type.
virtual void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Move the graphic crosshair cursor to the requested position expressed in world coordinates.
bool AddLibrary(const wxString &aLibName=wxEmptyString, FP_LIB_TABLE *aTable=nullptr)
Add an existing library to either the global or project library table.
void SetValue(const wxString &aValue)
Definition: footprint.h:494
FormatType fileType(const char *aFileName)
Definition: loadmodel.cpp:278
std::unique_ptr< FOOTPRINT > m_revertModule
#define FOOTPRINT_LIBRARY_HEADER_CNT
Definition: legacy_plugin.h:39
void Format(const BOARD_ITEM *aItem, int aNestLevel=0) const
Output aItem to aFormatter in s-expression format.
Definition: pcb_plugin.cpp:400
KIID GetLink() const
Definition: footprint.h:576
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:212
std::string GetStringOutput(bool doClear)
Definition: pcb_plugin.h:211
const KIID m_Uuid
Definition: eda_item.h:474
virtual FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition: project.cpp:283
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:97
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:200
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:196
void SetKeepUpright(bool aKeepUpright)
Definition: fp_text.h:115
void SetLink(const KIID &aLink)
Definition: footprint.h:577
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:227
wxString KiCadFootprintLibPathWildcard()
static TOOL_ACTION placeFootprint
Definition: pcb_actions.h:157
static wxString GetDefaultUserFootprintsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:108
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:158
Legacy Pcbnew file formats prior to s-expression.
Definition: io_mgr.h:55
see class PGM_BASE
const FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an FP_LIB_TABLE_ROW if aNickName is found in this table or in any chained fall back table frag...
FP_LIB_TABLE * selectLibTable(bool aOptional=false)
Prompts a user to select global or project library tables.
bool PlacingFootprint() const
Re-entrancy checker for above.
LIB_ID GetLoadedFPID() const
Return the LIB_ID of the part being edited.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:191
FOOTPRINT * try_load_footprint(const wxFileName &aFileName, IO_MGR::PCB_FILE_T aFileType, const wxString &aName)
Try to load a footprint, returning nullptr if the file couldn't be accessed.
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
static PLUGIN * PluginFind(PCB_FILE_T aFileType)
Return a PLUGIN which the caller can use to import, export, save, or load design documents.
Definition: io_mgr.cpp:58
void SetLastEditTime(timestamp_t aTime)
Definition: footprint.h:342
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
SAVE_T FootprintSave(const wxString &aNickname, const FOOTPRINT *aFootprint, bool aOverwrite=true)
Write aFootprint to an existing library given by aNickname.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
The main frame for Pcbnew.
bool SaveFootprintAs(FOOTPRINT *aFootprint)
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Revert the commit by restoring the modified items state.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
static const wxString INFO_LEGACY_LIB_WARN_DELETE(_("Modifying legacy libraries (.mod files) is not allowed\n" "Please save the current library under the new .pretty format\n" "and update your footprint lib table\n" "before deleting a footprint"))
int ShowModal() override
Definition: confirm.cpp:99
FOOTPRINT_EDITOR_SETTINGS * GetSettings()
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction) const
Invoke a function on all BOARD_ITEMs that belong to the footprint (pads, drawings,...
Definition: footprint.cpp:1298
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:180
wxString SelectLibrary(const wxString &aNicknameExisting)
Put up a dialog and allows the user to pick a library, for unspecified use.
void AddFootprintToBoard(FOOTPRINT *aFootprint) override
Override from PCB_BASE_EDIT_FRAME which adds a footprint to the editor's dummy board,...
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
BOARD * GetBoard() const
void SetPosition(const wxPoint &aPos) override
Definition: footprint.cpp:1561
void FootprintDelete(const wxString &aNickname, const wxString &aFootprintName)
Delete the aFootprintName from the library given by aNickname.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: footprint.cpp:1292
PCB_FILE_T
The set of file types that the IO_MGR knows about, and for which there has been a plugin written.
Definition: io_mgr.h:53
bool IsContentModified() const override
Get if any footprints or libraries have been modified but not saved.
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:307
bool SaveFootprint(FOOTPRINT *aFootprint)
Save in an existing library a given footprint.
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:142
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:323
const std::string KiCadFootprintLibPathExtension
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
wxString KiCadFootprintLibFileWildcard()
Custom text control validator definitions.
wxSize GetTextSize(PCB_LAYER_ID aLayer) const
Return the default text size from the layer class for the given layer.
static const wxChar * StringLibNameInvalidChars(bool aUserReadable)
Test for validity of the name in a library of the footprint ( no spaces, dir separators ....
Definition: footprint.cpp:1443
wxString NormalizePath(const wxFileName &aFilePath, const ENV_VAR_MAP *aEnvVars, const wxString &aProjectPath)
Normalize a file path to an environmental variable, if possible.
Definition: env_paths.cpp:69
bool FootprintExists(const wxString &aNickname, const wxString &aFootprintName)
Indicates whether or not the given footprint already exists in the given library.
static wxString GetGlobalTableFileName()
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
#define CTL_FOR_LIBRARY
Format output for a footprint library instead of clipboard or BOARD.
Definition: pcb_plugin.h:128
wxString GedaPcbFootprintLibFileWildcard()
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:112
FOOTPRINT * ImportFootprint(const wxString &aName=wxT(""))
Read a file containing only one footprint.
S-expression Pcbnew file format.
Definition: io_mgr.h:56
Container for design settings for a BOARD object.
wxString createNewLibrary(const wxString &aLibName, const wxString &aProposedName, FP_LIB_TABLE *aTable)
Create a new library in the given table (presumed to be either the global or project library table).
void SetListLabel(const wxString &aLabel)