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