KiCad PCB EDA Suite
Loading...
Searching...
No Matches
footprint_editor_control.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 (C) 2014-2019 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Maciej Suminski <[email protected]>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
23
24#include <memory>
25
26#include <advanced_config.h>
27#include <string_utils.h>
28#include <pgm_base.h>
30#include <tool/tool_manager.h>
32#include <tools/pcb_actions.h>
34#include <eda_doc.h>
37#include <pcbnew_settings.h>
38#include <pcbnew_id.h>
39#include <confirm.h>
40#include <kidialog.h>
41#include <wx/debug.h>
42#include <wx/filedlg.h>
43#include <wx/filename.h>
45#include <launch_ext.h> // To default when file manager setting is empty
46#include <gestfich.h> // To open with a text editor
47#include <widgets/wx_infobar.h>
48#include <footprint.h>
49#include <pad.h>
50#include <pcb_group.h>
51#include <zone.h>
58#include <kiway.h>
59#include <pcb_plotter.h>
60#include <project_pcb.h>
61#include <view/view_controls.h>
66#include <wx/dirdlg.h>
67
68
70 PCB_TOOL_BASE( "pcbnew.ModuleEditor" ),
71 m_frame( nullptr ),
72 m_checkerDialog( nullptr )
73{
74}
75
76
84
85
87{
88 LIBRARY_EDITOR_CONTROL* libraryTreeTool = m_toolMgr->GetTool<LIBRARY_EDITOR_CONTROL>();
89
90 // Build a context menu for the footprint tree
91 //
92 CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
93
94 auto libSelectedCondition =
95 [this]( const SELECTION& aSel )
96 {
97 LIB_ID sel = m_frame->GetLibTree()->GetSelectedLibId();
98 return !sel.GetLibNickname().empty() && sel.GetLibItemName().empty();
99 };
100
101 // The libInferredCondition allows you to do things like New Symbol and Paste with a
102 // symbol selected (in other words, when we know the library context even if the library
103 // itself isn't selected.
104 auto libInferredCondition =
105 [this]( const SELECTION& aSel )
106 {
107 LIB_ID sel = m_frame->GetLibTree()->GetSelectedLibId();
108 return !sel.GetLibNickname().empty();
109 };
110
111 auto fpSelectedCondition =
112 [this]( const SELECTION& aSel )
113 {
114 LIB_ID sel = m_frame->GetLibTree()->GetSelectedLibId();
115 return !sel.GetLibNickname().empty() && !sel.GetLibItemName().empty();
116 };
117
118 auto fpExportCondition =
119 [this]( const SELECTION& aSel )
120 {
121 FOOTPRINT* fp = m_frame->GetBoard()->GetFirstFootprint();
122 return fp != nullptr;
123 };
124
125 auto canOpenExternally =
126 [this]( const SELECTION& aSel )
127 {
128 // The option is shown if the editor has no current edits,
129 // dumb/simple guard against opening a new file that does not exist on disk
130 bool ret = !m_frame->IsContentModified();
131 return ret;
132 };
133
134// clang-format off
135 ctxMenu.AddItem( PCB_ACTIONS::newFootprint, libSelectedCondition, 10 );
136 ctxMenu.AddItem( PCB_ACTIONS::createFootprint, libSelectedCondition, 10 );
137
138 ctxMenu.AddSeparator( 10 );
139 ctxMenu.AddItem( ACTIONS::save, SELECTION_CONDITIONS::ShowAlways, 10 );
140 ctxMenu.AddItem( ACTIONS::saveAs, libSelectedCondition || fpSelectedCondition, 10 );
141 ctxMenu.AddItem( ACTIONS::revert, libSelectedCondition || libInferredCondition, 10 );
142
143 ctxMenu.AddSeparator( 10 );
144 ctxMenu.AddItem( PCB_ACTIONS::cutFootprint, fpSelectedCondition, 10 );
145 ctxMenu.AddItem( PCB_ACTIONS::copyFootprint, fpSelectedCondition, 10 );
146 ctxMenu.AddItem( PCB_ACTIONS::pasteFootprint, libInferredCondition, 10 );
147 ctxMenu.AddItem( PCB_ACTIONS::duplicateFootprint, fpSelectedCondition, 10 );
148 ctxMenu.AddItem( PCB_ACTIONS::renameFootprint, fpSelectedCondition, 10 );
149 ctxMenu.AddItem( PCB_ACTIONS::deleteFootprint, fpSelectedCondition, 10 );
150 ctxMenu.AddItem( PCB_ACTIONS::footprintProperties, fpSelectedCondition, 10 );
151
152 ctxMenu.AddSeparator( 100 );
153 ctxMenu.AddItem( PCB_ACTIONS::importFootprint, libInferredCondition, 100 );
154 ctxMenu.AddItem( PCB_ACTIONS::exportFootprint, fpExportCondition, 100 );
155
156 if( ADVANCED_CFG::GetCfg().m_EnableLibWithText )
157 {
158 ctxMenu.AddSeparator( 200 );
159 ctxMenu.AddItem( ACTIONS::openWithTextEditor, canOpenExternally && fpSelectedCondition, 200 );
160 }
161
162 if( ADVANCED_CFG::GetCfg().m_EnableLibDir )
163 {
164 ctxMenu.AddSeparator( 200 );
165 ctxMenu.AddItem( ACTIONS::openDirectory, canOpenExternally && ( libSelectedCondition || fpSelectedCondition ), 200 );
166 }
167
168 ctxMenu.AddSeparator( 300 );
169 ctxMenu.AddItem( PCB_ACTIONS::showLibFootprintFieldsTable, libInferredCondition, 300 );
170// clang-format on
171
172 libraryTreeTool->AddContextMenuItems( &ctxMenu );
173
174 // Ensure the left toolbar's Line modes group reflects the current setting at startup
175 if( m_toolMgr )
177
178 return true;
179}
180
181
183 const LIB_ID& aTargetLib )
184{
185 const wxString libraryName = aTargetLib.GetUniStringLibNickname();
186
187 if( aTargetLib.GetLibNickname().empty() )
188 {
189 // Do nothing - the footprint will need to be saved manually to assign
190 // to a library.
191 }
192 else
193 {
194 if( !PROJECT_PCB::FootprintLibAdapter( &m_frame->Prj() )->IsFootprintLibWritable( libraryName ) )
195 {
196 // If the library is not writeable, we'll give the user a
197 // footprint not in a library. But add a warning to let them know
198 // they didn't quite get what they wanted.
199 m_frame->ShowInfoBarWarning(
200 wxString::Format(
201 _( "The footprint could not be added to the selected library ('%s'). "
202 "This library is read-only." ),
203 libraryName ),
204 false );
205 // And the footprint will need to be saved manually
206 }
207 else
208 {
209 // Go ahead and save it to the library
210 LIB_ID fpid = aFootprint.GetFPID();
211 fpid.SetLibNickname( aTargetLib.GetLibNickname() );
212 aFootprint.SetFPID( fpid );
213
214 // Clear the modified flag only on a successful save, else the edits are silently
215 // lost (issue #23850).
216 if( m_frame->SaveFootprint( &aFootprint ) )
217 m_frame->ClearModify();
218 }
219 }
220}
221
222
224{
225 const LIB_ID selected = m_frame->GetTargetFPID();
226 const wxString libraryName = selected.GetUniStringLibNickname();
227
228 if( !m_frame->BeginNewFootprint( libraryName ) )
229 return 0;
230
231 FOOTPRINT* newFootprint = m_frame->CreateNewFootprint( wxEmptyString, libraryName );
232
233 if( !newFootprint )
234 return 0;
235
236 // Give the new footprint a resolvable identity so it opens in its own tab instead of
237 // overwriting the active one.
238 if( !libraryName.IsEmpty() )
239 newFootprint->SetFPID( LIB_ID( libraryName, newFootprint->GetFPID().GetLibItemName() ) );
240
242 m_frame->AddFootprintToBoard( newFootprint );
243
244 // Initialize data relative to nets and netclasses (for a new footprint the defaults are
245 // used). This is mandatory to handle and draw pads.
247 newFootprint->SetPosition( VECTOR2I( 0, 0 ) );
248 newFootprint->ClearFlags();
249
250 m_frame->Zoom_Automatique( false );
251 m_frame->GetScreen()->SetContentModified();
252
253 tryToSaveFootprintInLibrary( *newFootprint, selected );
254
255 m_frame->UpdateView();
256 m_frame->GetCanvas()->ForceRefresh();
257 m_frame->Update3DView( true, true );
258
259 m_frame->SyncLibraryTree( false );
260 return 0;
261}
262
263
265{
266 LIB_ID selected = m_frame->GetLibTree()->GetSelectedLibId();
267
268 if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_FOOTPRINT_WIZARD, true, m_frame ) )
269 {
270 FOOTPRINT_WIZARD_FRAME* wizard = static_cast<FOOTPRINT_WIZARD_FRAME*>( frame );
271
272 if( wizard->ShowModal( nullptr, m_frame ) )
273 {
274 // Creates the new footprint from python script wizard
275 FOOTPRINT* newFootprint = wizard->GetBuiltFootprint();
276
277 if( newFootprint ) // i.e. if create footprint command is OK
278 {
279 m_frame->BeginNewFootprint( selected.GetLibNickname() );
280
282 // Add the new object to board
283 m_frame->AddFootprintToBoard( newFootprint );
284
285 // Initialize data relative to nets and netclasses (for a new footprint the
286 // defaults are used). This is mandatory to handle and draw pads.
288 newFootprint->SetPosition( VECTOR2I( 0, 0 ) );
289 newFootprint->ClearFlags();
290
291 m_frame->Zoom_Automatique( false );
292 m_frame->GetScreen()->SetContentModified();
293 m_frame->OnModify();
294
295 tryToSaveFootprintInLibrary( *newFootprint, selected );
296
297 m_frame->UpdateView();
298 canvas()->Refresh();
299 m_frame->Update3DView( true, true );
300
301 m_frame->SyncLibraryTree( false );
302 }
303 }
304
305 wizard->Destroy();
306 }
307
308 return 0;
309}
310
311
313{
314 if( !footprint() ) // no loaded footprint
315 return 0;
316
317 const LIB_ID loadedId = m_frame->GetLoadedFPID();
318
319 // An unsaved import has no library identity for the tree selection to match, and save-as is the only
320 // way to give it one, so never let an unrelated selection swallow its save
321 if( m_frame->GetTargetFPID() == loadedId || loadedId.GetLibNickname().empty() )
322 {
323 if( m_frame->SaveFootprint( footprint() ) )
324 {
325 view()->Update( footprint() );
326
327 canvas()->ForceRefresh();
328 m_frame->ClearModify();
329 }
330 }
331
332 m_frame->RefreshLibraryTree();
333 return 0;
334}
335
336
338{
339 if( m_frame->GetTargetFPID().GetLibItemName().empty() )
340 {
342
343 // Save Library As
344 const wxString& src_libNickname = m_frame->GetTargetFPID().GetLibNickname();
345 std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, src_libNickname, true );
346 wxCHECK( optUri, 0 );
347
348 if( m_frame->SaveLibraryAs( *optUri ) )
349 m_frame->SyncLibraryTree( true );
350 }
351 else if( m_frame->GetTargetFPID() == m_frame->GetLoadedFPID() )
352 {
353 // Save Footprint As
354 if( footprint() && m_frame->SaveFootprintAs( footprint() ) )
355 {
356 view()->Update( footprint() );
357 m_frame->ClearModify();
358
359 // Get rid of the save-will-update-board-only (or any other dismissable warning)
360 WX_INFOBAR* infobar = m_frame->GetInfoBar();
361
362 if( infobar->IsShownOnScreen() && infobar->HasCloseButton() )
363 infobar->Dismiss();
364
365 canvas()->ForceRefresh();
366 m_frame->SyncLibraryTree( true );
367 }
368 }
369 else
370 {
371 // Save Selected Footprint As
372 FOOTPRINT* footprint = m_frame->LoadFootprint( m_frame->GetTargetFPID() );
373
374 if( footprint && m_frame->SaveFootprintAs( footprint ) )
375 {
376 m_frame->SyncLibraryTree( true );
377 m_frame->FocusOnLibID( footprint->GetFPID() );
378 }
379 }
380
381 m_frame->RefreshLibraryTree();
382 return 0;
383}
384
385
387{
388 getEditFrame<FOOTPRINT_EDIT_FRAME>()->RevertFootprint();
389 return 0;
390}
391
392
394{
395 LIB_ID fpID = m_frame->GetLibTree()->GetSelectedLibId();
396
397 if( fpID == m_frame->GetLoadedFPID() )
398 {
399 m_copiedFootprint = std::make_unique<FOOTPRINT>( *m_frame->GetBoard()->GetFirstFootprint() );
400 m_copiedFootprint->SetParent( nullptr );
401 }
402 else
403 {
404 m_copiedFootprint.reset( m_frame->LoadFootprint( fpID ) );
405 }
406
407 if( aEvent.IsAction( &PCB_ACTIONS::cutFootprint ) )
408 DeleteFootprint( aEvent );
409
410 return 0;
411}
412
413
415{
416 if( m_copiedFootprint && !m_frame->GetLibTree()->GetSelectedLibId().GetLibNickname().empty() )
417 {
418 wxString newLib = m_frame->GetLibTree()->GetSelectedLibId().GetLibNickname();
419 wxString newName = m_copiedFootprint->GetFPID().GetLibItemName();
420
421 while( PROJECT_PCB::FootprintLibAdapter( &m_frame->Prj() )->FootprintExists( newLib, newName ) )
422 newName += _( "_copy" );
423
424 m_copiedFootprint->SetFPID( LIB_ID( newLib, newName ) );
425 m_frame->SaveFootprintInLibrary( m_copiedFootprint.get(), newLib );
426
427 m_frame->SyncLibraryTree( true );
428 m_frame->LoadFootprintFromLibrary( m_copiedFootprint->GetFPID() );
429 m_frame->FocusOnLibID( m_copiedFootprint->GetFPID() );
430 m_frame->RefreshLibraryTree();
431 }
432
433 return 0;
434}
435
436
438{
439 LIB_ID fpID = m_frame->GetLibTree()->GetSelectedLibId();
441
442 if( fpID == m_frame->GetLoadedFPID() )
443 footprint = new FOOTPRINT( *m_frame->GetBoard()->GetFirstFootprint() );
444 else
445 footprint = m_frame->LoadFootprint( m_frame->GetTargetFPID() );
446
447 if( footprint && m_frame->DuplicateFootprint( footprint ) )
448 {
449 m_frame->SyncLibraryTree( true );
450 m_frame->LoadFootprintFromLibrary( footprint->GetFPID() );
451 m_frame->FocusOnLibID( footprint->GetFPID() );
452 m_frame->RefreshLibraryTree();
453 }
454
455 return 0;
456}
457
458
460{
463
464 LIB_ID fpID = m_frame->GetLibTree()->GetSelectedLibId();
465 wxString libraryName = fpID.GetLibNickname();
466 wxString oldName = fpID.GetLibItemName();
467 wxString newName;
468 wxString msg;
469
470 if( !libTool->RenameLibrary( _( "Change Footprint Name" ), oldName,
471 [&]( const wxString& aNewName )
472 {
473 newName = aNewName;
474
475 if( newName.IsEmpty() )
476 {
477 wxMessageBox( _( "Footprint must have a name." ) );
478 return false;
479 }
480
481 // If no change, accept it without prompting
482 if( oldName != newName && adapter->FootprintExists( libraryName, newName ) )
483 {
484 msg = wxString::Format( _( "Footprint '%s' already exists in library '%s'." ),
485 newName, libraryName );
486
487 KIDIALOG errorDlg( m_frame, msg, _( "Confirmation" ),
488 wxOK | wxCANCEL | wxICON_WARNING );
489 errorDlg.SetOKLabel( _( "Overwrite" ) );
490
491 return errorDlg.ShowModal() == wxID_OK;
492 }
493
494 return true;
495 } ) )
496 {
497 return 0; // canceled by user
498 }
499
500 if( newName == oldName )
501 return 0;
502
503 FOOTPRINT* footprint = nullptr;
504
505 if( fpID == m_frame->GetLoadedFPID() )
506 {
507 footprint = m_frame->GetBoard()->GetFirstFootprint();
508
509 if( footprint )
510 {
511 footprint->SetFPID( LIB_ID( libraryName, newName ) );
512
513 if( footprint->GetValue() == oldName )
514 footprint->SetValue( newName );
515
516 m_frame->OnModify();
517 m_frame->UpdateView();
518 }
519 }
520 else
521 {
522 footprint = m_frame->LoadFootprint( fpID );
523
524 if( footprint )
525 {
526 try
527 {
528 footprint->SetFPID( LIB_ID( libraryName, newName ) );
529
530 if( footprint->GetValue() == oldName )
531 footprint->SetValue( newName );
532
533 m_frame->SaveFootprintInLibrary( footprint, libraryName );
534
535 adapter->DeleteFootprint( libraryName, oldName );
536 }
537 catch( const IO_ERROR& ioe )
538 {
539 DisplayErrorMessage( m_frame, _( "Error renaming footprint" ), ioe.What() );
540 }
541 catch( ... )
542 {
543 // Best efforts...
544 }
545 }
546 }
547
548 if( footprint )
549 m_frame->RenameFootprintTab( fpID, LIB_ID( libraryName, newName ) );
550
551 wxDataViewItem treeItem = m_frame->GetLibTreeAdapter()->FindItem( fpID );
552
553 if( footprint )
554 {
555 m_frame->UpdateLibraryTree( treeItem, footprint );
556 m_frame->FocusOnLibID( LIB_ID( libraryName, newName ) );
557 }
558
559 return 0;
560}
561
562
564{
566 const LIB_ID fpID = frame->GetTargetFPID();
567
568 if( frame->DeleteFootprintFromLibrary( fpID, true ) )
569 {
570 // Close only the deleted footprint's tab, leaving the others open.
571 frame->CloseFootprintTab( fpID );
572
573 frame->SyncLibraryTree( true );
574 }
575
576 return 0;
577}
578
579
581{
582 bool is_last_fp_from_brd = m_frame->IsCurrentFPFromBoard();
583
585
586 // A cancelled file dialog must leave the editor exactly as it was
587 if( !m_frame->ImportFootprint() )
588 return 0;
589
590 if( m_frame->GetBoard()->GetFirstFootprint() )
591 m_frame->GetBoard()->GetFirstFootprint()->ClearFlags();
592
593 frame()->ClearUndoRedoList();
594
595 // Update the save items if needed.
596 if( is_last_fp_from_brd )
597 {
598 m_frame->ReCreateMenuBar();
599 m_frame->ReCreateHToolbar();
600 }
601
602 m_toolMgr->RunAction( ACTIONS::zoomFitScreen );
603 m_frame->OnModify();
604 return 0;
605}
606
607
609{
610 if( FOOTPRINT* fp = m_frame->GetBoard()->GetFirstFootprint() )
611 m_frame->ExportFootprint( fp );
612
613 return 0;
614}
615
616
618{
619 FOOTPRINT* fp = m_frame->GetBoard()->GetFirstFootprint();
620
621 if( !fp )
622 {
623 wxMessageBox( _( "No footprint to export" ) );
624 return 0;
625 }
626
627 wxFileName fn( fp->GetFPID().GetLibItemName() );
628 fn.SetExt( FILEEXT::SVGFileExtension );
629
630 wxString pro_dir = wxPathOnly( m_frame->Prj().GetProjectFullName() );
631
632 wxString fullFileName = wxFileSelector( _( "SVG File Name" ), pro_dir, fn.GetFullName(), FILEEXT::SVGFileExtension,
633 FILEEXT::SVGFileWildcard(), wxFD_SAVE, m_frame );
634
635 if( !fullFileName.IsEmpty() )
636 {
637 PCB_PLOT_PARAMS plotOpts;
638 plotOpts.SetFormat( PLOT_FORMAT::SVG );
639 plotOpts.SetColorSettings( m_frame->GetColorSettings() );
640 plotOpts.SetScale( 1.0 );
641 plotOpts.SetAutoScale( false );
642
644
645 PlotFootprintToSVG( *fp, m_frame->Prj(), nullptr, plotOpts, layersToPlot, LSEQ(), fullFileName );
646 }
647
648 return 0;
649}
650
651
653{
654 wxCHECK( m_frame, 0 );
655
656 const wxString libNickname = m_frame->GetTargetFPID().GetUniStringLibNickname();
657
658 if( libNickname.IsEmpty() )
659 {
660 m_frame->ShowInfoBarError( _( "Select a library to compare against another." ) );
661 return 0;
662 }
663
665
666 wxCHECK( adapter, 0 );
667
668 std::optional<LIBRARY_TABLE_ROW*> row = adapter->GetRow( libNickname );
669
670 if( !row )
671 {
672 m_frame->ShowInfoBarError( wxString::Format( _( "Library '%s' is not in the footprint "
673 "library table." ),
674 libNickname ) );
675 return 0;
676 }
677
678 // MakeAbsolute so relative table URIs resolve from the project dir, not
679 // the process cwd.
680 wxFileName currentFn = wxFileName::DirName(
681 LIBRARY_MANAGER::GetFullURI( *row, /*aSubstituted=*/true ) );
682 currentFn.MakeAbsolute();
683 const wxString currentPath = currentFn.GetPath();
684
685 wxDirDialog dlg( m_frame, _( "Choose .pretty Folder to Compare With" ), wxEmptyString,
686 wxDD_DIR_MUST_EXIST );
687
688 if( dlg.ShowModal() != wxID_OK )
689 return 0;
690
691 wxFileName otherFn = wxFileName::DirName( dlg.GetPath() );
692 otherFn.MakeAbsolute();
693
694 if( otherFn.GetDirs().IsEmpty()
695 || !otherFn.GetDirs().Last().EndsWith( wxS( ".pretty" ) ) )
696 {
697 m_frame->ShowInfoBarError(
698 _( "Select a KiCad footprint library folder (ends with .pretty)." ) );
699 return 0;
700 }
701
702 if( otherFn.SameAs( currentFn ) )
703 {
704 m_frame->ShowInfoBarError(
705 _( "Select a different .pretty folder than the active library." ) );
706 return 0;
707 }
708
709 const wxString otherPath = otherFn.GetPath();
710
711 std::vector<std::unique_ptr<FOOTPRINT>> beforeStorage;
712 std::vector<std::unique_ptr<FOOTPRINT>> afterStorage;
715
716 auto load =
717 [&]( const wxString& aPath,
718 std::vector<std::unique_ptr<FOOTPRINT>>& aOwners,
720 {
721 try
722 {
723 auto loaded = KICAD_DIFF::FP_LIB_DIFFER::LoadLibrary( aPath );
724 aOwners = std::move( loaded.first );
725 aMap = std::move( loaded.second );
726 return true;
727 }
728 catch( const IO_ERROR& ioe )
729 {
730 m_frame->ShowInfoBarError(
731 wxString::Format( _( "Failed to load %s: %s" ), aPath, ioe.What() ) );
732 }
733 catch( const std::exception& e )
734 {
735 m_frame->ShowInfoBarError(
736 wxString::Format( _( "Failed to load %s: %s" ), aPath,
737 wxString::FromUTF8( e.what() ) ) );
738 }
739
740 return false;
741 };
742
743 if( !load( currentPath, beforeStorage, beforeMap ) )
744 return 0;
745
746 if( !load( otherPath, afterStorage, afterMap ) )
747 return 0;
748
749 KICAD_DIFF::FP_LIB_DIFFER differ( beforeMap, afterMap, otherPath );
751
752 DIALOG_KICAD_DIFF dlgDiff( m_frame, currentPath, otherPath, result );
753 dlgDiff.ShowModal();
754
755 return 0;
756}
757
758
760{
761 // No check for multi selection since the context menu option must be hidden in that case
762 LIB_ID libId = m_frame->GetTargetFPID();
763
764 wxString libName = libId.GetLibNickname();
765 wxString libItemName = libId.GetLibItemName();
766 wxString path = wxEmptyString;
767
769 std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, libName, true );
770
771 if( !optUri )
772 return 0;
773
774 path = *optUri;
775
776 wxString fileExt = wxEmptyString;
777
778 // If selection is footprint
779 if( !libItemName.IsEmpty() )
781
782 wxFileName fileName( path, libItemName, fileExt );
783 wxString explorerCommand;
784
785 if( COMMON_SETTINGS* cfg = Pgm().GetCommonSettings() )
786 explorerCommand = cfg->m_System.file_explorer;
787
788 if( explorerCommand.IsEmpty() )
789 {
790 path = fileName.GetFullPath().BeforeLast( wxFileName::GetPathSeparator() );
791
792 if( !path.IsEmpty() && wxDirExists( path ) )
794
795 return 0;
796 }
797
798 if( !explorerCommand.EndsWith( "%F" ) )
799 {
800 wxMessageBox( _( "Missing/malformed file explorer argument '%F' in common settings." ) );
801 return 0;
802 }
803
804 wxString escapedFilePath = fileName.GetFullPath();
805 escapedFilePath.Replace( wxS( "\"" ), wxS( "_" ) );
806
807 wxString fileArg = wxEmptyString;
808 fileArg << '"' << escapedFilePath << '"';
809
810 explorerCommand.Replace( wxT( "%F" ), fileArg );
811
812 if( !explorerCommand.IsEmpty() )
813 wxExecute( explorerCommand );
814
815 return 0;
816}
817
818
820{
821 wxString fullEditorName = Pgm().GetTextEditor();
822
823 if( fullEditorName.IsEmpty() )
824 {
825 wxMessageBox( _( "No text editor selected in KiCad. Please choose one." ) );
826 return 0;
827 }
828
829 // No check for multi selection since the context menu option must be hidden in that case
830 LIB_ID libId = m_frame->GetLibTree()->GetSelectedLibId();
831
833
834 wxString libName = libId.GetLibNickname();
835 wxString libItemName = wxEmptyString;
836
837 std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, libName, true );
838
839 if( !optUri )
840 return 0;
841
842 libItemName = *optUri;
843 libItemName << wxFileName::GetPathSeparator();
844 libItemName << libId.GetLibItemName();
845 libItemName << '.' + FILEEXT::KiCadFootprintFileExtension;
846
847 if( !wxFileName::FileExists( libItemName ) )
848 return 0;
849
850 ExecuteFile( fullEditorName, libItemName.wc_str(), nullptr, false );
851
852 return 0;
853}
854
855
857{
858 if( FOOTPRINT* footprint = m_frame->GetBoard()->GetFirstFootprint() )
859 {
860 std::optional<wxString> url = GetFootprintDocumentationURL( *footprint );
861
862 if( !url.has_value() )
863 {
864 frame()->ShowInfoBarMsg( _( "No datasheet found in the footprint." ) );
865 }
866 else
867 {
868 // Only absolute URLs are supported
869 SEARCH_STACK* searchStack = nullptr;
870 GetAssociatedDocument( m_frame, *url, &m_frame->Prj(), searchStack,
871 { m_frame->GetBoard(), footprint } );
872 }
873 }
874 return 0;
875}
876
877
879{
880 m_frame->LoadFootprintFromLibrary( m_frame->GetLibTree()->GetSelectedLibId() );
881 return 0;
882}
883
884
886{
887 FOOTPRINT* footprint = m_frame->GetBoard()->GetFirstFootprint();
888
889 if( !footprint || !m_frame->IsCurrentFPFromBoard() )
890 {
891 wxBell();
892 return 0;
893 }
894
895 m_frame->LoadFootprintFromLibrary( footprint->GetFPID() );
896
897 if( !m_frame->IsLibraryTreeShown() )
898 m_frame->ToggleLibraryTree();
899
900 return 0;
901}
902
903
905{
906 m_frame->ToggleLayersManager();
907 return 0;
908}
909
910
912{
913 m_frame->ToggleProperties();
914 return 0;
915}
916
917
919{
920 // Check if called from tree context menu
922 {
923 LIB_ID treeLibId = m_frame->GetLibTree()->GetSelectedLibId();
924
925 // Check if a different footprint is selected in the tree
926 if( treeLibId.IsValid()
927 && ( !m_frame->GetBoard()->GetFirstFootprint()
928 || m_frame->GetBoard()->GetFirstFootprint()->GetFPID() != treeLibId ) )
929 {
930 // Edit properties directly from library without loading to canvas
932 return 0;
933 }
934 }
935
936 if( FOOTPRINT* footprint = m_frame->GetBoard()->GetFirstFootprint() )
937 {
938 getEditFrame<FOOTPRINT_EDIT_FRAME>()->OnEditItemRequest( footprint );
939 m_frame->GetCanvas()->Refresh();
940 }
941
942 return 0;
943}
944
945
947{
948 // Load the footprint from the library (without adding it to the canvas)
949 FOOTPRINT* libraryFootprint = m_frame->LoadFootprint( aLibId );
950
951 if( !libraryFootprint )
952 return;
953
954 // Create a temporary board to hold the footprint (required by the dialog)
955 std::unique_ptr<BOARD> tempBoard( new BOARD() );
956
957 // Set up the temp board with the current project and board settings.
958 // Use reference-only mode to avoid modifying the project's settings.
959 tempBoard->SetDesignSettings( m_frame->GetBoard()->GetDesignSettings() );
960 tempBoard->SetProject( &m_frame->Prj(), true );
961 tempBoard->SetBoardUse( BOARD_USE::FPHOLDER );
962 tempBoard->SynchronizeProperties();
963
964 // Create a copy to work with and add it to the temporary board
965 FOOTPRINT* tempFootprint = static_cast<FOOTPRINT*>( libraryFootprint->Clone() );
966 delete libraryFootprint;
967
968 tempBoard->Add( tempFootprint );
969 tempFootprint->SetParent( tempBoard.get() );
970
971 LIB_ID oldFPID = tempFootprint->GetFPID();
972
973 // Open the properties dialog
974 DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR dialog( m_frame, tempFootprint );
975
976 if( dialog.ShowQuasiModal() != wxID_OK )
977 return;
978
979 // Remove from temporary board before saving (to avoid double-delete)
980 tempBoard->Remove( tempFootprint );
981
982 // Save the modified footprint back to the library
984 wxString libName = aLibId.GetLibNickname();
985
986 try
987 {
988 adapter->SaveFootprint( libName, tempFootprint, true );
989
990 // Update the tree view
991 wxDataViewItem treeItem = m_frame->GetLibTreeAdapter()->FindItem( oldFPID );
992 m_frame->UpdateLibraryTree( treeItem, tempFootprint );
993 m_frame->SyncLibraryTree( true );
994
995 // Clean up
996 delete tempFootprint;
997 }
998 catch( const IO_ERROR& ioe )
999 {
1000 delete tempFootprint;
1001 DisplayError( m_frame, ioe.What() );
1002 }
1003}
1004
1005
1007{
1008 getEditFrame<FOOTPRINT_EDIT_FRAME>()->ShowPadPropertiesDialog( nullptr );
1009 return 0;
1010}
1011
1012
1014{
1016 DIALOG_CLEANUP_GRAPHICS dlg( editFrame, true );
1017
1018 dlg.ShowModal();
1019 return 0;
1020}
1021
1022
1024{
1025 if( !m_checkerDialog )
1026 {
1028 m_checkerDialog->Show( true );
1029 }
1030 else // The dialog is just not visible (because the user has double clicked on an error item)
1031 {
1032 m_checkerDialog->Show( true );
1033 }
1034
1035 return 0;
1036}
1037
1038
1040{
1041 if( !m_checkerDialog )
1043
1044 if( !m_checkerDialog->IsShownOnScreen() )
1045 m_checkerDialog->Show( true );
1046
1047 m_checkerDialog->SelectMarker( aMarker );
1048}
1049
1050
1052{
1053 if( m_checkerDialog )
1054 {
1055 m_checkerDialog->Destroy();
1056 m_checkerDialog = nullptr;
1057 }
1058}
1059
1060
1062{
1063 FOOTPRINT* footprint = board()->Footprints().front();
1064 int errors = 0;
1065 wxString details;
1066
1067 // Repair duplicate IDs and missing nets.
1068 std::set<KIID> ids;
1069 int duplicates = 0;
1070
1071 auto processItem =
1072 [&]( EDA_ITEM* aItem )
1073 {
1074 if( ids.count( aItem->m_Uuid ) )
1075 {
1076 duplicates++;
1077 if( BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( aItem ) )
1078 boardItem->ResetUuid();
1079 }
1080
1081 ids.insert( aItem->m_Uuid );
1082 };
1083
1084 // Footprint IDs are the most important, so give them the first crack at "claiming" a
1085 // particular KIID.
1086
1087 processItem( footprint );
1088
1089 // After that the principal use is for DRC marker pointers, which are most likely to pads.
1090
1091 for( PAD* pad : footprint->Pads() )
1092 processItem( pad );
1093
1094 // From here out I don't think order matters much.
1095
1096 processItem( &footprint->Reference() );
1097 processItem( &footprint->Value() );
1098
1099 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1100 processItem( item );
1101
1102 for( ZONE* zone : footprint->Zones() )
1103 processItem( zone );
1104
1105 for( PCB_GROUP* group : footprint->Groups() )
1106 processItem( group );
1107
1108 if( duplicates )
1109 {
1110 errors += duplicates;
1111 details += wxString::Format( _( "%d duplicate IDs replaced.\n" ), duplicates );
1112 }
1113
1114 if( errors )
1115 {
1116 m_frame->OnModify();
1117
1118 wxString msg = wxString::Format( _( "%d potential problems repaired." ), errors );
1119 DisplayInfoMessage( m_frame, msg, details );
1120 }
1121 else
1122 {
1123 DisplayInfoMessage( m_frame, _( "No footprint problems found." ) );
1124 }
1125
1126 return 0;
1127}
1128
1129
1130// The appearance panel also claims Ctrl+Tab for layer-preset cycling, so it wins when focused.
1132{
1133 wxWindow* appearance = aFrame->GetAppearancePanel();
1134
1135 if( !appearance )
1136 return false;
1137
1138 for( wxWindow* focus = wxWindow::FindFocus(); focus; focus = focus->GetParent() )
1139 {
1140 if( focus == appearance )
1141 return true;
1142 }
1143
1144 return false;
1145}
1146
1147
1149{
1151 return 0;
1152
1153 m_frame->AdvanceFootprintTab( true );
1154 return 0;
1155}
1156
1157
1159{
1161 return 0;
1162
1163 m_frame->AdvanceFootprintTab( false );
1164 return 0;
1165}
1166
1167
1169{
1170 m_frame->CloseActiveFootprintTab();
1171 return 0;
1172}
1173
1174
1176{
1177 if( m_frame->GetTargetFPID().GetLibNickname().empty() )
1178 return 0;
1179
1180 if( m_frame->HasModifiedFootprintTabs() )
1181 {
1182 DisplayInfoMessage( m_frame, _( "Save or discard the changes in all modified footprint tabs before opening "
1183 "the Footprint Fields Table." ) );
1184 return 0;
1185 }
1186
1188
1189 dlg.ShowModal();
1190 return 0;
1191}
1192
1193
1195{
1196 // clang-format off
1205
1211
1219
1223
1226
1229
1233
1238 // clang-format on
1239
1240 // Line modes for the footprint editor: explicit modes, next-mode, and toolbar sync
1246}
1247
1249{
1250 LEADER_MODE mode = aEvent.Parameter<LEADER_MODE>();
1251 GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" )->m_AngleSnapMode = mode;
1252 m_toolMgr->PostAction( ACTIONS::refreshPreview );
1254 return 0;
1255}
1256
1258{
1260
1261 if( !f )
1262 return 0;
1263
1264 LEADER_MODE mode = GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" )->m_AngleSnapMode;
1265
1266 switch( mode )
1267 {
1270 default:
1272 }
1273
1274 return 0;
1275}
@ FPHOLDER
Definition board.h:401
static TOOL_ACTION openWithTextEditor
Definition actions.h:64
static TOOL_ACTION revert
Definition actions.h:58
static TOOL_ACTION saveAs
Definition actions.h:55
static TOOL_ACTION openDirectory
Definition actions.h:65
static TOOL_ACTION showDatasheet
Definition actions.h:263
static TOOL_ACTION save
Definition actions.h:54
static TOOL_ACTION zoomFitScreen
Definition actions.h:138
static TOOL_ACTION showProperties
Definition actions.h:262
static TOOL_ACTION refreshPreview
Definition actions.h:155
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
void BuildListOfNets()
Definition board.h:1170
const FOOTPRINTS & Footprints() const
Definition board.h:463
File-compare dialog (Phase 7).
int ShowModal() override
void SelectToolbarAction(const TOOL_ACTION &aAction) override
Select the given action in the toolbar group which contains it, if any.
KIGFX::VIEW_CONTROLS * GetViewControls() const
Return a pointer to the #VIEW_CONTROLS instance used in the panel.
void ForceRefresh()
Force a redraw.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:160
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:153
int Revert(const TOOL_EVENT &aEvent)
int OpenWithTextEditor(const TOOL_EVENT &aEvent)
int PasteFootprint(const TOOL_EVENT &aEvent)
DIALOG_FOOTPRINT_CHECKER * m_checkerDialog
int CutCopyFootprint(const TOOL_EVENT &aEvent)
int EditFootprint(const TOOL_EVENT &aEvent)
int CloseTab(const TOOL_EVENT &aEvent)
int ToggleProperties(const TOOL_EVENT &aEvent)
int Save(const TOOL_EVENT &aEvent)
int OpenDirectory(const TOOL_EVENT &aEvent)
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
int CreateFootprint(const TOOL_EVENT &aEvent)
int NextTab(const TOOL_EVENT &aEvent)
int ExportFootprintAsSVG(const TOOL_EVENT &aEvent)
int ShowLibraryFieldsTable(const TOOL_EVENT &aEvent)
int NewFootprint(const TOOL_EVENT &aEvent)
int CompareLibraryWithFile(const TOOL_EVENT &aEvent)
Diff the currently-selected footprint library against another .pretty directory.
int DefaultPadProperties(const TOOL_EVENT &aEvent)
Edit the properties used for new pad creation.
void CrossProbe(const PCB_MARKER *aMarker)
int ChangeLineMode(const TOOL_EVENT &aEvent)
int ImportFootprint(const TOOL_EVENT &aEvent)
int CleanupGraphics(const TOOL_EVENT &aEvent)
int ShowDatasheet(const TOOL_EVENT &aEvent)
void tryToSaveFootprintInLibrary(FOOTPRINT &aFootprint, const LIB_ID &aLibId)
Try to save the footprint in the library, if it is valid and writable.
int PrevTab(const TOOL_EVENT &aEvent)
int Properties(const TOOL_EVENT &aEvent)
int ToggleLayersManager(const TOOL_EVENT &aEvent)
int RepairFootprint(const TOOL_EVENT &aEvent)
int RenameFootprint(const TOOL_EVENT &aEvent)
int DuplicateFootprint(const TOOL_EVENT &aEvent)
std::unique_ptr< FOOTPRINT > m_copiedFootprint
bool Init() override
Init() is called once upon a registration of the tool.
int OnAngleSnapModeChanged(const TOOL_EVENT &aEvent)
int ExportFootprint(const TOOL_EVENT &aEvent)
int EditLibraryFootprint(const TOOL_EVENT &aEvent)
void editFootprintPropertiesFromLibrary(const LIB_ID &aLibId)
int DeleteFootprint(const TOOL_EVENT &aEvent)
int SaveAs(const TOOL_EVENT &aEvent)
void setTransitions() override
< Set up handlers for various events.
int CheckFootprint(const TOOL_EVENT &aEvent)
An interface to the global shared library manager that is schematic-specific and linked to one projec...
SAVE_T SaveFootprint(const wxString &aNickname, const FOOTPRINT *aFootprint, bool aOverwrite=true)
Write aFootprint to an existing library given by aNickname.
FOOTPRINT * GetBuiltFootprint()
Return a duplicate of the generated footprint. The caller takes ownership.
void SetPosition(const VECTOR2I &aPos) override
void SetFPID(const LIB_ID &aFPID)
Definition footprint.h:474
EDA_ITEM * Clone() const override
Invoke a function on all children.
const LIB_ID & GetFPID() const
Definition footprint.h:473
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()
Diff two .pretty footprint library directories.
static std::pair< std::vector< std::unique_ptr< FOOTPRINT > >, FOOTPRINT_MAP > LoadLibrary(const wxString &aPrettyPath)
Load a .pretty directory into a FOOTPRINT_MAP.
DOCUMENT_DIFF Diff() override
Produce a DOCUMENT_DIFF of the inputs the concrete differ was constructed with.
std::map< wxString, const FOOTPRINT * > FOOTPRINT_MAP
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:38
int ShowModal() override
Definition kidialog.cpp:89
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition pcb_view.cpp:87
virtual void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Move the graphic crosshair cursor to the requested position expressed in world coordinates.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
virtual bool ShowModal(wxString *aResult=nullptr, wxWindow *aResultantFocusWindow=nullptr)
Show this wxFrame as if it were a modal dialog, with all other instantiated wxFrames disabled until t...
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
Module editor specific tools.
bool RenameLibrary(const wxString &aTitle, const wxString &aName, std::function< bool(const wxString &aNewName)> aValidator)
void AddContextMenuItems(CONDITIONAL_MENU *aMenu)
std::optional< LIBRARY_TABLE_ROW * > GetRow(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::GetRow but filtered to the LIBRARY_TABLE_TYPE of this adapter.
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false)
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
bool IsValid() const
Check if this LID_ID is valid.
Definition lib_id.h:168
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:113
const wxString GetUniStringLibNickname() const
Definition lib_id.h:84
const UTF8 & GetLibItemName() const
Definition lib_id.h:98
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition lib_id.h:83
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition lseq.h:47
LSEQ SeqStackupForPlotting() const
Return the sequence that is typical for a bottom-to-top stack-up.
Definition lset.cpp:400
static const LSET & AllLayersMask()
Definition lset.cpp:637
Definition pad.h:61
static TOOL_ACTION lineModeFree
Unconstrained angle mode (icon lines_any)
static TOOL_ACTION deleteFootprint
static TOOL_ACTION renameFootprint
static TOOL_ACTION showLayersManager
static TOOL_ACTION createFootprint
static TOOL_ACTION editFootprint
static TOOL_ACTION exportFootprint
static TOOL_ACTION editTextAndGraphics
static TOOL_ACTION lineMode45
45-degree-or-orthogonal mode (icon hv45mode)
static TOOL_ACTION angleSnapModeChanged
Notification event when angle mode changes.
static TOOL_ACTION newFootprint
static TOOL_ACTION defaultPadProperties
static TOOL_ACTION prevFootprintTab
static TOOL_ACTION importFootprint
static TOOL_ACTION pasteFootprint
static TOOL_ACTION footprintProperties
static TOOL_ACTION lineMode90
90-degree-only mode (icon lines90)
static TOOL_ACTION closeFootprintTab
static TOOL_ACTION nextFootprintTab
static TOOL_ACTION showLibFootprintFieldsTable
static TOOL_ACTION checkFootprint
static TOOL_ACTION editLibFpInFpEditor
static TOOL_ACTION duplicateFootprint
static TOOL_ACTION cutFootprint
static TOOL_ACTION repairFootprint
static TOOL_ACTION exportFootprintAsSVG
static TOOL_ACTION compareFpLibraryWithFile
static TOOL_ACTION copyFootprint
static TOOL_ACTION cleanupGraphics
APPEARANCE_CONTROLS * GetAppearancePanel()
A set of BOARD_ITEMs (i.e., without duplicates).
Definition pcb_group.h:51
Parameters and options when plotting/printing a board.
void SetAutoScale(bool aFlag)
void SetScale(double aVal)
void SetColorSettings(COLOR_SETTINGS *aSettings)
void SetFormat(PLOT_FORMAT aFormat)
T * frame() const
KIGFX::PCB_VIEW * view() const
PCB_TOOL_BASE(TOOL_ID aId, const std::string &aName)
Constructor.
BOARD * board() const
PCB_DRAW_PANEL_GAL * canvas() const
FOOTPRINT * footprint() const
virtual const wxString & GetTextEditor(bool aCanShowFileChooser=true)
Return the path to the preferred text editor application.
Definition pgm_base.cpp:216
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:125
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
Look for files in a number of paths.
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition tool_base.h:182
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition tool_base.cpp:40
TOOL_MANAGER * m_toolMgr
Definition tool_base.h:220
RESET_REASON
Determine the reason of reset for a tool.
Definition tool_base.h:74
Generic, UI-independent tool event.
Definition tool_event.h:167
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:469
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
std::unique_ptr< TOOL_MENU > m_menu
The functions below are not yet implemented - their interface may change.
bool empty() const
Definition utf8.h:105
A modified version of the wxInfoBar class that allows us to:
Definition wx_infobar.h:76
bool HasCloseButton() const
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Handle a list of polygons defining a copper zone.
Definition zone.h:70
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:245
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
#define _(s)
bool GetAssociatedDocument(wxWindow *aParent, const wxString &aDocName, PROJECT *aProject, SEARCH_STACK *aPaths, std::vector< EMBEDDED_FILES * > aFilesStack)
Open a document (file) with the suitable browser.
Definition eda_doc.cpp:59
This file is part of the common library.
static bool appearancePanelHasFocus(FOOTPRINT_EDIT_FRAME *aFrame)
@ FRAME_FOOTPRINT_WIZARD
Definition frame_type.h:42
std::optional< wxString > GetFootprintDocumentationURL(const FOOTPRINT &aFootprint)
Get a URL to the documentation for a LIB_ID in a #FP_LIB_TABLE.
LEADER_MODE
The kind of the leader line.
@ DEG45
45 Degree only
@ DIRECT
Unconstrained point-to-point.
@ DEG90
90 Degree only
int ExecuteFile(const wxString &aEditorName, const wxString &aFileName, wxProcess *aCallback, bool aFileForKicad)
Call the executable file aEditorName with the parameter aFileName.
Definition gestfich.cpp:161
static const std::string SVGFileExtension
static const std::string KiCadFootprintFileExtension
static wxString SVGFileWildcard()
bool LaunchExternal(const wxString &aPath)
Launches the given file or folder in the host OS.
Class to handle a set of BOARD_ITEMs.
bool PlotFootprintToSVG(const FOOTPRINT &aFootprint, PROJECT &aProject, const std::map< wxString, wxString > *aVarOverrides, PCB_PLOT_PARAMS &aPlotOpts, const LSEQ &aLayersToPlot, const LSEQ &aLayersOnAll, const wxString &aFileName, REPORTER *aReporter)
Plot a footprint to an SVG file, with the footprint origin at the SVG origin and the page/viewBox siz...
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
T * GetAppSettings(const char *aFilename)
The full set of changes between two parsed documents of one type.
std::string path
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682
Definition of file extensions used in Kicad.