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