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 (C) 2014-2023 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, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <cstring>
26
27#include <core/ignore.h>
28#include <macros.h>
29#include <kiway.h>
30#include <kiway_player.h>
31#include <kiway_express.h>
32#include <pgm_base.h>
33#include <config.h>
34#include <core/arraydim.h>
35#include <id.h>
36#include <kiplatform/app.h>
39#include <tool/action_manager.h>
40#include <logging.h>
41
42#include <wx/dynlib.h>
43#include <wx/stdpaths.h>
44#include <wx/debug.h>
45#include <wx/utils.h>
46#include <confirm.h>
47
48#ifdef KICAD_USE_SENTRY
49#include <sentry.h>
50#endif
51
52KIFACE* KIWAY::m_kiface[KIWAY_FACE_COUNT];
53int KIWAY::m_kiface_version[KIWAY_FACE_COUNT];
54
55
56
57KIWAY::KIWAY( PGM_BASE* aProgram, int aCtlBits, wxFrame* aTop ):
58 m_program( aProgram ), m_ctl( aCtlBits ), m_top( nullptr ), m_blockingDialog( wxID_NONE )
59{
60 SetTop( aTop ); // hook player_destroy_handler() into aTop.
61
62 // Set the array of all known frame window IDs to empty = wxID_NONE,
63 // once they are be created, they are added with FRAME_T as index to this array.
64 // Note: A non empty entry does not mean the frame still exists.
65 // It means only the frame was created at least once. It can be destroyed after.
66 // These entries are not cleared automatically on window closing. The purpose is just
67 // to allow a call to wxWindow::FindWindowById() using a FRAME_T frame type
68 for( int n = 0; n < KIWAY_PLAYER_COUNT; n++ )
69 m_playerFrameId[n] = wxID_NONE;
70}
71
72
73#if 0
74// Any event types derived from wxCommandEvt, like wxWindowDestroyEvent, are
75// propagated upwards to parent windows if not handled below. Therefore the
76// m_top window should receive all wxWindowDestroyEvents originating from
77// KIWAY_PLAYERs. It does anyways, but now player_destroy_handler eavesdrops
78// on that event stream looking for KIWAY_PLAYERs being closed.
79
80void KIWAY::player_destroy_handler( wxWindowDestroyEvent& event )
81{
82 // Currently : do nothing
83 event.Skip(); // skip to who, the wxApp? I'm the top window.
84}
85#endif
86
87
88void KIWAY::SetTop( wxFrame* aTop )
89{
90#if 0
91 if( m_top )
92 {
93 m_top->Disconnect( wxEVT_DESTROY,
94 wxWindowDestroyEventHandler( KIWAY::player_destroy_handler ),
95 nullptr, this );
96 }
97
98 if( aTop )
99 {
100 aTop->Connect( wxEVT_DESTROY,
101 wxWindowDestroyEventHandler( KIWAY::player_destroy_handler ),
102 nullptr, this );
103 }
104#endif
105
106 m_top = aTop;
107}
108
109
110const wxString KIWAY::dso_search_path( FACE_T aFaceId )
111{
112 const char* name;
113
114 switch( aFaceId )
115 {
116 case FACE_SCH: name = KIFACE_PREFIX "eeschema"; break;
117 case FACE_PCB: name = KIFACE_PREFIX "pcbnew"; break;
118 case FACE_CVPCB: name = KIFACE_PREFIX "cvpcb"; break;
119 case FACE_GERBVIEW: name = KIFACE_PREFIX "gerbview"; break;
120 case FACE_PL_EDITOR: name = KIFACE_PREFIX "pl_editor"; break;
121 case FACE_PCB_CALCULATOR: name = KIFACE_PREFIX "pcb_calculator"; break;
122 case FACE_BMP2CMP: name = KIFACE_PREFIX "bitmap2component"; break;
123 case FACE_PYTHON: name = KIFACE_PREFIX "kipython"; break;
124
125 default:
126 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFaceId" ) );
127 return wxEmptyString;
128 }
129
130#ifndef __WXMAC__
131 wxString path;
132
134 {
135 // The 2 *.cpp program launchers: single_top.cpp and kicad.cpp expect
136 // the *.kiface's to reside in same directory as their binaries do.
137 path = wxStandardPaths::Get().GetExecutablePath();
138 }
139
140 wxFileName fn = path;
141#else
142 // we have the dso's in main OSX bundle kicad.app/Contents/PlugIns
143 wxFileName fn = Pgm().GetExecutablePath();
144 fn.AppendDir( wxT( "Contents" ) );
145 fn.AppendDir( wxT( "PlugIns" ) );
146#endif
147
148 fn.SetName( name );
149
150 // To speed up development, it's sometimes nice to run kicad from inside
151 // the build path. In that case, each program will be in a subdirectory.
152 // To find the DSOs, we need to go up one directory and then enter a subdirectory.
153
154 if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
155 {
156#ifdef __WXMAC__
157 // On Mac, all of the kifaces are placed in the kicad.app bundle, even though the individual
158 // standalone binaries are placed in separate bundles before the make install step runs.
159 // So, we have to jump up to the kicad directory, then the PlugIns section of the kicad
160 // bundle.
161 fn = wxStandardPaths::Get().GetExecutablePath();
162
163 fn.RemoveLastDir();
164 fn.RemoveLastDir();
165 fn.RemoveLastDir();
166 fn.RemoveLastDir();
167 fn.AppendDir( wxT( "kicad" ) );
168 fn.AppendDir( wxT( "kicad.app" ) );
169 fn.AppendDir( wxT( "Contents" ) );
170 fn.AppendDir( wxT( "PlugIns" ) );
171 fn.SetName( name );
172#else
173 const char* dirName;
174
175 // The subdirectories usually have the same name as the kiface
176 switch( aFaceId )
177 {
178 case FACE_PL_EDITOR: dirName = "pagelayout_editor"; break;
179 case FACE_PYTHON: dirName = "scripting"; break;
180 default: dirName = name + 1; break;
181 }
182
183 fn.RemoveLastDir();
184 fn.AppendDir( dirName );
185#endif
186 }
187
188 // Here a "suffix" == an extension with a preceding '.',
189 // so skip the preceding '.' to get an extension
190 fn.SetExt( &KIFACE_SUFFIX[1] );
191
192 return fn.GetFullPath();
193}
194
195
197{
198 return Pgm().GetSettingsManager().Prj();
199}
200
201
202KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad )
203{
204 // Since this will be called from python, cannot assume that code will
205 // not pass a bad aFaceId.
206 if( (unsigned) aFaceId >= arrayDim( m_kiface ) )
207 {
208 // @todo : throw an exception here for python's benefit, at least that
209 // way it gets some explanatory text.
210
211 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFaceId" ) );
212 return nullptr;
213 }
214
215 // return the previously loaded KIFACE, if it was.
216 if( m_kiface[aFaceId] )
217 return m_kiface[aFaceId];
218
219 // DSO with KIFACE has not been loaded yet, does caller want to load it?
220 if( doLoad )
221 {
222 wxString dname = dso_search_path( aFaceId );
223
224 // Insert DLL search path for kicad_3dsg from build dir
225 if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
226 {
227 wxFileName myPath = wxStandardPaths::Get().GetExecutablePath();
228
229 if( !myPath.GetPath().EndsWith( wxT( "pcbnew" ) ) )
230 {
231 myPath.RemoveLastDir();
232 myPath.AppendDir( wxT( "pcbnew" ) );
234 }
235 }
236
237 wxString msg;
238
239#ifdef KICAD_WIN32_VERIFY_CODESIGN
240 bool codeSignOk = KIPLATFORM::ENV::VerifyFileSignature( dname );
241 if( !codeSignOk )
242 {
243 msg.Printf( _( "Failed to verify kiface library '%s' signature." ), dname );
244 THROW_IO_ERROR( msg );
245 }
246#endif
247
248 wxDynamicLibrary dso;
249
250 void* addr = nullptr;
251
252 // For some reason wxDynamicLibrary::Load() crashes in some languages
253 // (chinese for instance) when loading the dynamic library.
254 // The crash happens for Eeschema.
255 // So switch to "C" locale during loading (LC_COLLATE is enough).
256 int lc_new_type = LC_COLLATE;
257 std::string user_locale = setlocale( lc_new_type, nullptr );
258 setlocale( lc_new_type, "C" );
259
260 bool success = dso.Load( dname, wxDL_VERBATIM | wxDL_NOW | wxDL_GLOBAL );
261
262 setlocale( lc_new_type, user_locale.c_str() );
263
264#ifdef KICAD_USE_SENTRY
265 if( Pgm().IsSentryOptedIn() )
266 {
267 msg = wxString::Format( "Loading kiface %d", aFaceId );
268 sentry_value_t crumb = sentry_value_new_breadcrumb( "navigation", msg.utf8_str() );
269 sentry_value_set_by_key( crumb, "category", sentry_value_new_string( "kiway.kiface" ) );
270 sentry_value_set_by_key( crumb, "level", sentry_value_new_string( "info" ) );
271 sentry_add_breadcrumb( crumb );
272 }
273#endif
274
275 if( !success )
276 {
277 // Failure: error reporting UI was done via wxLogSysError().
278 // No further reporting required here. Apparently this is not true on all
279 // platforms and/or wxWidgets builds and KiCad will crash. Throwing the exception
280 // here and catching it in the KiCad launcher resolves the crash issue. See bug
281 // report https://bugs.launchpad.net/kicad/+bug/1577786.
282
283 msg.Printf( _( "Failed to load kiface library '%s'." ), dname );
284 THROW_IO_ERROR( msg );
285 }
286 else if( ( addr = dso.GetSymbol( wxT( KIFACE_INSTANCE_NAME_AND_VERSION ) ) ) == nullptr )
287 {
288 // Failure: error reporting UI was done via wxLogSysError().
289 // No further reporting required here. Assume the same thing applies here as
290 // above with the Load() call. This has not been tested.
291 msg.Printf( _( "Could not read instance name and version from kiface library '%s'." ),
292 dname );
293 THROW_IO_ERROR( msg );
294 }
295 else
296 {
297 KIFACE_GETTER_FUNC* ki_getter = (KIFACE_GETTER_FUNC*) addr;
298
299 KIFACE* kiface = ki_getter( &m_kiface_version[aFaceId], KIFACE_VERSION, m_program );
300
301 // KIFACE_GETTER_FUNC function comment (API) says the non-NULL is unconditional.
302 wxASSERT_MSG( kiface,
303 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( m_program, 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 exception resides in
321 Pgm().HandleException( std::current_exception() );
322 }
323
324 if( startSuccess )
325 {
326 return m_kiface[aFaceId] = kiface;
327 }
328 else
329 {
330 // Usually means cancelled initial global library setup
331 // But it could have been an exception/failure
332 // Let the module go out of scope to unload
333 dso.Attach( dsoHandle );
334
335 return nullptr;
336 }
337 }
338
339 // In any of the failure cases above, dso.Unload() should be called here
340 // by dso destructor.
341 // However:
342
343 // There is a file installation bug. We only look for KIFACE's which we know
344 // to exist, and we did not find one. If we do not find one, this is an
345 // installation bug.
346
347 msg = wxString::Format( _( "Fatal Installation Bug. File:\n"
348 "'%s'\ncould not be loaded\n" ), dname );
349
350 if( ! wxFileExists( dname ) )
351 msg << _( "It is missing.\n" );
352 else
353 msg << _( "Perhaps a shared library (.dll or .so) file is missing.\n" );
354
355 msg << _( "From command line: argv[0]:\n'" );
356 msg << wxStandardPaths::Get().GetExecutablePath() << wxT( "'\n" );
357
358 // This is a fatal error, one from which we cannot recover, nor do we want
359 // to protect against in client code which would require numerous noisy
360 // tests in numerous places. So we inform the user that the installation
361 // is bad. This exception will likely not get caught until way up in the
362 // wxApp derivative, at which point the process will exit gracefully.
363 THROW_IO_ERROR( msg );
364 }
365
366 return nullptr;
367}
368
369
371{
372 switch( aFrameType )
373 {
374 case FRAME_SCH:
376 case FRAME_SCH_VIEWER:
378 case FRAME_SIMULATOR:
379 return FACE_SCH;
380
381 case FRAME_PCB_EDITOR:
387 return FACE_PCB;
388
389 case FRAME_CVPCB:
391 return FACE_CVPCB;
392
393 case FRAME_PYTHON:
394 return FACE_PYTHON;
395
396 case FRAME_GERBER:
397 return FACE_GERBVIEW;
398
399 case FRAME_PL_EDITOR:
400 return FACE_PL_EDITOR;
401
402 case FRAME_CALC:
403 return FACE_PCB_CALCULATOR;
404
405 case FRAME_BM2CMP:
406 return FACE_BMP2CMP;
407
408 default:
409 return FACE_T( -1 );
410 }
411}
412
413
415{
416 wxWindowID storedId = m_playerFrameId[aFrameType];
417
418 if( storedId == wxID_NONE )
419 return nullptr;
420
421 wxWindow* frame = wxWindow::FindWindowById( storedId );
422
423 // Since wxWindow::FindWindow*() is not cheap (especially if the window does not exist),
424 // clear invalid entries to save CPU on repeated calls that do not lead to frame creation
425 if( !frame )
426 m_playerFrameId[aFrameType].compare_exchange_strong( storedId, wxID_NONE );
427
428 return static_cast<KIWAY_PLAYER*>( frame );
429}
430
431
432KIWAY_PLAYER* KIWAY::Player( FRAME_T aFrameType, bool doCreate, wxTopLevelWindow* aParent )
433{
434 // Since this will be called from python, cannot assume that code will
435 // not pass a bad aFrameType.
436 if( (unsigned) aFrameType >= KIWAY_PLAYER_COUNT )
437 {
438 // @todo : throw an exception here for python's benefit, at least that
439 // way it gets some explanatory text.
440
441 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFrameType" ) );
442 return nullptr;
443 }
444
445 // return the previously opened window
446 KIWAY_PLAYER* frame = GetPlayerFrame( aFrameType );
447
448 if( frame )
449 return frame;
450
451 if( doCreate )
452 {
453 try
454 {
455#ifdef KICAD_USE_SENTRY
456 if( Pgm().IsSentryOptedIn() )
457 {
458 wxString msg = wxString::Format( "Creating window type %d", aFrameType );
459 sentry_value_t crumb = sentry_value_new_breadcrumb( "navigation", msg.utf8_str() );
460 sentry_value_set_by_key( crumb, "category",
461 sentry_value_new_string( "kiway.player" ) );
462 sentry_value_set_by_key( crumb, "level", sentry_value_new_string( "info" ) );
463 sentry_add_breadcrumb( crumb );
464 }
465#endif
466
467 FACE_T face_type = KifaceType( aFrameType );
468 KIFACE* kiface = KiFACE( face_type );
469
470 if( !kiface )
471 return nullptr;
472
474 aParent, // Parent window of frame in modal mode,
475 // NULL in non modal mode
476 aFrameType,
477 this,
478 m_ctl // questionable need, these same flags
479 // were passed to KIFACE::OnKifaceStart()
480 );
481
482 m_playerFrameId[aFrameType].store( frame->GetId() );
483 return frame;
484 }
485 catch( ... )
486 {
487 Pgm().HandleException( std::current_exception() );
488 wxLogError( _( "Error loading editor." ) );
489 }
490 }
491
492 return nullptr;
493}
494
495
496bool KIWAY::PlayerClose( FRAME_T aFrameType, bool doForce )
497{
498 // Since this will be called from python, cannot assume that code will
499 // not pass a bad aFrameType.
500 if( (unsigned) aFrameType >= KIWAY_PLAYER_COUNT )
501 {
502 // @todo : throw an exception here for python's benefit, at least that
503 // way it gets some explanatory text.
504
505 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFrameType" ) );
506 return false;
507 }
508
509 KIWAY_PLAYER* frame = GetPlayerFrame( aFrameType );
510
511 if( frame == nullptr ) // Already closed
512 return true;
513
514#ifdef KICAD_USE_SENTRY
515 if( Pgm().IsSentryOptedIn() )
516 {
517 wxString msg = wxString::Format( "Closing window type %d", aFrameType );
518 sentry_value_t crumb = sentry_value_new_breadcrumb( "navigation", msg.utf8_str() );
519 sentry_value_set_by_key( crumb, "category",
520 sentry_value_new_string( "kiway.playerclose" ) );
521 sentry_value_set_by_key( crumb, "level", sentry_value_new_string( "info" ) );
522 sentry_add_breadcrumb( crumb );
523 }
524#endif
525
526 if( frame->NonUserClose( doForce ) )
527 {
528 m_playerFrameId[aFrameType] = wxID_NONE;
529 return true;
530 }
531
532 return false;
533}
534
535
536bool KIWAY::PlayersClose( bool doForce )
537{
538 bool ret = true;
539
540 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
541 ret = ret && PlayerClose( FRAME_T( i ), doForce );
542
543 return ret;
544}
545
546
548{
549 m_playerFrameId[aFrameType] = wxID_NONE;
550}
551
552
553void KIWAY::ExpressMail( FRAME_T aDestination, MAIL_T aCommand, std::string& aPayload,
554 wxWindow* aSource )
555{
556 KIWAY_EXPRESS mail( aDestination, aCommand, aPayload, aSource );
557
558 ProcessEvent( mail );
559}
560
561
562void KIWAY::GetActions( std::vector<TOOL_ACTION*>& aActions ) const
563{
565 aActions.push_back( action );
566}
567
568
569void KIWAY::SetLanguage( int aLanguage )
570{
571 wxString errMsg;
572 bool ret = false;
573
574 {
575 // Only allow the traces to be logged by wx. We use our own system to log when the
576 // OS doesn't support the language, so we want to hide the wx error.
577 WX_LOG_TRACE_ONLY logtraceOnly;
578 Pgm().SetLanguageIdentifier( aLanguage );
579 ret = Pgm().SetLanguage( errMsg );
580 }
581
582 if( !ret )
583 {
584 wxString lang;
585
586 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
587 {
588 if( aLanguage == LanguagesList[ii].m_KI_Lang_Identifier )
589 {
590 if( LanguagesList[ii].m_DoNotTranslate )
591 lang = LanguagesList[ii].m_Lang_Label;
592 else
593 lang = wxGetTranslation( LanguagesList[ii].m_Lang_Label );
594
595 break;
596 }
597 }
598
599 DisplayErrorMessage( nullptr,
600 wxString::Format( _( "Unable to switch language to %s" ), lang ),
601 errMsg );
602 return;
603 }
604
605#if 1
606 // This is a risky hack that goes away if we allow the language to be
607 // set only from the top most frame if !Kiface.IsSingle()
608
609 // Only for the C++ project manager, and not for the python one and not for
610 // single_top do we look for the EDA_BASE_FRAME as the top level window.
611 // For single_top this is not needed because that window is registered in
612 // the array below.
614 {
615 // A dynamic_cast could be better, but creates link issues
616 // (some basic_frame functions not found) on some platforms,
617 // so a static_cast is used.
618 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
619
620 if( top )
621 top->ShowChangedLanguage();
622 }
623#endif
624
625 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
626 {
627 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
628
629 if( frame )
630 {
631 frame->ShowChangedLanguage();
632 }
633 }
634}
635
636
637void KIWAY::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
638{
640 {
641 // A dynamic_cast could be better, but creates link issues
642 // (some basic_frame functions not found) on some platforms,
643 // so a static_cast is used.
644 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
645
646 if( top )
647 top->CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
648 }
649
650 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
651 {
652 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
653
654 if( frame )
655 frame->CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
656 }
657}
658
659
661{
662#ifdef KICAD_USE_SENTRY
663 sentry_value_t crumb = sentry_value_new_breadcrumb( "navigation", "Changing project" );
664 sentry_value_set_by_key( crumb, "category", sentry_value_new_string( "kiway.projectchanged" ) );
665 sentry_value_set_by_key( crumb, "level", sentry_value_new_string( "info" ) );
666 sentry_add_breadcrumb( crumb );
667#endif
668
670 {
671 // A dynamic_cast could be better, but creates link issues
672 // (some basic_frame functions not found) on some platforms,
673 // so a static_cast is used.
674 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
675
676 if( top )
677 top->ProjectChanged();
678 }
679
680 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
681 {
682 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
683
684 if( frame )
685 frame->ProjectChanged();
686 }
687}
688
690{
691 return wxWindow::FindWindowById( m_blockingDialog );
692}
693
694void KIWAY::SetBlockingDialog( wxWindow* aWin )
695{
696 if( !aWin )
697 m_blockingDialog = wxID_NONE;
698 else
699 m_blockingDialog = aWin->GetId();
700}
701
702
703bool KIWAY::ProcessEvent( wxEvent& aEvent )
704{
705 KIWAY_EXPRESS* mail = dynamic_cast<KIWAY_EXPRESS*>( &aEvent );
706
707 if( mail )
708 {
709 FRAME_T dest = mail->Dest();
710
711 // see if recipient is alive
712 KIWAY_PLAYER* alive = Player( dest, false );
713
714 if( alive )
715 {
716#if 1
717 return alive->ProcessEvent( aEvent );
718#else
719 alive->KiwayMailIn( *mail );
720 return true;
721#endif
722 }
723 }
724
725 return false;
726}
727
728
730{
731 KIFACE* kiface = KiFACE( aFace );
732
733 return kiface->HandleJob( job );
734}
735
736
738{
740 {
741 // A dynamic_cast could be better, but creates link issues
742 // (some basic_frame functions not found) on some platforms,
743 // so a static_cast is used.
744 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
745
746 if( top )
747 top->Close( false );
748 }
749}
750
751
753{
754 for( KIFACE* i : m_kiface )
755 {
756 if( i )
757 i->OnKifaceEnd();
758 }
759}
const char * name
Definition: DXF_plotter.cpp:57
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
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 ShowChangedLanguage() override
Redraw the menus and what not in current language.
void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged) override
Notification event that some of the common (suite-wide) settings have changed.
bool ProcessEvent(wxEvent &aEvent) override
Override the default process event handler to implement the auto save feature.
An simple container class that lets us dispatch output jobs to kifaces.
Definition: job.h:32
Carry a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition: kiway_express.h:39
FRAME_T Dest()
Return the destination player id of the message.
Definition: kiway_express.h:44
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:67
virtual void KiwayMailIn(KIWAY_EXPRESS &aEvent)
Receive KIWAY_EXPRESS messages from other players.
void OnKiCadExit()
Definition: kiway.cpp:737
virtual void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition: kiway.cpp:637
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:432
const wxString dso_search_path(FACE_T aFaceId)
Get the [path &] name of the DSO holding the requested FACE_T.
Definition: kiway.cpp:110
int ProcessJob(KIWAY::FACE_T aFace, JOB *job)
Definition: kiway.cpp:729
PGM_BASE * m_program
Definition: kiway.h:462
void SetBlockingDialog(wxWindow *aWin)
Definition: kiway.cpp:694
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:496
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:370
wxWindowID m_blockingDialog
Definition: kiway.h:467
KIWAY(PGM_BASE *aProgram, int aCtlBits, wxFrame *aTop=nullptr)
Definition: kiway.cpp:57
wxWindow * GetBlockingDialog()
Gets the window pointer to the blocking dialog (to send it signals)
Definition: kiway.cpp:689
static KIFACE * m_kiface[KIWAY_FACE_COUNT]
Definition: kiway.h:459
wxFrame * m_top
Definition: kiway.h:465
virtual void SetLanguage(int aLanguage)
Change the language and then calls ShowChangedLanguage() on all #KIWAY_PLAYERs.
Definition: kiway.cpp:569
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition: kiway.cpp:202
FACE_T
Known KIFACE implementations.
Definition: kiway.h:285
@ FACE_SCH
eeschema DSO
Definition: kiway.h:286
@ FACE_PL_EDITOR
Definition: kiway.h:290
@ FACE_PYTHON
Definition: kiway.h:293
@ FACE_PCB
pcbnew DSO
Definition: kiway.h:287
@ FACE_CVPCB
Definition: kiway.h:288
@ FACE_GERBVIEW
Definition: kiway.h:289
@ FACE_BMP2CMP
Definition: kiway.h:292
@ FACE_PCB_CALCULATOR
Definition: kiway.h:291
static int m_kiface_version[KIWAY_FACE_COUNT]
Definition: kiway.h:460
KIWAY_PLAYER * GetPlayerFrame(FRAME_T aFrameType)
Definition: kiway.cpp:414
bool ProcessEvent(wxEvent &aEvent) override
Definition: kiway.cpp:703
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:536
std::atomic< wxWindowID > m_playerFrameId[KIWAY_PLAYER_COUNT]
Definition: kiway.h:475
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr)
Send aPayload to aDestination from aSource.
Definition: kiway.cpp:553
void OnKiwayEnd()
Definition: kiway.cpp:752
void PlayerDidClose(FRAME_T aFrameType)
Notifies a Kiway that a player has been closed.
Definition: kiway.cpp:547
virtual void GetActions(std::vector< TOOL_ACTION * > &aActions) const
Append all registered actions to the given list.
Definition: kiway.cpp:562
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:88
virtual void ProjectChanged()
Calls ProjectChanged() on all KIWAY_PLAYERs.
Definition: kiway.cpp:660
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition: kiway.cpp:196
int m_ctl
Definition: kiway.h:463
Container for data for KiCad programs.
Definition: pgm_base.h:96
Container for project specific data.
Definition: project.h:62
Represent a single user action.
Definition: tool_action.h:269
A logger class that filters out all log messages that are not generated by wxLogTrace and ignores the...
Definition: logging.h:32
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:305
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:33
@ FRAME_PCB_EDITOR
Definition: frame_type.h:42
@ FRAME_CALC
Definition: frame_type.h:63
@ FRAME_SCH_SYMBOL_EDITOR
Definition: frame_type.h:35
@ FRAME_CVPCB_DISPLAY
Definition: frame_type.h:53
@ FRAME_FOOTPRINT_VIEWER
Definition: frame_type.h:45
@ FRAME_BM2CMP
Definition: frame_type.h:61
@ FRAME_FOOTPRINT_WIZARD
Definition: frame_type.h:46
@ FRAME_SCH_VIEWER
Definition: frame_type.h:36
@ FRAME_SCH
Definition: frame_type.h:34
@ FRAME_SIMULATOR
Definition: frame_type.h:38
@ KIWAY_PLAYER_COUNT
Definition: frame_type.h:65
@ FRAME_FOOTPRINT_CHOOSER
Definition: frame_type.h:44
@ FRAME_PL_EDITOR
Definition: frame_type.h:59
@ FRAME_FOOTPRINT_EDITOR
Definition: frame_type.h:43
@ FRAME_GERBER
Definition: frame_type.h:57
@ FRAME_PYTHON
Definition: frame_type.h:55
@ FRAME_PCB_DISPLAY3D
Definition: frame_type.h:47
@ FRAME_CVPCB
Definition: frame_type.h:52
@ FRAME_SYMBOL_CHOOSER
Definition: frame_type.h:37
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
#define KFCTL_CPP_PROJECT_SUITE
Running under C++ project mgr, possibly with others.
Definition: kiway.h:159
KIFACE * KIFACE_GETTER_FUNC(int *aKIFACEversion, int aKIWAYversion, PGM_BASE *aProgram)
Point to the one and only KIFACE export.
Definition: kiway.h:498
#define KIFACE_INSTANCE_NAME_AND_VERSION
Definition: kiway.h:115
#define KIFACE_VERSION
The KIWAY and KIFACE classes are used to communicate between various process modules,...
Definition: kiway.h:110
#define KFCTL_STANDALONE
Running as a standalone Top.
Definition: kiway.h:158
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:38
void AddDynamicLibrarySearchPath(const wxString &aPath)
Inserts a search path for loading dynamic libraries.
Definition: gtk/app.cpp:100
bool VerifyFileSignature(const wxString &aPath)
Validates the code signing signature of a given file This is most likely only ever going to be applic...
LANGUAGE_DESCR LanguagesList[]
An array containing all the languages that KiCad supports.
Definition: pgm_base.cpp:88
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:119
bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits, KIWAY *aKiway) override
Typically start_common() is called from here.
wxWindow * CreateKiWindow(wxWindow *aParent, int aClassId, KIWAY *aKiway, int aCtlBits=0) override
Create a wxWindow for the current project.
Implement a participant in the KIWAY alchemy.
Definition: kiway.h:151
virtual int HandleJob(JOB *aJob)
Definition: kiway.h:244
int m_KI_Lang_Identifier
KiCad identifier used in menu selection (See id.h)
Definition: pgm_base.h:67
wxString m_Lang_Label
Labels used in menus.
Definition: pgm_base.h:70
IFACE KIFACE_BASE kiface("pcb_test_frame", KIWAY::FACE_PCB)