KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcbnew.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) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
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
22#include <pgm_base.h>
23#include <eda_pattern_match.h>
26#include <confirm.h>
29#include <api/api_handler_pcb.h>
30#include <api/api_server.h>
31#include <api/api_utils.h>
35#include <kiface_base.h>
36#include <kiface_ids.h>
37#include <kiway_holder.h>
38#include <pcb_edit_frame.h>
39#include <macros.h>
40#include <gestfich.h>
41#include <paths.h>
42#include <pcbnew_settings.h>
43#include <footprint.h>
53#include <footprint_info_impl.h>
54#include <footprint.h>
55#include <board.h>
56#include <board_loader.h>
57#include <lib_id.h>
58#include <nlohmann/json.hpp>
62#include <panel_edit_options.h>
74#include <project_pcb.h>
75#include <string_utils.h>
76#include <thread_pool.h>
77#include <trace_helpers.h>
78#include <widgets/kistatusbar.h>
79
80#include <wx/tokenzr.h>
81
82#include "invoke_pcb_dialog.h"
84#include "pcbnew_jobs_handler.h"
86#include <reporter.h>
87#include "git/kigit_pcb_merge.h"
88#include "git/kigit_fp_merge.h"
90
94#include <toolbars_pcb_editor.h>
95
96#include <wx/crt.h>
97
98
111static wxString filterFootprints( const wxString& aFilterJson )
112{
113 using json = nlohmann::json;
114
115 try
116 {
117 json input = json::parse( aFilterJson.ToStdString() );
118
119 int pinCount = input.value( "pin_count", 0 );
120 bool zeroFilters = input.value( "zero_filters", true );
121 int maxResults = input.value( "max_results", 400 );
122
123 std::vector<std::unique_ptr<EDA_PATTERN_MATCH>> filterMatchers;
124
125 if( input.contains( "filters" ) && input["filters"].is_array() )
126 {
127 for( const auto& f : input["filters"] )
128 {
129 if( f.is_string() )
130 {
131 wxString pattern = wxString::FromUTF8( f.get<std::string>() );
132 auto matcher = std::make_unique<EDA_PATTERN_MATCH_WILDCARD_ANCHORED>();
133 matcher->SetPattern( pattern.Lower() );
134 filterMatchers.push_back( std::move( matcher ) );
135 }
136 }
137 }
138
139 bool hasFilters = ( pinCount > 0 || !filterMatchers.empty() );
140
141 if( zeroFilters && !hasFilters )
142 return wxS( "[]" );
143
144 PROJECT* project = nullptr;
145
146 if( wxTheApp )
147 {
148 wxWindow* focus = wxWindow::FindFocus();
149 wxWindow* top = focus ? wxGetTopLevelParent( focus ) : wxTheApp->GetTopWindow();
150
151 if( top )
152 {
153 if( KIWAY_HOLDER* holder = dynamic_cast<KIWAY_HOLDER*>( top ) )
154 project = &holder->Prj();
155 }
156 }
157
158 if( !project )
160
162
163 if( !adapter )
164 return wxS( "[]" );
165
166 adapter->AsyncLoad();
167 adapter->BlockUntilLoaded();
168
169 // Iterate through preloaded footprints directly instead of re-reading from disk
170 json output = json::array();
171 int count = 0;
172
173 for( const wxString& nickname : adapter->GetLibraryNames() )
174 {
175 std::vector<FOOTPRINT*> footprints = adapter->GetFootprints( nickname, true );
176
177 for( FOOTPRINT* fp : footprints )
178 {
179 if( !fp )
180 continue;
181
182 // Pin count filter
183 if( pinCount > 0 )
184 {
185 int fpPadCount = fp->GetNumberedPadCount();
186
187 if( fpPadCount != pinCount )
188 continue;
189 }
190
191 // Footprint filter patterns with case-insensitive matching
192 if( !filterMatchers.empty() )
193 {
194 bool matches = false;
195
196 for( const auto& matcher : filterMatchers )
197 {
198 wxString name;
199
200 // If filter contains ':', include library nickname in match string
201 if( matcher->GetPattern().Contains( wxS( ":" ) ) )
202 name = fp->GetFPID().GetLibNickname().wx_str().Lower() + wxS( ":" );
203
204 name += fp->GetFPID().GetLibItemName().wx_str().Lower();
205
206 if( matcher->Find( name ) )
207 {
208 matches = true;
209 break;
210 }
211 }
212
213 if( !matches )
214 continue;
215 }
216
217 wxString libId = fp->GetFPID().Format();
218 output.push_back( libId.ToStdString() );
219
220 if( ++count >= maxResults )
221 break;
222 }
223
224 if( count >= maxResults )
225 break;
226 }
227
228 return wxString::FromUTF8( output.dump() );
229 }
230 catch( const std::exception& )
231 {
232 return wxS( "[]" );
233 }
234}
235
236
237namespace PCB {
238
239// Non-job kiface exports for diff/merge (returned by IfaceOrAddress). Defined
240// after the kiface instance so they can route into its jobs handler.
241static int pcbnewMergeExport( int aKind, const wxString& aAncestor, const wxString& aOurs,
242 const wxString& aTheirs, const wxString& aOutput, bool aInteractive,
243 bool aSingleFile, REPORTER* aReporter );
244static int pcbnewOpenDiffDialogExport( int aKind, const wxString& aFileA, const wxString& aFileB,
245 const wxString& aLabelA, const wxString& aLabelB,
246 wxWindow* aParent, REPORTER* aReporter );
247
248
249static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
250{
251 // Of course all are virtual overloads, implementations of the KIFACE.
252
253 IFACE( const char* aName, KIWAY::FACE_T aType ) :
254 KIFACE_BASE( aName, aType ),
256 {}
257
258 bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits, KIWAY* aKiway ) override;
259
260 void Reset() override;
261
262 void OnKifaceEnd() override;
263
264 wxWindow* CreateKiWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway, int aCtlBits = 0 ) override
265 {
266 switch( aClassId )
267 {
268 case FRAME_PCB_EDITOR:
269 {
270 auto frame = new PCB_EDIT_FRAME( aKiway, aParent );
271
272 if( Kiface().IsSingle() )
273 {
274 // only run this under single_top, not under a project manager.
277 }
278
279 return frame;
280 }
281
283 return new FOOTPRINT_EDIT_FRAME( aKiway, aParent );
286 return new FOOTPRINT_VIEWER_FRAME( aKiway, aParent );
287
289 return new FOOTPRINT_CHOOSER_FRAME( aKiway, aParent );
290
292 return new FOOTPRINT_WIZARD_FRAME( aKiway, aParent, FRAME_T( aClassId ) );
293
295 return FOOTPRINT_PREVIEW_PANEL::New( aKiway, aParent, this );
296
298 {
299 DIALOG_CONFIGURE_PATHS dlg( aParent );
300
301 // The dialog's constructor probably failed to set its Kiway because the
302 // dynamic_cast fails when aParent was allocated by a separate compilation
303 // module. So set it directly.
304 dlg.SetKiway( &dlg, aKiway );
305
306 // Use QuasiModal so that HTML help window will work
307 if( dlg.ShowQuasiModal() == wxID_OK )
309
310 // Dialog has completed; nothing to return.
311 return nullptr;
312 }
313
315 InvokePcbLibTableEditor( aKiway, aParent );
316 // Dialog has completed; nothing to return.
317 return nullptr;
318
320 return new PANEL_DISPLAY_OPTIONS( aParent, GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" ) );
321
322 case PANEL_FP_GRIDS:
323 {
324 FOOTPRINT_EDITOR_SETTINGS* cfg = GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" );
325 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
326
327 if( !frame )
328 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
329
330 if( !frame )
331 frame = aKiway->Player( FRAME_PCB_EDITOR, false );
332
333 if( frame )
334 SetUserUnits( frame->GetUserUnits() );
335
336 return new PANEL_GRID_SETTINGS( aParent, this, frame, cfg, FRAME_FOOTPRINT_EDITOR );
337 }
343
347
349 {
350 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
351
352 if( !frame )
353 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
355 if( !frame )
356 frame = aKiway->Player( FRAME_PCB_EDITOR, false );
357
358 if( frame )
359 SetUserUnits( frame->GetUserUnits() );
360
361 return new PANEL_EDIT_OPTIONS( aParent, this, frame, true );
366 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
367
368 if( !frame )
369 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
371 if( !frame )
372 frame = aKiway->Player( FRAME_PCB_EDITOR, false );
374 if( frame )
376
377 return new PANEL_FP_EDITOR_FIELD_DEFAULTS( aParent );
382 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
383
384 if( !frame )
385 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
386
387 if( !frame )
388 frame = aKiway->Player( FRAME_PCB_EDITOR, false );
389
390 if( frame )
391 SetUserUnits( frame->GetUserUnits() );
392
393 return new PANEL_FP_EDITOR_GRAPHICS_DEFAULTS( aParent, this );
394 }
395
397 return new class PANEL_FP_USER_LAYER_NAMES( aParent );
398
400 {
401 APP_SETTINGS_BASE* cfg = GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" );
402 TOOLBAR_SETTINGS* tb = GetToolbarSettings<FOOTPRINT_EDIT_TOOLBAR_SETTINGS>( "fpedit-toolbars" );
403
404 std::vector<TOOL_ACTION*> actions;
405 std::vector<ACTION_TOOLBAR_CONTROL*> controls;
406
407 for( TOOL_ACTION* action : ACTION_MANAGER::GetActionList() )
408 actions.push_back( action );
409
410 for( ACTION_TOOLBAR_CONTROL* control : ACTION_TOOLBAR::GetCustomControlList( FRAME_FOOTPRINT_EDITOR ) )
411 controls.push_back( control );
412
413 return new PANEL_TOOLBAR_CUSTOMIZATION( aParent, cfg, tb, FRAME_FOOTPRINT_EDITOR, actions, controls );
414 }
415
416 case PANEL_FP_COLORS:
417 return new PANEL_FP_EDITOR_COLOR_SETTINGS( aParent );
418
420 return new PANEL_DISPLAY_OPTIONS( aParent, GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" ) );
421
422 case PANEL_PCB_GRIDS:
423 {
424 PCBNEW_SETTINGS* cfg = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
425 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_PCB_EDITOR, false );
426
427 if( !frame )
428 frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
429
430 if( !frame )
431 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
432
433 if( frame )
434 SetUserUnits( frame->GetUserUnits() );
435
436 return new PANEL_GRID_SETTINGS( aParent, this, frame, cfg, FRAME_PCB_EDITOR );
437 }
438
442
444 return new PANEL_PCBNEW_DISPLAY_ORIGIN( aParent, GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" ),
446
448 {
449 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_PCB_EDITOR, false );
450
451 if( !frame )
452 frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
453
454 if( !frame )
455 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
456
457 if( frame )
458 SetUserUnits( frame->GetUserUnits() );
459
460 return new PANEL_EDIT_OPTIONS( aParent, this, frame, false );
461 }
462
463 case PANEL_PCB_COLORS:
464 {
465 BOARD* board = nullptr;
466 EDA_BASE_FRAME* boardProvider = aKiway->Player( FRAME_PCB_EDITOR, false );
467
468 if( boardProvider )
469 board = static_cast<PCB_EDIT_FRAME*>( boardProvider )->GetBoard();
470
471 return new PANEL_PCBNEW_COLOR_SETTINGS( aParent, board );
472 }
473
475 {
476 APP_SETTINGS_BASE* cfg = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
477 TOOLBAR_SETTINGS* tb = GetToolbarSettings<PCB_EDIT_TOOLBAR_SETTINGS>( "pcbnew-toolbars" );
478
479 std::vector<TOOL_ACTION*> actions;
480 std::vector<ACTION_TOOLBAR_CONTROL*> controls;
481
482 for( TOOL_ACTION* action : ACTION_MANAGER::GetActionList() )
483 actions.push_back( action );
484
485 for( ACTION_TOOLBAR_CONTROL* control : ACTION_TOOLBAR::GetCustomControlList( FRAME_PCB_EDITOR ) )
486 controls.push_back( control );
487
488 return new PANEL_TOOLBAR_CUSTOMIZATION( aParent, cfg, tb, FRAME_PCB_EDITOR, actions, controls );
489 }
490
492 return new PANEL_PCBNEW_ACTION_PLUGINS( aParent );
493
495 return new PANEL_3D_DISPLAY_OPTIONS( aParent );
496
497 case PANEL_3DV_OPENGL:
498 return new PANEL_3D_OPENGL_OPTIONS( aParent );
499
501 return new PANEL_3D_RAYTRACING_OPTIONS( aParent );
502
504 {
505 APP_SETTINGS_BASE* cfg = GetAppSettings<EDA_3D_VIEWER_SETTINGS>( "3d_viewer" );
506 TOOLBAR_SETTINGS* tb = GetToolbarSettings<EDA_3D_VIEWER_TOOLBAR_SETTINGS>( "3d_viewer-toolbars" );
507
508 std::vector<TOOL_ACTION*> actions;
509 std::vector<ACTION_TOOLBAR_CONTROL*> controls;
510
511 for( TOOL_ACTION* action : ACTION_MANAGER::GetActionList() )
512 actions.push_back( action );
513
514 for( ACTION_TOOLBAR_CONTROL* control : ACTION_TOOLBAR::GetCustomControlList( FRAME_PCB_DISPLAY3D ) )
515 controls.push_back( control );
516
517 return new PANEL_TOOLBAR_CUSTOMIZATION( aParent, cfg, tb, FRAME_PCB_DISPLAY3D, actions, controls );
518 }
519
520 default:
521 return nullptr;
522 }
523 }
524
535 void* IfaceOrAddress( int aDataId ) override
536 {
537 switch( aDataId )
538 {
540 {
541 // This is the mechanism by which FOOTPRINT_SELECT_WIDGET can get access to the adapter
542 // without directly linking to pcbnew or pcbcommon, going through PROJECT::FootprintLibAdapter
543 PROJECT* project = nullptr;
544
545 if( wxTheApp )
546 {
547 wxWindow* focus = wxWindow::FindFocus();
548 wxWindow* top = focus ? wxGetTopLevelParent( focus ) : wxTheApp->GetTopWindow();
549
550 if( top )
551 {
552 if( KIWAY_HOLDER* holder = dynamic_cast<KIWAY_HOLDER*>( top ) )
553 project = &holder->Prj();
554 }
555 }
556
557 if( !project )
559
561 }
562
564 {
565 // Return function pointer for filtering footprints
566 // Signature: wxString (*)(const wxString& aFilterJson)
567 return reinterpret_cast<void*>( &filterFootprints );
568 }
569
571 return reinterpret_cast<void*>( &pcbnewMergeExport );
572
574 return reinterpret_cast<void*>( &pcbnewOpenDiffDialogExport );
575
576 default:
577 return nullptr;
578 }
579 }
580
582 PCBNEW_JOBS_HANDLER* JobHandler() const { return m_jobHandler.get(); }
583
589 void SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcProjectName,
590 const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
591 const wxString& aSrcFilePath, wxString& aErrors ) override;
592
593 int HandleJob( JOB* aJob, REPORTER* aReporter, PROGRESS_REPORTER* aProgressReporter ) override;
594
595 bool HandleJobConfig( JOB* aJob, wxWindow* aParent ) override;
596
597 bool HandleApiOpenDocument( const DOCUMENT_SPEC& aSpec,
598 KICAD_API_SERVER* aServer,
599 wxString* aError ) override;
600
601 bool HandleApiCloseDocument( const wxString& aBoardFileName,
602 KICAD_API_SERVER* aServer,
603 wxString* aError ) override;
604
605 bool handleOpenPcb( const wxString& aPath, KICAD_API_SERVER* aServer, wxString* aError );
606
607 bool handleCreatePcb( const wxString& aPath, KICAD_API_SERVER* aServer, wxString* aError );
608
609 bool handleOpenFootprint( const wxString& aProjectPath, const wxString& aLibIdStr, KICAD_API_SERVER* aServer,
610 wxString* aError );
611
612 void PreloadLibraries( KIWAY* aKiway ) override;
613 void ProjectChanged() override;
614 void CancelPreload( bool aBlock = true ) override;
615 void RegisterLibraryHandlers( KICAD_API_SERVER* aServer ) override;
616 bool LoadAllLibraries() override;
617
618
619private:
620 std::unique_ptr<PCBNEW_JOBS_HANDLER> m_jobHandler;
621 std::shared_ptr<BACKGROUND_JOB> m_libraryPreloadBackgroundJob;
622 std::future<void> m_libraryPreloadReturn;
624 std::atomic_bool m_libraryPreloadAbort;
625
626 void closeCurrentDocument( KICAD_API_SERVER* aServer );
627
628 KIWAY* m_kiway = nullptr;
629 std::shared_ptr<HEADLESS_PCB_CONTEXT> m_openContext;
630 std::unique_ptr<API_HANDLER_PCB> m_openHandler;
631 std::shared_ptr<HEADLESS_FOOTPRINT_CONTEXT> m_openFpContext;
632 std::unique_ptr<API_HANDLER_FOOTPRINT> m_openFpHandler;
633 std::unique_ptr<API_HANDLER_FP_LIBRARIES> m_apiHandlerFpLibs;
634
635} kiface( "pcbnew", KIWAY::FACE_PCB );
636
637
638int pcbnewMergeExport( int aKind, const wxString& aAncestor, const wxString& aOurs,
639 const wxString& aTheirs, const wxString& aOutput, bool aInteractive,
640 bool aSingleFile, REPORTER* aReporter )
641{
642 return kiface.JobHandler()->RunMerge( static_cast<KICAD_DIFF::DOC_KIND>( aKind ), aAncestor,
643 aOurs, aTheirs, aOutput, aInteractive, aSingleFile,
644 aReporter );
645}
646
647
648int pcbnewOpenDiffDialogExport( int aKind, const wxString& aFileA, const wxString& aFileB,
649 const wxString& aLabelA, const wxString& aLabelB,
650 wxWindow* aParent, REPORTER* aReporter )
651{
652 return kiface.JobHandler()->OpenDiffDialog( static_cast<KICAD_DIFF::DOC_KIND>( aKind ), aFileA,
653 aFileB, aLabelA, aLabelB, aParent, aReporter );
654}
655
656} // namespace
657
658
659using namespace PCB;
660
661
663
664
665// KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h.
666// KIFACE_GETTER will not have name mangling due to declaration in kiway.h.
667KIFACE_API KIFACE* KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram )
668{
669 return &kiface;
670}
671
672
673bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits, KIWAY* aKiway )
674{
675 // This is process-level-initialization, not project-level-initialization of the DSO.
676 // Do nothing in here pertinent to a project!
678
679 SETTINGS_MANAGER& mgr = aProgram->GetSettingsManager();
680
683
684 // We intentionally register KifaceSettings after FOOTPRINT_EDITOR_SETTINGS and EDA_3D_VIEWER_SETTINGS
685 // In legacy configs, many settings were in a single editor config and the migration routine
686 // for the main editor file will try and call into the now separate settings stores
687 // to move the settings into them
689
690 // Register the footprint editor settings as well because they share a KiFACE and need to be
691 // loaded prior to use to avoid threading deadlocks
693
694 start_common( aCtlBits );
695
696 m_kiway = aKiway;
697
698 m_jobHandler = std::make_unique<PCBNEW_JOBS_HANDLER>( aKiway );
699
701 {
702 m_jobHandler->SetReporter( &CLI_REPORTER::GetInstance() );
703 m_jobHandler->SetProgressReporter( &CLI_PROGRESS_REPORTER::GetInstance() );
704 }
705
706 // Register the PCB and footprint merge drivers with libgit2 so
707 // .gitattributes entries `merge=kicad-pcb` and `merge=kicad-fp` route
708 // through our 3-way merge pipeline. git_merge_driver_register is not
709 // thread-safe; this runs once at kiface init before any background work
710 // spawns. The registry is idempotent so re-loads of the kiface are safe.
713
714 if( Pgm().ApiServerOrNull() )
715 {
716 m_apiHandlerFpLibs = std::make_unique<API_HANDLER_FP_LIBRARIES>();
718 }
719
720 return true;
721}
722
723
725{
726}
727
728
730{
732 {
733 if( Pgm().ApiServerOrNull() )
735
736 m_apiHandlerFpLibs.reset();
737 }
738
739 // Release the CLI-cached board while the static DRC_ITEM tables it serializes against are
740 // still alive; deferring to static teardown crashes reading dangling severity keys
741 if( m_jobHandler )
742 m_jobHandler->ClearCachedBoard();
743
744 end_common();
745}
746
747
748void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcProjectName,
749 const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
750 const wxString& aSrcFilePath, wxString& aErrors )
751{
752 wxFileName destFile( aSrcFilePath );
753 wxString destPath = destFile.GetPathWithSep();
754 wxUniChar pathSep = wxFileName::GetPathSeparator();
755 wxString ext = destFile.GetExt();
756
757 if( destPath.StartsWith( aProjectBasePath + pathSep ) )
758 destPath.Replace( aProjectBasePath, aNewProjectBasePath, false );
759
760 wxString srcProjectFootprintLib = pathSep + aSrcProjectName + wxT( ".pretty" ) + pathSep;
761 wxString newProjectFootprintLib = pathSep + aNewProjectName + wxT( ".pretty" ) + pathSep;
762
763 destPath.Replace( srcProjectFootprintLib, newProjectFootprintLib, true );
764
765 destFile.SetPath( destPath );
766
769 {
770 if( destFile.GetName() == aSrcProjectName )
771 destFile.SetName( aNewProjectName );
772
773 CopySexprFile( aSrcFilePath, destFile.GetFullPath(),
774 [&]( const std::string& token, wxString& value )
775 {
776 if( token == "sheetfile" )
777 {
778 for( const wxString extension : { wxT( ".sch" ), wxT( ".kicad_sch" ) } )
779 {
780 if( value == aSrcProjectName + extension )
781 {
782 value = aNewProjectName + extension;
783 return true;
784 }
785 else if( value == aProjectBasePath + "/" + aSrcProjectName + extension )
786 {
787 value = aNewProjectBasePath + "/" + aNewProjectName + extension;
788 return true;
789 }
790 else if( value.StartsWith( aProjectBasePath ) )
791 {
792 value.Replace( aProjectBasePath, aNewProjectBasePath, false );
793 return true;
794 }
795 }
796 }
797
798 return false;
799 },
800 aErrors );
801 }
802 else if( ext == FILEEXT::LegacyPcbFileExtension )
803 {
804 if( destFile.GetName() == aSrcProjectName )
805 destFile.SetName( aNewProjectName );
806
807 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
808 }
811 {
812 // Footprints are not project-specific. Keep their source names.
813 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
814 }
816 {
817 // TODO
818 }
819 else if( ext == wxT( "rpt" ) )
820 {
821 // DRC must be the "gold standard". Since we can't guarantee that there aren't
822 // any non-deterministic cases in the save-as algorithm, we don't want to certify
823 // the result with the source's DRC report. Therefore copy it under the old
824 // name.
825 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
826 }
827 else if( destFile.GetName() == FILEEXT::FootprintLibraryTableFileName )
828 {
829 wxFileName libTableFn( aSrcFilePath );
830 LIBRARY_TABLE libTable( libTableFn, LIBRARY_TABLE_SCOPE::PROJECT );
831 libTable.SetPath( destFile.GetFullPath() );
832 libTable.SetType( LIBRARY_TABLE_TYPE::FOOTPRINT );
833
834 for( LIBRARY_TABLE_ROW& row : libTable.Rows() )
835 {
836 wxString uri = row.URI();
837
838 uri.Replace( wxT( "/" ) + aSrcProjectName + wxT( ".pretty" ),
839 wxT( "/" ) + aNewProjectName + wxT( ".pretty" ) );
840
841 row.SetURI( uri );
842 }
843
844 libTable.Save().map_error(
845 [&]( const LIBRARY_ERROR& aError )
846 {
847 wxString msg;
848
849 if( !aErrors.empty() )
850 aErrors += wxT( "\n" );
851
852 msg.Printf( _( "Cannot copy file '%s'." ), destFile.GetFullPath() );
853 aErrors += msg;
854 } );
855 }
856 else
857 {
858 wxFAIL_MSG( wxT( "Unexpected filetype for Pcbnew::SaveFileAs()" ) );
859 }
860}
861
862
863int IFACE::HandleJob( JOB* aJob, REPORTER* aReporter, PROGRESS_REPORTER* aProgressReporter )
864{
865 return m_jobHandler->RunJob( aJob, aReporter, aProgressReporter );
866}
867
868
869bool IFACE::HandleJobConfig( JOB* aJob, wxWindow* aParent )
870{
871 return m_jobHandler->HandleJobConfig( aJob, aParent );
872}
873
874
876{
877 if( m_openHandler )
878 {
879 if( aServer )
880 aServer->DeregisterHandler( m_openHandler.get() );
881
882 m_openHandler.reset();
883 }
884
885 m_openContext.reset();
886
887 // The jobs handler caches the last-loaded board. Clear it so the next job
888 // uses the board from the newly opened document rather than a stale copy.
889 m_jobHandler->ClearCachedBoard();
890
891 if( m_openFpHandler )
892 {
893 if( aServer )
894 aServer->DeregisterHandler( m_openFpHandler.get() );
895
896 m_openFpHandler.reset();
897 }
898
899 m_openFpContext.reset();
900}
901
902
903bool IFACE::HandleApiOpenDocument( const DOCUMENT_SPEC& aSpec, KICAD_API_SERVER* aServer, wxString* aError )
904{
905 wxCHECK( aServer, false );
906
907 if( aSpec.kind == DOCUMENT_SPEC::KIND::FPID_KIND )
908 return handleOpenFootprint( aSpec.path, aSpec.libId.GetUniStringLibId(), aServer, aError );
909
910 if( aSpec.kind == DOCUMENT_SPEC::KIND::CREATE_KIND )
911 return handleCreatePcb( aSpec.path, aServer, aError );
912
913 if( aSpec.path.IsEmpty() )
914 {
915 if( aError )
916 *aError = wxS( "No path specified to open" );
917
918 return false;
919 }
920
921 return handleOpenPcb( aSpec.path, aServer, aError );
922}
923
924
925bool IFACE::handleOpenFootprint( const wxString& aProjectPath, const wxString& aLibIdStr, KICAD_API_SERVER* aServer,
926 wxString* aError )
927{
928 LIB_ID fpid;
929
930 if( fpid.Parse( aLibIdStr ) >= 0 )
931 {
932 if( aError )
933 *aError = wxString::Format( wxS( "Invalid footprint LIB_ID: %s" ), aLibIdStr );
934
935 return false;
936 }
937
938 wxFileName projectPath( aProjectPath );
939 projectPath.MakeAbsolute();
940
941 SETTINGS_MANAGER& settingsManager = Pgm().GetSettingsManager();
942
943 if( !settingsManager.LoadProject( projectPath.GetFullPath(), true ) )
944 {
945 wxLogTrace( traceApi, "Warning: no project file found for %s", aProjectPath );
946 }
947
948 PROJECT* project = settingsManager.GetProject( projectPath.GetFullPath() );
949
950 if( !project )
951 {
952 if( aError )
953 *aError = wxString::Format( wxS( "Error loading project for %s" ), aProjectPath );
954
955 return false;
956 }
957
958 std::shared_ptr<HEADLESS_FOOTPRINT_CONTEXT> newContext;
959
960 try
961 {
963 adapter->AsyncLoad();
964 adapter->BlockUntilLoaded();
965 std::unique_ptr<FOOTPRINT> footprint( adapter->LoadFootprintWithOptionalNickname( fpid, true ) );
966
967 if( !footprint )
968 {
969 if( aError )
970 *aError = wxString::Format( wxS( "Footprint not found: %s" ), aLibIdStr );
971
972 return false;
973 }
974
975 newContext = std::make_shared<HEADLESS_FOOTPRINT_CONTEXT>(
976 std::move( footprint ), fpid, project, GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" ), m_kiway );
977 }
978 catch( ... )
979 {
980 if( aError )
981 *aError = wxString::Format( wxS( "Failed to load footprint: %s" ), aLibIdStr );
982
983 return false;
984 }
985
986 closeCurrentDocument( aServer );
987
988 if( !m_apiHandlerFpLibs )
989 {
990 m_apiHandlerFpLibs = std::make_unique<API_HANDLER_FP_LIBRARIES>();
991 aServer->RegisterHandler( m_apiHandlerFpLibs.get() );
992 }
993
994 m_openFpContext = std::move( newContext );
995
996 m_openFpHandler = std::make_unique<API_HANDLER_FOOTPRINT>( m_openFpContext, nullptr );
997 aServer->RegisterHandler( m_openFpHandler.get() );
998
999 return true;
1000}
1001
1002
1003bool IFACE::handleOpenPcb( const wxString& aPath, KICAD_API_SERVER* aServer, wxString* aError )
1004{
1005 wxFileName projectPath( aPath );
1006
1007 if( projectPath.GetExt() == FILEEXT::KiCadPcbFileExtension )
1008 projectPath.SetExt( FILEEXT::ProjectFileExtension );
1009 else if( projectPath.GetExt() != FILEEXT::ProjectFileExtension )
1010 projectPath.SetExt( FILEEXT::ProjectFileExtension );
1011
1012 projectPath.MakeAbsolute();
1013
1014 // We currently only support one document per type (and each needs to come from
1015 // the same project). This will need evolution once we support MDI and multi-project.
1016 closeCurrentDocument( aServer );
1017
1018 SETTINGS_MANAGER& settingsManager = Pgm().GetSettingsManager();
1019
1020 // Reuse an already-loaded project if one exists for this path.
1021 PROJECT* project = settingsManager.GetProject( projectPath.GetFullPath() );
1022
1023 if( !project )
1024 {
1025 if( !settingsManager.LoadProject( projectPath.GetFullPath(), true ) )
1026 wxLogTrace( traceApi, "Warning: no project file found for %s", aPath );
1027
1028 project = settingsManager.GetProject( projectPath.GetFullPath() );
1029 }
1030
1031 if( !project )
1032 {
1033 if( aError )
1034 *aError = wxString::Format( wxS( "Error loading project for %s" ), aPath );
1035
1036 return false;
1037 }
1038
1039 wxFileName boardPath( projectPath );
1040 boardPath.SetExt( FILEEXT::KiCadPcbFileExtension );
1041
1042 if( !boardPath.FileExists() )
1043 {
1044 if( aError )
1045 *aError = wxString::Format( wxS( "File not found: %s" ), aPath );
1046
1047 return false;
1048 }
1049
1050 PCB_IO_MGR::PCB_FILE_T pluginType =
1052
1053 if( pluginType == PCB_IO_MGR::FILE_TYPE_NONE )
1054 {
1055 if( aError )
1056 *aError = wxString::Format( wxS( "%s is not a recognized file type" ), aPath );
1057
1058 return false;
1059 }
1060
1061 std::shared_ptr<HEADLESS_PCB_CONTEXT> newContext;
1062
1063 try
1064 {
1065 std::unique_ptr<BOARD> loadedBoard = BOARD_LOADER::Load( boardPath.GetFullPath(), pluginType, project );
1066
1067 if( !loadedBoard )
1068 {
1069 if( aError )
1070 *aError = wxS( "Failed to load board" );
1071
1072 return false;
1073 }
1074
1075 newContext = std::make_shared<HEADLESS_PCB_CONTEXT>( std::move( loadedBoard ), project,
1077 }
1078 catch( const IO_ERROR& ioe )
1079 {
1080 if( aError )
1081 *aError = wxString::Format( wxS( "Failed to load board: %s" ), ioe.What() );
1082
1083 return false;
1084 }
1085 catch( ... )
1086 {
1087 if( aError )
1088 *aError = wxS( "Failed to load board" );
1089
1090 return false;
1091 }
1092
1093 if( !m_apiHandlerFpLibs )
1094 {
1095 m_apiHandlerFpLibs = std::make_unique<API_HANDLER_FP_LIBRARIES>();
1096 aServer->RegisterHandler( m_apiHandlerFpLibs.get() );
1097 }
1098
1099 m_openContext = std::move( newContext );
1100
1101 m_openHandler = std::make_unique<API_HANDLER_PCB>( m_openContext, nullptr );
1102 aServer->RegisterHandler( m_openHandler.get() );
1103
1104 return true;
1105}
1106
1107
1108bool IFACE::handleCreatePcb( const wxString& aPath, KICAD_API_SERVER* aServer, wxString* aError )
1109{
1110 wxFileName boardPath( aPath );
1111 boardPath.MakeAbsolute();
1112
1113 wxFileName projectPath( boardPath );
1114 projectPath.SetExt( FILEEXT::ProjectFileExtension );
1115
1116 if( m_openContext && m_openContext->IsContentModified() )
1117 {
1118 if( aError )
1119 *aError = wxS( "The current board has unsaved changes; save or revert it first" );
1120
1121 return false;
1122 }
1123
1124 closeCurrentDocument( aServer );
1125
1126 SETTINGS_MANAGER& settingsManager = Pgm().GetSettingsManager();
1127
1128 PROJECT* project = settingsManager.GetProject( projectPath.GetFullPath() );
1129
1130 if( !project )
1131 {
1132 settingsManager.LoadProject( projectPath.GetFullPath(), true );;
1133 project = settingsManager.GetProject( projectPath.GetFullPath() );
1134 }
1135
1136 if( !project )
1137 {
1138 if( aError )
1139 *aError = wxString::Format( wxS( "Error creating project for %s" ), aPath );
1140
1141 return false;
1142 }
1143
1144 std::shared_ptr<HEADLESS_PCB_CONTEXT> newContext;
1145
1146 try
1147 {
1148 std::unique_ptr<BOARD> newBoard = BOARD_LOADER::CreateEmptyBoard( project );
1149
1150 if( !newBoard )
1151 {
1152 if( aError )
1153 *aError = wxS( "Failed to create board" );
1154
1155 return false;
1156 }
1157
1158 newBoard->SetFileName( boardPath.GetFullPath() );
1159
1160 newContext = std::make_shared<HEADLESS_PCB_CONTEXT>( std::move( newBoard ), project,
1162 }
1163 catch( ... )
1164 {
1165 if( aError )
1166 *aError = wxS( "Failed to create board" );
1167
1168 return false;
1169 }
1170
1171 m_openContext = std::move( newContext );
1172
1173 if( !m_apiHandlerFpLibs )
1174 {
1175 m_apiHandlerFpLibs = std::make_unique<API_HANDLER_FP_LIBRARIES>();
1176 aServer->RegisterHandler( m_apiHandlerFpLibs.get() );
1177 }
1178
1179 m_openHandler = std::make_unique<API_HANDLER_PCB>( m_openContext, nullptr );
1180 aServer->RegisterHandler( m_openHandler.get() );
1181
1182 return true;
1183}
1184
1185
1186bool IFACE::HandleApiCloseDocument( const wxString& aFileName, KICAD_API_SERVER* aServer, wxString* aError )
1187{
1188 wxCHECK( aServer, false );
1189
1191 {
1192 if( aError )
1193 *aError = wxS( "No document is currently open" );
1194
1195 return false;
1196 }
1197
1198 if( !aFileName.IsEmpty() && m_openContext )
1199 {
1200 wxFileName currentBoard( m_openContext->GetCurrentFileName() );
1201
1202 if( currentBoard.GetFullName() != aFileName )
1203 {
1204 if( aError )
1205 *aError = wxS( "Requested document does not match the open document" );
1206
1207 return false;
1208 }
1209 }
1210
1211 closeCurrentDocument( aServer );
1212 return true;
1213}
1214
1215
1217{
1218 constexpr static int interval = 150;
1219 constexpr static int timeLimit = 120000;
1220
1221 wxCHECK( aKiway, /* void */ );
1222
1223 // Use compare_exchange to atomically check and set the flag to prevent race conditions
1224 // when PreloadLibraries is called multiple times concurrently (e.g., from project manager
1225 // and pcb editor both scheduling via CallAfter)
1226 bool expected = false;
1227
1228 if( !m_libraryPreloadInProgress.compare_exchange_strong( expected, true ) )
1229 return;
1230
1232
1234 Pgm().GetBackgroundJobMonitor().Create( _( "Loading Footprint Libraries" ) );
1235
1236 auto preload =
1237 [this, aKiway]() -> void
1238 {
1239 std::shared_ptr<BACKGROUND_JOB_REPORTER> reporter =
1241
1243
1244 int elapsed = 0;
1245 bool aborted = false;
1246
1247 reporter->Report( _( "Loading Footprint Libraries" ) );
1248 adapter->AsyncLoad();
1249
1250 while( true )
1251 {
1252 if( m_libraryPreloadAbort.load() )
1253 {
1254 m_libraryPreloadAbort.store( false );
1255 aborted = true;
1256 break;
1257 }
1258
1259 std::this_thread::sleep_for( std::chrono::milliseconds( interval ) );
1260
1261 if( std::optional<float> loadStatus = adapter->AsyncLoadProgress() )
1262 {
1263 float progress = *loadStatus;
1264 reporter->SetCurrentProgress( progress );
1265
1266 if( progress >= 1 )
1267 break;
1268 }
1269 else
1270 {
1271 reporter->SetCurrentProgress( 1 );
1272 break;
1273 }
1274
1275 elapsed += interval;
1276
1277 if( elapsed > timeLimit )
1278 break;
1279 }
1280
1281 // AbortAsyncLoad() sets the adapter's worker abort flag and then blocks,
1282 // so workers exit at their next checkpoint. BlockUntilLoaded() alone just
1283 // waits for each future to complete naturally, which can hang indefinitely
1284 // if a worker is stuck on a stalled network or filesystem operation.
1285 if( aborted )
1286 adapter->AbortAsyncLoad();
1287 else
1288 adapter->BlockUntilLoaded();
1289
1290 // If aborted, skip operations that use the adapter since the project may have changed
1291 // and the adapter's project reference could be stale. This prevents use-after-free
1292 // crashes when switching projects during library preload.
1293 if( !aborted )
1294 {
1295 // Report library load errors from adapter
1297 }
1298 else
1299 {
1300 wxLogTrace( traceLibraries, "pcbnew PreloadLibraries: aborted, skipping footprint processing" );
1301 }
1302
1303 m_libraryPreloadAbort.store( false );
1306 m_libraryPreloadInProgress.store( false );
1307
1308 // Only send reload notifications if we weren't aborted
1309 if( !aborted )
1310 {
1311 std::string payload = "";
1312 aKiway->ExpressMail( FRAME_PCB_EDITOR, MAIL_RELOAD_LIB, payload, nullptr, true );
1313 aKiway->ExpressMail( FRAME_FOOTPRINT_EDITOR, MAIL_RELOAD_LIB, payload, nullptr, true );
1314 aKiway->ExpressMail( FRAME_CVPCB, MAIL_RELOAD_LIB, payload, nullptr, true );
1315 }
1316 };
1317
1318 std::future<void> preloadFuture = std::async( std::launch::async, preload );
1319 m_libraryPreloadReturn = std::move( preloadFuture );
1320}
1321
1322
1324{
1325 if( m_libraryPreloadInProgress.load() )
1326 m_libraryPreloadAbort.store( true );
1327}
1328
1329
1330void IFACE::CancelPreload( bool aBlock )
1331{
1332 if( m_libraryPreloadInProgress.load() )
1333 {
1334 m_libraryPreloadAbort.store( true );
1335
1336 if( aBlock )
1338 }
1339}
1340
1341
1343{
1344 wxCHECK_RET( aServer, "no API server provided" );
1345
1346 if( !m_apiHandlerFpLibs )
1347 {
1348 m_apiHandlerFpLibs = std::make_unique<API_HANDLER_FP_LIBRARIES>();
1349 aServer->RegisterHandler( m_apiHandlerFpLibs.get() );
1350 }
1351}
1352
1353
1355{
1357
1358 if( !adapter )
1359 return false;
1360
1361 adapter->AsyncLoad();
1362 return true;
1363}
const char * name
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
static std::list< TOOL_ACTION * > & GetActionList()
Return list of TOOL_ACTIONs.
static std::list< ACTION_TOOLBAR_CONTROL * > GetCustomControlList(FRAME_T aContext)
Get the list of custom controls that could be used on a particular frame type.
std::shared_ptr< BACKGROUND_JOB > Create(const wxString &aName)
Creates a background job with the given name.
void Remove(std::shared_ptr< BACKGROUND_JOB > job)
Removes the given background job from any lists and frees it.
static std::unique_ptr< BOARD > CreateEmptyBoard(PROJECT *aProject)
static std::unique_ptr< BOARD > Load(const wxString &aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, PROJECT *aProject, const OPTIONS &aOptions)
static CLI_PROGRESS_REPORTER & GetInstance()
static CLI_REPORTER & GetInstance()
Definition reporter.cpp:261
static bool IsOnStandardSocketPath()
static void AnnounceToPrimary(FRAME_T aFrameType)
The base frame for deriving all KiCad main window classes.
SNAP_INFERENCE_SETTINGS m_SnapInference
An interface to the global shared library manager that is schematic-specific and linked to one projec...
std::vector< FOOTPRINT * > GetFootprints(const wxString &aNickname, bool aBestEfforts=false)
Retrieves a list of footprints contained in a given loaded library.
FOOTPRINT * LoadFootprintWithOptionalNickname(const LIB_ID &aFootprintId, bool aKeepUUID)
Load a footprint having aFootprintId with possibly an empty nickname.
static FOOTPRINT_PREVIEW_PANEL * New(KIWAY *aKiway, wxWindow *aParent, UNITS_PROVIDER *aUnitsProvider)
Component library viewer main window.
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()
An simple container class that lets us dispatch output jobs to kifaces.
Definition job.h:184
void RegisterHandler(API_HANDLER *aHandler)
Adds a new request handler to the server.
void DeregisterHandler(API_HANDLER *aHandler)
A KIFACE implementation.
Definition kiface_base.h:35
KIFACE_BASE(const char *aKifaceName, KIWAY::FACE_T aId)
Definition kiface_base.h:63
void InitSettings(APP_SETTINGS_BASE *aSettings)
Definition kiface_base.h:93
void end_common()
Common things to do for a top program module, during OnKifaceEnd();.
APP_SETTINGS_BASE * KifaceSettings() const
Definition kiface_base.h:91
bool start_common(int aCtlBits)
Common things to do for a top program module, during OnKifaceStart().
int m_start_flags
flags provided in OnKifaceStart()
bool IsSingle() const
Is this KIFACE running under single_top?
static int Apply(const git_merge_driver_source *aSrc, const char **aPathOut, unsigned int *aModeOut, git_buf *aMergedOut)
libgit2 merge-driver apply callback shim.
static int Apply(const git_merge_driver_source *aSrc, const char **aPathOut, unsigned int *aModeOut, git_buf *aMergedOut)
A mix in class which holds the location of a wxWindow's KIWAY.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:340
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:388
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr, bool aFromOtherThread=false)
Send aPayload to aDestination from aSource.
Definition kiway.cpp:486
FACE_T
Known KIFACE implementations.
Definition kiway.h:346
@ FACE_PCB
pcbnew DSO
Definition kiway.h:348
virtual void CommonSettingsChanged(int aFlags=0)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition kiway.cpp:580
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition kiway.cpp:201
std::optional< float > AsyncLoadProgress() const
Returns async load progress between 0.0 and 1.0, or nullopt if load is not in progress.
std::vector< KI_ERROR > GetLibraryLoadErrors() const
Returns all library load errors as newline-separated strings for display.
void AbortAsyncLoad()
Aborts any async load in progress; blocks until fully done aborting.
std::vector< wxString > GetLibraryNames() const
Returns a list of library nicknames that are available (skips any that failed to load)
void AsyncLoad()
Loads all available libraries for this adapter type in the background.
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition lib_id.cpp:65
wxString GetUniStringLibId() const
Definition lib_id.h:144
MAGNETIC_SETTINGS m_MagneticItems
SNAP_INFERENCE_SETTINGS m_SnapInference
The main frame for Pcbnew.
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:52
static PCB_FILE_T FindPluginTypeFromBoardPath(const wxString &aFileName, int aCtl=0)
Return a plugin type given a path for a board file.
Container for data for KiCad programs.
Definition pgm_base.h:101
virtual BACKGROUND_JOBS_MONITOR & GetBackgroundJobMonitor() const
Definition pgm_base.h:129
void AddLibraryLoadMessages(const std::vector< KI_ERROR > &aMessages)
Add library load messages to all registered status bars.
void ClearLibraryLoadMessages()
Clear library load messages from all registered status bars.
KICAD_API_SERVER & GetApiServer()
Definition pgm_base.h:141
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:123
A progress reporter interface for use in multi-threaded environments.
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
Container for project specific data.
Definition project.h:63
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
T * RegisterSettings(T *aSettings, bool aLoadNow=true)
Take ownership of the pointer passed in.
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
PROJECT * GetProject(const wxString &aFullPath) const
Retrieve a loaded project by name.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
UNITS_PROVIDER(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits)
EDA_UNITS GetUserUnits() const
void SetUserUnits(EDA_UNITS aUnits)
This file is part of the common library.
#define _(s)
Abstract pattern-matching tool and implementations.
EDA_UNITS
Definition eda_units.h:44
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition frame_type.h:29
@ PANEL_PCB_GRIDS
Definition frame_type.h:102
@ FRAME_PCB_EDITOR
Definition frame_type.h:38
@ PANEL_3DV_TOOLBARS
Definition frame_type.h:113
@ FRAME_FOOTPRINT_VIEWER
Definition frame_type.h:41
@ PANEL_3DV_OPENGL
Definition frame_type.h:111
@ PANEL_FP_DEFAULT_GRAPHICS_VALUES
Definition frame_type.h:97
@ PANEL_PCB_TOOLBARS
Definition frame_type.h:106
@ PANEL_PCB_ORIGINS_AXES
Definition frame_type.h:108
@ FRAME_FOOTPRINT_WIZARD
Definition frame_type.h:42
@ PANEL_PCB_EDIT_OPTIONS
Definition frame_type.h:104
@ PANEL_FP_DISPLAY_OPTIONS
Definition frame_type.h:90
@ PANEL_PCB_COLORS
Definition frame_type.h:105
@ PANEL_FP_SNAPPING
Definition frame_type.h:92
@ PANEL_FP_USER_LAYER_NAMES
Definition frame_type.h:98
@ PANEL_3DV_RAYTRACING
Definition frame_type.h:112
@ DIALOG_PCB_LIBRARY_TABLE
Definition frame_type.h:133
@ FRAME_FOOTPRINT_PREVIEW
Definition frame_type.h:44
@ FRAME_FOOTPRINT_CHOOSER
Definition frame_type.h:40
@ PANEL_FP_GRIDS
Definition frame_type.h:91
@ PANEL_FP_ORIGINS_AXES
Definition frame_type.h:99
@ PANEL_PCB_DISPLAY_OPTS
Definition frame_type.h:101
@ DIALOG_CONFIGUREPATHS
Definition frame_type.h:130
@ PANEL_FP_COLORS
Definition frame_type.h:94
@ PANEL_FP_DEFAULT_FIELDS
Definition frame_type.h:96
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:39
@ FRAME_PCB_DISPLAY3D
Definition frame_type.h:43
@ PANEL_FP_EDIT_OPTIONS
Definition frame_type.h:93
@ PANEL_FP_TOOLBARS
Definition frame_type.h:95
@ PANEL_PCB_ACTION_PLUGINS
Definition frame_type.h:107
@ PANEL_3DV_DISPLAY_OPTIONS
Definition frame_type.h:110
@ FRAME_CVPCB
Definition frame_type.h:48
@ PANEL_PCB_SNAPPING
Definition frame_type.h:103
nlohmann::json json
Definition gerbview.cpp:50
void CopySexprFile(const wxString &aSrcPath, const wxString &aDestPath, std::function< bool(const std::string &token, wxString &value)> aCallback, wxString &aErrors)
Definition gestfich.cpp:370
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition gestfich.cpp:343
static const std::string ProjectFileExtension
static const std::string LegacyPcbFileExtension
static const std::string FootprintLibraryTableFileName
static const std::string BackupFileSuffix
static const std::string LegacyFootprintLibPathExtension
static const std::string FootprintAssignmentFileExtension
static const std::string KiCadFootprintFileExtension
static const std::string KiCadPcbFileExtension
const wxChar *const traceLibraries
Flag to enable library table and library manager tracing.
const wxChar *const traceApi
Flag to enable debug output related to the IPC API and its plugin system.
Definition api_utils.cpp:33
#define KIFACE_API
@ KIFACE_MERGE_DOCUMENT
int (*)( int aKind, const wxString& aAncestor, const wxString& aOurs, const wxString& aTheirs,...
Definition kiface_ids.h:45
@ KIFACE_FOOTPRINT_LIBRARY_ADAPTER
Definition kiface_ids.h:30
@ KIFACE_FILTER_FOOTPRINTS
Function pointer type: wxString (*)(const wxString& aFilterJson) Input JSON: {"pin_count": N,...
Definition kiface_ids.h:35
@ KIFACE_OPEN_DIFF_DIALOG
int (*)( int aKind, const wxString& aFileA, const wxString& aFileB, const wxString& aLabelA,...
Definition kiface_ids.h:52
#define KFCTL_CLI
Running as CLI app.
Definition kiway.h:176
#define KIFACE_GETTER
Definition kiway.h:110
#define KICTL_KICAD_ONLY
chosen file is from KiCad according to user
This file contains miscellaneous commonly used macros and functions.
@ MAIL_RELOAD_LIB
Definition mail_type.h:53
DOC_KIND
Document type a diff/merge entry point should route to, derived from a file path's extension.
bool RegisterMergeDriver(const char *aName, MERGE_APPLY_FN aApply)
Register a KiCad merge driver with libgit2.
PCB::IFACE KIFACE_BASE, UNITS_PROVIDER kiface("pcbnew", KIWAY::FACE_PCB)
static int pcbnewOpenDiffDialogExport(int aKind, const wxString &aFileA, const wxString &aFileB, const wxString &aLabelA, const wxString &aLabelB, wxWindow *aParent, REPORTER *aReporter)
Definition pcbnew.cpp:648
static int pcbnewMergeExport(int aKind, const wxString &aAncestor, const wxString &aOurs, const wxString &aTheirs, const wxString &aOutput, bool aInteractive, bool aSingleFile, REPORTER *aReporter)
Definition pcbnew.cpp:638
void InvokePcbLibTableEditor(KIWAY *aKiway, wxWindow *aCaller)
Function InvokePcbLibTableEditor shows the modal DIALOG_FP_LIB_TABLE for purposes of editing the glob...
PANEL_SNAPPING * CreateSnappingPanel(wxWindow *aParent, SETTINGS_T *aCfg, FRAME_T aFrameType, SNAP_INFERENCE_SETTINGS SETTINGS_T::*aInference=nullptr, MAGNETIC_SETTINGS SETTINGS_T::*aMagnetics=nullptr)
Build the snapping page for an editor.
static wxString filterFootprints(const wxString &aFilterJson)
Filter footprints based on criteria passed as JSON.
Definition pcbnew.cpp:111
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
Definition pcbnew.cpp:662
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
T * GetToolbarSettings(const wxString &aFilename)
T * GetAppSettings(const char *aFilename)
bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits, KIWAY *aKiway) override
Typically start_common() is called from here.
wxString path
File path (KIND::FILE_KIND) or project path (KIND::FPID_KIND).
Definition kiway.h:164
LIB_ID libId
Library identifier; valid when kind == KIND::FPID_KIND.
Definition kiway.h:165
Implement a participant in the KIWAY alchemy.
Definition kiway.h:153
std::atomic_bool m_libraryPreloadInProgress
Definition pcbnew.cpp:623
bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits, KIWAY *aKiway) override
Typically start_common() is called from here.
Definition pcbnew.cpp:673
void PreloadLibraries(KIWAY *aKiway) override
Definition pcbnew.cpp:1216
KIWAY * m_kiway
Definition pcbnew.cpp:628
void ProjectChanged() override
Definition pcbnew.cpp:1323
void SaveFileAs(const wxString &aProjectBasePath, const wxString &aSrcProjectName, const wxString &aNewProjectBasePath, const wxString &aNewProjectName, const wxString &aSrcFilePath, wxString &aErrors) override
Saving a file under a different name is delegated to the various KIFACEs because the project doesn't ...
Definition pcbnew.cpp:748
void CancelPreload(bool aBlock=true) override
Definition pcbnew.cpp:1330
void closeCurrentDocument(KICAD_API_SERVER *aServer)
Definition pcbnew.cpp:875
std::shared_ptr< BACKGROUND_JOB > m_libraryPreloadBackgroundJob
Definition pcbnew.cpp:621
void * IfaceOrAddress(int aDataId) override
Return a pointer to the requested object.
Definition pcbnew.cpp:535
void RegisterLibraryHandlers(KICAD_API_SERVER *aServer) override
Register this face's library API handlers on the given server.
Definition pcbnew.cpp:1342
void Reset() override
Reloads global state.
Definition pcbnew.cpp:724
std::unique_ptr< API_HANDLER_FOOTPRINT > m_openFpHandler
Definition pcbnew.cpp:632
wxWindow * CreateKiWindow(wxWindow *aParent, int aClassId, KIWAY *aKiway, int aCtlBits=0) override
Create a wxWindow for the current project.
Definition pcbnew.cpp:264
bool handleOpenFootprint(const wxString &aProjectPath, const wxString &aLibIdStr, KICAD_API_SERVER *aServer, wxString *aError)
Definition pcbnew.cpp:925
IFACE(const char *aName, KIWAY::FACE_T aType)
Definition pcbnew.cpp:253
std::unique_ptr< API_HANDLER_PCB > m_openHandler
Definition pcbnew.cpp:630
std::atomic_bool m_libraryPreloadAbort
Definition pcbnew.cpp:624
bool HandleApiCloseDocument(const wxString &aBoardFileName, KICAD_API_SERVER *aServer, wxString *aError) override
Definition pcbnew.cpp:1186
int HandleJob(JOB *aJob, REPORTER *aReporter, PROGRESS_REPORTER *aProgressReporter) override
Definition pcbnew.cpp:863
bool LoadAllLibraries() override
Starts a background load of all libraries of the type owned by this face.
Definition pcbnew.cpp:1354
std::shared_ptr< HEADLESS_FOOTPRINT_CONTEXT > m_openFpContext
Definition pcbnew.cpp:631
std::shared_ptr< HEADLESS_PCB_CONTEXT > m_openContext
Definition pcbnew.cpp:629
bool HandleApiOpenDocument(const DOCUMENT_SPEC &aSpec, KICAD_API_SERVER *aServer, wxString *aError) override
Definition pcbnew.cpp:903
PCBNEW_JOBS_HANDLER * JobHandler() const
Accessor for the non-job diff/merge exports (pcbnewMergeExport etc.).
Definition pcbnew.cpp:582
std::unique_ptr< API_HANDLER_FP_LIBRARIES > m_apiHandlerFpLibs
Definition pcbnew.cpp:633
std::unique_ptr< PCBNEW_JOBS_HANDLER > m_jobHandler
Definition pcbnew.cpp:620
bool HandleJobConfig(JOB *aJob, wxWindow *aParent) override
Definition pcbnew.cpp:869
bool handleCreatePcb(const wxString &aPath, KICAD_API_SERVER *aServer, wxString *aError)
Definition pcbnew.cpp:1108
bool handleOpenPcb(const wxString &aPath, KICAD_API_SERVER *aServer, wxString *aError)
Definition pcbnew.cpp:1003
void OnKifaceEnd() override
Called just once just before the DSO is to be unloaded.
Definition pcbnew.cpp:729
std::future< void > m_libraryPreloadReturn
Definition pcbnew.cpp:622
IbisParser parser & reporter
KIBIS top(path, &reporter)
VECTOR3I expected(15, 30, 45)
static const long long MM
#define ENVVARS_CHANGED
wxLogTrace helper definitions.
Definition of file extensions used in Kicad.