KiCad PCB EDA Suite
Loading...
Searching...
No Matches
single_top.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, 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
26/*
27
28 This is a program launcher for a single KIFACE DSO. It only mimics a KIWAY,
29 not actually implements one, since only a single DSO is supported by it.
30
31 It is compiled multiple times, once for each standalone program and as such
32 gets different compiler command line supplied #defines from CMake.
33
34*/
35
36
37#include <typeinfo>
38#include <wx/cmdline.h>
39#include <wx/dialog.h>
40#include <wx/filename.h>
41#include <wx/stdpaths.h>
42#include <wx/snglinst.h>
43#include <wx/html/htmlwin.h>
44
45#include <kiway.h>
46#include <build_version.h>
47#include <pgm_base.h>
48#include <kiway_player.h>
49#include <macros.h>
50#include <confirm.h>
53#include <paths.h>
54
55#include <kiplatform/app.h>
57
58#include <git2.h>
59
60#ifdef KICAD_USE_SENTRY
61#include <sentry.h>
62#endif
63
64#ifdef KICAD_IPC_API
65#include <api/api_server.h>
66#endif
67
68// Only a single KIWAY is supported in this single_top top level component,
69// which is dedicated to loading only a single DSO.
71
72
73// implement a PGM_BASE and a wxApp side by side:
74
78static struct PGM_SINGLE_TOP : public PGM_BASE
79{
80 bool OnPgmInit();
81
82 void OnPgmExit()
83 {
84
86
87#ifdef KICAD_IPC_API
88 m_api_server.reset();
89#endif
90
92 {
94 m_settings_manager->Save();
95 }
96
97 // Destroy everything in PGM_BASE, especially wxSingleInstanceCheckerImpl
98 // earlier than wxApp and earlier than static destruction would.
100 git_libgit2_shutdown();
101 }
102
103 void MacOpenFile( const wxString& aFileName ) override
104 {
105 wxFileName filename( aFileName );
106
107 if( filename.FileExists() )
108 {
109 #if 0
110 // this pulls in EDA_DRAW_FRAME type info, which we don't want in
111 // the single_top link image.
112 KIWAY_PLAYER* frame = dynamic_cast<KIWAY_PLAYER*>( App().GetTopWindow() );
113 #else
114 KIWAY_PLAYER* frame = (KIWAY_PLAYER*) App().GetTopWindow();
115 #endif
116 if( frame )
117 {
118 if( wxWindow* blocking_win = frame->Kiway().GetBlockingDialog() )
119 blocking_win->Close( true );
120
121 frame->OpenProjectFiles( std::vector<wxString>( 1, aFileName ) );
122 }
123 }
124 }
125
127
128
129// A module to allow Html module initialization/cleanup
130// When a wxHtmlWindow is used *only* in a dll/so module, the Html text is displayed
131// as plain text.
132// This helper class is just used to force wxHtmlWinParser initialization
133// see https://groups.google.com/forum/#!topic/wx-users/FF0zv5qGAT0
134class HtmlModule: public wxModule
135{
136public:
138 virtual bool OnInit() override { AddDependency( CLASSINFO( wxHtmlWinParser ) ); return true; };
139 virtual void OnExit() override {};
140
141private:
143};
144
146
147
148#ifdef NDEBUG
149// Define a custom assertion handler
150void CustomAssertHandler( const wxString& file,
151 int line,
152 const wxString& func,
153 const wxString& cond,
154 const wxString& msg )
155{
156 Pgm().HandleAssert( file, line, func, cond, msg );
157}
158#endif
159
160
165struct APP_SINGLE_TOP : public wxApp
166{
167 APP_SINGLE_TOP() : wxApp()
168 {
169 SetPgm( &program );
170
171 // Init the environment each platform wants
173 }
174
175
176 bool OnInit() override
177 {
178#ifdef NDEBUG
179 // These checks generate extra assert noise
180 wxSizerFlags::DisableConsistencyChecks();
181 wxDISABLE_DEBUG_SUPPORT();
182 wxSetAssertHandler( CustomAssertHandler );
183#endif
184
185 // Perform platform-specific init tasks
186 if( !KIPLATFORM::APP::Init() )
187 return false;
188
189#ifndef DEBUG
190 // Enable logging traces to the console in release build.
191 // This is usually disabled, but it can be useful for users to run to help
192 // debug issues and other problems.
193 if( wxGetEnv( wxS( "KICAD_ENABLE_WXTRACE" ), nullptr ) )
194 {
195 wxLog::EnableLogging( true );
196 wxLog::SetLogLevel( wxLOG_Trace );
197 }
198#endif
199
200 // Force wxHtmlWinParser initialization when a wxHtmlWindow is used only
201 // in a shared library (.so or .dll file)
202 // Otherwise the Html text is displayed as plain text.
203 HtmlModule html_init;
204
205 try
206 {
207 return program.OnPgmInit();
208 }
209 catch( ... )
210 {
211 Pgm().HandleException( std::current_exception() );
212 }
213
215
216 return false;
217 }
218
219 int OnExit() override
220 {
222 return wxApp::OnExit();
223 }
224
225 int OnRun() override
226 {
227 int ret = -1;
228
229 try
230 {
231 ret = wxApp::OnRun();
232 }
233 catch(...)
234 {
235 Pgm().HandleException( std::current_exception() );
236 }
237
238 return ret;
239 }
240
241 int FilterEvent( wxEvent& aEvent ) override
242 {
243 if( aEvent.GetEventType() == wxEVT_SHOW )
244 {
245 wxShowEvent& event = static_cast<wxShowEvent&>( aEvent );
246 wxDialog* dialog = dynamic_cast<wxDialog*>( event.GetEventObject() );
247
248 std::vector<void*>& dlgs = Pgm().m_ModalDialogs;
249
250 if( dialog )
251 {
252 if( event.IsShown() && dialog->IsModal() )
253 {
254 dlgs.push_back( dialog );
255 }
256 // Under GTK, sometimes the modal flag is cleared before hiding
257 else if( !event.IsShown() && !dlgs.empty() )
258 {
259 // If we close the expected dialog, remove it from our stack
260 if( dlgs.back() == dialog )
261 dlgs.pop_back();
262 // If an out-of-order, remove all dialogs added after the closed one
263 else if( auto it = std::find( dlgs.begin(), dlgs.end(), dialog ); it != dlgs.end() )
264 dlgs.erase( it, dlgs.end() );
265 }
266 }
267 }
268
269 return Event_Skip;
270 }
271
272#if defined( DEBUG )
280 virtual bool OnExceptionInMainLoop() override
281 {
282 try
283 {
284 throw;
285 }
286 catch( ... )
287 {
288 Pgm().HandleException( std::current_exception() );
289 }
290
291 return false; // continue on. Return false to abort program
292 }
293#endif
294
295#ifdef __WXMAC__
296
304 void MacOpenFile( const wxString& aFileName ) override
305 {
306 Pgm().MacOpenFile( aFileName );
307 }
308
309#endif
310};
311
312IMPLEMENT_APP( APP_SINGLE_TOP )
313
314
315bool PGM_SINGLE_TOP::OnPgmInit()
316{
317#if defined(DEBUG)
318 wxString absoluteArgv0 = wxStandardPaths::Get().GetExecutablePath();
319
320 if( !wxIsAbsolutePath( absoluteArgv0 ) )
321 {
322 wxLogError( wxT( "No meaningful argv[0]" ) );
323 return false;
324 }
325#endif
326
327 // Initialize the git library before trying to initialize individual programs
328 int gitInit = git_libgit2_init();
329
330 if( gitInit < 0 )
331 {
332 const git_error* err = git_error_last();
333 wxString msg = wxS( "Failed to initialize git library" );
334
335 if( err && err->message )
336 msg += wxS( ": " ) + wxString::FromUTF8( err->message );
337
338 wxLogError( msg );
339 return false;
340 }
341
342 // Not all KiCad applications use the python stuff. skip python init
343 // for these apps.
344 bool skip_python_initialization = false;
345
346#if defined( BITMAP_2_CMP ) || defined( PL_EDITOR ) || defined( GERBVIEW ) || \
347 defined( PCB_CALCULATOR_BUILD )
348 skip_python_initialization = true;
349#endif
350
351 if( !InitPgm( false, skip_python_initialization ) )
352 {
353 // Clean up
354 OnPgmExit();
355 return false;
356 }
357
358#if !defined(BUILD_KIWAY_DLL)
359
360 // Only bitmap2component and pcb_calculator use this code currently, as they
361 // are not split to use single_top as a link image separate from a *.kiface.
362 // i.e. they are single part link images so don't need to load a *.kiface.
363
364 // Get the getter, it is statically linked into this binary image.
365 KIFACE_GETTER_FUNC* ki_getter = &KIFACE_GETTER;
366
367 int kiface_version;
368
369 // Get the KIFACE.
370 KIFACE* kiface = ki_getter( &kiface_version, KIFACE_VERSION, this );
371
372 // Trick the KIWAY into thinking it loaded a KIFACE, by recording the KIFACE
373 // in the KIWAY. It needs to be there for KIWAY::OnKiwayEnd() anyways.
374 Kiway.set_kiface( KIWAY::KifaceType( TOP_FRAME ), kiface );
375#endif
376
377 // Tell the settings manager about the current Kiway
379
381
382#ifdef KICAD_IPC_API
383 // Create the API server thread once the app event loop exists
384 m_api_server = std::make_unique<KICAD_API_SERVER>();
385#endif
386
387 // Use KIWAY to create a top window, which registers its existence also.
388 // "TOP_FRAME" is a macro that is passed on compiler command line from CMake,
389 // and is one of the types in FRAME_T.
390 KIWAY_PLAYER* frame = Kiway.Player( TOP_FRAME, true );
391
392 if( frame == nullptr )
393 {
394 // Clean up
395 OnPgmExit();
396 return false;
397 }
398
399 Kiway.SetTop( frame );
400
401 App().SetTopWindow( frame ); // wxApp gets a face.
402 App().SetAppDisplayName( frame->GetAboutTitle() );
403
404 wxString relaunchDisplayName = frame->GetAboutTitle() + " " + GetMajorMinorVersion();
406
407 // Allocate a slice of time to show the frame and update wxWidgets widgets
408 // (especially setting valid sizes) after creating frame and before calling
409 // OpenProjectFiles() that can update/use some widgets.
410 // The 2 calls to wxSafeYield are needed on wxGTK for best results.
411 wxSafeYield();
412 HideSplash();
413 frame->Show();
414 wxSafeYield();
415
416 // Now after the frame processing, the rest of the positional args are files
417 std::vector<wxString> fileArgs;
418
419
420 static const wxCmdLineEntryDesc desc[] = {
421 { wxCMD_LINE_PARAM, nullptr, nullptr, "File to load", wxCMD_LINE_VAL_STRING,
422 wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
423 { wxCMD_LINE_NONE, nullptr, nullptr, nullptr, wxCMD_LINE_VAL_NONE, 0 }
424 };
425
426 wxCmdLineParser parser( App().argc, App().argv );
427 parser.SetDesc( desc );
428 parser.Parse( false );
429
430 if( parser.GetParamCount() )
431 {
432 /*
433 gerbview handles multiple project data files, i.e. gerber files on
434 cmd line. Others currently do not, they handle only one. For common
435 code simplicity we simply pass all the arguments in however, each
436 program module can do with them what they want, ignore, complain
437 whatever. We don't establish policy here, as this is a multi-purpose
438 launcher.
439 */
440
441 for( size_t i = 0; i < parser.GetParamCount(); i++ )
442 fileArgs.push_back( parser.GetParam( i ) );
443
444 // special attention to a single argument: argv[1] (==argSet[0])
445 if( fileArgs.size() == 1 )
446 {
447 wxFileName argv1( fileArgs[0] );
448
449#if defined(PGM_DATA_FILE_EXT)
450 // PGM_DATA_FILE_EXT, if present, may be different for each compile,
451 // it may come from CMake on the compiler command line, but often does not.
452 // This facility is mostly useful for those program footprints
453 // supporting a single argv[1].
454 if( !argv1.GetExt() )
455 argv1.SetExt( wxT( PGM_DATA_FILE_EXT ) );
456#endif
457 argv1.MakeAbsolute();
458
459 fileArgs[0] = argv1.GetFullPath();
460 }
461
462 frame->OpenProjectFiles( fileArgs );
463 }
464
465#ifdef KICAD_IPC_API
466 m_api_server->SetReadyToReply();
467#endif
468
469 return true;
470}
wxString GetMajorMinorVersion()
Get only the major and minor version in a string major.minor.
const wxString & GetAboutTitle() const
virtual bool OnInit() override
Definition: single_top.cpp:138
virtual void OnExit() override
Definition: single_top.cpp:139
wxDECLARE_DYNAMIC_CLASS(HtmlModule)
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:65
virtual bool OpenProjectFiles(const std::vector< wxString > &aFileList, int aCtl=0)
Open a project or set of files given by aFileList.
Definition: kiway_player.h:113
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:286
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:395
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:333
bool set_kiface(FACE_T aFaceType, KIFACE *aKiface)
Definition: kiway.h:451
wxWindow * GetBlockingDialog()
Gets the window pointer to the blocking dialog (to send it signals)
Definition: kiway.cpp:637
void OnKiwayEnd()
Definition: kiway.cpp:709
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:85
static const wxString & GetExecutablePath()
Definition: paths.cpp:629
Container for data for KiCad programs.
Definition: pgm_base.h:103
virtual wxApp & App()
Return a bare naked wxApp which may come from wxPython, SINGLE_TOP, or kicad.exe.
Definition: pgm_base.cpp:183
virtual void MacOpenFile(const wxString &aFileName)=0
Specific to MacOSX (not used under Linux or Windows).
std::unique_ptr< SETTINGS_MANAGER > m_settings_manager
Definition: pgm_base.h:375
void Destroy()
Definition: pgm_base.cpp:173
std::vector< void * > m_ModalDialogs
Definition: pgm_base.h:355
void HandleException(std::exception_ptr aPtr)
A exception handler to be used at the top level if exceptions bubble up that for.
Definition: pgm_base.cpp:826
void HandleAssert(const wxString &aFile, int aLine, const wxString &aFunc, const wxString &aCond, const wxString &aMsg)
A common assert handler to be used between single_top and kicad.
Definition: pgm_base.cpp:851
virtual const wxString & GetExecutablePath() const
Definition: pgm_base.cpp:879
void SaveCommonSettings()
Save the program (process) settings subset which are stored .kicad_common.
Definition: pgm_base.cpp:556
T * RegisterSettings(T *aSettings, bool aLoadNow=true)
Take ownership of the pointer passed in.
void SetKiway(KIWAY *aKiway)
Associate this setting manager with the given Kiway.
This file is part of the common library.
KIFACE * KIFACE_GETTER_FUNC(int *aKIFACEversion, int aKIWAYversion, PGM_BASE *aProgram)
Point to the one and only KIFACE export.
Definition: kiway.h:506
#define KIFACE_GETTER
Definition: kiway.h:110
#define KIFACE_VERSION
The KIWAY and KIFACE classes are used to communicate between various process modules,...
Definition: kiway.h:109
#define KFCTL_STANDALONE
Running as a standalone Top.
Definition: kiway.h:160
This file contains miscellaneous commonly used macros and functions.
bool Init()
Perform application-specific initialization tasks.
Definition: unix/app.cpp:40
void Init()
Perform environment initialization tasks.
void SetAppDetailsForWindow(wxWindow *aWindow, const wxString &aRelaunchCommand, const wxString &aRelaunchDisplayName)
Sets the relaunch command for taskbar pins, this is intended for Windows.
SETTINGS_MANAGER * GetSettingsManager()
void SetPgm(PGM_BASE *pgm)
Definition: pgm_base.cpp:916
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:902
see class PGM_BASE
PGM_SINGLE_TOP program
wxIMPLEMENT_DYNAMIC_CLASS(HtmlModule, wxModule)
KIWAY Kiway(KFCTL_STANDALONE)
Implement a bare naked wxApp (so that we don't become dependent on functionality in a wxApp derivativ...
Definition: single_top.cpp:166
int OnRun() override
Definition: single_top.cpp:225
int OnExit() override
Definition: single_top.cpp:219
bool OnInit() override
Definition: single_top.cpp:176
int FilterEvent(wxEvent &aEvent) override
Definition: single_top.cpp:241
Implement a participant in the KIWAY alchemy.
Definition: kiway.h:153
Implement PGM_BASE with its own OnPgmInit() and OnPgmExit().
Definition: single_top.cpp:79
void MacOpenFile(const wxString &aFileName) override
Specific to MacOSX (not used under Linux or Windows).
Definition: single_top.cpp:103
void OnPgmExit()
Definition: single_top.cpp:82
IFACE KIFACE_BASE kiface("pcb_test_frame", KIWAY::FACE_PCB)