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