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#ifdef KICAD_USE_SENTRY
56#include <sentry.h>
57#endif
58
59// Only a single KIWAY is supported in this single_top top level component,
60// which is dedicated to loading only a single DSO.
62
63
64// implement a PGM_BASE and a wxApp side by side:
65
70static struct PGM_SINGLE_TOP : public PGM_BASE
71{
72 bool OnPgmInit();
73
74 void OnPgmExit()
75 {
77
79 {
81 m_settings_manager->Save();
82 }
83
84 // Destroy everything in PGM_BASE, especially wxSingleInstanceCheckerImpl
85 // earlier than wxApp and earlier than static destruction would.
87 }
88
89 void MacOpenFile( const wxString& aFileName ) override
90 {
91 wxFileName filename( aFileName );
92
93 if( filename.FileExists() )
94 {
95 #if 0
96 // this pulls in EDA_DRAW_FRAME type info, which we don't want in
97 // the single_top link image.
98 KIWAY_PLAYER* frame = dynamic_cast<KIWAY_PLAYER*>( App().GetTopWindow() );
99 #else
100 KIWAY_PLAYER* frame = (KIWAY_PLAYER*) App().GetTopWindow();
101 #endif
102 if( frame )
103 {
104 if( wxWindow* blocking_win = frame->Kiway().GetBlockingDialog() )
105 blocking_win->Close( true );
106
107 frame->OpenProjectFiles( std::vector<wxString>( 1, aFileName ) );
108 }
109 }
110 }
111
113
114
116{
117 return program;
118}
119
120// A module to allow Html module initialization/cleanup
121// When a wxHtmlWindow is used *only* in a dll/so module, the Html text is displayed
122// as plain text.
123// This helper class is just used to force wxHtmlWinParser initialization
124// see https://groups.google.com/forum/#!topic/wx-users/FF0zv5qGAT0
125class HtmlModule: public wxModule
126{
127public:
129 virtual bool OnInit() override { AddDependency( CLASSINFO( wxHtmlWinParser ) ); return true; };
130 virtual void OnExit() override {};
131private:
133};
135
136#ifdef NDEBUG
137// Define a custom assertion handler
138void CustomAssertHandler(const wxString& file,
139 int line,
140 const wxString& func,
141 const wxString& cond,
142 const wxString& msg)
143{
144 Pgm().HandleAssert( file, line, func, cond, msg );
145}
146#endif
147
153struct APP_SINGLE_TOP : public wxApp
154{
155 APP_SINGLE_TOP() : wxApp()
156 {
157 // Init the environment each platform wants
159 }
160
161
162 bool OnInit() override
163 {
164#ifdef NDEBUG
165 // These checks generate extra assert noise
166 wxSizerFlags::DisableConsistencyChecks();
167 wxDISABLE_DEBUG_SUPPORT();
168 wxSetAssertHandler( CustomAssertHandler );
169#endif
170
171 // Perform platform-specific init tasks
172 if( !KIPLATFORM::APP::Init() )
173 return false;
174
175 // Force wxHtmlWinParser initialization when a wxHtmlWindow is used only
176 // in a shared library (.so or .dll file)
177 // Otherwise the Html text is displayed as plain text.
178 HtmlModule html_init;
179
180 try
181 {
182 return program.OnPgmInit();
183 }
184 catch( ... )
185 {
186 Pgm().HandleException( std::current_exception() );
187 }
188
190
191 return false;
192 }
193
194 int OnExit() override
195 {
197 return wxApp::OnExit();
198 }
199
200 int OnRun() override
201 {
202 int ret = -1;
203
204 try
205 {
206 ret = wxApp::OnRun();
207 }
208 catch(...)
209 {
210 Pgm().HandleException( std::current_exception() );
211 }
212
213 return ret;
214 }
215
216 int FilterEvent( wxEvent& aEvent ) override
217 {
218 if( aEvent.GetEventType() == wxEVT_SHOW )
219 {
220 wxShowEvent& event = static_cast<wxShowEvent&>( aEvent );
221 wxDialog* dialog = dynamic_cast<wxDialog*>( event.GetEventObject() );
222
223 std::vector<void*>& dlgs = Pgm().m_ModalDialogs;
224
225 if( dialog )
226 {
227 if( event.IsShown() && dialog->IsModal() )
228 {
229 dlgs.push_back( dialog );
230 }
231 // Under GTK, sometimes the modal flag is cleared before hiding
232 else if( !event.IsShown() && !dlgs.empty() )
233 {
234 // If we close the expected dialog, remove it from our stack
235 if( dlgs.back() == dialog )
236 dlgs.pop_back();
237 // If an out-of-order, remove all dialogs added after the closed one
238 else if( auto it = std::find( dlgs.begin(), dlgs.end(), dialog ) ; it != dlgs.end() )
239 dlgs.erase( it, dlgs.end() );
240 }
241 }
242 }
243
244 return Event_Skip;
245 }
246
247#if defined( DEBUG )
255 virtual bool OnExceptionInMainLoop() override
256 {
257 try
258 {
259 throw;
260 }
261 catch( ... )
262 {
263 Pgm().HandleException( std::current_exception() );
264 }
265
266 return false; // continue on. Return false to abort program
267 }
268#endif
269
270#ifdef __WXMAC__
271
278 void MacOpenFile( const wxString& aFileName ) override
279 {
280 Pgm().MacOpenFile( aFileName );
281 }
282
283#endif
284};
285
286IMPLEMENT_APP( APP_SINGLE_TOP )
287
288
289bool PGM_SINGLE_TOP::OnPgmInit()
290{
291#if defined(DEBUG)
292 wxString absoluteArgv0 = wxStandardPaths::Get().GetExecutablePath();
293
294 if( !wxIsAbsolutePath( absoluteArgv0 ) )
295 {
296 wxLogError( wxT( "No meaningful argv[0]" ) );
297 return false;
298 }
299#endif
300
301 // Not all kicad applications use the python stuff. skip python init
302 // for these apps.
303 bool skip_python_initialization = false;
304#if defined( BITMAP_2_CMP ) || defined( PL_EDITOR ) || defined( GERBVIEW ) ||\
305 defined( PCB_CALCULATOR_BUILD )
306 skip_python_initialization = true;
307#endif
308
309 if( !InitPgm( false, skip_python_initialization ) )
310 {
311 // Clean up
312 OnPgmExit();
313 return false;
314 }
315
316#if !defined(BUILD_KIWAY_DLL)
317
318 // Only bitmap2component and pcb_calculator use this code currently, as they
319 // are not split to use single_top as a link image separate from a *.kiface.
320 // i.e. they are single part link images so don't need to load a *.kiface.
321
322 // Get the getter, it is statically linked into this binary image.
323 KIFACE_GETTER_FUNC* ki_getter = &KIFACE_GETTER;
324
325 int kiface_version;
326
327 // Get the KIFACE.
328 KIFACE* kiface = ki_getter( &kiface_version, KIFACE_VERSION, this );
329
330 // Trick the KIWAY into thinking it loaded a KIFACE, by recording the KIFACE
331 // in the KIWAY. It needs to be there for KIWAY::OnKiwayEnd() anyways.
332 Kiway.set_kiface( KIWAY::KifaceType( TOP_FRAME ), kiface );
333#endif
334
335 // Tell the settings manager about the current Kiway
337
339
340 // Use KIWAY to create a top window, which registers its existence also.
341 // "TOP_FRAME" is a macro that is passed on compiler command line from CMake,
342 // and is one of the types in FRAME_T.
343 KIWAY_PLAYER* frame = Kiway.Player( TOP_FRAME, true );
344
345 if( frame == nullptr )
346 {
347 return false;
348 }
349
350 Kiway.SetTop( frame );
351
352 App().SetTopWindow( frame ); // wxApp gets a face.
353 App().SetAppDisplayName( frame->GetAboutTitle() );
354
355 // Allocate a slice of time to show the frame and update wxWidgets widgets
356 // (especially setting valid sizes) after creating frame and before calling
357 // OpenProjectFiles() that can update/use some widgets.
358 // The 2 calls to wxSafeYield are needed on wxGTK for best results.
359 wxSafeYield();
360 HideSplash();
361 frame->Show();
362 wxSafeYield();
363
364 // Now after the frame processing, the rest of the positional args are files
365 std::vector<wxString> fileArgs;
366
367
368 static const wxCmdLineEntryDesc desc[] = {
369 { wxCMD_LINE_PARAM, nullptr, nullptr, "File to load", wxCMD_LINE_VAL_STRING,
370 wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
371 { wxCMD_LINE_NONE, nullptr, nullptr, nullptr, wxCMD_LINE_VAL_NONE, 0 }
372 };
373
374 wxCmdLineParser parser( App().argc, App().argv );
375 parser.SetDesc( desc );
376 parser.Parse( false );
377 if( parser.GetParamCount() )
378 {
379 /*
380 gerbview handles multiple project data files, i.e. gerber files on
381 cmd line. Others currently do not, they handle only one. For common
382 code simplicity we simply pass all the arguments in however, each
383 program module can do with them what they want, ignore, complain
384 whatever. We don't establish policy here, as this is a multi-purpose
385 launcher.
386 */
387
388 for( size_t i = 0; i < parser.GetParamCount(); i++ )
389 fileArgs.push_back( parser.GetParam( i ) );
390
391 // special attention to a single argument: argv[1] (==argSet[0])
392 if( fileArgs.size() == 1 )
393 {
394 wxFileName argv1( fileArgs[0] );
395
396#if defined(PGM_DATA_FILE_EXT)
397 // PGM_DATA_FILE_EXT, if present, may be different for each compile,
398 // it may come from CMake on the compiler command line, but often does not.
399 // This facility is mostly useful for those program footprints
400 // supporting a single argv[1].
401 if( !argv1.GetExt() )
402 argv1.SetExt( wxT( PGM_DATA_FILE_EXT ) );
403#endif
404 argv1.MakeAbsolute();
405
406 fileArgs[0] = argv1.GetFullPath();
407 }
408
409 frame->OpenProjectFiles( fileArgs );
410 }
411
412 return true;
413}
const wxString & GetAboutTitle() const
virtual bool OnInit() override
Definition: single_top.cpp:129
virtual void OnExit() override
Definition: single_top.cpp:130
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:66
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: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:99
virtual wxApp & App()
Returns a bare naked wxApp which may come from wxPython, SINGLE_TOP, or kicad.exe.
Definition: pgm_base.cpp:175
std::unique_ptr< SETTINGS_MANAGER > m_settings_manager
Definition: pgm_base.h:397
void Destroy()
Definition: pgm_base.cpp:159
virtual const wxString & GetExecutablePath() const
Definition: pgm_base.cpp:961
void SaveCommonSettings()
Save the program (process) settings subset which are stored .kicad_common.
Definition: pgm_base.cpp:631
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:115
Struct APP_SINGLE_TOP implements a bare naked wxApp (so that we don't become dependent on functionali...
Definition: single_top.cpp:154
int OnRun() override
Definition: single_top.cpp:200
int OnExit() override
Definition: single_top.cpp:194
bool OnInit() override
Definition: single_top.cpp:162
int FilterEvent(wxEvent &aEvent) override
Definition: single_top.cpp:216
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:71
void MacOpenFile(const wxString &aFileName) override
Specific to MacOSX (not used under Linux or Windows).
Definition: single_top.cpp:89
void OnPgmExit()
Definition: single_top.cpp:74
IFACE KIFACE_BASE kiface("pcb_test_frame", KIWAY::FACE_PCB)