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