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