KiCad PCB EDA Suite
Loading...
Searching...
No Matches
eeschema.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) 2004 Jean-Pierre Charras, [email protected]
5 * Copyright (C) 2008 Wayne Stambaugh <[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, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
27#include <pgm_base.h>
28#include <kiface_base.h>
31#include <confirm.h>
32#include <gestfich.h>
33#include <eda_dde.h>
35#include "eeschema_helpers.h"
36#include <eeschema_settings.h>
37#include <sch_edit_frame.h>
39#include <symbol_edit_frame.h>
40#include <symbol_viewer_frame.h>
46#include <kiway.h>
47#include <project_sch.h>
48#include <richio.h>
51#include <sexpr/sexpr.h>
52#include <sexpr/sexpr_parser.h>
53#include <string_utils.h>
54#include <trace_helpers.h>
55#include <thread_pool.h>
56#include <kiface_ids.h>
57#include <widgets/kistatusbar.h>
59#include <wx/ffile.h>
60#include <wx/tokenzr.h>
62
63#include <schematic.h>
64#include <connection_graph.h>
75#include <sim/simulator_frame.h>
76
78#include <toolbars_sch_editor.h>
80
81#if defined( KICAD_IPC_API )
82#include <api/api_handler_sch.h>
83#include <api/api_server.h>
84#include <api/api_utils.h>
86#include <sch_io/sch_io.h>
87#include <sch_io/sch_io_mgr.h>
88#endif
89
90#include <wx/crt.h>
91
92// The main sheet of the project
94
95
96namespace SCH {
97
98
99// TODO: This should move out of this file
100static std::unique_ptr<SCHEMATIC> readSchematicFromFile( const std::string& aFilename )
101{
102 SCH_IO* pi = SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD );
103 std::unique_ptr<SCHEMATIC> schematic = std::make_unique<SCHEMATIC>( nullptr );
104
106
107 wxFileName pro( aFilename );
108 pro.SetExt( FILEEXT::ProjectFileExtension );
109 pro.MakeAbsolute();
110 wxString projectPath = pro.GetFullPath();
111
112 PROJECT* project = manager.GetProject( projectPath );
113
114 if( !project )
115 {
116 manager.LoadProject( projectPath, true );
117 project = manager.GetProject( projectPath );
118 }
119
120 schematic->Reset();
121 schematic->SetProject( project );
122 SCH_SHEET* rootSheet = pi->LoadSchematicFile( aFilename, schematic.get() );
123
124 if( !rootSheet )
125 return nullptr;
126
127 schematic->SetTopLevelSheets( { rootSheet } );
128
129 SCH_SCREENS screens( schematic->Root() );
130
131 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
132 screen->UpdateLocalLibSymbolLinks();
133
134 SCH_SHEET_LIST sheets = schematic->Hierarchy();
135
136 // Restore all of the loaded symbol instances from the root sheet screen.
137 sheets.UpdateSymbolInstanceData( schematic->RootScreen()->GetSymbolInstances() );
138
139 if( schematic->RootScreen()->GetFileFormatVersionAtLoad() < 20230221 )
140 {
141 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
142 screen->FixLegacyPowerSymbolMismatches();
143 }
144
145 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
146 screen->MigrateSimModels();
147
148 sheets.AnnotatePowerSymbols();
149
150 // NOTE: This is required for multi-unit symbols to be correct
151 for( SCH_SHEET_PATH& sheet : sheets )
152 sheet.UpdateAllScreenReferences();
153
154 // TODO: this must handle SchematicCleanup somehow. The original version didn't because
155 // it knew that QA test cases were saved in a clean state.
156
157 // TODO: does this need to handle PruneOrphanedSymbolInstances() and
158 // PruneOrphanedSheetInstances()?
159
160 schematic->ConnectionGraph()->Recalculate( sheets, true );
161
162 return schematic;
163}
164
165
166// TODO: This should move out of this file
167bool generateSchematicNetlist( const wxString& aFilename, std::string& aNetlist )
168{
169 std::unique_ptr<SCHEMATIC> schematic = readSchematicFromFile( aFilename.ToStdString() );
170 NETLIST_EXPORTER_KICAD exporter( schematic.get() );
171 STRING_FORMATTER formatter;
172
173 exporter.Format( &formatter, GNL_ALL | GNL_OPT_KICAD );
174 aNetlist = formatter.GetString();
175
176 return true;
177}
178
179
180static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
181{
182 // Of course all are virtual overloads, implementations of the KIFACE.
183
184 IFACE( const char* aName, KIWAY::FACE_T aType ) :
185 KIFACE_BASE( aName, aType ),
188 {}
189
190 bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits, KIWAY* aKiway ) override;
191
192 void Reset() override;
193
194 void OnKifaceEnd() override;
195
196 wxWindow* CreateKiWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway, int aCtlBits = 0 ) override
197 {
198 switch( aClassId )
199 {
200 case FRAME_SCH:
201 {
202 SCH_EDIT_FRAME* frame = new SCH_EDIT_FRAME( aKiway, aParent );
203
205
206 if( Kiface().IsSingle() )
207 {
208 // only run this under single_top, not under a project manager.
210 }
211
212 return frame;
213 }
214
216 return new SYMBOL_EDIT_FRAME( aKiway, aParent );
217
218 case FRAME_SIMULATOR:
219 {
220 try
221 {
222 SIMULATOR_FRAME* frame = new SIMULATOR_FRAME( aKiway, aParent );
223 return frame;
225 catch( const SIMULATOR_INIT_ERR& )
226 {
227 // catch the init err exception as we don't want it to bubble up
228 // its going to be some ngspice install issue but we don't want to log that
229 return nullptr;
230 }
231 }
232
233 case FRAME_SCH_VIEWER:
234 return new SYMBOL_VIEWER_FRAME( aKiway, aParent );
235
237 {
238 bool cancelled = false;
239 SYMBOL_CHOOSER_FRAME* chooser = new SYMBOL_CHOOSER_FRAME( aKiway, aParent, cancelled );
241 if( cancelled )
242 {
243 chooser->Destroy();
244 return nullptr;
246
247 return chooser;
248 }
249
251 InvokeSchEditSymbolLibTable( aKiway, aParent );
252 // Dialog has completed; nothing to return.
253 return nullptr;
254
256 InvokeEditDesignBlockLibTable( aKiway, aParent );
257 // Dialog has completed; nothing to return.
258 return nullptr;
261 return new PANEL_SYM_DISPLAY_OPTIONS( aParent, GetAppSettings<SYMBOL_EDITOR_SETTINGS>( "symbol_editor" ) );
262
268 if( !frame )
269 frame = aKiway->Player( FRAME_SCH_VIEWER, false );
270
271 if( !frame )
272 frame = aKiway->Player( FRAME_SCH, false );
273
274 if( frame )
275 SetUserUnits( frame->GetUserUnits() );
276
277 return new PANEL_GRID_SETTINGS( aParent, this, frame, cfg, FRAME_SCH_SYMBOL_EDITOR );
278 }
279
281 {
282 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
283
284 if( !frame )
285 frame = aKiway->Player( FRAME_SCH_VIEWER, false );
286
287 if( !frame )
288 frame = aKiway->Player( FRAME_SCH, false );
289
290 if( frame )
291 SetUserUnits( frame->GetUserUnits() );
292
293 return new PANEL_SYM_EDITING_OPTIONS( aParent, this, frame );
294 }
295
297 {
298 APP_SETTINGS_BASE* cfg = GetAppSettings<SYMBOL_EDITOR_SETTINGS>( "symbol_editor" );
299 TOOLBAR_SETTINGS* tb = GetToolbarSettings<SYMBOL_EDIT_TOOLBAR_SETTINGS>( "symbol_editor-toolbars" );
300
301 std::vector<TOOL_ACTION*> actions;
302 std::vector<ACTION_TOOLBAR_CONTROL*> controls;
303
304 for( TOOL_ACTION* action : ACTION_MANAGER::GetActionList() )
305 actions.push_back( action );
306
307 for( ACTION_TOOLBAR_CONTROL* control : ACTION_TOOLBAR::GetCustomControlList( FRAME_SCH_SYMBOL_EDITOR ) )
308 controls.push_back( control );
309
310 return new PANEL_TOOLBAR_CUSTOMIZATION( aParent, cfg, tb, FRAME_SCH_SYMBOL_EDITOR, actions, controls );
311 }
312
313 case PANEL_SYM_COLORS:
314 return new PANEL_SYM_COLOR_SETTINGS( aParent );
315
317 return new PANEL_EESCHEMA_DISPLAY_OPTIONS( aParent, GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) );
318
319 case PANEL_SCH_GRIDS:
320 {
321 EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
322 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_SCH, false );
323
324 if( !frame )
325 frame = aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
326
327 if( !frame )
328 frame = aKiway->Player( FRAME_SCH_VIEWER, false );
329
330 if( frame )
331 SetUserUnits( frame->GetUserUnits() );
332
333 return new PANEL_GRID_SETTINGS( aParent, this, frame, cfg, FRAME_SCH );
334 }
335
337 {
338 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_SCH, false );
339
340 if( !frame )
341 frame = aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
342
343 if( !frame )
344 frame = aKiway->Player( FRAME_SCH_VIEWER, false );
345
346 if( frame )
347 SetUserUnits( frame->GetUserUnits() );
348
349 return new PANEL_EESCHEMA_EDITING_OPTIONS( aParent, this, frame );
350 }
351
353 {
354 APP_SETTINGS_BASE* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
355 TOOLBAR_SETTINGS* tb = GetToolbarSettings<SCH_EDIT_TOOLBAR_SETTINGS>( "eeschema-toolbars" );
356
357 std::vector<TOOL_ACTION*> actions;
358 std::vector<ACTION_TOOLBAR_CONTROL*> controls;
359
360 for( TOOL_ACTION* action : ACTION_MANAGER::GetActionList() )
361 actions.push_back( action );
362
363 for( ACTION_TOOLBAR_CONTROL* control : ACTION_TOOLBAR::GetCustomControlList( FRAME_SCH ) )
364 controls.push_back( control );
365
366 return new PANEL_TOOLBAR_CUSTOMIZATION( aParent, cfg, tb, FRAME_SCH, actions, controls );
367 }
368
369 case PANEL_SCH_COLORS:
370 return new PANEL_EESCHEMA_COLOR_SETTINGS( aParent );
371
373 return new PANEL_TEMPLATE_FIELDNAMES( aParent, nullptr );
374
376 {
377 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_SCH, false );
378
379 if( !frame )
380 frame = aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
381
382 if( !frame )
383 frame = aKiway->Player( FRAME_SCH_VIEWER, false );
384
385 return new class PANEL_SCH_DATA_SOURCES( aParent, frame );
386 }
387
389 return new PANEL_SIMULATOR_PREFERENCES( aParent );
390
391 default:
392 return nullptr;
393 }
394 }
395
406 void* IfaceOrAddress( int aDataId ) override
407 {
408 switch( aDataId )
409 {
411 return (void*) generateSchematicNetlist;
412 }
413
414 return nullptr;
415 }
416
422 void SaveFileAs( const wxString& aProjectBasePath, const wxString& aProjectName,
423 const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
424 const wxString& aSrcFilePath, wxString& aErrors ) override;
425
426
427 int HandleJob( JOB* aJob, REPORTER* aReporter, PROGRESS_REPORTER* aProgressReporter ) override;
428
429 bool HandleJobConfig( JOB* aJob, wxWindow* aParent ) override;
430
431#if defined( KICAD_IPC_API )
432 bool HandleApiOpenDocument( const wxString& aPath,
433 KICAD_API_SERVER* aServer,
434 wxString* aError ) override;
435
436 bool HandleApiCloseDocument( const wxString& aSchFileName,
437 KICAD_API_SERVER* aServer,
438 wxString* aError ) override;
439#endif
440
441 void PreloadLibraries( KIWAY* aKiway ) override;
442 void CancelPreload( bool aBlock = true ) override;
443 void ProjectChanged() override;
444
445private:
446 std::unique_ptr<EESCHEMA_JOBS_HANDLER> m_jobHandler;
447 std::shared_ptr<BACKGROUND_JOB> m_libraryPreloadBackgroundJob;
448 std::future<void> m_libraryPreloadReturn;
450 std::atomic_bool m_libraryPreloadAbort;
451
452#if defined( KICAD_IPC_API )
453 void closeCurrentDocument( KICAD_API_SERVER* aServer );
454
455 KIWAY* m_kiway = nullptr;
456 SCHEMATIC* m_openSchematic = nullptr;
457 std::shared_ptr<HEADLESS_SCH_CONTEXT> m_openContext;
458 std::unique_ptr<API_HANDLER_SCH> m_openHandler;
459#endif
460
461} kiface( "eeschema", KIWAY::FACE_SCH );
462
463} // namespace
464
465using namespace SCH;
466
467
469
470
471// KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h.
472// KIFACE_GETTER will not have name mangling due to declaration in kiway.h.
473KIFACE_API KIFACE* KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram )
474{
475 return &kiface;
476}
477
478
479bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits, KIWAY* aKiway )
480{
481 // This is process-level-initialization, not project-level-initialization of the DSO.
482 // Do nothing in here pertinent to a project!
484
485 // Register the symbol editor settings as well because they share a KiFACE and need to be
486 // loaded prior to use to avoid threading deadlocks
488 aProgram->GetSettingsManager().RegisterSettings( symSettings ); // manager takes ownership
489
490 // We intentionally register KifaceSettings after SYMBOL_EDITOR_SETTINGS
491 // In legacy configs, many settings were in a single editor config nd the migration routine
492 // for the main editor file will try and call into the now separate settings stores
493 // to move the settings into them
495
496 start_common( aCtlBits );
497
498#if defined( KICAD_IPC_API )
499 m_kiway = aKiway;
500#endif
501
502 m_jobHandler = std::make_unique<EESCHEMA_JOBS_HANDLER>( aKiway );
503
505 {
506 m_jobHandler->SetReporter( &CLI_REPORTER::GetInstance() );
507 m_jobHandler->SetProgressReporter( &CLI_PROGRESS_REPORTER::GetInstance() );
508 }
509
510 return true;
511}
512
513
515{
516}
517
518
520{
521 constexpr static int interval = 150;
522 constexpr static int timeLimit = 120000;
523
524 wxCHECK( aKiway, /* void */ );
525
526 // Use compare_exchange to atomically check and set the flag to prevent race conditions
527 // when PreloadLibraries is called multiple times concurrently (e.g., from project manager
528 // and schematic editor both scheduling via CallAfter)
529 bool expected = false;
530
531 if( !m_libraryPreloadInProgress.compare_exchange_strong( expected, true ) )
532 return;
533
535
537 Pgm().GetBackgroundJobMonitor().Create( _( "Loading Symbol Libraries" ) );
538
539 auto preload =
540 [this, aKiway]() -> void
541 {
542 std::shared_ptr<BACKGROUND_JOB_REPORTER> reporter =
544
546
547 int elapsed = 0;
548
549 reporter->Report( _( "Loading Symbol Libraries" ) );
550 adapter->AsyncLoad();
551
552 while( true )
553 {
554 if( m_libraryPreloadAbort.load() )
555 {
556 m_libraryPreloadAbort.store( false );
557 break;
558 }
559
560 std::this_thread::sleep_for( std::chrono::milliseconds( interval ) );
561
562 if( std::optional<float> loadStatus = adapter->AsyncLoadProgress() )
563 {
564 float progress = *loadStatus;
565 reporter->SetCurrentProgress( progress );
566
567 if( progress >= 1 )
568 break;
569 }
570 else
571 {
572 reporter->SetCurrentProgress( 1 );
573 break;
574 }
575
576 elapsed += interval;
577
578 if( elapsed > timeLimit )
579 break;
580 }
581
582 adapter->BlockUntilLoaded();
583
584 // Collect library load errors for async reporting
585 wxString errors = adapter->GetLibraryLoadErrors();
586
587 wxLogTrace( traceLibraries, "eeschema PreloadLibraries: errors.IsEmpty()=%d, length=%zu",
588 errors.IsEmpty(), errors.length() );
589
590 std::vector<LOAD_MESSAGE> messages =
592
593 if( !messages.empty() )
594 {
595 wxLogTrace( traceLibraries, " -> collected %zu messages, calling AddLibraryLoadMessages",
596 messages.size() );
597 Pgm().AddLibraryLoadMessages( messages );
598 }
599 else
600 {
601 wxLogTrace( traceLibraries, " -> no errors from symbol libraries" );
602 }
603
606 m_libraryPreloadInProgress.store( false );
607
608 std::string payload = "";
609 aKiway->ExpressMail( FRAME_SCH, MAIL_RELOAD_LIB, payload, nullptr, true );
610 aKiway->ExpressMail( FRAME_SCH_SYMBOL_EDITOR, MAIL_RELOAD_LIB, payload, nullptr, true );
611 aKiway->ExpressMail( FRAME_SCH_VIEWER, MAIL_RELOAD_LIB, payload, nullptr, true );
612 };
613
615 m_libraryPreloadReturn = tp.submit_task( preload );
616}
617
618
619void IFACE::CancelPreload( bool aBlock )
620{
621 if( m_libraryPreloadInProgress.load() )
622 {
623 m_libraryPreloadAbort.store( true );
624
625 if( aBlock )
627 }
628}
629
630
632{
633 if( m_libraryPreloadInProgress.load() )
634 m_libraryPreloadAbort.store( true );
635}
636
637
639{
640 end_common();
641}
642
643
644void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aProjectName,
645 const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
646 const wxString& aSrcFilePath, wxString& aErrors )
647{
648 wxFileName destFile( aSrcFilePath );
649 wxString destPath = destFile.GetPathWithSep();
650 wxUniChar pathSep = wxFileName::GetPathSeparator();
651 wxString ext = destFile.GetExt();
652
653 if( destPath.StartsWith( aProjectBasePath + pathSep ) )
654 destPath.Replace( aProjectBasePath, aNewProjectBasePath, false );
655
656 destFile.SetPath( destPath );
657
662 {
663 if( destFile.GetName() == aProjectName )
664 {
665 destFile.SetName( aNewProjectName );
666 }
667 else if( destFile.GetName() == aNewProjectName )
668 {
669 wxString msg;
670
671 if( !aErrors.empty() )
672 aErrors += wxS( "\n" );
673
674 msg.Printf( _( "Cannot copy file '%s' as it will be overwritten by the new root "
675 "sheet file." ), destFile.GetFullPath() );
676 aErrors += msg;
677 return;
678 }
679
680 CopySexprFile( aSrcFilePath, destFile.GetFullPath(),
681 [&]( const std::string& token, wxString& value ) -> bool
682 {
683 if( token == "project" && value == aProjectName )
684 {
685 value = aNewProjectName;
686 return true;
687 }
688
689 return false;
690 },
691 aErrors );
692 }
694 {
695 // Symbols are not project-specific. Keep their source names.
696 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
697 }
701 {
702 if( destFile.GetName() == aProjectName + wxS( "-cache" ) )
703 destFile.SetName( aNewProjectName + wxS( "-cache" ) );
704
705 if( destFile.GetName() == aProjectName + wxS( "-rescue" ) )
706 destFile.SetName( aNewProjectName + wxS( "-rescue" ) );
707
708 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
709 }
710 else if( ext == FILEEXT::NetlistFileExtension )
711 {
712 if( destFile.GetName() == aProjectName )
713 destFile.SetName( aNewProjectName );
714
715 CopySexprFile( aSrcFilePath, destFile.GetFullPath(),
716 [&]( const std::string& token, wxString& value ) -> bool
717 {
718 if( token == "source" )
719 {
720 for( const wxString& extension : { wxString( wxT( ".sch" ) ), wxString( wxT( ".kicad_sch" ) ) } )
721 {
722 if( value == aProjectName + extension )
723 {
724 value = aNewProjectName + extension;
725 return true;
726 }
727 else if( value == aProjectBasePath + "/" + aProjectName + extension )
728 {
729 value = aNewProjectBasePath + "/" + aNewProjectName + extension;
730 return true;
731 }
732 else if( value.StartsWith( aProjectBasePath ) )
733 {
734 value.Replace( aProjectBasePath, aNewProjectBasePath, false );
735 return true;
736 }
737 }
738 }
739
740 return false;
741 },
742 aErrors );
743 }
744 else if( destFile.GetName() == FILEEXT::SymbolLibraryTableFileName )
745 {
746 wxFileName libTableFn( aSrcFilePath );
747 LIBRARY_TABLE libTable( libTableFn, LIBRARY_TABLE_SCOPE::PROJECT );
748 libTable.SetPath( destFile.GetFullPath() );
749 libTable.SetType( LIBRARY_TABLE_TYPE::SYMBOL );
750
751 for( LIBRARY_TABLE_ROW& row : libTable.Rows() )
752 {
753 wxString uri = row.URI();
754
755 uri.Replace( wxS( "/" ) + aProjectName + wxS( "-cache.lib" ),
756 wxS( "/" ) + aNewProjectName + wxS( "-cache.lib" ) );
757 uri.Replace( wxS( "/" ) + aProjectName + wxS( "-rescue.lib" ),
758 wxS( "/" ) + aNewProjectName + wxS( "-rescue.lib" ) );
759 uri.Replace( wxS( "/" ) + aProjectName + wxS( ".lib" ),
760 wxS( "/" ) + aNewProjectName + wxS( ".lib" ) );
761
762 row.SetURI( uri );
763 }
764
765 libTable.Save().map_error(
766 [&]( const LIBRARY_ERROR& aError )
767 {
768 wxString msg;
769
770 if( !aErrors.empty() )
771 aErrors += wxT( "\n" );
772
773 msg.Printf( _( "Cannot copy file '%s'." ), destFile.GetFullPath() );
774 aErrors += msg;
775 } );
776 }
777 else
778 {
779 wxFAIL_MSG( wxS( "Unexpected filetype for Eeschema::SaveFileAs()" ) );
780 }
781}
782
783
784int IFACE::HandleJob( JOB* aJob, REPORTER* aReporter, PROGRESS_REPORTER* aProgressReporter )
785{
786 return m_jobHandler->RunJob( aJob, aReporter, aProgressReporter );
787}
788
789
790bool IFACE::HandleJobConfig( JOB* aJob, wxWindow* aParent )
791{
792 return m_jobHandler->HandleJobConfig( aJob, aParent );
793}
794
795
796#if defined( KICAD_IPC_API )
797// TODO(JE) some of the below methods can probably be factored out and shared between sch/pcb
798void IFACE::closeCurrentDocument( KICAD_API_SERVER* aServer )
799{
800 if( m_openHandler )
801 {
802 if( aServer )
803 aServer->DeregisterHandler( m_openHandler.get() );
804
805 m_openHandler.reset();
806 }
807
808 m_openContext.reset();
809
810 delete m_openSchematic;
811 m_openSchematic = nullptr;
812}
813
814
815bool IFACE::HandleApiOpenDocument( const wxString& aPath, KICAD_API_SERVER* aServer,
816 wxString* aError )
817{
818 wxCHECK( aServer, false );
819
820 if( aPath.IsEmpty() )
821 {
822 if( aError )
823 *aError = wxS( "No path specified to open" );
824
825 return false;
826 }
827
828 wxFileName projectPath( aPath );
829
830 if( projectPath.GetExt() == FILEEXT::KiCadSchematicFileExtension )
831 projectPath.SetExt( FILEEXT::ProjectFileExtension );
832 else if( projectPath.GetExt() != FILEEXT::ProjectFileExtension )
833 projectPath.SetExt( FILEEXT::ProjectFileExtension );
834
835 projectPath.MakeAbsolute();
836
837 SETTINGS_MANAGER& settingsManager = Pgm().GetSettingsManager();
838
839 if( !settingsManager.LoadProject( projectPath.GetFullPath(), true ) )
840 {
841 wxLogTrace( traceApi, "Warning: no project file found for %s", aPath );
842 }
843
844 PROJECT* project = settingsManager.GetProject( projectPath.GetFullPath() );
845
846 if( !project )
847 {
848 if( aError )
849 *aError = wxString::Format( wxS( "Error loading project for %s" ), aPath );
850
851 return false;
852 }
853
854 wxFileName schPath( projectPath );
855 schPath.SetExt( FILEEXT::KiCadSchematicFileExtension );
856
857 if( !schPath.FileExists() )
858 {
859 if( aError )
860 *aError = wxString::Format( wxS( "File not found: %s" ), schPath.GetFullPath() );
861
862 return false;
863 }
864
865 SCHEMATIC* schematic = nullptr;
866
867 try
868 {
869 schematic = EESCHEMA_HELPERS::LoadSchematic( schPath.GetFullPath(), false, false, project );
870
871 if( !schematic )
872 {
873 if( aError )
874 *aError = wxS( "Failed to load schematic" );
875
876 return false;
877 }
878 }
879 catch( ... )
880 {
881 if( aError )
882 *aError = wxS( "Failed to load schematic" );
883
884 return false;
885 }
886
887 closeCurrentDocument( aServer );
888 m_openSchematic = schematic;
889
890 m_openContext = std::make_shared<HEADLESS_SCH_CONTEXT>( m_openSchematic, project, m_kiway );
891 m_openHandler = std::make_unique<API_HANDLER_SCH>( m_openContext );
892 aServer->RegisterHandler( m_openHandler.get() );
893
894 return true;
895}
896
897
898bool IFACE::HandleApiCloseDocument( const wxString& aSchFileName, KICAD_API_SERVER* aServer,
899 wxString* aError )
900{
901 wxCHECK( aServer, false );
902
903 if( !m_openContext )
904 {
905 if( aError )
906 *aError = wxS( "No document is currently open" );
907
908 return false;
909 }
910
911 if( !aSchFileName.IsEmpty() )
912 {
913 wxFileName currentSch( m_openContext->GetCurrentFileName() );
914
915 if( currentSch.GetFullName() != aSchFileName )
916 {
917 if( aError )
918 *aError = wxS( "Requested document does not match the open document" );
919
920 return false;
921 }
922 }
923
924 closeCurrentDocument( aServer );
925 return true;
926}
927#endif
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
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.
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
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 CLI_PROGRESS_REPORTER & GetInstance()
static CLI_REPORTER & GetInstance()
Definition reporter.cpp:134
The base frame for deriving all KiCad main window classes.
static void SetSchEditFrame(SCH_EDIT_FRAME *aSchEditFrame)
static SCHEMATIC * LoadSchematic(const wxString &aFileName, bool aSetActive, bool aForceDefaultProject, PROJECT *aProject=nullptr, bool aCalculateConnectivity=true)
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:39
KIFACE_BASE(const char *aKifaceName, KIWAY::FACE_T aId)
Definition kiface_base.h:67
void InitSettings(APP_SETTINGS_BASE *aSettings)
Definition kiface_base.h:97
void end_common()
Common things to do for a top program module, during OnKifaceEnd();.
APP_SETTINGS_BASE * KifaceSettings() const
Definition kiface_base.h:95
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?
void CreateServer(int service, bool local=true)
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:315
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:402
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:500
FACE_T
Known KIFACE implementations.
Definition kiway.h:321
@ FACE_SCH
eeschema DSO
Definition kiway.h:322
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition kiway.cpp:205
std::optional< float > AsyncLoadProgress() const
Returns async load progress between 0.0 and 1.0, or nullopt if load is not in progress.
wxString GetLibraryLoadErrors() const
Returns all library load errors as newline-separated strings for display.
void AsyncLoad()
Loads all available libraries for this adapter type in the background.
Generate the KiCad netlist format supported by Pcbnew.
void Format(OUTPUTFORMATTER *aOutputFormatter, int aCtl)
Output this s-expression netlist into aOutputFormatter.
Container for data for KiCad programs.
Definition pgm_base.h:108
virtual BACKGROUND_JOBS_MONITOR & GetBackgroundJobMonitor() const
Definition pgm_base.h:136
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:994
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:130
A progress reporter interface for use in multi-threaded environments.
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
Container for project specific data.
Definition project.h:66
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
Holds all the data relating to one schematic.
Definition schematic.h:89
Schematic editor (Eeschema) main window.
Base class that schematic file and library loading and saving plugins should derive from.
Definition sch_io.h:59
virtual SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr)
Load information from some input file format that this SCH_IO implementation knows about,...
Definition sch_io.cpp:67
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition sch_screen.h:749
SCH_SCREEN * GetNext()
SCH_SCREEN * GetFirst()
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void AnnotatePowerSymbols()
Silently annotate the not yet annotated power symbols of the entire hierarchy of the sheet path list.
void UpdateSymbolInstanceData(const std::vector< SCH_SYMBOL_INSTANCE > &aSymbolInstances)
Update all of the symbol instance information using aSymbolInstances.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
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.
The SIMULATOR_FRAME holds the main user-interface for running simulations.
Implement an OUTPUTFORMATTER to a memory buffer.
Definition richio.h:422
const std::string & GetString()
Definition richio.h:445
The symbol library editor main window.
An interface to the global shared library manager that is schematic-specific and linked to one projec...
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_SCH_PORT_SERVICE_NUMBER
Eeschema listens on this port for commands from Pcbnew.
Definition eda_dde.h:43
EDA_UNITS
Definition eda_units.h:48
SCH_SHEET * g_RootSheet
Definition eeschema.cpp:93
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
Definition eeschema.cpp:468
@ PANEL_SYM_EDIT_GRIDS
Definition frame_type.h:73
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:35
@ PANEL_SCH_FIELD_NAME_TEMPLATES
Definition frame_type.h:83
@ PANEL_SCH_TOOLBARS
Definition frame_type.h:82
@ FRAME_SCH_VIEWER
Definition frame_type.h:36
@ PANEL_SCH_DISP_OPTIONS
Definition frame_type.h:78
@ PANEL_SCH_SIMULATOR
Definition frame_type.h:84
@ FRAME_SCH
Definition frame_type.h:34
@ PANEL_SYM_TOOLBARS
Definition frame_type.h:76
@ FRAME_SIMULATOR
Definition frame_type.h:38
@ PANEL_SYM_EDIT_OPTIONS
Definition frame_type.h:74
@ PANEL_SCH_EDIT_OPTIONS
Definition frame_type.h:80
@ PANEL_SYM_DISP_OPTIONS
Definition frame_type.h:72
@ DIALOG_SCH_LIBRARY_TABLE
Definition frame_type.h:125
@ PANEL_SCH_DATA_SOURCES
Definition frame_type.h:85
@ PANEL_SYM_COLORS
Definition frame_type.h:75
@ PANEL_SCH_GRIDS
Definition frame_type.h:79
@ PANEL_SCH_COLORS
Definition frame_type.h:81
@ DIALOG_DESIGN_BLOCK_LIBRARY_TABLE
Definition frame_type.h:124
@ FRAME_SYMBOL_CHOOSER
Definition frame_type.h:37
void CopySexprFile(const wxString &aSrcPath, const wxString &aDestPath, std::function< bool(const std::string &token, wxString &value)> aCallback, wxString &aErrors)
Definition gestfich.cpp:320
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition gestfich.cpp:293
static const std::string LegacySchematicFileExtension
static const std::string NetlistFileExtension
static const std::string SymbolLibraryTableFileName
static const std::string ProjectFileExtension
static const std::string SchematicSymbolFileExtension
static const std::string KiCadSchematicFileExtension
static const std::string LegacySymbolLibFileExtension
static const std::string KiCadSymbolLibFileExtension
static const std::string BackupFileSuffix
static const std::string LegacySymbolDocumentFileExtension
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:27
#define KIFACE_API
@ KIFACE_NETLIST_SCHEMATIC
Definition kiface_ids.h:42
#define KFCTL_CLI
Running as CLI app.
Definition kiway.h:165
#define KIFACE_GETTER
Definition kiway.h:113
@ MAIL_RELOAD_LIB
Definition mail_type.h:57
static std::unique_ptr< SCHEMATIC > readSchematicFromFile(const std::string &aFilename)
Definition eeschema.cpp:100
SCH::IFACE KIFACE_BASE, UNITS_PROVIDER kiface("eeschema", KIWAY::FACE_SCH)
bool generateSchematicNetlist(const wxString &aFilename, std::string &aNetlist)
Definition eeschema.cpp:167
#define GNL_ALL
@ GNL_OPT_KICAD
void InvokeEditDesignBlockLibTable(KIWAY *aKiway, wxWindow *aParent)
void InvokeSchEditSymbolLibTable(KIWAY *aKiway, wxWindow *aParent)
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:156
virtual bool HandleApiCloseDocument(const wxString &aBoardFileName, KICAD_API_SERVER *aServer, wxString *aError)
Definition kiway.h:269
virtual bool HandleApiOpenDocument(const wxString &aPath, KICAD_API_SERVER *aServer, wxString *aError)
Definition kiway.h:259
std::future< void > m_libraryPreloadReturn
Definition eeschema.cpp:448
bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits, KIWAY *aKiway) override
Typically start_common() is called from here.
Definition eeschema.cpp:479
std::shared_ptr< BACKGROUND_JOB > m_libraryPreloadBackgroundJob
Definition eeschema.cpp:447
void PreloadLibraries(KIWAY *aKiway) override
Definition eeschema.cpp:519
void SaveFileAs(const wxString &aProjectBasePath, const wxString &aProjectName, 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 eeschema.cpp:644
void ProjectChanged() override
Definition eeschema.cpp:631
void CancelPreload(bool aBlock=true) override
Definition eeschema.cpp:619
wxWindow * CreateKiWindow(wxWindow *aParent, int aClassId, KIWAY *aKiway, int aCtlBits=0) override
Create a wxWindow for the current project.
Definition eeschema.cpp:196
std::atomic_bool m_libraryPreloadAbort
Definition eeschema.cpp:450
IFACE(const char *aName, KIWAY::FACE_T aType)
Definition eeschema.cpp:184
void Reset() override
Reloads global state.
Definition eeschema.cpp:514
void * IfaceOrAddress(int aDataId) override
Return a pointer to the requested object.
Definition eeschema.cpp:406
int HandleJob(JOB *aJob, REPORTER *aReporter, PROGRESS_REPORTER *aProgressReporter) override
Definition eeschema.cpp:784
std::unique_ptr< EESCHEMA_JOBS_HANDLER > m_jobHandler
Definition eeschema.cpp:446
std::atomic_bool m_libraryPreloadInProgress
Definition eeschema.cpp:449
bool HandleJobConfig(JOB *aJob, wxWindow *aParent) override
Definition eeschema.cpp:790
void OnKifaceEnd() override
Called just once just before the DSO is to be unloaded.
Definition eeschema.cpp:638
VECTOR3I expected(15, 30, 45)
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
static thread_pool * tp
BS::priority_thread_pool thread_pool
Definition thread_pool.h:31
wxLogTrace helper definitions.
Definition of file extensions used in Kicad.