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 <memory>
25#include <wx/ffile.h>
26#include <pgm_base.h>
27#include <kiface_base.h>
28#include <confirm.h>
29#include <kidialog.h>
30#include <macros.h>
31#include <pcb_edit_frame.h>
32#include <eda_list_dialog.h>
33#include <filter_reader.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>
48#include <env_paths.h>
49#include <paths.h>
51#include <project_pcb.h>
56#include <view/view_controls.h>
57#include <wx/filedlg.h>
58#include <wx/fswatcher.h>
59
60
61static constexpr int ID_MAKE_NEW_LIBRARY = 4173;
62
63
64// unique, "file local" translations:
65
66
67static const wxString INFO_LEGACY_LIB_WARN_EDIT(
68 _( "Writing/modifying legacy libraries (.mod files) is not allowed\n"\
69 "Please save the current library to the new .pretty format\n"\
70 "and update your footprint lib table\n"\
71 "to save your footprint (a .kicad_mod file) in the .pretty library folder" ) );
72
73static const wxString INFO_LEGACY_LIB_WARN_DELETE(
74 _( "Modifying legacy libraries (.mod files) is not allowed\n"\
75 "Please save the current library under the new .pretty format\n"\
76 "and update your footprint lib table\n"\
77 "before deleting a footprint" ) );
78
79
81{
82 wxFileName fn;
83
84 if( !aName.empty() )
85 {
86 fn = aName;
87 }
88 else
89 {
90 // Prompt the user for a footprint file to open.
91 static int lastFilterIndex = 0; // To store the last choice during a session.
92 wxString fileFiltersStr;
93 std::vector<std::string> allExtensions;
94 std::set<wxString> allWildcardsSet;
95
96 for( const auto& plugin : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
97 {
98 IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
99
100 if( !pi )
101 continue;
102
103 const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryFileDesc();
104
105 if( !desc )
106 continue;
107
108 if( !fileFiltersStr.IsEmpty() )
109 fileFiltersStr += wxChar( '|' );
110
111 fileFiltersStr += desc.FileFilter();
112
113 for( const std::string& ext : desc.m_FileExtensions )
114 {
115 allExtensions.emplace_back( ext );
116 allWildcardsSet.insert( wxT( "*." ) + formatWildcardExt( ext ) + wxT( ";" ) );
117 }
118 }
119
120 wxString allWildcardsStr;
121
122 for( const wxString& wildcard : allWildcardsSet )
123 allWildcardsStr << wildcard;
124
125 fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" )
126 + fileFiltersStr;
127
128 wxFileDialog dlg( this, _( "Import Footprint" ), m_mruPath, wxEmptyString, fileFiltersStr,
129 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
130
131 wxArrayString dummy1, dummy2;
132 const int nWildcards = wxParseCommonDialogsFilter( fileFiltersStr, dummy1, dummy2 );
133
134 if( lastFilterIndex >= 0 && lastFilterIndex < nWildcards )
135 dlg.SetFilterIndex( lastFilterIndex );
136
137 if( dlg.ShowModal() == wxID_CANCEL )
138 return nullptr;
139
140 lastFilterIndex = dlg.GetFilterIndex();
141
142 fn = dlg.GetPath();
143 }
144
145 if( !fn.IsOk() )
146 return nullptr;
147
148 if( !wxFileExists( fn.GetFullPath() ) )
149 {
150 wxString msg = wxString::Format( _( "File '%s' not found." ), fn.GetFullPath() );
151 DisplayError( this, msg );
152 return nullptr;
153 }
154
155 m_mruPath = fn.GetPath();
156
158
159 for( const auto& plugin : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
160 {
161 IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
162
163 if( !pi )
164 continue;
165
166 if( pi->GetLibraryFileDesc().m_FileExtensions.empty() )
167 continue;
168
169 if( pi->CanReadFootprint( fn.GetFullPath() ) )
170 {
171 fileType = plugin.m_type;
172 break;
173 }
174 }
175
177 {
178 DisplayError( this, _( "Not a footprint file." ) );
179 return nullptr;
180 }
181
182 FOOTPRINT* footprint = nullptr;
183 wxString footprintName;
184
185 try
186 {
188
189 footprint = pi->ImportFootprint( fn.GetFullPath(), footprintName);
190
191 if( !footprint )
192 {
193 wxString msg = wxString::Format( _( "Unable to load footprint '%s' from '%s'" ),
194 footprintName, fn.GetFullPath() );
195 DisplayError( this, msg );
196 return nullptr;
197 }
198 }
199 catch( const IO_ERROR& ioe )
200 {
201 DisplayError( this, ioe.What() );
202
203 // if the footprint is not loaded, exit.
204 // However, even if an error happens, it can be loaded, because in KICAD and GPCB format,
205 // a fp library is a set of separate files, and the error(s) are not necessary when
206 // reading the selected file
207
208 if( !footprint )
209 return nullptr;
210 }
211
212 footprint->SetFPID( LIB_ID( wxEmptyString, footprintName ) );
213
214 // Insert footprint in list
215 AddFootprintToBoard( footprint );
216
217 // Display info :
218 SetMsgPanel( footprint );
219 PlaceFootprint( footprint );
220
221 footprint->SetPosition( VECTOR2I( 0, 0 ) );
222
224 UpdateView();
225
226 return footprint;
227}
228
229
231{
232 wxFileName fn;
234
235 if( !aFootprint )
236 return;
237
238 fn.SetName( aFootprint->GetFPID().GetLibItemName() );
239
240 wxString wildcard = FILEEXT::KiCadFootprintLibFileWildcard();
241
243
244 if( !cfg->m_LastExportPath.empty() )
245 fn.SetPath( cfg->m_LastExportPath );
246 else
247 fn.SetPath( m_mruPath );
248
249 wxFileDialog dlg( this, _( "Export Footprint" ), fn.GetPath(), fn.GetFullName(),
250 wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
251
252 if( dlg.ShowModal() == wxID_CANCEL )
253 return;
254
256 cfg->m_LastExportPath = fn.GetPath();
257
258 try
259 {
260 // Export as *.kicad_pcb format, using a strategy which is specifically chosen
261 // as an example on how it could also be used to send it to the system clipboard.
262
264
265 /* This footprint should *already* be "normalized" in a way such that
266 orientation is zero, etc., since it came from the Footprint Editor.
267
268 aFootprint->SetParent( 0 );
269 aFootprint->SetOrientation( 0 );
270 */
271
272 pcb_io.Format( aFootprint );
273
274 FILE* fp = wxFopen( dlg.GetPath(), wxT( "wt" ) );
275
276 if( fp == nullptr )
277 {
278 DisplayErrorMessage( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
279 dlg.GetPath() ) );
280 return;
281 }
282
283 std::string prettyData = pcb_io.GetStringOutput( false );
284 KICAD_FORMAT::Prettify( prettyData, KICAD_FORMAT::FORMAT_MODE::NORMAL );
285
286 fprintf( fp, "%s", prettyData.c_str() );
287 fclose( fp );
288 }
289 catch( const IO_ERROR& ioe )
290 {
291 DisplayError( this, ioe.What() );
292 return;
293 }
294
295 wxString msg = wxString::Format( _( "Footprint exported to file '%s'." ), dlg.GetPath() );
296 DisplayInfoMessage( this, msg );
297}
298
299
300wxString PCB_BASE_EDIT_FRAME::CreateNewProjectLibrary( const wxString& aDialogTitle, const wxString& aLibName )
301{
302 return createNewLibrary( aDialogTitle, aLibName, wxEmptyString, LIBRARY_TABLE_SCOPE::PROJECT );
303}
304
305
306wxString PCB_BASE_EDIT_FRAME::CreateNewLibrary( const wxString& aDialogTitle, const wxString& aInitialPath )
307{
308 return createNewLibrary( aDialogTitle, wxEmptyString, aInitialPath );
309}
310
311
312wxString PCB_BASE_EDIT_FRAME::createNewLibrary( const wxString& aDialogTitle, const wxString& aLibName,
313 const wxString& aInitialPath, std::optional<LIBRARY_TABLE_SCOPE> aScope )
314{
315 // Kicad cannot write legacy format libraries, only .pretty new format because the legacy
316 // format cannot handle current features.
317 // The footprint library is actually a directory.
318
319 wxFileName fn;
320 bool doAdd = false;
321 bool isGlobal = false;
322 FILEDLG_HOOK_NEW_LIBRARY tableChooser( isGlobal );
323 FILEDLG_HOOK_NEW_LIBRARY* fileDlgHook = &tableChooser;
324
325 if( aScope )
326 fileDlgHook = nullptr;
327
328 if( aLibName.IsEmpty() )
329 {
330 fn = aInitialPath.IsEmpty() ? Prj().GetProjectPath() : aInitialPath;
331
332 if( !LibraryFileBrowser( aDialogTitle, false, fn, FILEEXT::KiCadFootprintLibPathWildcard(),
333 FILEEXT::KiCadFootprintLibPathExtension, false, fileDlgHook ) )
334 {
335 return wxEmptyString;
336 }
337
338 if( fileDlgHook )
339 {
340 isGlobal = fileDlgHook->GetUseGlobalTable();
342 }
343
344 doAdd = true;
345 }
346 else
347 {
349
350 if( !fn.IsAbsolute() )
351 {
352 fn.SetName( aLibName );
353 fn.MakeAbsolute( Prj().GetProjectPath() );
354 }
355 }
356
357 // We can save fp libs only using PCB_IO_MGR::KICAD_SEXP format (.pretty libraries)
359 wxString libPath = fn.GetFullPath();
360
361 try
362 {
364
365 bool writable = false;
366 bool exists = false;
367
368 try
369 {
370 writable = pi->IsLibraryWritable( libPath );
371 exists = true; // no exception was thrown, lib must exist.
372 }
373 catch( const IO_ERROR& )
374 {
375 // best efforts....
376 }
377
378 if( exists )
379 {
380 if( !writable )
381 {
382 wxString msg = wxString::Format( _( "Library %s is read only." ), libPath );
383 ShowInfoBarError( msg );
384 return wxEmptyString;
385 }
386 else
387 {
388 wxString msg = wxString::Format( _( "Library %s already exists." ), libPath );
389 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
390 dlg.SetOKLabel( _( "Overwrite" ) );
391 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
392
393 if( dlg.ShowModal() == wxID_CANCEL )
394 return wxEmptyString;
395
396 pi->DeleteLibrary( libPath );
397 }
398 }
399
400 pi->CreateLibrary( libPath );
401 }
402 catch( const IO_ERROR& ioe )
403 {
404 DisplayError( this, ioe.What() );
405 return wxEmptyString;
406 }
407
408 if( doAdd )
409 AddLibrary( aDialogTitle, libPath, aScope );
410
411 return libPath;
412}
413
414
415wxString PCB_BASE_EDIT_FRAME::SelectLibrary( const wxString& aDialogTitle, const wxString& aListLabel,
416 const std::vector<std::pair<wxString, bool*>>& aExtraCheckboxes )
417{
418 // Keep asking the user for a new name until they give a valid one or cancel the operation
419 while( true )
420 {
421 wxArrayString headers;
422 std::vector<wxArrayString> itemsToDisplay;
423
424 GetLibraryItemsForListDialog( headers, itemsToDisplay );
425
426 wxString libraryName = Prj().GetRString( PROJECT::PCB_LIB_NICKNAME );
427
428 EDA_LIST_DIALOG dlg( this, aDialogTitle, headers, itemsToDisplay, libraryName, false );
429 dlg.SetListLabel( aListLabel );
430
431 for( const auto& [label, val] : aExtraCheckboxes )
432 dlg.AddExtraCheckbox( label, val );
433
434 wxButton* newLibraryButton = new wxButton( &dlg, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
435 dlg.m_ButtonsSizer->Prepend( 80, 20 );
436 dlg.m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
437
438 newLibraryButton->Bind( wxEVT_BUTTON,
439 [&dlg]( wxCommandEvent& )
440 {
441 dlg.EndModal( ID_MAKE_NEW_LIBRARY );
443
444 dlg.Layout();
445 dlg.GetSizer()->Fit( &dlg );
446
447 int ret = dlg.ShowModal();
448
449 switch( ret )
450 {
451 case wxID_CANCEL:
452 return wxEmptyString;
453
454 case wxID_OK:
455 libraryName = dlg.GetTextSelection();
456 Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, libraryName );
458 return libraryName;
459
461 {
462 wxFileName fn = CreateNewLibrary( _( "New Footprint Library" ),
463 Prj().GetRString( PROJECT::PCB_LIB_PATH ) );
464
465 Prj().SetRString( PROJECT::PCB_LIB_PATH, fn.GetPath() );
466 Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, fn.GetName() );
467 break;
468 }
469
470 default:
471 break;
472 }
473 }
474}
475
476
477bool PCB_BASE_EDIT_FRAME::AddLibrary( const wxString& aDialogTitle, const wxString& aFilename,
478 std::optional<LIBRARY_TABLE_SCOPE> aScope )
479{
482 bool isGlobal = false;
483 FILEDLG_HOOK_NEW_LIBRARY tableChooser( isGlobal );
484 FILEDLG_HOOK_NEW_LIBRARY* fileDlgHook = &tableChooser;
485
486 if( aScope )
487 {
488 isGlobal = ( *aScope == LIBRARY_TABLE_SCOPE::GLOBAL );
489 fileDlgHook = nullptr;
490 }
491
492 wxFileName fn( aFilename );
493
494 if( aFilename.IsEmpty() )
495 {
496 if( !LibraryFileBrowser( aDialogTitle, true, fn, FILEEXT::KiCadFootprintLibPathWildcard(),
497 FILEEXT::KiCadFootprintLibPathExtension, true, fileDlgHook ) )
498 {
499 return false;
500 }
501
502 if( fileDlgHook )
503 isGlobal = fileDlgHook->GetUseGlobalTable();
504 }
505
507
508 wxString libPath = fn.GetFullPath();
509 wxString libName = fn.GetName();
510
511 if( libName.IsEmpty() )
512 return false;
513
515
516 if( lib_type == PCB_IO_MGR::FILE_TYPE_NONE )
517 lib_type = PCB_IO_MGR::KICAD_SEXP;
518
519 wxString type = PCB_IO_MGR::ShowType( lib_type );
520
521 // KiCad lib is our default guess. So it might not have the .pretty extension
522 // In this case, the extension is part of the library name
523 if( lib_type == PCB_IO_MGR::KICAD_SEXP && fn.GetExt() != FILEEXT::KiCadFootprintLibPathExtension )
524 libName = fn.GetFullName();
525
526 // try to use path normalized to an environmental variable or project path
527 wxString normalizedPath = NormalizePath( libPath, &Pgm().GetLocalEnvVariables(), &Prj() );
528 bool success = true;
529
530 try
531 {
532 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::FOOTPRINT, aScope.value() );
533 wxCHECK( optTable, false );
534 LIBRARY_TABLE* table = optTable.value();
535
536 LIBRARY_TABLE_ROW& row = table->InsertRow();
537
538 row.SetNickname( libName );
539 row.SetURI( normalizedPath );
540 row.SetType( type );
541
542 table->Save().map_error(
543 [&]( const LIBRARY_ERROR& aError )
544 {
545 wxMessageBox( _( "Error saving library table:\n\n" ) + aError.message,
546 _( "File Save Error" ), wxOK | wxICON_ERROR );
547 success = false;
548 } );
549 }
550 catch( const IO_ERROR& ioe )
551 {
552 DisplayError( this, ioe.What() );
553 return false;
554 }
555
556 if( success )
557 {
558 manager.ReloadTables( aScope.value(), { LIBRARY_TABLE_TYPE::FOOTPRINT } );
559 adapter->LoadOne( fn.GetName() );
560
561 // Don't use dynamic_cast; it will fail across compile units on MacOS
563 {
564 LIB_ID libID( libName, wxEmptyString );
565 editor->SyncLibraryTree( true );
566 editor->FocusOnLibID( libID );
567 }
568
569 auto viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_VIEWER, false );
570
571 if( viewer )
572 viewer->ReCreateLibraryList();
573 }
574
575 return success;
576}
577
578
580{
581 if( !aFPID.IsValid() )
582 return false;
583
586
587 wxString nickname = aFPID.GetLibNickname();
588 wxString fpname = aFPID.GetLibItemName();
589 wxString libfullname;
590
591 // Legacy libraries are readable, but modifying legacy format is not allowed
592 // So prompt the user if he try to delete a footprint from a legacy lib
593 if( std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, nickname ) )
594 libfullname = *optUri;
595 else
596 return false;
597
599 {
601 return false;
602 }
603
604 if( !adapter->IsFootprintLibWritable( nickname ) )
605 {
606 wxString msg = wxString::Format( _( "Library '%s' is read only." ), nickname );
607 ShowInfoBarError( msg );
608 return false;
609 }
610
611 // Confirmation
612 wxString msg = wxString::Format( _( "Delete footprint '%s' from library '%s'?" ),
613 fpname.GetData(),
614 nickname.GetData() );
615
616 if( aConfirm && !IsOK( this, msg ) )
617 return false;
618
619 try
620 {
621 adapter->DeleteFootprint( nickname, fpname );
622 }
623 catch( const IO_ERROR& ioe )
624 {
625 DisplayError( this, ioe.What() );
626 return false;
627 }
628
629 msg.Printf( _( "Footprint '%s' deleted from library '%s'" ),
630 fpname.GetData(),
631 nickname.GetData() );
632
633 SetStatusText( msg );
634
635 return true;
636}
637
638
639void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxString& aLibName,
640 wxString* aLibPath )
641{
642 if( GetBoard()->GetFirstFootprint() == nullptr )
643 {
644 DisplayInfoMessage( this, _( "No footprints to export!" ) );
645 return;
646 }
647
648 bool map = false;
649 PROJECT& prj = Prj();
650 wxString nickname = SelectLibrary( _( "Export Footprints" ), _( "Export footprints to library:" ),
651 { { _( "Update board footprints to link to exported footprints" ), &map } } );
652
653 if( !nickname ) // Aborted
654 return;
655
656 prj.SetRString( PROJECT::PCB_LIB_NICKNAME, nickname );
657
658 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
659 {
660 try
661 {
663
664 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
665 {
666 FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate( IGNORE_PARENT_GROUP ) );
667
668 // Reset reference designator, group membership, and zone offset before saving
669
670 fpCopy->SetReference( "REF**" );
671 fpCopy->SetParentGroup( nullptr );
672
673 for( ZONE* zone : fpCopy->Zones() )
674 zone->Move( -fpCopy->GetPosition() );
675
676 adapter->SaveFootprint( nickname, fpCopy, true );
677
678 delete fpCopy;
679 }
680 }
681 catch( const IO_ERROR& ioe )
682 {
683 DisplayError( this, ioe.What() );
684 }
685
686 if( map )
687 {
688 LIB_ID id = footprint->GetFPID();
689 id.SetLibNickname( nickname );
690 footprint->SetFPID( id );
691 }
692 }
693}
694
695
697{
698 if( !aFootprint ) // Happen if no footprint loaded
699 return false;
700
701 PAD_TOOL* padTool = m_toolManager->GetTool<PAD_TOOL>();
702
703 if( padTool->InPadEditMode() )
705
706 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
707 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
708 bool nameChanged = m_footprintNameWhenLoaded != footprintName;
709
710 if( aFootprint->GetLink() != niluuid )
711 {
712 if( SaveFootprintToBoard( false ) )
713 {
714 m_footprintNameWhenLoaded = footprintName;
715 return true;
716 }
717
718 return false;
719 }
720 else if( libraryName.IsEmpty() || footprintName.IsEmpty() )
721 {
722 if( SaveFootprintAs( aFootprint ) )
723 {
724 m_footprintNameWhenLoaded = footprintName;
725 SyncLibraryTree( true );
726 return true;
727 }
728
729 return false;
730 }
731
733
734 // Legacy libraries are readable, but modifying legacy format is not allowed
735 // So prompt the user if he try to add/replace a footprint in a legacy lib
736 wxString libfullname;
737
738 if( std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, libraryName ) )
739 libfullname = *optUri;
740 else
741 return false;
742
744 {
746 return false;
747 }
748
749 if( nameChanged )
750 {
751 LIB_ID oldFPID( libraryName, m_footprintNameWhenLoaded );
752 DeleteFootprintFromLibrary( oldFPID, false );
753 }
754
755 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
756 return false;
757
758 if( nameChanged )
759 {
760 m_footprintNameWhenLoaded = footprintName;
761 SyncLibraryTree( true );
762 }
763
764 return true;
765}
766
767
769{
772
773 LIB_ID fpID = aFootprint->GetFPID();
774 wxString libraryName = fpID.GetLibNickname();
775 wxString footprintName = fpID.GetLibItemName();
776
777 // Legacy libraries are readable, but modifying legacy format is not allowed
778 // So prompt the user if he try to add/replace a footprint in a legacy lib
779 if( std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, libraryName ) )
780 {
782 {
784 return false;
785 }
786 }
787 else
788 {
789 return false;
790 }
791
792 int i = 1;
793 wxString newName = footprintName;
794
795 // Append a number to the name until the name is unique in the library.
796 while( adapter->FootprintExists( libraryName, newName ) )
797 newName.Printf( "%s_%d", footprintName, i++ );
798
799 aFootprint->SetFPID( LIB_ID( libraryName, newName ) );
800
801 if( aFootprint->GetValue() == footprintName )
802 aFootprint->SetValue( newName );
803
804 return SaveFootprintInLibrary( aFootprint, libraryName );
805}
806
807
809 const wxString& aLibraryName )
810{
811 try
812 {
813 aFootprint->SetFPID( LIB_ID( wxEmptyString, aFootprint->GetFPID().GetLibItemName() ) );
814
816 adapter->SaveFootprint( aLibraryName, aFootprint );
817
818 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
819
820 if( aFootprint == GetBoard()->GetFirstFootprint() )
821 setFPWatcher( aFootprint );
822
823 return true;
824 }
825 catch( const IO_ERROR& ioe )
826 {
827 DisplayError( this, ioe.What() );
828
829 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
830 return false;
831 }
832}
833
834
836{
837 // update footprint in the current board,
838 // not just add it to the board with total disregard for the netlist...
839 PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB_EDITOR, false );
840
841 if( pcbframe == nullptr ) // happens when the board editor is not active (or closed)
842 {
843 ShowInfoBarError( _( "No board currently open." ) );
844 return false;
845 }
846
847 BOARD* mainpcb = pcbframe->GetBoard();
848 FOOTPRINT* sourceFootprint = nullptr;
849 FOOTPRINT* editorFootprint = GetBoard()->GetFirstFootprint();
850
851 if( !editorFootprint )
852 return false;
853
854 // Search the old footprint (source) if exists
855 // Because this source could be deleted when editing the main board...
856 if( editorFootprint->GetLink() != niluuid ) // this is not a new footprint ...
857 {
858 sourceFootprint = nullptr;
859
860 for( FOOTPRINT* candidate : mainpcb->Footprints() )
861 {
862 if( editorFootprint->GetLink() == candidate->m_Uuid )
863 {
864 sourceFootprint = candidate;
865 break;
866 }
867 }
868 }
869
870 if( !aAddNew && sourceFootprint == nullptr ) // source not found
871 {
872 DisplayError( this, _( "Unable to find the footprint on the main board.\nCannot save." ) );
873 return false;
874 }
875
876 TOOL_MANAGER* pcb_ToolManager = pcbframe->GetToolManager();
877
878 if( aAddNew && pcb_ToolManager->GetTool<BOARD_EDITOR_CONTROL>()->PlacingFootprint() )
879 {
880 DisplayError( this, _( "Previous footprint placement still in progress." ) );
881 return false;
882 }
883
885 BOARD_COMMIT commit( pcbframe );
886
887 // Create a copy for the board, first using Clone() to keep existing Uuids, and then either
888 // resetting the uuids to the board values or assigning new Uuids.
889 FOOTPRINT* newFootprint = static_cast<FOOTPRINT*>( editorFootprint->Clone() );
890 newFootprint->SetParent( mainpcb );
891 newFootprint->SetLink( niluuid );
892
893 auto fixUuid =
894 [&]( KIID& aUuid )
895 {
896 if( editorFootprint->GetLink() != niluuid && m_boardFootprintUuids.count( aUuid ) )
897 aUuid = m_boardFootprintUuids[ aUuid ];
898 else
899 aUuid = KIID();
900 };
901
902 fixUuid( const_cast<KIID&>( newFootprint->m_Uuid ) );
903
904 newFootprint->RunOnChildren(
905 [&]( BOARD_ITEM* aChild )
906 {
907 fixUuid( const_cast<KIID&>( aChild->m_Uuid ) );
908 },
910
911 // Right now, we only show the "Unconnected" net in the footprint editor, but this is still
912 // referenced in the footprint. So we need to update the net pointers in the footprint to
913 // point to the nets in the main board.
914 newFootprint->RunOnChildren(
915 [&]( BOARD_ITEM* aChild )
916 {
917 if( BOARD_CONNECTED_ITEM* conn = dynamic_cast<BOARD_CONNECTED_ITEM*>( aChild ) )
918 {
919 NETINFO_ITEM* net = conn->GetNet();
920 auto& netmap = mainpcb->GetNetInfo().NetsByName();
921
922 if( net )
923 {
924 auto it = netmap.find( net->GetNetname() );
925
926 if( it != netmap.end() )
927 conn->SetNet( it->second );
928 }
929
930 }
931 },
933
934 BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings();
935
938 bds.m_StyleFPBarcodes );
939
940 if( sourceFootprint ) // this is an update command
941 {
942 // In the main board the new footprint replaces the old one (pos, orient, ref, value,
943 // connections and properties are kept) and the sourceFootprint (old footprint) is
944 // deleted
945 pcbframe->ExchangeFootprint( sourceFootprint, newFootprint, commit );
946 commit.Push( _( "Update Footprint" ) );
947 }
948 else // This is an insert command
949 {
950 KIGFX::VIEW_CONTROLS* viewControls = pcbframe->GetCanvas()->GetViewControls();
951 VECTOR2D cursorPos = viewControls->GetCursorPosition();
952
953 commit.Add( newFootprint );
954 viewControls->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
955 pcbframe->PlaceFootprint( newFootprint );
956 newFootprint->SetPosition( VECTOR2I( 0, 0 ) );
957 viewControls->SetCrossHairCursorPosition( cursorPos, false );
958 const_cast<KIID&>( newFootprint->m_Uuid ) = KIID();
959 commit.Push( _( "Insert Footprint" ) );
960
961 pcbframe->Raise();
962 pcb_ToolManager->RunAction( PCB_ACTIONS::placeFootprint, newFootprint );
963 }
964
965 newFootprint->ClearFlags();
966
967 return true;
968}
969
970
972{
973public:
974 SAVE_AS_DIALOG( FOOTPRINT_EDIT_FRAME* aParent, const wxString& aFootprintName,
975 const wxString& aLibraryPreselect,
976 std::function<bool( wxString libName, wxString fpName )> aValidator ) :
977 EDA_LIST_DIALOG( aParent, _( "Save Footprint As" ), false ),
978 m_validator( std::move( aValidator ) )
979 {
981 std::vector<wxString> nicknames = adapter->GetLibraryNames();
982 wxArrayString headers;
983 std::vector<wxArrayString> itemsToDisplay;
984
985 aParent->GetLibraryItemsForListDialog( headers, itemsToDisplay );
986 initDialog( headers, itemsToDisplay, aLibraryPreselect );
987
988 SetListLabel( _( "Save in library:" ) );
989 SetOKLabel( _( "Save" ) );
990
991 wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
992
993 wxStaticText* label = new wxStaticText( this, wxID_ANY, _( "Name:" ) );
994 bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
995
996 m_fpNameCtrl = new wxTextCtrl( this, wxID_ANY, aFootprintName );
997 bNameSizer->Add( m_fpNameCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
998
999 wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST );
1000 nameValidator.SetCharExcludes( FOOTPRINT::StringLibNameInvalidChars( false ) );
1001 m_fpNameCtrl->SetValidator( nameValidator );
1002
1003 wxButton* newLibraryButton = new wxButton( this, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
1004 m_ButtonsSizer->Prepend( 80, 20 );
1005 m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
1006
1007 GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
1008
1009 // If a footprint name was specified, disable loading of previously-saved state
1010 if( !aFootprintName.IsEmpty() )
1012
1013 Bind( wxEVT_BUTTON,
1014 [this]( wxCommandEvent& )
1015 {
1016 EndModal( ID_MAKE_NEW_LIBRARY );
1018
1019 // Move nameTextCtrl to the head of the tab-order
1020 if( GetChildren().DeleteObject( m_fpNameCtrl ) )
1021 GetChildren().Insert( m_fpNameCtrl );
1022
1024
1026
1027 Layout();
1028 GetSizer()->Fit( this );
1029
1030 Centre();
1031 }
1032
1033 wxString GetFPName()
1034 {
1035 wxString footprintName = m_fpNameCtrl->GetValue();
1036 footprintName.Trim( true );
1037 footprintName.Trim( false );
1038 return footprintName;
1039 }
1040
1041protected:
1042 bool TransferDataToWindow() override
1043 {
1044 // Respond to any filter text loaded from previously-saved state
1045 wxCommandEvent dummy;
1047
1048 return true;
1049 }
1050
1052 {
1053 return m_validator( GetTextSelection(), GetFPName() );
1054 }
1055
1056private:
1057 wxTextCtrl* m_fpNameCtrl;
1058 std::function<bool( wxString libName, wxString fpName )> m_validator;
1059};
1060
1061
1063{
1064 if( aFootprint == nullptr )
1065 return false;
1066
1067 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
1069
1070 SetMsgPanel( aFootprint );
1071
1072 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
1073 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
1074 bool updateValue = aFootprint->GetValue() == footprintName;
1075 bool done = false;
1076 bool footprintExists = false;
1077
1078 while( !done )
1079 {
1080 SAVE_AS_DIALOG dlg( this, footprintName, libraryName,
1081 [&]( const wxString& newLib, const wxString& newName )
1082 {
1083 if( newLib.IsEmpty() )
1084 {
1085 wxMessageBox( _( "A library must be specified." ) );
1086 return false;
1087 }
1088
1089 if( newName.IsEmpty() )
1090 {
1091 wxMessageBox( _( "Footprint must have a name." ) );
1092 return false;
1093 }
1094
1095 // Legacy libraries are readable, but modifying legacy format is not allowed
1096 // So prompt the user if he try to add/replace a footprint in a legacy lib
1097 if( std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, newLib ) )
1098 {
1100 {
1102 return false;
1103 }
1104 }
1105 else
1106 {
1107 return false;
1108 }
1109
1110 footprintExists = adapter->FootprintExists( newLib, newName );
1111
1112 if( footprintExists )
1113 {
1114 wxString msg = wxString::Format( _( "Footprint %s already exists in %s." ),
1115 newName,
1116 newLib );
1117
1118 KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1119 errorDlg.SetOKLabel( _( "Overwrite" ) );
1120
1121 return errorDlg.ShowModal() == wxID_OK;
1122 }
1123
1124 return true;
1125 } );
1126
1127 int ret = dlg.ShowModal();
1128
1129 if( ret == wxID_CANCEL )
1130 {
1131 return false;
1132 }
1133 else if( ret == wxID_OK )
1134 {
1135 footprintName = dlg.GetFPName();
1136 libraryName = dlg.GetTextSelection();
1137 done = true;
1138 }
1139 else if( ret == ID_MAKE_NEW_LIBRARY )
1140 {
1141 wxFileName fn = CreateNewLibrary( _( "New Footprint Library" ),
1142 Prj().GetRString( PROJECT::PCB_LIB_PATH ) );
1143
1144 Prj().SetRString( PROJECT::PCB_LIB_PATH, fn.GetPath() );
1145 Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, fn.GetName() );
1146 libraryName = fn.GetName();
1147 }
1148 }
1149
1150 aFootprint->SetFPID( LIB_ID( libraryName, footprintName ) );
1151
1152 if( updateValue )
1153 aFootprint->SetValue( footprintName );
1154
1155 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
1156 return false;
1157
1158 // Once saved-as a board footprint is no longer a board footprint
1159 aFootprint->SetLink( niluuid );
1160
1161 wxString fmt = footprintExists ? _( "Footprint '%s' replaced in '%s'" )
1162 : _( "Footprint '%s' added to '%s'" );
1163
1164 wxString msg = wxString::Format( fmt, footprintName.GetData(), libraryName.GetData() );
1165 SetStatusText( msg );
1166 UpdateTitle();
1168
1169 return true;
1170}
1171
1172
1174{
1176 {
1177 wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1178 GetLoadedFPID().GetLibItemName().wx_str() );
1179
1180 if( ConfirmRevertDialog( this, msg ) )
1181 {
1182 Clear_Pcb( false );
1183 AddFootprintToBoard( static_cast<FOOTPRINT*>( m_originalFootprintCopy->Clone() ) );
1184
1185 Zoom_Automatique( false );
1186
1187 Update3DView( true, true );
1188
1190 GetScreen()->SetContentModified( false );
1191
1192 UpdateView();
1193 GetCanvas()->Refresh();
1194
1195 return true;
1196 }
1197 }
1198
1199 return false;
1200}
1201
1202
1203FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( wxString aFootprintName, const wxString& aLibName )
1204{
1205 if( aFootprintName.IsEmpty() )
1206 aFootprintName = _( "Untitled" );
1207
1208 int footprintAttrs = FP_SMD;
1209
1210 if( !aLibName.IsEmpty() )
1211 {
1213 std::vector<wxString> fpnames;
1214 wxString baseName = aFootprintName;
1215 int idx = 1;
1216
1217 // Make sure the name is unique
1218 while( adapter->FootprintExists( aLibName, aFootprintName ) )
1219 aFootprintName = baseName + wxString::Format( wxS( "_%d" ), idx++ );
1220
1221 // Try to infer the footprint attributes from an existing footprint in the library
1222 try
1223 {
1224 fpnames = adapter->GetFootprintNames( aLibName, true );
1225
1226 if( !fpnames.empty() )
1227 {
1228 std::unique_ptr<FOOTPRINT> fp( adapter->LoadFootprint( aLibName, fpnames.back(), false ) );
1229
1230 if( fp )
1231 footprintAttrs = fp->GetAttributes();
1232 }
1233 }
1234 catch( ... )
1235 {
1236 // best efforts
1237 }
1238 }
1239
1240 // Create the new footprint and add it to the head of the linked list of footprints
1241 FOOTPRINT* footprint = new FOOTPRINT( GetBoard() );
1242
1243 // Update its name in lib
1244 footprint->SetFPID( LIB_ID( wxEmptyString, aFootprintName ) );
1245
1246 footprint->SetAttributes( footprintAttrs );
1247
1248 PCB_LAYER_ID txt_layer;
1249 VECTOR2I default_pos;
1251
1252 if( settings.m_DefaultFPTextItems.size() > 0 )
1253 {
1254 footprint->Reference().SetText( settings.m_DefaultFPTextItems[0].m_Text );
1255 footprint->Reference().SetVisible( settings.m_DefaultFPTextItems[0].m_Visible );
1256 }
1257
1258 txt_layer = settings.m_DefaultFPTextItems[0].m_Layer;
1259 footprint->Reference().SetLayer( txt_layer );
1260 default_pos.y -= settings.GetTextSize( txt_layer ).y / 2;
1261 footprint->Reference().SetPosition( default_pos );
1262 default_pos.y += settings.GetTextSize( txt_layer ).y;
1263
1264 if( settings.m_DefaultFPTextItems.size() > 1 )
1265 {
1266 footprint->Value().SetText( settings.m_DefaultFPTextItems[1].m_Text );
1267 footprint->Value().SetVisible( settings.m_DefaultFPTextItems[1].m_Visible );
1268 }
1269
1270 txt_layer = settings.m_DefaultFPTextItems[1].m_Layer;
1271 footprint->Value().SetLayer( txt_layer );
1272 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1273 footprint->Value().SetPosition( default_pos );
1274 default_pos.y += settings.GetTextSize( txt_layer ).y;
1275
1276 for( size_t i = 2; i < settings.m_DefaultFPTextItems.size(); ++i )
1277 {
1278 PCB_TEXT* textItem = new PCB_TEXT( footprint );
1279 textItem->SetText( settings.m_DefaultFPTextItems[i].m_Text );
1280 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[i].m_Layer;
1281 textItem->SetLayer( txt_layer );
1282 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1283 textItem->SetPosition( default_pos );
1284 default_pos.y += settings.GetTextSize( txt_layer ).y;
1285 footprint->GraphicalItems().push_back( textItem );
1286 }
1287
1288 if( footprint->GetReference().IsEmpty() )
1289 footprint->SetReference( aFootprintName );
1290
1291 if( footprint->GetValue().IsEmpty() )
1292 footprint->SetValue( aFootprintName );
1293
1294 footprint->RunOnChildren(
1295 [&]( BOARD_ITEM* aChild )
1296 {
1297 if( aChild->Type() == PCB_FIELD_T || aChild->Type() == PCB_TEXT_T )
1298 {
1299 PCB_TEXT* textItem = static_cast<PCB_TEXT*>( aChild );
1300 PCB_LAYER_ID layer = textItem->GetLayer();
1301
1302 textItem->SetTextThickness( settings.GetTextThickness( layer ) );
1303 textItem->SetTextSize( settings.GetTextSize( layer ) );
1304 textItem->SetItalic( settings.GetTextItalic( layer ) );
1305 textItem->SetKeepUpright( settings.GetTextUpright( layer ) );
1306 }
1307 },
1309
1310 SetMsgPanel( footprint );
1311 return footprint;
1312}
1313
1314
1316 std::vector<wxArrayString>& aItemsToDisplay )
1317{
1318 aHeaders.Add( _( "Library" ) );
1319 aHeaders.Add( _( "Description" ) );
1320
1324 std::vector<wxString> nicknames = adapter->GetLibraryNames();
1325 std::vector<wxArrayString> unpinned;
1326
1327 for( const wxString& nickname : nicknames )
1328 {
1329 wxArrayString item;
1330 wxString description = adapter->GetLibraryDescription( nickname ).value_or( wxEmptyString );
1331
1332 if( alg::contains( project.m_PinnedFootprintLibs, nickname )
1333 || alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1334 {
1335 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
1336 item.Add( description );
1337 aItemsToDisplay.push_back( item );
1338 }
1339 else
1340 {
1341 item.Add( nickname );
1342 item.Add( description );
1343 unpinned.push_back( item );
1344 }
1345 }
1346
1347 std::ranges::copy( unpinned, std::back_inserter( aItemsToDisplay ) );
1348}
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:224
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:83
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:236
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:284
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
const NETINFO_LIST & GetNetInfo() const
Definition board.h:955
void BuildListOfNets()
Definition board.h:918
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition board.h:505
const FOOTPRINTS & Footprints() const
Definition board.h:363
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition commit.h:78
void OptOut(wxWindow *aWindow)
Opt out of control state saving.
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:82
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...
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
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.
bool LibraryFileBrowser(const wxString &aTitle, bool doOpen, wxFileName &aFilename, const wxString &wildcard, const wxString &ext, bool isDirectory, FILEDLG_HOOK_NEW_LIBRARY *aFileDlgHook=nullptr)
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:516
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:144
virtual void SetParentGroup(EDA_GROUP *aGroup)
Definition eda_item.h:115
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
A dialog which shows:
void textChangeInFilterBox(wxCommandEvent &event) override
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 AddExtraCheckbox(const wxString &aLabel, bool *aValuePtr)
Add a checkbox value to the dialog.
void GetExtraCheckboxValues()
Fills in the value pointers from the checkboxes after the dialog has run.
EDA_LIST_DIALOG(wxWindow *aParent, const wxString &aTitle, const wxArrayString &aItemHeaders, const std::vector< wxArrayString > &aItemList, const wxString &aPreselectText=wxEmptyString, bool aSortList=true)
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:540
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:394
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition eda_text.cpp:292
void SetKeepUpright(bool aKeepUpright)
Definition eda_text.cpp:433
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:278
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition eda_text.cpp:315
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()
An interface to the global shared library manager that is schematic-specific and linked to one projec...
bool IsFootprintLibWritable(const wxString &aNickname)
Return true if the library given by aNickname is writable.
void DeleteFootprint(const wxString &aNickname, const wxString &aFootprintName)
Deletes the aFootprintName from the library given by aNickname.
SAVE_T SaveFootprint(const wxString &aNickname, const FOOTPRINT *aFootprint, bool aOverwrite=true)
Write aFootprint to an existing library given by aNickname.
std::vector< wxString > GetFootprintNames(const wxString &aNickname, bool aBestEfforts=false)
Retrieves a list of footprint names contained in a given loaded library.
FOOTPRINT * LoadFootprint(const wxString &aNickname, const wxString &aName, bool aKeepUUID)
Load a FOOTPRINT having aName from the library given by aNickname.
std::optional< LIB_STATUS > LoadOne(LIB_DATA *aLib) override
Loads or reloads the given library, if it exists.
bool FootprintExists(const wxString &aNickname, const wxString &aName)
Component library viewer main window.
void SetPosition(const VECTOR2I &aPos) override
void SetFPID(const LIB_ID &aFPID)
Definition footprint.h:270
void SetLink(const KIID &aLink)
Definition footprint.h:887
ZONES & Zones()
Definition footprint.h:230
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
void SetAttributes(int aAttributes)
Definition footprint.h:328
EDA_ITEM * Clone() const override
Invoke a function on all children.
PCB_FIELD & Value()
read/write accessors:
Definition footprint.h:697
const LIB_ID & GetFPID() const
Definition footprint.h:269
void SetReference(const wxString &aReference)
Definition footprint.h:667
void ApplyDefaultSettings(const BOARD &board, bool aStyleFields, bool aStyleText, bool aStyleShapes, bool aStyleDimensions, bool aStyleBarcodes)
Apply default board settings to the footprint field text properties.
void SetValue(const wxString &aValue)
Definition footprint.h:688
PCB_FIELD & Reference()
Definition footprint.h:698
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
KIID GetLink() const
Definition footprint.h:886
static const wxChar * StringLibNameInvalidChars(bool aUserReadable)
Test for validity of the name in a library of the footprint ( no spaces, dir separators ....
const wxString & GetValue() const
Definition footprint.h:683
const wxString & GetReference() const
Definition footprint.h:661
VECTOR2I GetPosition() const override
Definition footprint.h:245
DRAWINGS & GraphicalItems()
Definition footprint.h:227
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:42
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition kidialog.cpp:55
int ShowModal() override
Definition kidialog.cpp:93
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:403
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition kiway.cpp:200
std::optional< wxString > GetLibraryDescription(const wxString &aNickname) const
std::vector< wxString > GetLibraryNames() const
Returns a list of library nicknames that are available (skips any that failed to load)
void ReloadTables(LIBRARY_TABLE_SCOPE aScope, std::initializer_list< LIBRARY_TABLE_TYPE > aTablesToLoad={})
std::optional< LIBRARY_TABLE * > Table(LIBRARY_TABLE_TYPE aType, LIBRARY_TABLE_SCOPE aScope)
Retrieves a given table; creating a new empty project table if a valid project is loaded and the give...
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
void SetURI(const wxString &aUri)
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
static const wxString GetPinningSymbol()
Handle the data for a net.
Definition netinfo.h:54
const wxString & GetNetname() const
Definition netinfo.h:112
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition netinfo.h:238
bool InPadEditMode()
Definition pad_tool.h:63
static TOOL_ACTION recombinePad
static TOOL_ACTION placeFootprint
wxString CreateNewLibrary(const wxString &aDialogTitle, const wxString &aInitialPath=wxEmptyString)
If a library name is given, creates a new footprint library in the project folder with the given name...
wxString SelectLibrary(const wxString &aDialogTitle, const wxString &aListLabel, const std::vector< std::pair< wxString, bool * > > &aExtraCheckboxes={})
Put up a dialog and allows the user to pick a library, for unspecified use.
wxString createNewLibrary(const wxString &aDialogTitle, const wxString &aLibName, const wxString &aInitialPath, std::optional< LIBRARY_TABLE_SCOPE > aScope=std::nullopt)
Create a new library in the given table.
wxString CreateNewProjectLibrary(const wxString &aDialogTitle, const wxString &aLibName)
bool AddLibrary(const wxString &aDialogTitle, const wxString &aLibName=wxEmptyString, std::optional< LIBRARY_TABLE_SCOPE > aScope=std::nullopt)
Add an existing library to either the global or project library table.
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.
void GetLibraryItemsForListDialog(wxArrayString &aHeaders, std::vector< wxArrayString > &aItemsToDisplay)
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
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, std::optional< VECTOR2I > aPosition=std::nullopt)
Place aFootprint at the current cursor position (or provided one) and updates footprint coordinates w...
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 resetTextPositions=true, bool resetTextContent=true, bool resetFabricationAttrs=true, bool resetClearanceOverrides=true, bool reset3DModels=true, bool *aUpdated=nullptr)
Replace aExisting footprint by aNew footprint using the Existing footprint settings (position,...
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:95
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
@ 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_IO * FindPlugin(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a footprint library's libPath.
static const wxString ShowType(PCB_FILE_T aFileType)
Return a brief name for a plugin given aFileType enum.
virtual void SetPosition(const VECTOR2I &aPos) override
Definition pcb_text.h:84
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:537
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:131
The backing store for a PROJECT, in JSON format.
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
Container for project specific data.
Definition project.h:65
@ PCB_LIB_PATH
Definition project.h:223
@ PCB_LIB_NICKNAME
Definition project.h:224
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:167
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:199
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:339
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:350
bool TransferDataFromWindow() override
SAVE_AS_DIALOG(FOOTPRINT_EDIT_FRAME *aParent, const wxString &aFootprintName, const wxString &aLibraryPreselect, std::function< bool(wxString libName, wxString fpName)> aValidator)
bool TransferDataToWindow() override
std::function< bool(wxString libName, wxString fpName)> m_validator
TOOL_MANAGER * m_toolManager
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Master controller class:
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
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:580
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:259
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:230
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
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:177
This file is part of the common library.
#define _(s)
@ RECURSE
Definition eda_item.h:51
#define IGNORE_PARENT_GROUP
Definition eda_item.h:55
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:82
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 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"))
static constexpr int ID_MAKE_NEW_LIBRARY
@ 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:629
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, FORMAT_MODE aMode)
Pretty-prints s-expression text according to KiCad format rules.
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:946
see class PGM_BASE
KIWAY Kiway(KFCTL_STANDALONE)
std::vector< FAB_LAYER_COLOR > dummy
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
wxString message
@ 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.