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