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#ifdef KICAD_WIN32_VERIFY_CODESIGN
240 bool codeSignOk = KIPLATFORM::ENV::VerifyFileSignature( dname );
241
242 if( !codeSignOk )
243 THROW_IO_ERRORF( _( "Failed to verify kiface library '%s' signature." ), dname );
244#endif
245
246 wxDynamicLibrary dso;
247 void* addr = nullptr;
248
249 // For some reason wxDynamicLibrary::Load() crashes in some languages
250 // (chinese for instance) when loading the dynamic library.
251 // The crash happens for Eeschema.
252 // So switch to "C" locale during loading (LC_COLLATE is enough).
253 int lc_new_type = LC_COLLATE;
254 std::string user_locale = setlocale( lc_new_type, nullptr );
255 setlocale( lc_new_type, "C" );
256
257 bool success = dso.Load( dname, wxDL_VERBATIM | wxDL_NOW | wxDL_GLOBAL );
258
259 setlocale( lc_new_type, user_locale.c_str() );
260
261 APP_MONITOR::AddNavigationBreadcrumb( wxString::Format( "Loading kiface %d", aFaceId ), "kiway.kiface" );
262
263 if( !success )
264 {
265 // Failure: error reporting UI was done via wxLogSysError().
266 // No further reporting required here. Apparently this is not true on all
267 // platforms and/or wxWidgets builds and KiCad will crash. Throwing the exception
268 // here and catching it in the KiCad launcher resolves the crash issue. See bug
269 // report https://bugs.launchpad.net/kicad/+bug/1577786.
270
271 THROW_IO_ERRORF( _( "Failed to load kiface library '%s'." ), dname );
272 }
273 else if( ( addr = dso.GetSymbol( wxT( KIFACE_INSTANCE_NAME_AND_VERSION ) ) ) == nullptr )
274 {
275 // Failure: error reporting UI was done via wxLogSysError().
276 // No further reporting required here. Assume the same thing applies here as
277 // above with the Load() call. This has not been tested.
278 THROW_IO_ERRORF( _( "Could not read instance name and version from kiface library '%s'." ), dname );
279 }
280 else
281 {
282 KIFACE_GETTER_FUNC* ki_getter = (KIFACE_GETTER_FUNC*) addr;
283
284 KIFACE* kiface = ki_getter( &m_kiface_version[aFaceId], KIFACE_VERSION, &Pgm() );
285
286 // KIFACE_GETTER_FUNC function comment (API) says the non-NULL is unconditional.
287 wxASSERT_MSG( kiface, wxT( "attempted DSO has a bug, failed to return a KIFACE*" ) );
288
289 wxDllType dsoHandle = dso.Detach();
290
291 bool startSuccess = false;
292
293 // Give the DSO a single chance to do its "process level" initialization.
294 // "Process level" specifically means stay away from any projects in there.
295
296 try
297 {
298 startSuccess = kiface->OnKifaceStart( &Pgm(), m_ctl, this );
299 }
300 catch (...)
301 {
302 // OnKiFaceStart may generate an exception
303 // Before we continue and ultimately unload our module to retry we need
304 // to process the exception before we delete the free the memory space the
305 // exception resides in
306 Pgm().HandleException( std::current_exception() );
307 }
308
309 if( startSuccess )
310 {
311 return m_kiface[aFaceId] = kiface;
312 }
313 else
314 {
315 // Usually means canceled initial global library setup
316 // But it could have been an exception/failure
317 // Let the module go out of scope to unload
318 dso.Attach( dsoHandle );
319
320 return nullptr;
321 }
322 }
323 }
324
325 return nullptr;
326}
327
328
330{
331 switch( aFrameType )
332 {
333 case FRAME_SCH:
335 case FRAME_SCH_VIEWER:
337 case FRAME_SIMULATOR:
338 return FACE_SCH;
339
340 case FRAME_PCB_EDITOR:
346 return FACE_PCB;
347
348 case FRAME_CVPCB:
350 return FACE_CVPCB;
351
352 case FRAME_GERBER:
353 return FACE_GERBVIEW;
354
355 case FRAME_PL_EDITOR:
356 return FACE_PL_EDITOR;
357
358 case FRAME_CALC:
359 return FACE_PCB_CALCULATOR;
360
361 case FRAME_BM2CMP:
362 return FACE_BMP2CMP;
363
364 default:
365 return FACE_T( -1 );
366 }
367}
368
369
371{
372 wxWindowID storedId = m_playerFrameId[aFrameType];
373
374 if( storedId == wxID_NONE )
375 return nullptr;
376
377 wxWindow* frame = wxWindow::FindWindowById( storedId );
378
379 // Since wxWindow::FindWindow*() is not cheap (especially if the window does not exist),
380 // clear invalid entries to save CPU on repeated calls that do not lead to frame creation
381 if( !frame )
382 m_playerFrameId[aFrameType].compare_exchange_strong( storedId, wxID_NONE );
383
384 return static_cast<KIWAY_PLAYER*>( frame );
385}
386
387
388KIWAY_PLAYER* KIWAY::Player( FRAME_T aFrameType, bool doCreate, wxTopLevelWindow* aParent )
389{
390 // Since this will be called from python, cannot assume that code will
391 // not pass a bad aFrameType.
392 if( (unsigned) aFrameType >= KIWAY_PLAYER_COUNT )
393 {
394 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFrameType" ) );
395 return nullptr;
396 }
397
398 // return the previously opened window
399 KIWAY_PLAYER* frame = GetPlayerFrame( aFrameType );
400
401 if( frame )
402 return frame;
403
404 if( doCreate )
405 {
406 try
407 {
408 wxString msg = wxString::Format( "Creating window type %d", aFrameType );
409 APP_MONITOR::AddNavigationBreadcrumb( msg, "kiway.player" );
410
411 FACE_T face_type = KifaceType( aFrameType );
412 KIFACE* kiface = KiFACE( face_type );
413
414 if( !kiface )
415 return nullptr;
416
417 frame = (KIWAY_PLAYER*) kiface->CreateKiWindow(
418 aParent, // Parent window of frame in modal mode,
419 // NULL in non modal mode
420 aFrameType,
421 this,
422 m_ctl // questionable need, these same flags
423 // were passed to KIFACE::OnKifaceStart()
424 );
425 if( frame )
426 m_playerFrameId[aFrameType].store( frame->GetId() );
427
428 return frame;
429 }
430 catch( ... )
431 {
432 Pgm().HandleException( std::current_exception() );
433 wxLogError( _( "Error loading editor." ) );
434 }
435 }
436
437 return nullptr;
438}
439
440
441bool KIWAY::PlayerClose( FRAME_T aFrameType, bool doForce )
442{
443 // Since this will be called from python, cannot assume that code will
444 // not pass a bad aFrameType.
445 if( (unsigned) aFrameType >= KIWAY_PLAYER_COUNT )
446 {
447 wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFrameType" ) );
448 return false;
449 }
450
451 KIWAY_PLAYER* frame = GetPlayerFrame( aFrameType );
452
453 if( frame == nullptr ) // Already closed
454 return true;
455
456 wxString msg = wxString::Format( "Closing window type %d", aFrameType );
457 APP_MONITOR::AddNavigationBreadcrumb( msg, "kiway.playerclose" );
458
459 if( frame->NonUserClose( doForce ) )
460 {
461 m_playerFrameId[aFrameType] = wxID_NONE;
462 return true;
463 }
464
465 return false;
466}
467
468
469bool KIWAY::PlayersClose( bool doForce )
470{
471 bool ret = true;
472
473 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
474 ret = ret && PlayerClose( FRAME_T( i ), doForce );
475
476 return ret;
477}
478
479
481{
482 m_playerFrameId[aFrameType] = wxID_NONE;
483}
484
485
486void KIWAY::ExpressMail( FRAME_T aDestination, MAIL_T aCommand, std::string& aPayload,
487 wxWindow* aSource, bool aFromOtherThread )
488{
489 std::unique_ptr<KIWAY_MAIL_EVENT> mail =
490 std::make_unique<KIWAY_MAIL_EVENT>( aDestination, aCommand, aPayload, aSource );
491
492 if( aFromOtherThread )
493 QueueEvent( mail.release() );
494 else
495 ProcessEvent( *mail );
496}
497
498
499void KIWAY::GetActions( std::vector<TOOL_ACTION*>& aActions ) const
500{
502 aActions.push_back( action );
503}
504
505
506void KIWAY::SetLanguage( int aLanguage )
507{
508 wxString errMsg;
509 bool ret = false;
510
511 {
512 // Only allow the traces to be logged by wx. We use our own system to log when the
513 // OS doesn't support the language, so we want to hide the wx error.
514 WX_LOG_TRACE_ONLY logtraceOnly;
515 Pgm().SetLanguageIdentifier( aLanguage );
516 ret = Pgm().SetLanguage( errMsg );
517 }
518
519 if( !ret )
520 {
521 wxString lang;
522
523 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
524 {
525 if( aLanguage == LanguagesList[ii].m_KI_Lang_Identifier )
526 {
527 if( LanguagesList[ii].m_DoNotTranslate )
528 lang = LanguagesList[ii].m_Lang_Label;
529 else
530 lang = wxGetTranslation( LanguagesList[ii].m_Lang_Label );
531
532 break;
533 }
534 }
535
536 DisplayErrorMessage( nullptr,
537 wxString::Format( _( "Unable to switch language to %s" ), lang ),
538 errMsg );
539 return;
540 }
541
542#if 1
543 // This is a risky hack that goes away if we allow the language to be
544 // set only from the top most frame if !Kiface.IsSingle()
545
546 // Only for the C++ project manager, and not for the python one and not for
547 // single_top do we look for the EDA_BASE_FRAME as the top level window.
548 // For single_top this is not needed because that window is registered in
549 // the array below.
551 {
552 // A dynamic_cast could be better, but creates link issues
553 // (some basic_frame functions not found) on some platforms,
554 // so a static_cast is used.
555 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
556
557 if ( top )
558 {
559 top->ShowChangedLanguage();
560 wxCommandEvent e( EDA_LANG_CHANGED );
561 top->GetEventHandler()->ProcessEvent( e );
562 }
563 }
564#endif
565
566 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
567 {
568 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
569
570 if( frame )
571 {
572 frame->ShowChangedLanguage();
573 wxCommandEvent e( EDA_LANG_CHANGED );
574 frame->GetEventHandler()->ProcessEvent( e );
575 }
576 }
577}
578
579
581{
583 {
584 // A dynamic_cast could be better, but creates link issues
585 // (some basic_frame functions not found) on some platforms,
586 // so a static_cast is used.
587 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
588
589 if( top )
590 top->CommonSettingsChanged( aFlags );
591 }
592
593 if( aFlags & ENVVARS_CHANGED )
594 {
595 if( KIFACE* sch = KiFACE( FACE_SCH, false ) )
596 sch->PreloadLibraries( this );
597
598 if( KIFACE* pcb = KiFACE( FACE_PCB, false ) )
599 pcb->PreloadLibraries( this );
600 }
601
602 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
603 {
604 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
605
606 if( frame )
607 frame->CommonSettingsChanged( aFlags );
608 }
609}
610
611
613{
615 {
616 // A dynamic_cast could be better, but creates link issues
617 // (some basic_frame functions not found) on some platforms,
618 // so a static_cast is used.
619 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
620
621 if( top )
622 top->ClearFileHistory();
623 }
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 frame->ClearFileHistory();
631 }
632}
633
634
636{
637 // Skip project change notifications during application shutdown to avoid
638 // clearing savers and re-registering them unnecessarily
639 if( PgmOrNull() && Pgm().m_Quitting )
640 return;
641
642 APP_MONITOR::AddNavigationBreadcrumb( "Changing project", "kiway.projectchanged" );
643
645
647 {
648 // A dynamic_cast could be better, but creates link issues
649 // (some basic_frame functions not found) on some platforms,
650 // so a static_cast is used.
651 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
652
653 if( top )
654 top->ProjectChanged();
655 }
656
657 // Cancel an in-progress load of libraries; handled through the schematic and PCB ifaces.
658 // Use doLoad=false: only notify already-loaded kifaces, don't force-load absent ones
659 // (e.g. eeschema kiface isn't available in standalone pcbnew).
660 if ( KIFACE* schface = KiFACE( KIWAY::FACE_SCH, false ) )
661 schface->ProjectChanged();
662
663 if ( KIFACE* pcbface = KiFACE( KIWAY::FACE_PCB, false ) )
664 pcbface->ProjectChanged();
665
666 for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
667 {
668 KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
669
670 if( frame )
671 frame->ProjectChanged();
672 }
673}
674
675
677{
678 return wxWindow::FindWindowById( m_blockingDialog );
679}
680
681
682void KIWAY::SetBlockingDialog( wxWindow* aWin )
683{
684 if( !aWin )
685 m_blockingDialog = wxID_NONE;
686 else
687 m_blockingDialog = aWin->GetId();
688}
689
690
691bool KIWAY::ProcessEvent( wxEvent& aEvent )
692{
693 KIWAY_MAIL_EVENT* mail = dynamic_cast<KIWAY_MAIL_EVENT*>( &aEvent );
694
695 if( mail )
696 {
697 FRAME_T dest = mail->Dest();
698
699 // see if recipient is alive
700 KIWAY_PLAYER* alive = Player( dest, false );
701
702 if( alive )
703 {
704#if 1
705 return alive->ProcessEvent( aEvent );
706#else
707 alive->KiwayMailIn( *mail );
708 return true;
709#endif
710 }
711 }
712
713 return false;
714}
715
716
717void KIWAY::QueueEvent( wxEvent* aEvent )
718{
719 KIWAY_MAIL_EVENT* mail = dynamic_cast<KIWAY_MAIL_EVENT*>( aEvent );
720
721 if( mail )
722 {
723 FRAME_T dest = mail->Dest();
724
725 // see if recipient is alive
726 KIWAY_PLAYER* alive = Player( dest, false );
727
728 if( alive )
729 {
730 alive->GetEventHandler()->QueueEvent( aEvent );
731 }
732 }
733}
734
735
736int KIWAY::ProcessJob( KIWAY::FACE_T aFace, JOB* job, REPORTER* aReporter, PROGRESS_REPORTER* aProgressReporter )
737{
738 KIFACE* kiface = KiFACE( aFace );
739
740 return kiface->HandleJob( job, aReporter, aProgressReporter );
741}
742
743
744bool KIWAY::ProcessJobConfigDialog( KIWAY::FACE_T aFace, JOB* aJob, wxWindow* aWindow )
745{
746 KIFACE* kiface = KiFACE( aFace );
747
748 return kiface->HandleJobConfig( aJob, aWindow );
749}
750
751
752bool KIWAY::ProcessApiOpenDocument( KIWAY::FACE_T aFace, const wxString& aPath, KICAD_API_SERVER* aServer,
753 wxString* aError )
754{
755 KIFACE* kiface = KiFACE( aFace );
756
757 if( !kiface )
758 {
759 if( aError )
760 *aError = wxS( "Failed to load requested face" );
761
762 return false;
763 }
764
765 return kiface->HandleApiOpenDocument( aPath, aServer, aError );
766}
767
768
769bool KIWAY::ProcessApiCloseDocument( KIWAY::FACE_T aFace, const wxString& aPath, KICAD_API_SERVER* aServer,
770 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->HandleApiCloseDocument( aPath, aServer, aError );
783}
784
785
787{
789 {
790 // A dynamic_cast could be better, but creates link issues
791 // (some basic_frame functions not found) on some platforms,
792 // so a static_cast is used.
793 EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
794
795 if( top )
796 top->Close( false );
797 }
798}
799
800
802{
803 for( KIFACE* i : m_kiface )
804 {
805 if( i )
806 i->OnKifaceEnd();
807 }
808}
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:786
bool ProcessJobConfigDialog(KIWAY::FACE_T aFace, JOB *aJob, wxWindow *aWindow)
Definition kiway.cpp:744
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:388
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:736
void SetBlockingDialog(wxWindow *aWin)
Definition kiway.cpp:682
LOCAL_HISTORY * m_local_history
Definition kiway.h:531
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:441
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:329
wxWindowID m_blockingDialog
Definition kiway.h:521
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:486
wxWindow * GetBlockingDialog()
Gets the window pointer to the blocking dialog (to send it signals)
Definition kiway.cpp:676
static std::array< KIFACE *, KIWAY_FACE_COUNT > m_kiface
Definition kiway.h:514
void ClearFileHistory()
Clear the wxWidgets file history on each open frame.
Definition kiway.cpp:612
bool ProcessApiCloseDocument(KIWAY::FACE_T aFace, const wxString &aPath, KICAD_API_SERVER *aServer, wxString *aError=nullptr)
Definition kiway.cpp:769
wxFrame * m_top
Definition kiway.h:519
virtual void SetLanguage(int aLanguage)
Change the language and then calls ShowChangedLanguage() on all #KIWAY_PLAYERs.
Definition kiway.cpp:506
bool ProcessApiOpenDocument(KIWAY::FACE_T aFace, const wxString &aPath, KICAD_API_SERVER *aServer, wxString *aError=nullptr)
Definition kiway.cpp:752
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:370
bool ProcessEvent(wxEvent &aEvent) override
Definition kiway.cpp:691
static std::array< int, KIWAY_FACE_COUNT > m_kiface_version
Definition kiway.h:515
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:469
std::atomic< wxWindowID > m_playerFrameId[KIWAY_PLAYER_COUNT]
Definition kiway.h:529
void OnKiwayEnd()
Definition kiway.cpp:801
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:580
~KIWAY()
Definition kiway.cpp:67
void QueueEvent(wxEvent *aEvent) override
Definition kiway.cpp:717
void PlayerDidClose(FRAME_T aFrameType)
Notifies a Kiway that a player has been closed.
Definition kiway.cpp:480
virtual void GetActions(std::vector< TOOL_ACTION * > &aActions) const
Append all registered actions to the given list.
Definition kiway.cpp:499
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:635
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition kiway.cpp:201
int m_ctl
Definition kiway.h:517
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: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:124
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:72
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_ERRORF(msg,...)
#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:550
#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