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