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