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>
28#include <api/api_handler_pcb.h>
29#include <api/api_server.h>
30#include <api/api_utils.h>
33#include <kiface_base.h>
34#include <kiface_ids.h>
35#include <kiway_holder.h>
36#include <pcb_edit_frame.h>
37#include <eda_dde.h>
38#include <macros.h>
39#include <wx/snglinst.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>
73#include <project_pcb.h>
74#include <string_utils.h>
75#include <thread_pool.h>
76#include <trace_helpers.h>
77#include <widgets/kistatusbar.h>
78
79#include <wx/tokenzr.h>
80
81#include "invoke_pcb_dialog.h"
83#include "pcbnew_jobs_handler.h"
85#include <reporter.h>
86#include "git/kigit_pcb_merge.h"
87#include "git/kigit_fp_merge.h"
89
93#include <toolbars_pcb_editor.h>
94
95#include <wx/crt.h>
96
97
110static wxString filterFootprints( const wxString& aFilterJson )
111{
112 using json = nlohmann::json;
113
114 try
115 {
116 json input = json::parse( aFilterJson.ToStdString() );
117
118 int pinCount = input.value( "pin_count", 0 );
119 bool zeroFilters = input.value( "zero_filters", true );
120 int maxResults = input.value( "max_results", 400 );
121
122 std::vector<std::unique_ptr<EDA_PATTERN_MATCH>> filterMatchers;
123
124 if( input.contains( "filters" ) && input["filters"].is_array() )
125 {
126 for( const auto& f : input["filters"] )
127 {
128 if( f.is_string() )
129 {
130 wxString pattern = wxString::FromUTF8( f.get<std::string>() );
131 auto matcher = std::make_unique<EDA_PATTERN_MATCH_WILDCARD_ANCHORED>();
132 matcher->SetPattern( pattern.Lower() );
133 filterMatchers.push_back( std::move( matcher ) );
134 }
135 }
136 }
137
138 bool hasFilters = ( pinCount > 0 || !filterMatchers.empty() );
139
140 if( zeroFilters && !hasFilters )
141 return wxS( "[]" );
142
143 PROJECT* project = nullptr;
144
145 if( wxTheApp )
146 {
147 wxWindow* focus = wxWindow::FindFocus();
148 wxWindow* top = focus ? wxGetTopLevelParent( focus ) : wxTheApp->GetTopWindow();
149
150 if( top )
151 {
152 if( KIWAY_HOLDER* holder = dynamic_cast<KIWAY_HOLDER*>( top ) )
153 project = &holder->Prj();
154 }
155 }
156
157 if( !project )
159
161
162 if( !adapter )
163 return wxS( "[]" );
164
165 adapter->AsyncLoad();
166 adapter->BlockUntilLoaded();
167
168 // Iterate through preloaded footprints directly instead of re-reading from disk
169 json output = json::array();
170 int count = 0;
171
172 for( const wxString& nickname : adapter->GetLibraryNames() )
173 {
174 std::vector<FOOTPRINT*> footprints = adapter->GetFootprints( nickname, true );
175
176 for( FOOTPRINT* fp : footprints )
177 {
178 if( !fp )
179 continue;
180
181 // Pin count filter
182 if( pinCount > 0 )
183 {
184 int fpPadCount = fp->GetUniquePadCount( DO_NOT_INCLUDE_NPTH );
185
186 if( fpPadCount != pinCount )
187 continue;
188 }
189
190 // Footprint filter patterns with case-insensitive matching
191 if( !filterMatchers.empty() )
192 {
193 bool matches = false;
194
195 for( const auto& matcher : filterMatchers )
196 {
197 wxString name;
198
199 // If filter contains ':', include library nickname in match string
200 if( matcher->GetPattern().Contains( wxS( ":" ) ) )
201 name = fp->GetFPID().GetLibNickname().wx_str().Lower() + wxS( ":" );
202
203 name += fp->GetFPID().GetLibItemName().wx_str().Lower();
204
205 if( matcher->Find( name ) )
206 {
207 matches = true;
208 break;
209 }
210 }
211
212 if( !matches )
213 continue;
214 }
215
216 wxString libId = fp->GetFPID().Format();
217 output.push_back( libId.ToStdString() );
218
219 if( ++count >= maxResults )
220 break;
221 }
222
223 if( count >= maxResults )
224 break;
225 }
226
227 return wxString::FromUTF8( output.dump() );
228 }
229 catch( const std::exception& )
230 {
231 return wxS( "[]" );
232 }
233}
234
235
236namespace PCB {
237
238// Non-job kiface exports for diff/merge (returned by IfaceOrAddress). Defined
239// after the kiface instance so they can route into its jobs handler.
240static int pcbnewMergeExport( int aKind, const wxString& aAncestor, const wxString& aOurs,
241 const wxString& aTheirs, const wxString& aOutput, bool aInteractive,
242 bool aSingleFile, REPORTER* aReporter );
243static int pcbnewOpenDiffDialogExport( int aKind, const wxString& aFileA, const wxString& aFileB,
244 const wxString& aLabelA, const wxString& aLabelB,
245 wxWindow* aParent, REPORTER* aReporter );
246
247
248static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
249{
250 // Of course all are virtual overloads, implementations of the KIFACE.
251
252 IFACE( const char* aName, KIWAY::FACE_T aType ) :
253 KIFACE_BASE( aName, aType ),
255 {}
256
257 bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits, KIWAY* aKiway ) override;
258
259 void Reset() override;
260
261 void OnKifaceEnd() override;
262
263 wxWindow* CreateKiWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway, int aCtlBits = 0 ) override
264 {
265 switch( aClassId )
266 {
267 case FRAME_PCB_EDITOR:
268 {
269 auto frame = new PCB_EDIT_FRAME( aKiway, aParent );
270
271 if( Kiface().IsSingle() )
272 {
273 // only run this under single_top, not under a project manager.
274 frame->CreateServer( KICAD_PCB_PORT_SERVICE_NUMBER );
275 }
276
277 return frame;
278 }
279
281 return new FOOTPRINT_EDIT_FRAME( aKiway, aParent );
282
284 return new FOOTPRINT_VIEWER_FRAME( aKiway, aParent );
285
287 return new FOOTPRINT_CHOOSER_FRAME( aKiway, aParent );
288
290 return new FOOTPRINT_WIZARD_FRAME( aKiway, aParent, FRAME_T( aClassId ) );
291
293 return FOOTPRINT_PREVIEW_PANEL::New( aKiway, aParent, this );
294
296 {
297 DIALOG_CONFIGURE_PATHS dlg( aParent );
298
299 // The dialog's constructor probably failed to set its Kiway because the
300 // dynamic_cast fails when aParent was allocated by a separate compilation
301 // module. So set it directly.
302 dlg.SetKiway( &dlg, aKiway );
303
304 // Use QuasiModal so that HTML help window will work
305 if( dlg.ShowQuasiModal() == wxID_OK )
307
308 // Dialog has completed; nothing to return.
309 return nullptr;
310 }
311
313 InvokePcbLibTableEditor( aKiway, aParent );
314 // Dialog has completed; nothing to return.
315 return nullptr;
316
318 return new PANEL_DISPLAY_OPTIONS( aParent, GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" ) );
319
320 case PANEL_FP_GRIDS:
323 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
324
325 if( !frame )
326 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
327
328 if( !frame )
329 frame = aKiway->Player( FRAME_PCB_EDITOR, false );
330
331 if( frame )
333
334 return new PANEL_GRID_SETTINGS( aParent, this, frame, cfg, FRAME_FOOTPRINT_EDITOR );
335 }
342 {
343 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
345 if( !frame )
346 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
347
348 if( !frame )
349 frame = aKiway->Player( FRAME_PCB_EDITOR, false );
351 if( frame )
352 SetUserUnits( frame->GetUserUnits() );
353
354 return new PANEL_EDIT_OPTIONS( aParent, this, frame, true );
359 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
361 if( !frame )
362 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
364 if( !frame )
365 frame = aKiway->Player( FRAME_PCB_EDITOR, false );
367 if( frame )
368 SetUserUnits( frame->GetUserUnits() );
369
370 return new PANEL_FP_EDITOR_FIELD_DEFAULTS( aParent );
371 }
372
374 {
375 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
376
377 if( !frame )
378 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
379
380 if( !frame )
381 frame = aKiway->Player( FRAME_PCB_EDITOR, false );
382
383 if( frame )
384 SetUserUnits( frame->GetUserUnits() );
385
386 return new PANEL_FP_EDITOR_GRAPHICS_DEFAULTS( aParent, this );
387 }
388
390 return new class PANEL_FP_USER_LAYER_NAMES( aParent );
391
393 {
394 APP_SETTINGS_BASE* cfg = GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" );
395 TOOLBAR_SETTINGS* tb = GetToolbarSettings<FOOTPRINT_EDIT_TOOLBAR_SETTINGS>( "fpedit-toolbars" );
396
397 std::vector<TOOL_ACTION*> actions;
398 std::vector<ACTION_TOOLBAR_CONTROL*> controls;
399
400 for( TOOL_ACTION* action : ACTION_MANAGER::GetActionList() )
401 actions.push_back( action );
402
403 for( ACTION_TOOLBAR_CONTROL* control : ACTION_TOOLBAR::GetCustomControlList( FRAME_FOOTPRINT_EDITOR ) )
404 controls.push_back( control );
405
406 return new PANEL_TOOLBAR_CUSTOMIZATION( aParent, cfg, tb, FRAME_FOOTPRINT_EDITOR, actions, controls );
407 }
408
409 case PANEL_FP_COLORS:
410 return new PANEL_FP_EDITOR_COLOR_SETTINGS( aParent );
411
413 return new PANEL_DISPLAY_OPTIONS( aParent, GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" ) );
414
415 case PANEL_PCB_GRIDS:
416 {
417 PCBNEW_SETTINGS* cfg = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
418 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_PCB_EDITOR, false );
419
420 if( !frame )
421 frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
422
423 if( !frame )
424 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
425
426 if( frame )
427 SetUserUnits( frame->GetUserUnits() );
428
429 return new PANEL_GRID_SETTINGS( aParent, this, frame, cfg, FRAME_PCB_EDITOR );
430 }
431
433 return new PANEL_PCBNEW_DISPLAY_ORIGIN( aParent, GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" ),
435
437 {
438 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_PCB_EDITOR, false );
439
440 if( !frame )
441 frame = aKiway->Player( FRAME_FOOTPRINT_EDITOR, false );
442
443 if( !frame )
444 frame = aKiway->Player( FRAME_FOOTPRINT_VIEWER, false );
445
446 if( frame )
447 SetUserUnits( frame->GetUserUnits() );
448
449 return new PANEL_EDIT_OPTIONS( aParent, this, frame, false );
450 }
451
452 case PANEL_PCB_COLORS:
453 {
454 BOARD* board = nullptr;
455 EDA_BASE_FRAME* boardProvider = aKiway->Player( FRAME_PCB_EDITOR, false );
456
457 if( boardProvider )
458 board = static_cast<PCB_EDIT_FRAME*>( boardProvider )->GetBoard();
459
460 return new PANEL_PCBNEW_COLOR_SETTINGS( aParent, board );
461 }
462
464 {
465 APP_SETTINGS_BASE* cfg = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
466 TOOLBAR_SETTINGS* tb = GetToolbarSettings<PCB_EDIT_TOOLBAR_SETTINGS>( "pcbnew-toolbars" );
467
468 std::vector<TOOL_ACTION*> actions;
469 std::vector<ACTION_TOOLBAR_CONTROL*> controls;
470
471 for( TOOL_ACTION* action : ACTION_MANAGER::GetActionList() )
472 actions.push_back( action );
473
474 for( ACTION_TOOLBAR_CONTROL* control : ACTION_TOOLBAR::GetCustomControlList( FRAME_PCB_EDITOR ) )
475 controls.push_back( control );
476
477 return new PANEL_TOOLBAR_CUSTOMIZATION( aParent, cfg, tb, FRAME_PCB_EDITOR, actions, controls );
478 }
479
481 return new PANEL_PCBNEW_ACTION_PLUGINS( aParent );
482
484 return new PANEL_3D_DISPLAY_OPTIONS( aParent );
485
486 case PANEL_3DV_OPENGL:
487 return new PANEL_3D_OPENGL_OPTIONS( aParent );
488
490 return new PANEL_3D_RAYTRACING_OPTIONS( aParent );
491
493 {
494 APP_SETTINGS_BASE* cfg = GetAppSettings<EDA_3D_VIEWER_SETTINGS>( "3d_viewer" );
495 TOOLBAR_SETTINGS* tb = GetToolbarSettings<EDA_3D_VIEWER_TOOLBAR_SETTINGS>( "3d_viewer-toolbars" );
496
497 std::vector<TOOL_ACTION*> actions;
498 std::vector<ACTION_TOOLBAR_CONTROL*> controls;
499
500 for( TOOL_ACTION* action : ACTION_MANAGER::GetActionList() )
501 actions.push_back( action );
502
503 for( ACTION_TOOLBAR_CONTROL* control : ACTION_TOOLBAR::GetCustomControlList( FRAME_PCB_DISPLAY3D ) )
504 controls.push_back( control );
505
506 return new PANEL_TOOLBAR_CUSTOMIZATION( aParent, cfg, tb, FRAME_PCB_DISPLAY3D, actions, controls );
507 }
508
509 default:
510 return nullptr;
511 }
512 }
513
524 void* IfaceOrAddress( int aDataId ) override
525 {
526 switch( aDataId )
527 {
529 {
530 // This is the mechanism by which FOOTPRINT_SELECT_WIDGET can get access to the adapter
531 // without directly linking to pcbnew or pcbcommon, going through PROJECT::FootprintLibAdapter
532 PROJECT* project = nullptr;
533
534 if( wxTheApp )
535 {
536 wxWindow* focus = wxWindow::FindFocus();
537 wxWindow* top = focus ? wxGetTopLevelParent( focus ) : wxTheApp->GetTopWindow();
538
539 if( top )
540 {
541 if( KIWAY_HOLDER* holder = dynamic_cast<KIWAY_HOLDER*>( top ) )
542 project = &holder->Prj();
543 }
544 }
545
546 if( !project )
548
550 }
551
553 {
554 // Return function pointer for filtering footprints
555 // Signature: wxString (*)(const wxString& aFilterJson)
556 return reinterpret_cast<void*>( &filterFootprints );
557 }
558
560 return reinterpret_cast<void*>( &pcbnewMergeExport );
561
563 return reinterpret_cast<void*>( &pcbnewOpenDiffDialogExport );
564
565 default:
566 return nullptr;
567 }
568 }
569
571 PCBNEW_JOBS_HANDLER* JobHandler() const { return m_jobHandler.get(); }
572
578 void SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcProjectName,
579 const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
580 const wxString& aSrcFilePath, wxString& aErrors ) override;
581
582 int HandleJob( JOB* aJob, REPORTER* aReporter, PROGRESS_REPORTER* aProgressReporter ) override;
583
584 bool HandleJobConfig( JOB* aJob, wxWindow* aParent ) override;
585
586 bool HandleApiOpenDocument( const wxString& aPath,
587 KICAD_API_SERVER* aServer,
588 wxString* aError ) override;
589
590 bool HandleApiCloseDocument( const wxString& aBoardFileName,
591 KICAD_API_SERVER* aServer,
592 wxString* aError ) override;
593
594 bool handleOpenPcb( const wxString& aPath, KICAD_API_SERVER* aServer, wxString* aError );
595
596 bool handleOpenFootprint( const wxString& aProjectPath, const wxString& aLibIdStr, KICAD_API_SERVER* aServer,
597 wxString* aError );
598
599 void PreloadLibraries( KIWAY* aKiway ) override;
600 void ProjectChanged() override;
601 void CancelPreload( bool aBlock = true ) override;
602
603private:
604 std::unique_ptr<PCBNEW_JOBS_HANDLER> m_jobHandler;
605 std::shared_ptr<BACKGROUND_JOB> m_libraryPreloadBackgroundJob;
606 std::future<void> m_libraryPreloadReturn;
608 std::atomic_bool m_libraryPreloadAbort;
609
610 void closeCurrentDocument( KICAD_API_SERVER* aServer );
611
612 KIWAY* m_kiway = nullptr;
613 std::shared_ptr<HEADLESS_PCB_CONTEXT> m_openContext;
614 std::unique_ptr<API_HANDLER_PCB> m_openHandler;
615 std::shared_ptr<HEADLESS_FOOTPRINT_CONTEXT> m_openFpContext;
616 std::unique_ptr<API_HANDLER_FOOTPRINT> m_openFpHandler;
617
618} kiface( "pcbnew", KIWAY::FACE_PCB );
619
620
621int pcbnewMergeExport( int aKind, const wxString& aAncestor, const wxString& aOurs,
622 const wxString& aTheirs, const wxString& aOutput, bool aInteractive,
623 bool aSingleFile, REPORTER* aReporter )
624{
625 return kiface.JobHandler()->RunMerge( static_cast<KICAD_DIFF::DOC_KIND>( aKind ), aAncestor,
626 aOurs, aTheirs, aOutput, aInteractive, aSingleFile,
627 aReporter );
628}
629
630
631int pcbnewOpenDiffDialogExport( int aKind, const wxString& aFileA, const wxString& aFileB,
632 const wxString& aLabelA, const wxString& aLabelB,
633 wxWindow* aParent, REPORTER* aReporter )
634{
635 return kiface.JobHandler()->OpenDiffDialog( static_cast<KICAD_DIFF::DOC_KIND>( aKind ), aFileA,
636 aFileB, aLabelA, aLabelB, aParent, aReporter );
637}
638
639} // namespace
640
641
642using namespace PCB;
643
644
646
647
648// KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h.
649// KIFACE_GETTER will not have name mangling due to declaration in kiway.h.
650KIFACE_API KIFACE* KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram )
651{
652 return &kiface;
653}
654
655
656bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits, KIWAY* aKiway )
657{
658 // This is process-level-initialization, not project-level-initialization of the DSO.
659 // Do nothing in here pertinent to a project!
661
662 SETTINGS_MANAGER& mgr = aProgram->GetSettingsManager();
663
666
667 // We intentionally register KifaceSettings after FOOTPRINT_EDITOR_SETTINGS and EDA_3D_VIEWER_SETTINGS
668 // In legacy configs, many settings were in a single editor config and the migration routine
669 // for the main editor file will try and call into the now separate settings stores
670 // to move the settings into them
672
673 // Register the footprint editor settings as well because they share a KiFACE and need to be
674 // loaded prior to use to avoid threading deadlocks
676
677 start_common( aCtlBits );
678
679 m_kiway = aKiway;
680
681 m_jobHandler = std::make_unique<PCBNEW_JOBS_HANDLER>( aKiway );
682
684 {
685 m_jobHandler->SetReporter( &CLI_REPORTER::GetInstance() );
686 m_jobHandler->SetProgressReporter( &CLI_PROGRESS_REPORTER::GetInstance() );
687 }
688
689 // Register the PCB and footprint merge drivers with libgit2 so
690 // .gitattributes entries `merge=kicad-pcb` and `merge=kicad-fp` route
691 // through our 3-way merge pipeline. git_merge_driver_register is not
692 // thread-safe; this runs once at kiface init before any background work
693 // spawns. The registry is idempotent so re-loads of the kiface are safe.
696
697 return true;
698}
699
700
702{
703}
704
705
707{
708 end_common();
709}
710
711
712void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcProjectName,
713 const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
714 const wxString& aSrcFilePath, wxString& aErrors )
715{
716 wxFileName destFile( aSrcFilePath );
717 wxString destPath = destFile.GetPathWithSep();
718 wxUniChar pathSep = wxFileName::GetPathSeparator();
719 wxString ext = destFile.GetExt();
720
721 if( destPath.StartsWith( aProjectBasePath + pathSep ) )
722 destPath.Replace( aProjectBasePath, aNewProjectBasePath, false );
723
724 wxString srcProjectFootprintLib = pathSep + aSrcProjectName + wxT( ".pretty" ) + pathSep;
725 wxString newProjectFootprintLib = pathSep + aNewProjectName + wxT( ".pretty" ) + pathSep;
726
727 destPath.Replace( srcProjectFootprintLib, newProjectFootprintLib, true );
728
729 destFile.SetPath( destPath );
730
733 {
734 if( destFile.GetName() == aSrcProjectName )
735 destFile.SetName( aNewProjectName );
736
737 CopySexprFile( aSrcFilePath, destFile.GetFullPath(),
738 [&]( const std::string& token, wxString& value )
739 {
740 if( token == "sheetfile" )
741 {
742 for( const wxString extension : { wxT( ".sch" ), wxT( ".kicad_sch" ) } )
743 {
744 if( value == aSrcProjectName + extension )
745 {
746 value = aNewProjectName + extension;
747 return true;
748 }
749 else if( value == aProjectBasePath + "/" + aSrcProjectName + extension )
750 {
751 value = aNewProjectBasePath + "/" + aNewProjectName + extension;
752 return true;
753 }
754 else if( value.StartsWith( aProjectBasePath ) )
755 {
756 value.Replace( aProjectBasePath, aNewProjectBasePath, false );
757 return true;
758 }
759 }
760 }
761
762 return false;
763 },
764 aErrors );
765 }
766 else if( ext == FILEEXT::LegacyPcbFileExtension )
767 {
768 if( destFile.GetName() == aSrcProjectName )
769 destFile.SetName( aNewProjectName );
770
771 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
772 }
775 {
776 // Footprints are not project-specific. Keep their source names.
777 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
778 }
780 {
781 // TODO
782 }
783 else if( ext == wxT( "rpt" ) )
784 {
785 // DRC must be the "gold standard". Since we can't guarantee that there aren't
786 // any non-deterministic cases in the save-as algorithm, we don't want to certify
787 // the result with the source's DRC report. Therefore copy it under the old
788 // name.
789 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
790 }
791 else if( destFile.GetName() == FILEEXT::FootprintLibraryTableFileName )
792 {
793 wxFileName libTableFn( aSrcFilePath );
794 LIBRARY_TABLE libTable( libTableFn, LIBRARY_TABLE_SCOPE::PROJECT );
795 libTable.SetPath( destFile.GetFullPath() );
796 libTable.SetType( LIBRARY_TABLE_TYPE::FOOTPRINT );
797
798 for( LIBRARY_TABLE_ROW& row : libTable.Rows() )
799 {
800 wxString uri = row.URI();
801
802 uri.Replace( wxT( "/" ) + aSrcProjectName + wxT( ".pretty" ),
803 wxT( "/" ) + aNewProjectName + wxT( ".pretty" ) );
804
805 row.SetURI( uri );
806 }
807
808 libTable.Save().map_error(
809 [&]( const LIBRARY_ERROR& aError )
810 {
811 wxString msg;
812
813 if( !aErrors.empty() )
814 aErrors += wxT( "\n" );
815
816 msg.Printf( _( "Cannot copy file '%s'." ), destFile.GetFullPath() );
817 aErrors += msg;
818 } );
819 }
820 else
821 {
822 wxFAIL_MSG( wxT( "Unexpected filetype for Pcbnew::SaveFileAs()" ) );
823 }
824}
825
826
827int IFACE::HandleJob( JOB* aJob, REPORTER* aReporter, PROGRESS_REPORTER* aProgressReporter )
828{
829 return m_jobHandler->RunJob( aJob, aReporter, aProgressReporter );
830}
831
832
833bool IFACE::HandleJobConfig( JOB* aJob, wxWindow* aParent )
834{
835 return m_jobHandler->HandleJobConfig( aJob, aParent );
836}
837
838
840{
841 if( m_openHandler )
842 {
843 if( aServer )
844 aServer->DeregisterHandler( m_openHandler.get() );
845
846 m_openHandler.reset();
847 }
848
849 m_openContext.reset();
850
851 // The jobs handler caches the last-loaded board. Clear it so the next job
852 // uses the board from the newly opened document rather than a stale copy.
853 m_jobHandler->ClearCachedBoard();
854
855 if( m_openFpHandler )
856 {
857 if( aServer )
858 aServer->DeregisterHandler( m_openFpHandler.get() );
859
860 m_openFpHandler.reset();
861 }
862
863 m_openFpContext.reset();
864}
865
866
867bool IFACE::HandleApiOpenDocument( const wxString& aPath, KICAD_API_SERVER* aServer, wxString* aError )
868{
869 wxCHECK( aServer, false );
870
871 if( aPath.IsEmpty() )
872 {
873 if( aError )
874 *aError = wxS( "No path specified to open" );
875
876 return false;
877 }
878
879 return handleOpenPcb( aPath, aServer, aError );
880}
881
882
883bool IFACE::handleOpenFootprint( const wxString& aProjectPath, const wxString& aLibIdStr, KICAD_API_SERVER* aServer,
884 wxString* aError )
885{
886 LIB_ID fpid;
887
888 if( fpid.Parse( aLibIdStr ) >= 0 )
889 {
890 if( aError )
891 *aError = wxString::Format( wxS( "Invalid footprint LIB_ID: %s" ), aLibIdStr );
892
893 return false;
894 }
895
896 wxFileName projectPath( aProjectPath );
897 projectPath.MakeAbsolute();
898
899 SETTINGS_MANAGER& settingsManager = Pgm().GetSettingsManager();
900
901 if( !settingsManager.LoadProject( projectPath.GetFullPath(), true ) )
902 {
903 wxLogTrace( traceApi, "Warning: no project file found for %s", aProjectPath );
904 }
905
906 PROJECT* project = settingsManager.GetProject( projectPath.GetFullPath() );
907
908 if( !project )
909 {
910 if( aError )
911 *aError = wxString::Format( wxS( "Error loading project for %s" ), aProjectPath );
912
913 return false;
914 }
915
916 std::shared_ptr<HEADLESS_FOOTPRINT_CONTEXT> newContext;
917
918 try
919 {
921 adapter->AsyncLoad();
922 adapter->BlockUntilLoaded();
923 std::unique_ptr<FOOTPRINT> footprint( adapter->LoadFootprintWithOptionalNickname( fpid, true ) );
924
925 if( !footprint )
926 {
927 if( aError )
928 *aError = wxString::Format( wxS( "Footprint not found: %s" ), aLibIdStr );
929
930 return false;
931 }
932
933 newContext = std::make_shared<HEADLESS_FOOTPRINT_CONTEXT>(
934 std::move( footprint ), fpid, project, GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" ), m_kiway );
935 }
936 catch( ... )
937 {
938 if( aError )
939 *aError = wxString::Format( wxS( "Failed to load footprint: %s" ), aLibIdStr );
940
941 return false;
942 }
943
944 closeCurrentDocument( aServer );
945 m_openFpContext = std::move( newContext );
946
947 m_openFpHandler = std::make_unique<API_HANDLER_FOOTPRINT>( m_openFpContext, nullptr );
948 aServer->RegisterHandler( m_openFpHandler.get() );
949
950 return true;
951}
952
953
954bool IFACE::handleOpenPcb( const wxString& aPath, KICAD_API_SERVER* aServer, wxString* aError )
955{
956 wxFileName projectPath( aPath );
957
958 if( projectPath.GetExt() == FILEEXT::KiCadPcbFileExtension )
959 projectPath.SetExt( FILEEXT::ProjectFileExtension );
960 else if( projectPath.GetExt() != FILEEXT::ProjectFileExtension )
961 projectPath.SetExt( FILEEXT::ProjectFileExtension );
962
963 projectPath.MakeAbsolute();
964
965 // Close any existing document before loading a new project. LoadProject with
966 // aSetActive=true destroys the old PROJECT, which would leave the old board and
967 // context holding dangling m_project pointers.
968 closeCurrentDocument( aServer );
969
970 SETTINGS_MANAGER& settingsManager = Pgm().GetSettingsManager();
971
972 if( !settingsManager.LoadProject( projectPath.GetFullPath(), true ) )
973 {
974 wxLogTrace( traceApi, "Warning: no project file found for %s", aPath );
975 }
976
977 PROJECT* project = settingsManager.GetProject( projectPath.GetFullPath() );
978
979 if( !project )
980 {
981 if( aError )
982 *aError = wxString::Format( wxS( "Error loading project for %s" ), aPath );
983
984 return false;
985 }
986
987 wxFileName boardPath( projectPath );
988 boardPath.SetExt( FILEEXT::KiCadPcbFileExtension );
989
990 if( !boardPath.FileExists() )
991 {
992 if( aError )
993 *aError = wxString::Format( wxS( "File not found: %s" ), aPath );
994
995 return false;
996 }
997
998 PCB_IO_MGR::PCB_FILE_T pluginType =
1000
1001 if( pluginType == PCB_IO_MGR::FILE_TYPE_NONE )
1002 {
1003 if( aError )
1004 *aError = wxString::Format( wxS( "%s is not a recognized file type" ), aPath );
1005
1006 return false;
1007 }
1008
1009 std::shared_ptr<HEADLESS_PCB_CONTEXT> newContext;
1010
1011 try
1012 {
1013 std::unique_ptr<BOARD> loadedBoard = BOARD_LOADER::Load( boardPath.GetFullPath(), pluginType, project );
1014
1015 if( !loadedBoard )
1016 {
1017 if( aError )
1018 *aError = wxS( "Failed to load board" );
1019
1020 return false;
1021 }
1022
1023 newContext = std::make_shared<HEADLESS_PCB_CONTEXT>( std::move( loadedBoard ), project,
1025 }
1026 catch( const IO_ERROR& ioe )
1027 {
1028 if( aError )
1029 *aError = wxString::Format( wxS( "Failed to load board: %s" ), ioe.What() );
1030
1031 return false;
1032 }
1033 catch( ... )
1034 {
1035 if( aError )
1036 *aError = wxS( "Failed to load board" );
1037
1038 return false;
1039 }
1040
1041 m_openContext = std::move( newContext );
1042
1043 m_openHandler = std::make_unique<API_HANDLER_PCB>( m_openContext, nullptr );
1044 aServer->RegisterHandler( m_openHandler.get() );
1045
1046 return true;
1047}
1048
1049
1050bool IFACE::HandleApiCloseDocument( const wxString& aFileName, KICAD_API_SERVER* aServer, wxString* aError )
1051{
1052 wxCHECK( aServer, false );
1053
1055 {
1056 if( aError )
1057 *aError = wxS( "No document is currently open" );
1058
1059 return false;
1060 }
1061
1062 if( !aFileName.IsEmpty() && m_openContext )
1063 {
1064 wxFileName currentBoard( m_openContext->GetCurrentFileName() );
1065
1066 if( currentBoard.GetFullName() != aFileName )
1067 {
1068 if( aError )
1069 *aError = wxS( "Requested document does not match the open document" );
1070
1071 return false;
1072 }
1073 }
1074
1075 closeCurrentDocument( aServer );
1076 return true;
1077}
1078
1079
1081{
1082 constexpr static int interval = 150;
1083 constexpr static int timeLimit = 120000;
1084
1085 wxCHECK( aKiway, /* void */ );
1086
1087 // Use compare_exchange to atomically check and set the flag to prevent race conditions
1088 // when PreloadLibraries is called multiple times concurrently (e.g., from project manager
1089 // and pcb editor both scheduling via CallAfter)
1090 bool expected = false;
1091
1092 if( !m_libraryPreloadInProgress.compare_exchange_strong( expected, true ) )
1093 return;
1094
1096
1098 Pgm().GetBackgroundJobMonitor().Create( _( "Loading Footprint Libraries" ) );
1099
1100 auto preload =
1101 [this, aKiway]() -> void
1102 {
1103 std::shared_ptr<BACKGROUND_JOB_REPORTER> reporter =
1105
1107
1108 int elapsed = 0;
1109 bool aborted = false;
1110
1111 reporter->Report( _( "Loading Footprint Libraries" ) );
1112 adapter->AsyncLoad();
1113
1114 while( true )
1115 {
1116 if( m_libraryPreloadAbort.load() )
1117 {
1118 m_libraryPreloadAbort.store( false );
1119 aborted = true;
1120 break;
1121 }
1122
1123 std::this_thread::sleep_for( std::chrono::milliseconds( interval ) );
1124
1125 if( std::optional<float> loadStatus = adapter->AsyncLoadProgress() )
1126 {
1127 float progress = *loadStatus;
1128 reporter->SetCurrentProgress( progress );
1129
1130 if( progress >= 1 )
1131 break;
1132 }
1133 else
1134 {
1135 reporter->SetCurrentProgress( 1 );
1136 break;
1137 }
1138
1139 elapsed += interval;
1140
1141 if( elapsed > timeLimit )
1142 break;
1143 }
1144
1145 // AbortAsyncLoad() sets the adapter's worker abort flag and then blocks,
1146 // so workers exit at their next checkpoint. BlockUntilLoaded() alone just
1147 // waits for each future to complete naturally, which can hang indefinitely
1148 // if a worker is stuck on a stalled network or filesystem operation.
1149 if( aborted )
1150 adapter->AbortAsyncLoad();
1151 else
1152 adapter->BlockUntilLoaded();
1153
1154 // If aborted, skip operations that use the adapter since the project may have changed
1155 // and the adapter's project reference could be stale. This prevents use-after-free
1156 // crashes when switching projects during library preload.
1157 if( !aborted )
1158 {
1159 // Collect and report library load errors from adapter
1160 wxString errors = adapter->GetLibraryLoadErrors();
1161
1162 wxLogTrace( traceLibraries,
1163 "pcbnew PreloadLibraries: adapter errors.IsEmpty()=%d, length=%zu",
1164 errors.IsEmpty(), errors.length() );
1165
1166 if( !errors.IsEmpty() )
1167 {
1168 std::vector<LOAD_MESSAGE> messages =
1170
1171 wxLogTrace( traceLibraries, " -> adapter: collected %zu messages",
1172 messages.size() );
1173
1174 if( !messages.empty() )
1175 Pgm().AddLibraryLoadMessages( messages );
1176 }
1177 else
1178 {
1179 wxLogTrace( traceLibraries, " -> no errors from footprint adapter" );
1180 }
1181 }
1182 else
1183 {
1184 wxLogTrace( traceLibraries, "pcbnew PreloadLibraries: aborted, skipping footprint processing" );
1185 }
1186
1187 m_libraryPreloadAbort.store( false );
1190 m_libraryPreloadInProgress.store( false );
1191
1192 // Only send reload notifications if we weren't aborted
1193 if( !aborted )
1194 {
1195 std::string payload = "";
1196 aKiway->ExpressMail( FRAME_PCB_EDITOR, MAIL_RELOAD_LIB, payload, nullptr, true );
1197 aKiway->ExpressMail( FRAME_FOOTPRINT_EDITOR, MAIL_RELOAD_LIB, payload, nullptr, true );
1198 aKiway->ExpressMail( FRAME_CVPCB, MAIL_RELOAD_LIB, payload, nullptr, true );
1199 }
1200 };
1201
1202 std::future<void> preloadFuture = std::async( std::launch::async, preload );
1203 m_libraryPreloadReturn = std::move( preloadFuture );
1204}
1205
1206
1208{
1209 if( m_libraryPreloadInProgress.load() )
1210 m_libraryPreloadAbort.store( true );
1211}
1212
1213
1214void IFACE::CancelPreload( bool aBlock )
1215{
1216 if( m_libraryPreloadInProgress.load() )
1217 {
1218 m_libraryPreloadAbort.store( true );
1219
1220 if( aBlock )
1222 }
1223}
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 > 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:157
The base frame for deriving all KiCad main window classes.
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)
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:311
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:398
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:496
FACE_T
Known KIFACE implementations.
Definition kiway.h:317
@ FACE_PCB
pcbnew DSO
Definition kiway.h:319
virtual void CommonSettingsChanged(int aFlags=0)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition kiway.cpp:590
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.
void AbortAsyncLoad()
Aborts any async load in progress; blocks until fully done aborting.
wxString GetLibraryLoadErrors() const
Returns all library load errors as newline-separated strings for display.
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:48
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:102
virtual BACKGROUND_JOBS_MONITOR & GetBackgroundJobMonitor() const
Definition pgm_base.h:130
void ClearLibraryLoadMessages()
Clear library load messages from all registered status bars.
void AddLibraryLoadMessages(const std::vector< LOAD_MESSAGE > &aMessages)
Add library load messages to all registered status bars.
Definition pgm_base.cpp:990
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:124
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:62
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:71
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)
DDE server & client.
#define KICAD_PCB_PORT_SERVICE_NUMBER
Pcbnew listens on this port for commands from Eeschema.
Definition eda_dde.h:36
Abstract pattern-matching tool and implementations.
EDA_UNITS
Definition eda_units.h:44
@ DO_NOT_INCLUDE_NPTH
Definition footprint.h:72
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:99
@ FRAME_PCB_EDITOR
Definition frame_type.h:38
@ PANEL_3DV_TOOLBARS
Definition frame_type.h:109
@ FRAME_FOOTPRINT_VIEWER
Definition frame_type.h:41
@ PANEL_3DV_OPENGL
Definition frame_type.h:107
@ PANEL_FP_DEFAULT_GRAPHICS_VALUES
Definition frame_type.h:94
@ PANEL_PCB_TOOLBARS
Definition frame_type.h:102
@ PANEL_PCB_ORIGINS_AXES
Definition frame_type.h:104
@ FRAME_FOOTPRINT_WIZARD
Definition frame_type.h:42
@ PANEL_PCB_EDIT_OPTIONS
Definition frame_type.h:100
@ PANEL_FP_DISPLAY_OPTIONS
Definition frame_type.h:88
@ PANEL_PCB_COLORS
Definition frame_type.h:101
@ PANEL_FP_USER_LAYER_NAMES
Definition frame_type.h:95
@ PANEL_3DV_RAYTRACING
Definition frame_type.h:108
@ DIALOG_PCB_LIBRARY_TABLE
Definition frame_type.h:127
@ FRAME_FOOTPRINT_PREVIEW
Definition frame_type.h:44
@ FRAME_FOOTPRINT_CHOOSER
Definition frame_type.h:40
@ PANEL_FP_GRIDS
Definition frame_type.h:89
@ PANEL_FP_ORIGINS_AXES
Definition frame_type.h:96
@ PANEL_PCB_DISPLAY_OPTS
Definition frame_type.h:98
@ DIALOG_CONFIGUREPATHS
Definition frame_type.h:124
@ PANEL_FP_COLORS
Definition frame_type.h:91
@ PANEL_FP_DEFAULT_FIELDS
Definition frame_type.h:93
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:39
@ FRAME_PCB_DISPLAY3D
Definition frame_type.h:43
@ PANEL_FP_EDIT_OPTIONS
Definition frame_type.h:90
@ PANEL_FP_TOOLBARS
Definition frame_type.h:92
@ PANEL_PCB_ACTION_PLUGINS
Definition frame_type.h:103
@ PANEL_3DV_DISPLAY_OPTIONS
Definition frame_type.h:106
@ FRAME_CVPCB
Definition frame_type.h:48
nlohmann::json json
Definition gerbview.cpp:49
void CopySexprFile(const wxString &aSrcPath, const wxString &aDestPath, std::function< bool(const std::string &token, wxString &value)> aCallback, wxString &aErrors)
Definition gestfich.cpp:334
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition gestfich.cpp:307
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:29
#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:161
#define KIFACE_GETTER
Definition kiway.h:109
#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:54
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:631
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:621
void InvokePcbLibTableEditor(KIWAY *aKiway, wxWindow *aCaller)
Function InvokePcbLibTableEditor shows the modal DIALOG_FP_LIB_TABLE for purposes of editing the glob...
static wxString filterFootprints(const wxString &aFilterJson)
Filter footprints based on criteria passed as JSON.
Definition pcbnew.cpp:110
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
Definition pcbnew.cpp:645
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
@ RPT_SEVERITY_ERROR
T * GetToolbarSettings(const wxString &aFilename)
T * GetAppSettings(const char *aFilename)
std::vector< LOAD_MESSAGE > ExtractLibraryLoadErrors(const wxString &aErrorString, int aSeverity)
Parse library load error messages, extracting user-facing information while stripping internal code l...
bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits, KIWAY *aKiway) override
Typically start_common() is called from here.
Implement a participant in the KIWAY alchemy.
Definition kiway.h:152
std::atomic_bool m_libraryPreloadInProgress
Definition pcbnew.cpp:607
bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits, KIWAY *aKiway) override
Typically start_common() is called from here.
Definition pcbnew.cpp:656
void PreloadLibraries(KIWAY *aKiway) override
Definition pcbnew.cpp:1080
KIWAY * m_kiway
Definition pcbnew.cpp:612
void ProjectChanged() override
Definition pcbnew.cpp:1207
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:712
void CancelPreload(bool aBlock=true) override
Definition pcbnew.cpp:1214
void closeCurrentDocument(KICAD_API_SERVER *aServer)
Definition pcbnew.cpp:839
std::shared_ptr< BACKGROUND_JOB > m_libraryPreloadBackgroundJob
Definition pcbnew.cpp:605
void * IfaceOrAddress(int aDataId) override
Return a pointer to the requested object.
Definition pcbnew.cpp:524
void Reset() override
Reloads global state.
Definition pcbnew.cpp:701
std::unique_ptr< API_HANDLER_FOOTPRINT > m_openFpHandler
Definition pcbnew.cpp:616
wxWindow * CreateKiWindow(wxWindow *aParent, int aClassId, KIWAY *aKiway, int aCtlBits=0) override
Create a wxWindow for the current project.
Definition pcbnew.cpp:263
bool HandleApiOpenDocument(const wxString &aPath, KICAD_API_SERVER *aServer, wxString *aError) override
Definition pcbnew.cpp:867
bool handleOpenFootprint(const wxString &aProjectPath, const wxString &aLibIdStr, KICAD_API_SERVER *aServer, wxString *aError)
Definition pcbnew.cpp:883
IFACE(const char *aName, KIWAY::FACE_T aType)
Definition pcbnew.cpp:252
std::unique_ptr< API_HANDLER_PCB > m_openHandler
Definition pcbnew.cpp:614
std::atomic_bool m_libraryPreloadAbort
Definition pcbnew.cpp:608
bool HandleApiCloseDocument(const wxString &aBoardFileName, KICAD_API_SERVER *aServer, wxString *aError) override
Definition pcbnew.cpp:1050
int HandleJob(JOB *aJob, REPORTER *aReporter, PROGRESS_REPORTER *aProgressReporter) override
Definition pcbnew.cpp:827
std::shared_ptr< HEADLESS_FOOTPRINT_CONTEXT > m_openFpContext
Definition pcbnew.cpp:615
std::shared_ptr< HEADLESS_PCB_CONTEXT > m_openContext
Definition pcbnew.cpp:613
PCBNEW_JOBS_HANDLER * JobHandler() const
Accessor for the non-job diff/merge exports (pcbnewMergeExport etc.).
Definition pcbnew.cpp:571
std::unique_ptr< PCBNEW_JOBS_HANDLER > m_jobHandler
Definition pcbnew.cpp:604
bool HandleJobConfig(JOB *aJob, wxWindow *aParent) override
Definition pcbnew.cpp:833
bool handleOpenPcb(const wxString &aPath, KICAD_API_SERVER *aServer, wxString *aError)
Definition pcbnew.cpp:954
void OnKifaceEnd() override
Called just once just before the DSO is to be unloaded.
Definition pcbnew.cpp:706
std::future< void > m_libraryPreloadReturn
Definition pcbnew.cpp:606
IbisParser parser & reporter
KIBIS top(path, &reporter)
VECTOR3I expected(15, 30, 45)
static const long long MM
nlohmann::json output
#define ENVVARS_CHANGED
wxLogTrace helper definitions.
Definition of file extensions used in Kicad.