KiCad PCB EDA Suite
Loading...
Searching...
No Matches
footprint_libraries_utils.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <wx/ffile.h>
25#include <pgm_base.h>
26#include <kiface_base.h>
27#include <confirm.h>
28#include <string_utils.h>
29#include <macros.h>
30#include <pcb_edit_frame.h>
31#include <eda_list_dialog.h>
32#include <filter_reader.h>
33#include <fp_lib_table.h>
34#include <validators.h>
36#include <tool/tool_manager.h>
37#include <tools/pcb_actions.h>
39#include <tools/pad_tool.h>
40#include <footprint.h>
41#include <pcb_group.h>
42#include <board_commit.h>
47#include <env_paths.h>
48#include <paths.h>
50#include <project_pcb.h>
54#include <wx/choicdlg.h>
55#include <wx/filedlg.h>
56#include <wx/fswatcher.h>
57
58
59// unique, "file local" translations:
60
61
62static const wxString INFO_LEGACY_LIB_WARN_EDIT(
63 _( "Writing/modifying legacy libraries (.mod files) is not allowed\n"\
64 "Please save the current library to the new .pretty format\n"\
65 "and update your footprint lib table\n"\
66 "to save your footprint (a .kicad_mod file) in the .pretty library folder" ) );
67
68static const wxString INFO_LEGACY_LIB_WARN_DELETE(
69 _( "Modifying legacy libraries (.mod files) is not allowed\n"\
70 "Please save the current library under the new .pretty format\n"\
71 "and update your footprint lib table\n"\
72 "before deleting a footprint" ) );
73
74
76{
77 wxFileName fn;
78
79 if( !aName.empty() )
80 {
81 fn = aName;
82 }
83 else
84 {
85 // Prompt the user for a footprint file to open.
86 static int lastFilterIndex = 0; // To store the last choice during a session.
87 wxString fileFiltersStr;
88 std::vector<std::string> allExtensions;
89 std::set<wxString> allWildcardsSet;
90
91 for( const auto& plugin : IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
92 {
93 PLUGIN::RELEASER pi( plugin.m_createFunc() );
94
95 if( !pi )
96 continue;
97
99
100 if( !desc )
101 continue;
102
103 if( !fileFiltersStr.IsEmpty() )
104 fileFiltersStr += wxChar( '|' );
105
106 fileFiltersStr += desc.FileFilter();
107
108 for( const std::string& ext : desc.m_FileExtensions )
109 {
110 allExtensions.emplace_back( ext );
111 allWildcardsSet.insert( wxT( "*." ) + formatWildcardExt( ext ) + wxT( ";" ) );
112 }
113 }
114
115 wxString allWildcardsStr;
116 for( const wxString& wildcard : allWildcardsSet )
117 allWildcardsStr << wildcard;
118
119 fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" )
120 + fileFiltersStr;
121
122 wxFileDialog dlg( this, _( "Import Footprint" ), m_mruPath, wxEmptyString, fileFiltersStr,
123 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
124
125 dlg.SetFilterIndex( lastFilterIndex );
126
127 if( dlg.ShowModal() == wxID_CANCEL )
128 return nullptr;
129
130 lastFilterIndex = dlg.GetFilterIndex();
131
132 fn = dlg.GetPath();
133 }
134
135 if( !fn.IsOk() )
136 return nullptr;
137
138 if( !wxFileExists( fn.GetFullPath() ) )
139 {
140 wxString msg = wxString::Format( _( "File '%s' not found." ), fn.GetFullPath() );
141 DisplayError( this, msg );
142 return nullptr;
143 }
144
145 m_mruPath = fn.GetPath();
146
148
149 for( const auto& plugin : IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
150 {
151 PLUGIN::RELEASER pi( plugin.m_createFunc() );
152
153 if( !pi )
154 continue;
155
156 if( pi->GetFootprintFileDesc().m_FileExtensions.empty() )
157 continue;
158
159 if( pi->CanReadFootprint( fn.GetFullPath() ) )
160 {
161 fileType = plugin.m_type;
162 break;
163 }
164 }
165
167 {
168 DisplayError( this, _( "Not a footprint file." ) );
169 return nullptr;
170 }
171
172 FOOTPRINT* footprint = nullptr;
173 wxString footprintName;
174
175 try
176 {
178
179 footprint = pi->ImportFootprint( fn.GetFullPath(), footprintName);
180
181 if( !footprint )
182 {
183 wxString msg = wxString::Format( _( "Unable to load footprint '%s' from '%s'" ),
184 footprintName, fn.GetFullPath() );
185 DisplayError( this, msg );
186 return nullptr;
187 }
188 }
189 catch( const IO_ERROR& ioe )
190 {
191 DisplayError( this, ioe.What() );
192
193 // if the footprint is not loaded, exit.
194 // However, even if an error happens, it can be loaded, because in KICAD and GPCB format,
195 // a fp library is a set of separate files, and the error(s) are not necessary when
196 // reading the selected file
197
198 if( !footprint )
199 return nullptr;
200 }
201
202 footprint->SetFPID( LIB_ID( wxEmptyString, footprintName ) );
203
204 // Insert footprint in list
205 AddFootprintToBoard( footprint );
206
207 // Display info :
208 SetMsgPanel( footprint );
209 PlaceFootprint( footprint );
210
211 footprint->SetPosition( VECTOR2I( 0, 0 ) );
212
214 UpdateView();
215
216 return footprint;
217}
218
219
221{
222 wxFileName fn;
224
225 if( !aFootprint )
226 return;
227
228 fn.SetName( aFootprint->GetFPID().GetLibItemName() );
229
230 wxString wildcard = KiCadFootprintLibFileWildcard();
231
232 fn.SetExt( KiCadFootprintFileExtension );
233
234 if( !cfg->m_LastExportPath.empty() )
235 fn.SetPath( cfg->m_LastExportPath );
236 else
237 fn.SetPath( m_mruPath );
238
239 wxFileDialog dlg( this, _( "Export Footprint" ), fn.GetPath(), fn.GetFullName(),
240 wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
241
242 if( dlg.ShowModal() == wxID_CANCEL )
243 return;
244
246 cfg->m_LastExportPath = fn.GetPath();
247
248 try
249 {
250 // Export as *.kicad_pcb format, using a strategy which is specifically chosen
251 // as an example on how it could also be used to send it to the system clipboard.
252
254
255 /* This footprint should *already* be "normalized" in a way such that
256 orientation is zero, etc., since it came from the Footprint Editor.
257
258 aFootprint->SetParent( 0 );
259 aFootprint->SetOrientation( 0 );
260 */
261
262 pcb_io.Format( aFootprint );
263
264 FILE* fp = wxFopen( dlg.GetPath(), wxT( "wt" ) );
265
266 if( fp == nullptr )
267 {
268 DisplayErrorMessage( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
269 dlg.GetPath() ) );
270 return;
271 }
272
273 fprintf( fp, "%s", pcb_io.GetStringOutput( false ).c_str() );
274 fclose( fp );
275 }
276 catch( const IO_ERROR& ioe )
277 {
278 DisplayError( this, ioe.What() );
279 return;
280 }
281
282 wxString msg = wxString::Format( _( "Footprint exported to file '%s'." ), dlg.GetPath() );
283 DisplayInfoMessage( this, msg );
284}
285
286
287wxString PCB_BASE_EDIT_FRAME::CreateNewProjectLibrary( const wxString& aLibName,
288 const wxString& aProposedName )
289{
290 return createNewLibrary( aLibName, aProposedName, PROJECT_PCB::PcbFootprintLibs( &Prj() ) );
291}
292
293
294wxString PCB_BASE_EDIT_FRAME::CreateNewLibrary( const wxString& aLibName,
295 const wxString& aProposedName )
296{
297 FP_LIB_TABLE* table = selectLibTable();
298
299 return createNewLibrary( aLibName, aProposedName, table );
300}
301
302
303wxString PCB_BASE_EDIT_FRAME::createNewLibrary( const wxString& aLibName,
304 const wxString& aProposedName,
305 FP_LIB_TABLE* aTable )
306{
307 // Kicad cannot write legacy format libraries, only .pretty new format because the legacy
308 // format cannot handle current features.
309 // The footprint library is actually a directory.
310
311 if( aTable == nullptr )
312 return wxEmptyString;
313
314 wxString initialPath = aProposedName.IsEmpty() ? Prj().GetProjectPath() : aProposedName;
315 wxFileName fn;
316 bool doAdd = false;
317 bool isGlobal = ( aTable == &GFootprintTable );
318
319 if( aLibName.IsEmpty() )
320 {
321 fn = initialPath;
322
324 KiCadFootprintLibPathExtension, false, isGlobal,
326 {
327 return wxEmptyString;
328 }
329
330 doAdd = true;
331 }
332 else
333 {
335
336 if( !fn.IsAbsolute() )
337 {
338 fn.SetName( aLibName );
339 fn.MakeAbsolute( initialPath );
340 }
341 }
342
343 // We can save fp libs only using IO_MGR::KICAD_SEXP format (.pretty libraries)
345 wxString libPath = fn.GetFullPath();
346
347 try
348 {
349 PLUGIN::RELEASER pi( IO_MGR::PluginFind( piType ) );
350
351 bool writable = false;
352 bool exists = false;
353
354 try
355 {
356 writable = pi->IsFootprintLibWritable( libPath );
357 exists = true; // no exception was thrown, lib must exist.
358 }
359 catch( const IO_ERROR& )
360 {
361 // best efforts....
362 }
363
364 if( exists )
365 {
366 if( !writable )
367 {
368 wxString msg = wxString::Format( _( "Library %s is read only." ), libPath );
369 ShowInfoBarError( msg );
370 return wxEmptyString;
371 }
372 else
373 {
374 wxString msg = wxString::Format( _( "Library %s already exists." ), libPath );
375 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
376 dlg.SetOKLabel( _( "Overwrite" ) );
377 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
378
379 if( dlg.ShowModal() == wxID_CANCEL )
380 return wxEmptyString;
381
382 pi->FootprintLibDelete( libPath );
383 }
384 }
385
386 pi->FootprintLibCreate( libPath );
387 }
388 catch( const IO_ERROR& ioe )
389 {
390 DisplayError( this, ioe.What() );
391 return wxEmptyString;
392 }
393
394 if( doAdd )
395 AddLibrary( libPath, aTable );
396
397 return libPath;
398}
399
400
402{
403 // If no project is loaded, always work with the global table
404 if( Prj().IsNullProject() )
405 {
407
408 if( aOptional )
409 {
410 wxMessageDialog dlg( this, _( "Add the library to the global library table?" ),
411 _( "Add To Global Library Table" ), wxYES_NO );
412
413 if( dlg.ShowModal() != wxID_OK )
414 ret = nullptr;
415 }
416
417 return ret;
418 }
419
420 wxArrayString libTableNames;
421 libTableNames.Add( _( "Global" ) );
422 libTableNames.Add( _( "Project" ) );
423
424 wxSingleChoiceDialog dlg( this, _( "Choose the Library Table to add the library to:" ),
425 _( "Add To Library Table" ), libTableNames );
426
427 if( aOptional )
428 {
429 dlg.FindWindow( wxID_CANCEL )->SetLabel( _( "Skip" ) );
430 dlg.FindWindow( wxID_OK )->SetLabel( _( "Add" ) );
431 }
432
433 if( dlg.ShowModal() != wxID_OK )
434 return nullptr;
435
436 switch( dlg.GetSelection() )
437 {
438 case 0: return &GFootprintTable;
439 case 1: return PROJECT_PCB::PcbFootprintLibs( &Prj() );
440 default: return nullptr;
441 }
442}
443
444
445bool PCB_BASE_EDIT_FRAME::AddLibrary( const wxString& aFilename, FP_LIB_TABLE* aTable )
446{
447 if( aTable == nullptr )
448 aTable = selectLibTable();
449
450 if( aTable == nullptr )
451 return wxEmptyString;
452
453 bool isGlobal = ( aTable == &GFootprintTable );
454
455 wxFileName fn( aFilename );
456
457 if( aFilename.IsEmpty() )
458 {
460 KiCadFootprintLibPathExtension, true, isGlobal,
462 {
463 return false;
464 }
465 }
466
467 wxString libPath = fn.GetFullPath();
468 wxString libName = fn.GetName();
469
470 if( libName.IsEmpty() )
471 return false;
472
474
475 if( lib_type == IO_MGR::FILE_TYPE_NONE )
476 lib_type = IO_MGR::KICAD_SEXP;
477
478 wxString type = IO_MGR::ShowType( lib_type );
479
480 // KiCad lib is our default guess. So it might not have the .pretty extension
481 // In this case, the extension is part of the library name
482 if( lib_type == IO_MGR::KICAD_SEXP && fn.GetExt() != KiCadFootprintLibPathExtension )
483 libName = fn.GetFullName();
484
485 // try to use path normalized to an environmental variable or project path
486 wxString normalizedPath = NormalizePath( libPath, &Pgm().GetLocalEnvVariables(), &Prj() );
487
488 try
489 {
490 FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libName, normalizedPath, type, wxEmptyString );
491 aTable->InsertRow( row );
492
493 if( isGlobal )
495 else
496 PROJECT_PCB::PcbFootprintLibs( &Prj() )->Save( Prj().FootprintLibTblName() );
497 }
498 catch( const IO_ERROR& ioe )
499 {
500 DisplayError( this, ioe.What() );
501 return false;
502 }
503
505
506 if( editor )
507 {
508 LIB_ID libID( libName, wxEmptyString );
509 editor->SyncLibraryTree( true );
510 editor->FocusOnLibID( libID );
511 }
512
513 auto viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_VIEWER, false );
514
515 if( viewer )
516 viewer->ReCreateLibraryList();
517
518 return true;
519}
520
521
523{
524 if( !aFPID.IsValid() )
525 return false;
526
527 wxString nickname = aFPID.GetLibNickname();
528 wxString fpname = aFPID.GetLibItemName();
529
530 // Legacy libraries are readable, but modifying legacy format is not allowed
531 // So prompt the user if he try to delete a footprint from a legacy lib
532 wxString libfullname = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( nickname )->GetFullURI();
533
535 {
537 return false;
538 }
539
540 if( !PROJECT_PCB::PcbFootprintLibs( &Prj() )->IsFootprintLibWritable( nickname ) )
541 {
542 wxString msg = wxString::Format( _( "Library '%s' is read only." ), nickname );
543 ShowInfoBarError( msg );
544 return false;
545 }
546
547 // Confirmation
548 wxString msg = wxString::Format( _( "Delete footprint '%s' from library '%s'?" ),
549 fpname.GetData(),
550 nickname.GetData() );
551
552 if( aConfirm && !IsOK( this, msg ) )
553 return false;
554
555 try
556 {
557 PROJECT_PCB::PcbFootprintLibs( &Prj() )->FootprintDelete( nickname, fpname );
558 }
559 catch( const IO_ERROR& ioe )
560 {
561 DisplayError( this, ioe.What() );
562 return false;
563 }
564
565 msg.Printf( _( "Footprint '%s' deleted from library '%s'" ),
566 fpname.GetData(),
567 nickname.GetData() );
568
569 SetStatusText( msg );
570
571 return true;
572}
573
574
575void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxString& aLibName,
576 wxString* aLibPath )
577{
578 if( GetBoard()->GetFirstFootprint() == nullptr )
579 {
580 DisplayInfoMessage( this, _( "No footprints to export!" ) );
581 return;
582 }
583
584 wxString footprintName;
585
586 auto resetReference =
587 []( FOOTPRINT* aFootprint )
588 {
589 aFootprint->SetReference( "REF**" );
590 };
591
592 if( !aStoreInNewLib )
593 {
594 // The footprints are saved in an existing .pretty library in the fp lib table
595 PROJECT& prj = Prj();
596 wxString last_nickname = prj.GetRString( PROJECT::PCB_LIB_NICKNAME );
597 wxString nickname = SelectLibrary( last_nickname );
598
599 if( !nickname ) // Aborted
600 return;
601
602 bool map = IsOK( this, wxString::Format( _( "Update footprints on board to refer to %s?" ),
603 nickname ) );
604
605 prj.SetRString( PROJECT::PCB_LIB_NICKNAME, nickname );
606
607 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
608 {
609 try
610 {
612
613 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
614 {
615 FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
616
617 resetReference( fpCopy );
618 tbl->FootprintSave( nickname, fpCopy, true );
619
620 delete fpCopy;
621 }
622 }
623 catch( const IO_ERROR& ioe )
624 {
625 DisplayError( this, ioe.What() );
626 }
627
628 if( map )
629 {
630 LIB_ID id = footprint->GetFPID();
631 id.SetLibNickname( nickname );
632 footprint->SetFPID( id );
633 }
634 }
635 }
636 else
637 {
638 // The footprints are saved in a new .pretty library.
639 // If this library already exists, all previous footprints will be deleted
640 wxString libPath = CreateNewLibrary( aLibName );
641
642 if( libPath.IsEmpty() ) // Aborted
643 return;
644
645 if( aLibPath )
646 *aLibPath = libPath;
647
648 wxString libNickname;
649 bool map = IsOK( this, _( "Update footprints on board to refer to new library?" ) );
650
651 if( map )
652 {
653 const LIB_TABLE_ROW* row = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRowByURI( libPath );
654
655 if( row )
656 libNickname = row->GetNickName();
657 }
658
660 PLUGIN::RELEASER pi( IO_MGR::PluginFind( piType ) );
661
662 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
663 {
664 try
665 {
666 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
667 {
668 FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
669
670 resetReference( fpCopy );
671 pi->FootprintSave( libPath, fpCopy );
672
673 // Remove reference to the group before deleting
674 if( PCB_GROUP* parentGroup = fpCopy->GetParentGroup() )
675 parentGroup->RemoveItem( fpCopy );
676
677 delete fpCopy;
678 }
679 }
680 catch( const IO_ERROR& ioe )
681 {
682 DisplayError( this, ioe.What() );
683 }
684
685 if( map )
686 {
687 LIB_ID id = footprint->GetFPID();
688 id.SetLibNickname( libNickname );
689 footprint->SetFPID( id );
690 }
691 }
692 }
693}
694
695
697{
698 if( !aFootprint ) // Happen if no footprint loaded
699 return false;
700
701 PAD_TOOL* padTool = m_toolManager->GetTool<PAD_TOOL>();
702
703 if( padTool->InPadEditMode() )
705
706 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
707 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
708 bool nameChanged = m_footprintNameWhenLoaded != footprintName;
709
710 if( aFootprint->GetLink() != niluuid )
711 {
712 if( SaveFootprintToBoard( false ) )
713 {
714 m_footprintNameWhenLoaded = footprintName;
715 return true;
716 }
717 else
718 {
719 return false;
720 }
721 }
722 else if( libraryName.IsEmpty() || footprintName.IsEmpty() )
723 {
724 if( SaveFootprintAs( aFootprint ) )
725 {
726 m_footprintNameWhenLoaded = footprintName;
727 SyncLibraryTree( true );
728 return true;
729 }
730 else
731 {
732 return false;
733 }
734 }
735
737
738 // Legacy libraries are readable, but modifying legacy format is not allowed
739 // So prompt the user if he try to add/replace a footprint in a legacy lib
740 wxString libfullname;
741
742 try
743 {
744 libfullname = tbl->FindRow( libraryName )->GetFullURI();
745 }
746 catch( IO_ERROR& error )
747 {
748 DisplayInfoMessage( this, error.What() );
749 return false;
750 }
751
753 {
755 return false;
756 }
757
758 if( nameChanged )
759 {
760 LIB_ID oldFPID( libraryName, m_footprintNameWhenLoaded );
761 DeleteFootprintFromLibrary( oldFPID, false );
762 }
763
764 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
765 return false;
766
767 if( nameChanged )
768 {
769 m_footprintNameWhenLoaded = footprintName;
770 SyncLibraryTree( true );
771 }
772
773 return true;
774}
775
776
778{
779 LIB_ID fpID = aFootprint->GetFPID();
780 wxString libraryName = fpID.GetLibNickname();
781 wxString footprintName = fpID.GetLibItemName();
782
783 // Legacy libraries are readable, but modifying legacy format is not allowed
784 // So prompt the user if he try to add/replace a footprint in a legacy lib
785 wxString libFullName = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( libraryName )->GetFullURI();
786
788 {
790 return false;
791 }
792
794 int i = 1;
795 wxString newName = footprintName;
796
797 // Append a number to the name until the name is unique in the library.
798 while( tbl->FootprintExists( libraryName, newName ) )
799 newName.Printf( "%s_%d", footprintName, i++ );
800
801 aFootprint->SetFPID( LIB_ID( libraryName, newName ) );
802
803 if( aFootprint->GetValue() == footprintName )
804 aFootprint->SetValue( newName );
805
806 return SaveFootprintInLibrary( aFootprint, libraryName );
807}
808
809
811 const wxString& aLibraryName )
812{
813 try
814 {
815 aFootprint->SetFPID( LIB_ID( wxEmptyString, aFootprint->GetFPID().GetLibItemName() ) );
816
817 PROJECT_PCB::PcbFootprintLibs( &Prj() )->FootprintSave( aLibraryName, aFootprint );
818
819 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
820 return true;
821 }
822 catch( const IO_ERROR& ioe )
823 {
824 DisplayError( this, ioe.What() );
825
826 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
827 return false;
828 }
829}
830
831
833{
834 // update footprint in the current board,
835 // not just add it to the board with total disregard for the netlist...
836 PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB_EDITOR, false );
837
838 if( pcbframe == nullptr ) // happens when the board editor is not active (or closed)
839 {
840 ShowInfoBarError( _( "No board currently open." ) );
841 return false;
842 }
843
844 BOARD* mainpcb = pcbframe->GetBoard();
845 FOOTPRINT* sourceFootprint = nullptr;
846 FOOTPRINT* editorFootprint = GetBoard()->GetFirstFootprint();
847
848 // Search the old footprint (source) if exists
849 // Because this source could be deleted when editing the main board...
850 if( editorFootprint->GetLink() != niluuid ) // this is not a new footprint ...
851 {
852 sourceFootprint = nullptr;
853
854 for( FOOTPRINT* candidate : mainpcb->Footprints() )
855 {
856 if( editorFootprint->GetLink() == candidate->m_Uuid )
857 {
858 sourceFootprint = candidate;
859 break;
860 }
861 }
862 }
863
864 if( !aAddNew && sourceFootprint == nullptr ) // source not found
865 {
866 DisplayError( this, _( "Unable to find the footprint on the main board.\nCannot save." ) );
867 return false;
868 }
869
870 TOOL_MANAGER* pcb_ToolManager = pcbframe->GetToolManager();
871
872 if( aAddNew && pcb_ToolManager->GetTool<BOARD_EDITOR_CONTROL>()->PlacingFootprint() )
873 {
874 DisplayError( this, _( "Previous footprint placement still in progress." ) );
875 return false;
876 }
877
879 BOARD_COMMIT commit( pcbframe );
880
881 // Create a copy for the board, first using Clone() to keep existing Uuids, and then either
882 // resetting the uuids to the board values or assigning new Uuids.
883 FOOTPRINT* newFootprint = static_cast<FOOTPRINT*>( editorFootprint->Clone() );
884 newFootprint->SetParent( mainpcb );
885 newFootprint->SetLink( niluuid );
886
887 auto fixUuid =
888 [&]( KIID& aUuid )
889 {
890 if( editorFootprint->GetLink() != niluuid && m_boardFootprintUuids.count( aUuid ) )
891 aUuid = m_boardFootprintUuids[ aUuid ];
892 else
893 aUuid = KIID();
894 };
895
896 fixUuid( const_cast<KIID&>( newFootprint->m_Uuid ) );
897
898 newFootprint->RunOnDescendants(
899 [&]( BOARD_ITEM* aChild )
900 {
901 fixUuid( const_cast<KIID&>( aChild->m_Uuid ) );
902 } );
903
905
907 bds.m_StyleFPShapes );
908
909 if( sourceFootprint ) // this is an update command
910 {
911 // In the main board the new footprint replaces the old one (pos, orient, ref, value,
912 // connections and properties are kept) and the sourceFootprint (old footprint) is
913 // deleted
914 pcbframe->ExchangeFootprint( sourceFootprint, newFootprint, commit );
915 commit.Push( wxT( "Update footprint" ) );
916 }
917 else // This is an insert command
918 {
919 KIGFX::VIEW_CONTROLS* viewControls = pcbframe->GetCanvas()->GetViewControls();
920 VECTOR2D cursorPos = viewControls->GetCursorPosition();
921
922 commit.Add( newFootprint );
923 viewControls->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
924 pcbframe->PlaceFootprint( newFootprint );
925 newFootprint->SetPosition( VECTOR2I( 0, 0 ) );
926 viewControls->SetCrossHairCursorPosition( cursorPos, false );
927 const_cast<KIID&>( newFootprint->m_Uuid ) = KIID();
928 commit.Push( wxT( "Insert footprint" ) );
929
930 pcbframe->Raise();
931 pcb_ToolManager->RunAction( PCB_ACTIONS::placeFootprint, newFootprint );
932 }
933
934 newFootprint->ClearFlags();
935
936 return true;
937}
938
939
940static int ID_MAKE_NEW_LIBRARY = 4173;
941
942
943class SAVE_AS_DIALOG : public EDA_LIST_DIALOG
944{
945public:
946 SAVE_AS_DIALOG( FOOTPRINT_EDIT_FRAME* aParent, const wxString& aFootprintName,
947 const wxString& aLibraryPreselect,
948 std::function<bool( wxString libName, wxString fpName )> aValidator ) :
949 EDA_LIST_DIALOG( aParent, _( "Save Footprint As" ), false ),
950 m_validator( std::move( aValidator ) )
951 {
952 COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
953 PROJECT_FILE& project = aParent->Prj().GetProjectFile();
954 FP_LIB_TABLE* tbl = PROJECT_PCB::PcbFootprintLibs( &aParent->Prj() );
955 std::vector<wxString> nicknames = tbl->GetLogicalLibs();
956 wxArrayString headers;
957 std::vector<wxArrayString> itemsToDisplay;
958
959 headers.Add( _( "Nickname" ) );
960 headers.Add( _( "Description" ) );
961
962 for( const wxString& nickname : nicknames )
963 {
964 if( alg::contains( project.m_PinnedFootprintLibs, nickname )
965 || alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
966 {
967 wxArrayString item;
968
969 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
970 item.Add( tbl->GetDescription( nickname ) );
971 itemsToDisplay.push_back( item );
972 }
973 }
974
975 for( const wxString& nickname : nicknames )
976 {
977 if( !alg::contains( project.m_PinnedFootprintLibs, nickname )
978 && !alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
979 {
980 wxArrayString item;
981
982 item.Add( nickname );
983 item.Add( tbl->GetDescription( nickname ) );
984 itemsToDisplay.push_back( item );
985 }
986 }
987 initDialog( headers, itemsToDisplay, aLibraryPreselect );
988
989 SetListLabel( _( "Save in library:" ) );
990 SetOKLabel( _( "Save" ) );
991
992 wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
993
994 wxStaticText* label = new wxStaticText( this, wxID_ANY, _( "Name:" ) );
995 bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
996
997 m_fpNameCtrl = new wxTextCtrl( this, wxID_ANY, aFootprintName );
998 bNameSizer->Add( m_fpNameCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
999
1000 wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST );
1001 nameValidator.SetCharExcludes( FOOTPRINT::StringLibNameInvalidChars( false ) );
1002 m_fpNameCtrl->SetValidator( nameValidator );
1003
1004 wxButton* newLibraryButton = new wxButton( this, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
1005 m_ButtonsSizer->Prepend( 80, 20 );
1006 m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
1007
1008 GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
1009
1010 Bind( wxEVT_BUTTON,
1011 [this]( wxCommandEvent& )
1012 {
1013 EndModal( ID_MAKE_NEW_LIBRARY );
1015
1016 // Move nameTextCtrl to the head of the tab-order
1017 if( GetChildren().DeleteObject( m_fpNameCtrl ) )
1018 GetChildren().Insert( m_fpNameCtrl );
1019
1021
1023
1024 Layout();
1025 GetSizer()->Fit( this );
1026
1027 Centre();
1028 }
1029
1030 wxString GetFPName()
1031 {
1032 wxString footprintName = m_fpNameCtrl->GetValue();
1033 footprintName.Trim( true );
1034 footprintName.Trim( false );
1035 return footprintName;
1036 }
1037
1038protected:
1040 {
1041 return m_validator( GetTextSelection(), GetFPName() );
1042 }
1043
1044private:
1045 wxTextCtrl* m_fpNameCtrl;
1046 std::function<bool( wxString libName, wxString fpName )> m_validator;
1047};
1048
1049
1051{
1052 if( aFootprint == nullptr )
1053 return false;
1054
1056
1057 SetMsgPanel( aFootprint );
1058
1059 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
1060 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
1061 bool updateValue = aFootprint->GetValue() == footprintName;
1062 bool done = false;
1063 bool footprintExists = false;
1064
1065 while( !done )
1066 {
1067 SAVE_AS_DIALOG dlg( this, footprintName, libraryName,
1068 [&]( const wxString& newLib, const wxString& newName )
1069 {
1070 if( newLib.IsEmpty() )
1071 {
1072 wxMessageBox( _( "A library must be specified." ) );
1073 return false;
1074 }
1075
1076 if( newName.IsEmpty() )
1077 {
1078 wxMessageBox( _( "Footprint must have a name." ) );
1079 return false;
1080 }
1081
1082 // Legacy libraries are readable, but modifying legacy format is not allowed
1083 // So prompt the user if he try to add/replace a footprint in a legacy lib
1084 const FP_LIB_TABLE_ROW* row = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( newLib );
1085 wxString libPath = row->GetFullURI();
1087
1088 if( piType == IO_MGR::LEGACY )
1089 {
1091 return false;
1092 }
1093
1094 footprintExists = tbl->FootprintExists( newLib, newName );
1095
1096 if( footprintExists )
1097 {
1098 wxString msg = wxString::Format( _( "Footprint %s already exists in %s." ),
1099 newName,
1100 newLib );
1101
1102 KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
1103 wxOK | wxCANCEL | wxICON_WARNING );
1104 errorDlg.SetOKLabel( _( "Overwrite" ) );
1105
1106 return errorDlg.ShowModal() == wxID_OK;
1107 }
1108
1109 return true;
1110 } );
1111
1112 int ret = dlg.ShowModal();
1113
1114 if( ret == wxID_CANCEL )
1115 {
1116 return false;
1117 }
1118 else if( ret == wxID_OK )
1119 {
1120 footprintName = dlg.GetFPName();
1121 libraryName = dlg.GetTextSelection();
1122 done = true;
1123 }
1124 else if( ret == ID_MAKE_NEW_LIBRARY )
1125 {
1126 wxFileName newLibrary( CreateNewLibrary() );
1127 libraryName = newLibrary.GetName();
1128 }
1129 }
1130
1131 aFootprint->SetFPID( LIB_ID( libraryName, footprintName ) );
1132
1133 if( updateValue )
1134 aFootprint->SetValue( footprintName );
1135
1136 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
1137 return false;
1138
1139 // Once saved-as a board footprint is no longer a board footprint
1140 aFootprint->SetLink( niluuid );
1141
1142 wxString fmt = footprintExists ? _( "Footprint '%s' replaced in '%s'" )
1143 : _( "Footprint '%s' added to '%s'" );
1144
1145 wxString msg = wxString::Format( fmt, footprintName.GetData(), libraryName.GetData() );
1146 SetStatusText( msg );
1147 UpdateTitle();
1149
1150 return true;
1151}
1152
1153
1155{
1157 {
1158 wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1159 GetLoadedFPID().GetLibItemName().wx_str() );
1160
1161 if( ConfirmRevertDialog( this, msg ) )
1162 {
1163 Clear_Pcb( false );
1164 AddFootprintToBoard( static_cast<FOOTPRINT*>( m_originalFootprintCopy->Clone() ) );
1165
1166 Zoom_Automatique( false );
1167
1168 Update3DView( true, true );
1169
1171 GetScreen()->SetContentModified( false );
1172
1173 UpdateView();
1174 GetCanvas()->Refresh();
1175
1176 return true;
1177 }
1178 }
1179
1180 return false;
1181}
1182
1183
1185{
1186public:
1187 NEW_FP_DIALOG( PCB_BASE_FRAME* aParent, const wxString& aName, int aFootprintType,
1188 std::function<bool( wxString newName )> aValidator ) :
1189 WX_TEXT_ENTRY_DIALOG( aParent, _( "Enter footprint name:" ), _( "New Footprint" ),
1190 aName, _( "Footprint type:" ),
1191 { _( "Through hole" ), _( "SMD" ), _( "Other" ) },
1192 aFootprintType ),
1193 m_validator( std::move( aValidator ) )
1194 { }
1195
1196 wxString GetFPName()
1197 {
1198 wxString name = m_textCtrl->GetValue();
1199 name.Trim( true ).Trim( false );
1200 return name;
1201 }
1202
1203protected:
1205 {
1206 return m_validator( GetFPName() );
1207 }
1208
1209private:
1210 std::function<bool( wxString newName )> m_validator;
1211};
1212
1213
1214FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( const wxString& aFootprintName,
1215 const wxString& aLibName, bool aQuiet )
1216{
1218 wxString footprintName = aFootprintName;
1219 wxString msg;
1220
1221 // Static to store user preference for a session
1222 static int footprintType = 1;
1223 int footprintTranslated = FP_SMD;
1224
1225 // Ask for the new footprint name
1226 if( footprintName.IsEmpty() && !aQuiet )
1227 {
1228 NEW_FP_DIALOG dlg( this, footprintName, footprintType,
1229 [&]( wxString newName )
1230 {
1231 if( newName.IsEmpty() )
1232 {
1233 wxMessageBox( _( "Footprint must have a name." ) );
1234 return false;
1235 }
1236
1237 if( !aLibName.IsEmpty() && tbl->FootprintExists( aLibName, newName ) )
1238 {
1239 msg = wxString::Format( _( "Footprint '%s' already exists in library '%s'." ),
1240 newName, aLibName );
1241
1242 KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
1243 wxOK | wxCANCEL | wxICON_WARNING );
1244 errorDlg.SetOKLabel( _( "Overwrite" ) );
1245
1246 return errorDlg.ShowModal() == wxID_OK;
1247 }
1248
1249 return true;
1250 } );
1251
1252 dlg.SetTextValidator( FOOTPRINT_NAME_VALIDATOR( &footprintName ) );
1253
1254 if( dlg.ShowModal() != wxID_OK )
1255 return nullptr; //Aborted by user
1256
1257 footprintName = dlg.GetFPName();
1258 footprintType = dlg.GetChoice();
1259
1260 switch( footprintType )
1261 {
1262 case 0: footprintTranslated = FP_THROUGH_HOLE; break;
1263 case 1: footprintTranslated = FP_SMD; break;
1264 default: footprintTranslated = 0; break;
1265 }
1266 }
1267
1268 // Creates the new footprint and add it to the head of the linked list of footprints
1269 FOOTPRINT* footprint = new FOOTPRINT( GetBoard() );
1270
1271 // Update its name in lib
1272 footprint->SetFPID( LIB_ID( wxEmptyString, footprintName ) );
1273
1274 footprint->SetAttributes( footprintTranslated );
1275
1276 PCB_LAYER_ID txt_layer;
1277 VECTOR2I default_pos;
1279
1280 footprint->Reference().SetText( settings.m_DefaultFPTextItems[0].m_Text );
1281 footprint->Reference().SetVisible( settings.m_DefaultFPTextItems[0].m_Visible );
1282 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[0].m_Layer;
1283 footprint->Reference().SetLayer( txt_layer );
1284 default_pos.y -= settings.GetTextSize( txt_layer ).y / 2;
1285 footprint->Reference().SetPosition( default_pos );
1286 default_pos.y += settings.GetTextSize( txt_layer ).y;
1287
1288 footprint->Value().SetText( settings.m_DefaultFPTextItems[1].m_Text );
1289 footprint->Value().SetVisible( settings.m_DefaultFPTextItems[1].m_Visible );
1290 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[1].m_Layer;
1291 footprint->Value().SetLayer( txt_layer );
1292 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1293 footprint->Value().SetPosition( default_pos );
1294 default_pos.y += settings.GetTextSize( txt_layer ).y;
1295
1296 for( size_t i = 2; i < settings.m_DefaultFPTextItems.size(); ++i )
1297 {
1298 PCB_TEXT* textItem = new PCB_TEXT( footprint );
1299 textItem->SetText( settings.m_DefaultFPTextItems[i].m_Text );
1300 textItem->SetVisible( settings.m_DefaultFPTextItems[i].m_Visible );
1301 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[i].m_Layer;
1302 textItem->SetLayer( txt_layer );
1303 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1304 textItem->SetPosition( default_pos );
1305 default_pos.y += settings.GetTextSize( txt_layer ).y;
1306 footprint->GraphicalItems().push_back( textItem );
1307 }
1308
1309 if( footprint->GetReference().IsEmpty() )
1310 footprint->SetReference( footprintName );
1311
1312 if( footprint->GetValue().IsEmpty() )
1313 footprint->SetValue( footprintName );
1314
1315 footprint->RunOnDescendants(
1316 [&]( BOARD_ITEM* aChild )
1317 {
1318 if( aChild->Type() == PCB_FIELD_T || aChild->Type() == PCB_TEXT_T )
1319 {
1320 PCB_TEXT* textItem = static_cast<PCB_TEXT*>( aChild );
1321 PCB_LAYER_ID layer = textItem->GetLayer();
1322
1323 textItem->SetTextThickness( settings.GetTextThickness( layer ) );
1324 textItem->SetTextSize( settings.GetTextSize( layer ) );
1325 textItem->SetItalic( settings.GetTextItalic( layer ) );
1326 textItem->SetKeepUpright( settings.GetTextUpright( layer ) );
1327 }
1328 } );
1329
1330 SetMsgPanel( footprint );
1331 return footprint;
1332}
1333
1334
1335wxString PCB_BASE_FRAME::SelectLibrary( const wxString& aNicknameExisting )
1336{
1337 wxArrayString headers;
1338
1339 headers.Add( _( "Nickname" ) );
1340 headers.Add( _( "Description" ) );
1341
1342 COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
1345 std::vector< wxArrayString > itemsToDisplay;
1346 std::vector< wxString > nicknames = fptbl->GetLogicalLibs();
1347
1348 for( const wxString& nickname : nicknames )
1349 {
1350 if( alg::contains( project.m_PinnedFootprintLibs, nickname )
1351 || alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1352 {
1353 wxArrayString item;
1354
1355 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
1356 item.Add( fptbl->GetDescription( nickname ) );
1357 itemsToDisplay.push_back( item );
1358 }
1359 }
1360
1361 for( const wxString& nickname : nicknames )
1362 {
1363 if( !alg::contains( project.m_PinnedFootprintLibs, nickname )
1364 && !alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1365 {
1366 wxArrayString item;
1367
1368 item.Add( nickname );
1369 item.Add( fptbl->GetDescription( nickname ) );
1370 itemsToDisplay.push_back( item );
1371 }
1372 }
1373
1374 EDA_LIST_DIALOG dlg( this, _( "Select Library" ), headers, itemsToDisplay, aNicknameExisting,
1375 false );
1376
1377 if( dlg.ShowModal() != wxID_OK )
1378 return wxEmptyString;
1379
1380 return dlg.GetTextSelection();
1381}
const char * name
Definition: DXF_plotter.cpp:57
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
Container for design settings for a BOARD object.
std::vector< TEXT_ITEM_INFO > m_DefaultFPTextItems
bool GetTextUpright(PCB_LAYER_ID aLayer) const
int GetTextThickness(PCB_LAYER_ID aLayer) const
Return the default text thickness from the layer class for the given layer.
bool GetTextItalic(PCB_LAYER_ID aLayer) const
VECTOR2I GetTextSize(PCB_LAYER_ID aLayer) const
Return the default text size from the layer class for the given layer.
Handle actions specific to the board editor in PcbNew.
bool PlacingFootprint() const
Re-entrancy checker for above.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:77
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:225
PCB_GROUP * GetParentGroup() const
Definition: board_item.h:91
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:259
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:276
void BuildListOfNets()
Definition: board.h:790
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:414
FOOTPRINTS & Footprints()
Definition: board.h:318
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:766
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
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
void SetupStandardButtons(std::map< int, wxString > aLabels={})
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
wxString m_mruPath
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
bool LibraryFileBrowser(bool doOpen, wxFileName &aFilename, const wxString &wildcard, const wxString &ext, bool isDirectory=false, bool aIsGlobal=false, const wxString &aGlobalPath=wxEmptyString)
virtual void Zoom_Automatique(bool aWarpPointer)
Redraw the screen with best zoom level and the best centering that shows all the page or the board.
KIGFX::VIEW_CONTROLS * GetViewControls() const
Return a pointer to the #VIEW_CONTROLS instance used in the panel.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
const KIID m_Uuid
Definition: eda_item.h:482
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:125
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
A dialog which shows:
void SetOKLabel(const wxString &aLabel)
void initDialog(const wxArrayString &aItemHeaders, const std::vector< wxArrayString > &aItemList, const wxString &aPreselectText)
wxString GetTextSelection(int aColumn=0)
Return the selected text from aColumn in the wxListCtrl in the dialog.
void SetListLabel(const wxString &aLabel)
void SetTextSize(VECTOR2I aNewSize)
Definition: eda_text.cpp:358
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:229
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:197
void SetKeepUpright(bool aKeepUpright)
Definition: eda_text.cpp:268
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:183
void SetItalic(bool aItalic)
Definition: eda_text.cpp:213
void SyncLibraryTree(bool aProgress)
Synchronize the footprint library tree to the current state of the footprint library table.
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.
bool Clear_Pcb(bool doAskAboutUnsavedChanges)
Delete all and reinitialize the current board.
Definition: initpcb.cpp:103
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.
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:77
Component library viewer main window.
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:1997
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:231
void SetLink(const KIID &aLink)
Definition: footprint.h:798
void SetAttributes(int aAttributes)
Definition: footprint.h:278
void RunOnDescendants(const std::function< void(BOARD_ITEM *)> &aFunction) const override
Invoke a function on all descendants.
Definition: footprint.cpp:1727
EDA_ITEM * Clone() const override
Invoke a function on all children.
Definition: footprint.cpp:1695
PCB_FIELD & Value()
read/write accessors:
Definition: footprint.h:592
void ApplyDefaultSettings(const BOARD &board, bool aStyleFields, bool aStyleText, bool aStyleShapes)
Apply default board settings to the footprint field text properties.
Definition: footprint.cpp:358
const LIB_ID & GetFPID() const
Definition: footprint.h:230
void SetReference(const wxString &aReference)
Definition: footprint.h:562
void SetValue(const wxString &aValue)
Definition: footprint.h:583
PCB_FIELD & Reference()
Definition: footprint.h:593
KIID GetLink() const
Definition: footprint.h:797
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:1878
const wxString & GetValue() const
Definition: footprint.h:578
const wxString & GetReference() const
Definition: footprint.h:556
DRAWINGS & GraphicalItems()
Definition: footprint.h:191
Hold a record identifying a library accessed by the appropriate footprint library PLUGIN object in th...
Definition: fp_lib_table.h:41
const FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an FP_LIB_TABLE_ROW if aNickName is found in this table or in any chained fall back table frag...
void FootprintDelete(const wxString &aNickname, const wxString &aFootprintName)
Delete the aFootprintName from the library given by aNickname.
bool FootprintExists(const wxString &aNickname, const wxString &aFootprintName)
Indicates whether or not the given footprint already exists in the given library.
SAVE_T FootprintSave(const wxString &aNickname, const FOOTPRINT *aFootprint, bool aOverwrite=true)
Write aFootprint to an existing library given by aNickname.
static wxString GetGlobalTableFileName()
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
static PLUGIN_REGISTRY * Instance()
Definition: io_mgr.h:91
static const wxString ShowType(PCB_FILE_T aFileType)
Return a brief name for a plugin given aFileType enum.
Definition: io_mgr.cpp:83
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a footprint library's libPath.
Definition: io_mgr.cpp:141
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:57
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition: io_mgr.h:56
@ FILE_TYPE_NONE
Definition: io_mgr.h:74
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:64
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:47
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:49
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:432
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition: kiway.cpp:196
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:172
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:99
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.
wxString GetFullURI(const wxString &aLibNickname, bool aExpandEnvVars=true) const
Return the full URI of the library mapped to aLibNickname.
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()
NEW_FP_DIALOG(PCB_BASE_FRAME *aParent, const wxString &aName, int aFootprintType, std::function< bool(wxString newName)> aValidator)
std::function< bool(wxString newName)> m_validator
bool TransferDataFromWindow() override
Tool relating to pads and pad settings.
Definition: pad_tool.h:37
bool InPadEditMode()
Definition: pad_tool.h:65
static wxString GetDefaultUserFootprintsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:109
static TOOL_ACTION recombinePad
Definition: pcb_actions.h:476
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:68
static TOOL_ACTION placeFootprint
Definition: pcb_actions.h:219
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.
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
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, const wxString &aLibName, bool aQuiet)
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 set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:51
A PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
Definition: pcb_plugin.h:275
std::string GetStringOutput(bool doClear)
Definition: pcb_plugin.h:366
void Format(const BOARD_ITEM *aItem, int aNestLevel=0) const
Output aItem to aFormatter in s-expression format.
Definition: pcb_plugin.cpp:360
virtual void SetPosition(const VECTOR2I &aPos) override
Definition: pcb_text.h:84
Releases a PLUGIN in the context of a potential thrown exception through its destructor.
Definition: io_mgr.h:614
virtual void FootprintLibCreate(const wxString &aLibraryPath, const STRING_UTF8_MAP *aProperties=nullptr)
Create a new empty footprint library at aLibraryPath empty.
Definition: plugin.cpp:242
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:249
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:226
virtual PLUGIN_FILE_DESC GetFootprintFileDesc() const
Returns footprint file description for the PLUGIN.
Definition: plugin.cpp:49
virtual bool IsFootprintLibWritable(const wxString &aLibraryPath)
Return true if the library at aLibraryPath is writable.
Definition: plugin.cpp:256
virtual bool CanReadFootprint(const wxString &aFileName) const
Checks if this PLUGIN can read a footprint from specified file or directory.
Definition: plugin.cpp:77
virtual FOOTPRINT * ImportFootprint(const wxString &aFootprintPath, wxString &aFootprintNameOut, const STRING_UTF8_MAP *aProperties=nullptr)
Load a single footprint from aFootprintPath and put its name in aFootprintNameOut.
Definition: plugin.cpp:179
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:70
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
Definition: project_pcb.cpp:37
Container for project specific data.
Definition: project.h:62
@ PCB_LIB_NICKNAME
Definition: project.h:190
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:143
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:166
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:277
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:288
bool TransferDataFromWindow() override
SAVE_AS_DIALOG(FOOTPRINT_EDIT_FRAME *aParent, const wxString &aFootprintName, const wxString &aLibraryPreselect, std::function< bool(wxString libName, wxString fpName)> aValidator)
std::function< bool(wxString libName, wxString symbolName)> m_validator
std::function< bool(wxString libName, wxString fpName)> m_validator
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:165
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
Master controller class:
Definition: tool_manager.h:57
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:145
wxTextCtrl * m_textCtrl
A KICAD version of wxTextEntryDialog which supports the various improvements/work-arounds from DIALOG...
void SetTextValidator(wxTextValidatorStyle style)
wxString EnsureFileExtension(const wxString &aFilename, const wxString &aExtension)
It's annoying to throw up nag dialogs when the extension isn't right.
Definition: common.cpp:398
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:360
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:332
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:305
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:73
@ FP_THROUGH_HOLE
Definition: footprint.h:72
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 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"))
@ FRAME_PCB_EDITOR
Definition: frame_type.h:42
@ FRAME_FOOTPRINT_VIEWER
Definition: frame_type.h:45
@ FRAME_FOOTPRINT_EDITOR
Definition: frame_type.h:43
const std::string KiCadFootprintLibPathExtension
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
const std::string KiCadFootprintFileExtension
wxString KiCadFootprintLibPathWildcard()
wxString KiCadFootprintLibFileWildcard()
PROJECT & Prj()
Definition: kicad.cpp:576
KIID niluuid(0)
KIWAY Kiway
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
This file contains miscellaneous commonly used macros and functions.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
STL namespace.
Class to handle a set of BOARD_ITEMs.
#define CTL_FOR_LIBRARY
Format output for a footprint library instead of clipboard or BOARD.
Definition: pcb_plugin.h:172
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:119
MODEL3D_FORMAT_TYPE fileType(const char *aFileName)
std::vector< wxString > pinned_fp_libs
Container that describes file type info.
wxString FileFilter() const
std::vector< std::string > m_FileExtensions
Filter used for file pickers if m_IsFile is true.
static int ID_MAKE_NEW_LIBRARY
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition: typeinfo.h:90
Custom text control validator definitions.
VECTOR2< double > VECTOR2D
Definition: vector2d.h:587
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588
Definition of file extensions used in Kicad.