KiCad PCB EDA Suite
Loading...
Searching...
No Matches
kiway.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2014 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <cstring>
22
23#include <app_monitor.h>
24#include <core/ignore.h>
25#include <macros.h>
26#include <kiway.h>
27#include <kiway_player.h>
28#include <kiway_mail.h>
29#include <paths.h>
30#include <pgm_base.h>
31#include <config.h>
32#include <id.h>
33#include <kiplatform/app.h>
36#include <tool/action_manager.h>
37#include <logging.h>
38#include <local_history.h>
39
40#include <wx/dynlib.h>
41#include <wx/stdpaths.h>
42#include <wx/debug.h>
43#include <wx/utils.h>
44#include <confirm.h>
45
46std::array<KIFACE*, KIWAY::FACE_T::KIWAY_FACE_COUNT> KIWAY::m_kiface;
47std::array<int, KIWAY::FACE_T::KIWAY_FACE_COUNT> KIWAY::m_kiface_version;
48
49
50
51KIWAY::KIWAY( int aCtlBits, wxFrame* aTop ):
52 m_ctl( aCtlBits ), m_top( nullptr ), m_blockingDialog( wxID_NONE ), m_local_history( nullptr )
53{
55 SetTop( aTop ); // hook player_destroy_handler() into aTop.
56
57 // Set the array of all known frame window IDs to empty = wxID_NONE,
58 // once they are be created, they are added with FRAME_T as index to this array.
59 // Note: A non empty entry does not mean the frame still exists.
60 // It means only the frame was created at least once. It can be destroyed after.
61 // These entries are not cleared automatically on window closing. The purpose is just
62 // to allow a call to wxWindow::FindWindowById() using a FRAME_T frame type
63 for( int n = 0; n < KIWAY_PLAYER_COUNT; n++ )
64 m_playerFrameId[n] = wxID_NONE;
65}
66
67
69{
70 delete m_local_history;
71}
72
73
74#if 0
75// Any event types derived from wxCommandEvt, like wxWindowDestroyEvent, are
76// propagated upwards to parent windows if not handled below. Therefore the
77// m_top window should receive all wxWindowDestroyEvents originating from
78// KIWAY_PLAYERs. It does anyways, but now player_destroy_handler eavesdrops
79// on that event stream looking for KIWAY_PLAYERs being closed.
80
81void KIWAY::player_destroy_handler( wxWindowDestroyEvent& event )
82{
83 // Currently : do nothing
84 event.Skip(); // skip to who, the wxApp? I'm the top window.
85}
86#endif
87
88
89void KIWAY::SetTop( wxFrame* aTop )
90{
91#if 0
92 if( m_top )
93 {
94 m_top->Disconnect( wxEVT_DESTROY,
95 wxWindowDestroyEventHandler( KIWAY::player_destroy_handler ),
96 nullptr, this );
97 }
98
99 if( aTop )
100 {
101 aTop->Connect( wxEVT_DESTROY,
102 wxWindowDestroyEventHandler( KIWAY::player_destroy_handler ),
103 nullptr, this );
104 }
105#endif
106
107 m_top = aTop;
108}
109
110
111const wxString KIWAY::dso_search_path( FACE_T aFaceId )
112{
113 const char* name;
114
115 switch( aFaceId )
116 {
117 case FACE_SCH: name = KIFACE_PREFIX "eeschema"; break;
118 case FACE_PCB: name = KIFACE_PREFIX "pcbnew"; break;
119 case FACE_CVPCB: name = KIFACE_PREFIX "cvpcb"; break;
120 case FACE_GERBVIEW: name = KIFACE_PREFIX "gerbview"; break;
121 case FACE_PL_EDITOR: name = KIFACE_PREFIX "pl_editor"; break;
122 case FACE_PCB_CALCULATOR: name = KIFACE_PREFIX "pcb_calculator"; break;
123
124 default:
125 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFaceId" ) );
126 return wxEmptyString;
127 }
128
129#ifndef __WXMAC__
130 wxString path;
131
133 {
134 // The 2 *.cpp program launchers: single_top.cpp and kicad.cpp expect
135 // the *.kiface's to reside in same directory as their binaries do.
136 wxString appDir;
137
138 // When running inside an AppImage, the bundled ld-linux is invoked as a wrapper
139 // which causes /proc/self/exe to resolve to the dynamic linker rather than the
140 // actual binary. Use APPDIR to construct the correct executable path.
141 if( wxGetEnv( wxT( "APPDIR" ), &appDir ) )
142 path = appDir + wxT( "/usr/bin/kicad" );
143 else
144 path = wxStandardPaths::Get().GetExecutablePath();
145 }
146
147 wxFileName fn = path;
148#else
149 // we have the dso's in main OSX bundle kicad.app/Contents/PlugIns
150 wxFileName fn = Pgm().GetExecutablePath();
151 fn.AppendDir( wxT( "Contents" ) );
152 fn.AppendDir( wxT( "PlugIns" ) );
153#endif
154
155 fn.SetName( name );
156
157 // To speed up development, it's sometimes nice to run kicad from inside
158 // the build path. In that case, each program will be in a subdirectory.
159 // To find the DSOs, we need to go up one directory and then enter a subdirectory.
161 {
162#ifdef __WXMAC__
163 // On Mac, all of the kifaces are placed in the kicad.app bundle, even though the individual
164 // standalone binaries are placed in separate bundles before the make install step runs.
165 // So, we have to jump up to the kicad directory, then the PlugIns section of the kicad
166 // bundle.
167 fn = wxStandardPaths::Get().GetExecutablePath();
168
169 fn.RemoveLastDir();
170 fn.RemoveLastDir();
171 fn.RemoveLastDir();
172 fn.RemoveLastDir();
173 fn.AppendDir( wxT( "kicad" ) );
174 fn.AppendDir( wxT( "kicad.app" ) );
175 fn.AppendDir( wxT( "Contents" ) );
176 fn.AppendDir( wxT( "PlugIns" ) );
177 fn.SetName( name );
178#else
179 const char* dirName;
180
181 // The subdirectories usually have the same name as the kiface
182 switch( aFaceId )
183 {
184 case FACE_PL_EDITOR: dirName = "pagelayout_editor"; break;
185 default: dirName = name + 1; break;
186 }
187
188 const wxString& buildRoot = PATHS::GetBuildRoot();
189
190 if( !buildRoot.IsEmpty() )
191 fn.AssignDir( buildRoot );
192 else
193 fn.RemoveLastDir();
194
195 fn.AppendDir( dirName );
196 fn.SetName( name );
197#endif
198 }
199
200 // Here a "suffix" == an extension with a preceding '.',
201 // so skip the preceding '.' to get an extension
202 fn.SetExt( &KIFACE_SUFFIX[1] );
203
204 return fn.GetFullPath();
205}
206
207
209{
210 return Pgm().GetSettingsManager().Prj();
211}
212
213
214KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad )
215{
216 // Since this will be called from python, cannot assume that code will
217 // not pass a bad aFaceId.
218 if( (unsigned) aFaceId >= m_kiface.size() )
219 {
220 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFaceId" ) );
221 return nullptr;
222 }
223
224 // return the previously loaded KIFACE, if it was.
225 if( m_kiface[aFaceId] )
226 return m_kiface[aFaceId];
227
228 // DSO with KIFACE has not been loaded yet, does caller want to load it?
229 if( doLoad )
230 {
231 wxString dname = dso_search_path( aFaceId );
232
233 // Insert DLL search path for kicad_3dsg from build dir
234 const wxString& buildRoot = PATHS::GetBuildRoot();
235
237 {
238 wxFileName myPath;
239
240 if( !buildRoot.IsEmpty() )
241 myPath.AssignDir( buildRoot );
242 else
243 myPath.Assign( wxStandardPaths::Get().GetExecutablePath() );
244
245 if( !myPath.GetPath().EndsWith( wxT( "pcbnew" ) ) )
246 {
247 if( buildRoot.IsEmpty() )
248 myPath.RemoveLastDir();
249
250 myPath.AppendDir( wxT( "pcbnew" ) );
252 }
253 }
254
255#ifdef KICAD_WIN32_VERIFY_CODESIGN
256 bool codeSignOk = KIPLATFORM::ENV::VerifyFileSignature( dname );
257
258 if( !codeSignOk )
259 THROW_IO_ERRORF( _( "Failed to verify kiface library '%s' signature." ), dname );
260#endif
261
262 wxDynamicLibrary dso;
263 void* addr = nullptr;
264
265 // For some reason wxDynamicLibrary::Load() crashes in some languages
266 // (chinese for instance) when loading the dynamic library.
267 // The crash happens for Eeschema.
268 // So switch to "C" locale during loading (LC_COLLATE is enough).
269 int lc_new_type = LC_COLLATE;
270 std::string user_locale = setlocale( lc_new_type, nullptr );
271 setlocale( lc_new_type, "C" );
272
273 bool success = dso.Load( dname, wxDL_VERBATIM | wxDL_NOW | wxDL_GLOBAL );
274
275 setlocale( lc_new_type, user_locale.c_str() );
276
277 APP_MONITOR::AddNavigationBreadcrumb( wxString::Format( "Loading kiface %d", aFaceId ), "kiway.kiface" );
278
279 if( !success )
280 {
281 // Failure: error reporting UI was done via wxLogSysError().
282 // No further reporting required here. Apparently this is not true on all
283 // platforms and/or wxWidgets builds and KiCad will crash. Throwing the exception
284 // here and catching it in the KiCad launcher resolves the crash issue. See bug
285 // report https://bugs.launchpad.net/kicad/+bug/1577786.
286
287 THROW_IO_ERRORF( _( "Failed to load kiface library '%s'." ), dname );
288 }
289 else if( ( addr = dso.GetSymbol( wxT( KIFACE_INSTANCE_NAME_AND_VERSION ) ) ) == nullptr )
290 {
291 // Failure: error reporting UI was done via wxLogSysError().
292 // No further reporting required here. Assume the same thing applies here as
293 // above with the Load() call. This has not been tested.
294 THROW_IO_ERRORF( _( "Could not read instance name and version from kiface library '%s'." ), dname );
295 }
296 else
297 {
298 KIFACE_GETTER_FUNC* ki_getter = (KIFACE_GETTER_FUNC*) addr;
299
300 KIFACE* kiface = ki_getter( &m_kiface_version[aFaceId], KIFACE_VERSION, &Pgm() );
301
302 // KIFACE_GETTER_FUNC function comment (API) says the non-NULL is unconditional.
303 wxASSERT_MSG( kiface, wxT( "attempted DSO has a bug, failed to return a KIFACE*" ) );
304
305 wxDllType dsoHandle = dso.Detach();
306
307 bool startSuccess = false;
308
309 // Give the DSO a single chance to do its "process level" initialization.
310 // "Process level" specifically means stay away from any projects in there.
311
312 try
313 {
314 startSuccess = kiface->OnKifaceStart( &Pgm(), m_ctl, this );
315 }
316 catch (...)
317 {
318 // OnKiFaceStart may generate an exception
319 // Before we continue and ultimately unload our module to retry we need
320 // to process the exception before we delete the free the memory space the
321 // exception resides in
322 Pgm().HandleException( std::current_exception() );
323 }
324
325 if( startSuccess )
326 {
327 return m_kiface[aFaceId] = kiface;
328 }
329 else
330 {
331 // Usually means canceled initial global library setup
332 // But it could have been an exception/failure
333 // Let the module go out of scope to unload
334 dso.Attach( dsoHandle );
335
336 return nullptr;
337 }
338 }
339 }
340
341 return nullptr;
342}
343
344
346{
347 switch( aFrameType )
348 {
349 case FRAME_SCH:
351 case FRAME_SCH_VIEWER:
353 case FRAME_SIMULATOR:
354 return FACE_SCH;
355
356 case FRAME_PCB_EDITOR:
362 return FACE_PCB;
363
364 case FRAME_CVPCB:
366 return FACE_CVPCB;
367
368 case FRAME_GERBER:
369 return FACE_GERBVIEW;
370
371 case FRAME_PL_EDITOR:
372 return FACE_PL_EDITOR;
373
374 case FRAME_CALC:
375 return FACE_PCB_CALCULATOR;
376
377 default:
378 return FACE_T( -1 );
379 }
380}
381
382
384{
385 wxWindowID storedId = m_playerFrameId[aFrameType];
386
387 if( storedId == wxID_NONE )
388 return nullptr;
389
390 wxWindow* frame = wxWindow::FindWindowById( storedId );
391
392 // Since wxWindow::FindWindow*() is not cheap (especially if the window does not exist),
393 // clear invalid entries to save CPU on repeated calls that do not lead to frame creation
394 if( !frame )
395 m_playerFrameId[aFrameType].compare_exchange_strong( storedId, wxID_NONE );
396
397 return static_cast<KIWAY_PLAYER*>( frame );
398}
399
400
401KIWAY_PLAYER* KIWAY::Player( FRAME_T aFrameType, bool doCreate, wxTopLevelWindow* aParent )
402{
403 // Since this will be called from python, cannot assume that code will
404 // not pass a bad aFrameType.
405 if( (unsigned) aFrameType >= KIWAY_PLAYER_COUNT )
406 {
407 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFrameType" ) );
408 return nullptr;
409 }
410
411 // return the previously opened window
412 KIWAY_PLAYER* frame = GetPlayerFrame( aFrameType );
413
414 if( frame )
415 return frame;
416
417 if( doCreate )
418 {
419 try
420 {
421 wxString msg = wxString::Format( "Creating window type %d", aFrameType );
422 APP_MONITOR::AddNavigationBreadcrumb( msg, "kiway.player" );
423
424 FACE_T face_type = KifaceType( aFrameType );
425 KIFACE* kiface = KiFACE( face_type );
426
427 if( !kiface )
428 return nullptr;
429
430 frame = (KIWAY_PLAYER*) kiface->CreateKiWindow(
431 aParent, // Parent window of frame in modal mode,
432 // NULL in non modal mode
433 aFrameType,
434 this,
435 m_ctl // questionable need, these same flags
436 // were passed to KIFACE::OnKifaceStart()
437 );
438 if( frame )
439 m_playerFrameId[aFrameType].store( frame->GetId() );
440
441 return frame;
442 }
443 catch( ... )
444 {
445 Pgm().HandleException( std::current_exception() );
446 wxLogError( _( "Error loading editor." ) );
447 }
448 }
449
450 return nullptr;
451}
452
453
454bool KIWAY::PlayerClose( FRAME_T aFrameType, bool doForce )
455{
456 // Since this will be called from python, cannot assume that code will
457 // not pass a bad aFrameType.
458 if( (unsigned) aFrameType >= KIWAY_PLAYER_COUNT )
459 {
460 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFrameType" ) );
461 return false;
462 }
463
464 KIWAY_PLAYER* frame = GetPlayerFrame( aFrameType );
465
466 if( frame == nullptr ) // Already closed
467 return true;
468
469 wxString msg = wxString::Format( "Closing window type %d", aFrameType );
470 APP_MONITOR::AddNavigationBreadcrumb( msg, "kiway.playerclose" );
471
472 if( frame->NonUserClose( doForce ) )
473 {
474 m_playerFrameId[aFrameType] = wxID_NONE;
475 return true;
476 }
477
478 return false;
479}
480
481
482bool KIWAY::PlayersClose( bool doForce )
483{
484 bool ret = true;
485
486 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
487 ret = ret && PlayerClose( FRAME_T( i ), doForce );
488
489 return ret;
490}
491
492
494{
495 m_playerFrameId[aFrameType] = wxID_NONE;
496}
497
498
499void KIWAY::ExpressMail( FRAME_T aDestination, MAIL_T aCommand, std::string& aPayload,
500 wxWindow* aSource, bool aFromOtherThread )
501{
502 std::unique_ptr<KIWAY_MAIL_EVENT> mail =
503 std::make_unique<KIWAY_MAIL_EVENT>( aDestination, aCommand, aPayload, aSource );
504
505 if( aFromOtherThread )
506 QueueEvent( mail.release() );
507 else
508 ProcessEvent( *mail );
509}
510
511
512void KIWAY::GetActions( std::vector<TOOL_ACTION*>& aActions ) const
513{
515 aActions.push_back( action );
516}
517
518
519void KIWAY::SetLanguage( int aLanguage )
520{
521 wxString errMsg;
522 bool ret = false;
523
524 {
525 // Only allow the traces to be logged by wx. We use our own system to log when the
526 // OS doesn't support the language, so we want to hide the wx error.
527 WX_LOG_TRACE_ONLY logtraceOnly;
528 Pgm().SetLanguageIdentifier( aLanguage );
529 ret = Pgm().SetLanguage( errMsg );
530 }
531
532 if( !ret )
533 {
534 wxString lang;
535
536 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
537 {
538 if( aLanguage == LanguagesList[ii].m_KI_Lang_Identifier )
539 {
540 if( LanguagesList[ii].m_DoNotTranslate )
541 lang = LanguagesList[ii].m_Lang_Label;
542 else
543 lang = wxGetTranslation( LanguagesList[ii].m_Lang_Label );
544
545 break;
546 }
547 }
548
549 DisplayErrorMessage( nullptr,
550 wxString::Format( _( "Unable to switch language to %s" ), lang ),
551 errMsg );
552 return;
553 }
554
555#if 1
556 // This is a risky hack that goes away if we allow the language to be
557 // set only from the top most frame if !Kiface.IsSingle()
558
559 // Only for the C++ project manager, and not for the python one and not for
560 // single_top do we look for the EDA_BASE_FRAME as the top level window.
561 // For single_top this is not needed because that window is registered in
562 // the array below.
564 {
565 // A dynamic_cast could be better, but creates link issues
566 // (some basic_frame functions not found) on some platforms,
567 // so a static_cast is used.
568 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
569
570 if ( top )
571 {
572 top->ShowChangedLanguage();
573 wxCommandEvent e( EDA_LANG_CHANGED );
574 top->GetEventHandler()->ProcessEvent( e );
575 }
576 }
577#endif
578
579 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
580 {
581 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
582
583 if( frame )
584 {
585 frame->ShowChangedLanguage();
586 wxCommandEvent e( EDA_LANG_CHANGED );
587 frame->GetEventHandler()->ProcessEvent( e );
588 }
589 }
590}
591
592
594{
595 // Fieldname templates have both a project and a global half, so we need to update the global templates
596 // and then re-resolve the calculated templates (meaning figure out who's visibility settings win)
598
600 {
601 // A dynamic_cast could be better, but creates link issues
602 // (some basic_frame functions not found) on some platforms,
603 // so a static_cast is used.
604 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
605
606 if( top )
607 top->CommonSettingsChanged( aFlags );
608 }
609
610 if( aFlags & ENVVARS_CHANGED )
611 {
612 if( KIFACE* sch = KiFACE( FACE_SCH, false ) )
613 sch->PreloadLibraries( this );
614
615 if( KIFACE* pcb = KiFACE( FACE_PCB, false ) )
616 pcb->PreloadLibraries( this );
617 }
618
619 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
620 {
621 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
622
623 if( frame )
624 frame->CommonSettingsChanged( aFlags );
625 }
626}
627
628
630{
632 {
633 // A dynamic_cast could be better, but creates link issues
634 // (some basic_frame functions not found) on some platforms,
635 // so a static_cast is used.
636 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
637
638 if( top )
639 top->ClearFileHistory();
640 }
641
642 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
643 {
644 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
645
646 if( frame )
647 frame->ClearFileHistory();
648 }
649}
650
651
653{
654 // Skip project change notifications during application shutdown to avoid
655 // clearing savers and re-registering them unnecessarily
656 if( PgmOrNull() && Pgm().m_Quitting )
657 return;
658
659 APP_MONITOR::AddNavigationBreadcrumb( "Changing project", "kiway.projectchanged" );
660
662
664 {
665 // A dynamic_cast could be better, but creates link issues
666 // (some basic_frame functions not found) on some platforms,
667 // so a static_cast is used.
668 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
669
670 if( top )
671 top->ProjectChanged();
672 }
673
674 // Cancel an in-progress load of libraries; handled through the schematic and PCB ifaces.
675 // Use doLoad=false: only notify already-loaded kifaces, don't force-load absent ones
676 // (e.g. eeschema kiface isn't available in standalone pcbnew).
677 if ( KIFACE* schface = KiFACE( KIWAY::FACE_SCH, false ) )
678 schface->ProjectChanged();
679
680 if ( KIFACE* pcbface = KiFACE( KIWAY::FACE_PCB, false ) )
681 pcbface->ProjectChanged();
682
683 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
684 {
685 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
686
687 if( frame )
688 frame->ProjectChanged();
689 }
690}
691
692
694{
695 return wxWindow::FindWindowById( m_blockingDialog );
696}
697
698
699void KIWAY::SetBlockingDialog( wxWindow* aWin )
700{
701 if( !aWin )
702 m_blockingDialog = wxID_NONE;
703 else
704 m_blockingDialog = aWin->GetId();
705}
706
707
708bool KIWAY::ProcessEvent( wxEvent& aEvent )
709{
710 KIWAY_MAIL_EVENT* mail = dynamic_cast<KIWAY_MAIL_EVENT*>( &aEvent );
711
712 if( mail )
713 {
714 FRAME_T dest = mail->Dest();
715
716 // see if recipient is alive
717 KIWAY_PLAYER* alive = Player( dest, false );
718
719 if( alive )
720 {
721#if 1
722 return alive->ProcessEvent( aEvent );
723#else
724 alive->KiwayMailIn( *mail );
725 return true;
726#endif
727 }
728 }
729
730 return false;
731}
732
733
734void KIWAY::QueueEvent( wxEvent* aEvent )
735{
736 KIWAY_MAIL_EVENT* mail = dynamic_cast<KIWAY_MAIL_EVENT*>( aEvent );
737
738 if( mail )
739 {
740 FRAME_T dest = mail->Dest();
741
742 // see if recipient is alive
743 KIWAY_PLAYER* alive = Player( dest, false );
744
745 if( alive )
746 {
747 alive->GetEventHandler()->QueueEvent( aEvent );
748 }
749 }
750}
751
752
753int KIWAY::ProcessJob( KIWAY::FACE_T aFace, JOB* job, REPORTER* aReporter, PROGRESS_REPORTER* aProgressReporter )
754{
755 KIFACE* kiface = KiFACE( aFace );
756
757 return kiface->HandleJob( job, aReporter, aProgressReporter );
758}
759
760
761bool KIWAY::ProcessJobConfigDialog( KIWAY::FACE_T aFace, JOB* aJob, wxWindow* aWindow )
762{
763 KIFACE* kiface = KiFACE( aFace );
764
765 return kiface->HandleJobConfig( aJob, aWindow );
766}
767
768
770 KICAD_API_SERVER* aServer, wxString* aError )
771{
772 KIFACE* kiface = KiFACE( aFace );
773
774 if( !kiface )
775 {
776 if( aError )
777 *aError = wxS( "Failed to load requested face" );
778
779 return false;
780 }
781
782 return kiface->HandleApiOpenDocument( aSpec, aServer, aError );
783}
784
785
787 KICAD_API_SERVER* aServer, wxString* aError )
788{
789 KIFACE* kiface = KiFACE( aFace );
790
791 if( !kiface )
792 {
793 if( aError )
794 *aError = wxS( "Failed to load requested face" );
795
796 return false;
797 }
798
799 return kiface->HandleApiCloseDocument( aSpec, aServer, aError );
800}
801
802
804{
806 {
807 // A dynamic_cast could be better, but creates link issues
808 // (some basic_frame functions not found) on some platforms,
809 // so a static_cast is used.
810 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
811
812 if( top )
813 top->Close( false );
814 }
815}
816
817
819{
820 for( KIFACE* i : m_kiface )
821 {
822 if( i )
823 i->OnKifaceEnd();
824 }
825}
const char * name
static std::list< TOOL_ACTION * > & GetActionList()
Return list of TOOL_ACTIONs.
The base frame for deriving all KiCad main window classes.
bool NonUserClose(bool aForce)
virtual void ProjectChanged()
Notification event that the project has changed.
void CommonSettingsChanged(int aFlags) override
Notification event that some of the common (suite-wide) settings have changed.
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
bool ProcessEvent(wxEvent &aEvent) override
Override the default process event handler to implement the auto save feature.
virtual void ClearFileHistory()
Remove all files from the file history.
An simple container class that lets us dispatch output jobs to kifaces.
Definition job.h:184
Carry a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition kiway_mail.h:34
FRAME_T Dest()
Return the destination player id of the message.
Definition kiway_mail.h:39
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
virtual void KiwayMailIn(KIWAY_MAIL_EVENT &aEvent)
Receive KIWAY_MAIL_EVENT messages from other players.
void OnKiCadExit()
Definition kiway.cpp:803
bool ProcessJobConfigDialog(KIWAY::FACE_T aFace, JOB *aJob, wxWindow *aWindow)
Definition kiway.cpp:761
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:401
const wxString dso_search_path(FACE_T aFaceId)
Get the [path &] name of the DSO holding the requested FACE_T.
Definition kiway.cpp:111
int ProcessJob(KIWAY::FACE_T aFace, JOB *aJob, REPORTER *aReporter=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Definition kiway.cpp:753
void SetBlockingDialog(wxWindow *aWin)
Definition kiway.cpp:699
LOCAL_HISTORY * m_local_history
Definition kiway.h:565
virtual bool PlayerClose(FRAME_T aFrameType, bool doForce)
Call the KIWAY_PLAYER::Close( bool force ) function on the window and if not vetoed,...
Definition kiway.cpp:454
static FACE_T KifaceType(FRAME_T aFrameType)
A simple mapping function which returns the FACE_T which is known to implement aFrameType.
Definition kiway.cpp:345
wxWindowID m_blockingDialog
Definition kiway.h:555
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:499
wxWindow * GetBlockingDialog()
Gets the window pointer to the blocking dialog (to send it signals)
Definition kiway.cpp:693
static std::array< KIFACE *, KIWAY_FACE_COUNT > m_kiface
Definition kiway.h:548
void ClearFileHistory()
Clear the wxWidgets file history on each open frame.
Definition kiway.cpp:629
wxFrame * m_top
Definition kiway.h:553
bool ProcessApiOpenDocument(KIWAY::FACE_T aFace, const KIFACE::DOCUMENT_SPEC &aSpec, KICAD_API_SERVER *aServer, wxString *aError=nullptr)
Definition kiway.cpp:769
virtual void SetLanguage(int aLanguage)
Change the language and then calls ShowChangedLanguage() on all KIWAY_PLAYER objects.
Definition kiway.cpp:519
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition kiway.cpp:214
FACE_T
Known KIFACE implementations.
Definition kiway.h:354
@ FACE_SCH
eeschema DSO
Definition kiway.h:355
@ FACE_PL_EDITOR
Definition kiway.h:359
@ FACE_PCB
pcbnew DSO
Definition kiway.h:356
@ FACE_CVPCB
Definition kiway.h:357
@ FACE_GERBVIEW
Definition kiway.h:358
@ FACE_PCB_CALCULATOR
Definition kiway.h:360
KIWAY_PLAYER * GetPlayerFrame(FRAME_T aFrameType)
Definition kiway.cpp:383
bool ProcessEvent(wxEvent &aEvent) override
Definition kiway.cpp:708
static std::array< int, KIWAY_FACE_COUNT > m_kiface_version
Definition kiway.h:549
virtual bool PlayersClose(bool doForce)
Call the KIWAY_PLAYER::Close( bool force ) function on all the windows and if none are vetoed,...
Definition kiway.cpp:482
bool ProcessApiCloseDocument(KIWAY::FACE_T aFace, const KIFACE::DOCUMENT_SPEC &aSpec, KICAD_API_SERVER *aServer, wxString *aError=nullptr)
Definition kiway.cpp:786
std::atomic< wxWindowID > m_playerFrameId[KIWAY_PLAYER_COUNT]
Definition kiway.h:563
void OnKiwayEnd()
Definition kiway.cpp:818
KIWAY(int aCtlBits, wxFrame *aTop=nullptr)
Definition kiway.cpp:51
LOCAL_HISTORY & LocalHistory()
Return the LOCAL_HISTORY associated with this KIWAY.
Definition kiway.h:457
virtual void CommonSettingsChanged(int aFlags=0)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition kiway.cpp:593
~KIWAY()
Definition kiway.cpp:68
void QueueEvent(wxEvent *aEvent) override
Definition kiway.cpp:734
void PlayerDidClose(FRAME_T aFrameType)
Notifies a Kiway that a player has been closed.
Definition kiway.cpp:493
virtual void GetActions(std::vector< TOOL_ACTION * > &aActions) const
Append all registered actions to the given list.
Definition kiway.cpp:512
void SetTop(wxFrame *aTop)
Tell this KIWAY about the top most frame in the program and optionally allows it to play the role of ...
Definition kiway.cpp:89
virtual void ProjectChanged()
Calls ProjectChanged() on all KIWAY_PLAYERs.
Definition kiway.cpp:652
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition kiway.cpp:208
int m_ctl
Definition kiway.h:551
Simple local history manager built on libgit2.
void ClearAllSavers()
Clear all registered savers.
static bool RunningFromBuildDir()
True when KiCad runs from its build tree or KICAD_RUN_FROM_BUILD_DIR is set.
Definition paths.cpp:698
static const wxString & GetBuildRoot()
The build root of the running executable, or empty outside a KiCad build tree.
Definition paths.cpp:690
void HandleException(std::exception_ptr aPtr, bool aUnhandled=false)
A exception handler to be used at the top level if exceptions bubble up that for.
Definition pgm_base.cpp:823
virtual void SetLanguageIdentifier(int menu_id)
Set in .m_language_id member the wxWidgets language identifier ID from the KiCad menu id (internal me...
Definition pgm_base.cpp:710
virtual const wxString & GetExecutablePath() const
Definition pgm_base.cpp:888
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:123
virtual bool SetLanguage(wxString &aErrMsg, bool first_time=false)
Set the dictionary file name for internationalization.
Definition pgm_base.cpp:568
A progress reporter interface for use in multi-threaded environments.
Container for project specific data.
Definition project.h:63
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
void SyncGlobalFieldNameTemplatesToProjects()
Synchronize the global field name templates into every loaded project.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
Represent a single user action.
A logger class that filters out all log messages that are not generated by wxLogTrace and ignores the...
Definition logging.h:28
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
This file is part of the common library.
#define _(s)
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition frame_type.h:29
@ FRAME_PCB_EDITOR
Definition frame_type.h:38
@ FRAME_CALC
Definition frame_type.h:57
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:31
@ FRAME_CVPCB_DISPLAY
Definition frame_type.h:49
@ FRAME_FOOTPRINT_VIEWER
Definition frame_type.h:41
@ FRAME_FOOTPRINT_WIZARD
Definition frame_type.h:42
@ FRAME_SCH_VIEWER
Definition frame_type.h:32
@ FRAME_SCH
Definition frame_type.h:30
@ FRAME_SIMULATOR
Definition frame_type.h:34
@ KIWAY_PLAYER_COUNT
Definition frame_type.h:64
@ FRAME_FOOTPRINT_CHOOSER
Definition frame_type.h:40
@ FRAME_PL_EDITOR
Definition frame_type.h:55
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:39
@ FRAME_GERBER
Definition frame_type.h:53
@ FRAME_PCB_DISPLAY3D
Definition frame_type.h:43
@ FRAME_CVPCB
Definition frame_type.h:48
@ FRAME_SYMBOL_CHOOSER
Definition frame_type.h:33
#define THROW_IO_ERRORF(msg,...)
#define KFCTL_CPP_PROJECT_SUITE
Running under C++ project mgr, possibly with others.
Definition kiway.h:175
KIFACE * KIFACE_GETTER_FUNC(int *aKIFACEversion, int aKIWAYversion, PGM_BASE *aProgram)
Point to the one and only KIFACE export.
Definition kiway.h:584
#define KIFACE_INSTANCE_NAME_AND_VERSION
Definition kiway.h:114
#define KIFACE_VERSION
Definition kiway.h:109
#define KFCTL_STANDALONE
Running as a standalone Top.
Definition kiway.h:174
This file contains miscellaneous commonly used macros and functions.
MAIL_T
The set of mail types sendable via KIWAY::ExpressMail() and supplied as the aCommand parameter to tha...
Definition mail_type.h:34
void AddNavigationBreadcrumb(const wxString &aMsg, const wxString &aCategory)
Add a navigation breadcrumb.
void AddDynamicLibrarySearchPath(const wxString &aPath)
Inserts a search path for loading dynamic libraries.
Definition unix/app.cpp:118
bool VerifyFileSignature(const wxString &aPath)
Validates the code signing signature of a given file This is most likely only ever going to be applic...
PGM_BASE & Pgm()
The global program "get" accessor.
PGM_BASE * PgmOrNull()
Return a reference that can be nullptr when running a shared lib from a script, not from a kicad app.
LANGUAGE_DESCR LanguagesList[]
An array containing all the languages that KiCad supports.
Definition pgm_base.cpp:86
see class PGM_BASE
Implement a participant in the KIWAY alchemy.
Definition kiway.h:153
IFACE KIFACE_BASE kiface("pcb_test_frame", KIWAY::FACE_PCB)
std::string path
KIBIS top(path, &reporter)
#define ENVVARS_CHANGED