KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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 The 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 <kidialog.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 <zone.h>
42#include <pcb_group.h>
46#include <env_paths.h>
47#include <paths.h>
49#include <project_pcb.h>
53#include <view/view_controls.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{
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 wxString libfullname;
531
532 // Legacy libraries are readable, but modifying legacy format is not allowed
533 // So prompt the user if he try to delete a footprint from a legacy lib
534 try
535 {
536 libfullname = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( nickname )->GetFullURI();
537 }
538 catch( ... )
539 {
540 // If we can't find the nickname, stop here
541 return false;
542 }
543
545 {
547 return false;
548 }
549
550 if( !PROJECT_PCB::PcbFootprintLibs( &Prj() )->IsFootprintLibWritable( nickname ) )
551 {
552 wxString msg = wxString::Format( _( "Library '%s' is read only." ), nickname );
553 ShowInfoBarError( msg );
554 return false;
555 }
556
557 // Confirmation
558 wxString msg = wxString::Format( _( "Delete footprint '%s' from library '%s'?" ),
559 fpname.GetData(),
560 nickname.GetData() );
561
562 if( aConfirm && !IsOK( this, msg ) )
563 return false;
564
565 try
566 {
567 PROJECT_PCB::PcbFootprintLibs( &Prj() )->FootprintDelete( nickname, fpname );
568 }
569 catch( const IO_ERROR& ioe )
570 {
571 DisplayError( this, ioe.What() );
572 return false;
573 }
574
575 msg.Printf( _( "Footprint '%s' deleted from library '%s'" ),
576 fpname.GetData(),
577 nickname.GetData() );
578
579 SetStatusText( msg );
580
581 return true;
582}
583
584
585void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxString& aLibName,
586 wxString* aLibPath )
587{
588 if( GetBoard()->GetFirstFootprint() == nullptr )
589 {
590 DisplayInfoMessage( this, _( "No footprints to export!" ) );
591 return;
592 }
593
594 wxString footprintName;
595
596 auto resetReference =
597 []( FOOTPRINT* aFootprint )
598 {
599 aFootprint->SetReference( "REF**" );
600 };
601
602 auto resetGroup =
603 []( FOOTPRINT* aFootprint )
604 {
605 if( PCB_GROUP* parentGroup = aFootprint->GetParentGroup() )
606 parentGroup->RemoveItem( aFootprint );
607 };
608
609 auto resetZones =
610 []( FOOTPRINT* aFootprint )
611 {
612 for( ZONE* zone : aFootprint->Zones() )
613 zone->Move( -aFootprint->GetPosition() );
614 };
615
616 if( !aStoreInNewLib )
617 {
618 // The footprints are saved in an existing .pretty library in the fp lib table
619 PROJECT& prj = Prj();
620 wxString last_nickname = prj.GetRString( PROJECT::PCB_LIB_NICKNAME );
621 wxString nickname = SelectLibrary( last_nickname );
622
623 if( !nickname ) // Aborted
624 return;
625
626 bool map = IsOK( this, wxString::Format( _( "Update footprints on board to refer to %s?" ),
627 nickname ) );
628
629 prj.SetRString( PROJECT::PCB_LIB_NICKNAME, nickname );
630
631 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
632 {
633 try
634 {
636
637 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
638 {
639 FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
640
641 // Reset reference designator and group membership before saving
642 resetReference( fpCopy );
643 resetGroup( fpCopy );
644 resetZones( fpCopy );
645
646 tbl->FootprintSave( nickname, fpCopy, true );
647
648 delete fpCopy;
649 }
650 }
651 catch( const IO_ERROR& ioe )
652 {
653 DisplayError( this, ioe.What() );
654 }
655
656 if( map )
657 {
658 LIB_ID id = footprint->GetFPID();
659 id.SetLibNickname( nickname );
660 footprint->SetFPID( id );
661 }
662 }
663 }
664 else
665 {
666 // The footprints are saved in a new .pretty library.
667 // If this library already exists, all previous footprints will be deleted
668 wxString libPath = CreateNewLibrary( aLibName );
669
670 if( libPath.IsEmpty() ) // Aborted
671 return;
672
673 if( aLibPath )
674 *aLibPath = libPath;
675
676 wxString libNickname;
677 bool map = IsOK( this, _( "Update footprints on board to refer to new library?" ) );
678
679 if( map )
680 {
681 const LIB_TABLE_ROW* row = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRowByURI( libPath );
682
683 if( row )
684 libNickname = row->GetNickName();
685 }
686
689 std::map<std::string, UTF8> options { { "skip_cache_validation", "1" } }; // Skip cache validation -- we just created it
690
691 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
692 {
693 try
694 {
695 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
696 {
697 FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
698
699 // Reset reference designator and group membership before saving
700 resetReference( fpCopy );
701 resetGroup( fpCopy );
702 resetZones( fpCopy );
703
704 pi->FootprintSave( libPath, fpCopy, &options );
705
706 delete fpCopy;
707 }
708 }
709 catch( const IO_ERROR& ioe )
710 {
711 DisplayError( this, ioe.What() );
712 }
713
714 if( map )
715 {
716 LIB_ID id = footprint->GetFPID();
717 id.SetLibNickname( libNickname );
718 footprint->SetFPID( id );
719 }
720 }
721 }
722}
723
724
726{
727 if( !aFootprint ) // Happen if no footprint loaded
728 return false;
729
730 PAD_TOOL* padTool = m_toolManager->GetTool<PAD_TOOL>();
731
732 if( padTool->InPadEditMode() )
734
735 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
736 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
737 bool nameChanged = m_footprintNameWhenLoaded != footprintName;
738
739 if( aFootprint->GetLink() != niluuid )
740 {
741 if( SaveFootprintToBoard( false ) )
742 {
743 m_footprintNameWhenLoaded = footprintName;
744 return true;
745 }
746 else
747 {
748 return false;
749 }
750 }
751 else if( libraryName.IsEmpty() || footprintName.IsEmpty() )
752 {
753 if( SaveFootprintAs( aFootprint ) )
754 {
755 m_footprintNameWhenLoaded = footprintName;
756 SyncLibraryTree( true );
757 return true;
758 }
759 else
760 {
761 return false;
762 }
763 }
764
766
767 // Legacy libraries are readable, but modifying legacy format is not allowed
768 // So prompt the user if he try to add/replace a footprint in a legacy lib
769 wxString libfullname;
770
771 try
772 {
773 libfullname = tbl->FindRow( libraryName )->GetFullURI();
774 }
775 catch( IO_ERROR& error )
776 {
777 DisplayInfoMessage( this, error.What() );
778 return false;
779 }
780
782 {
784 return false;
785 }
786
787 if( nameChanged )
788 {
789 LIB_ID oldFPID( libraryName, m_footprintNameWhenLoaded );
790 DeleteFootprintFromLibrary( oldFPID, false );
791 }
792
793 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
794 return false;
795
796 if( nameChanged )
797 {
798 m_footprintNameWhenLoaded = footprintName;
799 SyncLibraryTree( true );
800 }
801
802 return true;
803}
804
805
807{
808 LIB_ID fpID = aFootprint->GetFPID();
809 wxString libraryName = fpID.GetLibNickname();
810 wxString footprintName = fpID.GetLibItemName();
811
812 // Legacy libraries are readable, but modifying legacy format is not allowed
813 // So prompt the user if he try to add/replace a footprint in a legacy lib
814 wxString libFullName = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( libraryName )->GetFullURI();
815
817 {
819 return false;
820 }
821
823 int i = 1;
824 wxString newName = footprintName;
825
826 // Append a number to the name until the name is unique in the library.
827 while( tbl->FootprintExists( libraryName, newName ) )
828 newName.Printf( "%s_%d", footprintName, i++ );
829
830 aFootprint->SetFPID( LIB_ID( libraryName, newName ) );
831
832 if( aFootprint->GetValue() == footprintName )
833 aFootprint->SetValue( newName );
834
835 return SaveFootprintInLibrary( aFootprint, libraryName );
836}
837
838
840 const wxString& aLibraryName )
841{
842 try
843 {
844 aFootprint->SetFPID( LIB_ID( wxEmptyString, aFootprint->GetFPID().GetLibItemName() ) );
845
846 PROJECT_PCB::PcbFootprintLibs( &Prj() )->FootprintSave( aLibraryName, aFootprint );
847
848 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
849
850 if( aFootprint == GetBoard()->GetFirstFootprint() )
851 setFPWatcher( aFootprint );
852
853 return true;
854 }
855 catch( const IO_ERROR& ioe )
856 {
857 DisplayError( this, ioe.What() );
858
859 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
860 return false;
861 }
862}
863
864
866{
867 // update footprint in the current board,
868 // not just add it to the board with total disregard for the netlist...
869 PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB_EDITOR, false );
870
871 if( pcbframe == nullptr ) // happens when the board editor is not active (or closed)
872 {
873 ShowInfoBarError( _( "No board currently open." ) );
874 return false;
875 }
876
877 BOARD* mainpcb = pcbframe->GetBoard();
878 FOOTPRINT* sourceFootprint = nullptr;
879 FOOTPRINT* editorFootprint = GetBoard()->GetFirstFootprint();
880
881 // Search the old footprint (source) if exists
882 // Because this source could be deleted when editing the main board...
883 if( editorFootprint->GetLink() != niluuid ) // this is not a new footprint ...
884 {
885 sourceFootprint = nullptr;
886
887 for( FOOTPRINT* candidate : mainpcb->Footprints() )
888 {
889 if( editorFootprint->GetLink() == candidate->m_Uuid )
890 {
891 sourceFootprint = candidate;
892 break;
893 }
894 }
895 }
896
897 if( !aAddNew && sourceFootprint == nullptr ) // source not found
898 {
899 DisplayError( this, _( "Unable to find the footprint on the main board.\nCannot save." ) );
900 return false;
901 }
902
903 TOOL_MANAGER* pcb_ToolManager = pcbframe->GetToolManager();
904
905 if( aAddNew && pcb_ToolManager->GetTool<BOARD_EDITOR_CONTROL>()->PlacingFootprint() )
906 {
907 DisplayError( this, _( "Previous footprint placement still in progress." ) );
908 return false;
909 }
910
912 BOARD_COMMIT commit( pcbframe );
913
914 // Create a copy for the board, first using Clone() to keep existing Uuids, and then either
915 // resetting the uuids to the board values or assigning new Uuids.
916 FOOTPRINT* newFootprint = static_cast<FOOTPRINT*>( editorFootprint->Clone() );
917 newFootprint->SetParent( mainpcb );
918 newFootprint->SetLink( niluuid );
919
920 auto fixUuid =
921 [&]( KIID& aUuid )
922 {
923 if( editorFootprint->GetLink() != niluuid && m_boardFootprintUuids.count( aUuid ) )
924 aUuid = m_boardFootprintUuids[ aUuid ];
925 else
926 aUuid = KIID();
927 };
928
929 fixUuid( const_cast<KIID&>( newFootprint->m_Uuid ) );
930
931 newFootprint->RunOnChildren(
932 [&]( BOARD_ITEM* aChild )
933 {
934 fixUuid( const_cast<KIID&>( aChild->m_Uuid ) );
935 },
936 RECURSE_MODE::RECURSE );
937
938 // Right now, we only show the "Unconnected" net in the footprint editor, but this is still
939 // referenced in the footprint. So we need to update the net pointers in the footprint to
940 // point to the nets in the main board.
941 newFootprint->RunOnChildren(
942 [&]( BOARD_ITEM* aChild )
943 {
944 if( BOARD_CONNECTED_ITEM* conn = dynamic_cast<BOARD_CONNECTED_ITEM*>( aChild ) )
945 {
946 NETINFO_ITEM* net = conn->GetNet();
947 auto& netmap = mainpcb->GetNetInfo().NetsByName();
948
949 if( net )
950 {
951 auto it = netmap.find( net->GetNetname() );
952
953 if( it != netmap.end() )
954 conn->SetNet( it->second );
955 }
956
957 }
958 },
959 RECURSE_MODE::RECURSE );
960
962
964 bds.m_StyleFPShapes );
965
966 if( sourceFootprint ) // this is an update command
967 {
968 // In the main board the new footprint replaces the old one (pos, orient, ref, value,
969 // connections and properties are kept) and the sourceFootprint (old footprint) is
970 // deleted
971 pcbframe->ExchangeFootprint( sourceFootprint, newFootprint, commit );
972 commit.Push( _( "Update Footprint" ) );
973 }
974 else // This is an insert command
975 {
976 KIGFX::VIEW_CONTROLS* viewControls = pcbframe->GetCanvas()->GetViewControls();
977 VECTOR2D cursorPos = viewControls->GetCursorPosition();
978
979 commit.Add( newFootprint );
980 viewControls->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
981 pcbframe->PlaceFootprint( newFootprint );
982 newFootprint->SetPosition( VECTOR2I( 0, 0 ) );
983 viewControls->SetCrossHairCursorPosition( cursorPos, false );
984 const_cast<KIID&>( newFootprint->m_Uuid ) = KIID();
985 commit.Push( _( "Insert Footprint" ) );
986
987 pcbframe->Raise();
988 pcb_ToolManager->RunAction( PCB_ACTIONS::placeFootprint, newFootprint );
989 }
990
991 newFootprint->ClearFlags();
992
993 return true;
994}
995
996
997static int ID_MAKE_NEW_LIBRARY = 4173;
998
999
1000class SAVE_AS_DIALOG : public EDA_LIST_DIALOG
1001{
1002public:
1003 SAVE_AS_DIALOG( FOOTPRINT_EDIT_FRAME* aParent, const wxString& aFootprintName,
1004 const wxString& aLibraryPreselect,
1005 std::function<bool( wxString libName, wxString fpName )> aValidator ) :
1006 EDA_LIST_DIALOG( aParent, _( "Save Footprint As" ), false ),
1007 m_validator( std::move( aValidator ) )
1008 {
1010 PROJECT_FILE& project = aParent->Prj().GetProjectFile();
1011 FP_LIB_TABLE* tbl = PROJECT_PCB::PcbFootprintLibs( &aParent->Prj() );
1012 std::vector<wxString> nicknames = tbl->GetLogicalLibs();
1013 wxArrayString headers;
1014 std::vector<wxArrayString> itemsToDisplay;
1015
1016 headers.Add( _( "Nickname" ) );
1017 headers.Add( _( "Description" ) );
1018
1019 for( const wxString& nickname : nicknames )
1020 {
1021 if( alg::contains( project.m_PinnedFootprintLibs, nickname )
1022 || alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1023 {
1024 wxArrayString item;
1025
1026 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
1027 item.Add( tbl->GetDescription( nickname ) );
1028 itemsToDisplay.push_back( item );
1029 }
1030 }
1031
1032 for( const wxString& nickname : nicknames )
1033 {
1034 if( !alg::contains( project.m_PinnedFootprintLibs, nickname )
1035 && !alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1036 {
1037 wxArrayString item;
1038
1039 item.Add( nickname );
1040 item.Add( tbl->GetDescription( nickname ) );
1041 itemsToDisplay.push_back( item );
1042 }
1043 }
1044 initDialog( headers, itemsToDisplay, aLibraryPreselect );
1045
1046 SetListLabel( _( "Save in library:" ) );
1047 SetOKLabel( _( "Save" ) );
1048
1049 wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
1050
1051 wxStaticText* label = new wxStaticText( this, wxID_ANY, _( "Name:" ) );
1052 bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
1053
1054 m_fpNameCtrl = new wxTextCtrl( this, wxID_ANY, aFootprintName );
1055 bNameSizer->Add( m_fpNameCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
1056
1057 wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST );
1058 nameValidator.SetCharExcludes( FOOTPRINT::StringLibNameInvalidChars( false ) );
1059 m_fpNameCtrl->SetValidator( nameValidator );
1060
1061 wxButton* newLibraryButton = new wxButton( this, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
1062 m_ButtonsSizer->Prepend( 80, 20 );
1063 m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
1064
1065 GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
1066
1067 Bind( wxEVT_BUTTON,
1068 [this]( wxCommandEvent& )
1069 {
1070 EndModal( ID_MAKE_NEW_LIBRARY );
1072
1073 // Move nameTextCtrl to the head of the tab-order
1074 if( GetChildren().DeleteObject( m_fpNameCtrl ) )
1075 GetChildren().Insert( m_fpNameCtrl );
1076
1078
1080
1081 Layout();
1082 GetSizer()->Fit( this );
1083
1084 Centre();
1085 }
1086
1087 wxString GetFPName()
1088 {
1089 wxString footprintName = m_fpNameCtrl->GetValue();
1090 footprintName.Trim( true );
1091 footprintName.Trim( false );
1092 return footprintName;
1093 }
1094
1095protected:
1097 {
1098 return m_validator( GetTextSelection(), GetFPName() );
1099 }
1100
1101private:
1102 wxTextCtrl* m_fpNameCtrl;
1103 std::function<bool( wxString libName, wxString fpName )> m_validator;
1104};
1105
1106
1108{
1109 if( aFootprint == nullptr )
1110 return false;
1111
1113
1114 SetMsgPanel( aFootprint );
1115
1116 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
1117 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
1118 bool updateValue = aFootprint->GetValue() == footprintName;
1119 bool done = false;
1120 bool footprintExists = false;
1121
1122 while( !done )
1123 {
1124 SAVE_AS_DIALOG dlg( this, footprintName, libraryName,
1125 [&]( const wxString& newLib, const wxString& newName )
1126 {
1127 if( newLib.IsEmpty() )
1128 {
1129 wxMessageBox( _( "A library must be specified." ) );
1130 return false;
1131 }
1132
1133 if( newName.IsEmpty() )
1134 {
1135 wxMessageBox( _( "Footprint must have a name." ) );
1136 return false;
1137 }
1138
1139 // Legacy libraries are readable, but modifying legacy format is not allowed
1140 // So prompt the user if he try to add/replace a footprint in a legacy lib
1141 const FP_LIB_TABLE_ROW* row = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( newLib );
1142 wxString libPath = row->GetFullURI();
1144
1145 if( piType == PCB_IO_MGR::LEGACY )
1146 {
1148 return false;
1149 }
1150
1151 footprintExists = tbl->FootprintExists( newLib, newName );
1152
1153 if( footprintExists )
1154 {
1155 wxString msg = wxString::Format( _( "Footprint %s already exists in %s." ),
1156 newName,
1157 newLib );
1158
1159 KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
1160 wxOK | wxCANCEL | wxICON_WARNING );
1161 errorDlg.SetOKLabel( _( "Overwrite" ) );
1162
1163 return errorDlg.ShowModal() == wxID_OK;
1164 }
1165
1166 return true;
1167 } );
1168
1169 int ret = dlg.ShowModal();
1170
1171 if( ret == wxID_CANCEL )
1172 {
1173 return false;
1174 }
1175 else if( ret == wxID_OK )
1176 {
1177 footprintName = dlg.GetFPName();
1178 libraryName = dlg.GetTextSelection();
1179 done = true;
1180 }
1181 else if( ret == ID_MAKE_NEW_LIBRARY )
1182 {
1183 wxFileName newLibrary( CreateNewLibrary() );
1184 libraryName = newLibrary.GetName();
1185 }
1186 }
1187
1188 aFootprint->SetFPID( LIB_ID( libraryName, footprintName ) );
1189
1190 if( updateValue )
1191 aFootprint->SetValue( footprintName );
1192
1193 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
1194 return false;
1195
1196 // Once saved-as a board footprint is no longer a board footprint
1197 aFootprint->SetLink( niluuid );
1198
1199 wxString fmt = footprintExists ? _( "Footprint '%s' replaced in '%s'" )
1200 : _( "Footprint '%s' added to '%s'" );
1201
1202 wxString msg = wxString::Format( fmt, footprintName.GetData(), libraryName.GetData() );
1203 SetStatusText( msg );
1204 UpdateTitle();
1206
1207 return true;
1208}
1209
1210
1212{
1214 {
1215 wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1216 GetLoadedFPID().GetLibItemName().wx_str() );
1217
1218 if( ConfirmRevertDialog( this, msg ) )
1219 {
1220 Clear_Pcb( false );
1221 AddFootprintToBoard( static_cast<FOOTPRINT*>( m_originalFootprintCopy->Clone() ) );
1222
1223 Zoom_Automatique( false );
1224
1225 Update3DView( true, true );
1226
1228 GetScreen()->SetContentModified( false );
1229
1230 UpdateView();
1231 GetCanvas()->Refresh();
1232
1233 return true;
1234 }
1235 }
1236
1237 return false;
1238}
1239
1240
1241FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( wxString aFootprintName, const wxString& aLibName )
1242{
1243 if( aFootprintName.IsEmpty() )
1244 aFootprintName = _( "Untitled" );
1245
1246 int footprintAttrs = FP_SMD;
1247
1248 if( !aLibName.IsEmpty() )
1249 {
1251 wxArrayString fpnames;
1252 wxString baseName = aFootprintName;
1253 int idx = 1;
1254
1255 // Make sure the name is unique
1256 while( tbl->FootprintExists( aLibName, aFootprintName ) )
1257 aFootprintName = baseName + wxString::Format( wxS( "_%d" ), idx++ );
1258
1259 // Try to infer the footprint attributes from an existing footprint in the library
1260 try
1261 {
1262 tbl->FootprintEnumerate( fpnames, aLibName, true );
1263
1264 if( !fpnames.empty() )
1265 footprintAttrs = tbl->FootprintLoad( aLibName, fpnames.Last() )->GetAttributes();
1266 }
1267 catch( ... )
1268 {
1269 // best efforts
1270 }
1271 }
1272
1273 // Create the new footprint and add it to the head of the linked list of footprints
1274 FOOTPRINT* footprint = new FOOTPRINT( GetBoard() );
1275
1276 // Update its name in lib
1277 footprint->SetFPID( LIB_ID( wxEmptyString, aFootprintName ) );
1278
1279 footprint->SetAttributes( footprintAttrs );
1280
1281 PCB_LAYER_ID txt_layer;
1282 VECTOR2I default_pos;
1284
1285 footprint->Reference().SetText( settings.m_DefaultFPTextItems[0].m_Text );
1286 footprint->Reference().SetVisible( settings.m_DefaultFPTextItems[0].m_Visible );
1287 txt_layer = settings.m_DefaultFPTextItems[0].m_Layer;
1288 footprint->Reference().SetLayer( txt_layer );
1289 default_pos.y -= settings.GetTextSize( txt_layer ).y / 2;
1290 footprint->Reference().SetPosition( default_pos );
1291 default_pos.y += settings.GetTextSize( txt_layer ).y;
1292
1293 footprint->Value().SetText( settings.m_DefaultFPTextItems[1].m_Text );
1294 footprint->Value().SetVisible( settings.m_DefaultFPTextItems[1].m_Visible );
1295 txt_layer = settings.m_DefaultFPTextItems[1].m_Layer;
1296 footprint->Value().SetLayer( txt_layer );
1297 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1298 footprint->Value().SetPosition( default_pos );
1299 default_pos.y += settings.GetTextSize( txt_layer ).y;
1300
1301 for( size_t i = 2; i < settings.m_DefaultFPTextItems.size(); ++i )
1302 {
1303 PCB_TEXT* textItem = new PCB_TEXT( footprint );
1304 textItem->SetText( settings.m_DefaultFPTextItems[i].m_Text );
1305 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[i].m_Layer;
1306 textItem->SetLayer( txt_layer );
1307 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1308 textItem->SetPosition( default_pos );
1309 default_pos.y += settings.GetTextSize( txt_layer ).y;
1310 footprint->GraphicalItems().push_back( textItem );
1311 }
1312
1313 if( footprint->GetReference().IsEmpty() )
1314 footprint->SetReference( aFootprintName );
1315
1316 if( footprint->GetValue().IsEmpty() )
1317 footprint->SetValue( aFootprintName );
1318
1319 footprint->RunOnChildren(
1320 [&]( BOARD_ITEM* aChild )
1321 {
1322 if( aChild->Type() == PCB_FIELD_T || aChild->Type() == PCB_TEXT_T )
1323 {
1324 PCB_TEXT* textItem = static_cast<PCB_TEXT*>( aChild );
1325 PCB_LAYER_ID layer = textItem->GetLayer();
1326
1327 textItem->SetTextThickness( settings.GetTextThickness( layer ) );
1328 textItem->SetTextSize( settings.GetTextSize( layer ) );
1329 textItem->SetItalic( settings.GetTextItalic( layer ) );
1330 textItem->SetKeepUpright( settings.GetTextUpright( layer ) );
1331 }
1332 },
1333 RECURSE_MODE::RECURSE );
1334
1335 SetMsgPanel( footprint );
1336 return footprint;
1337}
1338
1339
1340wxString PCB_BASE_FRAME::SelectLibrary( const wxString& aNicknameExisting )
1341{
1342 wxArrayString headers;
1343
1344 headers.Add( _( "Nickname" ) );
1345 headers.Add( _( "Description" ) );
1346
1350 std::vector< wxArrayString > itemsToDisplay;
1351 std::vector< wxString > nicknames = fptbl->GetLogicalLibs();
1352
1353 for( const wxString& nickname : nicknames )
1354 {
1355 if( alg::contains( project.m_PinnedFootprintLibs, nickname )
1356 || alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1357 {
1358 wxArrayString item;
1359
1360 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
1361 item.Add( fptbl->GetDescription( nickname ) );
1362 itemsToDisplay.push_back( item );
1363 }
1364 }
1365
1366 for( const wxString& nickname : nicknames )
1367 {
1368 if( !alg::contains( project.m_PinnedFootprintLibs, nickname )
1369 && !alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1370 {
1371 wxArrayString item;
1372
1373 item.Add( nickname );
1374 item.Add( fptbl->GetDescription( nickname ) );
1375 itemsToDisplay.push_back( item );
1376 }
1377 }
1378
1379 EDA_LIST_DIALOG dlg( this, _( "Select Library" ), headers, itemsToDisplay, aNicknameExisting,
1380 false );
1381
1382 if( dlg.ShowModal() != wxID_OK )
1383 return wxEmptyString;
1384
1385 return dlg.GetTextSelection();
1386}
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
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:78
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:235
PCB_GROUP * GetParentGroup() const
Definition: board_item.h:94
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:286
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:297
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:897
void BuildListOfNets()
Definition: board.h:860
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:463
const FOOTPRINTS & Footprints() const
Definition: board.h:338
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:946
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
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:66
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int ShowModal() override
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 ReCreateHToolbar()
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:494
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:107
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:133
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:110
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:526
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:379
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:284
void SetKeepUpright(bool aKeepUpright)
Definition: eda_text.cpp:418
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:270
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition: eda_text.cpp:300
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
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:108
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()
Component library viewer main window.
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2456
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:254
void SetLink(const KIID &aLink)
Definition: footprint.h:845
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
Definition: footprint.cpp:2184
void SetAttributes(int aAttributes)
Definition: footprint.h:296
EDA_ITEM * Clone() const override
Invoke a function on all children.
Definition: footprint.cpp:2178
PCB_FIELD & Value()
read/write accessors:
Definition: footprint.h:655
void ApplyDefaultSettings(const BOARD &board, bool aStyleFields, bool aStyleText, bool aStyleShapes)
Apply default board settings to the footprint field text properties.
Definition: footprint.cpp:661
int GetAttributes() const
Definition: footprint.h:295
const LIB_ID & GetFPID() const
Definition: footprint.h:253
void SetReference(const wxString &aReference)
Definition: footprint.h:625
void SetValue(const wxString &aValue)
Definition: footprint.h:646
PCB_FIELD & Reference()
Definition: footprint.h:656
KIID GetLink() const
Definition: footprint.h:844
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:2338
const wxString & GetValue() const
Definition: footprint.h:641
const wxString & GetReference() const
Definition: footprint.h:619
DRAWINGS & GraphicalItems()
Definition: footprint.h:214
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.
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aNickname, bool aBestEfforts)
Return a list of footprint names contained within 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.
FOOTPRINT * FootprintLoad(const wxString &aNickname, const wxString &aFootprintName, bool aKeepUUID=false)
Load a footprint having aFootprintName from the library given by aNickname.
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: kidialog.h:43
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition: kidialog.cpp:51
int ShowModal() override
Definition: kidialog.cpp:95
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:195
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:100
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()
Handle the data for a net.
Definition: netinfo.h:56
const wxString & GetNetname() const
Definition: netinfo.h:114
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition: netinfo.h:372
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:99
static TOOL_ACTION recombinePad
Definition: pcb_actions.h:507
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:69
static TOOL_ACTION placeFootprint
Definition: pcb_actions.h:229
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.
void setFPWatcher(FOOTPRINT *aFootprint)
Create or removes a watcher on the specified footprint.
FOOTPRINT * CreateNewFootprint(wxString aFootprintName, const wxString &aLibName)
Create a new footprint at position 0,0.
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
Return the BOARD_DESIGN_SETTINGS for the open project.
void PlaceFootprint(FOOTPRINT *aFootprint, bool aRecreateRatsnest=true)
Place aFootprint at the current cursor position and updates footprint coordinates with the new positi...
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 ExchangeFootprint(FOOTPRINT *aExisting, FOOTPRINT *aNew, BOARD_COMMIT &aCommit, bool deleteExtraTexts=true, bool resetTextLayers=true, bool resetTextEffects=true, bool resetFabricationAttrs=true, bool resetTextContent=true, bool reset3DModels=true, bool *aUpdated=nullptr)
Replace aExisting footprint by aNew footprint using the Existing footprint settings (position,...
void ExportFootprintsToLibrary(bool aStoreInNewLib, const wxString &aLibName=wxEmptyString, wxString *aLibPath=nullptr)
Save footprints in a library:
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:52
A #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
void Format(const BOARD_ITEM *aItem) const
Output aItem to aFormatter in s-expression format.
std::string GetStringOutput(bool doClear)
static PLUGIN_REGISTRY * Instance()
Definition: pcb_io_mgr.h:94
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:69
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:77
@ 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:136
static const wxString ShowType(PCB_FILE_T aFileType)
Return a brief name for a plugin given aFileType enum.
Definition: pcb_io_mgr.cpp:78
virtual void SetPosition(const VECTOR2I &aPos) override
Definition: pcb_text.h:89
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:687
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:73
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:64
@ PCB_LIB_NICKNAME
Definition: project.h:227
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:146
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:203
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:318
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:329
bool TransferDataFromWindow() override
SAVE_AS_DIALOG(FOOTPRINT_EDIT_FRAME *aParent, const wxString &aFootprintName, const wxString &aLibraryPreselect, std::function< bool(wxString libName, wxString fpName)> aValidator)
SymLibNameValidator m_validator
std::function< bool(wxString libName, wxString fpName)> m_validator
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:171
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
Master controller class:
Definition: tool_manager.h:62
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:150
Handle a list of polygons defining a copper zone.
Definition: zone.h:74
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:425
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:249
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:221
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:194
bool ConfirmRevertDialog(wxWindow *parent, const wxString &aMessage)
Display a confirmation dialog for a revert action.
Definition: confirm.cpp:119
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
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:73
Helper functions to substitute paths with environmental variables.
@ FP_SMD
Definition: footprint.h:81
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:597
This file is part of the common library.
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:1071
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:43
std::vector< std::string > m_FileExtensions
Filter used for file pickers if m_IsFile is true.
Definition: io_base.h:47
wxString FileFilter() const
Definition: io_base.cpp:40
@ 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< int32_t > VECTOR2I
Definition: vector2d.h:695
VECTOR2< double > VECTOR2D
Definition: vector2d.h:694
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
Definition of file extensions used in Kicad.