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