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-2021 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>
38 #include <board.h>
39 #include <footprint.h>
40 #include <board_commit.h>
41 #include <footprint_edit_frame.h>
45 #include <env_paths.h>
46 #include <paths.h>
49 #include "footprint_viewer_frame.h"
50 #include <wx/choicdlg.h>
51 #include <wx/filedlg.h>
52 
53 
54 // unique, "file local" translations:
55 
56 
57 static const wxString INFO_LEGACY_LIB_WARN_EDIT(
58  _( "Writing/modifying legacy libraries (.mod files) is not allowed\n"\
59  "Please save the current library to the new .pretty format\n"\
60  "and update your footprint lib table\n"\
61  "to save your footprint (a .kicad_mod file) in the .pretty library folder" ) );
62 
63 static const wxString INFO_LEGACY_LIB_WARN_DELETE(
64  _( "Modifying legacy libraries (.mod files) is not allowed\n"\
65  "Please save the current library under the new .pretty format\n"\
66  "and update your footprint lib table\n"\
67  "before deleting a footprint" ) );
68 
69 
75 static wxFileName getFootprintFilenameFromUser( wxWindow* aParent, const wxString& aLastPath )
76 {
77  static int lastFilterIndex = 0; // To store the last choice during a session.
78  wxString wildCard;
79 
80  wildCard << KiCadFootprintLibFileWildcard() << wxChar( '|' )
81  << ModLegacyExportFileWildcard() << wxChar( '|' )
82  << GedaPcbFootprintLibFileWildcard() << wxChar( '|' )
83  << AllFilesWildcard();
84 
85  wxFileDialog dlg( aParent, _( "Import Footprint" ), aLastPath, wxEmptyString, wildCard,
86  wxFD_OPEN | wxFD_FILE_MUST_EXIST );
87 
88  dlg.SetFilterIndex( lastFilterIndex );
89 
90  if( dlg.ShowModal() == wxID_CANCEL )
91  return wxFileName();
92 
93  lastFilterIndex = dlg.GetFilterIndex();
94 
95  return wxFileName( dlg.GetPath() );
96 }
97 
98 
105 static IO_MGR::PCB_FILE_T detect_file_type( FILE* aFile, const wxFileName& aFileName,
106  wxString* aName )
107 {
108  FILE_LINE_READER freader( aFile, aFileName.GetFullPath() );
109  WHITESPACE_FILTER_READER reader( freader );
110  IO_MGR::PCB_FILE_T file_type;
111 
112  wxASSERT( aName );
113 
114  reader.ReadLine();
115  char* line = reader.Line();
116 
117  // first .kicad_mod file versions starts by "(module"
118  // recent .kicad_mod file versions starts by "(footprint"
119  if( strncasecmp( line, "(module", strlen( "(module" ) ) == 0
120  || strncasecmp( line, "(footprint", strlen( "(footprint" ) ) == 0 )
121  {
122  file_type = IO_MGR::KICAD_SEXP;
123  *aName = aFileName.GetName();
124  }
125  else if( !strncasecmp( line, FOOTPRINT_LIBRARY_HEADER, FOOTPRINT_LIBRARY_HEADER_CNT ) )
126  {
127  file_type = IO_MGR::LEGACY;
128 
129  while( reader.ReadLine() )
130  {
131  if( !strncasecmp( line, "$MODULE", strlen( "$MODULE" ) ) )
132  {
133  *aName = FROM_UTF8( StrPurge( line + strlen( "$MODULE" ) ) );
134  break;
135  }
136  }
137  }
138  else if( !strncasecmp( line, "Element", strlen( "Element" ) ) )
139  {
140  file_type = IO_MGR::GEDA_PCB;
141  *aName = aFileName.GetName();
142  }
143  else
144  {
145  file_type = IO_MGR::FILE_TYPE_NONE;
146  }
147 
148  return file_type;
149 }
150 
151 
158 static FOOTPRINT* parse_footprint_with_plugin( const wxFileName& aFileName,
159  IO_MGR::PCB_FILE_T aFileType,
160  const wxString& aName )
161 {
162  wxString path;
163 
164  switch( aFileType )
165  {
166  case IO_MGR::GEDA_PCB: path = aFileName.GetPath(); break;
167  case IO_MGR::LEGACY: path = aFileName.GetFullPath(); break;
168  default: wxFAIL_MSG( wxT( "unexpected IO_MGR::PCB_FILE_T" ) ); break;
169  }
170 
171  PLUGIN::RELEASER pi( IO_MGR::PluginFind( aFileType ) );
172 
173  return pi->FootprintLoad( path, aName );
174 }
175 
176 
181 static FOOTPRINT* parse_footprint_kicad( const wxFileName& aFileName )
182 {
183  wxString fcontents;
184  PCB_IO pcb_io;
185  wxFFile f( aFileName.GetFullPath() );
186 
187  if( !f.IsOpened() )
188  return nullptr;
189 
190  f.ReadAll( &fcontents );
191 
192  return dynamic_cast<FOOTPRINT*>( pcb_io.Parse( fcontents ) );
193 }
194 
195 
202 FOOTPRINT* try_load_footprint( const wxFileName& aFileName, IO_MGR::PCB_FILE_T aFileType,
203  const wxString& aName )
204 {
205  FOOTPRINT* footprint;
206 
207  switch( aFileType )
208  {
209  case IO_MGR::GEDA_PCB:
210  case IO_MGR::LEGACY:
211  footprint = parse_footprint_with_plugin( aFileName, aFileType, aName );
212  break;
213 
214  case IO_MGR::KICAD_SEXP:
215  footprint = parse_footprint_kicad( aFileName );
216  break;
217 
218  default:
219  wxFAIL_MSG( wxT( "unexpected IO_MGR::PCB_FILE_T" ) );
220  footprint = nullptr;
221  }
222 
223  return footprint;
224 }
225 
226 
228 {
229  wxString lastOpenedPathForLoading = m_mruPath;
231 
232  if( !cfg->m_LastImportExportPath.empty() )
233  lastOpenedPathForLoading = cfg->m_LastImportExportPath;
234 
235  wxFileName fn;
236 
237  if( aName != wxT("") )
238  fn = aName;
239  else
240  fn = getFootprintFilenameFromUser( this, lastOpenedPathForLoading );
241 
242  if( !fn.IsOk() )
243  return nullptr;
244 
245  FILE* fp = wxFopen( fn.GetFullPath(), wxT( "rt" ) );
246 
247  if( !fp )
248  {
249  wxString msg = wxString::Format( _( "File '%s' not found." ), fn.GetFullPath() );
250  DisplayError( this, msg );
251  return nullptr;
252  }
253 
254  cfg->m_LastImportExportPath = lastOpenedPathForLoading;
255 
256  wxString footprintName;
257  IO_MGR::PCB_FILE_T fileType = detect_file_type( fp, fn.GetFullPath(), &footprintName );
258 
260  {
261  DisplayError( this, _( "Not a footprint file." ) );
262  return nullptr;
263  }
264 
265  FOOTPRINT* footprint = nullptr;
266 
267  try
268  {
269  footprint = try_load_footprint( fn, fileType, footprintName );
270 
271  if( !footprint )
272  {
273  wxString msg = wxString::Format( _( "Unable to load footprint '%s' from '%s'" ),
274  footprintName,
275  fn.GetFullPath() );
276  DisplayError( this, msg );
277  return nullptr;
278  }
279  }
280  catch( const IO_ERROR& ioe )
281  {
282  DisplayError( this, ioe.What() );
283 
284  // if the footprint is not loaded, exit.
285  // However, even if an error happens, it can be loaded, because in KICAD and GPCB format,
286  // a fp library is a set of separate files, and the error(s) are not necessary when
287  // reading the selected file
288 
289  if( !footprint )
290  return nullptr;
291  }
292 
293  footprint->SetFPID( LIB_ID( wxEmptyString, footprintName ) );
294 
295  // Insert footprint in list
296  AddFootprintToBoard( footprint );
297 
298  // Display info :
299  SetMsgPanel( footprint );
300  PlaceFootprint( footprint );
301 
302  footprint->SetPosition( wxPoint( 0, 0 ) );
303 
305  UpdateView();
306 
307  return footprint;
308 }
309 
310 
312 {
313  wxFileName fn;
315 
316  if( !aFootprint )
317  return;
318 
319  fn.SetName( aFootprint->GetFPID().GetLibItemName() );
320 
321  wxString wildcard = KiCadFootprintLibFileWildcard();
322 
323  fn.SetExt( KiCadFootprintFileExtension );
324 
325  if( !cfg->m_LastImportExportPath.empty() )
326  fn.SetPath( cfg->m_LastImportExportPath );
327  else
328  fn.SetPath( m_mruPath );
329 
330  wxFileDialog dlg( this, _( "Export Footprint" ), fn.GetPath(), fn.GetFullName(),
331  wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
332 
333  if( dlg.ShowModal() == wxID_CANCEL )
334  return;
335 
336  fn = dlg.GetPath();
337  cfg->m_LastImportExportPath = fn.GetPath();
338 
339  try
340  {
341  // Export as *.kicad_pcb format, using a strategy which is specifically chosen
342  // as an example on how it could also be used to send it to the system clipboard.
343 
344  PCB_IO pcb_io( CTL_FOR_LIBRARY );
345 
346  /* This footprint should *already* be "normalized" in a way such that
347  orientation is zero, etc., since it came from the Footprint Editor.
348 
349  aFootprint->SetParent( 0 );
350  aFootprint->SetOrientation( 0 );
351  */
352 
353  pcb_io.Format( aFootprint );
354 
355  FILE* fp = wxFopen( dlg.GetPath(), wxT( "wt" ) );
356 
357  if( fp == nullptr )
358  {
359  wxMessageBox( wxString::Format( _( "Insufficient permissions to write file '%s'." ),
360  dlg.GetPath() ) );
361  return;
362  }
363 
364  fprintf( fp, "%s", pcb_io.GetStringOutput( false ).c_str() );
365  fclose( fp );
366  }
367  catch( const IO_ERROR& ioe )
368  {
369  DisplayError( this, ioe.What() );
370  return;
371  }
372 
373  wxString msg = wxString::Format( _( "Footprint exported to file '%s'." ), dlg.GetPath() );
374  DisplayInfoMessage( this, msg );
375 }
376 
377 
378 wxString PCB_BASE_EDIT_FRAME::CreateNewProjectLibrary( const wxString& aLibName,
379  const wxString& aProposedName )
380 {
381  return createNewLibrary( aLibName, aProposedName, Prj().PcbFootprintLibs() );
382 }
383 
384 
385 wxString PCB_BASE_EDIT_FRAME::CreateNewLibrary( const wxString& aLibName,
386  const wxString& aProposedName )
387 {
388  FP_LIB_TABLE* table = selectLibTable();
389 
390  return createNewLibrary( aLibName, aProposedName, table );
391 }
392 
393 
394 wxString PCB_BASE_EDIT_FRAME::createNewLibrary( const wxString& aLibName,
395  const wxString& aProposedName,
396  FP_LIB_TABLE* aTable )
397 {
398  // Kicad cannot write legacy format libraries, only .pretty new format because the legacy
399  // format cannot handle current features.
400  // The footprint library is actually a directory.
401 
402  if( aTable == nullptr )
403  return wxEmptyString;
404 
405  wxString initialPath = aProposedName.IsEmpty() ? Prj().GetProjectPath() : aProposedName;
406  wxFileName fn;
407  bool doAdd = false;
408  bool isGlobal = ( aTable == &GFootprintTable );
409 
410  if( aLibName.IsEmpty() )
411  {
412  fn = initialPath;
413 
415  KiCadFootprintLibPathExtension, false, isGlobal,
417  {
418  return wxEmptyString;
419  }
420 
421  doAdd = true;
422  }
423  else
424  {
425  fn = aLibName;
426 
427  if( !fn.IsAbsolute() )
428  {
429  fn.SetName( aLibName );
430  fn.MakeAbsolute( initialPath );
431  }
432 
433  // Enforce the .pretty extension:
434  fn.SetExt( KiCadFootprintLibPathExtension );
435  }
436 
437  // We can save fp libs only using IO_MGR::KICAD_SEXP format (.pretty libraries)
439  wxString libPath = fn.GetFullPath();
440 
441  try
442  {
443  PLUGIN::RELEASER pi( IO_MGR::PluginFind( piType ) );
444 
445  bool writable = false;
446  bool exists = false;
447 
448  try
449  {
450  writable = pi->IsFootprintLibWritable( libPath );
451  exists = true; // no exception was thrown, lib must exist.
452  }
453  catch( const IO_ERROR& )
454  {
455  // best efforts....
456  }
457 
458  if( exists )
459  {
460  if( !writable )
461  {
462  wxString msg = wxString::Format( _( "Library %s is read only." ), libPath );
463  ShowInfoBarError( msg );
464  return wxEmptyString;
465  }
466  else
467  {
468  wxString msg = wxString::Format( _( "Library %s already exists." ), libPath );
469  KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
470  dlg.SetOKLabel( _( "Overwrite" ) );
471  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
472 
473  if( dlg.ShowModal() == wxID_CANCEL )
474  return wxEmptyString;
475 
476  pi->FootprintLibDelete( libPath );
477  }
478  }
479 
480  pi->FootprintLibCreate( libPath );
481  }
482  catch( const IO_ERROR& ioe )
483  {
484  DisplayError( this, ioe.What() );
485  return wxEmptyString;
486  }
487 
488  if( doAdd )
489  AddLibrary( libPath, aTable );
490 
491  return libPath;
492 }
493 
494 
496 {
497  // If no project is loaded, always work with the global table
498  if( Prj().IsNullProject() )
499  {
501 
502  if( aOptional )
503  {
504  wxMessageDialog dlg( this, _( "Add the library to the global library table?" ),
505  _( "Add To Global Library Table" ), wxYES_NO );
506 
507  if( dlg.ShowModal() != wxID_OK )
508  ret = nullptr;
509  }
510 
511  return ret;
512  }
513 
514  wxArrayString libTableNames;
515  libTableNames.Add( _( "Global" ) );
516  libTableNames.Add( _( "Project" ) );
517 
518  wxSingleChoiceDialog dlg( this, _( "Choose the Library Table to add the library to:" ),
519  _( "Add To Library Table" ), libTableNames );
520 
521  if( aOptional )
522  {
523  dlg.FindWindow( wxID_CANCEL )->SetLabel( _( "Skip" ) );
524  dlg.FindWindow( wxID_OK )->SetLabel( _( "Add" ) );
525  }
526 
527  if( dlg.ShowModal() != wxID_OK )
528  return nullptr;
529 
530  switch( dlg.GetSelection() )
531  {
532  case 0: return &GFootprintTable;
533  case 1: return Prj().PcbFootprintLibs();
534  default: return nullptr;
535  }
536 }
537 
538 
539 bool PCB_BASE_EDIT_FRAME::AddLibrary( const wxString& aFilename, FP_LIB_TABLE* aTable )
540 {
541  if( aTable == nullptr )
542  aTable = selectLibTable();
543 
544  if( aTable == nullptr )
545  return wxEmptyString;
546 
547  bool isGlobal = ( aTable == &GFootprintTable );
548 
549  wxFileName fn( aFilename );
550 
551  if( aFilename.IsEmpty() )
552  {
554  KiCadFootprintLibPathExtension, true, isGlobal,
556  {
557  return false;
558  }
559  }
560 
561  wxString libPath = fn.GetFullPath();
562  wxString libName = fn.GetName();
563 
564  if( libName.IsEmpty() )
565  return false;
566 
567  wxString type = IO_MGR::ShowType( IO_MGR::GuessPluginTypeFromLibPath( libPath ) );
568 
569  // try to use path normalized to an environmental variable or project path
570  wxString normalizedPath = NormalizePath( libPath, &Pgm().GetLocalEnvVariables(), &Prj() );
571 
572  if( normalizedPath.IsEmpty() )
573  normalizedPath = libPath;
574 
575  try
576  {
577  FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libName, normalizedPath, type, wxEmptyString );
578  aTable->InsertRow( row );
579 
580  if( isGlobal )
582  else
583  Prj().PcbFootprintLibs()->Save( Prj().FootprintLibTblName() );
584  }
585  catch( const IO_ERROR& ioe )
586  {
587  DisplayError( this, ioe.What() );
588  return false;
589  }
590 
592 
593  if( editor )
594  {
595  LIB_ID libID( libName, wxEmptyString );
596  editor->SyncLibraryTree( true );
597  editor->FocusOnLibID( libID );
598  }
599 
600  auto viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_VIEWER, false );
601 
602  if( viewer )
603  viewer->ReCreateLibraryList();
604 
605  return true;
606 }
607 
608 
609 bool FOOTPRINT_EDIT_FRAME::DeleteFootprintFromLibrary( const LIB_ID& aFPID, bool aConfirm )
610 {
611  if( !aFPID.IsValid() )
612  return false;
613 
614  wxString nickname = aFPID.GetLibNickname();
615  wxString fpname = aFPID.GetLibItemName();
616 
617  // Legacy libraries are readable, but modifying legacy format is not allowed
618  // So prompt the user if he try to delete a footprint from a legacy lib
619  wxString libfullname = Prj().PcbFootprintLibs()->FindRow( nickname )->GetFullURI();
620 
621  if( IO_MGR::GuessPluginTypeFromLibPath( libfullname ) == IO_MGR::LEGACY )
622  {
624  return false;
625  }
626 
627  if( !Prj().PcbFootprintLibs()->IsFootprintLibWritable( nickname ) )
628  {
629  wxString msg = wxString::Format( _( "Library '%s' is read only." ), nickname );
630  ShowInfoBarError( msg );
631  return false;
632  }
633 
634  // Confirmation
635  wxString msg = wxString::Format( _( "Delete footprint '%s' from library '%s'?" ),
636  fpname.GetData(),
637  nickname.GetData() );
638 
639  if( aConfirm && !IsOK( this, msg ) )
640  return false;
641 
642  try
643  {
644  Prj().PcbFootprintLibs()->FootprintDelete( nickname, fpname );
645  }
646  catch( const IO_ERROR& ioe )
647  {
648  DisplayError( this, ioe.What() );
649  return false;
650  }
651 
652  msg.Printf( _( "Footprint '%s' deleted from library '%s'" ),
653  fpname.GetData(),
654  nickname.GetData() );
655 
656  SetStatusText( msg );
657 
658  return true;
659 }
660 
661 
662 void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxString& aLibName,
663  wxString* aLibPath )
664 {
665  if( GetBoard()->GetFirstFootprint() == nullptr )
666  {
667  DisplayInfoMessage( this, _( "No footprints to export!" ) );
668  return;
669  }
670 
671  wxString footprintName;
672 
673  auto resetReference =
674  []( FOOTPRINT* aFootprint )
675  {
676  aFootprint->SetReference( "REF**" );
677  };
678 
679  if( !aStoreInNewLib )
680  {
681  // The footprints are saved in an existing .pretty library in the fp lib table
682  PROJECT& prj = Prj();
683  wxString last_nickname = prj.GetRString( PROJECT::PCB_LIB_NICKNAME );
684  wxString nickname = SelectLibrary( last_nickname );
685 
686  if( !nickname ) // Aborted
687  return;
688 
689  bool map = IsOK( this, wxString::Format( _( "Update footprints on board to refer to %s?" ),
690  nickname ) );
691 
692  prj.SetRString( PROJECT::PCB_LIB_NICKNAME, nickname );
693 
694  for( FOOTPRINT* footprint : GetBoard()->Footprints() )
695  {
696  try
697  {
698  FP_LIB_TABLE* tbl = prj.PcbFootprintLibs();
699 
700  if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
701  {
702  FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
703 
704  resetReference( fpCopy );
705  tbl->FootprintSave( nickname, fpCopy, true );
706 
707  delete fpCopy;
708  }
709  }
710  catch( const IO_ERROR& ioe )
711  {
712  DisplayError( this, ioe.What() );
713  }
714 
715  if( map )
716  {
717  LIB_ID id = footprint->GetFPID();
718  id.SetLibNickname( nickname );
719  footprint->SetFPID( id );
720  }
721  }
722  }
723  else
724  {
725  // The footprints are saved in a new .pretty library.
726  // If this library already exists, all previous footprints will be deleted
727  wxString libPath = CreateNewLibrary( aLibName );
728 
729  if( libPath.IsEmpty() ) // Aborted
730  return;
731 
732  if( aLibPath )
733  *aLibPath = libPath;
734 
735  wxString libNickname;
736  bool map = IsOK( this, _( "Update footprints on board to refer to new library?" ) );
737 
738  if( map )
739  {
740  const LIB_TABLE_ROW* row = Prj().PcbFootprintLibs()->FindRowByURI( libPath );
741 
742  if( row )
743  libNickname = row->GetNickName();
744  }
745 
747  PLUGIN::RELEASER pi( IO_MGR::PluginFind( piType ) );
748 
749  for( FOOTPRINT* footprint : GetBoard()->Footprints() )
750  {
751  try
752  {
753  if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
754  {
755  FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
756 
757  resetReference( fpCopy );
758  pi->FootprintSave( libPath, fpCopy );
759 
760  delete fpCopy;
761  }
762  }
763  catch( const IO_ERROR& ioe )
764  {
765  DisplayError( this, ioe.What() );
766  }
767 
768  if( map )
769  {
770  LIB_ID id = footprint->GetFPID();
771  id.SetLibNickname( libNickname );
772  footprint->SetFPID( id );
773  }
774  }
775  }
776 }
777 
778 
780 {
781  if( !aFootprint ) // Happen if no footprint loaded
782  return false;
783 
784  wxString libraryName = aFootprint->GetFPID().GetLibNickname();
785  wxString footprintName = aFootprint->GetFPID().GetLibItemName();
786  bool nameChanged = m_footprintNameWhenLoaded != footprintName;
787 
788  if( aFootprint->GetLink() != niluuid )
789  {
790  if( SaveFootprintToBoard( false ) )
791  {
792  m_footprintNameWhenLoaded = footprintName;
793  return true;
794  }
795  else
796  {
797  return false;
798  }
799  }
800  else if( libraryName.IsEmpty() || footprintName.IsEmpty() )
801  {
802  if( SaveFootprintAs( aFootprint ) )
803  {
804  m_footprintNameWhenLoaded = footprintName;
805  SyncLibraryTree( true );
806  return true;
807  }
808  else
809  {
810  return false;
811  }
812  }
813 
814  FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs();
815 
816  // Legacy libraries are readable, but modifying legacy format is not allowed
817  // So prompt the user if he try to add/replace a footprint in a legacy lib
818  wxString libfullname = tbl->FindRow( libraryName )->GetFullURI();
819 
820  if( IO_MGR::GuessPluginTypeFromLibPath( libfullname ) == IO_MGR::LEGACY )
821  {
823  return false;
824  }
825 
826  if( nameChanged )
827  {
828  LIB_ID oldFPID( libraryName, m_footprintNameWhenLoaded );
829  DeleteFootprintFromLibrary( oldFPID, false );
830  }
831 
832  if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
833  return false;
834 
835  if( nameChanged )
836  {
837  m_footprintNameWhenLoaded = footprintName;
838  SyncLibraryTree( true );
839  }
840 
841  return true;
842 }
843 
844 
846  const wxString& aLibraryName )
847 {
848  try
849  {
850  aFootprint->SetFPID( LIB_ID( wxEmptyString, aFootprint->GetFPID().GetLibItemName() ) );
851 
852  Prj().PcbFootprintLibs()->FootprintSave( aLibraryName, aFootprint );
853 
854  aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
855  return true;
856  }
857  catch( const IO_ERROR& ioe )
858  {
859  DisplayError( this, ioe.What() );
860 
861  aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
862  return false;
863  }
864 }
865 
866 
868 {
869  // update footprint in the current board,
870  // not just add it to the board with total disregard for the netlist...
871  PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB_EDITOR, false );
872 
873  if( pcbframe == nullptr ) // happens when the board editor is not active (or closed)
874  {
875  ShowInfoBarError( _( "No board currently open." ) );
876  return false;
877  }
878 
879  BOARD* mainpcb = pcbframe->GetBoard();
880  FOOTPRINT* sourceFootprint = nullptr;
881  FOOTPRINT* editorFootprint = GetBoard()->GetFirstFootprint();
882 
883  // Search the old footprint (source) if exists
884  // Because this source could be deleted when editing the main board...
885  if( editorFootprint->GetLink() != niluuid ) // this is not a new footprint ...
886  {
887  sourceFootprint = nullptr;
888 
889  for( FOOTPRINT* candidate : mainpcb->Footprints() )
890  {
891  if( editorFootprint->GetLink() == candidate->m_Uuid )
892  {
893  sourceFootprint = candidate;
894  break;
895  }
896  }
897  }
898 
899  if( !aAddNew && sourceFootprint == nullptr ) // source not found
900  {
901  DisplayError( this, _( "Unable to find the footprint on the main board.\nCannot save." ) );
902  return false;
903  }
904 
907  BOARD_COMMIT commit( pcbframe );
908 
909  // Create a copy for the board, first using Clone() to keep existing Uuids, and then either
910  // resetting the uuids to the board values or assigning new Uuids.
911  FOOTPRINT* newFootprint = static_cast<FOOTPRINT*>( editorFootprint->Clone() );
912  newFootprint->SetParent( mainpcb );
913  newFootprint->SetLink( niluuid );
914 
915  auto fixUuid =
916  [&]( KIID& aUuid )
917  {
918  if( editorFootprint->GetLink() != niluuid && m_boardFootprintUuids.count( aUuid ) )
919  aUuid = m_boardFootprintUuids[ aUuid ];
920  else
921  aUuid = KIID();
922  };
923 
924  fixUuid( const_cast<KIID&>( newFootprint->m_Uuid ) );
925  newFootprint->RunOnChildren(
926  [&]( BOARD_ITEM* aChild )
927  {
928  fixUuid( const_cast<KIID&>( aChild->m_Uuid ) );
929  } );
930 
931  if( sourceFootprint ) // this is an update command
932  {
933  // In the main board the new footprint replaces the old one (pos, orient, ref, value,
934  // connections and properties are kept) and the sourceFootprint (old footprint) is
935  // deleted
936  pcbframe->ExchangeFootprint( sourceFootprint, newFootprint, commit );
937  commit.Push( wxT( "Update footprint" ) );
938  }
939  else // This is an insert command
940  {
941  KIGFX::VIEW_CONTROLS* viewControls = pcbframe->GetCanvas()->GetViewControls();
942  VECTOR2D cursorPos = viewControls->GetCursorPosition();
943 
944  commit.Add( newFootprint );
945  viewControls->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
946  pcbframe->PlaceFootprint( newFootprint );
947  newFootprint->SetPosition( wxPoint( 0, 0 ) );
948  viewControls->SetCrossHairCursorPosition( cursorPos, false );
949  const_cast<KIID&>( newFootprint->m_Uuid ) = KIID();
950  commit.Push( wxT( "Insert footprint" ) );
951 
952  pcbframe->Raise();
953  pcbframe->GetToolManager()->RunAction( PCB_ACTIONS::placeFootprint, true, newFootprint );
954  }
955 
956  newFootprint->ClearFlags();
957 
958  return true;
959 }
960 
961 
963 {
964  if( aFootprint == nullptr )
965  return false;
966 
967  FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs();
968 
969  SetMsgPanel( aFootprint );
970 
971  wxString libraryName = aFootprint->GetFPID().GetLibNickname();
972  wxString footprintName = aFootprint->GetFPID().GetLibItemName();
973  bool updateValue = aFootprint->GetValue() == footprintName;
974 
975  wxArrayString headers;
976  std::vector<wxArrayString> itemsToDisplay;
977  std::vector<wxString> nicknames = tbl->GetLogicalLibs();
978 
979  headers.Add( _( "Nickname" ) );
980  headers.Add( _( "Description" ) );
981 
982  for( const wxString& nickname : nicknames )
983  {
984  wxArrayString item;
985  item.Add( nickname );
986  item.Add( tbl->GetDescription( nickname ) );
987  itemsToDisplay.push_back( item );
988  }
989 
990  EDA_LIST_DIALOG dlg( this, _( "Save Footprint As" ), headers, itemsToDisplay, libraryName );
991  dlg.SetListLabel( _( "Save in library:" ) );
992  dlg.SetOKLabel( _( "Save" ) );
993 
994  wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
995 
996  wxStaticText* label = new wxStaticText( &dlg, wxID_ANY, _( "Name:" ),
997  wxDefaultPosition, wxDefaultSize, 0 );
998  bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
999 
1000  wxTextCtrl* nameTextCtrl = new wxTextCtrl( &dlg, wxID_ANY, footprintName,
1001  wxDefaultPosition, wxDefaultSize, 0 );
1002  bNameSizer->Add( nameTextCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
1003 
1004  wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST );
1005  nameValidator.SetCharExcludes( FOOTPRINT::StringLibNameInvalidChars( false ) );
1006  nameTextCtrl->SetValidator( nameValidator );
1007 
1008  wxSizer* mainSizer = dlg.GetSizer();
1009  mainSizer->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
1010 
1011  // Move nameTextCtrl to the head of the tab-order
1012  if( dlg.GetChildren().DeleteObject( nameTextCtrl ) )
1013  dlg.GetChildren().Insert( nameTextCtrl );
1014 
1015  dlg.SetInitialFocus( nameTextCtrl );
1016 
1017  dlg.Layout();
1018  mainSizer->Fit( &dlg );
1019 
1020  if( dlg.ShowModal() != wxID_OK )
1021  return false; // canceled by user
1022 
1023  libraryName = dlg.GetTextSelection();
1024 
1025  if( libraryName.IsEmpty() )
1026  {
1027  DisplayError( this, _( "No library specified. Footprint could not be saved." ) );
1028  return false;
1029  }
1030 
1031  footprintName = nameTextCtrl->GetValue();
1032  footprintName.Trim( true );
1033  footprintName.Trim( false );
1034 
1035  if( footprintName.IsEmpty() )
1036  {
1037  DisplayError( this, _( "No footprint name specified. Footprint could not be saved." ) );
1038  return false;
1039  }
1040 
1041  aFootprint->SetFPID( LIB_ID( libraryName, footprintName ) );
1042 
1043  if( updateValue )
1044  aFootprint->SetValue( footprintName );
1045 
1046  // Legacy libraries are readable, but modifying legacy format is not allowed
1047  // So prompt the user if he try to add/replace a footprint in a legacy lib
1048  wxString libfullname = Prj().PcbFootprintLibs()->FindRow( libraryName )->GetFullURI();
1050 
1051  if( piType == IO_MGR::LEGACY )
1052  {
1054  return false;
1055  }
1056 
1057  bool footprintExists = tbl->FootprintExists( libraryName, footprintName );
1058 
1059  if( footprintExists )
1060  {
1061  wxString msg = wxString::Format( _( "Footprint %s already exists in %s." ),
1062  footprintName,
1063  libraryName );
1064  KIDIALOG chkdlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1065  chkdlg.SetOKLabel( _( "Overwrite" ) );
1066 
1067  if( chkdlg.ShowModal() == wxID_CANCEL )
1068  return false;
1069  }
1070 
1071  if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
1072  return false;
1073 
1074  // Once saved-as a board footprint is no longer a board footprint
1075  aFootprint->SetLink( niluuid );
1076 
1077  wxString fmt = footprintExists ? _( "Footprint '%s' replaced in '%s'" )
1078  : _( "Footprint '%s' added to '%s'" );
1079 
1080  wxString msg = wxString::Format( fmt, footprintName.GetData(), libraryName.GetData() );
1081  SetStatusText( msg );
1082  UpdateTitle();
1083  ReCreateHToolbar();
1084 
1085  return true;
1086 }
1087 
1088 
1090 {
1092  {
1093  wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1094  GetLoadedFPID().GetLibItemName().wx_str() );
1095 
1096  if( ConfirmRevertDialog( this, msg ) )
1097  {
1098  Clear_Pcb( false );
1099  AddFootprintToBoard( static_cast<FOOTPRINT*>( m_revertModule->Clone() ) );
1100 
1101  Zoom_Automatique( false );
1102 
1103  Update3DView( true, true );
1104 
1106  GetScreen()->SetContentModified( false );
1107 
1108  UpdateView();
1109  GetCanvas()->Refresh();
1110 
1111  return true;
1112  }
1113  }
1114 
1115  return false;
1116 }
1117 
1118 
1119 FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( const wxString& aFootprintName )
1120 {
1121  wxString footprintName = aFootprintName;
1122 
1123  // Ask for the new footprint name
1124  if( footprintName.IsEmpty() )
1125  {
1126  WX_TEXT_ENTRY_DIALOG dlg( this, _( "Enter footprint name:" ), _( "New Footprint" ),
1127  footprintName );
1128  dlg.SetTextValidator( FOOTPRINT_NAME_VALIDATOR( &footprintName ) );
1129 
1130  if( dlg.ShowModal() != wxID_OK )
1131  return nullptr; //Aborted by user
1132  }
1133 
1134  footprintName.Trim( true );
1135  footprintName.Trim( false );
1136 
1137  if( footprintName.IsEmpty() )
1138  {
1139  DisplayInfoMessage( this, _( "No footprint name defined." ) );
1140  return nullptr;
1141  }
1142 
1143  // Creates the new footprint and add it to the head of the linked list of footprints
1144  FOOTPRINT* footprint = new FOOTPRINT( GetBoard() );
1145 
1146  // Update parameters: timestamp ...
1147  footprint->SetLastEditTime();
1148 
1149  // Update its name in lib
1150  footprint->SetFPID( LIB_ID( wxEmptyString, footprintName ) );
1151 
1152  PCB_LAYER_ID txt_layer;
1153  wxPoint default_pos;
1155 
1156  footprint->Reference().SetText( settings.m_DefaultFPTextItems[0].m_Text );
1157  footprint->Reference().SetVisible( settings.m_DefaultFPTextItems[0].m_Visible );
1158  txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[0].m_Layer;
1159  footprint->Reference().SetLayer( txt_layer );
1160  default_pos.y -= settings.GetTextSize( txt_layer ).y / 2;
1161  footprint->Reference().SetPosition( default_pos );
1162  default_pos.y += settings.GetTextSize( txt_layer ).y;
1163 
1164  footprint->Value().SetText( settings.m_DefaultFPTextItems[1].m_Text );
1165  footprint->Value().SetVisible( settings.m_DefaultFPTextItems[1].m_Visible );
1166  txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[1].m_Layer;
1167  footprint->Value().SetLayer( txt_layer );
1168  default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1169  footprint->Value().SetPosition( default_pos );
1170  default_pos.y += settings.GetTextSize( txt_layer ).y;
1171 
1172  for( size_t i = 2; i < settings.m_DefaultFPTextItems.size(); ++i )
1173  {
1174  FP_TEXT* textItem = new FP_TEXT( footprint );
1175  textItem->SetText( settings.m_DefaultFPTextItems[i].m_Text );
1176  textItem->SetVisible( settings.m_DefaultFPTextItems[i].m_Visible );
1177  txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[i].m_Layer;
1178  textItem->SetLayer( txt_layer );
1179  default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1180  textItem->SetPosition( default_pos );
1181  default_pos.y += settings.GetTextSize( txt_layer ).y;
1182  footprint->GraphicalItems().push_back( textItem );
1183  }
1184 
1185  if( footprint->GetReference().IsEmpty() )
1186  footprint->SetReference( footprintName );
1187 
1188  if( footprint->GetValue().IsEmpty() )
1189  footprint->SetValue( footprintName );
1190 
1191  footprint->RunOnChildren(
1192  [&] ( BOARD_ITEM* aChild )
1193  {
1194  if( aChild->Type() == PCB_FP_TEXT_T )
1195  {
1196  FP_TEXT* textItem = static_cast<FP_TEXT*>( aChild );
1197  PCB_LAYER_ID layer = textItem->GetLayer();
1198 
1199  textItem->SetTextThickness( settings.GetTextThickness( layer ) );
1200  textItem->SetTextSize( settings.GetTextSize( layer ) );
1201  textItem->SetItalic( settings.GetTextItalic( layer ) );
1202  textItem->SetKeepUpright( settings.GetTextUpright( layer ) );
1203  }
1204  } );
1205 
1206  SetMsgPanel( footprint );
1207  return footprint;
1208 }
1209 
1210 
1211 wxString PCB_BASE_FRAME::SelectLibrary( const wxString& aNicknameExisting )
1212 {
1213  wxArrayString headers;
1214 
1215  headers.Add( _( "Nickname" ) );
1216  headers.Add( _( "Description" ) );
1217 
1218  FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs();
1219 
1220  std::vector< wxArrayString > itemsToDisplay;
1221  std::vector< wxString > nicknames = fptbl->GetLogicalLibs();
1222 
1223  for( const wxString& nickname : nicknames )
1224  {
1225  wxArrayString item;
1226 
1227  item.Add( nickname );
1228  item.Add( fptbl->GetDescription( nickname ) );
1229 
1230  itemsToDisplay.push_back( item );
1231  }
1232 
1233  EDA_LIST_DIALOG dlg( this, _( "Select Library" ), headers, itemsToDisplay, aNicknameExisting );
1234 
1235  if( dlg.ShowModal() != wxID_OK )
1236  return wxEmptyString;
1237 
1238  return dlg.GetTextSelection();
1239 }
void SetReference(const wxString &aReference)
Definition: footprint.h:439
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:271
void BuildListOfNets()
Definition: board.h:663
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:220
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.
BOARD_ITEM * Parse(const wxString &aClipboardSourceInput)
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.
A PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
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:452
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:192
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:80
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.
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:179
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
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:382
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:237
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
#define CTL_FOR_LIBRARY
Format output for a footprint library instead of clipboard or BOARD.
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
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:116
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:466
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:467
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...
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:185
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:317
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:114
VECTOR2< double > VECTOR2D
Definition: vector2d.h:622
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.
std::string GetStringOutput(bool doClear)
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:233
char * StrPurge(char *text)
Remove leading and training spaces, tabs and end of line chars in text.
wxString ModLegacyExportFileWildcard()
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:430
#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:154
DRAWINGS & GraphicalItems()
Definition: footprint.h:171
const LIB_ID & GetFPID() const
Definition: footprint.h:194
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:460
FormatType fileType(const char *aFileName)
Definition: loadmodel.cpp:275
std::unique_ptr< FOOTPRINT > m_revertModule
#define FOOTPRINT_LIBRARY_HEADER_CNT
Definition: legacy_plugin.h:39
KIID GetLink() const
Definition: footprint.h:536
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
const KIID m_Uuid
Definition: eda_item.h:475
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
FOOTPRINT * CreateNewFootprint(const wxString &aFootprintName)
Creates a new footprint, at position 0,0.
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:195
void SetKeepUpright(bool aKeepUpright)
Definition: fp_text.h:115
void SetLink(const KIID &aLink)
Definition: footprint.h:537
void Format(const BOARD_ITEM *aItem, int aNestLevel=0) const
Output aItem to aFormatter in s-expression format.
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:160
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.
LIB_ID GetLoadedFPID() const
Return the LIB_ID of the part being edited.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
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:64
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:334
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:1236
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:159
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:1499
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:1230
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:299
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:171
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:315
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:1381
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.
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:113
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)