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 <pgm_base.h>
30#include <config.h>
31#include <id.h>
32#include <kiplatform/app.h>
35#include <tool/action_manager.h>
36#include <logging.h>
37#include <local_history.h>
38
39#include <wx/dynlib.h>
40#include <wx/stdpaths.h>
41#include <wx/debug.h>
42#include <wx/utils.h>
43#include <confirm.h>
44
45std::array<KIFACE*, KIWAY::FACE_T::KIWAY_FACE_COUNT> KIWAY::m_kiface;
46std::array<int, KIWAY::FACE_T::KIWAY_FACE_COUNT> KIWAY::m_kiface_version;
47
48
49
50KIWAY::KIWAY( int aCtlBits, wxFrame* aTop ):
51 m_ctl( aCtlBits ), m_top( nullptr ), m_blockingDialog( wxID_NONE ), m_local_history( nullptr )
52{
54 SetTop( aTop ); // hook player_destroy_handler() into aTop.
55
56 // Set the array of all known frame window IDs to empty = wxID_NONE,
57 // once they are be created, they are added with FRAME_T as index to this array.
58 // Note: A non empty entry does not mean the frame still exists.
59 // It means only the frame was created at least once. It can be destroyed after.
60 // These entries are not cleared automatically on window closing. The purpose is just
61 // to allow a call to wxWindow::FindWindowById() using a FRAME_T frame type
62 for( int n = 0; n < KIWAY_PLAYER_COUNT; n++ )
63 m_playerFrameId[n] = wxID_NONE;
64}
65
66
68{
69 delete m_local_history;
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
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.
160 if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
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 fn.RemoveLastDir();
189 fn.AppendDir( dirName );
190#endif
191 }
192
193 // Here a "suffix" == an extension with a preceding '.',
194 // so skip the preceding '.' to get an extension
195 fn.SetExt( &KIFACE_SUFFIX[1] );
196
197 return fn.GetFullPath();
198}
199
200
202{
203 return Pgm().GetSettingsManager().Prj();
204}
205
206
207KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad )
208{
209 // Since this will be called from python, cannot assume that code will
210 // not pass a bad aFaceId.
211 if( (unsigned) aFaceId >= m_kiface.size() )
212 {
213 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFaceId" ) );
214 return nullptr;
215 }
216
217 // return the previously loaded KIFACE, if it was.
218 if( m_kiface[aFaceId] )
219 return m_kiface[aFaceId];
220
221 // DSO with KIFACE has not been loaded yet, does caller want to load it?
222 if( doLoad )
223 {
224 wxString dname = dso_search_path( aFaceId );
225
226 // Insert DLL search path for kicad_3dsg from build dir
227 if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
228 {
229 wxFileName myPath = wxStandardPaths::Get().GetExecutablePath();
230
231 if( !myPath.GetPath().EndsWith( wxT( "pcbnew" ) ) )
232 {
233 myPath.RemoveLastDir();
234 myPath.AppendDir( wxT( "pcbnew" ) );
236 }
237 }
238
239 wxString msg;
240
241#ifdef KICAD_WIN32_VERIFY_CODESIGN
242 bool codeSignOk = KIPLATFORM::ENV::VerifyFileSignature( dname );
243 if( !codeSignOk )
244 {
245 msg.Printf( _( "Failed to verify kiface library '%s' signature." ), dname );
246 THROW_IO_ERROR( msg );
247 }
248#endif
249
250 wxDynamicLibrary dso;
251
252 void* addr = nullptr;
253
254 // For some reason wxDynamicLibrary::Load() crashes in some languages
255 // (chinese for instance) when loading the dynamic library.
256 // The crash happens for Eeschema.
257 // So switch to "C" locale during loading (LC_COLLATE is enough).
258 int lc_new_type = LC_COLLATE;
259 std::string user_locale = setlocale( lc_new_type, nullptr );
260 setlocale( lc_new_type, "C" );
261
262 bool success = dso.Load( dname, wxDL_VERBATIM | wxDL_NOW | wxDL_GLOBAL );
263
264 setlocale( lc_new_type, user_locale.c_str() );
265
266 msg = wxString::Format( "Loading kiface %d", aFaceId );
267 APP_MONITOR::AddNavigationBreadcrumb( msg, "kiway.kiface" );
268
269 if( !success )
270 {
271 // Failure: error reporting UI was done via wxLogSysError().
272 // No further reporting required here. Apparently this is not true on all
273 // platforms and/or wxWidgets builds and KiCad will crash. Throwing the exception
274 // here and catching it in the KiCad launcher resolves the crash issue. See bug
275 // report https://bugs.launchpad.net/kicad/+bug/1577786.
276
277 msg.Printf( _( "Failed to load kiface library '%s'." ), dname );
278 THROW_IO_ERROR( msg );
279 }
280 else if( ( addr = dso.GetSymbol( wxT( KIFACE_INSTANCE_NAME_AND_VERSION ) ) ) == nullptr )
281 {
282 // Failure: error reporting UI was done via wxLogSysError().
283 // No further reporting required here. Assume the same thing applies here as
284 // above with the Load() call. This has not been tested.
285 msg.Printf( _( "Could not read instance name and version from kiface library '%s'." ),
286 dname );
287 THROW_IO_ERROR( msg );
288 }
289 else
290 {
291 KIFACE_GETTER_FUNC* ki_getter = (KIFACE_GETTER_FUNC*) addr;
292
293 KIFACE* kiface = ki_getter( &m_kiface_version[aFaceId], KIFACE_VERSION, &Pgm() );
294
295 // KIFACE_GETTER_FUNC function comment (API) says the non-NULL is unconditional.
296 wxASSERT_MSG( kiface,
297 wxT( "attempted DSO has a bug, failed to return a KIFACE*" ) );
298
299 wxDllType dsoHandle = dso.Detach();
300
301 bool startSuccess = false;
302
303 // Give the DSO a single chance to do its "process level" initialization.
304 // "Process level" specifically means stay away from any projects in there.
305
306 try
307 {
308 startSuccess = kiface->OnKifaceStart( &Pgm(), m_ctl, this );
309 }
310 catch (...)
311 {
312 // OnKiFaceStart may generate an exception
313 // Before we continue and ultimately unload our module to retry we need
314 // to process the exception before we delete the free the memory space the
315 // exception resides in
316 Pgm().HandleException( std::current_exception() );
317 }
318
319 if( startSuccess )
320 {
321 return m_kiface[aFaceId] = kiface;
322 }
323 else
324 {
325 // Usually means canceled initial global library setup
326 // But it could have been an exception/failure
327 // Let the module go out of scope to unload
328 dso.Attach( dsoHandle );
329
330 return nullptr;
331 }
332 }
333 }
334
335 return nullptr;
336}
337
338
340{
341 switch( aFrameType )
342 {
343 case FRAME_SCH:
345 case FRAME_SCH_VIEWER:
347 case FRAME_SIMULATOR:
348 return FACE_SCH;
349
350 case FRAME_PCB_EDITOR:
356 return FACE_PCB;
357
358 case FRAME_CVPCB:
360 return FACE_CVPCB;
361
362 case FRAME_GERBER:
363 return FACE_GERBVIEW;
364
365 case FRAME_PL_EDITOR:
366 return FACE_PL_EDITOR;
367
368 case FRAME_CALC:
369 return FACE_PCB_CALCULATOR;
370
371 case FRAME_BM2CMP:
372 return FACE_BMP2CMP;
373
374 default:
375 return FACE_T( -1 );
376 }
377}
378
379
381{
382 wxWindowID storedId = m_playerFrameId[aFrameType];
383
384 if( storedId == wxID_NONE )
385 return nullptr;
386
387 wxWindow* frame = wxWindow::FindWindowById( storedId );
388
389 // Since wxWindow::FindWindow*() is not cheap (especially if the window does not exist),
390 // clear invalid entries to save CPU on repeated calls that do not lead to frame creation
391 if( !frame )
392 m_playerFrameId[aFrameType].compare_exchange_strong( storedId, wxID_NONE );
393
394 return static_cast<KIWAY_PLAYER*>( frame );
395}
396
397
398KIWAY_PLAYER* KIWAY::Player( FRAME_T aFrameType, bool doCreate, wxTopLevelWindow* aParent )
399{
400 // Since this will be called from python, cannot assume that code will
401 // not pass a bad aFrameType.
402 if( (unsigned) aFrameType >= KIWAY_PLAYER_COUNT )
403 {
404 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFrameType" ) );
405 return nullptr;
406 }
407
408 // return the previously opened window
409 KIWAY_PLAYER* frame = GetPlayerFrame( aFrameType );
410
411 if( frame )
412 return frame;
413
414 if( doCreate )
415 {
416 try
417 {
418 wxString msg = wxString::Format( "Creating window type %d", aFrameType );
419 APP_MONITOR::AddNavigationBreadcrumb( msg, "kiway.player" );
420
421 FACE_T face_type = KifaceType( aFrameType );
422 KIFACE* kiface = KiFACE( face_type );
423
424 if( !kiface )
425 return nullptr;
426
427 frame = (KIWAY_PLAYER*) kiface->CreateKiWindow(
428 aParent, // Parent window of frame in modal mode,
429 // NULL in non modal mode
430 aFrameType,
431 this,
432 m_ctl // questionable need, these same flags
433 // were passed to KIFACE::OnKifaceStart()
434 );
435 if( frame )
436 m_playerFrameId[aFrameType].store( frame->GetId() );
437
438 return frame;
439 }
440 catch( ... )
441 {
442 Pgm().HandleException( std::current_exception() );
443 wxLogError( _( "Error loading editor." ) );
444 }
445 }
446
447 return nullptr;
448}
449
450
451bool KIWAY::PlayerClose( FRAME_T aFrameType, bool doForce )
452{
453 // Since this will be called from python, cannot assume that code will
454 // not pass a bad aFrameType.
455 if( (unsigned) aFrameType >= KIWAY_PLAYER_COUNT )
456 {
457 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFrameType" ) );
458 return false;
459 }
460
461 KIWAY_PLAYER* frame = GetPlayerFrame( aFrameType );
462
463 if( frame == nullptr ) // Already closed
464 return true;
465
466 wxString msg = wxString::Format( "Closing window type %d", aFrameType );
467 APP_MONITOR::AddNavigationBreadcrumb( msg, "kiway.playerclose" );
468
469 if( frame->NonUserClose( doForce ) )
470 {
471 m_playerFrameId[aFrameType] = wxID_NONE;
472 return true;
473 }
474
475 return false;
476}
477
478
479bool KIWAY::PlayersClose( bool doForce )
480{
481 bool ret = true;
482
483 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
484 ret = ret && PlayerClose( FRAME_T( i ), doForce );
485
486 return ret;
487}
488
489
491{
492 m_playerFrameId[aFrameType] = wxID_NONE;
493}
494
495
496void KIWAY::ExpressMail( FRAME_T aDestination, MAIL_T aCommand, std::string& aPayload,
497 wxWindow* aSource, bool aFromOtherThread )
498{
499 std::unique_ptr<KIWAY_MAIL_EVENT> mail =
500 std::make_unique<KIWAY_MAIL_EVENT>( aDestination, aCommand, aPayload, aSource );
501
502 if( aFromOtherThread )
503 QueueEvent( mail.release() );
504 else
505 ProcessEvent( *mail );
506}
507
508
509void KIWAY::GetActions( std::vector<TOOL_ACTION*>& aActions ) const
510{
512 aActions.push_back( action );
513}
514
515
516void KIWAY::SetLanguage( int aLanguage )
517{
518 wxString errMsg;
519 bool ret = false;
520
521 {
522 // Only allow the traces to be logged by wx. We use our own system to log when the
523 // OS doesn't support the language, so we want to hide the wx error.
524 WX_LOG_TRACE_ONLY logtraceOnly;
525 Pgm().SetLanguageIdentifier( aLanguage );
526 ret = Pgm().SetLanguage( errMsg );
527 }
528
529 if( !ret )
530 {
531 wxString lang;
532
533 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
534 {
535 if( aLanguage == LanguagesList[ii].m_KI_Lang_Identifier )
536 {
537 if( LanguagesList[ii].m_DoNotTranslate )
538 lang = LanguagesList[ii].m_Lang_Label;
539 else
540 lang = wxGetTranslation( LanguagesList[ii].m_Lang_Label );
541
542 break;
543 }
544 }
545
546 DisplayErrorMessage( nullptr,
547 wxString::Format( _( "Unable to switch language to %s" ), lang ),
548 errMsg );
549 return;
550 }
551
552#if 1
553 // This is a risky hack that goes away if we allow the language to be
554 // set only from the top most frame if !Kiface.IsSingle()
555
556 // Only for the C++ project manager, and not for the python one and not for
557 // single_top do we look for the EDA_BASE_FRAME as the top level window.
558 // For single_top this is not needed because that window is registered in
559 // the array below.
561 {
562 // A dynamic_cast could be better, but creates link issues
563 // (some basic_frame functions not found) on some platforms,
564 // so a static_cast is used.
565 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
566
567 if ( top )
568 {
569 top->ShowChangedLanguage();
570 wxCommandEvent e( EDA_LANG_CHANGED );
571 top->GetEventHandler()->ProcessEvent( e );
572 }
573 }
574#endif
575
576 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
577 {
578 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
579
580 if( frame )
581 {
582 frame->ShowChangedLanguage();
583 wxCommandEvent e( EDA_LANG_CHANGED );
584 frame->GetEventHandler()->ProcessEvent( e );
585 }
586 }
587}
588
589
591{
593 {
594 // A dynamic_cast could be better, but creates link issues
595 // (some basic_frame functions not found) on some platforms,
596 // so a static_cast is used.
597 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
598
599 if( top )
600 top->CommonSettingsChanged( aFlags );
601 }
602
603 if( aFlags & ENVVARS_CHANGED )
604 {
605 if( KIFACE* sch = KiFACE( FACE_SCH, false ) )
606 sch->PreloadLibraries( this );
607
608 if( KIFACE* pcb = KiFACE( FACE_PCB, false ) )
609 pcb->PreloadLibraries( this );
610 }
611
612 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
613 {
614 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
615
616 if( frame )
617 frame->CommonSettingsChanged( aFlags );
618 }
619}
620
621
623{
625 {
626 // A dynamic_cast could be better, but creates link issues
627 // (some basic_frame functions not found) on some platforms,
628 // so a static_cast is used.
629 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
630
631 if( top )
632 top->ClearFileHistory();
633 }
634
635 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
636 {
637 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
638
639 if( frame )
640 frame->ClearFileHistory();
641 }
642}
643
644
646{
647 // Skip project change notifications during application shutdown to avoid
648 // clearing savers and re-registering them unnecessarily
649 if( PgmOrNull() && Pgm().m_Quitting )
650 return;
651
652 APP_MONITOR::AddNavigationBreadcrumb( "Changing project", "kiway.projectchanged" );
653
655
657 {
658 // A dynamic_cast could be better, but creates link issues
659 // (some basic_frame functions not found) on some platforms,
660 // so a static_cast is used.
661 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
662
663 if( top )
664 top->ProjectChanged();
665 }
666
667 // Cancel an in-progress load of libraries; handled through the schematic and PCB ifaces.
668 // Use doLoad=false: only notify already-loaded kifaces, don't force-load absent ones
669 // (e.g. eeschema kiface isn't available in standalone pcbnew).
670 if ( KIFACE* schface = KiFACE( KIWAY::FACE_SCH, false ) )
671 schface->ProjectChanged();
672
673 if ( KIFACE* pcbface = KiFACE( KIWAY::FACE_PCB, false ) )
674 pcbface->ProjectChanged();
675
676 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
677 {
678 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
679
680 if( frame )
681 frame->ProjectChanged();
682 }
683}
684
685
687{
688 return wxWindow::FindWindowById( m_blockingDialog );
689}
690
691
692void KIWAY::SetBlockingDialog( wxWindow* aWin )
693{
694 if( !aWin )
695 m_blockingDialog = wxID_NONE;
696 else
697 m_blockingDialog = aWin->GetId();
698}
699
700
701bool KIWAY::ProcessEvent( wxEvent& aEvent )
702{
703 KIWAY_MAIL_EVENT* mail = dynamic_cast<KIWAY_MAIL_EVENT*>( &aEvent );
704
705 if( mail )
706 {
707 FRAME_T dest = mail->Dest();
708
709 // see if recipient is alive
710 KIWAY_PLAYER* alive = Player( dest, false );
711
712 if( alive )
713 {
714#if 1
715 return alive->ProcessEvent( aEvent );
716#else
717 alive->KiwayMailIn( *mail );
718 return true;
719#endif
720 }
721 }
722
723 return false;
724}
725
726
727void KIWAY::QueueEvent( wxEvent* aEvent )
728{
729 KIWAY_MAIL_EVENT* mail = dynamic_cast<KIWAY_MAIL_EVENT*>( aEvent );
730
731 if( mail )
732 {
733 FRAME_T dest = mail->Dest();
734
735 // see if recipient is alive
736 KIWAY_PLAYER* alive = Player( dest, false );
737
738 if( alive )
739 {
740 alive->GetEventHandler()->QueueEvent( aEvent );
741 }
742 }
743}
744
745
746int KIWAY::ProcessJob( KIWAY::FACE_T aFace, JOB* job, REPORTER* aReporter, PROGRESS_REPORTER* aProgressReporter )
747{
748 KIFACE* kiface = KiFACE( aFace );
749
750 return kiface->HandleJob( job, aReporter, aProgressReporter );
751}
752
753
754bool KIWAY::ProcessJobConfigDialog( KIWAY::FACE_T aFace, JOB* aJob, wxWindow* aWindow )
755{
756 KIFACE* kiface = KiFACE( aFace );
757
758 return kiface->HandleJobConfig( aJob, aWindow );
759}
760
761
762bool KIWAY::ProcessApiOpenDocument( KIWAY::FACE_T aFace, const wxString& aPath, KICAD_API_SERVER* aServer,
763 wxString* aError )
764{
765 KIFACE* kiface = KiFACE( aFace );
766
767 if( !kiface )
768 {
769 if( aError )
770 *aError = wxS( "Failed to load requested face" );
771
772 return false;
773 }
774
775 return kiface->HandleApiOpenDocument( aPath, aServer, aError );
776}
777
778
779bool KIWAY::ProcessApiCloseDocument( KIWAY::FACE_T aFace, const wxString& aPath, KICAD_API_SERVER* aServer,
780 wxString* aError )
781{
782 KIFACE* kiface = KiFACE( aFace );
783
784 if( !kiface )
785 {
786 if( aError )
787 *aError = wxS( "Failed to load requested face" );
788
789 return false;
790 }
791
792 return kiface->HandleApiCloseDocument( aPath, aServer, aError );
793}
794
795
797{
799 {
800 // A dynamic_cast could be better, but creates link issues
801 // (some basic_frame functions not found) on some platforms,
802 // so a static_cast is used.
803 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
804
805 if( top )
806 top->Close( false );
807 }
808}
809
810
812{
813 for( KIFACE* i : m_kiface )
814 {
815 if( i )
816 i->OnKifaceEnd();
817 }
818}
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_ROUTED_EVENT messages from other players.
void OnKiCadExit()
Definition kiway.cpp:796
bool ProcessJobConfigDialog(KIWAY::FACE_T aFace, JOB *aJob, wxWindow *aWindow)
Definition kiway.cpp:754
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:398
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 *aJob, REPORTER *aReporter=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Definition kiway.cpp:746
void SetBlockingDialog(wxWindow *aWin)
Definition kiway.cpp:692
LOCAL_HISTORY * m_local_history
Definition kiway.h:530
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:451
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:339
wxWindowID m_blockingDialog
Definition kiway.h:520
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr, bool aFromOtherThread=false)
Send aPayload to aDestination from aSource.
Definition kiway.cpp:496
wxWindow * GetBlockingDialog()
Gets the window pointer to the blocking dialog (to send it signals)
Definition kiway.cpp:686
static std::array< KIFACE *, KIWAY_FACE_COUNT > m_kiface
Definition kiway.h:513
void ClearFileHistory()
Clear the wxWidgets file history on each open frame.
Definition kiway.cpp:622
bool ProcessApiCloseDocument(KIWAY::FACE_T aFace, const wxString &aPath, KICAD_API_SERVER *aServer, wxString *aError=nullptr)
Definition kiway.cpp:779
wxFrame * m_top
Definition kiway.h:518
virtual void SetLanguage(int aLanguage)
Change the language and then calls ShowChangedLanguage() on all #KIWAY_PLAYERs.
Definition kiway.cpp:516
bool ProcessApiOpenDocument(KIWAY::FACE_T aFace, const wxString &aPath, KICAD_API_SERVER *aServer, wxString *aError=nullptr)
Definition kiway.cpp:762
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition kiway.cpp:207
FACE_T
Known KIFACE implementations.
Definition kiway.h:317
@ FACE_SCH
eeschema DSO
Definition kiway.h:318
@ FACE_PL_EDITOR
Definition kiway.h:322
@ FACE_PCB
pcbnew DSO
Definition kiway.h:319
@ FACE_CVPCB
Definition kiway.h:320
@ FACE_GERBVIEW
Definition kiway.h:321
@ FACE_BMP2CMP
Definition kiway.h:324
@ FACE_PCB_CALCULATOR
Definition kiway.h:323
KIWAY_PLAYER * GetPlayerFrame(FRAME_T aFrameType)
Definition kiway.cpp:380
bool ProcessEvent(wxEvent &aEvent) override
Definition kiway.cpp:701
static std::array< int, KIWAY_FACE_COUNT > m_kiface_version
Definition kiway.h:514
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:479
std::atomic< wxWindowID > m_playerFrameId[KIWAY_PLAYER_COUNT]
Definition kiway.h:528
void OnKiwayEnd()
Definition kiway.cpp:811
KIWAY(int aCtlBits, wxFrame *aTop=nullptr)
Definition kiway.cpp:50
LOCAL_HISTORY & LocalHistory()
Return the LOCAL_HISTORY associated with this KIWAY.
Definition kiway.h:422
virtual void CommonSettingsChanged(int aFlags=0)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition kiway.cpp:590
~KIWAY()
Definition kiway.cpp:67
void QueueEvent(wxEvent *aEvent) override
Definition kiway.cpp:727
void PlayerDidClose(FRAME_T aFrameType)
Notifies a Kiway that a player has been closed.
Definition kiway.cpp:490
virtual void GetActions(std::vector< TOOL_ACTION * > &aActions) const
Append all registered actions to the given list.
Definition kiway.cpp:509
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:645
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition kiway.cpp:201
int m_ctl
Definition kiway.h:516
Simple local history manager built on libgit2.
void ClearAllSavers()
Clear all registered savers.
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:789
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:676
virtual const wxString & GetExecutablePath() const
Definition pgm_base.cpp:854
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:124
virtual bool SetLanguage(wxString &aErrMsg, bool first_time=false)
Set the dictionary file name for internationalization.
Definition pgm_base.cpp:534
A progress reporter interface for use in multi-threaded environments.
Container for project specific data.
Definition project.h:62
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:71
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:59
@ 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_BM2CMP
Definition frame_type.h:57
@ 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:66
@ 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_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define KFCTL_CPP_PROJECT_SUITE
Running under C++ project mgr, possibly with others.
Definition kiway.h:160
KIFACE * KIFACE_GETTER_FUNC(int *aKIFACEversion, int aKIWAYversion, PGM_BASE *aProgram)
Point to the one and only KIFACE export.
Definition kiway.h:549
#define KIFACE_INSTANCE_NAME_AND_VERSION
Definition kiway.h:113
#define KIFACE_VERSION
Definition kiway.h:108
#define KFCTL_STANDALONE
Running as a standalone Top.
Definition kiway.h:159
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:112
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:87
see class PGM_BASE
Implement a participant in the KIWAY alchemy.
Definition kiway.h:152
IFACE KIFACE_BASE kiface("pcb_test_frame", KIWAY::FACE_PCB)
std::string path
KIBIS top(path, &reporter)
#define ENVVARS_CHANGED