KiCad PCB EDA Suite
Loading...
Searching...
No Matches
footprint_libraries_utils.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <wx/ffile.h>
25#include <pgm_base.h>
26#include <kiface_base.h>
27#include <confirm.h>
28#include <kidialog.h>
29#include <macros.h>
30#include <pcb_edit_frame.h>
31#include <eda_list_dialog.h>
32#include <filter_reader.h>
34#include <validators.h>
36#include <tool/tool_manager.h>
37#include <tools/pcb_actions.h>
39#include <tools/pad_tool.h>
40#include <footprint.h>
41#include <zone.h>
42#include <pcb_group.h>
47#include <env_paths.h>
48#include <paths.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
136 if( dlg.ShowModal() == wxID_CANCEL )
137 return nullptr;
138
139 lastFilterIndex = dlg.GetFilterIndex();
140
141 fn = dlg.GetPath();
142 }
143
144 if( !fn.IsOk() )
145 return nullptr;
146
147 if( !wxFileExists( fn.GetFullPath() ) )
148 {
149 wxString msg = wxString::Format( _( "File '%s' not found." ), fn.GetFullPath() );
150 DisplayError( this, msg );
151 return nullptr;
152 }
153
154 m_mruPath = fn.GetPath();
155
157
158 for( const auto& plugin : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
159 {
160 IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
161
162 if( !pi )
163 continue;
164
165 if( pi->GetLibraryFileDesc().m_FileExtensions.empty() )
166 continue;
167
168 if( pi->CanReadFootprint( fn.GetFullPath() ) )
169 {
170 fileType = plugin.m_type;
171 break;
172 }
173 }
174
176 {
177 DisplayError( this, _( "Not a footprint file." ) );
178 return nullptr;
179 }
180
181 FOOTPRINT* footprint = nullptr;
182 wxString footprintName;
183
184 try
185 {
187
188 footprint = pi->ImportFootprint( fn.GetFullPath(), footprintName);
189
190 if( !footprint )
191 {
192 wxString msg = wxString::Format( _( "Unable to load footprint '%s' from '%s'" ),
193 footprintName, fn.GetFullPath() );
194 DisplayError( this, msg );
195 return nullptr;
196 }
197 }
198 catch( const IO_ERROR& ioe )
199 {
200 DisplayError( this, ioe.What() );
201
202 // if the footprint is not loaded, exit.
203 // However, even if an error happens, it can be loaded, because in KICAD and GPCB format,
204 // a fp library is a set of separate files, and the error(s) are not necessary when
205 // reading the selected file
206
207 if( !footprint )
208 return nullptr;
209 }
210
211 footprint->SetFPID( LIB_ID( wxEmptyString, footprintName ) );
212
213 // Insert footprint in list
214 AddFootprintToBoard( footprint );
215
216 // Display info :
217 SetMsgPanel( footprint );
218 PlaceFootprint( footprint );
219
220 footprint->SetPosition( VECTOR2I( 0, 0 ) );
221
223 UpdateView();
224
225 return footprint;
226}
227
228
230{
231 wxFileName fn;
233
234 if( !aFootprint )
235 return;
236
237 fn.SetName( aFootprint->GetFPID().GetLibItemName() );
238
239 wxString wildcard = FILEEXT::KiCadFootprintLibFileWildcard();
240
242
243 if( !cfg->m_LastExportPath.empty() )
244 fn.SetPath( cfg->m_LastExportPath );
245 else
246 fn.SetPath( m_mruPath );
247
248 wxFileDialog dlg( this, _( "Export Footprint" ), fn.GetPath(), fn.GetFullName(),
249 wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
250
251 if( dlg.ShowModal() == wxID_CANCEL )
252 return;
253
255 cfg->m_LastExportPath = fn.GetPath();
256
257 try
258 {
259 // Export as *.kicad_pcb format, using a strategy which is specifically chosen
260 // as an example on how it could also be used to send it to the system clipboard.
261
263
264 /* This footprint should *already* be "normalized" in a way such that
265 orientation is zero, etc., since it came from the Footprint Editor.
266
267 aFootprint->SetParent( 0 );
268 aFootprint->SetOrientation( 0 );
269 */
270
271 pcb_io.Format( aFootprint );
272
273 FILE* fp = wxFopen( dlg.GetPath(), wxT( "wt" ) );
274
275 if( fp == nullptr )
276 {
277 DisplayErrorMessage( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
278 dlg.GetPath() ) );
279 return;
280 }
281
282 std::string prettyData = pcb_io.GetStringOutput( false );
283 KICAD_FORMAT::Prettify( prettyData, KICAD_FORMAT::FORMAT_MODE::NORMAL );
284
285 fprintf( fp, "%s", prettyData.c_str() );
286 fclose( fp );
287 }
288 catch( const IO_ERROR& ioe )
289 {
290 DisplayError( this, ioe.What() );
291 return;
292 }
293
294 wxString msg = wxString::Format( _( "Footprint exported to file '%s'." ), dlg.GetPath() );
295 DisplayInfoMessage( this, msg );
296}
297
298
299wxString PCB_BASE_EDIT_FRAME::CreateNewProjectLibrary( const wxString& aDialogTitle, const wxString& aLibName )
300{
301 return createNewLibrary( aDialogTitle, aLibName, wxEmptyString, LIBRARY_TABLE_SCOPE::PROJECT );
302}
303
304
305wxString PCB_BASE_EDIT_FRAME::CreateNewLibrary( const wxString& aDialogTitle, const wxString& aInitialPath )
306{
307 return createNewLibrary( aDialogTitle, wxEmptyString, aInitialPath );
308}
309
310
311wxString PCB_BASE_EDIT_FRAME::createNewLibrary( const wxString& aDialogTitle, const wxString& aLibName,
312 const wxString& aInitialPath, std::optional<LIBRARY_TABLE_SCOPE> aScope )
313{
314 // Kicad cannot write legacy format libraries, only .pretty new format because the legacy
315 // format cannot handle current features.
316 // The footprint library is actually a directory.
317
318 wxFileName fn;
319 bool doAdd = false;
320 bool isGlobal = false;
321 FILEDLG_HOOK_NEW_LIBRARY tableChooser( isGlobal );
322 FILEDLG_HOOK_NEW_LIBRARY* fileDlgHook = &tableChooser;
323
324 if( aScope )
325 fileDlgHook = nullptr;
326
327 if( aLibName.IsEmpty() )
328 {
329 fn = aInitialPath.IsEmpty() ? Prj().GetProjectPath() : aInitialPath;
330
331 if( !LibraryFileBrowser( aDialogTitle, false, fn, FILEEXT::KiCadFootprintLibPathWildcard(),
332 FILEEXT::KiCadFootprintLibPathExtension, false, fileDlgHook ) )
333 {
334 return wxEmptyString;
335 }
336
337 if( fileDlgHook )
338 {
339 isGlobal = fileDlgHook->GetUseGlobalTable();
341 }
342
343 doAdd = true;
344 }
345 else
346 {
348
349 if( !fn.IsAbsolute() )
350 {
351 fn.SetName( aLibName );
352 fn.MakeAbsolute( Prj().GetProjectPath() );
353 }
354 }
355
356 // We can save fp libs only using PCB_IO_MGR::KICAD_SEXP format (.pretty libraries)
358 wxString libPath = fn.GetFullPath();
359
360 try
361 {
363
364 bool writable = false;
365 bool exists = false;
366
367 try
368 {
369 writable = pi->IsLibraryWritable( libPath );
370 exists = true; // no exception was thrown, lib must exist.
371 }
372 catch( const IO_ERROR& )
373 {
374 // best efforts....
375 }
376
377 if( exists )
378 {
379 if( !writable )
380 {
381 wxString msg = wxString::Format( _( "Library %s is read only." ), libPath );
382 ShowInfoBarError( msg );
383 return wxEmptyString;
384 }
385 else
386 {
387 wxString msg = wxString::Format( _( "Library %s already exists." ), libPath );
388 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
389 dlg.SetOKLabel( _( "Overwrite" ) );
390 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
391
392 if( dlg.ShowModal() == wxID_CANCEL )
393 return wxEmptyString;
394
395 pi->DeleteLibrary( libPath );
396 }
397 }
398
399 pi->CreateLibrary( libPath );
400 }
401 catch( const IO_ERROR& ioe )
402 {
403 DisplayError( this, ioe.What() );
404 return wxEmptyString;
405 }
406
407 if( doAdd )
408 AddLibrary( aDialogTitle, libPath, aScope );
409
410 return libPath;
411}
412
413
414wxString PCB_BASE_EDIT_FRAME::SelectLibrary( const wxString& aDialogTitle, const wxString& aListLabel,
415 const std::vector<std::pair<wxString, bool*>>& aExtraCheckboxes )
416{
417 // Keep asking the user for a new name until they give a valid one or cancel the operation
418 while( true )
419 {
420 wxArrayString headers;
421 std::vector<wxArrayString> itemsToDisplay;
422
423 GetLibraryItemsForListDialog( headers, itemsToDisplay );
424
425 wxString libraryName = Prj().GetRString( PROJECT::PCB_LIB_NICKNAME );
426
427 EDA_LIST_DIALOG dlg( this, aDialogTitle, headers, itemsToDisplay, libraryName, false );
428 dlg.SetListLabel( aListLabel );
429
430 for( const auto& [label, val] : aExtraCheckboxes )
431 dlg.AddExtraCheckbox( label, val );
432
433 wxButton* newLibraryButton = new wxButton( &dlg, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
434 dlg.m_ButtonsSizer->Prepend( 80, 20 );
435 dlg.m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
436
437 newLibraryButton->Bind( wxEVT_BUTTON,
438 [&dlg]( wxCommandEvent& )
439 {
440 dlg.EndModal( ID_MAKE_NEW_LIBRARY );
442
443 dlg.Layout();
444 dlg.GetSizer()->Fit( &dlg );
445
446 int ret = dlg.ShowModal();
447
448 switch( ret )
449 {
450 case wxID_CANCEL:
451 return wxEmptyString;
452
453 case wxID_OK:
454 libraryName = dlg.GetTextSelection();
455 Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, libraryName );
457 return libraryName;
458
460 {
461 wxFileName fn = CreateNewLibrary( _( "New Footprint Library" ),
462 Prj().GetRString( PROJECT::PCB_LIB_PATH ) );
463
464 Prj().SetRString( PROJECT::PCB_LIB_PATH, fn.GetPath() );
465 Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, fn.GetName() );
466 break;
467 }
468
469 default:
470 break;
471 }
472 }
473}
474
475
476bool PCB_BASE_EDIT_FRAME::AddLibrary( const wxString& aDialogTitle, const wxString& aFilename,
477 std::optional<LIBRARY_TABLE_SCOPE> aScope )
478{
479 bool isGlobal = false;
480 FILEDLG_HOOK_NEW_LIBRARY tableChooser( isGlobal );
481 FILEDLG_HOOK_NEW_LIBRARY* fileDlgHook = &tableChooser;
482
483 if( aScope )
484 {
485 isGlobal = ( *aScope == LIBRARY_TABLE_SCOPE::GLOBAL );
486 fileDlgHook = nullptr;
487 }
488
489 wxFileName fn( aFilename );
490
491 if( aFilename.IsEmpty() )
492 {
493 if( !LibraryFileBrowser( aDialogTitle, true, fn, FILEEXT::KiCadFootprintLibPathWildcard(),
494 FILEEXT::KiCadFootprintLibPathExtension, true, fileDlgHook ) )
495 {
496 return false;
497 }
498
499 if( fileDlgHook )
500 {
501 isGlobal = fileDlgHook->GetUseGlobalTable();
503 }
504 }
505
506 wxString libPath = fn.GetFullPath();
507 wxString libName = fn.GetName();
508
509 if( libName.IsEmpty() )
510 return false;
511
513
514 if( lib_type == PCB_IO_MGR::FILE_TYPE_NONE )
515 lib_type = PCB_IO_MGR::KICAD_SEXP;
516
517 wxString type = PCB_IO_MGR::ShowType( lib_type );
518
519 // KiCad lib is our default guess. So it might not have the .pretty extension
520 // In this case, the extension is part of the library name
521 if( lib_type == PCB_IO_MGR::KICAD_SEXP && fn.GetExt() != FILEEXT::KiCadFootprintLibPathExtension )
522 libName = fn.GetFullName();
523
524 // try to use path normalized to an environmental variable or project path
525 wxString normalizedPath = NormalizePath( libPath, &Pgm().GetLocalEnvVariables(), &Prj() );
526
527 try
528 {
529 std::optional<LIBRARY_TABLE*> table = Pgm().GetLibraryManager().Table( LIBRARY_TABLE_TYPE::FOOTPRINT, *aScope );
530 wxCHECK( table, false );
531
532 LIBRARY_TABLE_ROW& row = ( *table )->InsertRow();
533
534 row.SetNickname( libName );
535 row.SetURI( normalizedPath );
536 row.SetType( type );
537
538 ( *table )->Save().map_error(
539 []( const LIBRARY_ERROR& aError )
540 {
541 wxMessageBox( wxString::Format( _( "Error saving library table:\n\n%s" ), aError.message ),
542 _( "File Save Error" ), wxOK | wxICON_ERROR );
543 } );
544 }
545 catch( const IO_ERROR& ioe )
546 {
547 DisplayError( this, ioe.What() );
548 return false;
549 }
550
552
553 if( editor )
554 {
555 LIB_ID libID( libName, wxEmptyString );
556 editor->SyncLibraryTree( true );
557 editor->FocusOnLibID( libID );
558 }
559
560 auto viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_VIEWER, false );
561
562 if( viewer )
563 viewer->ReCreateLibraryList();
564
565 return true;
566}
567
568
570{
571 if( !aFPID.IsValid() )
572 return false;
573
576
577 wxString nickname = aFPID.GetLibNickname();
578 wxString fpname = aFPID.GetLibItemName();
579 wxString libfullname;
580
581 // Legacy libraries are readable, but modifying legacy format is not allowed
582 // So prompt the user if he try to delete a footprint from a legacy lib
583 if( std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, nickname ) )
584 libfullname = *optUri;
585 else
586 return false;
587
589 {
591 return false;
592 }
593
594 if( !adapter->IsFootprintLibWritable( nickname ) )
595 {
596 wxString msg = wxString::Format( _( "Library '%s' is read only." ), nickname );
597 ShowInfoBarError( msg );
598 return false;
599 }
600
601 // Confirmation
602 wxString msg = wxString::Format( _( "Delete footprint '%s' from library '%s'?" ),
603 fpname.GetData(),
604 nickname.GetData() );
605
606 if( aConfirm && !IsOK( this, msg ) )
607 return false;
608
609 try
610 {
611 adapter->DeleteFootprint( nickname, fpname );
612 }
613 catch( const IO_ERROR& ioe )
614 {
615 DisplayError( this, ioe.What() );
616 return false;
617 }
618
619 msg.Printf( _( "Footprint '%s' deleted from library '%s'" ),
620 fpname.GetData(),
621 nickname.GetData() );
622
623 SetStatusText( msg );
624
625 return true;
626}
627
628
629void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxString& aLibName,
630 wxString* aLibPath )
631{
632 if( GetBoard()->GetFirstFootprint() == nullptr )
633 {
634 DisplayInfoMessage( this, _( "No footprints to export!" ) );
635 return;
636 }
637
638 bool map = false;
639 PROJECT& prj = Prj();
640 wxString nickname = SelectLibrary( _( "Export Footprints" ), _( "Export footprints to library:" ),
641 { { _( "Update board footprints to link to exported footprints" ), &map } } );
642
643 if( !nickname ) // Aborted
644 return;
645
646 prj.SetRString( PROJECT::PCB_LIB_NICKNAME, nickname );
647
648 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
649 {
650 try
651 {
653
654 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
655 {
656 FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate( IGNORE_PARENT_GROUP ) );
657
658 // Reset reference designator, group membership, and zone offset before saving
659
660 fpCopy->SetReference( "REF**" );
661
662 if( EDA_GROUP* parentGroup = fpCopy->GetParentGroup() )
663 parentGroup->RemoveItem( fpCopy );
664
665 for( ZONE* zone : fpCopy->Zones() )
666 zone->Move( -fpCopy->GetPosition() );
667
668 adapter->SaveFootprint( nickname, fpCopy, true );
669
670 delete fpCopy;
671 }
672 }
673 catch( const IO_ERROR& ioe )
674 {
675 DisplayError( this, ioe.What() );
676 }
677
678 if( map )
679 {
680 LIB_ID id = footprint->GetFPID();
681 id.SetLibNickname( nickname );
682 footprint->SetFPID( id );
683 }
684 }
685}
686
687
689{
690 if( !aFootprint ) // Happen if no footprint loaded
691 return false;
692
693 PAD_TOOL* padTool = m_toolManager->GetTool<PAD_TOOL>();
694
695 if( padTool->InPadEditMode() )
697
698 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
699 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
700 bool nameChanged = m_footprintNameWhenLoaded != footprintName;
701
702 if( aFootprint->GetLink() != niluuid )
703 {
704 if( SaveFootprintToBoard( false ) )
705 {
706 m_footprintNameWhenLoaded = footprintName;
707 return true;
708 }
709
710 return false;
711 }
712 else if( libraryName.IsEmpty() || footprintName.IsEmpty() )
713 {
714 if( SaveFootprintAs( aFootprint ) )
715 {
716 m_footprintNameWhenLoaded = footprintName;
717 SyncLibraryTree( true );
718 return true;
719 }
720
721 return false;
722 }
723
725
726 // Legacy libraries are readable, but modifying legacy format is not allowed
727 // So prompt the user if he try to add/replace a footprint in a legacy lib
728 wxString libfullname;
729
730 if( std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, libraryName ) )
731 libfullname = *optUri;
732 else
733 return false;
734
736 {
738 return false;
739 }
740
741 if( nameChanged )
742 {
743 LIB_ID oldFPID( libraryName, m_footprintNameWhenLoaded );
744 DeleteFootprintFromLibrary( oldFPID, false );
745 }
746
747 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
748 return false;
749
750 if( nameChanged )
751 {
752 m_footprintNameWhenLoaded = footprintName;
753 SyncLibraryTree( true );
754 }
755
756 return true;
757}
758
759
761{
764
765 LIB_ID fpID = aFootprint->GetFPID();
766 wxString libraryName = fpID.GetLibNickname();
767 wxString footprintName = fpID.GetLibItemName();
768
769 // Legacy libraries are readable, but modifying legacy format is not allowed
770 // So prompt the user if he try to add/replace a footprint in a legacy lib
771 if( std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, libraryName ) )
772 {
774 {
776 return false;
777 }
778 }
779 else
780 {
781 return false;
782 }
783
784 int i = 1;
785 wxString newName = footprintName;
786
787 // Append a number to the name until the name is unique in the library.
788 while( adapter->FootprintExists( libraryName, newName ) )
789 newName.Printf( "%s_%d", footprintName, i++ );
790
791 aFootprint->SetFPID( LIB_ID( libraryName, newName ) );
792
793 if( aFootprint->GetValue() == footprintName )
794 aFootprint->SetValue( newName );
795
796 return SaveFootprintInLibrary( aFootprint, libraryName );
797}
798
799
801 const wxString& aLibraryName )
802{
803 try
804 {
805 aFootprint->SetFPID( LIB_ID( wxEmptyString, aFootprint->GetFPID().GetLibItemName() ) );
806
808 adapter->SaveFootprint( aLibraryName, aFootprint );
809
810 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
811
812 if( aFootprint == GetBoard()->GetFirstFootprint() )
813 setFPWatcher( aFootprint );
814
815 return true;
816 }
817 catch( const IO_ERROR& ioe )
818 {
819 DisplayError( this, ioe.What() );
820
821 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
822 return false;
823 }
824}
825
826
828{
829 // update footprint in the current board,
830 // not just add it to the board with total disregard for the netlist...
831 PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB_EDITOR, false );
832
833 if( pcbframe == nullptr ) // happens when the board editor is not active (or closed)
834 {
835 ShowInfoBarError( _( "No board currently open." ) );
836 return false;
837 }
838
839 BOARD* mainpcb = pcbframe->GetBoard();
840 FOOTPRINT* sourceFootprint = nullptr;
841 FOOTPRINT* editorFootprint = GetBoard()->GetFirstFootprint();
842
843 if( !editorFootprint )
844 return false;
845
846 // Search the old footprint (source) if exists
847 // Because this source could be deleted when editing the main board...
848 if( editorFootprint->GetLink() != niluuid ) // this is not a new footprint ...
849 {
850 sourceFootprint = nullptr;
851
852 for( FOOTPRINT* candidate : mainpcb->Footprints() )
853 {
854 if( editorFootprint->GetLink() == candidate->m_Uuid )
855 {
856 sourceFootprint = candidate;
857 break;
858 }
859 }
860 }
861
862 if( !aAddNew && sourceFootprint == nullptr ) // source not found
863 {
864 DisplayError( this, _( "Unable to find the footprint on the main board.\nCannot save." ) );
865 return false;
866 }
867
868 TOOL_MANAGER* pcb_ToolManager = pcbframe->GetToolManager();
869
870 if( aAddNew && pcb_ToolManager->GetTool<BOARD_EDITOR_CONTROL>()->PlacingFootprint() )
871 {
872 DisplayError( this, _( "Previous footprint placement still in progress." ) );
873 return false;
874 }
875
877 BOARD_COMMIT commit( pcbframe );
878
879 // Create a copy for the board, first using Clone() to keep existing Uuids, and then either
880 // resetting the uuids to the board values or assigning new Uuids.
881 FOOTPRINT* newFootprint = static_cast<FOOTPRINT*>( editorFootprint->Clone() );
882 newFootprint->SetParent( mainpcb );
883 newFootprint->SetLink( niluuid );
884
885 auto fixUuid =
886 [&]( KIID& aUuid )
887 {
888 if( editorFootprint->GetLink() != niluuid && m_boardFootprintUuids.count( aUuid ) )
889 aUuid = m_boardFootprintUuids[ aUuid ];
890 else
891 aUuid = KIID();
892 };
893
894 fixUuid( const_cast<KIID&>( newFootprint->m_Uuid ) );
895
896 newFootprint->RunOnChildren(
897 [&]( BOARD_ITEM* aChild )
898 {
899 fixUuid( const_cast<KIID&>( aChild->m_Uuid ) );
900 },
902
903 // Right now, we only show the "Unconnected" net in the footprint editor, but this is still
904 // referenced in the footprint. So we need to update the net pointers in the footprint to
905 // point to the nets in the main board.
906 newFootprint->RunOnChildren(
907 [&]( BOARD_ITEM* aChild )
908 {
909 if( BOARD_CONNECTED_ITEM* conn = dynamic_cast<BOARD_CONNECTED_ITEM*>( aChild ) )
910 {
911 NETINFO_ITEM* net = conn->GetNet();
912 auto& netmap = mainpcb->GetNetInfo().NetsByName();
913
914 if( net )
915 {
916 auto it = netmap.find( net->GetNetname() );
917
918 if( it != netmap.end() )
919 conn->SetNet( it->second );
920 }
921
922 }
923 },
925
926 BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings();
927
930 bds.m_StyleFPBarcodes );
931
932 if( sourceFootprint ) // this is an update command
933 {
934 // In the main board the new footprint replaces the old one (pos, orient, ref, value,
935 // connections and properties are kept) and the sourceFootprint (old footprint) is
936 // deleted
937 pcbframe->ExchangeFootprint( sourceFootprint, newFootprint, commit );
938 commit.Push( _( "Update Footprint" ) );
939 }
940 else // This is an insert command
941 {
942 KIGFX::VIEW_CONTROLS* viewControls = pcbframe->GetCanvas()->GetViewControls();
943 VECTOR2D cursorPos = viewControls->GetCursorPosition();
944
945 commit.Add( newFootprint );
946 viewControls->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
947 pcbframe->PlaceFootprint( newFootprint );
948 newFootprint->SetPosition( VECTOR2I( 0, 0 ) );
949 viewControls->SetCrossHairCursorPosition( cursorPos, false );
950 const_cast<KIID&>( newFootprint->m_Uuid ) = KIID();
951 commit.Push( _( "Insert Footprint" ) );
952
953 pcbframe->Raise();
954 pcb_ToolManager->RunAction( PCB_ACTIONS::placeFootprint, newFootprint );
955 }
956
957 newFootprint->ClearFlags();
958
959 return true;
960}
961
962
964{
965public:
966 SAVE_AS_DIALOG( FOOTPRINT_EDIT_FRAME* aParent, const wxString& aFootprintName,
967 const wxString& aLibraryPreselect,
968 std::function<bool( wxString libName, wxString fpName )> aValidator ) :
969 EDA_LIST_DIALOG( aParent, _( "Save Footprint As" ), false ),
970 m_validator( std::move( aValidator ) )
971 {
973 std::vector<wxString> nicknames = adapter->GetLibraryNames();
974 wxArrayString headers;
975 std::vector<wxArrayString> itemsToDisplay;
976
977 aParent->GetLibraryItemsForListDialog( headers, itemsToDisplay );
978 initDialog( headers, itemsToDisplay, aLibraryPreselect );
979
980 SetListLabel( _( "Save in library:" ) );
981 SetOKLabel( _( "Save" ) );
982
983 wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
984
985 wxStaticText* label = new wxStaticText( this, wxID_ANY, _( "Name:" ) );
986 bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
987
988 m_fpNameCtrl = new wxTextCtrl( this, wxID_ANY, aFootprintName );
989 bNameSizer->Add( m_fpNameCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
990
991 wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST );
992 nameValidator.SetCharExcludes( FOOTPRINT::StringLibNameInvalidChars( false ) );
993 m_fpNameCtrl->SetValidator( nameValidator );
994
995 wxButton* newLibraryButton = new wxButton( this, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
996 m_ButtonsSizer->Prepend( 80, 20 );
997 m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
998
999 GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
1000
1001 Bind( wxEVT_BUTTON,
1002 [this]( wxCommandEvent& )
1003 {
1004 EndModal( ID_MAKE_NEW_LIBRARY );
1006
1007 // Move nameTextCtrl to the head of the tab-order
1008 if( GetChildren().DeleteObject( m_fpNameCtrl ) )
1009 GetChildren().Insert( m_fpNameCtrl );
1010
1012
1014
1015 Layout();
1016 GetSizer()->Fit( this );
1017
1018 Centre();
1019 }
1020
1021 wxString GetFPName()
1022 {
1023 wxString footprintName = m_fpNameCtrl->GetValue();
1024 footprintName.Trim( true );
1025 footprintName.Trim( false );
1026 return footprintName;
1027 }
1028
1029protected:
1031 {
1032 return m_validator( GetTextSelection(), GetFPName() );
1033 }
1034
1035private:
1036 wxTextCtrl* m_fpNameCtrl;
1037 std::function<bool( wxString libName, wxString fpName )> m_validator;
1038};
1039
1040
1042{
1043 if( aFootprint == nullptr )
1044 return false;
1045
1046 LIBRARY_MANAGER& manager = Pgm().GetLibraryManager();
1048
1049 SetMsgPanel( aFootprint );
1050
1051 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
1052 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
1053 bool updateValue = aFootprint->GetValue() == footprintName;
1054 bool done = false;
1055 bool footprintExists = false;
1056
1057 while( !done )
1058 {
1059 SAVE_AS_DIALOG dlg( this, footprintName, libraryName,
1060 [&]( const wxString& newLib, const wxString& newName )
1061 {
1062 if( newLib.IsEmpty() )
1063 {
1064 wxMessageBox( _( "A library must be specified." ) );
1065 return false;
1066 }
1067
1068 if( newName.IsEmpty() )
1069 {
1070 wxMessageBox( _( "Footprint must have a name." ) );
1071 return false;
1072 }
1073
1074 // Legacy libraries are readable, but modifying legacy format is not allowed
1075 // So prompt the user if he try to add/replace a footprint in a legacy lib
1076 if( std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, newLib ) )
1077 {
1079 {
1081 return false;
1082 }
1083 }
1084 else
1085 {
1086 return false;
1087 }
1088
1089 footprintExists = adapter->FootprintExists( newLib, newName );
1090
1091 if( footprintExists )
1092 {
1093 wxString msg = wxString::Format( _( "Footprint %s already exists in %s." ),
1094 newName,
1095 newLib );
1096
1097 KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1098 errorDlg.SetOKLabel( _( "Overwrite" ) );
1099
1100 return errorDlg.ShowModal() == wxID_OK;
1101 }
1102
1103 return true;
1104 } );
1105
1106 int ret = dlg.ShowModal();
1107
1108 if( ret == wxID_CANCEL )
1109 {
1110 return false;
1111 }
1112 else if( ret == wxID_OK )
1113 {
1114 footprintName = dlg.GetFPName();
1115 libraryName = dlg.GetTextSelection();
1116 done = true;
1117 }
1118 else if( ret == ID_MAKE_NEW_LIBRARY )
1119 {
1120 wxFileName fn = CreateNewLibrary( _( "New Footprint Library" ),
1121 Prj().GetRString( PROJECT::PCB_LIB_PATH ) );
1122
1123 Prj().SetRString( PROJECT::PCB_LIB_PATH, fn.GetPath() );
1124 Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, fn.GetName() );
1125 libraryName = fn.GetName();
1126 }
1127 }
1128
1129 aFootprint->SetFPID( LIB_ID( libraryName, footprintName ) );
1130
1131 if( updateValue )
1132 aFootprint->SetValue( footprintName );
1133
1134 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
1135 return false;
1136
1137 // Once saved-as a board footprint is no longer a board footprint
1138 aFootprint->SetLink( niluuid );
1139
1140 wxString fmt = footprintExists ? _( "Footprint '%s' replaced in '%s'" )
1141 : _( "Footprint '%s' added to '%s'" );
1142
1143 wxString msg = wxString::Format( fmt, footprintName.GetData(), libraryName.GetData() );
1144 SetStatusText( msg );
1145 UpdateTitle();
1147
1148 return true;
1149}
1150
1151
1153{
1155 {
1156 wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1157 GetLoadedFPID().GetLibItemName().wx_str() );
1158
1159 if( ConfirmRevertDialog( this, msg ) )
1160 {
1161 Clear_Pcb( false );
1162 AddFootprintToBoard( static_cast<FOOTPRINT*>( m_originalFootprintCopy->Clone() ) );
1163
1164 Zoom_Automatique( false );
1165
1166 Update3DView( true, true );
1167
1169 GetScreen()->SetContentModified( false );
1170
1171 UpdateView();
1172 GetCanvas()->Refresh();
1173
1174 return true;
1175 }
1176 }
1177
1178 return false;
1179}
1180
1181
1182FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( wxString aFootprintName, const wxString& aLibName )
1183{
1184 if( aFootprintName.IsEmpty() )
1185 aFootprintName = _( "Untitled" );
1186
1187 int footprintAttrs = FP_SMD;
1188
1189 if( !aLibName.IsEmpty() )
1190 {
1192 std::vector<wxString> fpnames;
1193 wxString baseName = aFootprintName;
1194 int idx = 1;
1195
1196 // Make sure the name is unique
1197 while( adapter->FootprintExists( aLibName, aFootprintName ) )
1198 aFootprintName = baseName + wxString::Format( wxS( "_%d" ), idx++ );
1199
1200 // Try to infer the footprint attributes from an existing footprint in the library
1201 try
1202 {
1203 fpnames = adapter->GetFootprintNames( aLibName, true );
1204
1205 if( !fpnames.empty() )
1206 footprintAttrs = adapter->LoadFootprint( aLibName, fpnames.back(), false )->GetAttributes();
1207 }
1208 catch( ... )
1209 {
1210 // best efforts
1211 }
1212 }
1213
1214 // Create the new footprint and add it to the head of the linked list of footprints
1215 FOOTPRINT* footprint = new FOOTPRINT( GetBoard() );
1216
1217 // Update its name in lib
1218 footprint->SetFPID( LIB_ID( wxEmptyString, aFootprintName ) );
1219
1220 footprint->SetAttributes( footprintAttrs );
1221
1222 PCB_LAYER_ID txt_layer;
1223 VECTOR2I default_pos;
1225
1226 if( settings.m_DefaultFPTextItems.size() > 0 )
1227 {
1228 footprint->Reference().SetText( settings.m_DefaultFPTextItems[0].m_Text );
1229 footprint->Reference().SetVisible( settings.m_DefaultFPTextItems[0].m_Visible );
1230 }
1231
1232 txt_layer = settings.m_DefaultFPTextItems[0].m_Layer;
1233 footprint->Reference().SetLayer( txt_layer );
1234 default_pos.y -= settings.GetTextSize( txt_layer ).y / 2;
1235 footprint->Reference().SetPosition( default_pos );
1236 default_pos.y += settings.GetTextSize( txt_layer ).y;
1237
1238 if( settings.m_DefaultFPTextItems.size() > 1 )
1239 {
1240 footprint->Value().SetText( settings.m_DefaultFPTextItems[1].m_Text );
1241 footprint->Value().SetVisible( settings.m_DefaultFPTextItems[1].m_Visible );
1242 }
1243
1244 txt_layer = settings.m_DefaultFPTextItems[1].m_Layer;
1245 footprint->Value().SetLayer( txt_layer );
1246 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1247 footprint->Value().SetPosition( default_pos );
1248 default_pos.y += settings.GetTextSize( txt_layer ).y;
1249
1250 for( size_t i = 2; i < settings.m_DefaultFPTextItems.size(); ++i )
1251 {
1252 PCB_TEXT* textItem = new PCB_TEXT( footprint );
1253 textItem->SetText( settings.m_DefaultFPTextItems[i].m_Text );
1254 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[i].m_Layer;
1255 textItem->SetLayer( txt_layer );
1256 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1257 textItem->SetPosition( default_pos );
1258 default_pos.y += settings.GetTextSize( txt_layer ).y;
1259 footprint->GraphicalItems().push_back( textItem );
1260 }
1261
1262 if( footprint->GetReference().IsEmpty() )
1263 footprint->SetReference( aFootprintName );
1264
1265 if( footprint->GetValue().IsEmpty() )
1266 footprint->SetValue( aFootprintName );
1267
1268 footprint->RunOnChildren(
1269 [&]( BOARD_ITEM* aChild )
1270 {
1271 if( aChild->Type() == PCB_FIELD_T || aChild->Type() == PCB_TEXT_T )
1272 {
1273 PCB_TEXT* textItem = static_cast<PCB_TEXT*>( aChild );
1274 PCB_LAYER_ID layer = textItem->GetLayer();
1275
1276 textItem->SetTextThickness( settings.GetTextThickness( layer ) );
1277 textItem->SetTextSize( settings.GetTextSize( layer ) );
1278 textItem->SetItalic( settings.GetTextItalic( layer ) );
1279 textItem->SetKeepUpright( settings.GetTextUpright( layer ) );
1280 }
1281 },
1283
1284 SetMsgPanel( footprint );
1285 return footprint;
1286}
1287
1288
1290 std::vector<wxArrayString>& aItemsToDisplay )
1291{
1292 aHeaders.Add( _( "Library" ) );
1293 aHeaders.Add( _( "Description" ) );
1294
1298 std::vector<wxString> nicknames = adapter->GetLibraryNames();
1299
1300 for( const wxString& nickname : nicknames )
1301 {
1302 wxString description = adapter->GetLibraryDescription( nickname ).value_or( wxEmptyString );
1303
1304 if( alg::contains( project.m_PinnedFootprintLibs, nickname )
1305 || alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1306 {
1307 wxArrayString item;
1308
1309 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
1310 item.Add( description );
1311 aItemsToDisplay.push_back( item );
1312 }
1313 }
1314
1315 // TODO this double loop isn't used on the symbol side, what is broken here?
1316 for( const wxString& nickname : nicknames )
1317 {
1318 wxString description = adapter->GetLibraryDescription( nickname ).value_or( wxEmptyString );
1319
1320 if( !alg::contains( project.m_PinnedFootprintLibs, nickname )
1321 && !alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1322 {
1323 wxArrayString item;
1324
1325 item.Add( nickname );
1326 item.Add( description );
1327 aItemsToDisplay.push_back( item );
1328 }
1329 }
1330}
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:223
void SetContentModified(bool aModified=true)
Definition base_screen.h:59
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
Container for design settings for a BOARD object.
std::vector< TEXT_ITEM_INFO > m_DefaultFPTextItems
bool GetTextUpright(PCB_LAYER_ID aLayer) const
int GetTextThickness(PCB_LAYER_ID aLayer) const
Return the default text thickness from the layer class for the given layer.
bool GetTextItalic(PCB_LAYER_ID aLayer) const
VECTOR2I GetTextSize(PCB_LAYER_ID aLayer) const
Return the default text size from the layer class for the given layer.
Handle actions specific to the board editor in PcbNew.
bool PlacingFootprint() const
Re-entrancy checker for above.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:79
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:232
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:280
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
const NETINFO_LIST & GetNetInfo() const
Definition board.h:953
void BuildListOfNets()
Definition board.h:916
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition board.h:505
const FOOTPRINTS & Footprints() const
Definition board.h:363
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition commit.h:78
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:82
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int ShowModal() override
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
virtual void ReCreateHToolbar()
virtual void Zoom_Automatique(bool aWarpPointer)
Redraw the screen with best zoom level and the best centering that shows all the page or the board.
bool LibraryFileBrowser(const wxString &aTitle, bool doOpen, wxFileName &aFilename, const wxString &wildcard, const wxString &ext, bool isDirectory, FILEDLG_HOOK_NEW_LIBRARY *aFileDlgHook=nullptr)
KIGFX::VIEW_CONTROLS * GetViewControls() const
Return a pointer to the #VIEW_CONTROLS instance used in the panel.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:46
const KIID m_Uuid
Definition eda_item.h:516
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:144
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
A dialog which shows:
void SetOKLabel(const wxString &aLabel)
void initDialog(const wxArrayString &aItemHeaders, const std::vector< wxArrayString > &aItemList, const wxString &aPreselectText)
wxString GetTextSelection(int aColumn=0)
Return the selected text from aColumn in the wxListCtrl in the dialog.
void SetListLabel(const wxString &aLabel)
void 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:544
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:397
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition eda_text.cpp:295
void SetKeepUpright(bool aKeepUpright)
Definition eda_text.cpp:436
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:281
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition eda_text.cpp:318
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.
bool FootprintExists(const wxString &aNickname, const wxString &aName)
Component library viewer main window.
void SetPosition(const VECTOR2I &aPos) override
void SetFPID(const LIB_ID &aFPID)
Definition footprint.h:270
void SetLink(const KIID &aLink)
Definition footprint.h:887
ZONES & Zones()
Definition footprint.h:230
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
void SetAttributes(int aAttributes)
Definition footprint.h:328
EDA_ITEM * Clone() const override
Invoke a function on all children.
PCB_FIELD & Value()
read/write accessors:
Definition footprint.h:697
int GetAttributes() const
Definition footprint.h:327
const LIB_ID & GetFPID() const
Definition footprint.h:269
void SetReference(const wxString &aReference)
Definition footprint.h:667
void ApplyDefaultSettings(const BOARD &board, bool aStyleFields, bool aStyleText, bool aStyleShapes, bool aStyleDimensions, bool aStyleBarcodes)
Apply default board settings to the footprint field text properties.
void SetValue(const wxString &aValue)
Definition footprint.h:688
PCB_FIELD & Reference()
Definition footprint.h:698
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
KIID GetLink() const
Definition footprint.h:886
static const wxChar * StringLibNameInvalidChars(bool aUserReadable)
Test for validity of the name in a library of the footprint ( no spaces, dir separators ....
const wxString & GetValue() const
Definition footprint.h:683
const wxString & GetReference() const
Definition footprint.h:661
VECTOR2I GetPosition() const override
Definition footprint.h:245
DRAWINGS & GraphicalItems()
Definition footprint.h:227
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:42
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition kidialog.cpp:55
int ShowModal() override
Definition kidialog.cpp:93
An interface for classes handling user events controlling the view behavior such as zooming,...
virtual void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Move the graphic crosshair cursor to the requested position expressed in world coordinates.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
Definition kiid.h:49
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:403
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition kiway.cpp:200
std::optional< wxString > GetLibraryDescription(const wxString &aNickname) const
std::vector< wxString > GetLibraryNames() const
Returns a list of library nicknames that are available (skips any that failed to load)
std::optional< LIBRARY_TABLE * > Table(LIBRARY_TABLE_TYPE aType, LIBRARY_TABLE_SCOPE aScope)
Retrieves a given table; creating a new empty project table if a valid project is loaded and the give...
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
void SetURI(const wxString &aUri)
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
bool IsValid() const
Check if this LID_ID is valid.
Definition lib_id.h:172
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:100
const UTF8 & GetLibItemName() const
Definition lib_id.h:102
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition lib_id.h:87
static const wxString GetPinningSymbol()
Handle the data for a net.
Definition netinfo.h:54
const wxString & GetNetname() const
Definition netinfo.h:112
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition netinfo.h:238
bool InPadEditMode()
Definition pad_tool.h:63
static TOOL_ACTION recombinePad
static TOOL_ACTION placeFootprint
wxString CreateNewLibrary(const wxString &aDialogTitle, const wxString &aInitialPath=wxEmptyString)
If a library name is given, creates a new footprint library in the project folder with the given name...
wxString SelectLibrary(const wxString &aDialogTitle, const wxString &aListLabel, const std::vector< std::pair< wxString, bool * > > &aExtraCheckboxes={})
Put up a dialog and allows the user to pick a library, for unspecified use.
wxString createNewLibrary(const wxString &aDialogTitle, const wxString &aLibName, const wxString &aInitialPath, std::optional< LIBRARY_TABLE_SCOPE > aScope=std::nullopt)
Create a new library in the given table.
wxString CreateNewProjectLibrary(const wxString &aDialogTitle, const wxString &aLibName)
bool AddLibrary(const wxString &aDialogTitle, const wxString &aLibName=wxEmptyString, std::optional< LIBRARY_TABLE_SCOPE > aScope=std::nullopt)
Add an existing library to either the global or project library table.
void setFPWatcher(FOOTPRINT *aFootprint)
Create or removes a watcher on the specified footprint.
FOOTPRINT * CreateNewFootprint(wxString aFootprintName, const wxString &aLibName)
Create a new footprint at position 0,0.
void GetLibraryItemsForListDialog(wxArrayString &aHeaders, std::vector< wxArrayString > &aItemsToDisplay)
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Return the BOARD_DESIGN_SETTINGS for the open project.
void PlaceFootprint(FOOTPRINT *aFootprint, bool aRecreateRatsnest=true)
Place aFootprint at the current cursor position and updates footprint coordinates with the new positi...
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
The main frame for Pcbnew.
void ExportFootprintsToLibrary(bool aStoreInNewLib, const wxString &aLibName=wxEmptyString, wxString *aLibPath=nullptr)
Save footprints in a library:
void ExchangeFootprint(FOOTPRINT *aExisting, FOOTPRINT *aNew, BOARD_COMMIT &aCommit, bool deleteExtraTexts=true, bool resetTextLayers=true, bool resetTextEffects=true, bool resetTextPositions=true, bool resetTextContent=true, bool resetFabricationAttrs=true, bool resetClearanceOverrides=true, bool reset3DModels=true, bool *aUpdated=nullptr)
Replace aExisting footprint by aNew footprint using the Existing footprint settings (position,...
A #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
void Format(const BOARD_ITEM *aItem) const
Output aItem to aFormatter in s-expression format.
std::string GetStringOutput(bool doClear)
static PLUGIN_REGISTRY * Instance()
Definition pcb_io_mgr.h:95
PCB_FILE_T
The set of file types that the PCB_IO_MGR knows about, and for which there has been a plugin written,...
Definition pcb_io_mgr.h:56
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:58
@ LEGACY
Legacy Pcbnew file formats prior to s-expression.
Definition pcb_io_mgr.h:59
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a footprint library's libPath.
static const wxString ShowType(PCB_FILE_T aFileType)
Return a brief name for a plugin given aFileType enum.
virtual void SetPosition(const VECTOR2I &aPos) override
Definition pcb_text.h:89
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:537
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:131
The backing store for a PROJECT, in JSON format.
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
Container for project specific data.
Definition project.h:65
@ PCB_LIB_PATH
Definition project.h:228
@ PCB_LIB_NICKNAME
Definition project.h:229
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:167
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:339
virtual const wxString & GetRString(RSTRING_T aStringId)
Return a "retained string", which is any session and project specific string identified in enum RSTRI...
Definition project.cpp:350
bool TransferDataFromWindow() override
SAVE_AS_DIALOG(FOOTPRINT_EDIT_FRAME *aParent, const wxString &aFootprintName, const wxString &aLibraryPreselect, std::function< bool(wxString libName, wxString fpName)> aValidator)
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:439
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:259
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:230
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
bool ConfirmRevertDialog(wxWindow *parent, const wxString &aMessage)
Display a confirmation dialog for a revert action.
Definition confirm.cpp:118
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:177
This file is part of the common library.
#define _(s)
@ RECURSE
Definition eda_item.h:51
#define IGNORE_PARENT_GROUP
Definition eda_item.h:55
wxString NormalizePath(const wxFileName &aFilePath, const ENV_VAR_MAP *aEnvVars, const wxString &aProjectPath)
Normalize a file path to an environmental variable, if possible.
Definition env_paths.cpp:73
Helper functions to substitute paths with environmental variables.
@ FP_SMD
Definition footprint.h:82
static const wxString INFO_LEGACY_LIB_WARN_DELETE(_("Modifying legacy libraries (.mod files) is not allowed\n" "Please save the current library under the new .pretty format\n" "and update your footprint lib table\n" "before deleting a footprint"))
static const wxString INFO_LEGACY_LIB_WARN_EDIT(_("Writing/modifying legacy libraries (.mod files) is not allowed\n" "Please save the current library to the new .pretty format\n" "and update your footprint lib table\n" "to save your footprint (a .kicad_mod file) in the .pretty library folder"))
static constexpr int ID_MAKE_NEW_LIBRARY
@ FRAME_PCB_EDITOR
Definition frame_type.h:42
@ FRAME_FOOTPRINT_VIEWER
Definition frame_type.h:45
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:43
static const std::string KiCadFootprintLibPathExtension
static const std::string KiCadFootprintFileExtension
static wxString KiCadFootprintLibFileWildcard()
static wxString KiCadFootprintLibPathWildcard()
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
PROJECT & Prj()
Definition kicad.cpp:629
KIID niluuid(0)
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
This file contains miscellaneous commonly used macros and functions.
void Prettify(std::string &aSource, FORMAT_MODE aMode)
Pretty-prints s-expression text according to KiCad format rules.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:100
STL namespace.
Class to handle a set of BOARD_ITEMs.
#define CTL_FOR_LIBRARY
Format output for a footprint library instead of clipboard or BOARD.
PGM_BASE & Pgm()
The global program "get" accessor.
Definition pgm_base.cpp:946
see class PGM_BASE
KIWAY Kiway(KFCTL_STANDALONE)
MODEL3D_FORMAT_TYPE fileType(const char *aFileName)
std::vector< wxString > pinned_fp_libs
Container that describes file type info.
Definition io_base.h:45
std::vector< std::string > m_FileExtensions
Filter used for file pickers if m_IsFile is true.
Definition io_base.h:49
wxString FileFilter() const
Definition io_base.cpp:40
wxString message
@ ID_MAKE_NEW_LIBRARY
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:92
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition typeinfo.h:90
Custom text control validator definitions.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
Definition of file extensions used in Kicad.