KiCad PCB EDA Suite
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 <dick@softplc.com>
5  * Copyright (C) 2014 KiCad Developers, see CHANGELOG.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 <macros.h>
39 #include <fctsys.h>
40 #include <wx/filename.h>
41 #include <wx/stdpaths.h>
42 #include <wx/snglinst.h>
43 
44 #include <kiway.h>
45 #include <pgm_base.h>
46 #include <kiway_player.h>
47 #include <confirm.h>
48 
49 
50 // Only a single KIWAY is supported in this single_top top level component,
51 // which is dedicated to loading only a single DSO.
53 
54 
55 // implement a PGM_BASE and a wxApp side by side:
56 
61 static struct PGM_SINGLE_TOP : public PGM_BASE
62 {
63  bool OnPgmInit();
64 
65  void OnPgmExit()
66  {
67  Kiway.OnKiwayEnd();
68 
70 
71  // Destroy everything in PGM_BASE, especially wxSingleInstanceCheckerImpl
72  // earlier than wxApp and earlier than static destruction would.
74  }
75 
76  void MacOpenFile( const wxString& aFileName ) override
77  {
78  wxFileName filename( aFileName );
79 
80  if( filename.FileExists() )
81  {
82  #if 0
83  // this pulls in EDA_DRAW_FRAME type info, which we don't want in
84  // the single_top link image.
85  KIWAY_PLAYER* frame = dynamic_cast<KIWAY_PLAYER*>( App().GetTopWindow() );
86  #else
87  KIWAY_PLAYER* frame = (KIWAY_PLAYER*) App().GetTopWindow();
88  #endif
89  if( frame )
90  frame->OpenProjectFiles( std::vector<wxString>( 1, aFileName ) );
91  }
92  }
93 
94 } program;
95 
96 
98 {
99  return program;
100 }
101 
102 
108 struct APP_SINGLE_TOP : public wxApp
109 {
110 #if defined (__LINUX__)
111  APP_SINGLE_TOP(): wxApp()
112  {
113  // Disable proxy menu in Unity window manager. Only usual menubar works with wxWidgets (at least <= 3.1)
114  // When the proxy menu menubar is enable, some important things for us do not work: menuitems UI events and shortcuts.
115  wxString wm;
116 
117  if( wxGetEnv( wxT( "XDG_CURRENT_DESKTOP" ), &wm ) && wm.CmpNoCase( wxT( "Unity" ) ) == 0 )
118  {
119  wxSetEnv ( wxT("UBUNTU_MENUPROXY" ), wxT( "0" ) );
120  }
121  }
122 #endif
123 
124  bool OnInit() override
125  {
126  try
127  {
128  return program.OnPgmInit();
129  }
130  catch( const std::exception& e )
131  {
132  wxLogError( wxT( "Unhandled exception class: %s what: %s" ),
133  GetChars( FROM_UTF8( typeid(e).name() )),
134  GetChars( FROM_UTF8( e.what() ) ) );
135  }
136  catch( const IO_ERROR& ioe )
137  {
138  wxLogError( GetChars( ioe.What() ) );
139  }
140  catch(...)
141  {
142  wxLogError( wxT( "Unhandled exception of unknown type" ) );
143  }
144 
145  program.OnPgmExit();
146 
147  return false;
148  }
149 
150  int OnExit() override
151  {
152  // Fixes segfault when wxPython scripting is enabled.
153 #if defined( KICAD_SCRIPTING_WXPYTHON )
154  program.OnPgmExit();
155 #endif
156  return wxApp::OnExit();
157  }
158 
159  int OnRun() override
160  {
161  int ret = -1;
162 
163  try
164  {
165  ret = wxApp::OnRun();
166  }
167  catch( const std::exception& e )
168  {
169  wxLogError( wxT( "Unhandled exception class: %s what: %s" ),
170  GetChars( FROM_UTF8( typeid(e).name() )),
171  GetChars( FROM_UTF8( e.what() ) ) );
172  }
173  catch( const IO_ERROR& ioe )
174  {
175  wxLogError( GetChars( ioe.What() ) );
176  }
177  catch(...)
178  {
179  wxLogError( wxT( "Unhandled exception of unknown type" ) );
180  }
181 
182  // Works properly when wxPython scripting is disabled.
183 #if !defined( KICAD_SCRIPTING_WXPYTHON )
184  program.OnPgmExit();
185 #endif
186  return ret;
187  }
188 
189 #ifdef __WXMAC__
190 
197  void MacOpenFile( const wxString& aFileName ) override
198  {
199  Pgm().MacOpenFile( aFileName );
200  }
201 
202 #endif
203 };
204 
206 
207 
209 {
210 #if defined(DEBUG)
211  wxString absoluteArgv0 = wxStandardPaths::Get().GetExecutablePath();
212 
213  if( !wxIsAbsolutePath( absoluteArgv0 ) )
214  {
215  wxLogError( wxT( "No meaningful argv[0]" ) );
216  return false;
217  }
218 #endif
219 
220  if( !InitPgm() )
221  return false;
222 
223 #if !defined(BUILD_KIWAY_DLL)
224 
225  // Only bitmap2component and pcb_calculator use this code currently, as they
226  // are not split to use single_top as a link image separate from a *.kiface.
227  // i.e. they are single part link images so don't need to load a *.kiface.
228 
229  // Get the getter, it is statically linked into this binary image.
231 
232  int kiface_version;
233 
234  // Get the KIFACE.
235  KIFACE* kiface = getter( &kiface_version, KIFACE_VERSION, this );
236 
237  // Trick the KIWAY into thinking it loaded a KIFACE, by recording the KIFACE
238  // in the KIWAY. It needs to be there for KIWAY::OnKiwayEnd() anyways.
239  Kiway.set_kiface( KIWAY::KifaceType( TOP_FRAME ), kiface );
240 #endif
241 
242  // Use KIWAY to create a top window, which registers its existence also.
243  // "TOP_FRAME" is a macro that is passed on compiler command line from CMake,
244  // and is one of the types in FRAME_T.
245  KIWAY_PLAYER* frame = Kiway.Player( TOP_FRAME, true );
246 
247  Kiway.SetTop( frame );
248 
249  App().SetTopWindow( frame ); // wxApp gets a face.
250 
251  // Open project or file specified on the command line:
252  int argc = App().argc;
253 
254  if( argc > 1 )
255  {
256  /*
257  gerbview handles multiple project data files, i.e. gerber files on
258  cmd line. Others currently do not, they handle only one. For common
259  code simplicity we simply pass all the arguments in however, each
260  program module can do with them what they want, ignore, complain
261  whatever. We don't establish policy here, as this is a multi-purpose
262  launcher.
263  */
264 
265  std::vector<wxString> argSet;
266 
267  for( int i=1; i<argc; ++i )
268  {
269  argSet.push_back( App().argv[i] );
270  }
271 
272  // special attention to the first argument: argv[1] (==argSet[0])
273  wxFileName argv1( argSet[0] );
274 
275  if( argc == 2 )
276  {
277 #if defined(PGM_DATA_FILE_EXT)
278  // PGM_DATA_FILE_EXT, if present, may be different for each compile,
279  // it may come from CMake on the compiler command line, but often does not.
280  // This facillity is mostly useful for those program modules
281  // supporting a single argv[1].
282  if( !argv1.GetExt() )
283  argv1.SetExt( wxT( PGM_DATA_FILE_EXT ) );
284 #endif
285  argv1.MakeAbsolute();
286 
287  argSet[0] = argv1.GetFullPath();
288  }
289 
290  // Use the KIWAY_PLAYER::OpenProjectFiles() API function:
291  if( !frame->OpenProjectFiles( argSet ) )
292  {
293  // OpenProjectFiles() API asks that it report failure to the UI.
294  // Nothing further to say here.
295 
296  // We've already initialized things at this point, but wx won't call OnExit if
297  // we fail out. Call our own cleanup routine here to ensure the relevant resources
298  // are freed at the right time (if they aren't, segfaults will occur).
299  OnPgmExit();
300 
301  // Fail the process startup if the file could not be opened,
302  // although this is an optional choice, one that can be reversed
303  // also in the KIFACE specific OpenProjectFiles() return value.
304  return false;
305  }
306  }
307 
308  frame->Show();
309 
310  return true;
311 }
int OnRun() override
Definition: single_top.cpp:159
Class KIWAY_PLAYER is a wxFrame capable of the OpenProjectFiles function, meaning it can load a porti...
Definition: kiway_player.h:111
void MacOpenFile(const wxString &aFileName) override
Function MacOpenFile is specific to MacOSX (not used under Linux or Windows).
Definition: single_top.cpp:76
int OnExit() override
Definition: single_top.cpp:150
Struct PGM_SINGLE_TOP implements PGM_BASE with its own OnPgmInit() and OnPgmExit().
Definition: single_top.cpp:61
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:97
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
static FACE_T KifaceType(FRAME_T aFrameType)
Function KifaceType is a simple mapping function which returns the FACE_T which is known to implement...
Definition: kiway.cpp:252
void OnPgmExit()
Definition: single_top.cpp:65
This file is part of the common library.
void SaveCommonSettings()
Function saveCommonSettings saves the program (process) settings subset which are stored ...
Definition: pgm_base.cpp:646
Class PGM_BASE keeps program (whole process) data for KiCad programs.
Definition: pgm_base.h:107
#define KIFACE_VERSION
Definition: kiway.h:111
IMPLEMENT_APP(APP_SINGLE_TOP)
VTBL_ENTRY wxApp & App()
Function App returns a bare naked wxApp, which may come from wxPython, SINGLE_TOP, or kicad.exe.
Definition: pgm_base.cpp:321
void Destroy()
Definition: pgm_base.cpp:306
void OnKiwayEnd()
Definition: kiway.cpp:485
bool OnInit() override
Definition: single_top.cpp:124
VTBL_ENTRY bool OpenProjectFiles(const std::vector< wxString > &aFileList, int aCtl=0)
Function OpenProjectFiles is abstract, and opens a project or set of files given by aFileList...
Definition: kiway_player.h:170
This file contains miscellaneous commonly used macros and functions.
bool set_kiface(FACE_T aFaceType, KIFACE *aKiface)
Definition: kiway.h:394
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, KIWAY_PLAYER *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:302
KIFACE * KIFACE_GETTER(int *aKIFACEversion, int aKIWAYversion, PGM_BASE *aProgram)
No name mangling. Each KIFACE (DSO/DLL) will implement this once.
KIFACE * KIFACE_GETTER_FUNC(int *aKIFACEversion, int aKIWAYversion, PGM_BASE *aProgram)
Function Pointer KIFACE_GETTER_FUNC points to the one and only KIFACE export.
Definition: kiway.h:450
Class KIWAY is a minimalistic software bus for communications between various DLLs/DSOs (DSOs) within...
Definition: kiway.h:257
void SetTop(wxFrame *aTop)
Function SetTop tells this KIWAY about the top most frame in the program and optionally allows it to ...
Definition: kiway.cpp:78
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
see class PGM_BASE
PGM_SINGLE_TOP program
Class KIFACE is used by a participant in the KIWAY alchemy.
Definition: kiway.h:150
bool InitPgm()
Function initPgm initializes this program (process) in a KiCad standard way, using some generalized t...
Definition: pgm_base.cpp:396
const char * name
return & kiface
Definition: pcbnew.cpp:207
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
Struct APP_SINGLE_TOP implements a bare naked wxApp (so that we don't become dependent on functionali...
Definition: single_top.cpp:108
#define KFCTL_STANDALONE
Am running as a standalone Top.
Definition: kiway.h:158
KIWAY Kiway