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