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>
33#include <fp_lib_table.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, true );
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, PROJECT_PCB::PcbFootprintLibs( &Prj() ) );
302}
303
304
305wxString PCB_BASE_EDIT_FRAME::CreateNewLibrary( const wxString& aDialogTitle, const wxString& aInitialPath )
306{
307 return createNewLibrary( aDialogTitle, wxEmptyString, aInitialPath, nullptr );
308}
309
310
311wxString PCB_BASE_EDIT_FRAME::createNewLibrary( const wxString& aDialogTitle, const wxString& aLibName,
312 const wxString& aInitialPath, FP_LIB_TABLE* aTable )
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;
322 FILEDLG_HOOK_NEW_LIBRARY tableChooser( isGlobal );
323 FILEDLG_HOOK_NEW_LIBRARY* fileDlgHook = &tableChooser;
324
325 if( aTable )
326 {
327 isGlobal = ( aTable == &GFootprintTable );
328 libTable = aTable;
329 fileDlgHook = nullptr;
330 }
331
332 if( aLibName.IsEmpty() )
333 {
334 fn = aInitialPath.IsEmpty() ? Prj().GetProjectPath() : aInitialPath;
335
336 if( !LibraryFileBrowser( aDialogTitle, false, fn, FILEEXT::KiCadFootprintLibPathWildcard(),
337 FILEEXT::KiCadFootprintLibPathExtension, false, fileDlgHook ) )
338 {
339 return wxEmptyString;
340 }
341
342 if( fileDlgHook )
343 {
344 isGlobal = fileDlgHook->GetUseGlobalTable();
345 libTable = isGlobal ? &GFootprintTable : PROJECT_PCB::PcbFootprintLibs( &Prj() );
346 }
347
348 doAdd = true;
349 }
350 else
351 {
353
354 if( !fn.IsAbsolute() )
355 {
356 fn.SetName( aLibName );
357 fn.MakeAbsolute( Prj().GetProjectPath() );
358 }
359 }
360
361 // We can save fp libs only using PCB_IO_MGR::KICAD_SEXP format (.pretty libraries)
363 wxString libPath = fn.GetFullPath();
364
365 try
366 {
368
369 bool writable = false;
370 bool exists = false;
371
372 try
373 {
374 writable = pi->IsLibraryWritable( libPath );
375 exists = true; // no exception was thrown, lib must exist.
376 }
377 catch( const IO_ERROR& )
378 {
379 // best efforts....
380 }
381
382 if( exists )
383 {
384 if( !writable )
385 {
386 wxString msg = wxString::Format( _( "Library %s is read only." ), libPath );
387 ShowInfoBarError( msg );
388 return wxEmptyString;
389 }
390 else
391 {
392 wxString msg = wxString::Format( _( "Library %s already exists." ), libPath );
393 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
394 dlg.SetOKLabel( _( "Overwrite" ) );
395 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
396
397 if( dlg.ShowModal() == wxID_CANCEL )
398 return wxEmptyString;
399
400 pi->DeleteLibrary( libPath );
401 }
402 }
403
404 pi->CreateLibrary( libPath );
405 }
406 catch( const IO_ERROR& ioe )
407 {
408 DisplayError( this, ioe.What() );
409 return wxEmptyString;
410 }
411
412 if( doAdd )
413 AddLibrary( aDialogTitle, libPath, libTable );
414
415 return libPath;
416}
417
418
419wxString PCB_BASE_EDIT_FRAME::SelectLibrary( const wxString& aDialogTitle, const wxString& aListLabel,
420 const std::vector<std::pair<wxString, bool*>>& aExtraCheckboxes )
421{
422 // Keep asking the user for a new name until they give a valid one or cancel the operation
423 while( true )
424 {
425 wxArrayString headers;
426 std::vector<wxArrayString> itemsToDisplay;
427
428 GetLibraryItemsForListDialog( headers, itemsToDisplay );
429
430 wxString libraryName = Prj().GetRString( PROJECT::PCB_LIB_NICKNAME );
431
432 EDA_LIST_DIALOG dlg( this, aDialogTitle, headers, itemsToDisplay, libraryName, false );
433 dlg.SetListLabel( aListLabel );
434
435 for( const auto& [label, val] : aExtraCheckboxes )
436 dlg.AddExtraCheckbox( label, val );
437
438 wxButton* newLibraryButton = new wxButton( &dlg, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
439 dlg.m_ButtonsSizer->Prepend( 80, 20 );
440 dlg.m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
441
442 newLibraryButton->Bind( wxEVT_BUTTON,
443 [&dlg]( wxCommandEvent& )
444 {
445 dlg.EndModal( ID_MAKE_NEW_LIBRARY );
447
448 dlg.Layout();
449 dlg.GetSizer()->Fit( &dlg );
450
451 int ret = dlg.ShowModal();
452
453 switch( ret )
454 {
455 case wxID_CANCEL:
456 return wxEmptyString;
457
458 case wxID_OK:
459 libraryName = dlg.GetTextSelection();
460 Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, libraryName );
462 return libraryName;
463
465 {
466 wxFileName fn = CreateNewLibrary( _( "New Footprint Library" ),
467 Prj().GetRString( PROJECT::PCB_LIB_PATH ) );
468
469 Prj().SetRString( PROJECT::PCB_LIB_PATH, fn.GetPath() );
470 Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, fn.GetName() );
471 break;
472 }
473
474 default:
475 break;
476 }
477 }
478}
479
480
481bool PCB_BASE_EDIT_FRAME::AddLibrary( const wxString& aDialogTitle, const wxString& aFilename,
482 FP_LIB_TABLE* aTable )
483{
484 bool isGlobal = false;
486 FILEDLG_HOOK_NEW_LIBRARY tableChooser( isGlobal );
487 FILEDLG_HOOK_NEW_LIBRARY* fileDlgHook = &tableChooser;
488
489 if( aTable )
490 {
491 isGlobal = ( aTable == &GFootprintTable );
492 libTable = aTable;
493 fileDlgHook = nullptr;
494 }
495
496 wxFileName fn( aFilename );
497
498 if( aFilename.IsEmpty() )
499 {
500 if( !LibraryFileBrowser( aDialogTitle, true, fn, FILEEXT::KiCadFootprintLibPathWildcard(),
501 FILEEXT::KiCadFootprintLibPathExtension, true, fileDlgHook ) )
502 {
503 return false;
504 }
505
506 if( fileDlgHook )
507 {
508 isGlobal = fileDlgHook->GetUseGlobalTable();
509 libTable = isGlobal ? &GFootprintTable : PROJECT_PCB::PcbFootprintLibs( &Prj() );
510 }
511 }
512
513 wxString libPath = fn.GetFullPath();
514 wxString libName = fn.GetName();
515
516 if( libName.IsEmpty() )
517 return false;
518
520
521 if( lib_type == PCB_IO_MGR::FILE_TYPE_NONE )
522 lib_type = PCB_IO_MGR::KICAD_SEXP;
523
524 wxString type = PCB_IO_MGR::ShowType( lib_type );
525
526 // KiCad lib is our default guess. So it might not have the .pretty extension
527 // In this case, the extension is part of the library name
528 if( lib_type == PCB_IO_MGR::KICAD_SEXP && fn.GetExt() != FILEEXT::KiCadFootprintLibPathExtension )
529 libName = fn.GetFullName();
530
531 // try to use path normalized to an environmental variable or project path
532 wxString normalizedPath = NormalizePath( libPath, &Pgm().GetLocalEnvVariables(), &Prj() );
533
534 try
535 {
536 FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libName, normalizedPath, type, wxEmptyString );
537 libTable->InsertRow( row );
538
539 if( isGlobal )
541 else
542 libTable->Save( Prj().FootprintLibTblName() );
543 }
544 catch( const IO_ERROR& ioe )
545 {
546 DisplayError( this, ioe.What() );
547 return false;
548 }
549
551
552 if( editor )
553 {
554 LIB_ID libID( libName, wxEmptyString );
555 editor->SyncLibraryTree( true );
556 editor->FocusOnLibID( libID );
557 }
558
559 auto viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_VIEWER, false );
560
561 if( viewer )
562 viewer->ReCreateLibraryList();
563
564 return true;
565}
566
567
569{
570 if( !aFPID.IsValid() )
571 return false;
572
573 wxString nickname = aFPID.GetLibNickname();
574 wxString fpname = aFPID.GetLibItemName();
575 wxString libfullname;
576
577 // Legacy libraries are readable, but modifying legacy format is not allowed
578 // So prompt the user if he try to delete a footprint from a legacy lib
579 try
580 {
581 libfullname = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( nickname )->GetFullURI();
582 }
583 catch( ... )
584 {
585 // If we can't find the nickname, stop here
586 return false;
587 }
588
590 {
592 return false;
593 }
594
595 if( !PROJECT_PCB::PcbFootprintLibs( &Prj() )->IsFootprintLibWritable( nickname ) )
596 {
597 wxString msg = wxString::Format( _( "Library '%s' is read only." ), nickname );
598 ShowInfoBarError( msg );
599 return false;
600 }
601
602 // Confirmation
603 wxString msg = wxString::Format( _( "Delete footprint '%s' from library '%s'?" ),
604 fpname.GetData(),
605 nickname.GetData() );
606
607 if( aConfirm && !IsOK( this, msg ) )
608 return false;
609
610 try
611 {
612 PROJECT_PCB::PcbFootprintLibs( &Prj() )->FootprintDelete( nickname, fpname );
613 }
614 catch( const IO_ERROR& ioe )
615 {
616 DisplayError( this, ioe.What() );
617 return false;
618 }
619
620 msg.Printf( _( "Footprint '%s' deleted from library '%s'" ),
621 fpname.GetData(),
622 nickname.GetData() );
623
624 SetStatusText( msg );
625
626 return true;
627}
628
629
630void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxString& aLibName,
631 wxString* aLibPath )
632{
633 if( GetBoard()->GetFirstFootprint() == nullptr )
634 {
635 DisplayInfoMessage( this, _( "No footprints to export!" ) );
636 return;
637 }
638
639 bool map = false;
640 PROJECT& prj = Prj();
641 wxString nickname = SelectLibrary( _( "Export Footprints" ), _( "Export footprints to library:" ),
642 { { _( "Update board footprints to link to exported footprints" ), &map } } );
643
644 if( !nickname ) // Aborted
645 return;
646
647 prj.SetRString( PROJECT::PCB_LIB_NICKNAME, nickname );
648
649 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
650 {
651 try
652 {
654
655 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
656 {
657 FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate( IGNORE_PARENT_GROUP ) );
658
659 // Reset reference designator, group membership, and zone offset before saving
660
661 fpCopy->SetReference( "REF**" );
662
663 if( EDA_GROUP* parentGroup = fpCopy->GetParentGroup() )
664 parentGroup->RemoveItem( fpCopy );
665
666 for( ZONE* zone : fpCopy->Zones() )
667 zone->Move( -fpCopy->GetPosition() );
668
669 tbl->FootprintSave( nickname, fpCopy, true );
670
671 delete fpCopy;
672 }
673 }
674 catch( const IO_ERROR& ioe )
675 {
676 DisplayError( this, ioe.What() );
677 }
678
679 if( map )
680 {
681 LIB_ID id = footprint->GetFPID();
682 id.SetLibNickname( nickname );
683 footprint->SetFPID( id );
684 }
685 }
686}
687
688
690{
691 if( !aFootprint ) // Happen if no footprint loaded
692 return false;
693
694 PAD_TOOL* padTool = m_toolManager->GetTool<PAD_TOOL>();
695
696 if( padTool->InPadEditMode() )
698
699 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
700 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
701 bool nameChanged = m_footprintNameWhenLoaded != footprintName;
702
703 if( aFootprint->GetLink() != niluuid )
704 {
705 if( SaveFootprintToBoard( false ) )
706 {
707 m_footprintNameWhenLoaded = footprintName;
708 return true;
709 }
710
711 return false;
712 }
713 else if( libraryName.IsEmpty() || footprintName.IsEmpty() )
714 {
715 if( SaveFootprintAs( aFootprint ) )
716 {
717 m_footprintNameWhenLoaded = footprintName;
718 SyncLibraryTree( true );
719 return true;
720 }
721
722 return false;
723 }
724
726
727 // Legacy libraries are readable, but modifying legacy format is not allowed
728 // So prompt the user if he try to add/replace a footprint in a legacy lib
729 wxString libfullname;
730
731 try
732 {
733 libfullname = tbl->FindRow( libraryName )->GetFullURI();
734 }
735 catch( IO_ERROR& error )
736 {
737 DisplayInfoMessage( this, error.What() );
738 return false;
739 }
740
742 {
744 return false;
745 }
746
747 if( nameChanged )
748 {
749 LIB_ID oldFPID( libraryName, m_footprintNameWhenLoaded );
750 DeleteFootprintFromLibrary( oldFPID, false );
751 }
752
753 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
754 return false;
755
756 if( nameChanged )
757 {
758 m_footprintNameWhenLoaded = footprintName;
759 SyncLibraryTree( true );
760 }
761
762 return true;
763}
764
765
767{
768 LIB_ID fpID = aFootprint->GetFPID();
769 wxString libraryName = fpID.GetLibNickname();
770 wxString footprintName = fpID.GetLibItemName();
771
772 // Legacy libraries are readable, but modifying legacy format is not allowed
773 // So prompt the user if he try to add/replace a footprint in a legacy lib
774 wxString libFullName = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( libraryName )->GetFullURI();
775
777 {
779 return false;
780 }
781
783 int i = 1;
784 wxString newName = footprintName;
785
786 // Append a number to the name until the name is unique in the library.
787 while( tbl->FootprintExists( libraryName, newName ) )
788 newName.Printf( "%s_%d", footprintName, i++ );
789
790 aFootprint->SetFPID( LIB_ID( libraryName, newName ) );
791
792 if( aFootprint->GetValue() == footprintName )
793 aFootprint->SetValue( newName );
794
795 return SaveFootprintInLibrary( aFootprint, libraryName );
796}
797
798
800 const wxString& aLibraryName )
801{
802 try
803 {
804 aFootprint->SetFPID( LIB_ID( wxEmptyString, aFootprint->GetFPID().GetLibItemName() ) );
805
806 PROJECT_PCB::PcbFootprintLibs( &Prj() )->FootprintSave( aLibraryName, aFootprint );
807
808 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
809
810 if( aFootprint == GetBoard()->GetFirstFootprint() )
811 setFPWatcher( aFootprint );
812
813 return true;
814 }
815 catch( const IO_ERROR& ioe )
816 {
817 DisplayError( this, ioe.What() );
818
819 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
820 return false;
821 }
822}
823
824
826{
827 // update footprint in the current board,
828 // not just add it to the board with total disregard for the netlist...
829 PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB_EDITOR, false );
830
831 if( pcbframe == nullptr ) // happens when the board editor is not active (or closed)
832 {
833 ShowInfoBarError( _( "No board currently open." ) );
834 return false;
835 }
836
837 BOARD* mainpcb = pcbframe->GetBoard();
838 FOOTPRINT* sourceFootprint = nullptr;
839 FOOTPRINT* editorFootprint = GetBoard()->GetFirstFootprint();
840
841 if( !editorFootprint )
842 return false;
843
844 // Search the old footprint (source) if exists
845 // Because this source could be deleted when editing the main board...
846 if( editorFootprint->GetLink() != niluuid ) // this is not a new footprint ...
847 {
848 sourceFootprint = nullptr;
849
850 for( FOOTPRINT* candidate : mainpcb->Footprints() )
851 {
852 if( editorFootprint->GetLink() == candidate->m_Uuid )
853 {
854 sourceFootprint = candidate;
855 break;
856 }
857 }
858 }
859
860 if( !aAddNew && sourceFootprint == nullptr ) // source not found
861 {
862 DisplayError( this, _( "Unable to find the footprint on the main board.\nCannot save." ) );
863 return false;
864 }
865
866 TOOL_MANAGER* pcb_ToolManager = pcbframe->GetToolManager();
867
868 if( aAddNew && pcb_ToolManager->GetTool<BOARD_EDITOR_CONTROL>()->PlacingFootprint() )
869 {
870 DisplayError( this, _( "Previous footprint placement still in progress." ) );
871 return false;
872 }
873
875 BOARD_COMMIT commit( pcbframe );
876
877 // Create a copy for the board, first using Clone() to keep existing Uuids, and then either
878 // resetting the uuids to the board values or assigning new Uuids.
879 FOOTPRINT* newFootprint = static_cast<FOOTPRINT*>( editorFootprint->Clone() );
880 newFootprint->SetParent( mainpcb );
881 newFootprint->SetLink( niluuid );
882
883 auto fixUuid =
884 [&]( KIID& aUuid )
885 {
886 if( editorFootprint->GetLink() != niluuid && m_boardFootprintUuids.count( aUuid ) )
887 aUuid = m_boardFootprintUuids[ aUuid ];
888 else
889 aUuid = KIID();
890 };
891
892 fixUuid( const_cast<KIID&>( newFootprint->m_Uuid ) );
893
894 newFootprint->RunOnChildren(
895 [&]( BOARD_ITEM* aChild )
896 {
897 fixUuid( const_cast<KIID&>( aChild->m_Uuid ) );
898 },
900
901 // Right now, we only show the "Unconnected" net in the footprint editor, but this is still
902 // referenced in the footprint. So we need to update the net pointers in the footprint to
903 // point to the nets in the main board.
904 newFootprint->RunOnChildren(
905 [&]( BOARD_ITEM* aChild )
906 {
907 if( BOARD_CONNECTED_ITEM* conn = dynamic_cast<BOARD_CONNECTED_ITEM*>( aChild ) )
908 {
909 NETINFO_ITEM* net = conn->GetNet();
910 auto& netmap = mainpcb->GetNetInfo().NetsByName();
911
912 if( net )
913 {
914 auto it = netmap.find( net->GetNetname() );
915
916 if( it != netmap.end() )
917 conn->SetNet( it->second );
918 }
919
920 }
921 },
923
924 BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings();
925
927 bds.m_StyleFPShapes );
928
929 if( sourceFootprint ) // this is an update command
930 {
931 // In the main board the new footprint replaces the old one (pos, orient, ref, value,
932 // connections and properties are kept) and the sourceFootprint (old footprint) is
933 // deleted
934 pcbframe->ExchangeFootprint( sourceFootprint, newFootprint, commit );
935 commit.Push( _( "Update Footprint" ) );
936 }
937 else // This is an insert command
938 {
939 KIGFX::VIEW_CONTROLS* viewControls = pcbframe->GetCanvas()->GetViewControls();
940 VECTOR2D cursorPos = viewControls->GetCursorPosition();
941
942 commit.Add( newFootprint );
943 viewControls->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
944 pcbframe->PlaceFootprint( newFootprint );
945 newFootprint->SetPosition( VECTOR2I( 0, 0 ) );
946 viewControls->SetCrossHairCursorPosition( cursorPos, false );
947 const_cast<KIID&>( newFootprint->m_Uuid ) = KIID();
948 commit.Push( _( "Insert Footprint" ) );
949
950 pcbframe->Raise();
951 pcb_ToolManager->RunAction( PCB_ACTIONS::placeFootprint, newFootprint );
952 }
953
954 newFootprint->ClearFlags();
955
956 return true;
957}
958
959
961{
962public:
963 SAVE_AS_DIALOG( FOOTPRINT_EDIT_FRAME* aParent, const wxString& aFootprintName,
964 const wxString& aLibraryPreselect,
965 std::function<bool( wxString libName, wxString fpName )> aValidator ) :
966 EDA_LIST_DIALOG( aParent, _( "Save Footprint As" ), false ),
967 m_validator( std::move( aValidator ) )
968 {
969 FP_LIB_TABLE* tbl = PROJECT_PCB::PcbFootprintLibs( &aParent->Prj() );
970 std::vector<wxString> nicknames = tbl->GetLogicalLibs();
971 wxArrayString headers;
972 std::vector<wxArrayString> itemsToDisplay;
973
974 aParent->GetLibraryItemsForListDialog( headers, itemsToDisplay );
975 initDialog( headers, itemsToDisplay, aLibraryPreselect );
976
977 SetListLabel( _( "Save in library:" ) );
978 SetOKLabel( _( "Save" ) );
979
980 wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
981
982 wxStaticText* label = new wxStaticText( this, wxID_ANY, _( "Name:" ) );
983 bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
984
985 m_fpNameCtrl = new wxTextCtrl( this, wxID_ANY, aFootprintName );
986 bNameSizer->Add( m_fpNameCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
987
988 wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST );
989 nameValidator.SetCharExcludes( FOOTPRINT::StringLibNameInvalidChars( false ) );
990 m_fpNameCtrl->SetValidator( nameValidator );
991
992 wxButton* newLibraryButton = new wxButton( this, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
993 m_ButtonsSizer->Prepend( 80, 20 );
994 m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
995
996 GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
997
998 Bind( wxEVT_BUTTON,
999 [this]( wxCommandEvent& )
1000 {
1001 EndModal( ID_MAKE_NEW_LIBRARY );
1003
1004 // Move nameTextCtrl to the head of the tab-order
1005 if( GetChildren().DeleteObject( m_fpNameCtrl ) )
1006 GetChildren().Insert( m_fpNameCtrl );
1007
1009
1011
1012 Layout();
1013 GetSizer()->Fit( this );
1014
1015 Centre();
1016 }
1017
1018 wxString GetFPName()
1019 {
1020 wxString footprintName = m_fpNameCtrl->GetValue();
1021 footprintName.Trim( true );
1022 footprintName.Trim( false );
1023 return footprintName;
1024 }
1025
1026protected:
1028 {
1029 return m_validator( GetTextSelection(), GetFPName() );
1030 }
1031
1032private:
1033 wxTextCtrl* m_fpNameCtrl;
1034 std::function<bool( wxString libName, wxString fpName )> m_validator;
1035};
1036
1037
1039{
1040 if( aFootprint == nullptr )
1041 return false;
1042
1044
1045 SetMsgPanel( aFootprint );
1046
1047 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
1048 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
1049 bool updateValue = aFootprint->GetValue() == footprintName;
1050 bool done = false;
1051 bool footprintExists = false;
1052
1053 while( !done )
1054 {
1055 SAVE_AS_DIALOG dlg( this, footprintName, libraryName,
1056 [&]( const wxString& newLib, const wxString& newName )
1057 {
1058 if( newLib.IsEmpty() )
1059 {
1060 wxMessageBox( _( "A library must be specified." ) );
1061 return false;
1062 }
1063
1064 if( newName.IsEmpty() )
1065 {
1066 wxMessageBox( _( "Footprint must have a name." ) );
1067 return false;
1068 }
1069
1070 // Legacy libraries are readable, but modifying legacy format is not allowed
1071 // So prompt the user if he try to add/replace a footprint in a legacy lib
1072 const FP_LIB_TABLE_ROW* row = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( newLib );
1073 wxString libPath = row->GetFullURI();
1075
1076 if( piType == PCB_IO_MGR::LEGACY )
1077 {
1079 return false;
1080 }
1081
1082 footprintExists = tbl->FootprintExists( newLib, newName );
1083
1084 if( footprintExists )
1085 {
1086 wxString msg = wxString::Format( _( "Footprint %s already exists in %s." ),
1087 newName,
1088 newLib );
1089
1090 KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1091 errorDlg.SetOKLabel( _( "Overwrite" ) );
1092
1093 return errorDlg.ShowModal() == wxID_OK;
1094 }
1095
1096 return true;
1097 } );
1098
1099 int ret = dlg.ShowModal();
1100
1101 if( ret == wxID_CANCEL )
1102 {
1103 return false;
1104 }
1105 else if( ret == wxID_OK )
1106 {
1107 footprintName = dlg.GetFPName();
1108 libraryName = dlg.GetTextSelection();
1109 done = true;
1110 }
1111 else if( ret == ID_MAKE_NEW_LIBRARY )
1112 {
1113 wxFileName fn = CreateNewLibrary( _( "New Footprint Library" ),
1114 Prj().GetRString( PROJECT::PCB_LIB_PATH ) );
1115
1116 Prj().SetRString( PROJECT::PCB_LIB_PATH, fn.GetPath() );
1117 Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, fn.GetName() );
1118 libraryName = fn.GetName();
1119 }
1120 }
1121
1122 aFootprint->SetFPID( LIB_ID( libraryName, footprintName ) );
1123
1124 if( updateValue )
1125 aFootprint->SetValue( footprintName );
1126
1127 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
1128 return false;
1129
1130 // Once saved-as a board footprint is no longer a board footprint
1131 aFootprint->SetLink( niluuid );
1132
1133 wxString fmt = footprintExists ? _( "Footprint '%s' replaced in '%s'" )
1134 : _( "Footprint '%s' added to '%s'" );
1135
1136 wxString msg = wxString::Format( fmt, footprintName.GetData(), libraryName.GetData() );
1137 SetStatusText( msg );
1138 UpdateTitle();
1140
1141 return true;
1142}
1143
1144
1146{
1148 {
1149 wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1150 GetLoadedFPID().GetLibItemName().wx_str() );
1151
1152 if( ConfirmRevertDialog( this, msg ) )
1153 {
1154 Clear_Pcb( false );
1155 AddFootprintToBoard( static_cast<FOOTPRINT*>( m_originalFootprintCopy->Clone() ) );
1156
1157 Zoom_Automatique( false );
1158
1159 Update3DView( true, true );
1160
1162 GetScreen()->SetContentModified( false );
1163
1164 UpdateView();
1165 GetCanvas()->Refresh();
1166
1167 return true;
1168 }
1169 }
1170
1171 return false;
1172}
1173
1174
1175FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( wxString aFootprintName, const wxString& aLibName )
1176{
1177 if( aFootprintName.IsEmpty() )
1178 aFootprintName = _( "Untitled" );
1179
1180 int footprintAttrs = FP_SMD;
1181
1182 if( !aLibName.IsEmpty() )
1183 {
1185 wxArrayString fpnames;
1186 wxString baseName = aFootprintName;
1187 int idx = 1;
1188
1189 // Make sure the name is unique
1190 while( tbl->FootprintExists( aLibName, aFootprintName ) )
1191 aFootprintName = baseName + wxString::Format( wxS( "_%d" ), idx++ );
1192
1193 // Try to infer the footprint attributes from an existing footprint in the library
1194 try
1195 {
1196 tbl->FootprintEnumerate( fpnames, aLibName, true );
1197
1198 if( !fpnames.empty() )
1199 footprintAttrs = tbl->FootprintLoad( aLibName, fpnames.Last() )->GetAttributes();
1200 }
1201 catch( ... )
1202 {
1203 // best efforts
1204 }
1205 }
1206
1207 // Create the new footprint and add it to the head of the linked list of footprints
1208 FOOTPRINT* footprint = new FOOTPRINT( GetBoard() );
1209
1210 // Update its name in lib
1211 footprint->SetFPID( LIB_ID( wxEmptyString, aFootprintName ) );
1212
1213 footprint->SetAttributes( footprintAttrs );
1214
1215 PCB_LAYER_ID txt_layer;
1216 VECTOR2I default_pos;
1218
1219 if( settings.m_DefaultFPTextItems.size() > 0 )
1220 {
1221 footprint->Reference().SetText( settings.m_DefaultFPTextItems[0].m_Text );
1222 footprint->Reference().SetVisible( settings.m_DefaultFPTextItems[0].m_Visible );
1223 }
1224
1225 txt_layer = settings.m_DefaultFPTextItems[0].m_Layer;
1226 footprint->Reference().SetLayer( txt_layer );
1227 default_pos.y -= settings.GetTextSize( txt_layer ).y / 2;
1228 footprint->Reference().SetPosition( default_pos );
1229 default_pos.y += settings.GetTextSize( txt_layer ).y;
1230
1231 if( settings.m_DefaultFPTextItems.size() > 1 )
1232 {
1233 footprint->Value().SetText( settings.m_DefaultFPTextItems[1].m_Text );
1234 footprint->Value().SetVisible( settings.m_DefaultFPTextItems[1].m_Visible );
1235 }
1236
1237 txt_layer = settings.m_DefaultFPTextItems[1].m_Layer;
1238 footprint->Value().SetLayer( txt_layer );
1239 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1240 footprint->Value().SetPosition( default_pos );
1241 default_pos.y += settings.GetTextSize( txt_layer ).y;
1242
1243 for( size_t i = 2; i < settings.m_DefaultFPTextItems.size(); ++i )
1244 {
1245 PCB_TEXT* textItem = new PCB_TEXT( footprint );
1246 textItem->SetText( settings.m_DefaultFPTextItems[i].m_Text );
1247 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[i].m_Layer;
1248 textItem->SetLayer( txt_layer );
1249 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1250 textItem->SetPosition( default_pos );
1251 default_pos.y += settings.GetTextSize( txt_layer ).y;
1252 footprint->GraphicalItems().push_back( textItem );
1253 }
1254
1255 if( footprint->GetReference().IsEmpty() )
1256 footprint->SetReference( aFootprintName );
1257
1258 if( footprint->GetValue().IsEmpty() )
1259 footprint->SetValue( aFootprintName );
1260
1261 footprint->RunOnChildren(
1262 [&]( BOARD_ITEM* aChild )
1263 {
1264 if( aChild->Type() == PCB_FIELD_T || aChild->Type() == PCB_TEXT_T )
1265 {
1266 PCB_TEXT* textItem = static_cast<PCB_TEXT*>( aChild );
1267 PCB_LAYER_ID layer = textItem->GetLayer();
1268
1269 textItem->SetTextThickness( settings.GetTextThickness( layer ) );
1270 textItem->SetTextSize( settings.GetTextSize( layer ) );
1271 textItem->SetItalic( settings.GetTextItalic( layer ) );
1272 textItem->SetKeepUpright( settings.GetTextUpright( layer ) );
1273 }
1274 },
1276
1277 SetMsgPanel( footprint );
1278 return footprint;
1279}
1280
1281
1283 std::vector<wxArrayString>& aItemsToDisplay )
1284{
1285 aHeaders.Add( _( "Library" ) );
1286 aHeaders.Add( _( "Description" ) );
1287
1291 std::vector<wxString> nicknames = fptbl->GetLogicalLibs();
1292
1293 for( const wxString& nickname : nicknames )
1294 {
1295 if( alg::contains( project.m_PinnedFootprintLibs, nickname )
1296 || alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1297 {
1298 wxArrayString item;
1299
1300 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
1301 item.Add( fptbl->GetDescription( nickname ) );
1302 aItemsToDisplay.push_back( item );
1303 }
1304 }
1305
1306 for( const wxString& nickname : nicknames )
1307 {
1308 if( !alg::contains( project.m_PinnedFootprintLibs, nickname )
1309 && !alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1310 {
1311 wxArrayString item;
1312
1313 item.Add( nickname );
1314 item.Add( fptbl->GetDescription( nickname ) );
1315 aItemsToDisplay.push_back( item );
1316 }
1317 }
1318}
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:317
const NETINFO_LIST & GetNetInfo() const
Definition board.h:945
void BuildListOfNets()
Definition board.h:908
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition board.h:500
const FOOTPRINTS & Footprints() const
Definition board.h:358
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()
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
void ApplyDefaultSettings(const BOARD &board, bool aStyleFields, bool aStyleText, bool aStyleShapes)
Apply default board settings to the footprint field text properties.
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 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 a record identifying a library accessed by the appropriate footprint library #PLUGIN object in t...
const FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an FP_LIB_TABLE_ROW if aNickName is found in this table or in any chained fall back table frag...
void FootprintDelete(const wxString &aNickname, const wxString &aFootprintName)
Delete the aFootprintName from the library given by aNickname.
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aNickname, bool aBestEfforts)
Return a list of footprint names contained within the library given by aNickname.
bool FootprintExists(const wxString &aNickname, const wxString &aFootprintName)
Indicates whether or not the given footprint already exists in the given library.
FOOTPRINT * FootprintLoad(const wxString &aNickname, const wxString &aFootprintName, bool aKeepUUID=false)
Load a footprint having aFootprintName from the library given by aNickname.
SAVE_T FootprintSave(const wxString &aNickname, const FOOTPRINT *aFootprint, bool aOverwrite=true)
Write aFootprint to an existing library given by aNickname.
static wxString GetGlobalTableFileName()
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:395
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition kiway.cpp:192
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
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
const wxString GetDescription(const wxString &aNickname)
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
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:356
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.
bool AddLibrary(const wxString &aDialogTitle, const wxString &aLibName=wxEmptyString, FP_LIB_TABLE *aTable=nullptr)
Add an existing library to either the global or project library table.
wxString CreateNewProjectLibrary(const wxString &aDialogTitle, const wxString &aLibName)
wxString createNewLibrary(const wxString &aDialogTitle, const wxString &aLibName, const wxString &aInitialPath, FP_LIB_TABLE *aTable)
Create a new library in the given 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:94
static PCB_IO * PluginFind(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
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_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:576
The backing store for a PROJECT, in JSON format.
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
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:162
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:334
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:345
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:429
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:251
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:222
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:194
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:169
This file is part of the common library.
FP_LIB_TABLE GFootprintTable
The global footprint library table.
Definition cvpcb.cpp:150
#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:612
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, bool aCompactSave)
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:913
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: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
@ 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.