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