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 : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
92 {
93 IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
94
95 if( !pi )
96 continue;
97
98 const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryFileDesc();
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 : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
150 {
151 IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
152
153 if( !pi )
154 continue;
155
156 if( pi->GetLibraryFileDesc().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 = FILEEXT::KiCadFootprintLibFileWildcard();
231
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
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 PCB_IO_MGR::KICAD_SEXP format (.pretty libraries)
345 wxString libPath = fn.GetFullPath();
346
347 try
348 {
350
351 bool writable = false;
352 bool exists = false;
353
354 try
355 {
356 writable = pi->IsLibraryWritable( 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->DeleteLibrary( libPath );
383 }
384 }
385
386 pi->CreateLibrary( 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 {
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 == PCB_IO_MGR::FILE_TYPE_NONE )
476 lib_type = PCB_IO_MGR::KICAD_SEXP;
477
478 wxString type = PCB_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 == PCB_IO_MGR::KICAD_SEXP
484 libName = fn.GetFullName();
485
486 // try to use path normalized to an environmental variable or project path
487 wxString normalizedPath = NormalizePath( libPath, &Pgm().GetLocalEnvVariables(), &Prj() );
488
489 try
490 {
491 FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libName, normalizedPath, type, wxEmptyString );
492 aTable->InsertRow( row );
493
494 if( isGlobal )
496 else
497 PROJECT_PCB::PcbFootprintLibs( &Prj() )->Save( Prj().FootprintLibTblName() );
498 }
499 catch( const IO_ERROR& ioe )
500 {
501 DisplayError( this, ioe.What() );
502 return false;
503 }
504
506
507 if( editor )
508 {
509 LIB_ID libID( libName, wxEmptyString );
510 editor->SyncLibraryTree( true );
511 editor->FocusOnLibID( libID );
512 }
513
514 auto viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_VIEWER, false );
515
516 if( viewer )
517 viewer->ReCreateLibraryList();
518
519 return true;
520}
521
522
524{
525 if( !aFPID.IsValid() )
526 return false;
527
528 wxString nickname = aFPID.GetLibNickname();
529 wxString fpname = aFPID.GetLibItemName();
530
531 // Legacy libraries are readable, but modifying legacy format is not allowed
532 // So prompt the user if he try to delete a footprint from a legacy lib
533 wxString libfullname = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( nickname )->GetFullURI();
534
536 {
538 return false;
539 }
540
541 if( !PROJECT_PCB::PcbFootprintLibs( &Prj() )->IsFootprintLibWritable( nickname ) )
542 {
543 wxString msg = wxString::Format( _( "Library '%s' is read only." ), nickname );
544 ShowInfoBarError( msg );
545 return false;
546 }
547
548 // Confirmation
549 wxString msg = wxString::Format( _( "Delete footprint '%s' from library '%s'?" ),
550 fpname.GetData(),
551 nickname.GetData() );
552
553 if( aConfirm && !IsOK( this, msg ) )
554 return false;
555
556 try
557 {
558 PROJECT_PCB::PcbFootprintLibs( &Prj() )->FootprintDelete( nickname, fpname );
559 }
560 catch( const IO_ERROR& ioe )
561 {
562 DisplayError( this, ioe.What() );
563 return false;
564 }
565
566 msg.Printf( _( "Footprint '%s' deleted from library '%s'" ),
567 fpname.GetData(),
568 nickname.GetData() );
569
570 SetStatusText( msg );
571
572 return true;
573}
574
575
576void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxString& aLibName,
577 wxString* aLibPath )
578{
579 if( GetBoard()->GetFirstFootprint() == nullptr )
580 {
581 DisplayInfoMessage( this, _( "No footprints to export!" ) );
582 return;
583 }
584
585 wxString footprintName;
586
587 auto resetReference =
588 []( FOOTPRINT* aFootprint )
589 {
590 aFootprint->SetReference( "REF**" );
591 };
592
593 auto resetGroup =
594 []( FOOTPRINT* aFootprint )
595 {
596 if( PCB_GROUP* parentGroup = aFootprint->GetParentGroup() )
597 parentGroup->RemoveItem( aFootprint );
598 };
599
600 if( !aStoreInNewLib )
601 {
602 // The footprints are saved in an existing .pretty library in the fp lib table
603 PROJECT& prj = Prj();
604 wxString last_nickname = prj.GetRString( PROJECT::PCB_LIB_NICKNAME );
605 wxString nickname = SelectLibrary( last_nickname );
606
607 if( !nickname ) // Aborted
608 return;
609
610 bool map = IsOK( this, wxString::Format( _( "Update footprints on board to refer to %s?" ),
611 nickname ) );
612
613 prj.SetRString( PROJECT::PCB_LIB_NICKNAME, nickname );
614
615 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
616 {
617 try
618 {
620
621 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
622 {
623 FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
624
625 // Reset reference designator and group membership before saving
626 resetReference( fpCopy );
627 resetGroup( fpCopy );
628
629 tbl->FootprintSave( nickname, fpCopy, true );
630
631 delete fpCopy;
632 }
633 }
634 catch( const IO_ERROR& ioe )
635 {
636 DisplayError( this, ioe.What() );
637 }
638
639 if( map )
640 {
641 LIB_ID id = footprint->GetFPID();
642 id.SetLibNickname( nickname );
643 footprint->SetFPID( id );
644 }
645 }
646 }
647 else
648 {
649 // The footprints are saved in a new .pretty library.
650 // If this library already exists, all previous footprints will be deleted
651 wxString libPath = CreateNewLibrary( aLibName );
652
653 if( libPath.IsEmpty() ) // Aborted
654 return;
655
656 if( aLibPath )
657 *aLibPath = libPath;
658
659 wxString libNickname;
660 bool map = IsOK( this, _( "Update footprints on board to refer to new library?" ) );
661
662 if( map )
663 {
664 const LIB_TABLE_ROW* row = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRowByURI( libPath );
665
666 if( row )
667 libNickname = row->GetNickName();
668 }
669
672
673 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
674 {
675 try
676 {
677 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
678 {
679 FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
680
681 // Reset reference designator and group membership before saving
682 resetReference( fpCopy );
683 resetGroup( fpCopy );
684
685 pi->FootprintSave( libPath, fpCopy );
686
687 delete fpCopy;
688 }
689 }
690 catch( const IO_ERROR& ioe )
691 {
692 DisplayError( this, ioe.What() );
693 }
694
695 if( map )
696 {
697 LIB_ID id = footprint->GetFPID();
698 id.SetLibNickname( libNickname );
699 footprint->SetFPID( id );
700 }
701 }
702 }
703}
704
705
707{
708 if( !aFootprint ) // Happen if no footprint loaded
709 return false;
710
711 PAD_TOOL* padTool = m_toolManager->GetTool<PAD_TOOL>();
712
713 if( padTool->InPadEditMode() )
715
716 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
717 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
718 bool nameChanged = m_footprintNameWhenLoaded != footprintName;
719
720 if( aFootprint->GetLink() != niluuid )
721 {
722 if( SaveFootprintToBoard( false ) )
723 {
724 m_footprintNameWhenLoaded = footprintName;
725 return true;
726 }
727 else
728 {
729 return false;
730 }
731 }
732 else if( libraryName.IsEmpty() || footprintName.IsEmpty() )
733 {
734 if( SaveFootprintAs( aFootprint ) )
735 {
736 m_footprintNameWhenLoaded = footprintName;
737 SyncLibraryTree( true );
738 return true;
739 }
740 else
741 {
742 return false;
743 }
744 }
745
747
748 // Legacy libraries are readable, but modifying legacy format is not allowed
749 // So prompt the user if he try to add/replace a footprint in a legacy lib
750 wxString libfullname;
751
752 try
753 {
754 libfullname = tbl->FindRow( libraryName )->GetFullURI();
755 }
756 catch( IO_ERROR& error )
757 {
758 DisplayInfoMessage( this, error.What() );
759 return false;
760 }
761
763 {
765 return false;
766 }
767
768 if( nameChanged )
769 {
770 LIB_ID oldFPID( libraryName, m_footprintNameWhenLoaded );
771 DeleteFootprintFromLibrary( oldFPID, false );
772 }
773
774 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
775 return false;
776
777 if( nameChanged )
778 {
779 m_footprintNameWhenLoaded = footprintName;
780 SyncLibraryTree( true );
781 }
782
783 return true;
784}
785
786
788{
789 LIB_ID fpID = aFootprint->GetFPID();
790 wxString libraryName = fpID.GetLibNickname();
791 wxString footprintName = fpID.GetLibItemName();
792
793 // Legacy libraries are readable, but modifying legacy format is not allowed
794 // So prompt the user if he try to add/replace a footprint in a legacy lib
795 wxString libFullName = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( libraryName )->GetFullURI();
796
798 {
800 return false;
801 }
802
804 int i = 1;
805 wxString newName = footprintName;
806
807 // Append a number to the name until the name is unique in the library.
808 while( tbl->FootprintExists( libraryName, newName ) )
809 newName.Printf( "%s_%d", footprintName, i++ );
810
811 aFootprint->SetFPID( LIB_ID( libraryName, newName ) );
812
813 if( aFootprint->GetValue() == footprintName )
814 aFootprint->SetValue( newName );
815
816 return SaveFootprintInLibrary( aFootprint, libraryName );
817}
818
819
821 const wxString& aLibraryName )
822{
823 try
824 {
825 aFootprint->SetFPID( LIB_ID( wxEmptyString, aFootprint->GetFPID().GetLibItemName() ) );
826
827 PROJECT_PCB::PcbFootprintLibs( &Prj() )->FootprintSave( aLibraryName, aFootprint );
828
829 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
830
831 if( aFootprint == GetBoard()->GetFirstFootprint() )
832 setFPWatcher( aFootprint );
833
834 return true;
835 }
836 catch( const IO_ERROR& ioe )
837 {
838 DisplayError( this, ioe.What() );
839
840 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
841 return false;
842 }
843}
844
845
847{
848 // update footprint in the current board,
849 // not just add it to the board with total disregard for the netlist...
850 PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB_EDITOR, false );
851
852 if( pcbframe == nullptr ) // happens when the board editor is not active (or closed)
853 {
854 ShowInfoBarError( _( "No board currently open." ) );
855 return false;
856 }
857
858 BOARD* mainpcb = pcbframe->GetBoard();
859 FOOTPRINT* sourceFootprint = nullptr;
860 FOOTPRINT* editorFootprint = GetBoard()->GetFirstFootprint();
861
862 // Search the old footprint (source) if exists
863 // Because this source could be deleted when editing the main board...
864 if( editorFootprint->GetLink() != niluuid ) // this is not a new footprint ...
865 {
866 sourceFootprint = nullptr;
867
868 for( FOOTPRINT* candidate : mainpcb->Footprints() )
869 {
870 if( editorFootprint->GetLink() == candidate->m_Uuid )
871 {
872 sourceFootprint = candidate;
873 break;
874 }
875 }
876 }
877
878 if( !aAddNew && sourceFootprint == nullptr ) // source not found
879 {
880 DisplayError( this, _( "Unable to find the footprint on the main board.\nCannot save." ) );
881 return false;
882 }
883
884 TOOL_MANAGER* pcb_ToolManager = pcbframe->GetToolManager();
885
886 if( aAddNew && pcb_ToolManager->GetTool<BOARD_EDITOR_CONTROL>()->PlacingFootprint() )
887 {
888 DisplayError( this, _( "Previous footprint placement still in progress." ) );
889 return false;
890 }
891
893 BOARD_COMMIT commit( pcbframe );
894
895 // Create a copy for the board, first using Clone() to keep existing Uuids, and then either
896 // resetting the uuids to the board values or assigning new Uuids.
897 FOOTPRINT* newFootprint = static_cast<FOOTPRINT*>( editorFootprint->Clone() );
898 newFootprint->SetParent( mainpcb );
899 newFootprint->SetLink( niluuid );
900
901 auto fixUuid =
902 [&]( KIID& aUuid )
903 {
904 if( editorFootprint->GetLink() != niluuid && m_boardFootprintUuids.count( aUuid ) )
905 aUuid = m_boardFootprintUuids[ aUuid ];
906 else
907 aUuid = KIID();
908 };
909
910 fixUuid( const_cast<KIID&>( newFootprint->m_Uuid ) );
911
912 newFootprint->RunOnDescendants(
913 [&]( BOARD_ITEM* aChild )
914 {
915 fixUuid( const_cast<KIID&>( aChild->m_Uuid ) );
916 } );
917
919
921 bds.m_StyleFPShapes );
922
923 if( sourceFootprint ) // this is an update command
924 {
925 // In the main board the new footprint replaces the old one (pos, orient, ref, value,
926 // connections and properties are kept) and the sourceFootprint (old footprint) is
927 // deleted
928 pcbframe->ExchangeFootprint( sourceFootprint, newFootprint, commit );
929 commit.Push( _( "Update Footprint" ) );
930 }
931 else // This is an insert command
932 {
933 KIGFX::VIEW_CONTROLS* viewControls = pcbframe->GetCanvas()->GetViewControls();
934 VECTOR2D cursorPos = viewControls->GetCursorPosition();
935
936 commit.Add( newFootprint );
937 viewControls->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
938 pcbframe->PlaceFootprint( newFootprint );
939 newFootprint->SetPosition( VECTOR2I( 0, 0 ) );
940 viewControls->SetCrossHairCursorPosition( cursorPos, false );
941 const_cast<KIID&>( newFootprint->m_Uuid ) = KIID();
942 commit.Push( _( "Insert Footprint" ) );
943
944 pcbframe->Raise();
945 pcb_ToolManager->RunAction( PCB_ACTIONS::placeFootprint, newFootprint );
946 }
947
948 newFootprint->ClearFlags();
949
950 return true;
951}
952
953
954static int ID_MAKE_NEW_LIBRARY = 4173;
955
956
957class SAVE_AS_DIALOG : public EDA_LIST_DIALOG
958{
959public:
960 SAVE_AS_DIALOG( FOOTPRINT_EDIT_FRAME* aParent, const wxString& aFootprintName,
961 const wxString& aLibraryPreselect,
962 std::function<bool( wxString libName, wxString fpName )> aValidator ) :
963 EDA_LIST_DIALOG( aParent, _( "Save Footprint As" ), false ),
964 m_validator( std::move( aValidator ) )
965 {
967 PROJECT_FILE& project = aParent->Prj().GetProjectFile();
968 FP_LIB_TABLE* tbl = PROJECT_PCB::PcbFootprintLibs( &aParent->Prj() );
969 std::vector<wxString> nicknames = tbl->GetLogicalLibs();
970 wxArrayString headers;
971 std::vector<wxArrayString> itemsToDisplay;
972
973 headers.Add( _( "Nickname" ) );
974 headers.Add( _( "Description" ) );
975
976 for( const wxString& nickname : nicknames )
977 {
978 if( alg::contains( project.m_PinnedFootprintLibs, nickname )
979 || alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
980 {
981 wxArrayString item;
982
983 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
984 item.Add( tbl->GetDescription( nickname ) );
985 itemsToDisplay.push_back( item );
986 }
987 }
988
989 for( const wxString& nickname : nicknames )
990 {
991 if( !alg::contains( project.m_PinnedFootprintLibs, nickname )
992 && !alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
993 {
994 wxArrayString item;
995
996 item.Add( nickname );
997 item.Add( tbl->GetDescription( nickname ) );
998 itemsToDisplay.push_back( item );
999 }
1000 }
1001 initDialog( headers, itemsToDisplay, aLibraryPreselect );
1002
1003 SetListLabel( _( "Save in library:" ) );
1004 SetOKLabel( _( "Save" ) );
1005
1006 wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
1007
1008 wxStaticText* label = new wxStaticText( this, wxID_ANY, _( "Name:" ) );
1009 bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
1010
1011 m_fpNameCtrl = new wxTextCtrl( this, wxID_ANY, aFootprintName );
1012 bNameSizer->Add( m_fpNameCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
1013
1014 wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST );
1015 nameValidator.SetCharExcludes( FOOTPRINT::StringLibNameInvalidChars( false ) );
1016 m_fpNameCtrl->SetValidator( nameValidator );
1017
1018 wxButton* newLibraryButton = new wxButton( this, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
1019 m_ButtonsSizer->Prepend( 80, 20 );
1020 m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
1021
1022 GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
1023
1024 Bind( wxEVT_BUTTON,
1025 [this]( wxCommandEvent& )
1026 {
1027 EndModal( ID_MAKE_NEW_LIBRARY );
1029
1030 // Move nameTextCtrl to the head of the tab-order
1031 if( GetChildren().DeleteObject( m_fpNameCtrl ) )
1032 GetChildren().Insert( m_fpNameCtrl );
1033
1035
1037
1038 Layout();
1039 GetSizer()->Fit( this );
1040
1041 Centre();
1042 }
1043
1044 wxString GetFPName()
1045 {
1046 wxString footprintName = m_fpNameCtrl->GetValue();
1047 footprintName.Trim( true );
1048 footprintName.Trim( false );
1049 return footprintName;
1050 }
1051
1052protected:
1054 {
1055 return m_validator( GetTextSelection(), GetFPName() );
1056 }
1057
1058private:
1059 wxTextCtrl* m_fpNameCtrl;
1060 std::function<bool( wxString libName, wxString fpName )> m_validator;
1061};
1062
1063
1065{
1066 if( aFootprint == nullptr )
1067 return false;
1068
1070
1071 SetMsgPanel( aFootprint );
1072
1073 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
1074 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
1075 bool updateValue = aFootprint->GetValue() == footprintName;
1076 bool done = false;
1077 bool footprintExists = false;
1078
1079 while( !done )
1080 {
1081 SAVE_AS_DIALOG dlg( this, footprintName, libraryName,
1082 [&]( const wxString& newLib, const wxString& newName )
1083 {
1084 if( newLib.IsEmpty() )
1085 {
1086 wxMessageBox( _( "A library must be specified." ) );
1087 return false;
1088 }
1089
1090 if( newName.IsEmpty() )
1091 {
1092 wxMessageBox( _( "Footprint must have a name." ) );
1093 return false;
1094 }
1095
1096 // Legacy libraries are readable, but modifying legacy format is not allowed
1097 // So prompt the user if he try to add/replace a footprint in a legacy lib
1098 const FP_LIB_TABLE_ROW* row = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( newLib );
1099 wxString libPath = row->GetFullURI();
1101
1102 if( piType == PCB_IO_MGR::LEGACY )
1103 {
1105 return false;
1106 }
1107
1108 footprintExists = tbl->FootprintExists( newLib, newName );
1109
1110 if( footprintExists )
1111 {
1112 wxString msg = wxString::Format( _( "Footprint %s already exists in %s." ),
1113 newName,
1114 newLib );
1115
1116 KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
1117 wxOK | wxCANCEL | wxICON_WARNING );
1118 errorDlg.SetOKLabel( _( "Overwrite" ) );
1119
1120 return errorDlg.ShowModal() == wxID_OK;
1121 }
1122
1123 return true;
1124 } );
1125
1126 int ret = dlg.ShowModal();
1127
1128 if( ret == wxID_CANCEL )
1129 {
1130 return false;
1131 }
1132 else if( ret == wxID_OK )
1133 {
1134 footprintName = dlg.GetFPName();
1135 libraryName = dlg.GetTextSelection();
1136 done = true;
1137 }
1138 else if( ret == ID_MAKE_NEW_LIBRARY )
1139 {
1140 wxFileName newLibrary( CreateNewLibrary() );
1141 libraryName = newLibrary.GetName();
1142 }
1143 }
1144
1145 aFootprint->SetFPID( LIB_ID( libraryName, footprintName ) );
1146
1147 if( updateValue )
1148 aFootprint->SetValue( footprintName );
1149
1150 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
1151 return false;
1152
1153 // Once saved-as a board footprint is no longer a board footprint
1154 aFootprint->SetLink( niluuid );
1155
1156 wxString fmt = footprintExists ? _( "Footprint '%s' replaced in '%s'" )
1157 : _( "Footprint '%s' added to '%s'" );
1158
1159 wxString msg = wxString::Format( fmt, footprintName.GetData(), libraryName.GetData() );
1160 SetStatusText( msg );
1161 UpdateTitle();
1163
1164 return true;
1165}
1166
1167
1169{
1171 {
1172 wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1173 GetLoadedFPID().GetLibItemName().wx_str() );
1174
1175 if( ConfirmRevertDialog( this, msg ) )
1176 {
1177 Clear_Pcb( false );
1178 AddFootprintToBoard( static_cast<FOOTPRINT*>( m_originalFootprintCopy->Clone() ) );
1179
1180 Zoom_Automatique( false );
1181
1182 Update3DView( true, true );
1183
1185 GetScreen()->SetContentModified( false );
1186
1187 UpdateView();
1188 GetCanvas()->Refresh();
1189
1190 return true;
1191 }
1192 }
1193
1194 return false;
1195}
1196
1197
1199{
1200public:
1201 NEW_FP_DIALOG( PCB_BASE_FRAME* aParent, const wxString& aName, int aFootprintType,
1202 std::function<bool( wxString newName )> aValidator ) :
1203 WX_TEXT_ENTRY_DIALOG( aParent, _( "Enter footprint name:" ), _( "New Footprint" ),
1204 aName, _( "Footprint type:" ),
1205 { _( "Through hole" ), _( "SMD" ), _( "Other" ) },
1206 aFootprintType ),
1207 m_validator( std::move( aValidator ) )
1208 { }
1209
1210 wxString GetFPName()
1211 {
1212 wxString name = m_textCtrl->GetValue();
1213 name.Trim( true ).Trim( false );
1214 return name;
1215 }
1216
1217protected:
1219 {
1220 return m_validator( GetFPName() );
1221 }
1222
1223private:
1224 std::function<bool( wxString newName )> m_validator;
1225};
1226
1227
1228FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( const wxString& aFootprintName,
1229 const wxString& aLibName, bool aQuiet )
1230{
1232 wxString footprintName = aFootprintName;
1233 wxString msg;
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 NEW_FP_DIALOG dlg( this, footprintName, footprintType,
1243 [&]( wxString newName )
1244 {
1245 if( newName.IsEmpty() )
1246 {
1247 wxMessageBox( _( "Footprint must have a name." ) );
1248 return false;
1249 }
1250
1251 if( !aLibName.IsEmpty() && tbl->FootprintExists( aLibName, newName ) )
1252 {
1253 msg = wxString::Format( _( "Footprint '%s' already exists in library '%s'." ),
1254 newName, aLibName );
1255
1256 KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
1257 wxOK | wxCANCEL | wxICON_WARNING );
1258 errorDlg.SetOKLabel( _( "Overwrite" ) );
1259
1260 return errorDlg.ShowModal() == wxID_OK;
1261 }
1262
1263 return true;
1264 } );
1265
1266 dlg.SetTextValidator( FOOTPRINT_NAME_VALIDATOR( &footprintName ) );
1267
1268 if( dlg.ShowModal() != wxID_OK )
1269 return nullptr; //Aborted by user
1270
1271 footprintName = dlg.GetFPName();
1272 footprintType = dlg.GetChoice();
1273
1274 switch( footprintType )
1275 {
1276 case 0: footprintTranslated = FP_THROUGH_HOLE; break;
1277 case 1: footprintTranslated = FP_SMD; break;
1278 default: footprintTranslated = 0; break;
1279 }
1280 }
1281
1282 // Creates the new footprint and add it to the head of the linked list of footprints
1283 FOOTPRINT* footprint = new FOOTPRINT( GetBoard() );
1284
1285 // Update its name in lib
1286 footprint->SetFPID( LIB_ID( wxEmptyString, footprintName ) );
1287
1288 footprint->SetAttributes( footprintTranslated );
1289
1290 PCB_LAYER_ID txt_layer;
1291 VECTOR2I default_pos;
1293
1294 footprint->Reference().SetText( settings.m_DefaultFPTextItems[0].m_Text );
1295 footprint->Reference().SetVisible( settings.m_DefaultFPTextItems[0].m_Visible );
1296 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[0].m_Layer;
1297 footprint->Reference().SetLayer( txt_layer );
1298 default_pos.y -= settings.GetTextSize( txt_layer ).y / 2;
1299 footprint->Reference().SetPosition( default_pos );
1300 default_pos.y += settings.GetTextSize( txt_layer ).y;
1301
1302 footprint->Value().SetText( settings.m_DefaultFPTextItems[1].m_Text );
1303 footprint->Value().SetVisible( settings.m_DefaultFPTextItems[1].m_Visible );
1304 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[1].m_Layer;
1305 footprint->Value().SetLayer( txt_layer );
1306 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1307 footprint->Value().SetPosition( default_pos );
1308 default_pos.y += settings.GetTextSize( txt_layer ).y;
1309
1310 for( size_t i = 2; i < settings.m_DefaultFPTextItems.size(); ++i )
1311 {
1312 PCB_TEXT* textItem = new PCB_TEXT( footprint );
1313 textItem->SetText( settings.m_DefaultFPTextItems[i].m_Text );
1314 textItem->SetVisible( settings.m_DefaultFPTextItems[i].m_Visible );
1315 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[i].m_Layer;
1316 textItem->SetLayer( txt_layer );
1317 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1318 textItem->SetPosition( default_pos );
1319 default_pos.y += settings.GetTextSize( txt_layer ).y;
1320 footprint->GraphicalItems().push_back( textItem );
1321 }
1322
1323 if( footprint->GetReference().IsEmpty() )
1324 footprint->SetReference( footprintName );
1325
1326 if( footprint->GetValue().IsEmpty() )
1327 footprint->SetValue( footprintName );
1328
1329 footprint->RunOnDescendants(
1330 [&]( BOARD_ITEM* aChild )
1331 {
1332 if( aChild->Type() == PCB_FIELD_T || aChild->Type() == PCB_TEXT_T )
1333 {
1334 PCB_TEXT* textItem = static_cast<PCB_TEXT*>( aChild );
1335 PCB_LAYER_ID layer = textItem->GetLayer();
1336
1337 textItem->SetTextThickness( settings.GetTextThickness( layer ) );
1338 textItem->SetTextSize( settings.GetTextSize( layer ) );
1339 textItem->SetItalic( settings.GetTextItalic( layer ) );
1340 textItem->SetKeepUpright( settings.GetTextUpright( layer ) );
1341 }
1342 } );
1343
1344 SetMsgPanel( footprint );
1345 return footprint;
1346}
1347
1348
1349wxString PCB_BASE_FRAME::SelectLibrary( const wxString& aNicknameExisting )
1350{
1351 wxArrayString headers;
1352
1353 headers.Add( _( "Nickname" ) );
1354 headers.Add( _( "Description" ) );
1355
1359 std::vector< wxArrayString > itemsToDisplay;
1360 std::vector< wxString > nicknames = fptbl->GetLogicalLibs();
1361
1362 for( const wxString& nickname : nicknames )
1363 {
1364 if( alg::contains( project.m_PinnedFootprintLibs, nickname )
1365 || alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1366 {
1367 wxArrayString item;
1368
1369 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
1370 item.Add( fptbl->GetDescription( nickname ) );
1371 itemsToDisplay.push_back( item );
1372 }
1373 }
1374
1375 for( const wxString& nickname : nicknames )
1376 {
1377 if( !alg::contains( project.m_PinnedFootprintLibs, nickname )
1378 && !alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1379 {
1380 wxArrayString item;
1381
1382 item.Add( nickname );
1383 item.Add( fptbl->GetDescription( nickname ) );
1384 itemsToDisplay.push_back( item );
1385 }
1386 }
1387
1388 EDA_LIST_DIALOG dlg( this, _( "Select Library" ), headers, itemsToDisplay, aNicknameExisting,
1389 false );
1390
1391 if( dlg.ShowModal() != wxID_OK )
1392 return wxEmptyString;
1393
1394 return dlg.GetTextSelection();
1395}
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:226
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:260
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:281
void BuildListOfNets()
Definition: board.h:813
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:432
const FOOTPRINTS & Footprints() const
Definition: board.h:322
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:797
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:80
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:98
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:485
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:128
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:103
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, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:374
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:245
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:284
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:60
Component library viewer main window.
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2297
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:234
void SetLink(const KIID &aLink)
Definition: footprint.h:836
void SetAttributes(int aAttributes)
Definition: footprint.h:277
void RunOnDescendants(const std::function< void(BOARD_ITEM *)> &aFunction, int aDepth=0) const override
Invoke a function on all descendants.
Definition: footprint.cpp:2018
EDA_ITEM * Clone() const override
Invoke a function on all children.
Definition: footprint.cpp:1986
PCB_FIELD & Value()
read/write accessors:
Definition: footprint.h:624
void ApplyDefaultSettings(const BOARD &board, bool aStyleFields, bool aStyleText, bool aStyleShapes)
Apply default board settings to the footprint field text properties.
Definition: footprint.cpp:602
const LIB_ID & GetFPID() const
Definition: footprint.h:233
void SetReference(const wxString &aReference)
Definition: footprint.h:594
void SetValue(const wxString &aValue)
Definition: footprint.h:615
PCB_FIELD & Reference()
Definition: footprint.h:625
KIID GetLink() const
Definition: footprint.h:835
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:2174
const wxString & GetValue() const
Definition: footprint.h:610
const wxString & GetReference() const
Definition: footprint.h:588
DRAWINGS & GraphicalItems()
Definition: footprint.h:194
Hold a record identifying a library accessed by the appropriate footprint library #PLUGIN object in t...
Definition: fp_lib_table.h:42
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
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:406
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 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
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:98
static TOOL_ACTION recombinePad
Definition: pcb_actions.h:474
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:68
static TOOL_ACTION placeFootprint
Definition: pcb_actions.h:220
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.
void setFPWatcher(FOOTPRINT *aFootprint)
Creates (or removes) a watcher on the specified footprint.
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.
void Format(const BOARD_ITEM *aItem, int aNestLevel=0) const
Output aItem to aFormatter in s-expression format.
std::string GetStringOutput(bool doClear)
static PLUGIN_REGISTRY * Instance()
Definition: pcb_io_mgr.h:93
static PCB_IO * PluginFind(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
Definition: pcb_io_mgr.cpp:65
PCB_FILE_T
The set of file types that the PCB_IO_MGR knows about, and for which there has been a plugin written,...
Definition: pcb_io_mgr.h:56
@ FILE_TYPE_NONE
Definition: pcb_io_mgr.h:76
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition: pcb_io_mgr.h:58
@ LEGACY
Legacy Pcbnew file formats prior to s-expression.
Definition: pcb_io_mgr.h:59
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a footprint library's libPath.
Definition: pcb_io_mgr.cpp:132
static const wxString ShowType(PCB_FILE_T aFileType)
Return a brief name for a plugin given aFileType enum.
Definition: pcb_io_mgr.cpp:74
virtual void SetPosition(const VECTOR2I &aPos) override
Definition: pcb_text.h:87
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:678
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:135
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:269
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:280
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:167
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:415
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:150
#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
static const std::string KiCadFootprintLibPathExtension
static const std::string KiCadFootprintFileExtension
static wxString KiCadFootprintLibFileWildcard()
static wxString KiCadFootprintLibPathWildcard()
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition: io_mgr.h:33
PROJECT & Prj()
Definition: kicad.cpp:595
KIID niluuid(0)
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.
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1059
see class PGM_BASE
KIWAY Kiway(KFCTL_STANDALONE)
MODEL3D_FORMAT_TYPE fileType(const char *aFileName)
std::vector< wxString > pinned_fp_libs
Container that describes file type info.
Definition: io_base.h:39
std::vector< std::string > m_FileExtensions
Filter used for file pickers if m_IsFile is true.
Definition: io_base.h:41
wxString FileFilter() const
Definition: io_base.cpp:38
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
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
Definition of file extensions used in Kicad.