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, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
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/filename.h>
43#include <launch_ext.h> // To default when file manager setting is empty
44#include <gestfich.h> // To open with a text editor
45#include <widgets/wx_infobar.h>
46#include <footprint.h>
47#include <pad.h>
48#include <pcb_group.h>
49#include <zone.h>
54#include <kiway.h>
55#include <project_pcb.h>
56#include <view/view_controls.h>
57
58#include <memory>
59
61
62
64 PCB_TOOL_BASE( "pcbnew.ModuleEditor" ),
65 m_frame( nullptr ),
66 m_checkerDialog( nullptr )
67{
68}
69
70
78
79
81{
82 LIBRARY_EDITOR_CONTROL* libraryTreeTool = m_toolMgr->GetTool<LIBRARY_EDITOR_CONTROL>();
83
84 // Build a context menu for the footprint tree
85 //
86 CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
87
88 auto libSelectedCondition =
89 [this]( const SELECTION& aSel )
90 {
91 LIB_ID sel = m_frame->GetLibTree()->GetSelectedLibId();
92 return !sel.GetLibNickname().empty() && sel.GetLibItemName().empty();
93 };
94
95 // The libInferredCondition allows you to do things like New Symbol and Paste with a
96 // symbol selected (in other words, when we know the library context even if the library
97 // itself isn't selected.
98 auto libInferredCondition =
99 [this]( const SELECTION& aSel )
100 {
101 LIB_ID sel = m_frame->GetLibTree()->GetSelectedLibId();
102 return !sel.GetLibNickname().empty();
103 };
104
105 auto fpSelectedCondition =
106 [this]( const SELECTION& aSel )
107 {
108 LIB_ID sel = m_frame->GetLibTree()->GetSelectedLibId();
109 return !sel.GetLibNickname().empty() && !sel.GetLibItemName().empty();
110 };
111
112 auto fpExportCondition =
113 [this]( const SELECTION& aSel )
114 {
115 FOOTPRINT* fp = m_frame->GetBoard()->GetFirstFootprint();
116 return fp != nullptr;
117 };
118
119 auto canOpenExternally =
120 [this]( const SELECTION& aSel )
121 {
122 // The option is shown if the editor has no current edits,
123 // dumb/simple guard against opening a new file that does not exist on disk
124 bool ret = !m_frame->IsContentModified();
125 return ret;
126 };
127
128// clang-format off
129 ctxMenu.AddItem( PCB_ACTIONS::newFootprint, libSelectedCondition, 10 );
130 ctxMenu.AddItem( PCB_ACTIONS::createFootprint, libSelectedCondition, 10 );
131
132 ctxMenu.AddSeparator( 10 );
133 ctxMenu.AddItem( ACTIONS::save, SELECTION_CONDITIONS::ShowAlways, 10 );
134 ctxMenu.AddItem( ACTIONS::saveAs, libSelectedCondition || fpSelectedCondition, 10 );
135 ctxMenu.AddItem( ACTIONS::revert, libSelectedCondition || libInferredCondition, 10 );
136
137 ctxMenu.AddSeparator( 10 );
138 ctxMenu.AddItem( PCB_ACTIONS::cutFootprint, fpSelectedCondition, 10 );
139 ctxMenu.AddItem( PCB_ACTIONS::copyFootprint, fpSelectedCondition, 10 );
140 ctxMenu.AddItem( PCB_ACTIONS::pasteFootprint, libInferredCondition, 10 );
141 ctxMenu.AddItem( PCB_ACTIONS::duplicateFootprint, fpSelectedCondition, 10 );
142 ctxMenu.AddItem( PCB_ACTIONS::renameFootprint, fpSelectedCondition, 10 );
143 ctxMenu.AddItem( PCB_ACTIONS::deleteFootprint, fpSelectedCondition, 10 );
144
145 ctxMenu.AddSeparator( 100 );
146 ctxMenu.AddItem( PCB_ACTIONS::importFootprint, libInferredCondition, 100 );
147 ctxMenu.AddItem( PCB_ACTIONS::exportFootprint, fpExportCondition, 100 );
148
149 if( ADVANCED_CFG::GetCfg().m_EnableLibWithText )
150 {
151 ctxMenu.AddSeparator( 200 );
152 ctxMenu.AddItem( ACTIONS::openWithTextEditor, canOpenExternally && fpSelectedCondition, 200 );
153 }
154
155 if( ADVANCED_CFG::GetCfg().m_EnableLibDir )
156 {
157 ctxMenu.AddSeparator( 200 );
158 ctxMenu.AddItem( ACTIONS::openDirectory, canOpenExternally && ( libSelectedCondition || fpSelectedCondition ), 200 );
159 }
160// clang-format on
161
162 libraryTreeTool->AddContextMenuItems( &ctxMenu );
163
164 // Ensure the left toolbar's Line modes group reflects the current setting at startup
165 if( m_toolMgr )
167
168 return true;
169}
170
171
173 const LIB_ID& aTargetLib )
174{
175 const wxString libraryName = aTargetLib.GetUniStringLibNickname();
176
177 if( aTargetLib.GetLibNickname().empty() )
178 {
179 // Do nothing - the footprint will need to be saved manually to assign
180 // to a library.
181 }
182 else
183 {
184 if( !PROJECT_PCB::FootprintLibAdapter( &m_frame->Prj() )->IsFootprintLibWritable( libraryName ) )
185 {
186 // If the library is not writeable, we'll give the user a
187 // footprint not in a library. But add a warning to let them know
188 // they didn't quite get what they wanted.
189 m_frame->ShowInfoBarWarning(
190 wxString::Format(
191 _( "The footprint could not be added to the selected library ('%s'). "
192 "This library is read-only." ),
193 libraryName ),
194 false );
195 // And the footprint will need to be saved manually
196 }
197 else
198 {
199 // Go ahead and save it to the library
200 LIB_ID fpid = aFootprint.GetFPID();
201 fpid.SetLibNickname( aTargetLib.GetLibNickname() );
202 aFootprint.SetFPID( fpid );
203 m_frame->SaveFootprint( &aFootprint );
204 m_frame->ClearModify();
205 }
206 }
207}
208
209
211{
212 const LIB_ID selected = m_frame->GetTargetFPID();
213 const wxString libraryName = selected.GetUniStringLibNickname();
214 FOOTPRINT* newFootprint = m_frame->CreateNewFootprint( wxEmptyString, libraryName );
215
216 if( !newFootprint )
217 return 0;
218
219 if( !m_frame->Clear_Pcb( true ) )
220 return 0;
221
223 m_frame->AddFootprintToBoard( newFootprint );
224
225 // Initialize data relative to nets and netclasses (for a new footprint the defaults are
226 // used). This is mandatory to handle and draw pads.
228 newFootprint->SetPosition( VECTOR2I( 0, 0 ) );
229 newFootprint->ClearFlags();
230
231 m_frame->Zoom_Automatique( false );
232 m_frame->GetScreen()->SetContentModified();
233
234 tryToSaveFootprintInLibrary( *newFootprint, selected );
235
236 m_frame->UpdateView();
237 m_frame->GetCanvas()->ForceRefresh();
238 m_frame->Update3DView( true, true );
239
240 m_frame->SyncLibraryTree( false );
241 return 0;
242}
243
244
246{
247 LIB_ID selected = m_frame->GetLibTree()->GetSelectedLibId();
248 wxString libraryName = selected.GetUniStringLibNickname();
249
250 if( m_frame->IsContentModified() )
251 {
252 if( !HandleUnsavedChanges( m_frame, _( "The current footprint has been modified. "
253 "Save changes?" ),
254 [&]() -> bool
255 {
256 return m_frame->SaveFootprint( footprint() );
257 } ) )
258 {
259 return 0;
260 }
261 }
262
263 if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_FOOTPRINT_WIZARD, true, m_frame ) )
264 {
265 FOOTPRINT_WIZARD_FRAME* wizard = static_cast<FOOTPRINT_WIZARD_FRAME*>( frame );
266
267 if( wizard->ShowModal( nullptr, m_frame ) )
268 {
269 // Creates the new footprint from python script wizard
270 FOOTPRINT* newFootprint = wizard->GetBuiltFootprint();
271
272 if( newFootprint ) // i.e. if create footprint command is OK
273 {
274 m_frame->Clear_Pcb( false );
275
277 // Add the new object to board
278 m_frame->AddFootprintToBoard( newFootprint );
279
280 // Initialize data relative to nets and netclasses (for a new footprint the
281 // defaults are used). This is mandatory to handle and draw pads.
283 newFootprint->SetPosition( VECTOR2I( 0, 0 ) );
284 newFootprint->ClearFlags();
285
286 m_frame->Zoom_Automatique( false );
287 m_frame->GetScreen()->SetContentModified();
288 m_frame->OnModify();
289
290 tryToSaveFootprintInLibrary( *newFootprint, selected );
291
292 m_frame->UpdateView();
293 canvas()->Refresh();
294 m_frame->Update3DView( true, true );
295
296 m_frame->SyncLibraryTree( false );
297 }
298 }
299
300 wizard->Destroy();
301 }
302
303 return 0;
304}
305
306
308{
309 if( !footprint() ) // no loaded footprint
310 return 0;
311
312 if( m_frame->GetTargetFPID() == m_frame->GetLoadedFPID() )
313 {
314 if( m_frame->SaveFootprint( footprint() ) )
315 {
316 view()->Update( footprint() );
317
318 canvas()->ForceRefresh();
319 m_frame->ClearModify();
320 m_frame->UpdateTitle();
321 }
322 }
323
324 m_frame->RefreshLibraryTree();
325 return 0;
326}
327
328
330{
331 if( m_frame->GetTargetFPID().GetLibItemName().empty() )
332 {
334
335 // Save Library As
336 const wxString& src_libNickname = m_frame->GetTargetFPID().GetLibNickname();
337 std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, src_libNickname, true );
338 wxCHECK( optUri, 0 );
339
340 if( m_frame->SaveLibraryAs( *optUri ) )
341 m_frame->SyncLibraryTree( true );
342 }
343 else if( m_frame->GetTargetFPID() == m_frame->GetLoadedFPID() )
344 {
345 // Save Footprint As
346 if( footprint() && m_frame->SaveFootprintAs( footprint() ) )
347 {
348 view()->Update( footprint() );
349 m_frame->ClearModify();
350
351 // Get rid of the save-will-update-board-only (or any other dismissable warning)
352 WX_INFOBAR* infobar = m_frame->GetInfoBar();
353
354 if( infobar->IsShownOnScreen() && infobar->HasCloseButton() )
355 infobar->Dismiss();
356
357 canvas()->ForceRefresh();
358 m_frame->SyncLibraryTree( true );
359 }
360 }
361 else
362 {
363 // Save Selected Footprint As
364 FOOTPRINT* footprint = m_frame->LoadFootprint( m_frame->GetTargetFPID() );
365
366 if( footprint && m_frame->SaveFootprintAs( footprint ) )
367 {
368 m_frame->SyncLibraryTree( true );
369 m_frame->FocusOnLibID( footprint->GetFPID() );
370 }
371 }
372
373 m_frame->RefreshLibraryTree();
374 return 0;
375}
376
377
379{
380 getEditFrame<FOOTPRINT_EDIT_FRAME>()->RevertFootprint();
381 return 0;
382}
383
384
386{
387 LIB_ID fpID = m_frame->GetLibTree()->GetSelectedLibId();
388
389 if( fpID == m_frame->GetLoadedFPID() )
390 {
391 m_copiedFootprint = std::make_unique<FOOTPRINT>( *m_frame->GetBoard()->GetFirstFootprint() );
392 m_copiedFootprint->SetParent( nullptr );
393 }
394 else
395 {
396 m_copiedFootprint.reset( m_frame->LoadFootprint( fpID ) );
397 }
398
399 if( aEvent.IsAction( &PCB_ACTIONS::cutFootprint ) )
400 DeleteFootprint( aEvent );
401
402 return 0;
403}
404
405
407{
408 if( m_copiedFootprint && !m_frame->GetLibTree()->GetSelectedLibId().GetLibNickname().empty() )
409 {
410 wxString newLib = m_frame->GetLibTree()->GetSelectedLibId().GetLibNickname();
411 wxString newName = m_copiedFootprint->GetFPID().GetLibItemName();
412
413 while( PROJECT_PCB::FootprintLibAdapter( &m_frame->Prj() )->FootprintExists( newLib, newName ) )
414 newName += _( "_copy" );
415
416 m_copiedFootprint->SetFPID( LIB_ID( newLib, newName ) );
417 m_frame->SaveFootprintInLibrary( m_copiedFootprint.get(), newLib );
418
419 m_frame->SyncLibraryTree( true );
420 m_frame->LoadFootprintFromLibrary( m_copiedFootprint->GetFPID() );
421 m_frame->FocusOnLibID( m_copiedFootprint->GetFPID() );
422 m_frame->RefreshLibraryTree();
423 }
424
425 return 0;
426}
427
428
430{
431 LIB_ID fpID = m_frame->GetLibTree()->GetSelectedLibId();
433
434 if( fpID == m_frame->GetLoadedFPID() )
435 footprint = new FOOTPRINT( *m_frame->GetBoard()->GetFirstFootprint() );
436 else
437 footprint = m_frame->LoadFootprint( m_frame->GetTargetFPID() );
438
439 if( footprint && m_frame->DuplicateFootprint( footprint ) )
440 {
441 m_frame->SyncLibraryTree( true );
442 m_frame->LoadFootprintFromLibrary( footprint->GetFPID() );
443 m_frame->FocusOnLibID( footprint->GetFPID() );
444 m_frame->RefreshLibraryTree();
445 }
446
447 return 0;
448}
449
450
452{
455
456 LIB_ID fpID = m_frame->GetLibTree()->GetSelectedLibId();
457 wxString libraryName = fpID.GetLibNickname();
458 wxString oldName = fpID.GetLibItemName();
459 wxString newName;
460 wxString msg;
461
462 if( !libTool->RenameLibrary( _( "Change Footprint Name" ), oldName,
463 [&]( const wxString& aNewName )
464 {
465 newName = aNewName;
466
467 if( newName.IsEmpty() )
468 {
469 wxMessageBox( _( "Footprint must have a name." ) );
470 return false;
471 }
472
473 // If no change, accept it without prompting
474 if( oldName != newName && adapter->FootprintExists( libraryName, newName ) )
475 {
476 msg = wxString::Format( _( "Footprint '%s' already exists in library '%s'." ),
477 newName, libraryName );
478
479 KIDIALOG errorDlg( m_frame, msg, _( "Confirmation" ),
480 wxOK | wxCANCEL | wxICON_WARNING );
481 errorDlg.SetOKLabel( _( "Overwrite" ) );
482
483 return errorDlg.ShowModal() == wxID_OK;
484 }
485
486 return true;
487 } ) )
488 {
489 return 0; // canceled by user
490 }
491
492 if( newName == oldName )
493 return 0;
494
495 FOOTPRINT* footprint = nullptr;
496
497 if( fpID == m_frame->GetLoadedFPID() )
498 {
499 footprint = m_frame->GetBoard()->GetFirstFootprint();
500
501 if( footprint )
502 {
503 footprint->SetFPID( LIB_ID( libraryName, newName ) );
504
505 if( footprint->GetValue() == oldName )
506 footprint->SetValue( newName );
507
508 m_frame->OnModify();
509 m_frame->UpdateView();
510 }
511 }
512 else
513 {
514 footprint = m_frame->LoadFootprint( fpID );
515
516 if( footprint )
517 {
518 try
519 {
520 footprint->SetFPID( LIB_ID( libraryName, newName ) );
521
522 if( footprint->GetValue() == oldName )
523 footprint->SetValue( newName );
524
525 m_frame->SaveFootprintInLibrary( footprint, libraryName );
526
527 adapter->DeleteFootprint( libraryName, oldName );
528 }
529 catch( const IO_ERROR& ioe )
530 {
531 DisplayErrorMessage( m_frame, _( "Error renaming footprint" ), ioe.What() );
532 }
533 catch( ... )
534 {
535 // Best efforts...
536 }
537 }
538 }
539
540 wxDataViewItem treeItem = m_frame->GetLibTreeAdapter()->FindItem( fpID );
541
542 if( footprint )
543 {
544 m_frame->UpdateLibraryTree( treeItem, footprint );
545 m_frame->FocusOnLibID( LIB_ID( libraryName, newName ) );
546 }
547
548 return 0;
549}
550
551
553{
555
556 if( frame->DeleteFootprintFromLibrary( frame->GetTargetFPID(), true ) )
557 {
558 if( frame->GetTargetFPID() == frame->GetLoadedFPID() )
559 frame->Clear_Pcb( false );
560
561 frame->SyncLibraryTree( true );
562 }
563
564 return 0;
565}
566
567
569{
570 bool is_last_fp_from_brd = m_frame->IsCurrentFPFromBoard();
571
572 if( !m_frame->Clear_Pcb( true ) )
573 return -1; // this command is aborted
574
576 m_frame->ImportFootprint();
577
578 if( m_frame->GetBoard()->GetFirstFootprint() )
579 m_frame->GetBoard()->GetFirstFootprint()->ClearFlags();
580
581 frame()->ClearUndoRedoList();
582
583 // Update the save items if needed.
584 if( is_last_fp_from_brd )
585 {
586 m_frame->ReCreateMenuBar();
587 m_frame->ReCreateHToolbar();
588 }
589
590 m_toolMgr->RunAction( ACTIONS::zoomFitScreen );
591 m_frame->OnModify();
592 return 0;
593}
594
595
597{
598 if( FOOTPRINT* fp = m_frame->GetBoard()->GetFirstFootprint() )
599 m_frame->ExportFootprint( fp );
600
601 return 0;
602}
603
604
606{
607 // No check for multi selection since the context menu option must be hidden in that case
608 LIB_ID libId = m_frame->GetTargetFPID();
609
610 wxString libName = libId.GetLibNickname();
611 wxString libItemName = libId.GetLibItemName();
612 wxString path = wxEmptyString;
613
615 std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, libName, true );
616
617 if( !optUri )
618 return 0;
619
620 path = *optUri;
621
622 wxString fileExt = wxEmptyString;
623
624 // If selection is footprint
625 if( !libItemName.IsEmpty() )
627
628 wxFileName fileName( path, libItemName, fileExt );
629 wxString explorerCommand;
630
631 if( COMMON_SETTINGS* cfg = Pgm().GetCommonSettings() )
632 explorerCommand = cfg->m_System.file_explorer;
633
634 if( explorerCommand.IsEmpty() )
635 {
636 path = fileName.GetFullPath().BeforeLast( wxFileName::GetPathSeparator() );
637
638 if( !path.IsEmpty() && wxDirExists( path ) )
640
641 return 0;
642 }
643
644 if( !explorerCommand.EndsWith( "%F" ) )
645 {
646 wxMessageBox( _( "Missing/malformed file explorer argument '%F' in common settings." ) );
647 return 0;
648 }
649
650 wxString escapedFilePath = fileName.GetFullPath();
651 escapedFilePath.Replace( wxS( "\"" ), wxS( "_" ) );
652
653 wxString fileArg = wxEmptyString;
654 fileArg << '"' << escapedFilePath << '"';
655
656 explorerCommand.Replace( wxT( "%F" ), fileArg );
657
658 if( !explorerCommand.IsEmpty() )
659 wxExecute( explorerCommand );
660
661 return 0;
662}
663
664
666{
667 wxString fullEditorName = Pgm().GetTextEditor();
668
669 if( fullEditorName.IsEmpty() )
670 {
671 wxMessageBox( _( "No text editor selected in KiCad. Please choose one." ) );
672 return 0;
673 }
674
675 // No check for multi selection since the context menu option must be hidden in that case
676 LIB_ID libId = m_frame->GetLibTree()->GetSelectedLibId();
677
679
680 wxString libName = libId.GetLibNickname();
681 wxString libItemName = wxEmptyString;
682
683 std::optional<wxString> optUri = manager.GetFullURI( LIBRARY_TABLE_TYPE::FOOTPRINT, libName, true );
684
685 if( !optUri )
686 return 0;
687
688 libItemName = *optUri;
689 libItemName << wxFileName::GetPathSeparator();
690 libItemName << libId.GetLibItemName();
691 libItemName << '.' + FILEEXT::KiCadFootprintFileExtension;
692
693 if( !wxFileName::FileExists( libItemName ) )
694 return 0;
695
696 ExecuteFile( fullEditorName, libItemName.wc_str(), nullptr, false );
697
698 return 0;
699}
700
701
703{
704 if( FOOTPRINT* footprint = m_frame->GetBoard()->GetFirstFootprint() )
705 {
706 std::optional<wxString> url = GetFootprintDocumentationURL( *footprint );
707
708 if( !url.has_value() )
709 {
710 frame()->ShowInfoBarMsg( _( "No datasheet found in the footprint." ) );
711 }
712 else
713 {
714 // Only absolute URLs are supported
715 SEARCH_STACK* searchStack = nullptr;
716 GetAssociatedDocument( m_frame, *url, &m_frame->Prj(), searchStack,
717 { m_frame->GetBoard(), footprint } );
718 }
719 }
720 return 0;
721}
722
723
725{
726 m_frame->LoadFootprintFromLibrary( m_frame->GetLibTree()->GetSelectedLibId() );
727 return 0;
728}
729
730
732{
733 FOOTPRINT* footprint = m_frame->GetBoard()->GetFirstFootprint();
734
735 if( !footprint || !m_frame->IsCurrentFPFromBoard() )
736 {
737 wxBell();
738 return 0;
739 }
740
741 m_frame->LoadFootprintFromLibrary( footprint->GetFPID() );
742
743 if( !m_frame->IsLibraryTreeShown() )
744 m_frame->ToggleLibraryTree();
745
746 return 0;
747}
748
749
751{
752 m_frame->ToggleLayersManager();
753 return 0;
754}
755
756
758{
759 m_frame->ToggleProperties();
760 return 0;
761}
762
763
765{
766 if( FOOTPRINT* footprint = m_frame->GetBoard()->GetFirstFootprint() )
767 {
768 getEditFrame<FOOTPRINT_EDIT_FRAME>()->OnEditItemRequest( footprint );
769 m_frame->GetCanvas()->Refresh();
770 }
771
772 return 0;
773}
774
775
777{
778 getEditFrame<FOOTPRINT_EDIT_FRAME>()->ShowPadPropertiesDialog( nullptr );
779 return 0;
780}
781
782
784{
786 DIALOG_CLEANUP_GRAPHICS dlg( editFrame, true );
787
788 dlg.ShowModal();
789 return 0;
790}
791
792
794{
795 if( !m_checkerDialog )
796 {
798 m_checkerDialog->Show( true );
799 }
800 else // The dialog is just not visible (because the user has double clicked on an error item)
801 {
802 m_checkerDialog->Show( true );
803 }
804
805 return 0;
806}
807
808
810{
811 if( !m_checkerDialog )
813
814 if( !m_checkerDialog->IsShownOnScreen() )
815 m_checkerDialog->Show( true );
816
817 m_checkerDialog->SelectMarker( aMarker );
818}
819
820
822{
823 if( m_checkerDialog )
824 {
825 m_checkerDialog->Destroy();
826 m_checkerDialog = nullptr;
827 }
828}
829
830
832{
833 FOOTPRINT* footprint = board()->Footprints().front();
834 int errors = 0;
835 wxString details;
836
837 // Repair duplicate IDs and missing nets.
838 std::set<KIID> ids;
839 int duplicates = 0;
840
841 auto processItem =
842 [&]( EDA_ITEM* aItem )
843 {
844 if( ids.count( aItem->m_Uuid ) )
845 {
846 duplicates++;
847 const_cast<KIID&>( aItem->m_Uuid ) = KIID();
848 }
849
850 ids.insert( aItem->m_Uuid );
851 };
852
853 // Footprint IDs are the most important, so give them the first crack at "claiming" a
854 // particular KIID.
855
856 processItem( footprint );
857
858 // After that the principal use is for DRC marker pointers, which are most likely to pads.
859
860 for( PAD* pad : footprint->Pads() )
861 processItem( pad );
862
863 // From here out I don't think order matters much.
864
865 processItem( &footprint->Reference() );
866 processItem( &footprint->Value() );
867
868 for( BOARD_ITEM* item : footprint->GraphicalItems() )
869 processItem( item );
870
871 for( ZONE* zone : footprint->Zones() )
872 processItem( zone );
873
874 for( PCB_GROUP* group : footprint->Groups() )
875 processItem( group );
876
877 if( duplicates )
878 {
879 errors += duplicates;
880 details += wxString::Format( _( "%d duplicate IDs replaced.\n" ), duplicates );
881 }
882
883 if( errors )
884 {
885 m_frame->OnModify();
886
887 wxString msg = wxString::Format( _( "%d potential problems repaired." ), errors );
888 DisplayInfoMessage( m_frame, msg, details );
889 }
890 else
891 {
892 DisplayInfoMessage( m_frame, _( "No footprint problems found." ) );
893 }
894
895 return 0;
896}
897
898
900{
901 // clang-format off
910
916
919
923
926
929
934 // clang-format on
935
936 // Line modes for the footprint editor: explicit modes, next-mode, and toolbar sync
942}
943
945{
946 LEADER_MODE mode = aEvent.Parameter<LEADER_MODE>();
947 GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" )->m_AngleSnapMode = mode;
948 m_toolMgr->PostAction( ACTIONS::refreshPreview );
950 return 0;
951}
952
954{
956
957 if( !f )
958 return 0;
959
960 LEADER_MODE mode = GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" )->m_AngleSnapMode;
961
962 switch( mode )
963 {
966 break;
969 break;
971 default:
973 break;
974 }
975
976 return 0;
977}
static TOOL_ACTION openWithTextEditor
Definition actions.h:68
static TOOL_ACTION revert
Definition actions.h:62
static TOOL_ACTION saveAs
Definition actions.h:59
static TOOL_ACTION openDirectory
Definition actions.h:69
static TOOL_ACTION showDatasheet
Definition actions.h:266
static TOOL_ACTION save
Definition actions.h:58
static TOOL_ACTION zoomFitScreen
Definition actions.h:141
static TOOL_ACTION showProperties
Definition actions.h:265
static TOOL_ACTION refreshPreview
Definition actions.h:158
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:79
void BuildListOfNets()
Definition board.h:916
const FOOTPRINTS & Footprints() const
Definition board.h:363
int ShowModal() override
void SelectLeftToolbarAction(const TOOL_ACTION &aAction)
Select the given action in the left 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:144
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 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 NewFootprint(const TOOL_EVENT &aEvent)
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 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)
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...
void SetPosition(const VECTOR2I &aPos) override
void SetFPID(const LIB_ID &aFPID)
Definition footprint.h:270
const LIB_ID & GetFPID() const
Definition footprint.h:269
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:42
int ShowModal() override
Definition kidialog.cpp:93
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:91
virtual void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Move the graphic crosshair cursor to the requested position expressed in world coordinates.
Definition kiid.h:49
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< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:100
const wxString GetUniStringLibNickname() const
Definition lib_id.h:88
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
Definition pad.h:54
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 importFootprint
static TOOL_ACTION pasteFootprint
static TOOL_ACTION footprintProperties
static TOOL_ACTION lineMode90
90-degree-only mode (icon lines90)
static TOOL_ACTION checkFootprint
static TOOL_ACTION editLibFpInFpEditor
static TOOL_ACTION duplicateFootprint
static TOOL_ACTION cutFootprint
static TOOL_ACTION repairFootprint
static TOOL_ACTION copyFootprint
static TOOL_ACTION cleanupGraphics
A set of BOARD_ITEMs (i.e., without duplicates).
Definition pcb_group.h:53
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:206
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:131
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:186
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition tool_base.cpp:44
TOOL_MANAGER * m_toolMgr
Definition tool_base.h:220
RESET_REASON
Determine the reason of reset for a tool.
Definition tool_base.h:78
Generic, UI-independent tool event.
Definition tool_event.h:171
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:473
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:110
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:74
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:230
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition confirm.cpp:131
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
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:62
This file is part of the common library.
@ FRAME_FOOTPRINT_WIZARD
Definition frame_type.h:46
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:143
static const std::string KiCadFootprintFileExtension
bool LaunchExternal(const wxString &aPath)
Launches the given file or folder in the host OS.
Class to handle a set of BOARD_ITEMs.
PGM_BASE & Pgm()
The global program "get" accessor.
Definition pgm_base.cpp:946
see class PGM_BASE
T * GetAppSettings(const char *aFilename)
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694
Definition of file extensions used in Kicad.