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 wxMessageBox( 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;
574
575 wxString type = IO_MGR::ShowType( IO_MGR::GuessPluginTypeFromLibPath( libPath ) );
576
577 // try to use path normalized to an environmental variable or project path
578 wxString normalizedPath = NormalizePath( libPath, &Pgm().GetLocalEnvVariables(), &Prj() );
579
580 try
581 {
582 FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libName, normalizedPath, type, wxEmptyString );
583 aTable->InsertRow( row );
584
585 if( isGlobal )
587 else
588 Prj().PcbFootprintLibs()->Save( Prj().FootprintLibTblName() );
589 }
590 catch( const IO_ERROR& ioe )
591 {
592 DisplayError( this, ioe.What() );
593 return false;
594 }
595
597
598 if( editor )
599 {
600 LIB_ID libID( libName, wxEmptyString );
601 editor->SyncLibraryTree( true );
602 editor->FocusOnLibID( libID );
603 }
604
605 auto viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_VIEWER, false );
606
607 if( viewer )
608 viewer->ReCreateLibraryList();
609
610 return true;
611}
612
613
615{
616 if( !aFPID.IsValid() )
617 return false;
618
619 wxString nickname = aFPID.GetLibNickname();
620 wxString fpname = aFPID.GetLibItemName();
621
622 // Legacy libraries are readable, but modifying legacy format is not allowed
623 // So prompt the user if he try to delete a footprint from a legacy lib
624 wxString libfullname = Prj().PcbFootprintLibs()->FindRow( nickname )->GetFullURI();
625
627 {
629 return false;
630 }
631
632 if( !Prj().PcbFootprintLibs()->IsFootprintLibWritable( nickname ) )
633 {
634 wxString msg = wxString::Format( _( "Library '%s' is read only." ), nickname );
635 ShowInfoBarError( msg );
636 return false;
637 }
638
639 // Confirmation
640 wxString msg = wxString::Format( _( "Delete footprint '%s' from library '%s'?" ),
641 fpname.GetData(),
642 nickname.GetData() );
643
644 if( aConfirm && !IsOK( this, msg ) )
645 return false;
646
647 try
648 {
649 Prj().PcbFootprintLibs()->FootprintDelete( nickname, fpname );
650 }
651 catch( const IO_ERROR& ioe )
652 {
653 DisplayError( this, ioe.What() );
654 return false;
655 }
656
657 msg.Printf( _( "Footprint '%s' deleted from library '%s'" ),
658 fpname.GetData(),
659 nickname.GetData() );
660
661 SetStatusText( msg );
662
663 return true;
664}
665
666
667void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxString& aLibName,
668 wxString* aLibPath )
669{
670 if( GetBoard()->GetFirstFootprint() == nullptr )
671 {
672 DisplayInfoMessage( this, _( "No footprints to export!" ) );
673 return;
674 }
675
676 wxString footprintName;
677
678 auto resetReference =
679 []( FOOTPRINT* aFootprint )
680 {
681 aFootprint->SetReference( "REF**" );
682 };
683
684 if( !aStoreInNewLib )
685 {
686 // The footprints are saved in an existing .pretty library in the fp lib table
687 PROJECT& prj = Prj();
688 wxString last_nickname = prj.GetRString( PROJECT::PCB_LIB_NICKNAME );
689 wxString nickname = SelectLibrary( last_nickname );
690
691 if( !nickname ) // Aborted
692 return;
693
694 bool map = IsOK( this, wxString::Format( _( "Update footprints on board to refer to %s?" ),
695 nickname ) );
696
697 prj.SetRString( PROJECT::PCB_LIB_NICKNAME, nickname );
698
699 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
700 {
701 try
702 {
703 FP_LIB_TABLE* tbl = prj.PcbFootprintLibs();
704
705 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
706 {
707 FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
708
709 resetReference( fpCopy );
710 tbl->FootprintSave( nickname, fpCopy, true );
711
712 delete fpCopy;
713 }
714 }
715 catch( const IO_ERROR& ioe )
716 {
717 DisplayError( this, ioe.What() );
718 }
719
720 if( map )
721 {
722 LIB_ID id = footprint->GetFPID();
723 id.SetLibNickname( nickname );
724 footprint->SetFPID( id );
725 }
726 }
727 }
728 else
729 {
730 // The footprints are saved in a new .pretty library.
731 // If this library already exists, all previous footprints will be deleted
732 wxString libPath = CreateNewLibrary( aLibName );
733
734 if( libPath.IsEmpty() ) // Aborted
735 return;
736
737 if( aLibPath )
738 *aLibPath = libPath;
739
740 wxString libNickname;
741 bool map = IsOK( this, _( "Update footprints on board to refer to new library?" ) );
742
743 if( map )
744 {
745 const LIB_TABLE_ROW* row = Prj().PcbFootprintLibs()->FindRowByURI( libPath );
746
747 if( row )
748 libNickname = row->GetNickName();
749 }
750
752 PLUGIN::RELEASER pi( IO_MGR::PluginFind( piType ) );
753
754 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
755 {
756 try
757 {
758 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
759 {
760 FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
761
762 resetReference( fpCopy );
763 pi->FootprintSave( libPath, fpCopy );
764
765 delete fpCopy;
766 }
767 }
768 catch( const IO_ERROR& ioe )
769 {
770 DisplayError( this, ioe.What() );
771 }
772
773 if( map )
774 {
775 LIB_ID id = footprint->GetFPID();
776 id.SetLibNickname( libNickname );
777 footprint->SetFPID( id );
778 }
779 }
780 }
781}
782
783
785{
786 if( !aFootprint ) // Happen if no footprint loaded
787 return false;
788
789 PAD_TOOL* padTool = m_toolManager->GetTool<PAD_TOOL>();
790
791 if( padTool->InPadEditMode() )
793
794 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
795 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
796 bool nameChanged = m_footprintNameWhenLoaded != footprintName;
797
798 if( aFootprint->GetLink() != niluuid )
799 {
800 if( SaveFootprintToBoard( false ) )
801 {
802 m_footprintNameWhenLoaded = footprintName;
803 return true;
804 }
805 else
806 {
807 return false;
808 }
809 }
810 else if( libraryName.IsEmpty() || footprintName.IsEmpty() )
811 {
812 if( SaveFootprintAs( aFootprint ) )
813 {
814 m_footprintNameWhenLoaded = footprintName;
815 SyncLibraryTree( true );
816 return true;
817 }
818 else
819 {
820 return false;
821 }
822 }
823
825
826 // Legacy libraries are readable, but modifying legacy format is not allowed
827 // So prompt the user if he try to add/replace a footprint in a legacy lib
828 wxString libfullname = tbl->FindRow( libraryName )->GetFullURI();
829
831 {
833 return false;
834 }
835
836 if( nameChanged )
837 {
838 LIB_ID oldFPID( libraryName, m_footprintNameWhenLoaded );
839 DeleteFootprintFromLibrary( oldFPID, false );
840 }
841
842 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
843 return false;
844
845 if( nameChanged )
846 {
847 m_footprintNameWhenLoaded = footprintName;
848 SyncLibraryTree( true );
849 }
850
851 return true;
852}
853
854
856{
857 LIB_ID fpID = aFootprint->GetFPID();
858 wxString libraryName = fpID.GetLibNickname();
859 wxString footprintName = fpID.GetLibItemName();
860
861 // Legacy libraries are readable, but modifying legacy format is not allowed
862 // So prompt the user if he try to add/replace a footprint in a legacy lib
863 wxString libFullName = Prj().PcbFootprintLibs()->FindRow( libraryName )->GetFullURI();
864
866 {
868 return false;
869 }
870
872 int i = 1;
873 wxString newName = footprintName;
874
875 // Append a number to the name until the name is unique in the library.
876 while( tbl->FootprintExists( libraryName, newName ) )
877 newName.Printf( "%s_%d", footprintName, i++ );
878
879 aFootprint->SetFPID( LIB_ID( libraryName, newName ) );
880
881 if( aFootprint->GetValue() == footprintName )
882 aFootprint->SetValue( newName );
883
884 return SaveFootprintInLibrary( aFootprint, libraryName );
885}
886
887
889 const wxString& aLibraryName )
890{
891 try
892 {
893 aFootprint->SetFPID( LIB_ID( wxEmptyString, aFootprint->GetFPID().GetLibItemName() ) );
894
895 Prj().PcbFootprintLibs()->FootprintSave( aLibraryName, aFootprint );
896
897 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
898 return true;
899 }
900 catch( const IO_ERROR& ioe )
901 {
902 DisplayError( this, ioe.What() );
903
904 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
905 return false;
906 }
907}
908
909
911{
912 // update footprint in the current board,
913 // not just add it to the board with total disregard for the netlist...
914 PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB_EDITOR, false );
915
916 if( pcbframe == nullptr ) // happens when the board editor is not active (or closed)
917 {
918 ShowInfoBarError( _( "No board currently open." ) );
919 return false;
920 }
921
922 BOARD* mainpcb = pcbframe->GetBoard();
923 FOOTPRINT* sourceFootprint = nullptr;
924 FOOTPRINT* editorFootprint = GetBoard()->GetFirstFootprint();
925
926 // Search the old footprint (source) if exists
927 // Because this source could be deleted when editing the main board...
928 if( editorFootprint->GetLink() != niluuid ) // this is not a new footprint ...
929 {
930 sourceFootprint = nullptr;
931
932 for( FOOTPRINT* candidate : mainpcb->Footprints() )
933 {
934 if( editorFootprint->GetLink() == candidate->m_Uuid )
935 {
936 sourceFootprint = candidate;
937 break;
938 }
939 }
940 }
941
942 if( !aAddNew && sourceFootprint == nullptr ) // source not found
943 {
944 DisplayError( this, _( "Unable to find the footprint on the main board.\nCannot save." ) );
945 return false;
946 }
947
948 TOOL_MANAGER* pcb_ToolManager = pcbframe->GetToolManager();
949
950 if( aAddNew && pcb_ToolManager->GetTool<BOARD_EDITOR_CONTROL>()->PlacingFootprint() )
951 {
952 DisplayError( this, _( "Previous footprint placement still in progress." ) );
953 return false;
954 }
955
957 BOARD_COMMIT commit( pcbframe );
958
959 // Create a copy for the board, first using Clone() to keep existing Uuids, and then either
960 // resetting the uuids to the board values or assigning new Uuids.
961 FOOTPRINT* newFootprint = static_cast<FOOTPRINT*>( editorFootprint->Clone() );
962 newFootprint->SetParent( mainpcb );
963 newFootprint->SetLink( niluuid );
964
965 auto fixUuid =
966 [&]( KIID& aUuid )
967 {
968 if( editorFootprint->GetLink() != niluuid && m_boardFootprintUuids.count( aUuid ) )
969 aUuid = m_boardFootprintUuids[ aUuid ];
970 else
971 aUuid = KIID();
972 };
973
974 fixUuid( const_cast<KIID&>( newFootprint->m_Uuid ) );
975 newFootprint->RunOnChildren(
976 [&]( BOARD_ITEM* aChild )
977 {
978 fixUuid( const_cast<KIID&>( aChild->m_Uuid ) );
979 } );
980
981 if( sourceFootprint ) // this is an update command
982 {
983 // In the main board the new footprint replaces the old one (pos, orient, ref, value,
984 // connections and properties are kept) and the sourceFootprint (old footprint) is
985 // deleted
986 pcbframe->ExchangeFootprint( sourceFootprint, newFootprint, commit );
987 commit.Push( wxT( "Update footprint" ) );
988 }
989 else // This is an insert command
990 {
991 KIGFX::VIEW_CONTROLS* viewControls = pcbframe->GetCanvas()->GetViewControls();
992 VECTOR2D cursorPos = viewControls->GetCursorPosition();
993
994 commit.Add( newFootprint );
995 viewControls->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
996 pcbframe->PlaceFootprint( newFootprint );
997 newFootprint->SetPosition( wxPoint( 0, 0 ) );
998 viewControls->SetCrossHairCursorPosition( cursorPos, false );
999 const_cast<KIID&>( newFootprint->m_Uuid ) = KIID();
1000 commit.Push( wxT( "Insert footprint" ) );
1001
1002 pcbframe->Raise();
1003 pcb_ToolManager->RunAction( PCB_ACTIONS::placeFootprint, true, newFootprint );
1004 }
1005
1006 newFootprint->ClearFlags();
1007
1008 return true;
1009}
1010
1011
1012static int ID_SAVE_AS_NAME = 4172;
1013static int ID_MAKE_NEW_LIBRARY = 4173;
1014
1015
1017 const wxString& aLibraryPreselect )
1018{
1019 COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
1022 std::vector<wxString> nicknames = tbl->GetLogicalLibs();
1023 wxArrayString headers;
1024 std::vector<wxArrayString> itemsToDisplay;
1025
1026 headers.Add( _( "Nickname" ) );
1027 headers.Add( _( "Description" ) );
1028
1029 for( const wxString& nickname : nicknames )
1030 {
1031 if( alg::contains( project.m_PinnedFootprintLibs, nickname )
1032 || alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1033 {
1034 wxArrayString item;
1035
1036 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
1037 item.Add( tbl->GetDescription( nickname ) );
1038 itemsToDisplay.push_back( item );
1039 }
1040 }
1041
1042 for( const wxString& nickname : nicknames )
1043 {
1044 if( !alg::contains( project.m_PinnedFootprintLibs, nickname )
1045 && !alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1046 {
1047 wxArrayString item;
1048
1049 item.Add( nickname );
1050 item.Add( tbl->GetDescription( nickname ) );
1051 itemsToDisplay.push_back( item );
1052 }
1053 }
1054
1055 EDA_LIST_DIALOG* dlg = new EDA_LIST_DIALOG( this, _( "Save Footprint As" ), headers,
1056 itemsToDisplay, aLibraryPreselect, false );
1057
1058 dlg->SetListLabel( _( "Save in library:" ) );
1059 dlg->SetOKLabel( _( "Save" ) );
1060
1061 wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
1062
1063 wxStaticText* label = new wxStaticText( dlg, wxID_ANY, _( "Name:" ) );
1064 bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
1065
1066 wxTextCtrl* nameTextCtrl = new wxTextCtrl( dlg, ID_SAVE_AS_NAME, aFootprintName );
1067 bNameSizer->Add( nameTextCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
1068
1069 wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST );
1070 nameValidator.SetCharExcludes( FOOTPRINT::StringLibNameInvalidChars( false ) );
1071 nameTextCtrl->SetValidator( nameValidator );
1072
1073 wxButton* newLibraryButton = new wxButton( dlg, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
1074 dlg->m_ButtonsSizer->Prepend( 80, 20 );
1075 dlg->m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
1076
1077 dlg->GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
1078
1079 dlg->Bind( wxEVT_BUTTON,
1080 [dlg]( wxCommandEvent& )
1081 {
1082 dlg->EndModal( ID_MAKE_NEW_LIBRARY );
1084
1085 // Move nameTextCtrl to the head of the tab-order
1086 if( dlg->GetChildren().DeleteObject( nameTextCtrl ) )
1087 dlg->GetChildren().Insert( nameTextCtrl );
1088
1089 dlg->SetInitialFocus( nameTextCtrl );
1090
1091 dlg->Layout();
1092 dlg->GetSizer()->Fit( dlg );
1093
1094 return dlg;
1095}
1096
1097
1099{
1100 if( aFootprint == nullptr )
1101 return false;
1102
1104
1105 SetMsgPanel( aFootprint );
1106
1107 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
1108 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
1109 bool updateValue = aFootprint->GetValue() == footprintName;
1110 bool done = false;
1111
1112 std::unique_ptr<EDA_LIST_DIALOG> dlg;
1113
1114 while( !done )
1115 {
1116 dlg.reset( buildSaveAsDialog( footprintName, libraryName ) );
1117
1118 int ret = dlg->ShowModal();
1119
1120 if( ret == wxID_CANCEL )
1121 {
1122 return false;
1123 }
1124 else if( ret == wxID_OK )
1125 {
1126 done = true;
1127 }
1128 else if( ret == ID_MAKE_NEW_LIBRARY )
1129 {
1130 wxFileName newLibrary( CreateNewLibrary() );
1131 libraryName = newLibrary.GetName();
1132 }
1133 }
1134
1135 libraryName = dlg->GetTextSelection();
1136
1137 if( libraryName.IsEmpty() )
1138 {
1139 DisplayError( this, _( "No library specified. Footprint could not be saved." ) );
1140 return false;
1141 }
1142
1143 footprintName = static_cast<wxTextCtrl*>( dlg->FindWindow( ID_SAVE_AS_NAME ) )->GetValue();
1144 footprintName.Trim( true );
1145 footprintName.Trim( false );
1146
1147 if( footprintName.IsEmpty() )
1148 {
1149 DisplayError( this, _( "No footprint name specified. Footprint could not be saved." ) );
1150 return false;
1151 }
1152
1153 aFootprint->SetFPID( LIB_ID( libraryName, footprintName ) );
1154
1155 if( updateValue )
1156 aFootprint->SetValue( footprintName );
1157
1158 // Legacy libraries are readable, but modifying legacy format is not allowed
1159 // So prompt the user if he try to add/replace a footprint in a legacy lib
1160 wxString libfullname = Prj().PcbFootprintLibs()->FindRow( libraryName )->GetFullURI();
1162
1163 if( piType == IO_MGR::LEGACY )
1164 {
1166 return false;
1167 }
1168
1169 bool footprintExists = tbl->FootprintExists( libraryName, footprintName );
1170
1171 if( footprintExists )
1172 {
1173 wxString msg = wxString::Format( _( "Footprint %s already exists in %s." ),
1174 footprintName,
1175 libraryName );
1176 KIDIALOG chkdlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1177 chkdlg.SetOKLabel( _( "Overwrite" ) );
1178
1179 if( chkdlg.ShowModal() == wxID_CANCEL )
1180 return false;
1181 }
1182
1183 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
1184 return false;
1185
1186 // Once saved-as a board footprint is no longer a board footprint
1187 aFootprint->SetLink( niluuid );
1188
1189 wxString fmt = footprintExists ? _( "Footprint '%s' replaced in '%s'" )
1190 : _( "Footprint '%s' added to '%s'" );
1191
1192 wxString msg = wxString::Format( fmt, footprintName.GetData(), libraryName.GetData() );
1193 SetStatusText( msg );
1194 UpdateTitle();
1196
1197 return true;
1198}
1199
1200
1202{
1204 {
1205 wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1206 GetLoadedFPID().GetLibItemName().wx_str() );
1207
1208 if( ConfirmRevertDialog( this, msg ) )
1209 {
1210 Clear_Pcb( false );
1211 AddFootprintToBoard( static_cast<FOOTPRINT*>( m_revertModule->Clone() ) );
1212
1213 Zoom_Automatique( false );
1214
1215 Update3DView( true, true );
1216
1218 GetScreen()->SetContentModified( false );
1219
1220 UpdateView();
1221 GetCanvas()->Refresh();
1222
1223 return true;
1224 }
1225 }
1226
1227 return false;
1228}
1229
1230
1231FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( const wxString& aFootprintName, bool aQuiet )
1232{
1233 wxString footprintName = aFootprintName;
1234
1235 // Static to store user preference for a session
1236 static int footprintType = 1;
1237 int footprintTranslated = FP_SMD;
1238
1239 // Ask for the new footprint name
1240 if( footprintName.IsEmpty() && !aQuiet )
1241 {
1242 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Enter footprint name:" ), _( "New Footprint" ),
1243 footprintName, _( "Footprint type:" ),
1244 { _( "Through hole" ), _( "SMD" ), _( "Other" ) },
1245 footprintType );
1246 dlg.SetTextValidator( FOOTPRINT_NAME_VALIDATOR( &footprintName ) );
1247
1248 if( dlg.ShowModal() != wxID_OK )
1249 return nullptr; //Aborted by user
1250
1251 footprintType = dlg.GetChoice();
1252
1253 switch( footprintType )
1254 {
1255 case 0: footprintTranslated = FP_THROUGH_HOLE; break;
1256 case 1: footprintTranslated = FP_SMD; break;
1257 default: footprintTranslated = 0; break;
1258 }
1259 }
1260
1261 footprintName.Trim( true );
1262 footprintName.Trim( false );
1263
1264 if( footprintName.IsEmpty() )
1265 {
1266 if( !aQuiet )
1267 DisplayInfoMessage( this, _( "No footprint name defined." ) );
1268
1269 return nullptr;
1270 }
1271
1272 // Creates the new footprint and add it to the head of the linked list of footprints
1273 FOOTPRINT* footprint = new FOOTPRINT( GetBoard() );
1274
1275 // Update its name in lib
1276 footprint->SetFPID( LIB_ID( wxEmptyString, footprintName ) );
1277
1278 footprint->SetAttributes( footprintTranslated );
1279
1280 PCB_LAYER_ID txt_layer;
1281 wxPoint default_pos;
1283
1284 footprint->Reference().SetText( settings.m_DefaultFPTextItems[0].m_Text );
1285 footprint->Reference().SetVisible( settings.m_DefaultFPTextItems[0].m_Visible );
1286 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[0].m_Layer;
1287 footprint->Reference().SetLayer( txt_layer );
1288 default_pos.y -= settings.GetTextSize( txt_layer ).y / 2;
1289 footprint->Reference().SetPosition( default_pos );
1290 default_pos.y += settings.GetTextSize( txt_layer ).y;
1291
1292 footprint->Value().SetText( settings.m_DefaultFPTextItems[1].m_Text );
1293 footprint->Value().SetVisible( settings.m_DefaultFPTextItems[1].m_Visible );
1294 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[1].m_Layer;
1295 footprint->Value().SetLayer( txt_layer );
1296 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1297 footprint->Value().SetPosition( default_pos );
1298 default_pos.y += settings.GetTextSize( txt_layer ).y;
1299
1300 for( size_t i = 2; i < settings.m_DefaultFPTextItems.size(); ++i )
1301 {
1302 FP_TEXT* textItem = new FP_TEXT( footprint );
1303 textItem->SetText( settings.m_DefaultFPTextItems[i].m_Text );
1304 textItem->SetVisible( settings.m_DefaultFPTextItems[i].m_Visible );
1305 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[i].m_Layer;
1306 textItem->SetLayer( txt_layer );
1307 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1308 textItem->SetPosition( default_pos );
1309 default_pos.y += settings.GetTextSize( txt_layer ).y;
1310 footprint->GraphicalItems().push_back( textItem );
1311 }
1312
1313 if( footprint->GetReference().IsEmpty() )
1314 footprint->SetReference( footprintName );
1315
1316 if( footprint->GetValue().IsEmpty() )
1317 footprint->SetValue( footprintName );
1318
1319 footprint->RunOnChildren(
1320 [&] ( BOARD_ITEM* aChild )
1321 {
1322 if( aChild->Type() == PCB_FP_TEXT_T )
1323 {
1324 FP_TEXT* textItem = static_cast<FP_TEXT*>( aChild );
1325 PCB_LAYER_ID layer = textItem->GetLayer();
1326
1327 textItem->SetTextThickness( settings.GetTextThickness( layer ) );
1328 textItem->SetTextSize( settings.GetTextSize( layer ) );
1329 textItem->SetItalic( settings.GetTextItalic( layer ) );
1330 textItem->SetKeepUpright( settings.GetTextUpright( layer ) );
1331 }
1332 } );
1333
1334 SetMsgPanel( footprint );
1335 return footprint;
1336}
1337
1338
1339wxString PCB_BASE_FRAME::SelectLibrary( const wxString& aNicknameExisting )
1340{
1341 wxArrayString headers;
1342
1343 headers.Add( _( "Nickname" ) );
1344 headers.Add( _( "Description" ) );
1345
1346 COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
1348 FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs();
1349 std::vector< wxArrayString > itemsToDisplay;
1350 std::vector< wxString > nicknames = fptbl->GetLogicalLibs();
1351
1352 for( const wxString& nickname : nicknames )
1353 {
1354 if( alg::contains( project.m_PinnedFootprintLibs, nickname )
1355 || alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1356 {
1357 wxArrayString item;
1358
1359 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
1360 item.Add( fptbl->GetDescription( nickname ) );
1361 itemsToDisplay.push_back( item );
1362 }
1363 }
1364
1365 for( const wxString& nickname : nicknames )
1366 {
1367 if( !alg::contains( project.m_PinnedFootprintLibs, nickname )
1368 && !alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1369 {
1370 wxArrayString item;
1371
1372 item.Add( nickname );
1373 item.Add( fptbl->GetDescription( nickname ) );
1374 itemsToDisplay.push_back( item );
1375 }
1376 }
1377
1378 EDA_LIST_DIALOG dlg( this, _( "Select Library" ), headers, itemsToDisplay, aNicknameExisting,
1379 false );
1380
1381 if( dlg.ShowModal() != wxID_OK )
1382 return wxEmptyString;
1383
1384 return dlg.GetTextSelection();
1385}
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:50
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:167
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:201
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
void BuildListOfNets()
Definition: board.h:742
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:143
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.
std::unique_ptr< FOOTPRINT > m_revertModule
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
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:1636
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:208
void SetLink(const KIID &aLink)
Definition: footprint.h:630
void SetAttributes(int aAttributes)
Definition: footprint.h:246
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: footprint.cpp:1350
const LIB_ID & GetFPID() const
Definition: footprint.h:207
void SetReference(const wxString &aReference)
Definition: footprint.h:528
void SetValue(const wxString &aValue)
Definition: footprint.h:549
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:555
KIID GetLink() const
Definition: footprint.h:629
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:1356
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:1504
const wxString & GetValue() const
Definition: footprint.h:541
const wxString & GetReference() const
Definition: footprint.h:519
DRAWINGS & GraphicalItems()
Definition: footprint.h:177
FP_TEXT & Reference()
Definition: footprint.h:556
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:56
int ShowModal() override
Definition: confirm.cpp:100
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:47
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:165
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:101
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:421
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
static TOOL_ACTION placeFootprint
Definition: pcb_actions.h:186
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:169
BOARD_ITEM * Parse(const wxString &aClipboardSourceInput)
Definition: pcb_plugin.cpp:381
std::string GetStringOutput(bool doClear)
Definition: pcb_plugin.h:244
void Format(const BOARD_ITEM *aItem, int aNestLevel=0) const
Output aItem to aFormatter in s-expression format.
Definition: pcb_plugin.cpp:402
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 PROPERTIES *aProperties=nullptr)
Create a new empty footprint library at aLibraryPath empty.
Definition: plugin.cpp:124
virtual bool IsFootprintLibWritable(const wxString &aLibraryPath)
Return true if the library at aLibraryPath is writable.
Definition: plugin.cpp:139
virtual bool FootprintLibDelete(const wxString &aLibraryPath, const PROPERTIES *aProperties=nullptr)
Delete an existing footprint library and returns true, or if library does not exist returns false,...
Definition: plugin.cpp:131
virtual void FootprintSave(const wxString &aLibraryPath, const FOOTPRINT *aFootprint, const PROPERTIES *aProperties=nullptr)
Write aFootprint to an existing library located at aLibraryPath.
Definition: plugin.cpp:108
virtual FOOTPRINT * FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, bool aKeepUUID=false, const PROPERTIES *aProperties=nullptr)
Load a footprint having aFootprintName from the aLibraryPath containing a library format that this PL...
Definition: plugin.cpp:97
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:65
Container for project specific data.
Definition: project.h:63
@ PCB_LIB_NICKNAME
Definition: project.h:172
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:125
virtual FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition: project.cpp:318
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:148
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:253
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:264
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:342
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:280
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:320
bool ConfirmRevertDialog(wxWindow *parent, const wxString &aMessage)
Display a confirmation dialog for a revert action.
Definition: confirm.cpp:229
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:68
@ FP_THROUGH_HOLE
Definition: footprint.h:67
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
FormatType fileType(const char *aFileName)
Definition: loadmodel.cpp:292
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:155
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
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.