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
26#include <algorithm>
27
29#include <pgm_base.h>
30#include <kiface_base.h>
33#include <confirm.h>
34#include <gestfich.h>
35#include <eda_dde.h>
37#include "eeschema_helpers.h"
38#include <eeschema_settings.h>
39#include <sch_edit_frame.h>
41#include <symbol_edit_frame.h>
42#include <symbol_viewer_frame.h>
48#include <kiway.h>
49#include <project_sch.h>
50#include <richio.h>
53#include <sexpr/sexpr.h>
54#include <sexpr/sexpr_parser.h>
55#include <string_utils.h>
56#include <trace_helpers.h>
57#include <thread_pool.h>
58#include <kiface_ids.h>
59#include <widgets/kistatusbar.h>
61#include <wx/ffile.h>
62#include <wx/tokenzr.h>
64
65#include <schematic.h>
66#include <connection_graph.h>
77#include <sim/simulator_frame.h>
78
80#include <toolbars_sch_editor.h>
82
83#if defined( KICAD_IPC_API )
84#include <api/api_handler_sch.h>
85#include <api/api_server.h>
86#include <api/api_utils.h>
88#include <sch_io/sch_io.h>
89#include <sch_io/sch_io_mgr.h>
90#endif
91
92#include <wx/crt.h>
93
94// The main sheet of the project
96
97
98namespace SCH {
99
100
101// TODO: This should move out of this file
102static std::unique_ptr<SCHEMATIC> readSchematicFromFile( const std::string& aFilename )
103{
104 SCH_IO* pi = SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD );
105 std::unique_ptr<SCHEMATIC> schematic = std::make_unique<SCHEMATIC>( nullptr );
106
108
109 wxFileName pro( aFilename );
110 pro.SetExt( FILEEXT::ProjectFileExtension );
111 pro.MakeAbsolute();
112 wxString projectPath = pro.GetFullPath();
113
114 PROJECT* project = manager.GetProject( projectPath );
115
116 if( !project )
117 {
118 manager.LoadProject( projectPath, true );
119 project = manager.GetProject( projectPath );
120 }
121
122 schematic->Reset();
123 schematic->SetProject( project );
124 SCH_SHEET* rootSheet = pi->LoadSchematicFile( aFilename, schematic.get() );
125
126 if( !rootSheet )
127 return nullptr;
128
129 std::vector<SCH_SHEET*> topLevelSheets = schematic->GetTopLevelSheets();
130 bool rootIsTopLevel = std::find( topLevelSheets.begin(), topLevelSheets.end(), rootSheet )
131 != topLevelSheets.end();
132 bool rootIsVirtualRoot = rootSheet == &schematic->Root() || rootSheet->IsVirtualRootSheet();
133
134 if( !rootIsTopLevel && !rootIsVirtualRoot )
135 schematic->SetTopLevelSheets( { rootSheet } );
136
137 SCH_SCREENS screens( schematic->Root() );
138
139 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
140 screen->UpdateLocalLibSymbolLinks();
141
142 SCH_SHEET_LIST sheets = schematic->Hierarchy();
143
144 // Restore all of the loaded symbol instances from the root sheet screen.
145 sheets.UpdateSymbolInstanceData( schematic->RootScreen()->GetSymbolInstances() );
146
147 if( schematic->RootScreen()->GetFileFormatVersionAtLoad() < 20230221 )
148 {
149 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
150 screen->FixLegacyPowerSymbolMismatches();
151 }
152
153 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
154 screen->MigrateSimModels();
155
156 sheets.AnnotatePowerSymbols();
157
158 // NOTE: This is required for multi-unit symbols to be correct
159 for( SCH_SHEET_PATH& sheet : sheets )
160 sheet.UpdateAllScreenReferences();
161
162 // TODO: this must handle SchematicCleanup somehow. The original version didn't because
163 // it knew that QA test cases were saved in a clean state.
164
165 // TODO: does this need to handle PruneOrphanedSymbolInstances() and
166 // PruneOrphanedSheetInstances()?
167
168 schematic->ConnectionGraph()->Recalculate( sheets, true );
169
170 return schematic;
171}
172
173
174// TODO: This should move out of this file
175bool generateSchematicNetlist( const wxString& aFilename, std::string& aNetlist )
176{
177 std::unique_ptr<SCHEMATIC> schematic = readSchematicFromFile( aFilename.ToStdString() );
178 NETLIST_EXPORTER_KICAD exporter( schematic.get() );
179 STRING_FORMATTER formatter;
180
181 exporter.Format( &formatter, GNL_ALL | GNL_OPT_KICAD );
182 aNetlist = formatter.GetString();
183
184 return true;
185}
186
187
188static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
189{
190 // Of course all are virtual overloads, implementations of the KIFACE.
191
192 IFACE( const char* aName, KIWAY::FACE_T aType ) :
193 KIFACE_BASE( aName, aType ),
196 {}
197
198 bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits, KIWAY* aKiway ) override;
199
200 void Reset() override;
201
202 void OnKifaceEnd() override;
203
204 wxWindow* CreateKiWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway, int aCtlBits = 0 ) override
205 {
206 switch( aClassId )
207 {
208 case FRAME_SCH:
209 {
210 SCH_EDIT_FRAME* frame = new SCH_EDIT_FRAME( aKiway, aParent );
211
213
214 if( Kiface().IsSingle() )
215 {
216 // only run this under single_top, not under a project manager.
218 }
219
220 return frame;
221 }
222
224 return new SYMBOL_EDIT_FRAME( aKiway, aParent );
225
226 case FRAME_SIMULATOR:
227 {
228 try
229 {
230 SIMULATOR_FRAME* frame = new SIMULATOR_FRAME( aKiway, aParent );
231 return frame;
232 }
233 catch( const SIMULATOR_INIT_ERR& )
234 {
235 // catch the init err exception as we don't want it to bubble up
236 // its going to be some ngspice install issue but we don't want to log that
237 return nullptr;
238 }
239 }
241 case FRAME_SCH_VIEWER:
242 return new SYMBOL_VIEWER_FRAME( aKiway, aParent );
243
246 bool cancelled = false;
247 SYMBOL_CHOOSER_FRAME* chooser = new SYMBOL_CHOOSER_FRAME( aKiway, aParent, cancelled );
248
249 if( cancelled )
250 {
251 chooser->Destroy();
252 return nullptr;
253 }
254
255 return chooser;
256 }
257
259 InvokeSchEditSymbolLibTable( aKiway, aParent );
260 // Dialog has completed; nothing to return.
261 return nullptr;
262
265 // Dialog has completed; nothing to return.
266 return nullptr;
269 return new PANEL_SYM_DISPLAY_OPTIONS( aParent, GetAppSettings<SYMBOL_EDITOR_SETTINGS>( "symbol_editor" ) );
270
272 {
274 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
275
276 if( !frame )
277 frame = aKiway->Player( FRAME_SCH_VIEWER, false );
278
279 if( !frame )
280 frame = aKiway->Player( FRAME_SCH, false );
281
282 if( frame )
283 SetUserUnits( frame->GetUserUnits() );
284
285 return new PANEL_GRID_SETTINGS( aParent, this, frame, cfg, FRAME_SCH_SYMBOL_EDITOR );
286 }
287
289 {
290 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
291
292 if( !frame )
293 frame = aKiway->Player( FRAME_SCH_VIEWER, false );
294
295 if( !frame )
296 frame = aKiway->Player( FRAME_SCH, false );
297
298 if( frame )
299 SetUserUnits( frame->GetUserUnits() );
300
301 return new PANEL_SYM_EDITING_OPTIONS( aParent, this, frame );
302 }
303
305 {
306 APP_SETTINGS_BASE* cfg = GetAppSettings<SYMBOL_EDITOR_SETTINGS>( "symbol_editor" );
307 TOOLBAR_SETTINGS* tb = GetToolbarSettings<SYMBOL_EDIT_TOOLBAR_SETTINGS>( "symbol_editor-toolbars" );
308
309 std::vector<TOOL_ACTION*> actions;
310 std::vector<ACTION_TOOLBAR_CONTROL*> controls;
311
312 for( TOOL_ACTION* action : ACTION_MANAGER::GetActionList() )
313 actions.push_back( action );
314
315 for( ACTION_TOOLBAR_CONTROL* control : ACTION_TOOLBAR::GetCustomControlList( FRAME_SCH_SYMBOL_EDITOR ) )
316 controls.push_back( control );
317
318 return new PANEL_TOOLBAR_CUSTOMIZATION( aParent, cfg, tb, FRAME_SCH_SYMBOL_EDITOR, actions, controls );
319 }
320
321 case PANEL_SYM_COLORS:
322 return new PANEL_SYM_COLOR_SETTINGS( aParent );
323
325 return new PANEL_EESCHEMA_DISPLAY_OPTIONS( aParent, GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) );
326
327 case PANEL_SCH_GRIDS:
328 {
329 EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
330 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_SCH, false );
331
332 if( !frame )
333 frame = aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
334
335 if( !frame )
336 frame = aKiway->Player( FRAME_SCH_VIEWER, false );
337
338 if( frame )
339 SetUserUnits( frame->GetUserUnits() );
340
341 return new PANEL_GRID_SETTINGS( aParent, this, frame, cfg, FRAME_SCH );
342 }
343
345 {
346 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_SCH, false );
347
348 if( !frame )
349 frame = aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
350
351 if( !frame )
352 frame = aKiway->Player( FRAME_SCH_VIEWER, false );
353
354 if( frame )
355 SetUserUnits( frame->GetUserUnits() );
356
357 return new PANEL_EESCHEMA_EDITING_OPTIONS( aParent, this, frame );
358 }
359
361 {
362 APP_SETTINGS_BASE* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
363 TOOLBAR_SETTINGS* tb = GetToolbarSettings<SCH_EDIT_TOOLBAR_SETTINGS>( "eeschema-toolbars" );
364
365 std::vector<TOOL_ACTION*> actions;
366 std::vector<ACTION_TOOLBAR_CONTROL*> controls;
367
368 for( TOOL_ACTION* action : ACTION_MANAGER::GetActionList() )
369 actions.push_back( action );
370
371 for( ACTION_TOOLBAR_CONTROL* control : ACTION_TOOLBAR::GetCustomControlList( FRAME_SCH ) )
372 controls.push_back( control );
373
374 return new PANEL_TOOLBAR_CUSTOMIZATION( aParent, cfg, tb, FRAME_SCH, actions, controls );
375 }
376
377 case PANEL_SCH_COLORS:
378 return new PANEL_EESCHEMA_COLOR_SETTINGS( aParent );
379
381 return new PANEL_TEMPLATE_FIELDNAMES( aParent, nullptr );
382
384 {
385 EDA_BASE_FRAME* frame = aKiway->Player( FRAME_SCH, false );
386
387 if( !frame )
388 frame = aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
389
390 if( !frame )
391 frame = aKiway->Player( FRAME_SCH_VIEWER, false );
392
393 return new class PANEL_SCH_DATA_SOURCES( aParent, frame );
394 }
395
397 return new PANEL_SIMULATOR_PREFERENCES( aParent );
398
399 default:
400 return nullptr;
401 }
402 }
403
414 void* IfaceOrAddress( int aDataId ) override
415 {
416 switch( aDataId )
417 {
419 return (void*) generateSchematicNetlist;
420 }
421
422 return nullptr;
423 }
424
430 void SaveFileAs( const wxString& aProjectBasePath, const wxString& aProjectName,
431 const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
432 const wxString& aSrcFilePath, wxString& aErrors ) override;
433
434
435 int HandleJob( JOB* aJob, REPORTER* aReporter, PROGRESS_REPORTER* aProgressReporter ) override;
436
437 bool HandleJobConfig( JOB* aJob, wxWindow* aParent ) override;
438
439#if defined( KICAD_IPC_API )
440 bool HandleApiOpenDocument( const wxString& aPath,
441 KICAD_API_SERVER* aServer,
442 wxString* aError ) override;
443
444 bool HandleApiCloseDocument( const wxString& aSchFileName,
445 KICAD_API_SERVER* aServer,
446 wxString* aError ) override;
447#endif
448
449 void PreloadLibraries( KIWAY* aKiway ) override;
450 void CancelPreload( bool aBlock = true ) override;
451 void ProjectChanged() override;
452
453private:
454 std::unique_ptr<EESCHEMA_JOBS_HANDLER> m_jobHandler;
455 std::shared_ptr<BACKGROUND_JOB> m_libraryPreloadBackgroundJob;
456 std::future<void> m_libraryPreloadReturn;
458 std::atomic_bool m_libraryPreloadAbort;
459
460#if defined( KICAD_IPC_API )
461 void closeCurrentDocument( KICAD_API_SERVER* aServer );
462
463 KIWAY* m_kiway = nullptr;
464 SCHEMATIC* m_openSchematic = nullptr;
465 std::shared_ptr<HEADLESS_SCH_CONTEXT> m_openContext;
466 std::unique_ptr<API_HANDLER_SCH> m_openHandler;
467#endif
468
469} kiface( "eeschema", KIWAY::FACE_SCH );
470
471} // namespace
472
473using namespace SCH;
474
475
477
478
479// KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h.
480// KIFACE_GETTER will not have name mangling due to declaration in kiway.h.
481KIFACE_API KIFACE* KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram )
482{
483 return &kiface;
484}
485
486
487bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits, KIWAY* aKiway )
488{
489 // This is process-level-initialization, not project-level-initialization of the DSO.
490 // Do nothing in here pertinent to a project!
492
493 // Register the symbol editor settings as well because they share a KiFACE and need to be
494 // loaded prior to use to avoid threading deadlocks
496 aProgram->GetSettingsManager().RegisterSettings( symSettings ); // manager takes ownership
497
498 // We intentionally register KifaceSettings after SYMBOL_EDITOR_SETTINGS
499 // In legacy configs, many settings were in a single editor config nd the migration routine
500 // for the main editor file will try and call into the now separate settings stores
501 // to move the settings into them
503
504 start_common( aCtlBits );
505
506#if defined( KICAD_IPC_API )
507 m_kiway = aKiway;
508#endif
509
510 m_jobHandler = std::make_unique<EESCHEMA_JOBS_HANDLER>( aKiway );
511
513 {
514 m_jobHandler->SetReporter( &CLI_REPORTER::GetInstance() );
515 m_jobHandler->SetProgressReporter( &CLI_PROGRESS_REPORTER::GetInstance() );
516 }
517
518 return true;
519}
520
521
523{
524}
525
526
528{
529 constexpr static int interval = 150;
530 constexpr static int timeLimit = 120000;
531
532 wxCHECK( aKiway, /* void */ );
533
534 // Use compare_exchange to atomically check and set the flag to prevent race conditions
535 // when PreloadLibraries is called multiple times concurrently (e.g., from project manager
536 // and schematic editor both scheduling via CallAfter)
537 bool expected = false;
538
539 if( !m_libraryPreloadInProgress.compare_exchange_strong( expected, true ) )
540 return;
541
543
545 Pgm().GetBackgroundJobMonitor().Create( _( "Loading Symbol Libraries" ) );
546
547 auto preload =
548 [this, aKiway]() -> void
549 {
550 std::shared_ptr<BACKGROUND_JOB_REPORTER> reporter =
552
554
555 int elapsed = 0;
556
557 reporter->Report( _( "Loading Symbol Libraries" ) );
558 adapter->AsyncLoad();
559
560 while( true )
561 {
562 if( m_libraryPreloadAbort.load() )
563 {
564 m_libraryPreloadAbort.store( false );
565 break;
566 }
567
568 std::this_thread::sleep_for( std::chrono::milliseconds( interval ) );
569
570 if( std::optional<float> loadStatus = adapter->AsyncLoadProgress() )
571 {
572 float progress = *loadStatus;
573 reporter->SetCurrentProgress( progress );
574
575 if( progress >= 1 )
576 break;
577 }
578 else
579 {
580 reporter->SetCurrentProgress( 1 );
581 break;
582 }
583
584 elapsed += interval;
585
586 if( elapsed > timeLimit )
587 break;
588 }
589
590 adapter->BlockUntilLoaded();
591
592 // Collect library load errors for async reporting
593 wxString errors = adapter->GetLibraryLoadErrors();
594
595 wxLogTrace( traceLibraries, "eeschema PreloadLibraries: errors.IsEmpty()=%d, length=%zu",
596 errors.IsEmpty(), errors.length() );
597
598 std::vector<LOAD_MESSAGE> messages =
600
601 if( !messages.empty() )
602 {
603 wxLogTrace( traceLibraries, " -> collected %zu messages, calling AddLibraryLoadMessages",
604 messages.size() );
605 Pgm().AddLibraryLoadMessages( messages );
606 }
607 else
608 {
609 wxLogTrace( traceLibraries, " -> no errors from symbol libraries" );
610 }
611
614 m_libraryPreloadInProgress.store( false );
615
616 std::string payload = "";
617 aKiway->ExpressMail( FRAME_SCH, MAIL_RELOAD_LIB, payload, nullptr, true );
618 aKiway->ExpressMail( FRAME_SCH_SYMBOL_EDITOR, MAIL_RELOAD_LIB, payload, nullptr, true );
619 aKiway->ExpressMail( FRAME_SCH_VIEWER, MAIL_RELOAD_LIB, payload, nullptr, true );
620 };
621
622 std::future<void> preloadFuture = std::async( std::launch::async, preload );
623 m_libraryPreloadReturn = std::move( preloadFuture );
624}
625
626
627void IFACE::CancelPreload( bool aBlock )
628{
629 if( m_libraryPreloadInProgress.load() )
630 {
631 m_libraryPreloadAbort.store( true );
632
633 if( aBlock )
635 }
636}
637
638
640{
641 if( m_libraryPreloadInProgress.load() )
642 m_libraryPreloadAbort.store( true );
643}
644
645
647{
648 end_common();
649}
650
651
652void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aProjectName,
653 const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
654 const wxString& aSrcFilePath, wxString& aErrors )
655{
656 wxFileName destFile( aSrcFilePath );
657 wxString destPath = destFile.GetPathWithSep();
658 wxUniChar pathSep = wxFileName::GetPathSeparator();
659 wxString ext = destFile.GetExt();
660
661 if( destPath.StartsWith( aProjectBasePath + pathSep ) )
662 destPath.Replace( aProjectBasePath, aNewProjectBasePath, false );
663
664 destFile.SetPath( destPath );
665
670 {
671 if( destFile.GetName() == aProjectName )
672 {
673 destFile.SetName( aNewProjectName );
674 }
675 else if( destFile.GetName() == aNewProjectName )
676 {
677 wxString msg;
678
679 if( !aErrors.empty() )
680 aErrors += wxS( "\n" );
681
682 msg.Printf( _( "Cannot copy file '%s' as it will be overwritten by the new root "
683 "sheet file." ), destFile.GetFullPath() );
684 aErrors += msg;
685 return;
686 }
687
688 CopySexprFile( aSrcFilePath, destFile.GetFullPath(),
689 [&]( const std::string& token, wxString& value ) -> bool
690 {
691 if( token == "project" && value == aProjectName )
692 {
693 value = aNewProjectName;
694 return true;
695 }
696
697 return false;
698 },
699 aErrors );
700 }
702 {
703 // Symbols are not project-specific. Keep their source names.
704 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
705 }
709 {
710 if( destFile.GetName() == aProjectName + wxS( "-cache" ) )
711 destFile.SetName( aNewProjectName + wxS( "-cache" ) );
712
713 if( destFile.GetName() == aProjectName + wxS( "-rescue" ) )
714 destFile.SetName( aNewProjectName + wxS( "-rescue" ) );
715
716 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
717 }
718 else if( ext == FILEEXT::NetlistFileExtension )
719 {
720 if( destFile.GetName() == aProjectName )
721 destFile.SetName( aNewProjectName );
722
723 CopySexprFile( aSrcFilePath, destFile.GetFullPath(),
724 [&]( const std::string& token, wxString& value ) -> bool
725 {
726 if( token == "source" )
727 {
728 for( const wxString& extension : { wxString( wxT( ".sch" ) ), wxString( wxT( ".kicad_sch" ) ) } )
729 {
730 if( value == aProjectName + extension )
731 {
732 value = aNewProjectName + extension;
733 return true;
734 }
735 else if( value == aProjectBasePath + "/" + aProjectName + extension )
736 {
737 value = aNewProjectBasePath + "/" + aNewProjectName + extension;
738 return true;
739 }
740 else if( value.StartsWith( aProjectBasePath ) )
741 {
742 value.Replace( aProjectBasePath, aNewProjectBasePath, false );
743 return true;
744 }
745 }
746 }
747
748 return false;
749 },
750 aErrors );
751 }
752 else if( destFile.GetName() == FILEEXT::SymbolLibraryTableFileName )
753 {
754 wxFileName libTableFn( aSrcFilePath );
755 LIBRARY_TABLE libTable( libTableFn, LIBRARY_TABLE_SCOPE::PROJECT );
756 libTable.SetPath( destFile.GetFullPath() );
757 libTable.SetType( LIBRARY_TABLE_TYPE::SYMBOL );
758
759 for( LIBRARY_TABLE_ROW& row : libTable.Rows() )
760 {
761 wxString uri = row.URI();
762
763 uri.Replace( wxS( "/" ) + aProjectName + wxS( "-cache.lib" ),
764 wxS( "/" ) + aNewProjectName + wxS( "-cache.lib" ) );
765 uri.Replace( wxS( "/" ) + aProjectName + wxS( "-rescue.lib" ),
766 wxS( "/" ) + aNewProjectName + wxS( "-rescue.lib" ) );
767 uri.Replace( wxS( "/" ) + aProjectName + wxS( ".lib" ),
768 wxS( "/" ) + aNewProjectName + wxS( ".lib" ) );
769
770 row.SetURI( uri );
771 }
772
773 libTable.Save().map_error(
774 [&]( const LIBRARY_ERROR& aError )
775 {
776 wxString msg;
777
778 if( !aErrors.empty() )
779 aErrors += wxT( "\n" );
780
781 msg.Printf( _( "Cannot copy file '%s'." ), destFile.GetFullPath() );
782 aErrors += msg;
783 } );
784 }
785 else
786 {
787 wxFAIL_MSG( wxS( "Unexpected filetype for Eeschema::SaveFileAs()" ) );
788 }
789}
790
791
792int IFACE::HandleJob( JOB* aJob, REPORTER* aReporter, PROGRESS_REPORTER* aProgressReporter )
793{
794 return m_jobHandler->RunJob( aJob, aReporter, aProgressReporter );
795}
796
797
798bool IFACE::HandleJobConfig( JOB* aJob, wxWindow* aParent )
799{
800 return m_jobHandler->HandleJobConfig( aJob, aParent );
801}
802
803
804#if defined( KICAD_IPC_API )
805// TODO(JE) some of the below methods can probably be factored out and shared between sch/pcb
806void IFACE::closeCurrentDocument( KICAD_API_SERVER* aServer )
807{
808 if( m_openHandler )
809 {
810 if( aServer )
811 aServer->DeregisterHandler( m_openHandler.get() );
812
813 m_openHandler.reset();
814 }
815
816 m_openContext.reset();
817
818 delete m_openSchematic;
819 m_openSchematic = nullptr;
820
821 // The jobs handler caches the last-loaded schematic. Clear it so the next job
822 // uses the schematic from the newly opened document rather than a stale copy.
823 m_jobHandler->ClearCachedSchematic();
824}
825
826
827bool IFACE::HandleApiOpenDocument( const wxString& aPath, KICAD_API_SERVER* aServer,
828 wxString* aError )
829{
830 wxCHECK( aServer, false );
831
832 if( aPath.IsEmpty() )
833 {
834 if( aError )
835 *aError = wxS( "No path specified to open" );
836
837 return false;
838 }
839
840 wxFileName projectPath( aPath );
841
842 if( projectPath.GetExt() == FILEEXT::KiCadSchematicFileExtension )
843 projectPath.SetExt( FILEEXT::ProjectFileExtension );
844 else if( projectPath.GetExt() != FILEEXT::ProjectFileExtension )
845 projectPath.SetExt( FILEEXT::ProjectFileExtension );
846
847 projectPath.MakeAbsolute();
848
849 // Close any existing document before loading a new project. LoadProject with
850 // aSetActive=true destroys the old PROJECT, which would leave the old schematic
851 // and context holding dangling project pointers.
852 closeCurrentDocument( aServer );
853
854 SETTINGS_MANAGER& settingsManager = Pgm().GetSettingsManager();
855
856 if( !settingsManager.LoadProject( projectPath.GetFullPath(), true ) )
857 {
858 wxLogTrace( traceApi, "Warning: no project file found for %s", aPath );
859 }
860
861 PROJECT* project = settingsManager.GetProject( projectPath.GetFullPath() );
862
863 if( !project )
864 {
865 if( aError )
866 *aError = wxString::Format( wxS( "Error loading project for %s" ), aPath );
867
868 return false;
869 }
870
871 wxFileName schPath( projectPath );
872 schPath.SetExt( FILEEXT::KiCadSchematicFileExtension );
873
874 if( !schPath.FileExists() )
875 {
876 if( aError )
877 *aError = wxString::Format( wxS( "File not found: %s" ), schPath.GetFullPath() );
878
879 return false;
880 }
881
882 SCHEMATIC* schematic = nullptr;
883
884 try
885 {
886 schematic = EESCHEMA_HELPERS::LoadSchematic( schPath.GetFullPath(), false, false, project );
887
888 if( !schematic )
889 {
890 if( aError )
891 *aError = wxS( "Failed to load schematic" );
892
893 return false;
894 }
895 }
896 catch( ... )
897 {
898 if( aError )
899 *aError = wxS( "Failed to load schematic" );
900
901 return false;
902 }
903
904 m_openSchematic = schematic;
905
906 m_openContext = std::make_shared<HEADLESS_SCH_CONTEXT>( m_openSchematic, project, m_kiway );
907 m_openHandler = std::make_unique<API_HANDLER_SCH>( m_openContext );
908 aServer->RegisterHandler( m_openHandler.get() );
909
910 return true;
911}
912
913
914bool IFACE::HandleApiCloseDocument( const wxString& aSchFileName, KICAD_API_SERVER* aServer,
915 wxString* aError )
916{
917 wxCHECK( aServer, false );
918
919 if( !m_openContext )
920 {
921 if( aError )
922 *aError = wxS( "No document is currently open" );
923
924 return false;
925 }
926
927 if( !aSchFileName.IsEmpty() )
928 {
929 wxFileName currentSch( m_openContext->GetCurrentFileName() );
930
931 if( currentSch.GetFullName() != aSchFileName )
932 {
933 if( aError )
934 *aError = wxS( "Requested document does not match the open document" );
935
936 return false;
937 }
938 }
939
940 closeCurrentDocument( aServer );
941 return true;
942}
943#endif
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:127
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:161
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.
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:75
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:750
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
bool IsVirtualRootSheet() const
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
Symbol library viewer main window.
The symbol library editor main window.
An interface to the global shared library manager that is schematic-specific and linked to one projec...
Symbol library viewer main window.
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
std::unique_ptr< EESCHEMA_JOBS_HANDLER > m_jobHandler
Definition eeschema.cpp:264
SCH_SHEET * g_RootSheet
Definition eeschema.cpp:95
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
Definition eeschema.cpp:476
@ 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:338
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition gestfich.cpp:311
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:29
#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:58
static std::unique_ptr< SCHEMATIC > readSchematicFromFile(const std::string &aFilename)
Definition eeschema.cpp:102
SCH::IFACE KIFACE_BASE, UNITS_PROVIDER kiface("eeschema", KIWAY::FACE_SCH)
bool generateSchematicNetlist(const wxString &aFilename, std::string &aNetlist)
Definition eeschema.cpp:175
#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:456
bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits, KIWAY *aKiway) override
Typically start_common() is called from here.
Definition eeschema.cpp:487
std::shared_ptr< BACKGROUND_JOB > m_libraryPreloadBackgroundJob
Definition eeschema.cpp:455
void PreloadLibraries(KIWAY *aKiway) override
Definition eeschema.cpp:527
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:652
void ProjectChanged() override
Definition eeschema.cpp:639
void CancelPreload(bool aBlock=true) override
Definition eeschema.cpp:627
wxWindow * CreateKiWindow(wxWindow *aParent, int aClassId, KIWAY *aKiway, int aCtlBits=0) override
Create a wxWindow for the current project.
Definition eeschema.cpp:204
std::atomic_bool m_libraryPreloadAbort
Definition eeschema.cpp:458
IFACE(const char *aName, KIWAY::FACE_T aType)
Definition eeschema.cpp:192
void Reset() override
Reloads global state.
Definition eeschema.cpp:522
void * IfaceOrAddress(int aDataId) override
Return a pointer to the requested object.
Definition eeschema.cpp:414
int HandleJob(JOB *aJob, REPORTER *aReporter, PROGRESS_REPORTER *aProgressReporter) override
Definition eeschema.cpp:792
std::unique_ptr< EESCHEMA_JOBS_HANDLER > m_jobHandler
Definition eeschema.cpp:454
std::atomic_bool m_libraryPreloadInProgress
Definition eeschema.cpp:457
bool HandleJobConfig(JOB *aJob, wxWindow *aParent) override
Definition eeschema.cpp:798
void OnKifaceEnd() override
Called just once just before the DSO is to be unloaded.
Definition eeschema.cpp:646
IbisParser parser & reporter
VECTOR3I expected(15, 30, 45)
static const long long MM
wxLogTrace helper definitions.
Definition of file extensions used in Kicad.