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, aExtraCheckboxes );
433 dlg.SetListLabel( aListLabel );
434
435 wxButton* newLibraryButton = new wxButton( &dlg, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
436 dlg.m_ButtonsSizer->Prepend( 80, 20 );
437 dlg.m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
438
439 newLibraryButton->Bind( wxEVT_BUTTON,
440 [&dlg]( wxCommandEvent& )
441 {
442 dlg.EndModal( ID_MAKE_NEW_LIBRARY );
444
445 dlg.Layout();
446 dlg.GetSizer()->Fit( &dlg );
447
448 int ret = dlg.ShowModal();
449
450 switch( ret )
451 {
452 case wxID_CANCEL:
453 return wxEmptyString;
454
455 case wxID_OK:
456 libraryName = dlg.GetTextSelection();
457 Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, libraryName );
459 return libraryName;
460
462 {
463 wxFileName fn = CreateNewLibrary( _( "New Footprint Library" ),
464 Prj().GetRString( PROJECT::PCB_LIB_PATH ) );
465
466 Prj().SetRString( PROJECT::PCB_LIB_PATH, fn.GetPath() );
467 Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, fn.GetName() );
468 break;
469 }
470
471 default:
472 break;
473 }
474 }
475}
476
477
478bool PCB_BASE_EDIT_FRAME::AddLibrary( const wxString& aDialogTitle, const wxString& aFilename,
479 FP_LIB_TABLE* aTable )
480{
481 bool isGlobal = false;
483 FILEDLG_HOOK_NEW_LIBRARY tableChooser( isGlobal );
484 FILEDLG_HOOK_NEW_LIBRARY* fileDlgHook = &tableChooser;
485
486 if( aTable )
487 {
488 isGlobal = ( aTable == &GFootprintTable );
489 libTable = aTable;
490 fileDlgHook = nullptr;
491 }
492
493 wxFileName fn( aFilename );
494
495 if( aFilename.IsEmpty() )
496 {
497 if( !LibraryFileBrowser( aDialogTitle, true, fn, FILEEXT::KiCadFootprintLibPathWildcard(),
498 FILEEXT::KiCadFootprintLibPathExtension, true, fileDlgHook ) )
499 {
500 return false;
501 }
502
503 if( fileDlgHook )
504 {
505 isGlobal = fileDlgHook->GetUseGlobalTable();
506 libTable = isGlobal ? &GFootprintTable : PROJECT_PCB::PcbFootprintLibs( &Prj() );
507 }
508 }
509
510 wxString libPath = fn.GetFullPath();
511 wxString libName = fn.GetName();
512
513 if( libName.IsEmpty() )
514 return false;
515
517
518 if( lib_type == PCB_IO_MGR::FILE_TYPE_NONE )
519 lib_type = PCB_IO_MGR::KICAD_SEXP;
520
521 wxString type = PCB_IO_MGR::ShowType( lib_type );
522
523 // KiCad lib is our default guess. So it might not have the .pretty extension
524 // In this case, the extension is part of the library name
525 if( lib_type == PCB_IO_MGR::KICAD_SEXP && fn.GetExt() != FILEEXT::KiCadFootprintLibPathExtension )
526 libName = fn.GetFullName();
527
528 // try to use path normalized to an environmental variable or project path
529 wxString normalizedPath = NormalizePath( libPath, &Pgm().GetLocalEnvVariables(), &Prj() );
530
531 try
532 {
533 FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libName, normalizedPath, type, wxEmptyString );
534 libTable->InsertRow( row );
535
536 if( isGlobal )
538 else
539 libTable->Save( Prj().FootprintLibTblName() );
540 }
541 catch( const IO_ERROR& ioe )
542 {
543 DisplayError( this, ioe.What() );
544 return false;
545 }
546
548
549 if( editor )
550 {
551 LIB_ID libID( libName, wxEmptyString );
552 editor->SyncLibraryTree( true );
553 editor->FocusOnLibID( libID );
554 }
555
556 auto viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_VIEWER, false );
557
558 if( viewer )
559 viewer->ReCreateLibraryList();
560
561 return true;
562}
563
564
566{
567 if( !aFPID.IsValid() )
568 return false;
569
570 wxString nickname = aFPID.GetLibNickname();
571 wxString fpname = aFPID.GetLibItemName();
572 wxString libfullname;
573
574 // Legacy libraries are readable, but modifying legacy format is not allowed
575 // So prompt the user if he try to delete a footprint from a legacy lib
576 try
577 {
578 libfullname = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( nickname )->GetFullURI();
579 }
580 catch( ... )
581 {
582 // If we can't find the nickname, stop here
583 return false;
584 }
585
587 {
589 return false;
590 }
591
592 if( !PROJECT_PCB::PcbFootprintLibs( &Prj() )->IsFootprintLibWritable( nickname ) )
593 {
594 wxString msg = wxString::Format( _( "Library '%s' is read only." ), nickname );
595 ShowInfoBarError( msg );
596 return false;
597 }
598
599 // Confirmation
600 wxString msg = wxString::Format( _( "Delete footprint '%s' from library '%s'?" ),
601 fpname.GetData(),
602 nickname.GetData() );
603
604 if( aConfirm && !IsOK( this, msg ) )
605 return false;
606
607 try
608 {
609 PROJECT_PCB::PcbFootprintLibs( &Prj() )->FootprintDelete( nickname, fpname );
610 }
611 catch( const IO_ERROR& ioe )
612 {
613 DisplayError( this, ioe.What() );
614 return false;
615 }
616
617 msg.Printf( _( "Footprint '%s' deleted from library '%s'" ),
618 fpname.GetData(),
619 nickname.GetData() );
620
621 SetStatusText( msg );
622
623 return true;
624}
625
626
627void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxString& aLibName,
628 wxString* aLibPath )
629{
630 if( GetBoard()->GetFirstFootprint() == nullptr )
631 {
632 DisplayInfoMessage( this, _( "No footprints to export!" ) );
633 return;
634 }
635
636 bool map = false;
637 PROJECT& prj = Prj();
638 wxString nickname = SelectLibrary( _( "Export Footprints" ), _( "Export footprints to library:" ),
639 { { _( "Update board footprints to link to exported footprints" ), &map } } );
640
641 if( !nickname ) // Aborted
642 return;
643
644 prj.SetRString( PROJECT::PCB_LIB_NICKNAME, nickname );
645
646 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
647 {
648 try
649 {
651
652 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
653 {
654 FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate( IGNORE_PARENT_GROUP ) );
655
656 // Reset reference designator, group membership, and zone offset before saving
657
658 fpCopy->SetReference( "REF**" );
659
660 if( EDA_GROUP* parentGroup = fpCopy->GetParentGroup() )
661 parentGroup->RemoveItem( fpCopy );
662
663 for( ZONE* zone : fpCopy->Zones() )
664 zone->Move( -fpCopy->GetPosition() );
665
666 tbl->FootprintSave( nickname, fpCopy, true );
667
668 delete fpCopy;
669 }
670 }
671 catch( const IO_ERROR& ioe )
672 {
673 DisplayError( this, ioe.What() );
674 }
675
676 if( map )
677 {
678 LIB_ID id = footprint->GetFPID();
679 id.SetLibNickname( nickname );
680 footprint->SetFPID( id );
681 }
682 }
683}
684
685
687{
688 if( !aFootprint ) // Happen if no footprint loaded
689 return false;
690
691 PAD_TOOL* padTool = m_toolManager->GetTool<PAD_TOOL>();
692
693 if( padTool->InPadEditMode() )
695
696 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
697 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
698 bool nameChanged = m_footprintNameWhenLoaded != footprintName;
699
700 if( aFootprint->GetLink() != niluuid )
701 {
702 if( SaveFootprintToBoard( false ) )
703 {
704 m_footprintNameWhenLoaded = footprintName;
705 return true;
706 }
707
708 return false;
709 }
710 else if( libraryName.IsEmpty() || footprintName.IsEmpty() )
711 {
712 if( SaveFootprintAs( aFootprint ) )
713 {
714 m_footprintNameWhenLoaded = footprintName;
715 SyncLibraryTree( true );
716 return true;
717 }
718
719 return false;
720 }
721
723
724 // Legacy libraries are readable, but modifying legacy format is not allowed
725 // So prompt the user if he try to add/replace a footprint in a legacy lib
726 wxString libfullname;
727
728 try
729 {
730 libfullname = tbl->FindRow( libraryName )->GetFullURI();
731 }
732 catch( IO_ERROR& error )
733 {
734 DisplayInfoMessage( this, error.What() );
735 return false;
736 }
737
739 {
741 return false;
742 }
743
744 if( nameChanged )
745 {
746 LIB_ID oldFPID( libraryName, m_footprintNameWhenLoaded );
747 DeleteFootprintFromLibrary( oldFPID, false );
748 }
749
750 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
751 return false;
752
753 if( nameChanged )
754 {
755 m_footprintNameWhenLoaded = footprintName;
756 SyncLibraryTree( true );
757 }
758
759 return true;
760}
761
762
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 wxString libFullName = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( libraryName )->GetFullURI();
772
774 {
776 return false;
777 }
778
780 int i = 1;
781 wxString newName = footprintName;
782
783 // Append a number to the name until the name is unique in the library.
784 while( tbl->FootprintExists( libraryName, newName ) )
785 newName.Printf( "%s_%d", footprintName, i++ );
786
787 aFootprint->SetFPID( LIB_ID( libraryName, newName ) );
788
789 if( aFootprint->GetValue() == footprintName )
790 aFootprint->SetValue( newName );
791
792 return SaveFootprintInLibrary( aFootprint, libraryName );
793}
794
795
797 const wxString& aLibraryName )
798{
799 try
800 {
801 aFootprint->SetFPID( LIB_ID( wxEmptyString, aFootprint->GetFPID().GetLibItemName() ) );
802
803 PROJECT_PCB::PcbFootprintLibs( &Prj() )->FootprintSave( aLibraryName, aFootprint );
804
805 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
806
807 if( aFootprint == GetBoard()->GetFirstFootprint() )
808 setFPWatcher( aFootprint );
809
810 return true;
811 }
812 catch( const IO_ERROR& ioe )
813 {
814 DisplayError( this, ioe.What() );
815
816 aFootprint->SetFPID( LIB_ID( aLibraryName, aFootprint->GetFPID().GetLibItemName() ) );
817 return false;
818 }
819}
820
821
823{
824 // update footprint in the current board,
825 // not just add it to the board with total disregard for the netlist...
826 PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB_EDITOR, false );
827
828 if( pcbframe == nullptr ) // happens when the board editor is not active (or closed)
829 {
830 ShowInfoBarError( _( "No board currently open." ) );
831 return false;
832 }
833
834 BOARD* mainpcb = pcbframe->GetBoard();
835 FOOTPRINT* sourceFootprint = nullptr;
836 FOOTPRINT* editorFootprint = GetBoard()->GetFirstFootprint();
837
838 if( !editorFootprint )
839 return false;
840
841 // Search the old footprint (source) if exists
842 // Because this source could be deleted when editing the main board...
843 if( editorFootprint->GetLink() != niluuid ) // this is not a new footprint ...
844 {
845 sourceFootprint = nullptr;
846
847 for( FOOTPRINT* candidate : mainpcb->Footprints() )
848 {
849 if( editorFootprint->GetLink() == candidate->m_Uuid )
850 {
851 sourceFootprint = candidate;
852 break;
853 }
854 }
855 }
856
857 if( !aAddNew && sourceFootprint == nullptr ) // source not found
858 {
859 DisplayError( this, _( "Unable to find the footprint on the main board.\nCannot save." ) );
860 return false;
861 }
862
863 TOOL_MANAGER* pcb_ToolManager = pcbframe->GetToolManager();
864
865 if( aAddNew && pcb_ToolManager->GetTool<BOARD_EDITOR_CONTROL>()->PlacingFootprint() )
866 {
867 DisplayError( this, _( "Previous footprint placement still in progress." ) );
868 return false;
869 }
870
872 BOARD_COMMIT commit( pcbframe );
873
874 // Create a copy for the board, first using Clone() to keep existing Uuids, and then either
875 // resetting the uuids to the board values or assigning new Uuids.
876 FOOTPRINT* newFootprint = static_cast<FOOTPRINT*>( editorFootprint->Clone() );
877 newFootprint->SetParent( mainpcb );
878 newFootprint->SetLink( niluuid );
879
880 auto fixUuid =
881 [&]( KIID& aUuid )
882 {
883 if( editorFootprint->GetLink() != niluuid && m_boardFootprintUuids.count( aUuid ) )
884 aUuid = m_boardFootprintUuids[ aUuid ];
885 else
886 aUuid = KIID();
887 };
888
889 fixUuid( const_cast<KIID&>( newFootprint->m_Uuid ) );
890
891 newFootprint->RunOnChildren(
892 [&]( BOARD_ITEM* aChild )
893 {
894 fixUuid( const_cast<KIID&>( aChild->m_Uuid ) );
895 },
896 RECURSE_MODE::RECURSE );
897
898 // Right now, we only show the "Unconnected" net in the footprint editor, but this is still
899 // referenced in the footprint. So we need to update the net pointers in the footprint to
900 // point to the nets in the main board.
901 newFootprint->RunOnChildren(
902 [&]( BOARD_ITEM* aChild )
903 {
904 if( BOARD_CONNECTED_ITEM* conn = dynamic_cast<BOARD_CONNECTED_ITEM*>( aChild ) )
905 {
906 NETINFO_ITEM* net = conn->GetNet();
907 auto& netmap = mainpcb->GetNetInfo().NetsByName();
908
909 if( net )
910 {
911 auto it = netmap.find( net->GetNetname() );
912
913 if( it != netmap.end() )
914 conn->SetNet( it->second );
915 }
916
917 }
918 },
919 RECURSE_MODE::RECURSE );
920
922
924 bds.m_StyleFPShapes );
925
926 if( sourceFootprint ) // this is an update command
927 {
928 // In the main board the new footprint replaces the old one (pos, orient, ref, value,
929 // connections and properties are kept) and the sourceFootprint (old footprint) is
930 // deleted
931 pcbframe->ExchangeFootprint( sourceFootprint, newFootprint, commit );
932 commit.Push( _( "Update Footprint" ) );
933 }
934 else // This is an insert command
935 {
936 KIGFX::VIEW_CONTROLS* viewControls = pcbframe->GetCanvas()->GetViewControls();
937 VECTOR2D cursorPos = viewControls->GetCursorPosition();
938
939 commit.Add( newFootprint );
940 viewControls->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
941 pcbframe->PlaceFootprint( newFootprint );
942 newFootprint->SetPosition( VECTOR2I( 0, 0 ) );
943 viewControls->SetCrossHairCursorPosition( cursorPos, false );
944 const_cast<KIID&>( newFootprint->m_Uuid ) = KIID();
945 commit.Push( _( "Insert Footprint" ) );
946
947 pcbframe->Raise();
948 pcb_ToolManager->RunAction( PCB_ACTIONS::placeFootprint, newFootprint );
949 }
950
951 newFootprint->ClearFlags();
952
953 return true;
954}
955
956
958{
959public:
960 SAVE_AS_DIALOG( FOOTPRINT_EDIT_FRAME* aParent, const wxString& aFootprintName,
961 const wxString& aLibraryPreselect,
962 std::function<bool( wxString libName, wxString fpName )> aValidator ) :
963 EDA_LIST_DIALOG( aParent, _( "Save Footprint As" ), false ),
964 m_validator( std::move( aValidator ) )
965 {
966 FP_LIB_TABLE* tbl = PROJECT_PCB::PcbFootprintLibs( &aParent->Prj() );
967 std::vector<wxString> nicknames = tbl->GetLogicalLibs();
968 wxArrayString headers;
969 std::vector<wxArrayString> itemsToDisplay;
970
971 aParent->GetLibraryItemsForListDialog( headers, itemsToDisplay );
972 initDialog( headers, itemsToDisplay, aLibraryPreselect );
973
974 SetListLabel( _( "Save in library:" ) );
975 SetOKLabel( _( "Save" ) );
976
977 wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
978
979 wxStaticText* label = new wxStaticText( this, wxID_ANY, _( "Name:" ) );
980 bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
981
982 m_fpNameCtrl = new wxTextCtrl( this, wxID_ANY, aFootprintName );
983 bNameSizer->Add( m_fpNameCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
984
985 wxTextValidator nameValidator( wxFILTER_EXCLUDE_CHAR_LIST );
986 nameValidator.SetCharExcludes( FOOTPRINT::StringLibNameInvalidChars( false ) );
987 m_fpNameCtrl->SetValidator( nameValidator );
988
989 wxButton* newLibraryButton = new wxButton( this, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
990 m_ButtonsSizer->Prepend( 80, 20 );
991 m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
992
993 GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
994
995 Bind( wxEVT_BUTTON,
996 [this]( wxCommandEvent& )
997 {
998 EndModal( ID_MAKE_NEW_LIBRARY );
1000
1001 // Move nameTextCtrl to the head of the tab-order
1002 if( GetChildren().DeleteObject( m_fpNameCtrl ) )
1003 GetChildren().Insert( m_fpNameCtrl );
1004
1006
1008
1009 Layout();
1010 GetSizer()->Fit( this );
1011
1012 Centre();
1013 }
1014
1015 wxString GetFPName()
1016 {
1017 wxString footprintName = m_fpNameCtrl->GetValue();
1018 footprintName.Trim( true );
1019 footprintName.Trim( false );
1020 return footprintName;
1021 }
1022
1023protected:
1025 {
1026 return m_validator( GetTextSelection(), GetFPName() );
1027 }
1028
1029private:
1030 wxTextCtrl* m_fpNameCtrl;
1031 std::function<bool( wxString libName, wxString fpName )> m_validator;
1032};
1033
1034
1036{
1037 if( aFootprint == nullptr )
1038 return false;
1039
1041
1042 SetMsgPanel( aFootprint );
1043
1044 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
1045 wxString footprintName = aFootprint->GetFPID().GetLibItemName();
1046 bool updateValue = aFootprint->GetValue() == footprintName;
1047 bool done = false;
1048 bool footprintExists = false;
1049
1050 while( !done )
1051 {
1052 SAVE_AS_DIALOG dlg( this, footprintName, libraryName,
1053 [&]( const wxString& newLib, const wxString& newName )
1054 {
1055 if( newLib.IsEmpty() )
1056 {
1057 wxMessageBox( _( "A library must be specified." ) );
1058 return false;
1059 }
1060
1061 if( newName.IsEmpty() )
1062 {
1063 wxMessageBox( _( "Footprint must have a name." ) );
1064 return false;
1065 }
1066
1067 // Legacy libraries are readable, but modifying legacy format is not allowed
1068 // So prompt the user if he try to add/replace a footprint in a legacy lib
1069 const FP_LIB_TABLE_ROW* row = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRow( newLib );
1070 wxString libPath = row->GetFullURI();
1072
1073 if( piType == PCB_IO_MGR::LEGACY )
1074 {
1076 return false;
1077 }
1078
1079 footprintExists = tbl->FootprintExists( newLib, newName );
1080
1081 if( footprintExists )
1082 {
1083 wxString msg = wxString::Format( _( "Footprint %s already exists in %s." ),
1084 newName,
1085 newLib );
1086
1087 KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1088 errorDlg.SetOKLabel( _( "Overwrite" ) );
1089
1090 return errorDlg.ShowModal() == wxID_OK;
1091 }
1092
1093 return true;
1094 } );
1095
1096 int ret = dlg.ShowModal();
1097
1098 if( ret == wxID_CANCEL )
1099 {
1100 return false;
1101 }
1102 else if( ret == wxID_OK )
1103 {
1104 footprintName = dlg.GetFPName();
1105 libraryName = dlg.GetTextSelection();
1106 done = true;
1107 }
1108 else if( ret == ID_MAKE_NEW_LIBRARY )
1109 {
1110 wxFileName fn = CreateNewLibrary( _( "New Footprint Library" ),
1111 Prj().GetRString( PROJECT::PCB_LIB_PATH ) );
1112
1113 Prj().SetRString( PROJECT::PCB_LIB_PATH, fn.GetPath() );
1114 Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, fn.GetName() );
1115 libraryName = fn.GetName();
1116 }
1117 }
1118
1119 aFootprint->SetFPID( LIB_ID( libraryName, footprintName ) );
1120
1121 if( updateValue )
1122 aFootprint->SetValue( footprintName );
1123
1124 if( !SaveFootprintInLibrary( aFootprint, libraryName ) )
1125 return false;
1126
1127 // Once saved-as a board footprint is no longer a board footprint
1128 aFootprint->SetLink( niluuid );
1129
1130 wxString fmt = footprintExists ? _( "Footprint '%s' replaced in '%s'" )
1131 : _( "Footprint '%s' added to '%s'" );
1132
1133 wxString msg = wxString::Format( fmt, footprintName.GetData(), libraryName.GetData() );
1134 SetStatusText( msg );
1135 UpdateTitle();
1137
1138 return true;
1139}
1140
1141
1143{
1145 {
1146 wxString msg = wxString::Format( _( "Revert '%s' to last version saved?" ),
1147 GetLoadedFPID().GetLibItemName().wx_str() );
1148
1149 if( ConfirmRevertDialog( this, msg ) )
1150 {
1151 Clear_Pcb( false );
1152 AddFootprintToBoard( static_cast<FOOTPRINT*>( m_originalFootprintCopy->Clone() ) );
1153
1154 Zoom_Automatique( false );
1155
1156 Update3DView( true, true );
1157
1159 GetScreen()->SetContentModified( false );
1160
1161 UpdateView();
1162 GetCanvas()->Refresh();
1163
1164 return true;
1165 }
1166 }
1167
1168 return false;
1169}
1170
1171
1172FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( wxString aFootprintName, const wxString& aLibName )
1173{
1174 if( aFootprintName.IsEmpty() )
1175 aFootprintName = _( "Untitled" );
1176
1177 int footprintAttrs = FP_SMD;
1178
1179 if( !aLibName.IsEmpty() )
1180 {
1182 wxArrayString fpnames;
1183 wxString baseName = aFootprintName;
1184 int idx = 1;
1185
1186 // Make sure the name is unique
1187 while( tbl->FootprintExists( aLibName, aFootprintName ) )
1188 aFootprintName = baseName + wxString::Format( wxS( "_%d" ), idx++ );
1189
1190 // Try to infer the footprint attributes from an existing footprint in the library
1191 try
1192 {
1193 tbl->FootprintEnumerate( fpnames, aLibName, true );
1194
1195 if( !fpnames.empty() )
1196 footprintAttrs = tbl->FootprintLoad( aLibName, fpnames.Last() )->GetAttributes();
1197 }
1198 catch( ... )
1199 {
1200 // best efforts
1201 }
1202 }
1203
1204 // Create the new footprint and add it to the head of the linked list of footprints
1205 FOOTPRINT* footprint = new FOOTPRINT( GetBoard() );
1206
1207 // Update its name in lib
1208 footprint->SetFPID( LIB_ID( wxEmptyString, aFootprintName ) );
1209
1210 footprint->SetAttributes( footprintAttrs );
1211
1212 PCB_LAYER_ID txt_layer;
1213 VECTOR2I default_pos;
1215
1216 if( settings.m_DefaultFPTextItems.size() > 0 )
1217 {
1218 footprint->Reference().SetText( settings.m_DefaultFPTextItems[0].m_Text );
1219 footprint->Reference().SetVisible( settings.m_DefaultFPTextItems[0].m_Visible );
1220 }
1221
1222 txt_layer = settings.m_DefaultFPTextItems[0].m_Layer;
1223 footprint->Reference().SetLayer( txt_layer );
1224 default_pos.y -= settings.GetTextSize( txt_layer ).y / 2;
1225 footprint->Reference().SetPosition( default_pos );
1226 default_pos.y += settings.GetTextSize( txt_layer ).y;
1227
1228 if( settings.m_DefaultFPTextItems.size() > 1 )
1229 {
1230 footprint->Value().SetText( settings.m_DefaultFPTextItems[1].m_Text );
1231 footprint->Value().SetVisible( settings.m_DefaultFPTextItems[1].m_Visible );
1232 }
1233
1234 txt_layer = settings.m_DefaultFPTextItems[1].m_Layer;
1235 footprint->Value().SetLayer( txt_layer );
1236 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1237 footprint->Value().SetPosition( default_pos );
1238 default_pos.y += settings.GetTextSize( txt_layer ).y;
1239
1240 for( size_t i = 2; i < settings.m_DefaultFPTextItems.size(); ++i )
1241 {
1242 PCB_TEXT* textItem = new PCB_TEXT( footprint );
1243 textItem->SetText( settings.m_DefaultFPTextItems[i].m_Text );
1244 txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[i].m_Layer;
1245 textItem->SetLayer( txt_layer );
1246 default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
1247 textItem->SetPosition( default_pos );
1248 default_pos.y += settings.GetTextSize( txt_layer ).y;
1249 footprint->GraphicalItems().push_back( textItem );
1250 }
1251
1252 if( footprint->GetReference().IsEmpty() )
1253 footprint->SetReference( aFootprintName );
1254
1255 if( footprint->GetValue().IsEmpty() )
1256 footprint->SetValue( aFootprintName );
1257
1258 footprint->RunOnChildren(
1259 [&]( BOARD_ITEM* aChild )
1260 {
1261 if( aChild->Type() == PCB_FIELD_T || aChild->Type() == PCB_TEXT_T )
1262 {
1263 PCB_TEXT* textItem = static_cast<PCB_TEXT*>( aChild );
1264 PCB_LAYER_ID layer = textItem->GetLayer();
1265
1266 textItem->SetTextThickness( settings.GetTextThickness( layer ) );
1267 textItem->SetTextSize( settings.GetTextSize( layer ) );
1268 textItem->SetItalic( settings.GetTextItalic( layer ) );
1269 textItem->SetKeepUpright( settings.GetTextUpright( layer ) );
1270 }
1271 },
1272 RECURSE_MODE::RECURSE );
1273
1274 SetMsgPanel( footprint );
1275 return footprint;
1276}
1277
1278
1280 std::vector<wxArrayString>& aItemsToDisplay )
1281{
1282 aHeaders.Add( _( "Library" ) );
1283 aHeaders.Add( _( "Description" ) );
1284
1288 std::vector<wxString> nicknames = fptbl->GetLogicalLibs();
1289
1290 for( const wxString& nickname : nicknames )
1291 {
1292 if( alg::contains( project.m_PinnedFootprintLibs, nickname )
1293 || alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1294 {
1295 wxArrayString item;
1296
1297 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
1298 item.Add( fptbl->GetDescription( nickname ) );
1299 aItemsToDisplay.push_back( item );
1300 }
1301 }
1302
1303 for( const wxString& nickname : nicknames )
1304 {
1305 if( !alg::contains( project.m_PinnedFootprintLibs, nickname )
1306 && !alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
1307 {
1308 wxArrayString item;
1309
1310 item.Add( nickname );
1311 item.Add( fptbl->GetDescription( nickname ) );
1312 aItemsToDisplay.push_back( item );
1313 }
1314 }
1315}
1316
1317
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: actions.h:221
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:934
void BuildListOfNets()
Definition: board.h:897
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:489
const FOOTPRINTS & Footprints() const
Definition: board.h:358
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:1024
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition: commit.h:79
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:75
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...
wxString m_mruPath
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 GetExtraCheckboxValues()
Fills in the value pointers from the checkboxes after the dialog has run.
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:533
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:386
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:284
void SetKeepUpright(bool aKeepUpright)
Definition: eda_text.cpp:425
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:270
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition: eda_text.cpp:307
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
Definition: footprint.cpp:2513
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:252
void SetLink(const KIID &aLink)
Definition: footprint.h:844
ZONES & Zones()
Definition: footprint.h:215
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
Definition: footprint.cpp:2256
void SetAttributes(int aAttributes)
Definition: footprint.h:294
EDA_ITEM * Clone() const override
Invoke a function on all children.
Definition: footprint.cpp:2250
PCB_FIELD & Value()
read/write accessors:
Definition: footprint.h:663
void ApplyDefaultSettings(const BOARD &board, bool aStyleFields, bool aStyleText, bool aStyleShapes)
Apply default board settings to the footprint field text properties.
Definition: footprint.cpp:672
int GetAttributes() const
Definition: footprint.h:293
const LIB_ID & GetFPID() const
Definition: footprint.h:251
void SetReference(const wxString &aReference)
Definition: footprint.h:633
void SetValue(const wxString &aValue)
Definition: footprint.h:654
PCB_FIELD & Reference()
Definition: footprint.h:664
KIID GetLink() const
Definition: footprint.h:843
static const wxChar * StringLibNameInvalidChars(bool aUserReadable)
Test for validity of the name in a library of the footprint ( no spaces, dir separators ....
Definition: footprint.cpp:2395
const wxString & GetValue() const
Definition: footprint.h:649
const wxString & GetReference() const
Definition: footprint.h:627
VECTOR2I GetPosition() const override
Definition: footprint.h:227
DRAWINGS & GraphicalItems()
Definition: footprint.h:212
Hold a record identifying a library accessed by the appropriate footprint library #PLUGIN object in t...
Definition: fp_lib_table.h:42
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.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:50
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition: kidialog.cpp:51
int ShowModal() override
Definition: kidialog.cpp:95
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.
wxString GetFullURI(const wxString &aLibNickname, bool aExpandEnvVars=true) const
Return the full URI of the library mapped to aLibNickname.
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:56
const wxString & GetNetname() const
Definition: netinfo.h:114
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition: netinfo.h:372
bool InPadEditMode()
Definition: pad_tool.h:61
static TOOL_ACTION recombinePad
Definition: pcb_actions.h:502
static TOOL_ACTION placeFootprint
Definition: pcb_actions.h:216
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 ExchangeFootprint(FOOTPRINT *aExisting, FOOTPRINT *aNew, BOARD_COMMIT &aCommit, bool deleteExtraTexts=true, bool resetTextLayers=true, bool resetTextEffects=true, bool resetFabricationAttrs=true, bool resetTextContent=true, bool resetClearanceOverrides=true, bool reset3DModels=true, bool *aUpdated=nullptr)
Replace aExisting footprint by aNew footprint using the Existing footprint settings (position,...
void ExportFootprintsToLibrary(bool aStoreInNewLib, const wxString &aLibName=wxEmptyString, wxString *aLibPath=nullptr)
Save footprints in a library:
A #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
void Format(const BOARD_ITEM *aItem) const
Output aItem to aFormatter in s-expression format.
std::string GetStringOutput(bool doClear)
static PLUGIN_REGISTRY * Instance()
Definition: pcb_io_mgr.h: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.
Definition: pcb_io_mgr.cpp:68
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
@ FILE_TYPE_NONE
Definition: pcb_io_mgr.h:77
@ 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.
Definition: pcb_io_mgr.cpp:135
static const wxString ShowType(PCB_FILE_T aFileType)
Return a brief name for a plugin given aFileType enum.
Definition: pcb_io_mgr.cpp:77
virtual void SetPosition(const VECTOR2I &aPos) override
Definition: pcb_text.h:89
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:565
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:68
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
Definition: project_pcb.cpp:37
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:149
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:321
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:332
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
Definition: tools_holder.h:171
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
Master controller class:
Definition: tool_manager.h:62
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
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)
#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:81
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:608
This file is part of the common library.
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:902
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.