KiCad PCB EDA Suite
kicad.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) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2004-2018 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 
31 #include <wx/filename.h>
32 #include <wx/log.h>
33 #include <wx/stdpaths.h>
34 #include <wx/string.h>
35 
36 #include <common.h>
37 #include <hotkeys_basic.h>
38 #include <kiway.h>
39 #include <richio.h>
41 #include <systemdirsappend.h>
42 
43 #include <stdexcept>
44 
45 #include "pgm_kicad.h"
46 
47 #include "kicad.h"
48 
49 
50 // a dummy to quiet linking with EDA_BASE_FRAME::config();
51 #include <kiface_i.h>
53 {
54  // This function should never be called. It is only referenced from
55  // EDA_BASE_FRAME::config() and this is only provided to satisfy the linker,
56  // not to be actually called.
57  wxLogFatalError( wxT( "Unexpected call to Kiface() in kicad/kicad.cpp" ) );
58 
59  throw std::logic_error( "Unexpected call to Kiface() in kicad/kicad.cpp" );
60 }
61 
62 
64 
65 
67 {
68  return program;
69 }
70 
71 
73 {
74  return program;
75 }
76 
77 
79 {
80 #if defined(DEBUG)
81  wxString absoluteArgv0 = wxStandardPaths::Get().GetExecutablePath();
82 
83  if( !wxIsAbsolutePath( absoluteArgv0 ) )
84  {
85  wxLogError( wxT( "No meaningful argv[0]" ) );
86  return false;
87  }
88 #endif
89 
90  if( !InitPgm() )
91  return false;
92 
93  m_bm.Init();
94 
95  // Add search paths to feed the PGM_KICAD::SysSearch() function,
96  // currenly limited in support to only look for project templates
97  {
98  SEARCH_STACK bases;
99 
100  SystemDirsAppend( &bases );
101 
102  for( unsigned i = 0; i < bases.GetCount(); ++i )
103  {
104  wxFileName fn( bases[i], wxEmptyString );
105 
106  // Add KiCad template file path to search path list.
107  fn.AppendDir( wxT( "template" ) );
108 
109  // Only add path if exists and can be read by the user.
110  if( fn.DirExists() && fn.IsDirReadable() )
111  m_bm.m_search.AddPaths( fn.GetPath() );
112  }
113 
114  // The KICAD_TEMPLATE_DIR takes precedence over the search stack template path.
115  ENV_VAR_MAP_CITER it = GetLocalEnvVariables().find( "KICAD_TEMPLATE_DIR" );
116 
117  if( it != GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
118  m_bm.m_search.Insert( it->second.GetValue(), 0 );
119 
120  // The KICAD_USER_TEMPLATE_DIR takes precedence over KICAD_TEMPLATE_DIR and the search
121  // stack template path.
122  it = GetLocalEnvVariables().find( "KICAD_USER_TEMPLATE_DIR" );
123 
124  if( it != GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
125  m_bm.m_search.Insert( it->second.GetValue(), 0 );
126  }
127 
128  // Must be called before creating the main frame in order to
129  // display the real hotkeys in menus or tool tips
130  extern struct EDA_HOTKEY_CONFIG kicad_Manager_Hokeys_Descr[];
131  ReadHotkeyConfig( KICAD_MANAGER_FRAME_NAME, kicad_Manager_Hokeys_Descr );
132 
133  KICAD_MANAGER_FRAME* frame = new KICAD_MANAGER_FRAME( NULL, wxT( "KiCad" ),
134  wxDefaultPosition, wxSize( 775, -1 ) );
135  App().SetTopWindow( frame );
136 
137  Kiway.SetTop( frame );
138 
139  wxString projToLoad;
140 
141  if( App().argc > 1 )
142  {
143  projToLoad = App().argv[1];
144  }
145  else if( GetFileHistory().GetCount() )
146  {
147  wxString last_pro = GetFileHistory().GetHistoryFile( 0 );
148 
149  if( !wxFileExists( last_pro ) )
150  {
151  GetFileHistory().RemoveFileFromHistory( 0 );
152  }
153  else
154  {
155  // Try to open the last opened project,
156  // if a project name is not given when starting Kicad
157  projToLoad = last_pro;
158  }
159  }
160 
161  // Do not attempt to load a non-existent project file.
162  if( !projToLoad.empty() && wxFileExists( projToLoad ) )
163  {
164  frame->LoadProject( projToLoad );
165  }
166 
167  frame->Show( true );
168  frame->Raise();
169 
170  return true;
171 }
172 
173 
175 {
176  Kiway.OnKiwayEnd();
177 
179 
180  // write common settings to disk, and destroy everything in PGM_KICAD,
181  // especially wxSingleInstanceCheckerImpl earlier than wxApp and earlier
182  // than static destruction would.
183  Destroy();
184 }
185 
186 
187 void PGM_KICAD::MacOpenFile( const wxString& aFileName )
188 {
189 #if defined(__WXMAC__)
190 
191  KICAD_MANAGER_FRAME* frame = (KICAD_MANAGER_FRAME*) App().GetTopWindow();
192 
193  if( !aFileName.empty() && wxFileExists( aFileName ) )
194  frame->LoadProject( wxFileName( aFileName ) );
195 
196 #endif
197 }
198 
199 
201 {
202  // unlike a normal destructor, this is designed to be called more
203  // than once safely:
204 
205  m_bm.End();
206 
208 }
209 
210 
212 
213 
218 struct APP_KICAD : public wxApp
219 {
220 #if defined (__LINUX__)
221  APP_KICAD(): wxApp()
222  {
223  // Disable proxy menu in Unity window manager. Only usual menubar works with
224  // wxWidgets (at least <= 3.1). When the proxy menu menubar is enable, some
225  // important things for us do not work: menuitems UI events and shortcuts.
226  wxString wm;
227 
228  if( wxGetEnv( wxT( "XDG_CURRENT_DESKTOP" ), &wm ) && wm.CmpNoCase( wxT( "Unity" ) ) == 0 )
229  {
230  wxSetEnv ( wxT("UBUNTU_MENUPROXY" ), wxT( "0" ) );
231  }
232  }
233 #endif
234 
235  bool OnInit() override
236  {
237  return program.OnPgmInit();
238  }
239 
240  int OnExit() override
241  {
242  program.OnPgmExit();
243 
244 #if defined(__FreeBSD__)
245  /* Avoid wxLog crashing when used in destructors. */
246  wxLog::EnableLogging( false );
247 #endif
248 
249  return wxApp::OnExit();
250  }
251 
252  int OnRun() override
253  {
254  try
255  {
256  return wxApp::OnRun();
257  }
258  catch( const std::exception& e )
259  {
260  wxLogError( wxT( "Unhandled exception class: %s what: %s" ),
261  GetChars( FROM_UTF8( typeid(e).name() )),
262  GetChars( FROM_UTF8( e.what() ) ) );
263  }
264  catch( const IO_ERROR& ioe )
265  {
266  wxLogError( GetChars( ioe.What() ) );
267  }
268  catch(...)
269  {
270  wxLogError( wxT( "Unhandled exception of unknown type" ) );
271  }
272 
273  return -1;
274  }
275 
281  void MacOpenFile( const wxString& aFileName )
282  {
283  Pgm().MacOpenFile( aFileName );
284  }
285 };
286 
287 IMPLEMENT_APP( APP_KICAD )
288 
289 
290 // The C++ project manager supports one open PROJECT, so Prj() calls within
291 // this link image need this function.
293 {
294  return Kiway.Prj();
295 }
296 
#define KFCTL_CPP_PROJECT_SUITE
Am running under C++ project mgr, possibly with others.
Definition: kiway.h:160
Class KIFACE_I is a KIFACE (I)mplementation, with some features useful for DSOs which implement a KIF...
Definition: kiface_i.h:37
FILE_HISTORY & GetFileHistory()
Definition: pgm_kicad.h:57
Structure EDA_HOTKEY_CONFIG contains the information required to save hot key information to a config...
Definition: hotkeys_basic.h:94
void MacOpenFile(const wxString &aFileName)
Set MacOS file associations.
Definition: kicad.cpp:281
Class PROJECT holds project specific data.
Definition: project.h:57
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
int OnExit() override
Definition: kicad.cpp:240
void Init()
Definition: bin_mod.cpp:38
void SaveCommonSettings()
Function saveCommonSettings saves the program (process) settings subset which are stored ...
Definition: pgm_base.cpp:628
Class PGM_BASE keeps program (whole process) data for KiCad programs.
Definition: pgm_base.h:149
Class PGM_KICAD extends PGM_BASE to bring in FileHistory() and PdfBrowser() which were moved from EDA...
Definition: pgm_kicad.h:40
PROJECT & Prj()
Definition: kicad.cpp:292
void MacOpenFile(const wxString &aFileName) override
Function MacOpenFile is specific to MacOSX (not used under Linux or Windows).
Definition: kicad.cpp:187
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:188
void Destroy()
Definition: pgm_base.cpp:173
System directories search utilities.
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:66
Class SEARCH_STACK looks for files in a number of places.
Definition: search_stack.h:41
bool OnPgmInit()
Definition: kicad.cpp:78
void OnKiwayEnd()
Definition: kiway.cpp:482
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
bool OnInit() override
Definition: kicad.cpp:235
static PGM_KICAD program
Definition: kicad.cpp:63
void Destroy()
Definition: kicad.cpp:200
VTBL_ENTRY void MacOpenFile(const wxString &aFileName)=0
Function MacOpenFile is specific to MacOSX (not used under Linux or Windows).
VTBL_ENTRY const ENV_VAR_MAP & GetLocalEnvVariables() const
Definition: pgm_base.h:312
KICAD_MANAGER_FRAME is the KiCad main frame.
VTBL_ENTRY PROJECT & Prj() const
Function Prj returns the PROJECT associated with this KIWAY.
Definition: kiway.cpp:142
std::map< wxString, ENV_VAR_ITEM >::const_iterator ENV_VAR_MAP_CITER
Definition: pgm_base.h:131
The common library.
Class KIWAY is a minimalistic software bus for communications between various DLLs/DSOs (DSOs) within...
Definition: kiway.h:258
void SystemDirsAppend(SEARCH_STACK *aSearchStack)
Function SystemDirsAppend appends system places to aSearchStack in a platform specific way...
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:76
PGM_KICAD & PgmTop()
Definition: kicad.cpp:72
SEARCH_STACK m_search
Definition: bin_mod.h:62
int OnRun() override
Definition: kicad.cpp:252
int ReadHotkeyConfig(const wxString &aAppname, struct EDA_HOTKEY_CONFIG *aDescList)
Function ReadHotkeyConfig Read configuration data and fill the current hotkey list with hotkeys...
BIN_MOD m_bm
Definition: pgm_kicad.h:72
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
const char * name
Definition: DXF_plotter.cpp:61
size_t i
Definition: json11.cpp:597
bool InitPgm()
Function initPgm initializes this program (process) in a KiCad standard way, using some generalized t...
Definition: pgm_base.cpp:263
The common library.
Some functions to handle hotkeys in KiCad.
void LoadProject(const wxFileName &aProjectFileName)
Definition: prjconfig.cpp:61
void OnPgmExit()
Definition: kicad.cpp:174
Struct APP_KICAD is not publicly visible because most of the action is in PGM_KICAD these days...
Definition: kicad.cpp:218
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
The main KiCad project manager frame.
Definition: kicad.h:135
void AddPaths(const wxString &aPaths, int aIndex=-1)
Function AddPaths insert or append path(s)
#define KICAD_MANAGER_FRAME_NAME
Definition: kicad.h:40
KIWAY Kiway
void End()
Definition: bin_mod.cpp:63